RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

[RunU O 2.0 RC1& RC2] The Complete Customizable Vendor

Pure Insanity

Sorceror
Hands_Of_God;843091 said:
Im upgrading all my scripts to the newest SVN. does anyone know what i need to change these too.

Code:
Errors:
 + Customs/XML Systems/[RC2] Rewards System - XML Attachments .cs:
    CS0115: Line 2547: 'System.CustomizableVendor.MobileRewardVendor.OnBuyItems(
Server.Mobile, System.Collections.ArrayList)': no suitable method found to overr
ide

I have tried a few different things, but i must be missing something

To fix this, you need to change the OnBuyItems method in the file to look like this below.

Code:
public override bool OnBuyItems(Mobile buyer, List<BuyItemResponse> list)

Although once you do that, you'll get a list of more errors. I'm currently trying to fix mine to work with the latest svn. Once I get it finished, I'll post mine.
 

Pure Insanity

Sorceror
Eh, I seemed to have got it working for me on the latest svn. All I did was update some of the old Array's to the new List functions. And I also removed the RewardList part. Not sure what it was for, guess it was to fetch stuff from the VeteranRewards? I tried looking through it all to see if I could fix that bit, but then decided I really didn't care if it got items from the veteran rewards. It's working for me so far, been testing it to make sure it's not going to crash after the mods I made. Anyone else is welcome to try it out on their svn copy.

Code:
//Author: krazeykow
//Version: 1.0.1

using System;
using Server;
using Server.Items;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using Server.Gumps;
using Server.Network;
using Server.Targeting;
using Server.Mobiles;
using Server.ContextMenus;
using Server.Engines.XmlSpawner2;

namespace System.CustomizableVendor
{
public class Currency : Item
{

    private Payment m_Payment;
    private PropertyInfo m_PropertyInfo;
    private Type m_Payment_Type;
    private Type m_XML_Type;
    private int m_ItemID;
    private string m_Name;
    private int m_Hue;

    public Type XMLType { get { return m_XML_Type; } }
    public Type PaymentType { get { return m_Payment_Type; } }
    public string PayName { get { return m_Name; } }
    public int PayID { get { return m_ItemID; } }
    public int CurrHue { get { return m_Hue; } } 

    public enum Payment
    {
        ByGold,
        ByItem,
        ByProperty,
        ByXMLAttachment
    }
    //default
    public Currency()
    {
        m_Payment = Payment.ByGold;
        m_Payment_Type = typeof(Gold);
        m_PropertyInfo = null;
        m_ItemID = 3823;
        m_Name = "Gold";
    }
    public Currency(object bindedTo, Type attachType, PropertyInfo attachProp)
    {
        m_XML_Type = attachType;
        m_Payment = Payment.ByXMLAttachment;
        m_Payment_Type = bindedTo.GetType();
        m_PropertyInfo = attachProp;

        if (bindedTo is Mobile) {
            m_ItemID = 8461;
            m_Name = "Player " + attachProp.Name;
        }
        else if (bindedTo is Item) {
            m_ItemID = ((Item)bindedTo).ItemID;
            m_Name = GetName((Item)bindedTo) + "'s " + attachProp.Name;
            m_Hue = ((Item)bindedTo).Hue;
        }

    }
    //consume by item
    public Currency(Item i)
    {
        if ( i.GetType().Equals(typeof(Gold)) )
            m_Payment = Payment.ByGold;
        else
            m_Payment = Payment.ByItem;

        m_Payment_Type = i.GetType();
        m_PropertyInfo = null;
        m_ItemID = CoinID(i.ItemID);
        m_Name = GetName(i);
        m_Hue = i.Hue;
    }
    //consume property on player
    public Currency(Mobile m, PropertyInfo pi)
    {
        m_Payment = Payment.ByProperty;
        m_Payment_Type = m.GetType();
        m_PropertyInfo = pi;
        m_ItemID = 8461;
        m_Name = "Player " + pi.Name;
    }
    //consume by item's number based property
    public Currency(Item i, PropertyInfo pi)
    {
        m_Payment = Payment.ByProperty;
        m_Payment_Type = i.GetType();
        m_PropertyInfo = pi;
        m_ItemID = CoinID(i.ItemID);
        m_Name = GetName(i) + "'s " + pi.Name;
        m_Hue = i.Hue;
    }
    public void Modify(Type t, string append)
    {
        if ( (t.Equals(typeof(PlayerMobile)) || append == null ))
            return;

        Item i;
        
        i = (Item)Activator.CreateInstance(t, null);
        m_Name = GetName(i) + append;
        m_Hue = i.Hue;
        m_ItemID = CoinID(m_ItemID);
        
    }
    public int CoinID(int itemID)
    {
        if (itemID == 3821)
            return 3823;
        else if (itemID == 3824)
            return 3826;
        else
            return itemID;
    }
    public void VOneUpdate()
    {
        switch (m_Payment)
        {
            case Payment.ByGold:
            case Payment.ByItem:
                {
                    Modify(m_Payment_Type, "");
                    break;
                }
            case Payment.ByProperty:
                {
                    if (!(m_Payment_Type.Equals(typeof(PlayerMobile))))
                        Modify(m_Payment_Type, "'s " + m_PropertyInfo.Name);
                    break;
                }
        }

     }

    public string GetName(Item i)
    {
        if (String.IsNullOrEmpty(i.Name))
            return i.GetType().Name;
        else
            return i.Name;
    }
    public bool Purchase(Mobile m, int cost)
    {
        int remain = Value(m) - cost;

        if (remain < 0 || m.Backpack == null)
            return false;
        
        Charge(m, cost, remain);

        return true;
    }
    public void Charge(Container pack, Container bank, Type t, int cost)
    {
        if ( pack == null || bank == null )
            return;

        cost = cost - pack.ConsumeUpTo(t, cost);

        if ( cost > 0 )
            bank.ConsumeUpTo(t, cost);
    }
   
    public void Charge(Mobile m, Type t, PropertyInfo pi, int cost, int remain)
    {
        try
        {
            if (t.BaseType.Equals(typeof(Mobile)) || t.Equals(typeof(PlayerMobile)))
            {
                SetPropertyValue(m, remain);
            }
            else
            {
                if (m.Backpack == null || m.FindBankNoCreate() == null)
                    return;

                Item[] packItems = m.Backpack.FindItemsByType(t);
                Item[] bankItems = m.FindBankNoCreate().FindItemsByType(t);

                Item[] items = new Item[packItems.Length + bankItems.Length];
                packItems.CopyTo(items, 0);
                bankItems.CopyTo(items, packItems.Length);

                //none found in backpack
                if (items == null)
                    return;

                int i = 0, value = 0, dif = 0;

                //account for multiple objects
                while (cost > 0 && i < items.Length)
                {
                    value = GetPropertyValue(items[i]);

                    dif = value - cost;

                    //one item has enough
                    if (dif >= 0)
                    {
                        SetPropertyValue(items[i], dif);
                    }
                    //take what amount item has (the amount has already been confirmed by Value(m))
                    else // assert (dif < 0)
                    {
                        cost -= GetPropertyValue(items[i]);
                        SetPropertyValue(items[i], 0);
                    }
                    i++;
                }
            }
        }
        catch { }
    }
    public void Charge(Mobile m, Container pack, Container bank, int cost)
    {
        if ( pack == null || bank == null )
            return;

        cost = cost - pack.ConsumeUpTo(typeof(Gold), cost);

        if (cost > 0)
            Banker.Withdraw(m, cost);
    }
    public void Charge(Mobile m, int cost, int remain)
    {
        switch (m_Payment)
        {
            case Payment.ByGold:
                Charge(m, m.Backpack, m.FindBankNoCreate(), cost);
                break;
            case Payment.ByItem:
                Charge(m.Backpack, m.FindBankNoCreate(), m_Payment_Type, cost);
                break;
            case Payment.ByXMLAttachment:
            case Payment.ByProperty:
                Charge(m, m_Payment_Type, m_PropertyInfo, cost, remain);
                break;
        }
    }
    public int Value(Mobile m)
    {
        switch (m_Payment)
        {
            case Payment.ByGold:
                return ProcessByGold(m);
            case Payment.ByItem:
                return ProcessByItem(m, m_Payment_Type);
            case Payment.ByXMLAttachment:
            case Payment.ByProperty:
                return ProcessByProperty(m, m_Payment_Type, m_PropertyInfo);                       
        }
        return 0;
    }

    public int ProcessByGold(Mobile m)
    {
        if (m.Backpack == null)
            return 0;

        int totalGold = 0;

        totalGold += m.Backpack.GetAmount( typeof( Gold ) );
        totalGold += Banker.GetBalance( m );

        return totalGold;
    }
    public int ProcessByItem(Mobile m, Type t)
    {
        Container pack = m.Backpack;
        Container bank = m.FindBankNoCreate();

        if (pack == null || bank == null)
            return 0;

        int amount = (pack.GetAmount(t) + bank.GetAmount(t));

        return amount;
    }
    public int ProcessByProperty(Container pack, Container bank, Type t, PropertyInfo pi)
    {
        if (pack == null || bank == null)
            return 0;


        Item[] packItems = pack.FindItemsByType(t);
        Item[] bankItems = bank.FindItemsByType(t);

        Item[] items = new Item[packItems.Length + bankItems.Length];
        packItems.CopyTo(items, 0);
        bankItems.CopyTo(items, packItems.Length);
        
        int sum = 0;

        foreach (object o in items)
        {
            sum += GetPropertyValue(o);
        }

        return sum;
    }
    public int GetPropertyValue(object o)
    {
        int val = 0;

        if (m_Payment == Payment.ByXMLAttachment)
        {
            val = GetXMLValue(o);
        }
        else
        {
            val = (int)m_PropertyInfo.GetValue(o, null);
        }

        return val;
    }
    public void SetPropertyValue(object o, int val)
    {
        if (m_Payment == Payment.ByXMLAttachment)
        {
            SetXMLValue(o, val);
        }
        else
        {
            m_PropertyInfo.SetValue(o, val, null);
        }       
    }
    public int GetXMLValue(object o)
    {      
        int val = 0;

        if (m_XML_Type == null)
            return val;

        XmlAttachment attach = XmlAttach.FindAttachment(o, m_XML_Type);

        if (attach != null) {           
            val = (int)m_PropertyInfo.GetValue(attach, null);           
        }
        return val;
    }
    public void SetXMLValue(object o, int val)
    {
        if (m_XML_Type == null)
            return;

        XmlAttachment attach = XmlAttach.FindAttachment(o, m_XML_Type);

        if (attach != null) { 
            m_PropertyInfo.SetValue(attach, val, null);           
        }
    }
    //Master
    public int ProcessByProperty(Mobile m, Type t, PropertyInfo pi)
    {
        try
        { 

            if (t.BaseType.Equals(typeof(Mobile)) || t.Equals(typeof(Mobile)) )
            {
                return GetPropertyValue(m);
            }
            else
            {
                return ProcessByProperty(m.Backpack, m.FindBankNoCreate(), t, pi);
            }
        }
        catch {}
        
        return 0;
        
    }
   
    public Currency( Serial serial ) : base( serial )
	{
	}
	public override void Serialize( GenericWriter writer )
	{
		base.Serialize( writer );
		writer.Write( (int) 2 );

        //version 2
        writer.Write((string)(m_XML_Type == null ? "" : m_XML_Type.Name));

        //version 1
        writer.Write((int)m_Hue);
        
        //explicit casts are given for clarification        
        writer.Write((int)m_Payment);
        writer.Write((string)m_Payment_Type.Name);
        writer.Write((string)(m_PropertyInfo == null ? "" : m_PropertyInfo.Name));
        writer.Write((int)m_ItemID);
        writer.Write((string)m_Name);
        
	}
	
	public override void Deserialize(GenericReader reader)
	{
		base.Deserialize( reader );
		int version = reader.ReadInt();


        switch (version)
        {
            case 2:
                {
                    try
                    {
                        string name = reader.ReadString();
                        if (name.Equals(""))
                        {
                            m_XML_Type = null;
                        }
                        else
                        {
                            m_XML_Type = ScriptCompiler.FindTypeByName(name);
                        }
                    }
                    catch { }

                    goto case 1;
                }
            case 1:
                {
                    m_Hue = reader.ReadInt();
                    goto case 0;
                }
            case 0:
                {
                    m_Payment = (Payment)reader.ReadInt();

                    try { string name = reader.ReadString(); m_Payment_Type = ScriptCompiler.FindTypeByName(name); }
                    catch { }

                    try
                    {
                        string propName = reader.ReadString();
                        if (propName.Equals("")) //never set
                        {
                            m_PropertyInfo = null;
                        }
                        else if (m_Payment == Payment.ByXMLAttachment && m_XML_Type != null) //XML requires find property by the XML Class type (m_XML_Type)
                        {
                            m_PropertyInfo = m_XML_Type.GetProperty(propName);
                        }
                        else 
                        { 
                            m_PropertyInfo = m_Payment_Type.GetProperty(propName); 
                        }
                    }
                    catch { }

                    m_ItemID = reader.ReadInt();
                    m_Name = reader.ReadString();

                    break;
                }
        }
        if (version == 0)
        {
            try { VOneUpdate(); }
            catch {  }
        }
     }
}

public class Reward : Item, ICloneable
{      
    private Item m_Reward;
    private int m_Cost;
    private string m_Title;
    private string m_Description;

    private ObjectPropertyList m_Display;

    private RestockInfo m_RestockInfo;
    private int m_BuyCount;

    public int BuyCount { get { return m_BuyCount; } set { m_BuyCount = value; } }
    public RestockInfo Restock { get { return m_RestockInfo; } set { m_RestockInfo = value; } }

    public ObjectPropertyList Display
    {
        get
        {
            if (m_Display == null)
            {
                m_Display = new ObjectPropertyList(this);

                m_Reward.GetProperties(m_Display);
                m_Reward.AppendChildProperties(m_Display);

                m_Display.Terminate();
                m_Display.SetStatic();
            }

            return m_Display;
        }
    }

    public void Void_RestockInfo()
    {
        m_RestockInfo = null;
    }
    //returns ((-1) -> no restockInfo) or current count
    public int Try_Restock()
    {
        if (m_RestockInfo == null)
            return -1;        

        TimeSpan dif = DateTime.Now - m_RestockInfo.LastRestock;
        int cycles = 0;

        if (dif > (m_RestockInfo.RestockRate) && m_RestockInfo.RestockRate.TotalMinutes > 0)
        {
            cycles = (int)(dif.TotalMinutes / m_RestockInfo.RestockRate.TotalMinutes);

            for (int i = 0; i < cycles; ++i)
            {
                if (m_RestockInfo.Restock())
                    continue;
            }
        }

        return m_RestockInfo.Count;
    }
    public bool InStock(int amount)
    {
        return (m_RestockInfo == null ? true : (m_RestockInfo.Count - amount >= 0));       
    }
    public void RegisterBuy(int amount)
    {      
        if (m_RestockInfo != null && InStock(amount))
            m_RestockInfo.Count -= amount;

        this.m_BuyCount += amount;
    }

    //for retrieving information only
    public Item RewardInfo
    {
        get { return m_Reward; }
    }
    //use only when creating Reward for player
    public Item RewardCopy
    {
        get { return GetReward(); }
    }
    public int Cost
    {
        get { return m_Cost; }
        set { m_Cost = value; }
    }
    public string Title
    {
        get { return m_Title; }
        set { m_Title = value; }
    }
    public string Description
    {
        get { return m_Description; }
        set { m_Description = value; }
    }
    object ICloneable.Clone()
    {
        return new Reward(this);
    }
    public Reward()
    {
        m_Reward = new Item();
        m_Cost = 0;
        m_Title = "";
        m_Description = "";
        m_RestockInfo = null;
    }
    public Reward(Reward r)
    {
        m_Reward = r.RewardCopy;
        m_Cost = r.Cost;
        m_Title = r.Title;
        m_Description = r.Description;
        m_RestockInfo = null;
    }
    public Reward(Item i)
    {
        m_Reward = i;
        m_Cost = 0;
        m_Title = (i.Name == null ? i.GetType().Name : i.Name);
        m_Description = "None.";
        m_RestockInfo = null;

    }
    public Reward(Item i, int cost)
    {
        m_Reward = i;
        m_Cost = cost;
        m_Title = (i.Name == null ? i.GetType().Name : i.Name);
        m_Description = "None.";
        m_RestockInfo = null;
    }
    public Reward(Item i, int cost, string title)
    {
        m_Reward = i;
        m_Cost = cost;
        m_Title = title;
        m_Description = "None.";
        m_RestockInfo = null;
    }
    public Reward(Item i, int cost, string title, string desc)
    {
        m_Reward = i;
        m_Cost = cost;
        m_Title = title;
        m_Description = desc;
        m_RestockInfo = null;
    }

    public class RestockInfo 
    {
        private TimeSpan m_RestockRate;
        private DateTime m_LastRestock;

        private int m_RestockAmnt;
        private int m_Count;
        private int? m_Maximum;
        
        public TimeSpan RestockRate { get { return m_RestockRate; } }
        public DateTime LastRestock { get { return m_LastRestock; } }

        public int RestockAmnt { get { return m_RestockAmnt; } }
        public int Count { get { return m_Count; } set { m_Count = value; } }
        public int Maximum { get { return m_Maximum.GetValueOrDefault(-1); } }

        public int Hours { get { return (int)m_RestockRate.Hours; } }
        public int Minutes { get { return (int)m_RestockRate.Minutes; } }

        public RestockInfo()
        {
            m_RestockRate = new TimeSpan();
            m_RestockAmnt = 0;
            m_Count = 0;
            m_Maximum = null;
            m_LastRestock = DateTime.Now;

        }
        public RestockInfo(int count) : this()
        {
            m_Count = count;
        }
        public RestockInfo(int hour, int minute, int count, int RestockNum)
        {
            m_RestockRate = new TimeSpan(hour, minute, 0);
            m_Count = count;
            m_RestockAmnt = RestockNum;
            m_Maximum = null;
            m_LastRestock = DateTime.Now;

        }
        public RestockInfo(int hour, int minute, int count, int RestockNum, int maxNum) : this (hour, minute, count, RestockNum)
        {
            m_Maximum = maxNum;
        }
        public bool Equals(RestockInfo info)
        {
            return (this.m_RestockRate.Equals(info.RestockRate) && (this.m_RestockAmnt == info.RestockAmnt) && (this.m_Count == info.Count)
                && (this.m_Maximum == info.Maximum));
        }
        public bool Restock()
        {
            m_LastRestock = DateTime.Now;

            if (m_Maximum != null) //Restock to a limit
            {
                if ((m_Count + m_RestockAmnt) > m_Maximum)
                {
                    m_Count = m_Maximum.Value;
                    return false;
                }

                m_Count += m_RestockAmnt;
                return true;
            }
            
            m_Count += m_RestockAmnt;            
            return true;
        }

        public void Serialize( GenericWriter writer )
        {
            writer.Write((TimeSpan)m_RestockRate);           
            writer.Write((int)m_RestockAmnt);
            writer.Write((int)m_Count);
            writer.Write((int)m_Maximum.GetValueOrDefault(-1));
        }

        public RestockInfo( GenericReader reader )
        {
            m_RestockRate = reader.ReadTimeSpan();
            m_LastRestock = DateTime.Now;
            m_RestockAmnt = reader.ReadInt();
            m_Count = reader.ReadInt();
            
            int? max = reader.ReadInt();
         
            m_Maximum = ((max < 0) ? null : max);
        }
    }

    public void Edit(int cost, string title, string desc)
    {
        if (cost < 0 || title == null || desc == null)
            return;

        m_Cost = cost;
        m_Title = title;
        m_Description = desc;
    }
    public Item GetReward()
    {
        return ItemClone.Clone(m_Reward);
    }

    public Reward( Serial serial ) : base( serial )
	{
	}
	public override void Serialize( GenericWriter writer )
	{
		base.Serialize( writer );

		writer.Write( (int) 1 );

        writer.Write((int)m_BuyCount);

        if (m_RestockInfo == null)
        {
            writer.Write(false);
        }
        else
        {
            writer.Write(true);
            m_RestockInfo.Serialize(writer);
        }

        writer.WriteItem((Item)m_Reward);
        writer.Write((int)m_Cost);
        writer.Write((string)m_Title);
        writer.Write((string)m_Description);          
    }
	
	public override void Deserialize(GenericReader reader)
	{
		base.Deserialize( reader );
		int version = reader.ReadInt();

        switch (version)
        {
            case 1:
                {
                    m_BuyCount = reader.ReadInt();

                    if (reader.ReadBool())
                        m_RestockInfo = new RestockInfo(reader);

                    goto case 0;
                }
            case 0:
                {
                    m_Reward = (Item)reader.ReadItem();
                    m_Cost = reader.ReadInt();
                    m_Title = reader.ReadString();
                    m_Description = reader.ReadString();                  
                    
                    break;
                }
        }
    
	}

}
public class RewardCollection : List<Reward>, ICloneable
{
    

    object ICloneable.Clone()
    {
        RewardCollection clone = new RewardCollection();
        
        foreach (Reward r in this)
        {
            clone.Add(((Reward)(r as ICloneable).Clone()));
        }
        return clone;
    }
}

public static class WorldRewardVendors
{
    private static List<IRewardVendor> m_Vendors = new List<IRewardVendor>();

    public static List<IRewardVendor> Vendors { get { return m_Vendors; } }
   
    public static void RegisterVendor(IRewardVendor vendor)
    {
        m_Vendors.Add(vendor);
    }
    public static void RemoveVendor(IRewardVendor vendor)
    {
        m_Vendors.Remove(vendor);
    }
}

public class EditItemGump : Gump
{
    private IRewardVendor m_Vendor;
    private Reward m_Reward;

    private Reward.RestockInfo m_Restock;
    private bool m_RestockOpen;

    private bool m_IsAdd;

    private Storage m_Entries;

    public EditItemGump(IRewardVendor vendor, Reward r, Storage entries, bool openRestockInfo, bool addingItem) : base(0, 0)
    {
        m_Vendor = vendor;
        m_Reward = r;

        m_Restock = r.Restock;
        m_RestockOpen = openRestockInfo;
        m_IsAdd = addingItem;

        m_Entries = entries; 

        this.Closable = true;
        this.Disposable = true;
        this.Dragable = true;
        this.Resizable = false;

        AddPage(0);

        AddImageTiled(227, 46, 329, 518, 2702);
        AddImageTiled(252, 291, 280, 217, 5104);
        AddLabel(253, 266, 2124, @"Description:");
        AddImageTiled(334, 147, 192, 23, 5104);
        AddLabel(258, 150, 2124, @"Cost:");
        AddImageTiled(336, 107, 192, 23, 5104);
        AddLabel(258, 108, 2124, @"Name:");
        AddImage(354, 199, 2328);
        AddItem(373, 208, r.RewardInfo.ItemID, r.RewardInfo.Hue);
        AddImageTiled(330, 54, 138, 16, 5214);
        AddLabel(373, 51, 1324, @"Edit Item");
        AddButton(465, 222, 5601, 5605, 2, GumpButtonType.Reply, 0); //restock
        AddLabel(447, 198, 2120, @"Restock ");
        AddLabel(447, 246, 2120, @"(Optional)");
        AddButton(324, 523, 4023, 4024, 1, GumpButtonType.Reply, 0);//ok
        AddButton(421, 523, 4017, 4018, 0, GumpButtonType.Reply, 0); //cancel

        if (entries == null)
            InitialText();
        else
            PacketText();

        if (openRestockInfo || r.Restock != null)
        {
            AddRestockMenu();
            m_RestockOpen = true;
        }
    }
    public void InitialText()
    {
        AddTextEntry(252, 292, 277, 215, 1879, 0, m_Reward.Description);
        AddTextEntry(334, 148, 188, 20, 1879, 1, m_Reward.Cost.ToString());
        AddTextEntry(336, 108, 188, 20, 1879, 2, m_Reward.Title);    
    }
    public void PacketText()
    {
        AddTextEntry(252, 292, 277, 215, 1879, 0, m_Entries[0].ToString()); //desc
        AddTextEntry(334, 148, 188, 20, 1879, 1, m_Entries[1].ToString());  //cost 
        AddTextEntry(336, 108, 188, 20, 1879, 2, m_Entries[2].ToString());  //title
    }
    public void AddRestockMenu()
    {

        AddPage(1);

        AddImageTiled(601, 47, 181, 469, 2624);
        AddLabel(648, 60, 2129, @"Restock Info");
        AddLabel(637, 98, 1418, @"Available");
        AddImageTiled(633, 123, 120, 16, 5214);
        AddTextEntry(637, 121, 107, 20, 547, 3, (m_Restock == null ? "Enter." : m_Restock.Count.ToString())); //3 - beginning amount
        AddLabel(660, 161, 1418, @"Maximum");
        AddImageTiled(631, 186, 120, 16, 5214);
        AddTextEntry(635, 184, 107, 20, 547, 4, ((m_Restock == null || m_Restock.Maximum < 0) ? "None." : m_Restock.Maximum.ToString())); //4 - Maxinum
        AddLabel(648, 227, 1418, @"Restock Rate");
        AddImageTiled(635, 252, 72, 16, 5214);
        AddTextEntry(638, 250, 64, 20, 547, 5, (m_Restock == null ? "0" : m_Restock.Hours.ToString())); //5 - hour
        AddLabel(714, 250, 602, @"hours");
        AddImageTiled(635, 292, 72, 16, 5214);
        AddLabel(716, 290, 602, @"mins");
        AddLabel(632, 323, 602, @"amount to restock");
        AddImageTiled(636, 355, 72, 16, 5214);
        AddTextEntry(638, 290, 64, 20, 547, 6, (m_Restock == null ? "0" : m_Restock.Minutes.ToString())); //6 - minute
        AddTextEntry(639, 353, 64, 20, 547, 7, (m_Restock == null ? "0" : m_Restock.RestockAmnt.ToString())); //7 - Restock Amount      
        AddImage(655, 377, 109);
        AddButton(636, 474, 4022, 4021, 3, GumpButtonType.Reply, 0);
        AddLabel(679, 475, 132, @"Void Restock");
        
    }
    public Reward.RestockInfo GetRestockInfo(RelayInfo info)
    {
        if (m_RestockOpen)
        {
            int numMinutes = 0, numHours = 0;
            int numBegin, numMax, numRestockAmnt;

            TextRelay entry3 = info.GetTextEntry(3);
            string beginAmount = (entry3.Text.Trim());

            TextRelay entry4 = info.GetTextEntry(4);
            string max = (entry4.Text.Trim());

            TextRelay entry5 = info.GetTextEntry(5);
            string hour = (entry5.Text.Trim());

            TextRelay entry6 = info.GetTextEntry(6);
            string minute = (entry6.Text.Trim());

            TextRelay entry7 = info.GetTextEntry(7);
            string restockAmount = (entry7.Text.Trim());

            Int32.TryParse(hour, out numHours);
            Int32.TryParse(minute, out numMinutes);
            Int32.TryParse(beginAmount, out numBegin);
            Int32.TryParse(max, out numMax);
            Int32.TryParse(restockAmount, out numRestockAmnt);

            if (numBegin > 0)
            {
                if ((numMinutes + numHours) > 0 && numRestockAmnt > 0)
                {
                    if (numMax > 0)
                    {
                        return new Reward.RestockInfo(numHours, numMinutes, numBegin, numRestockAmnt, numMax);
                    }
                    else
                    {
                        return new Reward.RestockInfo(numHours, numMinutes, numBegin, numRestockAmnt);
                    }
                }

                return new Reward.RestockInfo(numBegin);
            }                   
        }
        return m_Restock; //default
    }
    public Storage GetEntries(RelayInfo info)
    {
        //Description
        TextRelay entry0 = info.GetTextEntry(0);
        string desc = (entry0 == null ? "None." : entry0.Text.Trim());

        //Cost
        TextRelay entry1 = info.GetTextEntry(1);
        string costtext = (entry1 == null ? "0" : entry1.Text.Trim());

        //Name
        TextRelay entry2 = info.GetTextEntry(2);
        string name = (entry2 == null ? "" : entry2.Text.Trim());

        return new Storage(desc, costtext, name);
    }
    public override void OnResponse(NetState sender, RelayInfo info)
    {
        Mobile m = sender.Mobile;

        switch (info.ButtonID)
        {
            case 0:
                {
                    //cancel
                    break;
                }
            case 1: //ok
                {
                    try
                    {
                        //Description
                        TextRelay entry0 = info.GetTextEntry(0);
                        string desc = (entry0 == null ? "None." : entry0.Text.Trim());

                        //Cost
                        TextRelay entry1 = info.GetTextEntry(1);
                        string costtext = (entry1 == null ? "%Error" : entry1.Text.Trim());
                        int cost = Int32.Parse(costtext);

                        //Name
                        TextRelay entry2 = info.GetTextEntry(2);
                        string name = (entry2 == null ? "" : entry2.Text.Trim());

                        if ( m_IsAdd )
                            m_Vendor.AddReward(m_Reward);
                        
                        m_Reward.Edit(cost, name, desc);

                        if (m_RestockOpen)
                        {
                            Reward.RestockInfo input = GetRestockInfo(info);

                            if (input != null)
                            {
                                if (m_Restock != null && !(m_Restock.Equals(input))) //do not reassign same object
                                {
                                    m_Reward.Restock = input;
                                }
                                else
                                {
                                    m_Reward.Restock = input;
                                }
                            }
                        }

                        m.SendMessage("{0} has been modified in {1}'s collection", name, m_Vendor.GetName());

                    }
                    catch { m.SendMessage("Please make sure all fields are filled correctly, and the title has not been previously used."); }

                    break;
                }
            case 2: //open restock options
                {                                  
                    m.SendGump(new EditItemGump(m_Vendor, m_Reward, GetEntries(info), true, m_IsAdd));
                    
                    return; //override display 
                }
            case 3: //delete restock options
                {                   
                    m_Reward.Void_RestockInfo();
                                    
                    m.SendGump(new EditItemGump(m_Vendor, m_Reward, GetEntries(info), false, m_IsAdd));
                    
                    return; //override display 
                }
        }
        MenuUploader.Display(m_Vendor.Menu, m, m_Vendor, true); //send back display
    }
}

public class Exhibit : Item
{
    private IRewardVendor m_Vendor;
    private Reward m_Reward;
    private ObjectPropertyList m_PropertyList;

    public Exhibit(IRewardVendor vendor, Reward r)
        : base()
    {
        m_Vendor = vendor;
        m_Reward = r;

        SetOPL(r);

        this.ItemID = r.RewardInfo.ItemID;
        this.Hue = r.RewardInfo.Hue;
    }
    public override void SendPropertiesTo(Mobile from)
    {
        if (m_PropertyList == null)
        {
            m_PropertyList = new ObjectPropertyList(this);
            m_PropertyList.Add("Display [Broken]");
        }

        from.Send(m_PropertyList);
    }
    public void SetOPL(Reward r)
    {
        Item i = r.RewardInfo;

        m_PropertyList = new ObjectPropertyList(this);

        m_PropertyList.Add("Cost: " + m_Reward.Cost.ToString() + " " + m_Vendor.Payment.PayName + " [Click for more]");

        i.GetProperties(m_PropertyList);
        i.AppendChildProperties(m_PropertyList);

        m_PropertyList.Terminate();
        m_PropertyList.SetStatic();

    }

    public override void OnDoubleClick(Mobile m)
    {
        if (m_Vendor == null || m_Vendor.IsRemoved() || m_Reward == null || !m_Vendor.Display.Contains(m_Reward))
        {
            m_Vendor = null; // free up resource
            m_Reward = null;
            m.SendMessage("This item is no longer available to purchase.");
        }
        else
            m.SendGump(new ViewItemGump(m, m_Vendor, m_Reward, false));
    }

    public Exhibit(Serial serial)
        : base(serial)
    {
    }
    public override void Deserialize(GenericReader reader)
    {
        base.Deserialize(reader);

        int version = reader.ReadInt();

        if (reader.ReadBool())
        {
            m_Reward = (Reward)reader.ReadItem();

            m_Vendor = (IRewardVendor)reader.ReadMobile();

            try { SetOPL(m_Reward); }
            catch { }
        }
    }

    public override void Serialize(GenericWriter writer)
    {
        base.Serialize(writer);

        writer.Write((int)0); // version  

        if (m_Vendor == null || m_Vendor.IsRemoved() || m_Reward == null || m_Reward.Deleted)
        {
            m_Vendor = null;
            m_Reward = null;

            writer.Write((bool)false); //do not deserialize
        }
        else
        {
            writer.Write((bool)true);

            writer.WriteItem((Reward)m_Reward);

            writer.Write((Mobile)m_Vendor.GetMobile());
        }
    }
}
public class ViewItemGump : Gump
{
    IRewardVendor m_Vendor;
    Reward m_Reward;

    public ViewItemGump(Mobile m, IRewardVendor vendor, Reward r, bool viewItem)
        : base(0, 0)
    {
        m_Vendor = vendor;
        m_Reward = r;

        this.Closable = true;
        this.Disposable = true;
        this.Dragable = true;
        this.Resizable = false;

        AddPage(0);
        AddImageTiled(149, 207, 548, 277, 2624);
        AddImage(184, 300, 2328);
        AddImage(101, 222, 10400);
        
        AddHtml(428, 290, 243, 140, r.Description, (bool)true, (bool)true);
        AddItem(201, 311, r.RewardInfo.ItemID, r.RewardInfo.Hue);
                
        AddLabel(430, 263, 2101, @"Description");
        AddButton(192, 442, 4029, 4030, 2, GumpButtonType.Reply, 0); //buy
        AddLabel(231, 444, 2125, "Buy (" + r.Cost +")");
        AddButton(366, 442, 4020, 4021, 0, GumpButtonType.Reply, 0); //cancel
        AddLabel(407, 444, 2116, @"Cancel");
        AddImageTiled(184, 239, 510, 8, 9201);

        AddItem(182, 376, m_Vendor.Payment.PayID, m_Vendor.Payment.CurrHue);
        AddLabel(248, 369, 83, @"Pay By: " + m_Vendor.Payment.PayName);
        AddLabel(184, 268, 43, @"Vendor: " + m_Vendor.GetName());
        AddLabel(363, 216, 2123, r.Title);

        if (m.AccessLevel > AccessLevel.GameMaster) //GM capabilities
        {
            if (!viewItem)
                AddLabel(363, 216, 2123, r.Title);
            else
            {
                AddLabel(336, 296, 2101, @"Edit Item");
                AddButton(294, 293, 4011, 4012, 4, GumpButtonType.Reply, 0); //edit item

                if (m_Vendor.GetMobile() != null)
                {
                    AddLabel(336, 348, 2101, @"Get Display");
                    AddButton(294, 345, 4011, 4012, 3, GumpButtonType.Reply, 0); //get display   
                }
            }
        }
        else
        {
            OpenDisplay(m); //prevent build up of box display during editing
        }

        //Edit gump for display object
        if (viewItem) //not display
        {
            AddLabel(336, 322, 2101, @"View Item");
            AddButton(294, 319, 4011, 4012, 1, GumpButtonType.Reply, 0); //view item
                    
        }
        else //display
        {
            AddLabel(279, 320, 38, @"Cost: " + m_Reward.Cost.ToString());
            AddLabel(249, 398, 69, @"You have: " + m_Vendor.Payment.Value(m));

            if (m_Reward.Restock != null)
            {
                m_Reward.Try_Restock();
                AddLabel(279, 340, 4, "In Stock: " + m_Reward.Restock.Count.ToString());
            }

            if (m_Reward.RewardInfo is Container)
                OpenDisplay(m); 
        }
    }
    public void OpenDisplay(Mobile m)
    {
        DisplayBox dbox = m_Vendor.Display;

        if (dbox != null)
            dbox.DisplayTo(m, m_Reward);
    }
    public override void OnResponse(NetState sender, RelayInfo info)
    {
        Mobile m = sender.Mobile;

        if (m_Vendor.IsRemoved())
            return;

        switch (info.ButtonID)
        {
            case 0:
                {
                    break;
                }
            case 1:
                {
                    try
                    {
                        OpenDisplay(m);
                        m.SendGump(this);
                    }
                    catch
                    {
                        m.SendMessage("This Reward can no longer be found.");
                    }
                    break;
                }
            case 2:
                {
                    Container bank = m.BankBox;
                    Container pack = m.Backpack;

                    if ( bank == null || pack == null )
                        break;

                    Currency curr = m_Vendor.Payment;

                    if (m_Reward.InStock(1))
                    {
                        if (curr.Purchase(m, m_Reward.Cost))
                        {
                            m_Reward.RegisterBuy(1);

                            Item i = m_Reward.RewardCopy;

                            if (!m.PlaceInBackpack(i))
                            {
                                bank.DropItem(i);
                                m.SendMessage("You are overweight, the Reward was added to your bank");
                            }

                            m.SendMessage("You bought {0} for {1} {2}.", m_Reward.Title, m_Reward.Cost, curr.PayName);

                        }
                        else
                            m.SendMessage("You cannot afford {0}", m_Reward.Title);
                    }                           
                    else
                        m.SendMessage("{0} is no longer in stock.", m_Reward.Title);  

                    break;
                }
            case 3:
                {
                    if (m.Backpack != null)
                        m.AddToBackpack(new Exhibit(m_Vendor, m_Reward));
                    break;
                }
            case 4:
                {
                    m.SendGump(new EditItemGump(m_Vendor, m_Reward, null, false, false));
                    break;
                }
        }
    }
}

//Created for the usage of Warning Gump delegate 
public class Storage
{
    object[] m_Objs;

    public object this[int index]
    {
        get { return m_Objs[index]; }
    }

    public Storage(params object[] input)
    {
        m_Objs = input;
    }
    
}


public class WorldVendorsGump : Gump
{
    IRewardVendor m_Vendor; //used in case of copy

    public WorldVendorsGump(IRewardVendor vendor) : base( 0, 0 )
    {
        m_Vendor = vendor;

        this.Closable=true;
		this.Disposable=true;
		this.Dragable=true;
		this.Resizable=false;

		AddPage(0);

        //background
        AddImageTiled(50, 3, 430, 556, 2702);
		AddImageTiled(93, 78, 387, 9, 10101);
		AddImage(33, 58, 10420);
		AddImageTiled(47, 2, 3, 556, 10004);
		AddImageTiled(0, 58, 82, 414, 10440);
		AddImageTiled(47, 558, 436, 3, 10001);
		AddImageTiled(47, 0, 435, 3, 10001);
		AddImageTiled(480, 2, 3, 556, 10004);

        AddPage(1);

        CreateVendors(); //fill out entries
    }
    
    public static void CopyVendor_Callback(Mobile from, bool okay, object state)
    {
        if (from.AccessLevel < AccessLevel.GameMaster)
            return;
                
        if (okay)
        {
            //indexes -> (vendor (0), vendor's copy target(1))
            Storage store = (Storage)state;

            IRewardVendor source = (IRewardVendor)store[0];
            IRewardVendor target = (IRewardVendor)store[1];

            try { source.CopyVendor(target); }
            catch { from.SendMessage("Error occured while copying, please insure backpack is on vendors."); return; }

            from.SendMessage("{0} has copied {1}'s Reward collection", source.GetName(), target.GetName());
        }
    }
    public override void OnResponse(NetState sender, RelayInfo info)
    {
        Mobile m = sender.Mobile;

        if (info.ButtonID == 0)
        {
            m.CloseGump(typeof(ControlPanelGump));
            return;
        }

        MenuUploader.Display(m_Vendor.Menu, m, m_Vendor, false);

        try
        {
            if (info.ButtonID % 2 == 0 ) //even ID: Copy Vendor
            {
                IRewardVendor selected = WorldRewardVendors.Vendors[(info.ButtonID / 2) - 1];

                if ( m_Vendor.GetName().Equals(selected.GetName()))
                {
                    m.SendMessage("A vendor cannot copy itself.");
                }
                else
                {
                    //params -> (vendor, vendor's copy target)
                    Storage store = new Storage(m_Vendor, selected);

                    m.SendGump(new WarningGump(1060635, 30720, "Warning: You will lose all saved items on " + m_Vendor.GetName(), 0xFFC000, 420, 400, new WarningGumpCallback(CopyVendor_Callback), store));
                }
            }
            else //assert odd ID: Goto 
            {
                IRewardVendor v = WorldRewardVendors.Vendors[((info.ButtonID + 1) / 2) - 1];

                m.Location = v.GetLocation();
                m.Map = v.GetMap();
            }
        }
        catch
        {
            m.SendMessage("Vendor cannot be found.");
        }
    }
    public void CreateVendors()
    {
        int yPos = 101, pageNum = 1, buttonNum = 0;
      
        for (int i = 0; i < WorldRewardVendors.Vendors.Count; ++i)
        {            
            AddButton(175, yPos + 38, 4005, 4006, ++buttonNum, GumpButtonType.Reply, pageNum); //goto button - odd ID
            AddButton(279, yPos + 38, 4011, 4012, ++buttonNum, GumpButtonType.Reply, pageNum); //copy vendor - even ID
            AddLabel(86, yPos, 1849, WorldRewardVendors.Vendors[i].GetName());
            AddImageTiled(86, yPos + 93, 359, 2, 96);

            if (WorldRewardVendors.Vendors[i].GetMobile() != null)
                AddItem(110, yPos + 27, 8461); // person
            else

                AddItem(110, yPos + 27, WorldRewardVendors.Vendors[i].GetItem().ItemID, WorldRewardVendors.Vendors[i].GetItem().Hue); //stone ID

            AddLabel(213, yPos + 43, 2209, @"Go To");
            AddLabel(318, yPos + 43, 2204, @"Copy Vendor");
            
            yPos += 99;

            //add new page every four entries
            if ((i + 1) % 4 == 0)
            {
                AddButton(417, 531, 9903, 248, -1, GumpButtonType.Page, (pageNum + 1));

                AddPage(++pageNum);

                AddButton(92, 532, 9909, 248, -1, GumpButtonType.Page, (pageNum - 1));

                //reset to top of page
                yPos = 101;
            }
        }
    }
}
public class InfoGump : Gump
{
    public InfoGump()
        : base(0, 0)
    {
        this.Closable = true;
        this.Disposable = true;
        this.Dragable = true;
        this.Resizable = false;

        AddPage(0);
        
        AddImageTiled(0, 0, 452, 516, 2702);
        AddHtml(21, 78, 407, 105, @"Consume Item:  Vendor counts the number of the chosen item present in player's backpack.  

        Property(Item/Player):  Vendor takes the total of the given number based property (example: PlayerPoints, Charges)
        (Items): Adds up from every item present.
        (Player): Simply takes from what is present.
        ", (bool)true, (bool)true);

        AddLabel(23, 52, 2000, @"Choosing How Player Pays:");
        AddHtml(21, 242, 407, 105, @"You can create your own rewards in game, all properties will be copied over.  ", (bool)true, (bool)true);
        AddLabel(24, 216, 2000, @"Adding Items");
        AddLabel(239, 479, 37, @"Author: krazeykow1102");
        AddItem(391, 467, 8451);
        AddLabel(24, 368, 2000, @"How Displays Work");
        AddHtml(24, 394, 410, 78, @"Displays allow you to create your own interactive Reward room.  The display is a simple mirror to the item on the vendor.  Payment and cost will reflect what is on the vendor.  Vendor must stay in tact for display to function", (bool)true, (bool)true);
    }
}


public class ControlPanelGump : Gump
{
    private IRewardVendor m_Vendor;
   
    public ControlPanelGump(Mobile m, IRewardVendor vendor)
        : base(0, 0)
    {

        m_Vendor = vendor;
                
        this.Closable = true;
        this.Disposable = true;
        this.Dragable = true;
        this.Resizable = false;

        AddPage(0);

        //background
        AddImageTiled(4, 3, 215, 571, 2702);
        AddImageTiled(3, 0, 217, 3, 10001);
        AddImageTiled(4, 572, 216, 3, 10001);
        AddImageTiled(3, 1, 3, 571, 10004);
        AddImageTiled(217, 1, 3, 574, 10004);

        AddImage(40, 8, 5214);
        AddLabel(41, 7, 47, @"Control Panel");

        AddLabel(109, 62, 55, @"Manage Rewards");
        AddButton(72, 60, 4008, 4009, 1, GumpButtonType.Reply, 0); //PlayerView
        AddItem(31, 63, 5366); //scope
        AddImageTiled(19, 160, 132, 2, 96);

        AddLabel(79, 123, 1324, @"Add Item or Container");
        AddButton(52, 126, 2117, 2118, 2, GumpButtonType.Reply, 0); //AddItem
        AddItem(0, 113, 8192); //box  
        
        AddLabel(11, 232, 55, @"Target Payment Source:");
        AddButton(170,232, 2117, 2118, 3, GumpButtonType.Reply, 0); //Payment
        AddLabel(12, 173, 55, @"Pay By: " + m_Vendor.Payment.PayName );
        AddItem(61, 197, m_Vendor.Payment.PayID, m_Vendor.Payment.CurrHue);

        AddLabel(12, 32, 55, @"Vendor: " + m_Vendor.GetName());
        AddButton(77, 533, 4026, 4027, 4, GumpButtonType.Reply, 0);
        AddLabel(78, 553, 104, @"Help");

        if (m_Vendor.GetMobile() != null)
        {
            AddButton(72, 91, 4011, 4012, 5, GumpButtonType.Reply, 0); //Displays
            AddLabel(109, 93, 55, @"Get All Displays");
        }
        else
            AddLabel(12, 93, 55, @"Use Mobile Vendor for displays.");

       
        AddLabel(51, 258, 43, @"XML Attachment");
        AddRadio(15, 258, 9720, 9724, false, 6);
        AddLabel(51, 303, 43, @"Consume Item");
        AddRadio(15, 300, 9720, 9724, false, 7);
        AddLabel(50, 349, 43, @"[props Name of Item/Player");
        AddRadio(15, 342, 9720, 9724, false, 8);
        AddImageTiled(12, 382, 156, 22, 5058);
        AddTextEntry(12, 382, 149, 20, 41, 0, @"[prop/XML Name Here");

        AddPage(1);

        CreateGumps(); //fill out entries
               
    }
    public override void OnResponse(NetState sender, RelayInfo info)
    {
        Mobile m = sender.Mobile;

        if (m_Vendor.IsRemoved())
        {
            m.SendMessage("This vendor has been deleted.");
            return;
        }

        switch (info.ButtonID)
        {
            case 0:
                {
                    m.CloseGump(typeof(WorldVendorsGump));

                    //close
                    break;
                }
            case 1: //PlayerView
                {
                    m.CloseGump(typeof(WorldVendorsGump));

                    MenuUploader.Display(m_Vendor.Menu, m, m_Vendor, true);
                    break;
                }
            case 2: //AddItem
                {
                    m.CloseGump(typeof(WorldVendorsGump));

                    m.Target = new AddItemTarget(m_Vendor);
                    break;
                }
            case 3: //Payment
                { 
                    
                        try
                        {
                            if (info.IsSwitched(6))
                            {
                                m.SendMessage("Target the player or item you wish to get the XMLAttribute from.");
                                TextRelay entry0 = info.GetTextEntry(0);
                                string propName = (entry0 == null ? "" : entry0.Text.Trim());

                                m.Target = new PaymentTarget(m_Vendor, propName, true);
                            }
                            else if ( info.IsSwitched(7)) // Consume by item amount
                            {
                                m.SendMessage("Warning: payment will be taken as the unmodified created item.");
                                m.Target = new PaymentTarget(m_Vendor);
                            }
                            else if (info.IsSwitched(8)) //Consume by item's property
                            {
                                m.SendMessage("Target yourself or an item.");
                                TextRelay entry0 = info.GetTextEntry(0);
                                string propName = (entry0 == null ? "" : entry0.Text.Trim());

                                m.Target = new PaymentTarget(m_Vendor, propName, false);
                            }
                            else
                            {                                
                                MenuUploader.Display(m_Vendor.Menu, m, m_Vendor, false);
                                m.SendMessage("Please select consume or property.");
                            }
                        }

                            catch { }

                            break;      
                  }
            case 4:
                {
                    MenuUploader.Display(m_Vendor.Menu, m, m_Vendor, false);
                    m.SendGump(new InfoGump());
                    break;
                }
            case 5: //Displays
                {
                    if (m.Backpack == null)
                        return;

                    MetalBox c = new MetalBox();
                    c.Name = m_Vendor.GetName() + "'s Reward Displays";

                    foreach (Reward r in m_Vendor.Rewards)
                    {
                        c.DropItem(new Exhibit(m_Vendor, r));
                    }

                    m.AddToBackpack(c);

                    break;
                }

            default: //Set Menu - IDs are >= 7
                {
                    try
                    {
                        Type menuType = MenuUploader.Menus[info.ButtonID - 7];

                        if (m_Vendor.GetItem() != null && menuType.Equals(typeof(ClassicVendorGump)))
                            m.SendMessage("Only Mobile Reward Vendors can have classic menus.");
                        else
                        {
                            m_Vendor.Menu = menuType;
                            m.SendMessage("Display changed to " + menuType.Name);
                        }
                    }
                    catch { }

                    MenuUploader.Display(m_Vendor.Menu, m, m_Vendor, false);

                    break;
                                      
                }
         }   
    }
    public void CreateGumps()
    {
        int yPos = 433, pageNum = 1;

        for (int i = 0; i < MenuUploader.Menus.Count; ++i )
        {

            AddLabel(50, yPos, 100, MenuUploader.Menus[i].Name);
            AddButton(12, yPos, 4005, 4006, (i + 7), GumpButtonType.Reply, pageNum);
            

            yPos += 26;

            //add new page every four entries
            if ((i + 1) % 4 == 0)
            {
                AddButton(144, 542, 9702, 9703, -1, GumpButtonType.Page, (pageNum + 1));

                AddPage(++pageNum);

                AddButton(10, 542, 9706, 9707, -1, GumpButtonType.Page, (pageNum - 1));

                //reset to top of page
                yPos = 433;
            }
        } 
    }
}
public static class MenuUploader 
{
    private static List<Type> m_Menus = new List<Type>(); 
    
    public static List<Type> Menus { get { return m_Menus; } }

    public static void RegisterMenu<G>(G menu) where G : Gump, IRewardVendorGump
    {
        m_Menus.Add(menu.GetType());
    }
    
    public static void Display(IRewardVendorGump menu, Mobile m, IRewardVendor vendor)
    {
        m.CloseGump(typeof(IRewardVendorGump));

        //create 'canvas'
        menu.CreateBackground();

        //create Reward displays
        foreach (Reward r in vendor.Rewards)
        {
            //refresh restock  
            if (r.Try_Restock() == 0 && !(menu is ManageItemsGump))
                continue;
            
            menu.AddEntry(r);
        }

        //send finished product
        menu.Send(m);
    }
    public static void Display(Type menu, Mobile m, IRewardVendor vendor, bool playerView)  //Note: Playerview is only relevant for Staff
    {
        try
        {
            if (m.AccessLevel > AccessLevel.GameMaster) 
            {
                if (playerView)
                    Display(new ManageItemsGump(vendor, m), m, vendor);
                else //control panel
                {
                    m.CloseGump(typeof(WorldVendorsGump));
                    m.CloseGump(typeof(ControlPanelGump));

                    m.SendGump(new WorldVendorsGump(vendor)); 
                    m.SendGump(new ControlPanelGump(m, vendor));
                }
            }
            else //player
            {
                Display((IRewardVendorGump)Activator.CreateInstance(menu, new object[] { vendor, m }), m, vendor); //create fresh instance
            }
        }
        catch
        {
            if ( m.AccessLevel > AccessLevel.GameMaster )
                m.SendMessage("The current display is invalid, try setting gump back to default, JewlRewardGump.");
            else
                m.SendMessage("The current display is invalid, please notify the staff.");
        }
    }
}
public class ManageItemsGump : JewlRewardGump
{
    private int m_ButtonNum;

    public ManageItemsGump(IRewardVendor vendor, Mobile m) : base(vendor, m)
    {
        m_ButtonNum = 0;
    }
    public override void AddEntryControl(Reward r)
    {
        ImageTileButtonInfo b = new ItemTileButtonInfo(r.RewardInfo);

        //begin time entries
        if (r.Restock != null)
        {
            if (r.Restock.RestockRate.TotalMinutes == 0)
                AddLabel(324, (PosY + 22), 5, "Limited");
            else
                AddLabel(324, (PosY + 22), 5, ((int)r.Restock.RestockRate.Hours).ToString() + " hours " + ((int)r.Restock.RestockRate.Minutes).ToString() + " min");

            if (r.Restock.Maximum > 0)
                AddLabel(324, (PosY + 68), 4, "In Stock: " + r.Restock.Count.ToString() + " / " + r.Restock.Maximum.ToString() + ", Purchased: " + r.BuyCount.ToString());
            else
                AddLabel(324, (PosY + 68), 4, "In Stock: " + r.Restock.Count.ToString() + ", Purchased: " + r.BuyCount.ToString());
        }
        else
        {
            AddLabel(324, (PosY + 68), 4, "Purchased: " + r.BuyCount.ToString());
        }
        //end 

        //create entry
        AddLabel(227, PosY, 2123, r.Title);
        AddLabel(324, (PosY + 45), 2115, "Cost: " + r.Cost);
        //odd numbers
        AddImageTiledButton(227, (PosY + 26), 2328, 2329, ++m_ButtonNum, GumpButtonType.Reply, PageNum, b.ItemID, b.Hue, 15, 10, r.Display.Header);
        AddImageTiled(215, (PosY + 95), 359, 2, 96);
        //odd numbers (same as above)
        AddButton(470, (PosY + 45), 4011, 4012, m_ButtonNum, GumpButtonType.Reply, PageNum);
        AddLabel(508, (PosY + 47), 1882, @"Options");
        //even numbers
        AddButton(470, (PosY + 19), 4020, 4021, ++m_ButtonNum, GumpButtonType.Reply, PageNum);
        AddLabel(509, (PosY + 21), 1882, @"Delete");
        PosY += 102;

        //add new page every four entries
        if (EntryNum % 4 == 0)
        {
            AddButton(546, 562, 9903, 9904, -1, GumpButtonType.Page, PageNum + 1);

            AddPage(++PageNum);

            AddButton(221, 563, 9909, 9910, -1, GumpButtonType.Page, PageNum - 1);

            //reset to top of page
            PosY = 130;
        }

        EntryNum++;
    }
    public static void DeleteReward_Callback(Mobile from, bool okay, object state)
    {
        if (from.AccessLevel < AccessLevel.GameMaster)
            return;

        if (okay)
        {
            //indexes -> (Vendor(0), Reward(1))
            Storage store = (Storage)state;

            IRewardVendor vendor = (IRewardVendor)store[0];
            Reward Reward = (Reward)store[1];

            try { vendor.RemoveReward(Reward); }
            catch { from.SendMessage("An error ocurred in the removal of this item."); }
            
            MenuUploader.Display(vendor.Menu, from, vendor, true);
        }
    }
    public override void OnResponse(NetState sender, RelayInfo info)
    {
        Mobile m = sender.Mobile;

        if (info.ButtonID == 0)
        {
            MenuUploader.Display(Vendor.Menu, m, Vendor, false);
            return;
        }
            
        if (info.ButtonID % 2 == 0) //even
        {
                try
                {
                    Reward r = Vendor.Rewards[(info.ButtonID / 2) - 1];

                    //params -> (vendor, Reward)
                    Storage store = new Storage(Vendor, r);

                    m.SendGump(new WarningGump(1060635, 30720, "Warning: Are you sure you want to remove " + r.Title, 0xFFC000, 420, 400, new WarningGumpCallback(DeleteReward_Callback), store));

                }
                catch { m.SendMessage("This item could not be found."); }
            
        }
        else //assert - odd
        {
            try
            {
                MenuUploader.Display(Vendor.Menu, m, Vendor, true);
                m.SendGump(new ViewItemGump(m, Vendor, Vendor.Rewards[((info.ButtonID + 1) / 2) - 1], true));
            }
            catch { m.SendMessage("Vendor could not be found"); }
        }
        
    }
    
}
public class XMLIntPropertyGump : Gump
{
    private Type m_XML_Type;
    private object m_Target;

    private IRewardVendor m_Vendor;
    private List<PropertyInfo> m_Props;

    private int m_PageNum;
    private  int m_PosY;
    private int m_EntryNum;

    public XMLIntPropertyGump(Type xmlType, object target, IRewardVendor vendor, List<PropertyInfo> props)
        : base(0, 0)
    {
        m_XML_Type = xmlType;
        m_Target = target;
        m_Vendor = vendor;
        m_Props = props;

        m_PageNum = 1;
        m_PosY = 134;
        m_EntryNum = 1;
      
        this.Closable = true;
        this.Disposable = true;
        this.Dragable = true;
        this.Resizable = false;

        AddPage(0);

        AddImageTiled(284, 90, 168, 384, 2702);
        AddLabel(315, 99, 49, xmlType.Name);
        AddImageTiled(292, 123, 151, 3, 9151);

        AddPage(1);

        FillEntries();
    }
    public void FillEntries()
    {
        foreach (PropertyInfo pi in m_Props)
        {
            AddButton(295, m_PosY, 5601, 5605, m_EntryNum, GumpButtonType.Reply, 0);
            AddLabel(319, m_PosY, 43, pi.Name);

            m_PosY += 26;

            if (m_EntryNum % 10 == 0)
            {
                AddButton(423, 444, 9903, 9904, -1, GumpButtonType.Page, m_PageNum + 1);

                AddPage(++m_PageNum);

                AddButton(292, 444, 9909, 9910, -1, GumpButtonType.Page, m_PageNum - 1);

                //reset to top of page
                m_PosY = 134;
            }
            m_EntryNum++;
        }

       
    }
    public override void OnResponse(NetState sender, RelayInfo info)
    {
        Mobile m = sender.Mobile;

        if (info.ButtonID == 0)
            return;

        m_Vendor.Payment = new Currency(m_Target, m_XML_Type, m_Props[info.ButtonID - 1]);
        m.SendMessage("{0}'s payment method set to {1}.{2}", m_Vendor.GetName(), m_XML_Type.Name, m_Props[info.ButtonID-1].Name);
    }

}
public class JewlRewardGump : Gump, IRewardVendorGump
{
    private int m_PageNum;
    private int m_EntryNum;
    private int m_PosY;
    private IRewardVendor m_Vendor;
    private Mobile m_Mobile;
    private int m_CurrencyAmnt;
   
    public static void Initialize()
    {
        MenuUploader.RegisterMenu(new JewlRewardGump());
    }

    public JewlRewardGump()
        : base(0, 0)
    {
        m_PageNum = 1;
        m_EntryNum = 1;
        m_PosY = 130;
        m_Vendor = null;
        m_Mobile = null;
        m_CurrencyAmnt = 0;
    }
    public JewlRewardGump(IRewardVendor vendor, Mobile m) : this()
    {
        m_Vendor = vendor;
        m_Mobile = m;
        m_CurrencyAmnt = vendor.Payment.Value(m);
    }

    //Properties
    public int PageNum { get { return m_PageNum; } set { m_PageNum = value; } }
    public int EntryNum { get { return m_EntryNum; } set { m_EntryNum = value; } }
    public int PosY { get { return m_PosY; } set { m_PosY = value; } }
    public IRewardVendor Vendor { get { return m_Vendor; } set { m_Vendor = value; } }
    public Mobile Mobile { get { return m_Mobile; } set { m_Mobile = value; } }
    public int CurrencyAmnt { get { return m_CurrencyAmnt; } set { m_CurrencyAmnt = value; } }

    //Interface Explicit Implementation 
    void IRewardVendorGump.Send(Mobile m) { SendControl(m); }
    void IRewardVendorGump.CreateBackground() { CreateBackgroundControl(); } 
    void IRewardVendorGump.AddEntry(Reward r) { AddEntryControl(r); }

    public virtual void SendControl(Mobile m)
    {
        m.SendGump(this);
    }
    public virtual void CreateBackgroundControl()
    {
        this.Closable = true;
        this.Disposable = true;
        this.Dragable = true;
        this.Resizable = false;

        AddPage(0);

        AddImageTiled(179, 34, 430, 556, 2702);
        AddImageTiled(222, 109, 387, 9, 10101);
        AddImage(162, 89, 10420);
        AddImageTiled(176, 33, 3, 556, 10004);
        AddImageTiled(129, 89, 82, 414, 10440);
        AddImageTiled(176, 589, 436, 3, 10001);
        AddImageTiled(176, 31, 435, 3, 10001);
        AddImageTiled(609, 33, 3, 556, 10004);
        AddLabel(348, 52, 2124, m_Vendor.GetName());
        AddImage(210, 52, 9818);
        AddImage(534, 52, 9818);
        AddLabel(404, 119, 2125, @"You have:");
        AddItem(348, 126, m_Vendor.Payment.PayID, m_Vendor.Payment.CurrHue);
        AddLabel(404, 137, 2125, (m_CurrencyAmnt.ToString() + " " + m_Vendor.Payment.PayName) );
        

        AddPage(1);
    }
      
    public virtual void AddEntryControl(Reward r)
    {
        ImageTileButtonInfo b = new ItemTileButtonInfo(r.RewardInfo);

        //create entry

        //begin time entries
        if (r.Restock != null)
        {
            if (r.Restock.RestockRate.TotalMinutes == 0)
                AddLabel(324, (PosY + 22), 5, "Limited");

            if (r.Restock.Maximum > 0)
                AddLabel(324, (PosY + 68), 4, "In Stock: " + r.Restock.Count.ToString());
            else
                AddLabel(324, (PosY + 68), 4, "In Stock: " + r.Restock.Count.ToString());
        }
        //end 

        AddLabel(227, m_PosY, 2123, r.Title);
        AddLabel(324, (m_PosY + 45), 2115, "Cost: " + r.Cost);
        AddImageTiledButton(227, (m_PosY + 26), 2328, 2329, (m_EntryNum), GumpButtonType.Reply, m_PageNum, b.ItemID, b.Hue, 15, 10, b.LocalizedTooltip);
        AddImageTiled(215, (m_PosY + 95), 359, 2, 96);
        AddButton(470, (PosY + 45), 4011, 4012, (m_EntryNum), GumpButtonType.Reply, m_PageNum);
        AddLabel(508, (PosY + 47), 745, @"View Item");
        m_PosY += 102;
        
        //add new page every four entries
        if (m_EntryNum % 4 == 0)
        {
            AddButton(546, 562, 9903, 9904, -1, GumpButtonType.Page, m_PageNum + 1);

            AddPage(++m_PageNum);

            AddButton(221, 563, 9909, 9910, -1, GumpButtonType.Page, m_PageNum - 1);

            //reset to top of page
            m_PosY = 130;
        }

        m_EntryNum++;
    }
    public override void OnResponse(NetState sender, RelayInfo info)
    {
        Mobile m = sender.Mobile;

        if (info.ButtonID == 0)
            return;

        MenuUploader.Display(m_Vendor.Menu, m, m_Vendor, true);

        try
        {
            m.SendGump(new ViewItemGump(m, m_Vendor, m_Vendor.Rewards[info.ButtonID - 1], true));
        }
        catch { m.SendMessage("Vendor could not be found"); }
    }
}

public class DisplayBox : LargeCrate, IEnumerable
{
    private Dictionary<Reward, MetalBox> m_Boxes;

    public override bool IsPublicContainer { get { return true; } }

    public MetalBox this[Reward r]
    {
        get
        {
            MetalBox box = null; //not found

            m_Boxes.TryGetValue(r, out box);

            return box;
        }
    }

    [Constructable]
    public DisplayBox()
        : base()
    {
        this.Name = "Display Box [DO NOT REMOVE]";
        this.LiftOverride = true;
        m_Boxes = new Dictionary<Reward, MetalBox>();
    }
    public DisplayBox(RewardCollection rc)
        : this()
    {
        CreateEntries(rc);
    }
    public bool Contains(Reward r)
    {
        return m_Boxes.ContainsKey(r);
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return m_Boxes.GetEnumerator();
    }
    public override bool CheckLift(Mobile from, Item item, ref LRReason reject)
    {
        reject = 0;
        return false;
    }
    public void DisplayTo(Mobile m, Reward r)
    {
        string invalid = "This item can no longer be displayed.";
        bool staff = m.AccessLevel >= AccessLevel.GameMaster;

        try
        {
            Container[] containers = new Container[] { (Container)this.Parent, this }; //cast exception if parent isn't container

            foreach (Container c in containers)
            {
                if (m.NetState != null && m.NetState.IsPost6017)
                    m.Send(new ContainerContent6017(m, c));
                else
                    m.Send(new ContainerContent(m, c));
            }

            m_Boxes[r].DisplayTo(m); //throws null ref if not found

            m.SendMessage("A container has been opened for you to view the item.");
        }
        catch (NullReferenceException)
        {
            if (staff)
                m.SendMessage("Display error - please insure Reward is still on this vendor.");
            else
                m.SendMessage(invalid);
        }
        catch (InvalidCastException)
        {
            if (staff)
                m.SendMessage("Display error - the current vendor does not have a DisplayBox in backpack.");
            else
                m.SendMessage(invalid);
        }
        catch (Exception)
        {
            if (staff)
                m.SendMessage("Unknown error occured with display.");
            else
                m.SendMessage(invalid);
        }
            
    }
    //Warning: must catch exception in methods
    public void CreateEntries(RewardCollection rc)
    {
        foreach (Reward r in rc)
        {
            this.AddDisplay(r, r.RewardInfo);
        }
    }
    public void AddDisplay(Reward key, Item i)
    {
        if (m_Boxes.ContainsKey(key))
            throw new Exception("Key already in use.");

        MetalBox container = new MetalBox();
        
        container.DropItem(i);

        this.DropItem(container);

        m_Boxes.Add(key, container);    
    }
    public void AddDisplay(Reward r)
    {
        AddDisplay(r, r.RewardInfo);
    }
    public void RemoveDisplay(Reward r)
    {
        ((Item)m_Boxes[r]).Delete(); //remove from displaybox
        m_Boxes.Remove(r);   //remove from hashtable      
    }
    //End Warning

    public override bool OnDragDrop( Mobile from, Item dropped )
    {
        return false;//do nothing
    }

    public DisplayBox( Serial serial ) : base( serial )
	{
	}
    
	public override void Serialize( GenericWriter writer )
    {
		base.Serialize( writer );

		writer.Write( (int) 0 ); // version
        
        int count = 0;
        try
        {
            count = m_Boxes.Count;
        }
        catch
        {
            m_Boxes = new Dictionary<Reward, MetalBox>();
            m_Boxes.Add(new Reward(), new MetalBox());
            count = m_Boxes.Count;
        }
        writer.Write((int)count);

        foreach (KeyValuePair<Reward, MetalBox> kvp in m_Boxes)
        {
            writer.Write((Reward)kvp.Key);
            writer.WriteItem((MetalBox)kvp.Value);
        }
        
    }

	public override void Deserialize( GenericReader reader )
    {
		base.Deserialize( reader );
                
		int version = reader.ReadInt();

        
        int count = reader.ReadInt();
        
        m_Boxes = new Dictionary<Reward, MetalBox>();     
        if (count > 0)
        {
            for (int i = 0; i < count; i++)
            {
                Reward r = (Reward)reader.ReadItem();
                MetalBox box = (MetalBox)reader.ReadItem();

                m_Boxes.Add(r, box);
            }
        }      
    }
}

public class LoadGumpEntry : ContextMenuEntry
{
    private IRewardVendor m_Vendor;
    private Mobile m_Mobile;

    public LoadGumpEntry(Mobile from, IRewardVendor vendor)
        : base(6103, 8)
    {
        m_Vendor = vendor;
        m_Mobile = from;
        Enabled = true;
    }

    public override void OnClick()
    {
        try
        {
            MenuUploader.Display((IRewardVendorGump)Activator.CreateInstance(m_Vendor.Menu, new object[] { m_Vendor, m_Mobile }), m_Mobile, m_Vendor); //create fresh instance
        }
        catch { m_Mobile.SendMessage("The current display is invalid.");  }
    }
}
public class ClassicVendorGump : Gump, IRewardVendorGump
{
    private IRewardVendor m_Vendor;
    private BaseVendor m_BVendor;

    private Mobile m_Mobile;   

    private List<ObjectPropertyList> m_Opls;
    List<BuyItemState> m_List;

    public List<ObjectPropertyList> ObjPropLists { get { return m_Opls; } 

    public static void Initialize()
    {
        MenuUploader.RegisterMenu(new ClassicVendorGump());
    }

    public ClassicVendorGump()
        : base(0, 0)
    {
        m_Vendor = null;
        m_Mobile = null;
        m_BVendor = null;
        m_Opls = null;
        m_List = null;
    }
    public ClassicVendorGump(IRewardVendor vendor, Mobile m) : this()
    {
        m_Vendor = vendor;
        m_Mobile = m;
        m_BVendor = Parent(vendor);
        m_Opls = new List<ObjectPropertyList>();
        m_List = new List<BuyItemState>();
    }
    private BaseVendor Parent(IRewardVendor vendor)
    {
        BaseVendor validVendor = null;

        if (vendor != null) //only available on mobiles inherited from BaseVendor
            validVendor = vendor as BaseVendor;

        return validVendor;
    }
    void IRewardVendorGump.Send(Mobile m)
    {
        if ( !m_Vendor.Payment.PaymentType.Equals(typeof(Gold)) ) //need custom payment display
            m.SendGump(this);    

        if (m_BVendor != null)
        {

            if (m_List.Count > 0)
            {
                m_List.Sort(new BuyItemStateComparer());

                m_BVendor.SendPacksTo(m);

                if (m.NetState == null)
                    return;

                if (m.NetState.IsPost6017)
                    m.Send(new VendorBuyContent6017(m_List));
                else
                    m.Send(new VendorBuyContent(m_List));
                m.Send(new VendorBuyList(m_BVendor, m_List));
                m.Send(new DisplayBuyList(m_BVendor));

                m.Send(new MobileStatusExtended(m));//make sure their gold amount is sent

                if (m_Opls != null)
                {
                    for (int i = 0; i < m_Opls.Count; ++i)
                    {
                        m.Send(m_Opls[i]);
                    }
                }

                m_BVendor.SayTo(m, 500186); // Greetings.  Have a look around.
            }
        }               
    }   
    void IRewardVendorGump.AddEntry(Reward r)
    {
        m_List.Add(new BuyItemState(r.Title, m_BVendor.BuyPack.Serial, r.Serial, r.Cost, (r.Restock == null ? 20 : r.Restock.Count), r.RewardInfo.ItemID, r.RewardInfo.Hue));

        m_Opls.Add(r.Display);      
    }
    void IRewardVendorGump.CreateBackground()
    {
        this.Closable = true;
        this.Disposable = true;
        this.Dragable = true;
        this.Resizable = false;

        AddPage(0);
        AddImage(36, 105, 2162);
        AddItem(111, 217, m_Vendor.Payment.PayID, m_Vendor.Payment.CurrHue);
        AddLabel(110, 172, 2122, @"Pay By:  " + m_Vendor.Payment.PayName);
        AddLabel(110, 299, 2120, @"You have: " + m_Vendor.Payment.Value(m_Mobile));
        AddImage(71, 302, 57);
        AddImage(71, 174, 57);
    }
}
public class MobileRewardVendor : Banker, IRewardVendor 
{
    private Currency m_Currency;
    private RewardCollection m_Rewards;
    private Type m_Menu;
    private DisplayBox m_Box;

    private bool m_IsBanker;

    [CommandProperty(AccessLevel.GameMaster)]
    public bool IsBanker
    {
        get { return m_IsBanker; }
        set { m_IsBanker = value; }     
    }
    Currency IRewardVendor.Payment
    {
        get { return m_Currency; }
        set { m_Currency = value; }
    }
    RewardCollection IRewardVendor.Rewards
    {
        get { return m_Rewards; }
        set { m_Rewards = value; }
    }
    Type IRewardVendor.Menu
    {
        get { return m_Menu; }
        set { m_Menu = value;  }
    }
    DisplayBox IRewardVendor.Display
    {
        get { return m_Box; }
    }
    [Constructable]
    public MobileRewardVendor() : base()
    {
        m_IsBanker = true;

        //default is Gold
        m_Currency = new Currency();
        m_Rewards = new RewardCollection();
        m_Menu = typeof(ClassicVendorGump);
        m_Box = new DisplayBox();

        //add to world collection
        WorldRewardVendors.RegisterVendor(this);
        //must be brought to world for client to view
        this.AddToBackpack(m_Box);

        this.Title = "";
    }
    public override void AddCustomContextEntries(Mobile from, List<ContextMenuEntry> list)
    {
        if (from.Alive)
        {
            list.Add(new LoadGumpEntry(from, this));

            if ( m_IsBanker)
                list.Add(new OpenBankEntry(from, this));
        }
    }
    Mobile IRewardVendor.GetMobile()
    {
        return this;
    }
    Item IRewardVendor.GetItem()
    {
        return null;
    }
   
    bool IRewardVendor.IsRemoved()
    {
        return this.Deleted;
    }
    Container IRewardVendor.GetContainer()
    {
        return this.Backpack;
    }
    string IRewardVendor.GetName()
    {
        return this.Name;
    }
    Map IRewardVendor.GetMap()
    {
        return this.Map;
    }
    Point3D IRewardVendor.GetLocation()
    {
        return this.Location;
    }
    //begin bank override
    public override bool HandlesOnSpeech(Mobile from)
    {
        if (!m_IsBanker)
            return false;

        base.HandlesOnSpeech(from);

        return true;
    }
    public override void OnSpeech(SpeechEventArgs e)
    {
        if (m_IsBanker)
            base.OnSpeech(e);
    }    
    //end

    //Warning: Following methods will throw Exceptions
    void IRewardVendor.AddReward(Reward r)
    {
        m_Box.AddDisplay(r);
        m_Rewards.Add(r);
    }
    void IRewardVendor.RemoveReward(Reward r)
    {
        m_Rewards.Remove(r);
        m_Box.RemoveDisplay(r);
    }
    
    void IRewardVendor.CopyVendor(IRewardVendor vendor)
    {
        Item currBox = this.Backpack.FindItemByType(typeof(DisplayBox));
        currBox.Delete();

        m_Currency = vendor.Payment;
        m_Menu = vendor.Menu;

        m_Rewards = (RewardCollection)((vendor.Rewards as ICloneable).Clone());
        m_Box = new DisplayBox(m_Rewards);

        this.AddToBackpack(m_Box);
    }
    //End Warning
    public override void OnDelete()
    {
        WorldRewardVendors.RemoveVendor(this);
        base.OnDelete();
    }
    //response to ClassicVendorGump - (must be inside BaseVendor)
    public override bool OnBuyItems(Mobile buyer, List<BuyItemResponse> list)
    {
        int totalCost = 0;
      
        Dictionary<Reward, int> purchases = new Dictionary<Reward, int>();

        Container bank = buyer.BankBox;
        Container pack = buyer.Backpack;

        if (pack == null || bank == null)
            return false;

        foreach (BuyItemResponse buy in list)
        {
            Serial ser = buy.Serial;
            int amount = buy.Amount;

            if (ser.IsItem)
            {
                Item item = World.FindItem(ser);

                if (item == null)
                    continue;

                Reward r = item as Reward;

                if (r == null || !r.InStock(amount))
                    continue;

                totalCost += (r.Cost * amount);

                purchases.Add(r, amount);
            }
        }

        if (purchases.Count == 0)
        {
            SayTo(buyer, 500190); // Thou hast bought nothing! 
            return false;
        }                    
            if (!m_Currency.Purchase(buyer, totalCost)) //cannot afford
            {
                SayTo(buyer, 500192);//Begging thy pardon, but thou casnt afford that.
                return false;
            }

            foreach (KeyValuePair<Reward, int> kvp in purchases)
            {
                kvp.Key.RegisterBuy(kvp.Value);

                for (int index = 0; index < kvp.Value; index++)
                {                    
                    Item i = kvp.Key.RewardCopy;

                    if (!buyer.PlaceInBackpack(i))
                    {
                        bank.DropItem(i);
                        buyer.SendMessage("You are overweight, the Reward was added to your bank");
                    }
                }

                buyer.SendMessage("You bought {0} {1}", kvp.Value, kvp.Key.Title);
            }

            buyer.PlaySound(0x32);

            return true;  
             
    }
    //respone to 'vendor buy'
    public override void VendorBuy(Mobile from)
    {       
        MenuUploader.Display((IRewardVendorGump)Activator.CreateInstance(m_Menu, new object[] { (IRewardVendor)this, from }), from, (IRewardVendor)this ); //create fresh instance
    }
    //end edit
    public override void OnDoubleClick(Mobile m)
    {
        if (InRange(m, 4) && InLOS(m))
            MenuUploader.Display(m_Menu, m, this, false);
    }
    public MobileRewardVendor( Serial serial ) : base( serial )
	{
	}
    
	public override void Serialize( GenericWriter writer )
    {
		base.Serialize( writer );   

		writer.Write( (int) 1 ); // version

        writer.Write((bool)m_IsBanker);

        int count = m_Rewards.Count;
        writer.Write((int)count);

        if ( count > 0 )
        {
            for (int i = 0; i < count; i++)
            {
                writer.WriteItem((Reward)m_Rewards[i]);
            }
        }
        
        writer.WriteItem((Currency)m_Currency);
        writer.Write((string)m_Menu.Name);
        writer.WriteItem((DisplayBox)m_Box);       
    }
    
	public override void Deserialize( GenericReader reader )
    {
		base.Deserialize( reader );

        WorldRewardVendors.RegisterVendor(this);

		int version = reader.ReadInt();
        
        m_Rewards = new RewardCollection();

        m_IsBanker = true; //for conversion
               
        switch (version)
        {
            case 1:
                {
                    m_IsBanker = reader.ReadBool();

                    goto case 0;
                }
            case 0:
               {                   
                    int count = reader.ReadInt();
                    if (count > 0)
                    {
                        for (int i = 0; i < count; i++)
                        {
                            Reward r = (Reward)reader.ReadItem();
                            m_Rewards.Add(r);
                        }
                    }

                    m_Currency = (Currency)reader.ReadItem();

                    try { string name = reader.ReadString(); m_Menu = ScriptCompiler.FindTypeByName(name); }
                    catch { m_Menu = typeof(JewlRewardGump); }

                    m_Box = (DisplayBox)reader.ReadItem();

                    break;
                }
        }
	}
}
public class StoneRewardHolder : MetalBox
{
    private StoneRewardVendor m_S_Vendor;

    public StoneRewardHolder(StoneRewardVendor sv)
        : base()
    {
        m_S_Vendor = sv;
        this.Movable = false;
        this.Name = sv.Name + "'s Display Container [DO NOT DELETE]";
    }
    public override void OnItemLifted(Mobile m, Item item)
    {
        m.SendMessage("This item should not be moved away from the vendor.");
    }

    public void UpdateName()
    {
        if (m_S_Vendor == null)
            return;

        this.Name = m_S_Vendor.Name + "'s Display Container [DO NOT DELETE]";
    }
    public StoneRewardHolder(Serial serial)
        : base(serial)
	{
	}

	public override void Serialize( GenericWriter writer )
	{
		base.Serialize( writer );

		writer.Write( (int) 0 ); // version
	}

	public override void Deserialize( GenericReader reader )
	{
		base.Deserialize( reader );

		int version = reader.ReadInt();
    }
}
public class StoneRewardVendor : Item, IRewardVendor
{
    private Currency m_Currency;
    private RewardCollection m_Rewards;
    private Type m_Menu;
    private StoneRewardHolder m_Box_Holder;
    private DisplayBox m_Box;

    Currency IRewardVendor.Payment
    {
        get { return m_Currency; }
        set { m_Currency = value; }
    }
    RewardCollection IRewardVendor.Rewards
    {
        get { return m_Rewards; }
        set { m_Rewards = value; }
    }
    Type IRewardVendor.Menu
    {
        get { return m_Menu; }
        set { m_Menu = value; }
    }
    DisplayBox IRewardVendor.Display
    {
        get { return m_Box; }
    }

    [Constructable]
    public StoneRewardVendor()
        : base()
    {
        m_Currency = new Currency();
        m_Rewards = new RewardCollection();
        m_Menu = typeof(JewlRewardGump);
        m_Box = new DisplayBox();

        ItemID = 0xEDC;
        Name = "Stone Vendor";

        WorldRewardVendors.RegisterVendor(this);

        m_Box_Holder = new StoneRewardHolder(this);
        m_Box_Holder.DropItem(m_Box);      

        this.Movable = false;
    }
    public override void OnLocationChange( Point3D oldLocation )
    {
        base.OnLocationChange(oldLocation);

        if (m_Box_Holder != null)
        {
            m_Box_Holder.Location = this.Location;
            m_Box_Holder.Z = this.Z - 10;
        }
    }
    public override void OnMapChange()
    {
        base.OnMapChange();

        if ( m_Box_Holder != null )
            m_Box_Holder.Map = this.Map;
    }
    Mobile IRewardVendor.GetMobile()
    {
        return null;
    }
    Item IRewardVendor.GetItem()
    {
        return this;
    }

    bool IRewardVendor.IsRemoved()
    {
        return this.Deleted;
    }
    Container IRewardVendor.GetContainer()
    {
        return m_Box_Holder;
    }
    string IRewardVendor.GetName()
    {
        return this.Name;
    }
    Map IRewardVendor.GetMap()
    {
        return this.Map;
    }
    Point3D IRewardVendor.GetLocation()
    {
        return this.Location;
    }
    void IRewardVendor.AddReward(Reward r)
    {
        m_Box.AddDisplay(r);
        m_Rewards.Add(r);
    }
    void IRewardVendor.RemoveReward(Reward r)
    {
        m_Rewards.Remove(r);
        m_Box.RemoveDisplay(r);
    }

    void IRewardVendor.CopyVendor(IRewardVendor vendor)
    {
        Item currBox = m_Box_Holder.FindItemByType(typeof(DisplayBox));
        currBox.Delete();

        m_Currency = vendor.Payment;
        m_Menu = vendor.Menu;

        m_Rewards = (RewardCollection)((vendor.Rewards as ICloneable).Clone());
        m_Box = new DisplayBox(m_Rewards);

        m_Box_Holder.DropItem(m_Box);
    }
    //End Warning
    public override void OnDelete()
    {
        if ( m_Box_Holder != null)
            m_Box_Holder.Delete();

        WorldRewardVendors.RemoveVendor(this);
        base.OnDelete();
    }
    
    public override void OnDoubleClick(Mobile m)
    {
        if (m_Box_Holder != null)
        {
            m_Box_Holder.MoveToWorld(this.Location, this.Map);
            m_Box_Holder.Z = this.Z - 10;
            m_Box_Holder.UpdateName();
        }
        MenuUploader.Display(m_Menu, m, this, false);
    }
     
    public StoneRewardVendor(Serial serial)
        : base(serial)
    {
    }

    public override void Serialize(GenericWriter writer)
    {
        base.Serialize(writer);

        writer.Write((int)0); //Version 0

        int count = m_Rewards.Count;
        writer.Write((int)count);

        if (count > 0)
        {
            for (int i = 0; i < count; i++)
            {
                writer.WriteItem((Reward)m_Rewards[i]);
            }
        }

        writer.WriteItem((Currency)m_Currency);
        writer.Write((string)m_Menu.Name);
        writer.WriteItem((DisplayBox)m_Box);
        writer.WriteItem((StoneRewardHolder)m_Box_Holder);
    }

    public override void Deserialize(GenericReader reader)
    {
        base.Deserialize(reader);

        WorldRewardVendors.RegisterVendor(this);

        int version = reader.ReadInt();

        m_Rewards = new RewardCollection();

        int count = reader.ReadInt();
        if (count > 0)
        {
            for (int i = 0; i < count; i++)
            {
                Reward r = (Reward)reader.ReadItem();
                m_Rewards.Add(r);
            }
        }

        m_Currency = (Currency)reader.ReadItem();

        try { string name = reader.ReadString(); m_Menu = ScriptCompiler.FindTypeByName(name); }
        catch { m_Menu = typeof(JewlRewardGump); }

        m_Box = (DisplayBox)reader.ReadItem();
        m_Box_Holder = (StoneRewardHolder)reader.ReadItem();
    }
}
public interface IRewardVendor
{
    //used to determine how player pays
    Currency Payment { get; set; }
    //to keep added items
    RewardCollection Rewards { get; set; }
    //to change gump
    Type Menu { get; set; }
    //to show player items
    DisplayBox Display { get; }
    //to return what holds 'DisplayBox' object
    Container GetContainer();
    //to return removal status
    bool IsRemoved();
   
    //serial /deserial
    Mobile GetMobile();
    Item GetItem();

    //used for 'world collection'
    string GetName();
    Point3D GetLocation();
    Map GetMap();

    //to manage RewardCollection
    void AddReward(Reward r);
    void RemoveReward(Reward r);
    
    //to create vendor clones
    void CopyVendor(IRewardVendor vendor);
}
public interface IRewardVendorGump
{
    void Send(Mobile m);
    void AddEntry(Reward r);
    void CreateBackground();
    
    //add entry || background || 
}


public class PaymentTarget : Target
{
    private string m_Name;
    private IRewardVendor m_Vendor;
    private bool m_Is_XML;

    public PaymentTarget()
        : base(2, false, TargetFlags.None)
    {
    }
    //by item
    public PaymentTarget(IRewardVendor vendor) : this ()
	{
        m_Vendor = vendor;
        m_Name = null;
        m_Is_XML = false;
    }
    //by item property
    public PaymentTarget(IRewardVendor vendor, string name, bool isXML) : this()
    {
        m_Vendor = vendor;
        m_Name = name;
        m_Is_XML = isXML;
    }
    protected override void OnTarget(Mobile m, object targeted)
    {
        if (m_Is_XML && !String.IsNullOrEmpty(m_Name))
        {
            Type attachType = ScriptCompiler.FindTypeByName(m_Name);

            if (attachType != null && attachType.BaseType.Equals(typeof(XmlAttachment)))
            {
                List<PropertyInfo> integerProps = new List<PropertyInfo>();

                foreach (PropertyInfo pi in attachType.GetProperties())
                {
                    if ((pi.CanRead && pi.CanWrite) && pi.PropertyType.Equals(typeof(System.Int32)))
                        integerProps.Add(pi);
                }

                if (integerProps.Count == 0)
                    m.SendMessage("{0} does not contain any integer based properties.", attachType.Name);
                else
                    m.SendGump(new XMLIntPropertyGump(attachType, targeted, m_Vendor, integerProps));
            }
            else
                m.SendMessage("The XML Attachment, {0}, could not be found, the search IS case sensitive", m_Name);
        }
        else if ( targeted is Item )
        {           
            //consume by item
            if (m_Name == null)
            {
                m_Vendor.Payment = new Currency((Item)targeted);
                m.SendMessage("{0} will now use {1} for payment.", m_Vendor.GetName(), targeted.GetType().Name);
            }
            //consume by item property
            else
            {
                SetByProperty(m, targeted);
            }
        }
        else if (targeted is PlayerMobile)
        {
            if (m_Name == null)
            {
                m.SendMessage("You can only use Property option for player.");

            }
            else
            {
                SetByProperty(m, null);
            }
        }
        else
        {
            m.SendMessage("Invalid, target must be Item or Player.");
        }

        MenuUploader.Display(m_Vendor.Menu, m, m_Vendor, false);
    }
    private void SetByProperty(Mobile m, object o)
    {
        string msg = "Please make sure you entered the name correctly, "
                        + "it IS case sensitive.";
        try
        {
            if (o != null)//Item
            {
                PropertyInfo pi = o.GetType().GetProperty(m_Name);

                if (pi != null && pi.PropertyType.Equals(typeof(Int32)))
                {
                    m_Vendor.Payment = new Currency((Item)o, pi);
                    m.SendMessage(m_Vendor.GetName() + "will now use {1}.{2} for payment.", m_Vendor.GetName(), o.GetType().Name, pi.Name);
                }
                else
                    m.SendMessage(msg);
            }
            else//Mobile
            {
                PropertyInfo pi = m.GetType().GetProperty(m_Name);

                if (pi != null && pi.PropertyType.Equals(typeof(Int32)))
                {
                    m_Vendor.Payment = new Currency(m, pi);
                    m.SendMessage("{0} will now use {1}.{2} for payment.", m_Vendor.GetName(), m.GetType().Name, pi.Name);
                }
                else
                    m.SendMessage(msg);
            }
        }
        catch { m.SendMessage(msg); }
    }
}
public class AddItemTarget : Target
{
    IRewardVendor m_Vendor;

    public AddItemTarget() : base( 2, false, TargetFlags.None )
	{
	}
    public AddItemTarget(IRewardVendor vendor)
        : this()
    {
        m_Vendor = vendor;
    }
    protected override void OnTarget(Mobile from, object targeted)
    {
        Item i = targeted as Item;

        if (m_Vendor == null || i == null)
            return;

        Item clone = ItemClone.Clone(i);

        if (clone != null) //copy did not fail
            from.SendGump(new EditItemGump(m_Vendor, new Reward(clone), null, false, true));
        else
            from.SendMessage("This item cannot be copied.");

    }
}

public class ItemClone
{
    public static Item Clone(Item item) 
    {
        try
        {
            if ( item is Container )
                return CloneBag(((Container)item).FindItemsByType(typeof(Item), false), (Container)item, (Container)Activator.CreateInstance(item.GetType(), null));
            else
                return Clone(item.GetType(), item, (Item)Activator.CreateInstance(item.GetType(), null));
        }
        catch {}
       
        return null;
    }
    public static Container CloneBag(Item[] contents, Container old, Container copy)
    {        
        //emtpy new container
        foreach (Item i in copy.FindItemsByType(typeof(Item)))
        {
            i.Delete();
        }

        //'old' contents into 'new'
        foreach (Item i in contents)
        {
            copy.DropItem(Clone(i));           
        }

        copy.Name = old.Name; //requires manual set

        return copy;
    }
    public static Item Clone(Type type, Item old, Item copy)
    {
        foreach (PropertyInfo pi in type.GetProperties())
        {
            if (pi.CanRead && pi.CanWrite && ValidProperty(pi.Name)) 
            {
                try
                {
                    if (pi.PropertyType.IsClass)
                        CloneInnerClass(pi.PropertyType, pi.GetValue(old, null), pi.GetValue(copy, null)); //found object property
                    else
                        pi.SetValue(copy, pi.GetValue(old, null), null); //found value property
                }
                catch {}
            }
        }

        copy.Name = old.Name; //requires manual set

        return copy;
    }
    public static void CloneInnerClass(Type type, object old, object copy)
    {
        if (old == null) //not defined
            return;
        
        foreach ( PropertyInfo pi in type.GetProperties() )
        {
            if ( pi.CanRead && pi.CanWrite ) 
            {
                try
                {
                    pi.SetValue(copy, pi.GetValue(old, null), null);
                }
                catch {}
            }
        }
    }
    public static bool ValidProperty(string str) 
    {
        return !( str.Equals("Parent") || str.Equals("TotalWeight") || str.Equals("TotalItems") || str.Equals("TotalGold") );
    }
   
}
}
 

deides

Traveler
great, thanks alot for this!! works perfectly !!!

except I had an error (missing a } somewhere). once I added the missing } everything worked fine.
 

Pure Insanity

Sorceror
My bad, I guess I copied it all before I made my final edits. At least it's working for you, should mean that it will work for everyone else using the latest svn.

Btw, this system is beyond awesome. Can't believe I've never heard of it till now, and never seen it on other shards. I can see us using this for a ton of things on our shard.
 

romanthebrain

Sorceror
Hey! I don't know if I messed up the script or something, but i loaded my vendor with ingots, just add one switch to classic view stock it to 5000, buy them with a character that can hold some but not all get a nice stack in my pack and the rest is added to my bank one by one, not in stacks! Any ideas to fix this problem? Thanks!

any solution for this error... i got the same but mine with regs , what can i do ?
 

aaron421

Wanderer
krazeykow;771617 said:
The Complete Customizable Vendor​
Full Support Any* XML Attachment Version (XmlPoints, etc.) Released 12/9/09

Update History:

New XML Version Released 12/9/09 - Supports any XML Attachment (XmlPoints, XmlStaffPoints, etc.)
New Version Released 11/20/09 - Includes Stone Vendor

Why is it called the Complete Customizable Vendor?

Now supports any XML attachment on a player or an item! For example, with XmlPoints system, you simply select XmlAttachment, type the name 'XmlPoints' and target the player!

Payment type can be set to anything imaginable. Tokens, PvP Points, Gold, Quest Items, etc. If it is a number in [props of the player or an item, it can be the payment! Direct consumption of the item also works.

Add customized items without ever scripting them inside the game. The vendor system automatically recognizes the additions you have made to the item through [props. Each item the vendor obtains is a mirror image of what you add. Bags work as well!

Choose between a stone based or mobile based reward vendor. Update 11/20/09 now includes a stone version, never bother with creating your own reward stones again!

Create your own automated reward room that runs directly off of the vendor system. Called 'Displays', they are individual items that can be displayed in a showcase. Once the player clicks on the item, a menu pops up with further information and the option to purchase. (Shown lower right in picture)

Restock options bring a whole new dimension of versatility. Items can be set to be 'Limited Editions' i.e. only a set amount can be sold. Of course, count, refresh rate, and many other options are also available.

The Classic OSI vendor menu is available through the mobile version, keeping continuity for vendor malls.

Never lose track of any of the vendors. All vendors are listed with a 'go to' option.

Make quick copies of your vendors with the 'copy vendor' option.


About me

With no prior knowledge, I came to this community in 2004 looking for a helping hand in learning programming. I never knew it would take me this far. This is my creation as an example of how far I've come with RunUO. Special thanks included below

*Zippy, Vorspire, Lord_Greywolf, Lokai, Taffer, b0b01​

Installation


Drag and drop.
Add a vendor - [add mobilerewardvendor
Add a stone - [add stonerewardvendor

Please leave feedback and/or suggestions, thank you.

NOTICE:
**First time installing the system:
If the compiler has an error that reads 'Namespace '<global namespace>' contains a definition conflicting with alias 'Reward'. Type namespace System.CustomizableVendor right before public class Currency at the top. Add { directly after it. Then add a } at the very bottom.
**Already have the system installed:
Use the Replace All method for Reward and use anything else (CustomReward, etc.).



Choose only one of the following.
I Keep Getting This I Even Did What You Said To do In Red? And Help?


RunUO - [www.runuo.com] Version 2.0, Build 3567.2838
Core: Running on .NET Framework Version 2.0.50727
Core: Optimizing for 2 processors
Scripts: Compiling C# scripts...failed (1 errors, 0 warnings)
Errors:
+ [RC2] Rewards System.cs:
CS1514: Line 15: { expected
CS0101: Line 18: The namespace '<global namespace>' already contains a defin
ition for 'Currency'
CS0102: Line 33: The type 'Currency' already contains a definition for 'Paym
ent'
CS0101: Line 364: The namespace '<global namespace>' already contains a defi
nition for 'Reward'
CS0102: Line 515: The type 'Reward' already contains a definition for 'Resto
ckInfo'
CS0101: Line 677: The namespace '<global namespace>' already contains a defi
nition for 'RewardCollection'
CS0101: Line 693: The namespace '<global namespace>' already contains a defi
nition for 'WorldRewardVendors'
CS0101: Line 709: The namespace '<global namespace>' already contains a defi
nition for 'EditItemGump'
CS0101: Line 946: The namespace '<global namespace>' already contains a defi
nition for 'Exhibit'
CS0101: Line 1045: The namespace '<global namespace>' already contains a def
inition for 'ViewItemGump'
CS0101: Line 1208: The namespace '<global namespace>' already contains a def
inition for 'Storage'
CS0101: Line 1225: The namespace '<global namespace>' already contains a def
inition for 'WorldVendorsGump'
CS0101: Line 1354: The namespace '<global namespace>' already contains a def
inition for 'InfoGump'
CS0101: Line 1385: The namespace '<global namespace>' already contains a def
inition for 'ControlPanelGump'
CS0101: Line 1586: The namespace '<global namespace>' already contains a def
inition for 'MenuUploader'
CS0101: Line 1648: The namespace '<global namespace>' already contains a def
inition for 'ManageItemsGump'
CS0101: Line 1765: The namespace '<global namespace>' already contains a def
inition for 'JewlRewardGump'
CS0101: Line 1900: The namespace '<global namespace>' already contains a def
inition for 'DisplayBox'
CS0101: Line 2079: The namespace '<global namespace>' already contains a def
inition for 'LoadGumpEntry'
CS0101: Line 2101: The namespace '<global namespace>' already contains a def
inition for 'ClassicVendorGump'
CS0101: Line 2205: The namespace '<global namespace>' already contains a def
inition for 'MobileRewardVendor'
CS0101: Line 2497: The namespace '<global namespace>' already contains a def
inition for 'StoneRewardHolder'
CS0101: Line 2539: The namespace '<global namespace>' already contains a def
inition for 'StoneRewardVendor'
CS0101: Line 2734: The namespace '<global namespace>' already contains a def
inition for 'IRewardVendor'
CS0101: Line 2765: The namespace '<global namespace>' already contains a def
inition for 'IRewardVendorGump'
CS0101: Line 2775: The namespace '<global namespace>' already contains a def
inition for 'PaymentTarget'
CS0101: Line 2865: The namespace '<global namespace>' already contains a def
inition for 'AddItemTarget'
CS0101: Line 2894: The namespace '<global namespace>' already contains a def
inition for 'ItemClone'
Scripts: One or more scripts failed to compile or no script files were found.
- Press return to exit, or R to try again.
 

runuosucks

Wanderer
Code:
Errors:
 + Customs/SVN Custom Addons/Donation Stuff/[RC2] Rewards System.cs:
    CS0117: Line 2155: 'Server.Network.NetState' does not contain a definition f
or 'IsPost6017'
    CS0117: Line 2361: 'Server.Network.NetState' does not contain a definition f
or 'IsPost6017'
Scripts: One or more scripts failed to compile or no script files were found.
 - Press return to exit, or R to try again.

Code:
//Author: krazeykow
//Version: 1.0.1

using System;
using Server;
using Server.Items;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using Server.Gumps;
using Server.Network;
using Server.Targeting;
using Server.Mobiles;
using Server.ContextMenus;
using Server.Engines.XmlSpawner2;

namespace System.CustomizableVendor
{
public class Currency : Item
{

    private Payment m_Payment;
    private PropertyInfo m_PropertyInfo;
    private Type m_Payment_Type;
    private Type m_XML_Type;
    private int m_ItemID;
    private string m_Name;
    private int m_Hue;

    public Type XMLType { get { return m_XML_Type; } }
    public Type PaymentType { get { return m_Payment_Type; } }
    public string PayName { get { return m_Name; } }
    public int PayID { get { return m_ItemID; } }
    public int CurrHue { get { return m_Hue; } } 

    public enum Payment
    {
        ByGold,
        ByItem,
        ByProperty,
        ByXMLAttachment
    }
    //default
    public Currency()
    {
        m_Payment = Payment.ByGold;
        m_Payment_Type = typeof(Gold);
        m_PropertyInfo = null;
        m_ItemID = 3823;
        m_Name = "Gold";
    }
    public Currency(object bindedTo, Type attachType, PropertyInfo attachProp)
    {
        m_XML_Type = attachType;
        m_Payment = Payment.ByXMLAttachment;
        m_Payment_Type = bindedTo.GetType();
        m_PropertyInfo = attachProp;

        if (bindedTo is Mobile) {
            m_ItemID = 8461;
            m_Name = "Player " + attachProp.Name;
        }
        else if (bindedTo is Item) {
            m_ItemID = ((Item)bindedTo).ItemID;
            m_Name = GetName((Item)bindedTo) + "'s " + attachProp.Name;
            m_Hue = ((Item)bindedTo).Hue;
        }

    }
    //consume by item
    public Currency(Item i)
    {
        if ( i.GetType().Equals(typeof(Gold)) )
            m_Payment = Payment.ByGold;
        else
            m_Payment = Payment.ByItem;

        m_Payment_Type = i.GetType();
        m_PropertyInfo = null;
        m_ItemID = CoinID(i.ItemID);
        m_Name = GetName(i);
        m_Hue = i.Hue;
    }
    //consume property on player
    public Currency(Mobile m, PropertyInfo pi)
    {
        m_Payment = Payment.ByProperty;
        m_Payment_Type = m.GetType();
        m_PropertyInfo = pi;
        m_ItemID = 8461;
        m_Name = "Player " + pi.Name;
    }
    //consume by item's number based property
    public Currency(Item i, PropertyInfo pi)
    {
        m_Payment = Payment.ByProperty;
        m_Payment_Type = i.GetType();
        m_PropertyInfo = pi;
        m_ItemID = CoinID(i.ItemID);
        m_Name = GetName(i) + "'s " + pi.Name;
        m_Hue = i.Hue;
    }
    public void Modify(Type t, string append)
    {
        if ( (t.Equals(typeof(PlayerMobile)) || append == null ))
            return;

        Item i;
        
        i = (Item)Activator.CreateInstance(t, null);
        m_Name = GetName(i) + append;
        m_Hue = i.Hue;
        m_ItemID = CoinID(m_ItemID);
        
    }
    public int CoinID(int itemID)
    {
        if (itemID == 3821)
            return 3823;
        else if (itemID == 3824)
            return 3826;
        else
            return itemID;
    }
    public void VOneUpdate()
    {
        switch (m_Payment)
        {
            case Payment.ByGold:
            case Payment.ByItem:
                {
                    Modify(m_Payment_Type, "");
                    break;
                }
            case Payment.ByProperty:
                {
                    if (!(m_Payment_Type.Equals(typeof(PlayerMobile))))
                        Modify(m_Payment_Type, "'s " + m_PropertyInfo.Name);
                    break;
                }
        }

     }

    public string GetName(Item i)
    {
        if (String.IsNullOrEmpty(i.Name))
            return i.GetType().Name;
        else
            return i.Name;
    }
    public bool Purchase(Mobile m, int cost)
    {
        int remain = Value(m) - cost;

        if (remain < 0 || m.Backpack == null)
            return false;
        
        Charge(m, cost, remain);

        return true;
    }
    public void Charge(Container pack, Container bank, Type t, int cost)
    {
        if ( pack == null || bank == null )
            return;

        cost = cost - pack.ConsumeUpTo(t, cost);

        if ( cost > 0 )
            bank.ConsumeUpTo(t, cost);
    }
   
    public void Charge(Mobile m, Type t, PropertyInfo pi, int cost, int remain)
    {
        try
        {
            if (t.BaseType.Equals(typeof(Mobile)) || t.Equals(typeof(PlayerMobile)))
            {
                SetPropertyValue(m, remain);
            }
            else
            {
                if (m.Backpack == null || m.FindBankNoCreate() == null)
                    return;

                Item[] packItems = m.Backpack.FindItemsByType(t);
                Item[] bankItems = m.FindBankNoCreate().FindItemsByType(t);

                Item[] items = new Item[packItems.Length + bankItems.Length];
                packItems.CopyTo(items, 0);
                bankItems.CopyTo(items, packItems.Length);

                //none found in backpack
                if (items == null)
                    return;

                int i = 0, value = 0, dif = 0;

                //account for multiple objects
                while (cost > 0 && i < items.Length)
                {
                    value = GetPropertyValue(items[i]);

                    dif = value - cost;

                    //one item has enough
                    if (dif >= 0)
                    {
                        SetPropertyValue(items[i], dif);
                    }
                    //take what amount item has (the amount has already been confirmed by Value(m))
                    else // assert (dif < 0)
                    {
                        cost -= GetPropertyValue(items[i]);
                        SetPropertyValue(items[i], 0);
                    }
                    i++;
                }
            }
        }
        catch { }
    }
    public void Charge(Mobile m, Container pack, Container bank, int cost)
    {
        if ( pack == null || bank == null )
            return;

        cost = cost - pack.ConsumeUpTo(typeof(Gold), cost);

        if (cost > 0)
            Banker.Withdraw(m, cost);
    }
    public void Charge(Mobile m, int cost, int remain)
    {
        switch (m_Payment)
        {
            case Payment.ByGold:
                Charge(m, m.Backpack, m.FindBankNoCreate(), cost);
                break;
            case Payment.ByItem:
                Charge(m.Backpack, m.FindBankNoCreate(), m_Payment_Type, cost);
                break;
            case Payment.ByXMLAttachment:
            case Payment.ByProperty:
                Charge(m, m_Payment_Type, m_PropertyInfo, cost, remain);
                break;
        }
    }
    public int Value(Mobile m)
    {
        switch (m_Payment)
        {
            case Payment.ByGold:
                return ProcessByGold(m);
            case Payment.ByItem:
                return ProcessByItem(m, m_Payment_Type);
            case Payment.ByXMLAttachment:
            case Payment.ByProperty:
                return ProcessByProperty(m, m_Payment_Type, m_PropertyInfo);                       
        }
        return 0;
    }

    public int ProcessByGold(Mobile m)
    {
        if (m.Backpack == null)
            return 0;

        int totalGold = 0;

        totalGold += m.Backpack.GetAmount( typeof( Gold ) );
        totalGold += Banker.GetBalance( m );

        return totalGold;
    }
    public int ProcessByItem(Mobile m, Type t)
    {
        Container pack = m.Backpack;
        Container bank = m.FindBankNoCreate();

        if (pack == null || bank == null)
            return 0;

        int amount = (pack.GetAmount(t) + bank.GetAmount(t));

        return amount;
    }
    public int ProcessByProperty(Container pack, Container bank, Type t, PropertyInfo pi)
    {
        if (pack == null || bank == null)
            return 0;


        Item[] packItems = pack.FindItemsByType(t);
        Item[] bankItems = bank.FindItemsByType(t);

        Item[] items = new Item[packItems.Length + bankItems.Length];
        packItems.CopyTo(items, 0);
        bankItems.CopyTo(items, packItems.Length);
        
        int sum = 0;

        foreach (object o in items)
        {
            sum += GetPropertyValue(o);
        }

        return sum;
    }
    public int GetPropertyValue(object o)
    {
        int val = 0;

        if (m_Payment == Payment.ByXMLAttachment)
        {
            val = GetXMLValue(o);
        }
        else
        {
            val = (int)m_PropertyInfo.GetValue(o, null);
        }

        return val;
    }
    public void SetPropertyValue(object o, int val)
    {
        if (m_Payment == Payment.ByXMLAttachment)
        {
            SetXMLValue(o, val);
        }
        else
        {
            m_PropertyInfo.SetValue(o, val, null);
        }       
    }
    public int GetXMLValue(object o)
    {      
        int val = 0;

        if (m_XML_Type == null)
            return val;

        XmlAttachment attach = XmlAttach.FindAttachment(o, m_XML_Type);

        if (attach != null) {           
            val = (int)m_PropertyInfo.GetValue(attach, null);           
        }
        return val;
    }
    public void SetXMLValue(object o, int val)
    {
        if (m_XML_Type == null)
            return;

        XmlAttachment attach = XmlAttach.FindAttachment(o, m_XML_Type);

        if (attach != null) { 
            m_PropertyInfo.SetValue(attach, val, null);           
        }
    }
    //Master
    public int ProcessByProperty(Mobile m, Type t, PropertyInfo pi)
    {
        try
        { 

            if (t.BaseType.Equals(typeof(Mobile)) || t.Equals(typeof(Mobile)) )
            {
                return GetPropertyValue(m);
            }
            else
            {
                return ProcessByProperty(m.Backpack, m.FindBankNoCreate(), t, pi);
            }
        }
        catch {}
        
        return 0;
        
    }
   
    public Currency( Serial serial ) : base( serial )
	{
	}
	public override void Serialize( GenericWriter writer )
	{
		base.Serialize( writer );
		writer.Write( (int) 2 );

        //version 2
        writer.Write((string)(m_XML_Type == null ? "" : m_XML_Type.Name));

        //version 1
        writer.Write((int)m_Hue);
        
        //explicit casts are given for clarification        
        writer.Write((int)m_Payment);
        writer.Write((string)m_Payment_Type.Name);
        writer.Write((string)(m_PropertyInfo == null ? "" : m_PropertyInfo.Name));
        writer.Write((int)m_ItemID);
        writer.Write((string)m_Name);
        
	}
	
	public override void Deserialize(GenericReader reader)
	{
		base.Deserialize( reader );
		int version = reader.ReadInt();


        switch (version)
        {
            case 2:
                {
                    try
                    {
                        string name = reader.ReadString();
                        if (name.Equals(""))
                        {
                            m_XML_Type = null;
                        }
                        else
                        {
                            m_XML_Type = ScriptCompiler.FindTypeByName(name);
                        }
                    }
                    catch { }

                    goto case 1;
                }
            case 1:
                {
                    m_Hue = reader.ReadInt();
                    goto case 0;
                }
            case 0:
                {
                    m_Payment = (Payment)reader.ReadInt();

                    try { string name = reader.ReadString(); m_Payment_Type = ScriptCompiler.FindTypeByName(name); }
                    catch { }

                    try
                    {
                        string propName = reader.ReadString();
                        if (propName.Equals("")) //never set
                        {
                            m_PropertyInfo = null;
                        }
                        else if (m_Payment == Payment.ByXMLAttachment && m_XML_Type != null) //XML requires find property by the XML Class type (m_XML_Type)
                        {
                            m_PropertyInfo = m_XML_Type.GetProperty(propName);
                        }
                        else 
                        { 
                            m_PropertyInfo = m_Payment_Type.GetProperty(propName); 
                        }
                    }
                    catch { }

                    m_ItemID = reader.ReadInt();
                    m_Name = reader.ReadString();

                    break;
                }
        }
        if (version == 0)
        {
            try { VOneUpdate(); }
            catch {  }
        }
     }
}

public class Reward : Item, ICloneable
{      
    private Item m_Reward;
    private int m_Cost;
    private string m_Title;
    private string m_Description;

    private ObjectPropertyList m_Display;

    private RestockInfo m_RestockInfo;
    private int m_BuyCount;

    public int BuyCount { get { return m_BuyCount; } set { m_BuyCount = value; } }
    public RestockInfo Restock { get { return m_RestockInfo; } set { m_RestockInfo = value; } }

    public ObjectPropertyList Display
    {
        get
        {
            if (m_Display == null)
            {
                m_Display = new ObjectPropertyList(this);

                m_Reward.GetProperties(m_Display);
                m_Reward.AppendChildProperties(m_Display);

                m_Display.Terminate();
                m_Display.SetStatic();
            }

            return m_Display;
        }
    }

    public void Void_RestockInfo()
    {
        m_RestockInfo = null;
    }
    //returns ((-1) -> no restockInfo) or current count
    public int Try_Restock()
    {
        if (m_RestockInfo == null)
            return -1;        

        TimeSpan dif = DateTime.Now - m_RestockInfo.LastRestock;
        int cycles = 0;

        if (dif > (m_RestockInfo.RestockRate) && m_RestockInfo.RestockRate.TotalMinutes > 0)
        {
            cycles = (int)(dif.TotalMinutes / m_RestockInfo.RestockRate.TotalMinutes);

            for (int i = 0; i < cycles; ++i)
            {
                if (m_RestockInfo.Restock())
                    continue;
            }
        }

        return m_RestockInfo.Count;
    }
    public bool InStock(int amount)
    {
        return (m_RestockInfo == null ? true : (m_RestockInfo.Count - amount >= 0));       
    }
    public void RegisterBuy(int amount)
    {      
        if (m_RestockInfo != null && InStock(amount))
            m_RestockInfo.Count -= amount;

        this.m_BuyCount += amount;
    }

    //for retrieving information only
    public Item RewardInfo
    {
        get { return m_Reward; }
    }
    //use only when creating Reward for player
    public Item RewardCopy
    {
        get { return GetReward(); }
    }
    public int Cost
    {
        get { return m_Cost; }
        set { m_Cost = value; }
    }
    public string Title
    {
        get { return m_Title; }
        set { m_Title = value; }
    }
    public string Description
    {
        get { return m_Description; }
        set { m_Description = value; }
    }
    object ICloneable.Clone()
    {
        return new Reward(this);
    }
    public Reward()
    {
        m_Reward = new Item();
        m_Cost = 0;
        m_Title = "";
        m_Description = "";
        m_RestockInfo = null;
    }
    public Reward(Reward r)
    {
        m_Reward = r.RewardCopy;
        m_Cost = r.Cost;
        m_Title = r.Title;
        m_Description = r.Description;
        m_RestockInfo = null;
    }
    public Reward(Item i)
    {
        m_Reward = i;
        m_Cost = 0;
        m_Title = (i.Name == null ? i.GetType().Name : i.Name);
        m_Description = "None.";
        m_RestockInfo = null;

    }
    public Reward(Item i, int cost)
    {
        m_Reward = i;
        m_Cost = cost;
        m_Title = (i.Name == null ? i.GetType().Name : i.Name);
        m_Description = "None.";
        m_RestockInfo = null;
    }
    public Reward(Item i, int cost, string title)
    {
        m_Reward = i;
        m_Cost = cost;
        m_Title = title;
        m_Description = "None.";
        m_RestockInfo = null;
    }
    public Reward(Item i, int cost, string title, string desc)
    {
        m_Reward = i;
        m_Cost = cost;
        m_Title = title;
        m_Description = desc;
        m_RestockInfo = null;
    }

    public class RestockInfo 
    {
        private TimeSpan m_RestockRate;
        private DateTime m_LastRestock;

        private int m_RestockAmnt;
        private int m_Count;
        private int? m_Maximum;
        
        public TimeSpan RestockRate { get { return m_RestockRate; } }
        public DateTime LastRestock { get { return m_LastRestock; } }

        public int RestockAmnt { get { return m_RestockAmnt; } }
        public int Count { get { return m_Count; } set { m_Count = value; } }
        public int Maximum { get { return m_Maximum.GetValueOrDefault(-1); } }

        public int Hours { get { return (int)m_RestockRate.Hours; } }
        public int Minutes { get { return (int)m_RestockRate.Minutes; } }

        public RestockInfo()
        {
            m_RestockRate = new TimeSpan();
            m_RestockAmnt = 0;
            m_Count = 0;
            m_Maximum = null;
            m_LastRestock = DateTime.Now;

        }
        public RestockInfo(int count) : this()
        {
            m_Count = count;
        }
        public RestockInfo(int hour, int minute, int count, int RestockNum)
        {
            m_RestockRate = new TimeSpan(hour, minute, 0);
            m_Count = count;
            m_RestockAmnt = RestockNum;
            m_Maximum = null;
            m_LastRestock = DateTime.Now;

        }
        public RestockInfo(int hour, int minute, int count, int RestockNum, int maxNum) : this (hour, minute, count, RestockNum)
        {
            m_Maximum = maxNum;
        }
        public bool Equals(RestockInfo info)
        {
            return (this.m_RestockRate.Equals(info.RestockRate) && (this.m_RestockAmnt == info.RestockAmnt) && (this.m_Count == info.Count)
                && (this.m_Maximum == info.Maximum));
        }
        public bool Restock()
        {
            m_LastRestock = DateTime.Now;

            if (m_Maximum != null) //Restock to a limit
            {
                if ((m_Count + m_RestockAmnt) > m_Maximum)
                {
                    m_Count = m_Maximum.Value;
                    return false;
                }

                m_Count += m_RestockAmnt;
                return true;
            }
            
            m_Count += m_RestockAmnt;            
            return true;
        }

        public void Serialize( GenericWriter writer )
        {
            writer.Write((TimeSpan)m_RestockRate);           
            writer.Write((int)m_RestockAmnt);
            writer.Write((int)m_Count);
            writer.Write((int)m_Maximum.GetValueOrDefault(-1));
        }

        public RestockInfo( GenericReader reader )
        {
            m_RestockRate = reader.ReadTimeSpan();
            m_LastRestock = DateTime.Now;
            m_RestockAmnt = reader.ReadInt();
            m_Count = reader.ReadInt();
            
            int? max = reader.ReadInt();
         
            m_Maximum = ((max < 0) ? null : max);
        }
    }

    public void Edit(int cost, string title, string desc)
    {
        if (cost < 0 || title == null || desc == null)
            return;

        m_Cost = cost;
        m_Title = title;
        m_Description = desc;
    }
    public Item GetReward()
    {
        return ItemClone.Clone(m_Reward);
    }

    public Reward( Serial serial ) : base( serial )
	{
	}
	public override void Serialize( GenericWriter writer )
	{
		base.Serialize( writer );

		writer.Write( (int) 1 );

        writer.Write((int)m_BuyCount);

        if (m_RestockInfo == null)
        {
            writer.Write(false);
        }
        else
        {
            writer.Write(true);
            m_RestockInfo.Serialize(writer);
        }

        writer.WriteItem((Item)m_Reward);
        writer.Write((int)m_Cost);
        writer.Write((string)m_Title);
        writer.Write((string)m_Description);          
    }
	
	public override void Deserialize(GenericReader reader)
	{
		base.Deserialize( reader );
		int version = reader.ReadInt();

        switch (version)
        {
            case 1:
                {
                    m_BuyCount = reader.ReadInt();

                    if (reader.ReadBool())
                        m_RestockInfo = new RestockInfo(reader);

                    goto case 0;
                }
            case 0:
                {
                    m_Reward = (Item)reader.ReadItem();
                    m_Cost = reader.ReadInt();
                    m_Title = reader.ReadString();
                    m_Description = reader.ReadString();                  
                    
                    break;
                }
        }
    
	}

}
public class RewardCollection : List<Reward>, ICloneable
{
    

    object ICloneable.Clone()
    {
        RewardCollection clone = new RewardCollection();
        
        foreach (Reward r in this)
        {
            clone.Add(((Reward)(r as ICloneable).Clone()));
        }
        return clone;
    }
}

public static class WorldRewardVendors
{
    private static List<IRewardVendor> m_Vendors = new List<IRewardVendor>();

    public static List<IRewardVendor> Vendors { get { return m_Vendors; } }
   
    public static void RegisterVendor(IRewardVendor vendor)
    {
        m_Vendors.Add(vendor);
    }
    public static void RemoveVendor(IRewardVendor vendor)
    {
        m_Vendors.Remove(vendor);
    }
}

public class EditItemGump : Gump
{
    private IRewardVendor m_Vendor;
    private Reward m_Reward;

    private Reward.RestockInfo m_Restock;
    private bool m_RestockOpen;

    private bool m_IsAdd;

    private Storage m_Entries;

    public EditItemGump(IRewardVendor vendor, Reward r, Storage entries, bool openRestockInfo, bool addingItem) : base(0, 0)
    {
        m_Vendor = vendor;
        m_Reward = r;

        m_Restock = r.Restock;
        m_RestockOpen = openRestockInfo;
        m_IsAdd = addingItem;

        m_Entries = entries; 

        this.Closable = true;
        this.Disposable = true;
        this.Dragable = true;
        this.Resizable = false;

        AddPage(0);

        AddImageTiled(227, 46, 329, 518, 2702);
        AddImageTiled(252, 291, 280, 217, 5104);
        AddLabel(253, 266, 2124, @"Description:");
        AddImageTiled(334, 147, 192, 23, 5104);
        AddLabel(258, 150, 2124, @"Cost:");
        AddImageTiled(336, 107, 192, 23, 5104);
        AddLabel(258, 108, 2124, @"Name:");
        AddImage(354, 199, 2328);
        AddItem(373, 208, r.RewardInfo.ItemID, r.RewardInfo.Hue);
        AddImageTiled(330, 54, 138, 16, 5214);
        AddLabel(373, 51, 1324, @"Edit Item");
        AddButton(465, 222, 5601, 5605, 2, GumpButtonType.Reply, 0); //restock
        AddLabel(447, 198, 2120, @"Restock ");
        AddLabel(447, 246, 2120, @"(Optional)");
        AddButton(324, 523, 4023, 4024, 1, GumpButtonType.Reply, 0);//ok
        AddButton(421, 523, 4017, 4018, 0, GumpButtonType.Reply, 0); //cancel

        if (entries == null)
            InitialText();
        else
            PacketText();

        if (openRestockInfo || r.Restock != null)
        {
            AddRestockMenu();
            m_RestockOpen = true;
        }
    }
    public void InitialText()
    {
        AddTextEntry(252, 292, 277, 215, 1879, 0, m_Reward.Description);
        AddTextEntry(334, 148, 188, 20, 1879, 1, m_Reward.Cost.ToString());
        AddTextEntry(336, 108, 188, 20, 1879, 2, m_Reward.Title);    
    }
    public void PacketText()
    {
        AddTextEntry(252, 292, 277, 215, 1879, 0, m_Entries[0].ToString()); //desc
        AddTextEntry(334, 148, 188, 20, 1879, 1, m_Entries[1].ToString());  //cost 
        AddTextEntry(336, 108, 188, 20, 1879, 2, m_Entries[2].ToString());  //title
    }
    public void AddRestockMenu()
    {

        AddPage(1);

        AddImageTiled(601, 47, 181, 469, 2624);
        AddLabel(648, 60, 2129, @"Restock Info");
        AddLabel(637, 98, 1418, @"Available");
        AddImageTiled(633, 123, 120, 16, 5214);
        AddTextEntry(637, 121, 107, 20, 547, 3, (m_Restock == null ? "Enter." : m_Restock.Count.ToString())); //3 - beginning amount
        AddLabel(660, 161, 1418, @"Maximum");
        AddImageTiled(631, 186, 120, 16, 5214);
        AddTextEntry(635, 184, 107, 20, 547, 4, ((m_Restock == null || m_Restock.Maximum < 0) ? "None." : m_Restock.Maximum.ToString())); //4 - Maxinum
        AddLabel(648, 227, 1418, @"Restock Rate");
        AddImageTiled(635, 252, 72, 16, 5214);
        AddTextEntry(638, 250, 64, 20, 547, 5, (m_Restock == null ? "0" : m_Restock.Hours.ToString())); //5 - hour
        AddLabel(714, 250, 602, @"hours");
        AddImageTiled(635, 292, 72, 16, 5214);
        AddLabel(716, 290, 602, @"mins");
        AddLabel(632, 323, 602, @"amount to restock");
        AddImageTiled(636, 355, 72, 16, 5214);
        AddTextEntry(638, 290, 64, 20, 547, 6, (m_Restock == null ? "0" : m_Restock.Minutes.ToString())); //6 - minute
        AddTextEntry(639, 353, 64, 20, 547, 7, (m_Restock == null ? "0" : m_Restock.RestockAmnt.ToString())); //7 - Restock Amount      
        AddImage(655, 377, 109);
        AddButton(636, 474, 4022, 4021, 3, GumpButtonType.Reply, 0);
        AddLabel(679, 475, 132, @"Void Restock");
        
    }
    public Reward.RestockInfo GetRestockInfo(RelayInfo info)
    {
        if (m_RestockOpen)
        {
            int numMinutes = 0, numHours = 0;
            int numBegin, numMax, numRestockAmnt;

            TextRelay entry3 = info.GetTextEntry(3);
            string beginAmount = (entry3.Text.Trim());

            TextRelay entry4 = info.GetTextEntry(4);
            string max = (entry4.Text.Trim());

            TextRelay entry5 = info.GetTextEntry(5);
            string hour = (entry5.Text.Trim());

            TextRelay entry6 = info.GetTextEntry(6);
            string minute = (entry6.Text.Trim());

            TextRelay entry7 = info.GetTextEntry(7);
            string restockAmount = (entry7.Text.Trim());

            Int32.TryParse(hour, out numHours);
            Int32.TryParse(minute, out numMinutes);
            Int32.TryParse(beginAmount, out numBegin);
            Int32.TryParse(max, out numMax);
            Int32.TryParse(restockAmount, out numRestockAmnt);

            if (numBegin > 0)
            {
                if ((numMinutes + numHours) > 0 && numRestockAmnt > 0)
                {
                    if (numMax > 0)
                    {
                        return new Reward.RestockInfo(numHours, numMinutes, numBegin, numRestockAmnt, numMax);
                    }
                    else
                    {
                        return new Reward.RestockInfo(numHours, numMinutes, numBegin, numRestockAmnt);
                    }
                }

                return new Reward.RestockInfo(numBegin);
            }                   
        }
        return m_Restock; //default
    }
    public Storage GetEntries(RelayInfo info)
    {
        //Description
        TextRelay entry0 = info.GetTextEntry(0);
        string desc = (entry0 == null ? "None." : entry0.Text.Trim());

        //Cost
        TextRelay entry1 = info.GetTextEntry(1);
        string costtext = (entry1 == null ? "0" : entry1.Text.Trim());

        //Name
        TextRelay entry2 = info.GetTextEntry(2);
        string name = (entry2 == null ? "" : entry2.Text.Trim());

        return new Storage(desc, costtext, name);
    }
    public override void OnResponse(NetState sender, RelayInfo info)
    {
        Mobile m = sender.Mobile;

        switch (info.ButtonID)
        {
            case 0:
                {
                    //cancel
                    break;
                }
            case 1: //ok
                {
                    try
                    {
                        //Description
                        TextRelay entry0 = info.GetTextEntry(0);
                        string desc = (entry0 == null ? "None." : entry0.Text.Trim());

                        //Cost
                        TextRelay entry1 = info.GetTextEntry(1);
                        string costtext = (entry1 == null ? "%Error" : entry1.Text.Trim());
                        int cost = Int32.Parse(costtext);

                        //Name
                        TextRelay entry2 = info.GetTextEntry(2);
                        string name = (entry2 == null ? "" : entry2.Text.Trim());

                        if ( m_IsAdd )
                            m_Vendor.AddReward(m_Reward);
                        
                        m_Reward.Edit(cost, name, desc);

                        if (m_RestockOpen)
                        {
                            Reward.RestockInfo input = GetRestockInfo(info);

                            if (input != null)
                            {
                                if (m_Restock != null && !(m_Restock.Equals(input))) //do not reassign same object
                                {
                                    m_Reward.Restock = input;
                                }
                                else
                                {
                                    m_Reward.Restock = input;
                                }
                            }
                        }

                        m.SendMessage("{0} has been modified in {1}'s collection", name, m_Vendor.GetName());

                    }
                    catch { m.SendMessage("Please make sure all fields are filled correctly, and the title has not been previously used."); }

                    break;
                }
            case 2: //open restock options
                {                                  
                    m.SendGump(new EditItemGump(m_Vendor, m_Reward, GetEntries(info), true, m_IsAdd));
                    
                    return; //override display 
                }
            case 3: //delete restock options
                {                   
                    m_Reward.Void_RestockInfo();
                                    
                    m.SendGump(new EditItemGump(m_Vendor, m_Reward, GetEntries(info), false, m_IsAdd));
                    
                    return; //override display 
                }
        }
        MenuUploader.Display(m_Vendor.Menu, m, m_Vendor, true); //send back display
    }
}

public class Exhibit : Item
{
    private IRewardVendor m_Vendor;
    private Reward m_Reward;
    private ObjectPropertyList m_PropertyList;

    public Exhibit(IRewardVendor vendor, Reward r)
        : base()
    {
        m_Vendor = vendor;
        m_Reward = r;

        SetOPL(r);

        this.ItemID = r.RewardInfo.ItemID;
        this.Hue = r.RewardInfo.Hue;
    }
    public override void SendPropertiesTo(Mobile from)
    {
        if (m_PropertyList == null)
        {
            m_PropertyList = new ObjectPropertyList(this);
            m_PropertyList.Add("Display [Broken]");
        }

        from.Send(m_PropertyList);
    }
    public void SetOPL(Reward r)
    {
        Item i = r.RewardInfo;

        m_PropertyList = new ObjectPropertyList(this);

        m_PropertyList.Add("Cost: " + m_Reward.Cost.ToString() + " " + m_Vendor.Payment.PayName + " [Click for more]");

        i.GetProperties(m_PropertyList);
        i.AppendChildProperties(m_PropertyList);

        m_PropertyList.Terminate();
        m_PropertyList.SetStatic();

    }

    public override void OnDoubleClick(Mobile m)
    {
        if (m_Vendor == null || m_Vendor.IsRemoved() || m_Reward == null || !m_Vendor.Display.Contains(m_Reward))
        {
            m_Vendor = null; // free up resource
            m_Reward = null;
            m.SendMessage("This item is no longer available to purchase.");
        }
        else
            m.SendGump(new ViewItemGump(m, m_Vendor, m_Reward, false));
    }

    public Exhibit(Serial serial)
        : base(serial)
    {
    }
    public override void Deserialize(GenericReader reader)
    {
        base.Deserialize(reader);

        int version = reader.ReadInt();

        if (reader.ReadBool())
        {
            m_Reward = (Reward)reader.ReadItem();

            m_Vendor = (IRewardVendor)reader.ReadMobile();

            try { SetOPL(m_Reward); }
            catch { }
        }
    }

    public override void Serialize(GenericWriter writer)
    {
        base.Serialize(writer);

        writer.Write((int)0); // version  

        if (m_Vendor == null || m_Vendor.IsRemoved() || m_Reward == null || m_Reward.Deleted)
        {
            m_Vendor = null;
            m_Reward = null;

            writer.Write((bool)false); //do not deserialize
        }
        else
        {
            writer.Write((bool)true);

            writer.WriteItem((Reward)m_Reward);

            writer.Write((Mobile)m_Vendor.GetMobile());
        }
    }
}
public class ViewItemGump : Gump
{
    IRewardVendor m_Vendor;
    Reward m_Reward;

    public ViewItemGump(Mobile m, IRewardVendor vendor, Reward r, bool viewItem)
        : base(0, 0)
    {
        m_Vendor = vendor;
        m_Reward = r;

        this.Closable = true;
        this.Disposable = true;
        this.Dragable = true;
        this.Resizable = false;

        AddPage(0);
        AddImageTiled(149, 207, 548, 277, 2624);
        AddImage(184, 300, 2328);
        AddImage(101, 222, 10400);
        
        AddHtml(428, 290, 243, 140, r.Description, (bool)true, (bool)true);
        AddItem(201, 311, r.RewardInfo.ItemID, r.RewardInfo.Hue);
                
        AddLabel(430, 263, 2101, @"Description");
        AddButton(192, 442, 4029, 4030, 2, GumpButtonType.Reply, 0); //buy
        AddLabel(231, 444, 2125, "Buy (" + r.Cost +")");
        AddButton(366, 442, 4020, 4021, 0, GumpButtonType.Reply, 0); //cancel
        AddLabel(407, 444, 2116, @"Cancel");
        AddImageTiled(184, 239, 510, 8, 9201);

        AddItem(182, 376, m_Vendor.Payment.PayID, m_Vendor.Payment.CurrHue);
        AddLabel(248, 369, 83, @"Pay By: " + m_Vendor.Payment.PayName);
        AddLabel(184, 268, 43, @"Vendor: " + m_Vendor.GetName());
        AddLabel(363, 216, 2123, r.Title);

        if (m.AccessLevel > AccessLevel.GameMaster) //GM capabilities
        {
            if (!viewItem)
                AddLabel(363, 216, 2123, r.Title);
            else
            {
                AddLabel(336, 296, 2101, @"Edit Item");
                AddButton(294, 293, 4011, 4012, 4, GumpButtonType.Reply, 0); //edit item

                if (m_Vendor.GetMobile() != null)
                {
                    AddLabel(336, 348, 2101, @"Get Display");
                    AddButton(294, 345, 4011, 4012, 3, GumpButtonType.Reply, 0); //get display   
                }
            }
        }
        else
        {
            OpenDisplay(m); //prevent build up of box display during editing
        }

        //Edit gump for display object
        if (viewItem) //not display
        {
            AddLabel(336, 322, 2101, @"View Item");
            AddButton(294, 319, 4011, 4012, 1, GumpButtonType.Reply, 0); //view item
                    
        }
        else //display
        {
            AddLabel(279, 320, 38, @"Cost: " + m_Reward.Cost.ToString());
            AddLabel(249, 398, 69, @"You have: " + m_Vendor.Payment.Value(m));

            if (m_Reward.Restock != null)
            {
                m_Reward.Try_Restock();
                AddLabel(279, 340, 4, "In Stock: " + m_Reward.Restock.Count.ToString());
            }

            if (m_Reward.RewardInfo is Container)
                OpenDisplay(m); 
        }
    }
    public void OpenDisplay(Mobile m)
    {
        DisplayBox dbox = m_Vendor.Display;

        if (dbox != null)
            dbox.DisplayTo(m, m_Reward);
    }
    public override void OnResponse(NetState sender, RelayInfo info)
    {
        Mobile m = sender.Mobile;

        if (m_Vendor.IsRemoved())
            return;

        switch (info.ButtonID)
        {
            case 0:
                {
                    break;
                }
            case 1:
                {
                    try
                    {
                        OpenDisplay(m);
                        m.SendGump(this);
                    }
                    catch
                    {
                        m.SendMessage("This Reward can no longer be found.");
                    }
                    break;
                }
            case 2:
                {
                    Container bank = m.BankBox;
                    Container pack = m.Backpack;

                    if ( bank == null || pack == null )
                        break;

                    Currency curr = m_Vendor.Payment;

                    if (m_Reward.InStock(1))
                    {
                        if (curr.Purchase(m, m_Reward.Cost))
                        {
                            m_Reward.RegisterBuy(1);

                            Item i = m_Reward.RewardCopy;

                            if (!m.PlaceInBackpack(i))
                            {
                                bank.DropItem(i);
                                m.SendMessage("You are overweight, the Reward was added to your bank");
                            }

                            m.SendMessage("You bought {0} for {1} {2}.", m_Reward.Title, m_Reward.Cost, curr.PayName);

                        }
                        else
                            m.SendMessage("You cannot afford {0}", m_Reward.Title);
                    }                           
                    else
                        m.SendMessage("{0} is no longer in stock.", m_Reward.Title);  

                    break;
                }
            case 3:
                {
                    if (m.Backpack != null)
                        m.AddToBackpack(new Exhibit(m_Vendor, m_Reward));
                    break;
                }
            case 4:
                {
                    m.SendGump(new EditItemGump(m_Vendor, m_Reward, null, false, false));
                    break;
                }
        }
    }
}

//Created for the usage of Warning Gump delegate 
public class Storage
{
    object[] m_Objs;

    public object this[int index]
    {
        get { return m_Objs[index]; }
    }

    public Storage(params object[] input)
    {
        m_Objs = input;
    }
    
}


public class WorldVendorsGump : Gump
{
    IRewardVendor m_Vendor; //used in case of copy

    public WorldVendorsGump(IRewardVendor vendor) : base( 0, 0 )
    {
        m_Vendor = vendor;

        this.Closable=true;
		this.Disposable=true;
		this.Dragable=true;
		this.Resizable=false;

		AddPage(0);

        //background
        AddImageTiled(50, 3, 430, 556, 2702);
		AddImageTiled(93, 78, 387, 9, 10101);
		AddImage(33, 58, 10420);
		AddImageTiled(47, 2, 3, 556, 10004);
		AddImageTiled(0, 58, 82, 414, 10440);
		AddImageTiled(47, 558, 436, 3, 10001);
		AddImageTiled(47, 0, 435, 3, 10001);
		AddImageTiled(480, 2, 3, 556, 10004);

        AddPage(1);

        CreateVendors(); //fill out entries
    }
    
    public static void CopyVendor_Callback(Mobile from, bool okay, object state)
    {
        if (from.AccessLevel < AccessLevel.GameMaster)
            return;
                
        if (okay)
        {
            //indexes -> (vendor (0), vendor's copy target(1))
            Storage store = (Storage)state;

            IRewardVendor source = (IRewardVendor)store[0];
            IRewardVendor target = (IRewardVendor)store[1];

            try { source.CopyVendor(target); }
            catch { from.SendMessage("Error occured while copying, please insure backpack is on vendors."); return; }

            from.SendMessage("{0} has copied {1}'s Reward collection", source.GetName(), target.GetName());
        }
    }
    public override void OnResponse(NetState sender, RelayInfo info)
    {
        Mobile m = sender.Mobile;

        if (info.ButtonID == 0)
        {
            m.CloseGump(typeof(ControlPanelGump));
            return;
        }

        MenuUploader.Display(m_Vendor.Menu, m, m_Vendor, false);

        try
        {
            if (info.ButtonID % 2 == 0 ) //even ID: Copy Vendor
            {
                IRewardVendor selected = WorldRewardVendors.Vendors[(info.ButtonID / 2) - 1];

                if ( m_Vendor.GetName().Equals(selected.GetName()))
                {
                    m.SendMessage("A vendor cannot copy itself.");
                }
                else
                {
                    //params -> (vendor, vendor's copy target)
                    Storage store = new Storage(m_Vendor, selected);

                    m.SendGump(new WarningGump(1060635, 30720, "Warning: You will lose all saved items on " + m_Vendor.GetName(), 0xFFC000, 420, 400, new WarningGumpCallback(CopyVendor_Callback), store));
                }
            }
            else //assert odd ID: Goto 
            {
                IRewardVendor v = WorldRewardVendors.Vendors[((info.ButtonID + 1) / 2) - 1];

                m.Location = v.GetLocation();
                m.Map = v.GetMap();
            }
        }
        catch
        {
            m.SendMessage("Vendor cannot be found.");
        }
    }
    public void CreateVendors()
    {
        int yPos = 101, pageNum = 1, buttonNum = 0;
      
        for (int i = 0; i < WorldRewardVendors.Vendors.Count; ++i)
        {            
            AddButton(175, yPos + 38, 4005, 4006, ++buttonNum, GumpButtonType.Reply, pageNum); //goto button - odd ID
            AddButton(279, yPos + 38, 4011, 4012, ++buttonNum, GumpButtonType.Reply, pageNum); //copy vendor - even ID
            AddLabel(86, yPos, 1849, WorldRewardVendors.Vendors[i].GetName());
            AddImageTiled(86, yPos + 93, 359, 2, 96);

            if (WorldRewardVendors.Vendors[i].GetMobile() != null)
                AddItem(110, yPos + 27, 8461); // person
            else

                AddItem(110, yPos + 27, WorldRewardVendors.Vendors[i].GetItem().ItemID, WorldRewardVendors.Vendors[i].GetItem().Hue); //stone ID

            AddLabel(213, yPos + 43, 2209, @"Go To");
            AddLabel(318, yPos + 43, 2204, @"Copy Vendor");
            
            yPos += 99;

            //add new page every four entries
            if ((i + 1) % 4 == 0)
            {
                AddButton(417, 531, 9903, 248, -1, GumpButtonType.Page, (pageNum + 1));

                AddPage(++pageNum);

                AddButton(92, 532, 9909, 248, -1, GumpButtonType.Page, (pageNum - 1));

                //reset to top of page
                yPos = 101;
            }
        }
    }
}
public class InfoGump : Gump
{
    public InfoGump()
        : base(0, 0)
    {
        this.Closable = true;
        this.Disposable = true;
        this.Dragable = true;
        this.Resizable = false;

        AddPage(0);
        
        AddImageTiled(0, 0, 452, 516, 2702);
        AddHtml(21, 78, 407, 105, @"Consume Item:  Vendor counts the number of the chosen item present in player's backpack.  

        Property(Item/Player):  Vendor takes the total of the given number based property (example: PlayerPoints, Charges)
        (Items): Adds up from every item present.
        (Player): Simply takes from what is present.
        ", (bool)true, (bool)true);

        AddLabel(23, 52, 2000, @"Choosing How Player Pays:");
        AddHtml(21, 242, 407, 105, @"You can create your own rewards in game, all properties will be copied over.  ", (bool)true, (bool)true);
        AddLabel(24, 216, 2000, @"Adding Items");
        AddLabel(239, 479, 37, @"Author: krazeykow1102");
        AddItem(391, 467, 8451);
        AddLabel(24, 368, 2000, @"How Displays Work");
        AddHtml(24, 394, 410, 78, @"Displays allow you to create your own interactive Reward room.  The display is a simple mirror to the item on the vendor.  Payment and cost will reflect what is on the vendor.  Vendor must stay in tact for display to function", (bool)true, (bool)true);
    }
}


public class ControlPanelGump : Gump
{
    private IRewardVendor m_Vendor;
   
    public ControlPanelGump(Mobile m, IRewardVendor vendor)
        : base(0, 0)
    {

        m_Vendor = vendor;
                
        this.Closable = true;
        this.Disposable = true;
        this.Dragable = true;
        this.Resizable = false;

        AddPage(0);

        //background
        AddImageTiled(4, 3, 215, 571, 2702);
        AddImageTiled(3, 0, 217, 3, 10001);
        AddImageTiled(4, 572, 216, 3, 10001);
        AddImageTiled(3, 1, 3, 571, 10004);
        AddImageTiled(217, 1, 3, 574, 10004);

        AddImage(40, 8, 5214);
        AddLabel(41, 7, 47, @"Control Panel");

        AddLabel(109, 62, 55, @"Manage Rewards");
        AddButton(72, 60, 4008, 4009, 1, GumpButtonType.Reply, 0); //PlayerView
        AddItem(31, 63, 5366); //scope
        AddImageTiled(19, 160, 132, 2, 96);

        AddLabel(79, 123, 1324, @"Add Item or Container");
        AddButton(52, 126, 2117, 2118, 2, GumpButtonType.Reply, 0); //AddItem
        AddItem(0, 113, 8192); //box  
        
        AddLabel(11, 232, 55, @"Target Payment Source:");
        AddButton(170,232, 2117, 2118, 3, GumpButtonType.Reply, 0); //Payment
        AddLabel(12, 173, 55, @"Pay By: " + m_Vendor.Payment.PayName );
        AddItem(61, 197, m_Vendor.Payment.PayID, m_Vendor.Payment.CurrHue);

        AddLabel(12, 32, 55, @"Vendor: " + m_Vendor.GetName());
        AddButton(77, 533, 4026, 4027, 4, GumpButtonType.Reply, 0);
        AddLabel(78, 553, 104, @"Help");

        if (m_Vendor.GetMobile() != null)
        {
            AddButton(72, 91, 4011, 4012, 5, GumpButtonType.Reply, 0); //Displays
            AddLabel(109, 93, 55, @"Get All Displays");
        }
        else
            AddLabel(12, 93, 55, @"Use Mobile Vendor for displays.");

       
        AddLabel(51, 258, 43, @"XML Attachment");
        AddRadio(15, 258, 9720, 9724, false, 6);
        AddLabel(51, 303, 43, @"Consume Item");
        AddRadio(15, 300, 9720, 9724, false, 7);
        AddLabel(50, 349, 43, @"[props Name of Item/Player");
        AddRadio(15, 342, 9720, 9724, false, 8);
        AddImageTiled(12, 382, 156, 22, 5058);
        AddTextEntry(12, 382, 149, 20, 41, 0, @"[prop/XML Name Here");

        AddPage(1);

        CreateGumps(); //fill out entries
               
    }
    public override void OnResponse(NetState sender, RelayInfo info)
    {
        Mobile m = sender.Mobile;

        if (m_Vendor.IsRemoved())
        {
            m.SendMessage("This vendor has been deleted.");
            return;
        }

        switch (info.ButtonID)
        {
            case 0:
                {
                    m.CloseGump(typeof(WorldVendorsGump));

                    //close
                    break;
                }
            case 1: //PlayerView
                {
                    m.CloseGump(typeof(WorldVendorsGump));

                    MenuUploader.Display(m_Vendor.Menu, m, m_Vendor, true);
                    break;
                }
            case 2: //AddItem
                {
                    m.CloseGump(typeof(WorldVendorsGump));

                    m.Target = new AddItemTarget(m_Vendor);
                    break;
                }
            case 3: //Payment
                { 
                    
                        try
                        {
                            if (info.IsSwitched(6))
                            {
                                m.SendMessage("Target the player or item you wish to get the XMLAttribute from.");
                                TextRelay entry0 = info.GetTextEntry(0);
                                string propName = (entry0 == null ? "" : entry0.Text.Trim());

                                m.Target = new PaymentTarget(m_Vendor, propName, true);
                            }
                            else if ( info.IsSwitched(7)) // Consume by item amount
                            {
                                m.SendMessage("Warning: payment will be taken as the unmodified created item.");
                                m.Target = new PaymentTarget(m_Vendor);
                            }
                            else if (info.IsSwitched(8)) //Consume by item's property
                            {
                                m.SendMessage("Target yourself or an item.");
                                TextRelay entry0 = info.GetTextEntry(0);
                                string propName = (entry0 == null ? "" : entry0.Text.Trim());

                                m.Target = new PaymentTarget(m_Vendor, propName, false);
                            }
                            else
                            {                                
                                MenuUploader.Display(m_Vendor.Menu, m, m_Vendor, false);
                                m.SendMessage("Please select consume or property.");
                            }
                        }

                            catch { }

                            break;      
                  }
            case 4:
                {
                    MenuUploader.Display(m_Vendor.Menu, m, m_Vendor, false);
                    m.SendGump(new InfoGump());
                    break;
                }
            case 5: //Displays
                {
                    if (m.Backpack == null)
                        return;

                    MetalBox c = new MetalBox();
                    c.Name = m_Vendor.GetName() + "'s Reward Displays";

                    foreach (Reward r in m_Vendor.Rewards)
                    {
                        c.DropItem(new Exhibit(m_Vendor, r));
                    }

                    m.AddToBackpack(c);

                    break;
                }

            default: //Set Menu - IDs are >= 7
                {
                    try
                    {
                        Type menuType = MenuUploader.Menus[info.ButtonID - 7];

                        if (m_Vendor.GetItem() != null && menuType.Equals(typeof(ClassicVendorGump)))
                            m.SendMessage("Only Mobile Reward Vendors can have classic menus.");
                        else
                        {
                            m_Vendor.Menu = menuType;
                            m.SendMessage("Display changed to " + menuType.Name);
                        }
                    }
                    catch { }

                    MenuUploader.Display(m_Vendor.Menu, m, m_Vendor, false);

                    break;
                                      
                }
         }   
    }
    public void CreateGumps()
    {
        int yPos = 433, pageNum = 1;

        for (int i = 0; i < MenuUploader.Menus.Count; ++i )
        {

            AddLabel(50, yPos, 100, MenuUploader.Menus[i].Name);
            AddButton(12, yPos, 4005, 4006, (i + 7), GumpButtonType.Reply, pageNum);
            

            yPos += 26;

            //add new page every four entries
            if ((i + 1) % 4 == 0)
            {
                AddButton(144, 542, 9702, 9703, -1, GumpButtonType.Page, (pageNum + 1));

                AddPage(++pageNum);

                AddButton(10, 542, 9706, 9707, -1, GumpButtonType.Page, (pageNum - 1));

                //reset to top of page
                yPos = 433;
            }
        } 
    }
}
public static class MenuUploader 
{
    private static List<Type> m_Menus = new List<Type>(); 
    
    public static List<Type> Menus { get { return m_Menus; } }

    public static void RegisterMenu<G>(G menu) where G : Gump, IRewardVendorGump
    {
        m_Menus.Add(menu.GetType());
    }
    
    public static void Display(IRewardVendorGump menu, Mobile m, IRewardVendor vendor)
    {
        m.CloseGump(typeof(IRewardVendorGump));

        //create 'canvas'
        menu.CreateBackground();

        //create Reward displays
        foreach (Reward r in vendor.Rewards)
        {
            //refresh restock  
            if (r.Try_Restock() == 0 && !(menu is ManageItemsGump))
                continue;
            
            menu.AddEntry(r);
        }

        //send finished product
        menu.Send(m);
    }
    public static void Display(Type menu, Mobile m, IRewardVendor vendor, bool playerView)  //Note: Playerview is only relevant for Staff
    {
        try
        {
            if (m.AccessLevel > AccessLevel.GameMaster) 
            {
                if (playerView)
                    Display(new ManageItemsGump(vendor, m), m, vendor);
                else //control panel
                {
                    m.CloseGump(typeof(WorldVendorsGump));
                    m.CloseGump(typeof(ControlPanelGump));

                    m.SendGump(new WorldVendorsGump(vendor)); 
                    m.SendGump(new ControlPanelGump(m, vendor));
                }
            }
            else //player
            {
                Display((IRewardVendorGump)Activator.CreateInstance(menu, new object[] { vendor, m }), m, vendor); //create fresh instance
            }
        }
        catch
        {
            if ( m.AccessLevel > AccessLevel.GameMaster )
                m.SendMessage("The current display is invalid, try setting gump back to default, JewlRewardGump.");
            else
                m.SendMessage("The current display is invalid, please notify the staff.");
        }
    }
}
public class ManageItemsGump : JewlRewardGump
{
    private int m_ButtonNum;

    public ManageItemsGump(IRewardVendor vendor, Mobile m) : base(vendor, m)
    {
        m_ButtonNum = 0;
    }
    public override void AddEntryControl(Reward r)
    {
        ImageTileButtonInfo b = new ItemTileButtonInfo(r.RewardInfo);

        //begin time entries
        if (r.Restock != null)
        {
            if (r.Restock.RestockRate.TotalMinutes == 0)
                AddLabel(324, (PosY + 22), 5, "Limited");
            else
                AddLabel(324, (PosY + 22), 5, ((int)r.Restock.RestockRate.Hours).ToString() + " hours " + ((int)r.Restock.RestockRate.Minutes).ToString() + " min");

            if (r.Restock.Maximum > 0)
                AddLabel(324, (PosY + 68), 4, "In Stock: " + r.Restock.Count.ToString() + " / " + r.Restock.Maximum.ToString() + ", Purchased: " + r.BuyCount.ToString());
            else
                AddLabel(324, (PosY + 68), 4, "In Stock: " + r.Restock.Count.ToString() + ", Purchased: " + r.BuyCount.ToString());
        }
        else
        {
            AddLabel(324, (PosY + 68), 4, "Purchased: " + r.BuyCount.ToString());
        }
        //end 

        //create entry
        AddLabel(227, PosY, 2123, r.Title);
        AddLabel(324, (PosY + 45), 2115, "Cost: " + r.Cost);
        //odd numbers
        AddImageTiledButton(227, (PosY + 26), 2328, 2329, ++m_ButtonNum, GumpButtonType.Reply, PageNum, b.ItemID, b.Hue, 15, 10, r.Display.Header);
        AddImageTiled(215, (PosY + 95), 359, 2, 96);
        //odd numbers (same as above)
        AddButton(470, (PosY + 45), 4011, 4012, m_ButtonNum, GumpButtonType.Reply, PageNum);
        AddLabel(508, (PosY + 47), 1882, @"Options");
        //even numbers
        AddButton(470, (PosY + 19), 4020, 4021, ++m_ButtonNum, GumpButtonType.Reply, PageNum);
        AddLabel(509, (PosY + 21), 1882, @"Delete");
        PosY += 102;

        //add new page every four entries
        if (EntryNum % 4 == 0)
        {
            AddButton(546, 562, 9903, 9904, -1, GumpButtonType.Page, PageNum + 1);

            AddPage(++PageNum);

            AddButton(221, 563, 9909, 9910, -1, GumpButtonType.Page, PageNum - 1);

            //reset to top of page
            PosY = 130;
        }

        EntryNum++;
    }
    public static void DeleteReward_Callback(Mobile from, bool okay, object state)
    {
        if (from.AccessLevel < AccessLevel.GameMaster)
            return;

        if (okay)
        {
            //indexes -> (Vendor(0), Reward(1))
            Storage store = (Storage)state;

            IRewardVendor vendor = (IRewardVendor)store[0];
            Reward Reward = (Reward)store[1];

            try { vendor.RemoveReward(Reward); }
            catch { from.SendMessage("An error ocurred in the removal of this item."); }
            
            MenuUploader.Display(vendor.Menu, from, vendor, true);
        }
    }
    public override void OnResponse(NetState sender, RelayInfo info)
    {
        Mobile m = sender.Mobile;

        if (info.ButtonID == 0)
        {
            MenuUploader.Display(Vendor.Menu, m, Vendor, false);
            return;
        }
            
        if (info.ButtonID % 2 == 0) //even
        {
                try
                {
                    Reward r = Vendor.Rewards[(info.ButtonID / 2) - 1];

                    //params -> (vendor, Reward)
                    Storage store = new Storage(Vendor, r);

                    m.SendGump(new WarningGump(1060635, 30720, "Warning: Are you sure you want to remove " + r.Title, 0xFFC000, 420, 400, new WarningGumpCallback(DeleteReward_Callback), store));

                }
                catch { m.SendMessage("This item could not be found."); }
            
        }
        else //assert - odd
        {
            try
            {
                MenuUploader.Display(Vendor.Menu, m, Vendor, true);
                m.SendGump(new ViewItemGump(m, Vendor, Vendor.Rewards[((info.ButtonID + 1) / 2) - 1], true));
            }
            catch { m.SendMessage("Vendor could not be found"); }
        }
        
    }
    
}
public class XMLIntPropertyGump : Gump
{
    private Type m_XML_Type;
    private object m_Target;

    private IRewardVendor m_Vendor;
    private List<PropertyInfo> m_Props;

    private int m_PageNum;
    private  int m_PosY;
    private int m_EntryNum;

    public XMLIntPropertyGump(Type xmlType, object target, IRewardVendor vendor, List<PropertyInfo> props)
        : base(0, 0)
    {
        m_XML_Type = xmlType;
        m_Target = target;
        m_Vendor = vendor;
        m_Props = props;

        m_PageNum = 1;
        m_PosY = 134;
        m_EntryNum = 1;
      
        this.Closable = true;
        this.Disposable = true;
        this.Dragable = true;
        this.Resizable = false;

        AddPage(0);

        AddImageTiled(284, 90, 168, 384, 2702);
        AddLabel(315, 99, 49, xmlType.Name);
        AddImageTiled(292, 123, 151, 3, 9151);

        AddPage(1);

        FillEntries();
    }
    public void FillEntries()
    {
        foreach (PropertyInfo pi in m_Props)
        {
            AddButton(295, m_PosY, 5601, 5605, m_EntryNum, GumpButtonType.Reply, 0);
            AddLabel(319, m_PosY, 43, pi.Name);

            m_PosY += 26;

            if (m_EntryNum % 10 == 0)
            {
                AddButton(423, 444, 9903, 9904, -1, GumpButtonType.Page, m_PageNum + 1);

                AddPage(++m_PageNum);

                AddButton(292, 444, 9909, 9910, -1, GumpButtonType.Page, m_PageNum - 1);

                //reset to top of page
                m_PosY = 134;
            }
            m_EntryNum++;
        }

       
    }
    public override void OnResponse(NetState sender, RelayInfo info)
    {
        Mobile m = sender.Mobile;

        if (info.ButtonID == 0)
            return;

        m_Vendor.Payment = new Currency(m_Target, m_XML_Type, m_Props[info.ButtonID - 1]);
        m.SendMessage("{0}'s payment method set to {1}.{2}", m_Vendor.GetName(), m_XML_Type.Name, m_Props[info.ButtonID-1].Name);
    }

}
public class JewlRewardGump : Gump, IRewardVendorGump
{
    private int m_PageNum;
    private int m_EntryNum;
    private int m_PosY;
    private IRewardVendor m_Vendor;
    private Mobile m_Mobile;
    private int m_CurrencyAmnt;
   
    public static void Initialize()
    {
        MenuUploader.RegisterMenu(new JewlRewardGump());
    }

    public JewlRewardGump()
        : base(0, 0)
    {
        m_PageNum = 1;
        m_EntryNum = 1;
        m_PosY = 130;
        m_Vendor = null;
        m_Mobile = null;
        m_CurrencyAmnt = 0;
    }
    public JewlRewardGump(IRewardVendor vendor, Mobile m) : this()
    {
        m_Vendor = vendor;
        m_Mobile = m;
        m_CurrencyAmnt = vendor.Payment.Value(m);
    }

    //Properties
    public int PageNum { get { return m_PageNum; } set { m_PageNum = value; } }
    public int EntryNum { get { return m_EntryNum; } set { m_EntryNum = value; } }
    public int PosY { get { return m_PosY; } set { m_PosY = value; } }
    public IRewardVendor Vendor { get { return m_Vendor; } set { m_Vendor = value; } }
    public Mobile Mobile { get { return m_Mobile; } set { m_Mobile = value; } }
    public int CurrencyAmnt { get { return m_CurrencyAmnt; } set { m_CurrencyAmnt = value; } }

    //Interface Explicit Implementation 
    void IRewardVendorGump.Send(Mobile m) { SendControl(m); }
    void IRewardVendorGump.CreateBackground() { CreateBackgroundControl(); } 
    void IRewardVendorGump.AddEntry(Reward r) { AddEntryControl(r); }

    public virtual void SendControl(Mobile m)
    {
        m.SendGump(this);
    }
    public virtual void CreateBackgroundControl()
    {
        this.Closable = true;
        this.Disposable = true;
        this.Dragable = true;
        this.Resizable = false;

        AddPage(0);

        AddImageTiled(179, 34, 430, 556, 2702);
        AddImageTiled(222, 109, 387, 9, 10101);
        AddImage(162, 89, 10420);
        AddImageTiled(176, 33, 3, 556, 10004);
        AddImageTiled(129, 89, 82, 414, 10440);
        AddImageTiled(176, 589, 436, 3, 10001);
        AddImageTiled(176, 31, 435, 3, 10001);
        AddImageTiled(609, 33, 3, 556, 10004);
        AddLabel(348, 52, 2124, m_Vendor.GetName());
        AddImage(210, 52, 9818);
        AddImage(534, 52, 9818);
        AddLabel(404, 119, 2125, @"You have:");
        AddItem(348, 126, m_Vendor.Payment.PayID, m_Vendor.Payment.CurrHue);
        AddLabel(404, 137, 2125, (m_CurrencyAmnt.ToString() + " " + m_Vendor.Payment.PayName) );
        

        AddPage(1);
    }
      
    public virtual void AddEntryControl(Reward r)
    {
        ImageTileButtonInfo b = new ItemTileButtonInfo(r.RewardInfo);

        //create entry

        //begin time entries
        if (r.Restock != null)
        {
            if (r.Restock.RestockRate.TotalMinutes == 0)
                AddLabel(324, (PosY + 22), 5, "Limited");

            if (r.Restock.Maximum > 0)
                AddLabel(324, (PosY + 68), 4, "In Stock: " + r.Restock.Count.ToString());
            else
                AddLabel(324, (PosY + 68), 4, "In Stock: " + r.Restock.Count.ToString());
        }
        //end 

        AddLabel(227, m_PosY, 2123, r.Title);
        AddLabel(324, (m_PosY + 45), 2115, "Cost: " + r.Cost);
        AddImageTiledButton(227, (m_PosY + 26), 2328, 2329, (m_EntryNum), GumpButtonType.Reply, m_PageNum, b.ItemID, b.Hue, 15, 10, b.LocalizedTooltip);
        AddImageTiled(215, (m_PosY + 95), 359, 2, 96);
        AddButton(470, (PosY + 45), 4011, 4012, (m_EntryNum), GumpButtonType.Reply, m_PageNum);
        AddLabel(508, (PosY + 47), 745, @"View Item");
        m_PosY += 102;
        
        //add new page every four entries
        if (m_EntryNum % 4 == 0)
        {
            AddButton(546, 562, 9903, 9904, -1, GumpButtonType.Page, m_PageNum + 1);

            AddPage(++m_PageNum);

            AddButton(221, 563, 9909, 9910, -1, GumpButtonType.Page, m_PageNum - 1);

            //reset to top of page
            m_PosY = 130;
        }

        m_EntryNum++;
    }
    public override void OnResponse(NetState sender, RelayInfo info)
    {
        Mobile m = sender.Mobile;

        if (info.ButtonID == 0)
            return;

        MenuUploader.Display(m_Vendor.Menu, m, m_Vendor, true);

        try
        {
            m.SendGump(new ViewItemGump(m, m_Vendor, m_Vendor.Rewards[info.ButtonID - 1], true));
        }
        catch { m.SendMessage("Vendor could not be found"); }
    }
}

public class DisplayBox : LargeCrate, IEnumerable
{
    private Dictionary<Reward, MetalBox> m_Boxes;

    public override bool IsPublicContainer { get { return true; } }

    public MetalBox this[Reward r]
    {
        get
        {
            MetalBox box = null; //not found

            m_Boxes.TryGetValue(r, out box);

            return box;
        }
    }

    [Constructable]
    public DisplayBox()
        : base()
    {
        this.Name = "Display Box [DO NOT REMOVE]";
        this.LiftOverride = true;
        m_Boxes = new Dictionary<Reward, MetalBox>();
    }
    public DisplayBox(RewardCollection rc)
        : this()
    {
        CreateEntries(rc);
    }
    public bool Contains(Reward r)
    {
        return m_Boxes.ContainsKey(r);
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return m_Boxes.GetEnumerator();
    }
    public override bool CheckLift(Mobile from, Item item, ref LRReason reject)
    {
        reject = 0;
        return false;
    }
    public void DisplayTo(Mobile m, Reward r)
    {
        string invalid = "This item can no longer be displayed.";
        bool staff = m.AccessLevel >= AccessLevel.GameMaster;

        try
        {
            Container[] containers = new Container[] { (Container)this.Parent, this }; //cast exception if parent isn't container

            foreach (Container c in containers)
            {
                if (m.NetState != null && m.NetState.IsPost6017)
                    m.Send(new ContainerContent6017(m, c));
                else
                    m.Send(new ContainerContent(m, c));
            }

            m_Boxes[r].DisplayTo(m); //throws null ref if not found

            m.SendMessage("A container has been opened for you to view the item.");
        }
        catch (NullReferenceException)
        {
            if (staff)
                m.SendMessage("Display error - please insure Reward is still on this vendor.");
            else
                m.SendMessage(invalid);
        }
        catch (InvalidCastException)
        {
            if (staff)
                m.SendMessage("Display error - the current vendor does not have a DisplayBox in backpack.");
            else
                m.SendMessage(invalid);
        }
        catch (Exception)
        {
            if (staff)
                m.SendMessage("Unknown error occured with display.");
            else
                m.SendMessage(invalid);
        }
            
    }
    //Warning: must catch exception in methods
    public void CreateEntries(RewardCollection rc)
    {
        foreach (Reward r in rc)
        {
            this.AddDisplay(r, r.RewardInfo);
        }
    }
    public void AddDisplay(Reward key, Item i)
    {
        if (m_Boxes.ContainsKey(key))
            throw new Exception("Key already in use.");

        MetalBox container = new MetalBox();
        
        container.DropItem(i);

        this.DropItem(container);

        m_Boxes.Add(key, container);    
    }
    public void AddDisplay(Reward r)
    {
        AddDisplay(r, r.RewardInfo);
    }
    public void RemoveDisplay(Reward r)
    {
        ((Item)m_Boxes[r]).Delete(); //remove from displaybox
        m_Boxes.Remove(r);   //remove from hashtable      
    }
    //End Warning

    public override bool OnDragDrop( Mobile from, Item dropped )
    {
        return false;//do nothing
    }

    public DisplayBox( Serial serial ) : base( serial )
	{
	}
    
	public override void Serialize( GenericWriter writer )
    {
		base.Serialize( writer );

		writer.Write( (int) 0 ); // version
        
        int count = 0;
        try
        {
            count = m_Boxes.Count;
        }
        catch
        {
            m_Boxes = new Dictionary<Reward, MetalBox>();
            m_Boxes.Add(new Reward(), new MetalBox());
            count = m_Boxes.Count;
        }
        writer.Write((int)count);

        foreach (KeyValuePair<Reward, MetalBox> kvp in m_Boxes)
        {
            writer.Write((Reward)kvp.Key);
            writer.WriteItem((MetalBox)kvp.Value);
        }
        
    }

	public override void Deserialize( GenericReader reader )
    {
		base.Deserialize( reader );
                
		int version = reader.ReadInt();

        
        int count = reader.ReadInt();
        
        m_Boxes = new Dictionary<Reward, MetalBox>();     
        if (count > 0)
        {
            for (int i = 0; i < count; i++)
            {
                Reward r = (Reward)reader.ReadItem();
                MetalBox box = (MetalBox)reader.ReadItem();

                m_Boxes.Add(r, box);
            }
        }      
    }
}

public class LoadGumpEntry : ContextMenuEntry
{
    private IRewardVendor m_Vendor;
    private Mobile m_Mobile;

    public LoadGumpEntry(Mobile from, IRewardVendor vendor)
        : base(6103, 8)
    {
        m_Vendor = vendor;
        m_Mobile = from;
        Enabled = true;
    }

    public override void OnClick()
    {
        try
        {
            MenuUploader.Display((IRewardVendorGump)Activator.CreateInstance(m_Vendor.Menu, new object[] { m_Vendor, m_Mobile }), m_Mobile, m_Vendor); //create fresh instance
        }
        catch { m_Mobile.SendMessage("The current display is invalid.");  }
    }
}
public class ClassicVendorGump : Gump, IRewardVendorGump
{
    private IRewardVendor m_Vendor;
    private BaseVendor m_BVendor;

    private Mobile m_Mobile;   

    private List<ObjectPropertyList> m_Opls;
    List<BuyItemState> m_List;

    public List<ObjectPropertyList> ObjPropLists { get { return m_Opls;} }
    
    public static void Initialize()
    {
      MenuUploader.RegisterMenu(new ClassicVendorGump());
    }

    public ClassicVendorGump()
        : base(0, 0)
    {
        m_Vendor = null;
        m_Mobile = null;
        m_BVendor = null;
        m_Opls = null;
        m_List = null;
    }
    public ClassicVendorGump(IRewardVendor vendor, Mobile m) : this()
    {
        m_Vendor = vendor;
        m_Mobile = m;
        m_BVendor = Parent(vendor);
        m_Opls = new List<ObjectPropertyList>();
        m_List = new List<BuyItemState>();
    }
    private BaseVendor Parent(IRewardVendor vendor)
    {
        BaseVendor validVendor = null;

        if (vendor != null) //only available on mobiles inherited from BaseVendor
            validVendor = vendor as BaseVendor;

        return validVendor;
    }
    void IRewardVendorGump.Send(Mobile m)
    {
        if ( !m_Vendor.Payment.PaymentType.Equals(typeof(Gold)) ) //need custom payment display
            m.SendGump(this);    

        if (m_BVendor != null)
        {

            if (m_List.Count > 0)
            {
                m_List.Sort(new BuyItemStateComparer());

                m_BVendor.SendPacksTo(m);

                if (m.NetState == null)
                    return;

                if (m.NetState.IsPost6017)
                    m.Send(new VendorBuyContent6017(m_List));
                else
                    m.Send(new VendorBuyContent(m_List));
                m.Send(new VendorBuyList(m_BVendor, m_List));
                m.Send(new DisplayBuyList(m_BVendor));

                m.Send(new MobileStatusExtended(m));//make sure their gold amount is sent

                if (m_Opls != null)
                {
                    for (int i = 0; i < m_Opls.Count; ++i)
                    {
                        m.Send(m_Opls[i]);
                    }
                }

                m_BVendor.SayTo(m, 500186); // Greetings.  Have a look around.
            }
        }               
    }   
    void IRewardVendorGump.AddEntry(Reward r)
    {
        m_List.Add(new BuyItemState(r.Title, m_BVendor.BuyPack.Serial, r.Serial, r.Cost, (r.Restock == null ? 20 : r.Restock.Count), r.RewardInfo.ItemID, r.RewardInfo.Hue));

        m_Opls.Add(r.Display);      
    }
    void IRewardVendorGump.CreateBackground()
    {
        this.Closable = true;
        this.Disposable = true;
        this.Dragable = true;
        this.Resizable = false;

        AddPage(0);
        AddImage(36, 105, 2162);
        AddItem(111, 217, m_Vendor.Payment.PayID, m_Vendor.Payment.CurrHue);
        AddLabel(110, 172, 2122, @"Pay By:  " + m_Vendor.Payment.PayName);
        AddLabel(110, 299, 2120, @"You have: " + m_Vendor.Payment.Value(m_Mobile));
        AddImage(71, 302, 57);
        AddImage(71, 174, 57);
    }
}
public class MobileRewardVendor : Banker, IRewardVendor 
{
    private Currency m_Currency;
    private RewardCollection m_Rewards;
    private Type m_Menu;
    private DisplayBox m_Box;

    private bool m_IsBanker;

    [CommandProperty(AccessLevel.GameMaster)]
    public bool IsBanker
    {
        get { return m_IsBanker; }
        set { m_IsBanker = value; }     
    }
    Currency IRewardVendor.Payment
    {
        get { return m_Currency; }
        set { m_Currency = value; }
    }
    RewardCollection IRewardVendor.Rewards
    {
        get { return m_Rewards; }
        set { m_Rewards = value; }
    }
    Type IRewardVendor.Menu
    {
        get { return m_Menu; }
        set { m_Menu = value;  }
    }
    DisplayBox IRewardVendor.Display
    {
        get { return m_Box; }
    }
    [Constructable]
    public MobileRewardVendor() : base()
    {
        m_IsBanker = true;

        //default is Gold
        m_Currency = new Currency();
        m_Rewards = new RewardCollection();
        m_Menu = typeof(ClassicVendorGump);
        m_Box = new DisplayBox();

        //add to world collection
        WorldRewardVendors.RegisterVendor(this);
        //must be brought to world for client to view
        this.AddToBackpack(m_Box);

        this.Title = "";
    }
    public override void AddCustomContextEntries(Mobile from, List<ContextMenuEntry> list)
    {
        if (from.Alive)
        {
            list.Add(new LoadGumpEntry(from, this));

            if ( m_IsBanker)
                list.Add(new OpenBankEntry(from, this));
        }
    }
    Mobile IRewardVendor.GetMobile()
    {
        return this;
    }
    Item IRewardVendor.GetItem()
    {
        return null;
    }
   
    bool IRewardVendor.IsRemoved()
    {
        return this.Deleted;
    }
    Container IRewardVendor.GetContainer()
    {
        return this.Backpack;
    }
    string IRewardVendor.GetName()
    {
        return this.Name;
    }
    Map IRewardVendor.GetMap()
    {
        return this.Map;
    }
    Point3D IRewardVendor.GetLocation()
    {
        return this.Location;
    }
    //begin bank override
    public override bool HandlesOnSpeech(Mobile from)
    {
        if (!m_IsBanker)
            return false;

        base.HandlesOnSpeech(from);

        return true;
    }
    public override void OnSpeech(SpeechEventArgs e)
    {
        if (m_IsBanker)
            base.OnSpeech(e);
    }    
    //end

    //Warning: Following methods will throw Exceptions
    void IRewardVendor.AddReward(Reward r)
    {
        m_Box.AddDisplay(r);
        m_Rewards.Add(r);
    }
    void IRewardVendor.RemoveReward(Reward r)
    {
        m_Rewards.Remove(r);
        m_Box.RemoveDisplay(r);
    }
    
    void IRewardVendor.CopyVendor(IRewardVendor vendor)
    {
        Item currBox = this.Backpack.FindItemByType(typeof(DisplayBox));
        currBox.Delete();

        m_Currency = vendor.Payment;
        m_Menu = vendor.Menu;

        m_Rewards = (RewardCollection)((vendor.Rewards as ICloneable).Clone());
        m_Box = new DisplayBox(m_Rewards);

        this.AddToBackpack(m_Box);
    }
    //End Warning
    public override void OnDelete()
    {
        WorldRewardVendors.RemoveVendor(this);
        base.OnDelete();
    }
    //response to ClassicVendorGump - (must be inside BaseVendor)
    public override bool OnBuyItems(Mobile buyer, List<BuyItemResponse> list)
    {
        int totalCost = 0;
      
        Dictionary<Reward, int> purchases = new Dictionary<Reward, int>();

        Container bank = buyer.BankBox;
        Container pack = buyer.Backpack;

        if (pack == null || bank == null)
            return false;

        foreach (BuyItemResponse buy in list)
        {
            Serial ser = buy.Serial;
            int amount = buy.Amount;

            if (ser.IsItem)
            {
                Item item = World.FindItem(ser);

                if (item == null)
                    continue;

                Reward r = item as Reward;

                if (r == null || !r.InStock(amount))
                    continue;

                totalCost += (r.Cost * amount);

                purchases.Add(r, amount);
            }
        }

        if (purchases.Count == 0)
        {
            SayTo(buyer, 500190); // Thou hast bought nothing! 
            return false;
        }                    
            if (!m_Currency.Purchase(buyer, totalCost)) //cannot afford
            {
                SayTo(buyer, 500192);//Begging thy pardon, but thou casnt afford that.
                return false;
            }

            foreach (KeyValuePair<Reward, int> kvp in purchases)
            {
                kvp.Key.RegisterBuy(kvp.Value);

                for (int index = 0; index < kvp.Value; index++)
                {                    
                    Item i = kvp.Key.RewardCopy;

                    if (!buyer.PlaceInBackpack(i))
                    {
                        bank.DropItem(i);
                        buyer.SendMessage("You are overweight, the Reward was added to your bank");
                    }
                }

                buyer.SendMessage("You bought {0} {1}", kvp.Value, kvp.Key.Title);
            }

            buyer.PlaySound(0x32);

            return true;  
             
    }
    //respone to 'vendor buy'
    public override void VendorBuy(Mobile from)
    {       
        MenuUploader.Display((IRewardVendorGump)Activator.CreateInstance(m_Menu, new object[] { (IRewardVendor)this, from }), from, (IRewardVendor)this ); //create fresh instance
    }
    //end edit
    public override void OnDoubleClick(Mobile m)
    {
        if (InRange(m, 4) && InLOS(m))
            MenuUploader.Display(m_Menu, m, this, false);
    }
    public MobileRewardVendor( Serial serial ) : base( serial )
	{
	}
    
	public override void Serialize( GenericWriter writer )
    {
		base.Serialize( writer );   

		writer.Write( (int) 1 ); // version

        writer.Write((bool)m_IsBanker);

        int count = m_Rewards.Count;
        writer.Write((int)count);

        if ( count > 0 )
        {
            for (int i = 0; i < count; i++)
            {
                writer.WriteItem((Reward)m_Rewards[i]);
            }
        }
        
        writer.WriteItem((Currency)m_Currency);
        writer.Write((string)m_Menu.Name);
        writer.WriteItem((DisplayBox)m_Box);       
    }
    
	public override void Deserialize( GenericReader reader )
    {
		base.Deserialize( reader );

        WorldRewardVendors.RegisterVendor(this);

		int version = reader.ReadInt();
        
        m_Rewards = new RewardCollection();

        m_IsBanker = true; //for conversion
               
        switch (version)
        {
            case 1:
                {
                    m_IsBanker = reader.ReadBool();

                    goto case 0;
                }
            case 0:
               {                   
                    int count = reader.ReadInt();
                    if (count > 0)
                    {
                        for (int i = 0; i < count; i++)
                        {
                            Reward r = (Reward)reader.ReadItem();
                            m_Rewards.Add(r);
                        }
                    }

                    m_Currency = (Currency)reader.ReadItem();

                    try { string name = reader.ReadString(); m_Menu = ScriptCompiler.FindTypeByName(name); }
                    catch { m_Menu = typeof(JewlRewardGump); }

                    m_Box = (DisplayBox)reader.ReadItem();

                    break;
                }
        }
	}
}
public class StoneRewardHolder : MetalBox
{
    private StoneRewardVendor m_S_Vendor;

    public StoneRewardHolder(StoneRewardVendor sv)
        : base()
    {
        m_S_Vendor = sv;
        this.Movable = false;
        this.Name = sv.Name + "'s Display Container [DO NOT DELETE]";
    }
    public override void OnItemLifted(Mobile m, Item item)
    {
        m.SendMessage("This item should not be moved away from the vendor.");
    }

    public void UpdateName()
    {
        if (m_S_Vendor == null)
            return;

        this.Name = m_S_Vendor.Name + "'s Display Container [DO NOT DELETE]";
    }
    public StoneRewardHolder(Serial serial)
        : base(serial)
	{
	}

	public override void Serialize( GenericWriter writer )
	{
		base.Serialize( writer );

		writer.Write( (int) 0 ); // version
	}

	public override void Deserialize( GenericReader reader )
	{
		base.Deserialize( reader );

		int version = reader.ReadInt();
    }
}
public class StoneRewardVendor : Item, IRewardVendor
{
    private Currency m_Currency;
    private RewardCollection m_Rewards;
    private Type m_Menu;
    private StoneRewardHolder m_Box_Holder;
    private DisplayBox m_Box;

    Currency IRewardVendor.Payment
    {
        get { return m_Currency; }
        set { m_Currency = value; }
    }
    RewardCollection IRewardVendor.Rewards
    {
        get { return m_Rewards; }
        set { m_Rewards = value; }
    }
    Type IRewardVendor.Menu
    {
        get { return m_Menu; }
        set { m_Menu = value; }
    }
    DisplayBox IRewardVendor.Display
    {
        get { return m_Box; }
    }

    [Constructable]
    public StoneRewardVendor()
        : base()
    {
        m_Currency = new Currency();
        m_Rewards = new RewardCollection();
        m_Menu = typeof(JewlRewardGump);
        m_Box = new DisplayBox();

        ItemID = 0xEDC;
        Name = "Stone Vendor";

        WorldRewardVendors.RegisterVendor(this);

        m_Box_Holder = new StoneRewardHolder(this);
        m_Box_Holder.DropItem(m_Box);      

        this.Movable = false;
    }
    public override void OnLocationChange( Point3D oldLocation )
    {
        base.OnLocationChange(oldLocation);

        if (m_Box_Holder != null)
        {
            m_Box_Holder.Location = this.Location;
            m_Box_Holder.Z = this.Z - 10;
        }
    }
    public override void OnMapChange()
    {
        base.OnMapChange();

        if ( m_Box_Holder != null )
            m_Box_Holder.Map = this.Map;
    }
    Mobile IRewardVendor.GetMobile()
    {
        return null;
    }
    Item IRewardVendor.GetItem()
    {
        return this;
    }

    bool IRewardVendor.IsRemoved()
    {
        return this.Deleted;
    }
    Container IRewardVendor.GetContainer()
    {
        return m_Box_Holder;
    }
    string IRewardVendor.GetName()
    {
        return this.Name;
    }
    Map IRewardVendor.GetMap()
    {
        return this.Map;
    }
    Point3D IRewardVendor.GetLocation()
    {
        return this.Location;
    }
    void IRewardVendor.AddReward(Reward r)
    {
        m_Box.AddDisplay(r);
        m_Rewards.Add(r);
    }
    void IRewardVendor.RemoveReward(Reward r)
    {
        m_Rewards.Remove(r);
        m_Box.RemoveDisplay(r);
    }

    void IRewardVendor.CopyVendor(IRewardVendor vendor)
    {
        Item currBox = m_Box_Holder.FindItemByType(typeof(DisplayBox));
        currBox.Delete();

        m_Currency = vendor.Payment;
        m_Menu = vendor.Menu;

        m_Rewards = (RewardCollection)((vendor.Rewards as ICloneable).Clone());
        m_Box = new DisplayBox(m_Rewards);

        m_Box_Holder.DropItem(m_Box);
    }
    //End Warning
    public override void OnDelete()
    {
        if ( m_Box_Holder != null)
            m_Box_Holder.Delete();

        WorldRewardVendors.RemoveVendor(this);
        base.OnDelete();
    }
    
    public override void OnDoubleClick(Mobile m)
    {
        if (m_Box_Holder != null)
        {
            m_Box_Holder.MoveToWorld(this.Location, this.Map);
            m_Box_Holder.Z = this.Z - 10;
            m_Box_Holder.UpdateName();
        }
        MenuUploader.Display(m_Menu, m, this, false);
    }
     
    public StoneRewardVendor(Serial serial)
        : base(serial)
    {
    }

    public override void Serialize(GenericWriter writer)
    {
        base.Serialize(writer);

        writer.Write((int)0); //Version 0

        int count = m_Rewards.Count;
        writer.Write((int)count);

        if (count > 0)
        {
            for (int i = 0; i < count; i++)
            {
                writer.WriteItem((Reward)m_Rewards[i]);
            }
        }

        writer.WriteItem((Currency)m_Currency);
        writer.Write((string)m_Menu.Name);
        writer.WriteItem((DisplayBox)m_Box);
        writer.WriteItem((StoneRewardHolder)m_Box_Holder);
    }

    public override void Deserialize(GenericReader reader)
    {
        base.Deserialize(reader);

        WorldRewardVendors.RegisterVendor(this);

        int version = reader.ReadInt();

        m_Rewards = new RewardCollection();

        int count = reader.ReadInt();
        if (count > 0)
        {
            for (int i = 0; i < count; i++)
            {
                Reward r = (Reward)reader.ReadItem();
                m_Rewards.Add(r);
            }
        }

        m_Currency = (Currency)reader.ReadItem();

        try { string name = reader.ReadString(); m_Menu = ScriptCompiler.FindTypeByName(name); }
        catch { m_Menu = typeof(JewlRewardGump); }

        m_Box = (DisplayBox)reader.ReadItem();
        m_Box_Holder = (StoneRewardHolder)reader.ReadItem();
    }
}
public interface IRewardVendor
{
    //used to determine how player pays
    Currency Payment { get; set; }
    //to keep added items
    RewardCollection Rewards { get; set; }
    //to change gump
    Type Menu { get; set; }
    //to show player items
    DisplayBox Display { get; }
    //to return what holds 'DisplayBox' object
    Container GetContainer();
    //to return removal status
    bool IsRemoved();
   
    //serial /deserial
    Mobile GetMobile();
    Item GetItem();

    //used for 'world collection'
    string GetName();
    Point3D GetLocation();
    Map GetMap();

    //to manage RewardCollection
    void AddReward(Reward r);
    void RemoveReward(Reward r);
    
    //to create vendor clones
    void CopyVendor(IRewardVendor vendor);
}
public interface IRewardVendorGump
{
    void Send(Mobile m);
    void AddEntry(Reward r);
    void CreateBackground();
    
    //add entry || background || 
}


public class PaymentTarget : Target
{
    private string m_Name;
    private IRewardVendor m_Vendor;
    private bool m_Is_XML;

    public PaymentTarget()
        : base(2, false, TargetFlags.None)
    {
    }
    //by item
    public PaymentTarget(IRewardVendor vendor) : this ()
	{
        m_Vendor = vendor;
        m_Name = null;
        m_Is_XML = false;
    }
    //by item property
    public PaymentTarget(IRewardVendor vendor, string name, bool isXML) : this()
    {
        m_Vendor = vendor;
        m_Name = name;
        m_Is_XML = isXML;
    }
    protected override void OnTarget(Mobile m, object targeted)
    {
        if (m_Is_XML && !String.IsNullOrEmpty(m_Name))
        {
            Type attachType = ScriptCompiler.FindTypeByName(m_Name);

            if (attachType != null && attachType.BaseType.Equals(typeof(XmlAttachment)))
            {
                List<PropertyInfo> integerProps = new List<PropertyInfo>();

                foreach (PropertyInfo pi in attachType.GetProperties())
                {
                    if ((pi.CanRead && pi.CanWrite) && pi.PropertyType.Equals(typeof(System.Int32)))
                        integerProps.Add(pi);
                }

                if (integerProps.Count == 0)
                    m.SendMessage("{0} does not contain any integer based properties.", attachType.Name);
                else
                    m.SendGump(new XMLIntPropertyGump(attachType, targeted, m_Vendor, integerProps));
            }
            else
                m.SendMessage("The XML Attachment, {0}, could not be found, the search IS case sensitive", m_Name);
        }
        else if ( targeted is Item )
        {           
            //consume by item
            if (m_Name == null)
            {
                m_Vendor.Payment = new Currency((Item)targeted);
                m.SendMessage("{0} will now use {1} for payment.", m_Vendor.GetName(), targeted.GetType().Name);
            }
            //consume by item property
            else
            {
                SetByProperty(m, targeted);
            }
        }
        else if (targeted is PlayerMobile)
        {
            if (m_Name == null)
            {
                m.SendMessage("You can only use Property option for player.");

            }
            else
            {
                SetByProperty(m, null);
            }
        }
        else
        {
            m.SendMessage("Invalid, target must be Item or Player.");
        }

        MenuUploader.Display(m_Vendor.Menu, m, m_Vendor, false);
    }
    private void SetByProperty(Mobile m, object o)
    {
        string msg = "Please make sure you entered the name correctly, "
                        + "it IS case sensitive.";
        try
        {
            if (o != null)//Item
            {
                PropertyInfo pi = o.GetType().GetProperty(m_Name);

                if (pi != null && pi.PropertyType.Equals(typeof(Int32)))
                {
                    m_Vendor.Payment = new Currency((Item)o, pi);
                    m.SendMessage(m_Vendor.GetName() + "will now use {1}.{2} for payment.", m_Vendor.GetName(), o.GetType().Name, pi.Name);
                }
                else
                    m.SendMessage(msg);
            }
            else//Mobile
            {
                PropertyInfo pi = m.GetType().GetProperty(m_Name);

                if (pi != null && pi.PropertyType.Equals(typeof(Int32)))
                {
                    m_Vendor.Payment = new Currency(m, pi);
                    m.SendMessage("{0} will now use {1}.{2} for payment.", m_Vendor.GetName(), m.GetType().Name, pi.Name);
                }
                else
                    m.SendMessage(msg);
            }
        }
        catch { m.SendMessage(msg); }
    }
}
public class AddItemTarget : Target
{
    IRewardVendor m_Vendor;

    public AddItemTarget() : base( 2, false, TargetFlags.None )
	{
	}
    public AddItemTarget(IRewardVendor vendor)
        : this()
    {
        m_Vendor = vendor;
    }
    protected override void OnTarget(Mobile from, object targeted)
    {
        Item i = targeted as Item;

        if (m_Vendor == null || i == null)
            return;

        Item clone = ItemClone.Clone(i);

        if (clone != null) //copy did not fail
            from.SendGump(new EditItemGump(m_Vendor, new Reward(clone), null, false, true));
        else
            from.SendMessage("This item cannot be copied.");

    }
}

public class ItemClone
{
    public static Item Clone(Item item) 
    {
        try
        {
            if ( item is Container )
                return CloneBag(((Container)item).FindItemsByType(typeof(Item), false), (Container)item, (Container)Activator.CreateInstance(item.GetType(), null));
            else
                return Clone(item.GetType(), item, (Item)Activator.CreateInstance(item.GetType(), null));
        }
        catch {}
       
        return null;
    }
    public static Container CloneBag(Item[] contents, Container old, Container copy)
    {        
        //emtpy new container
        foreach (Item i in copy.FindItemsByType(typeof(Item)))
        {
            i.Delete();
        }

        //'old' contents into 'new'
        foreach (Item i in contents)
        {
            copy.DropItem(Clone(i));           
        }

        copy.Name = old.Name; //requires manual set

        return copy;
    }
    public static Item Clone(Type type, Item old, Item copy)
    {
        foreach (PropertyInfo pi in type.GetProperties())
        {
            if (pi.CanRead && pi.CanWrite && ValidProperty(pi.Name)) 
            {
                try
                {
                    if (pi.PropertyType.IsClass)
                        CloneInnerClass(pi.PropertyType, pi.GetValue(old, null), pi.GetValue(copy, null)); //found object property
                    else
                        pi.SetValue(copy, pi.GetValue(old, null), null); //found value property
                }
                catch {}
            }
        }

        copy.Name = old.Name; //requires manual set

        return copy;
    }
    public static void CloneInnerClass(Type type, object old, object copy)
    {
        if (old == null) //not defined
            return;
        
        foreach ( PropertyInfo pi in type.GetProperties() )
        {
            if ( pi.CanRead && pi.CanWrite ) 
            {
                try
                {
                    pi.SetValue(copy, pi.GetValue(old, null), null);
                }
                catch {}
            }
        }
    }
    public static bool ValidProperty(string str) 
    {
        return !( str.Equals("Parent") || str.Equals("TotalWeight") || str.Equals("TotalItems") || str.Equals("TotalGold") );
    }
   
}
}
 

Jeff

Lord
Vorspire;852577 said:
Screw the ban evader, the rest of us may need your wise words :D

My helpful statement was that he was obviously using older Core code then what the script was written against. But this guy is the RunUO Extended (uokgames....) guy.. and hes so smart that he offers C# tutorials on his server for donations, so no reason to help him.
 

UO_Talon

Sorceror
I'm having an issue

Code:
RunUO - [www.runuo.com] Version 2.1, Build 3935.18827
Core: Running on .NET Framework Version 2.0.50727
Scripts: Compiling C# scripts...failed (1 errors, 0 warnings)
Errors:
 + Customs/Custom Mobiles/Customizable Vendor/[RC2] Rewards System.cs:
    CS0115: Line 2246: 'MobileMyRewardVendor.OnBuyItems(Server.Mobile, System.Co
llections.ArrayList)': no suitable method found to override
Scripts: One or more scripts failed to compile or no script files were found.
 - Press return to exit, or R to try again.
 

Phr3d13

Sorceror
UO_Talon;860692 said:
I'm having an issue

Code:
RunUO - [www.runuo.com] Version 2.1, Build 3935.18827
Core: Running on .NET Framework Version 2.0.50727
Scripts: Compiling C# scripts...failed (1 errors, 0 warnings)
Errors:
 + Customs/Custom Mobiles/Customizable Vendor/[RC2] Rewards System.cs:
    CS0115: Line 2246: 'MobileMyRewardVendor.OnBuyItems(Server.Mobile, System.Co
llections.ArrayList)': no suitable method found to override
Scripts: One or more scripts failed to compile or no script files were found.
 - Press return to exit, or R to try again.

I'm getting this same error, anyone figure it out?

EDIT: Found the "svn" version and getting these errors now:
CS0117: Line 2155: 'Server.Network.NetState' does not contain a definition for 'IsPost6017'
CS0117: Line 2361: 'Server.Network.NetState' does not contain a definition for 'IsPost6017'
 

Pure Insanity

Sorceror
The svn version will not work without actually using the svn...you have an older core.

AS for the first error you got with the other version. You need to update the vendors. Open one of your vendors such as a Baker or something. See how it handles everything. You'll notice that the Baker uses <Lists> and not arrays any more. It's a pretty easy fix, and something you'll have to do to a lot of old things you find on here to get it working with a newer core.
 

Phr3d13

Sorceror
James420;862801 said:
The svn version will not work without actually using the svn...you have an older core.

AS for the first error you got with the other version. You need to update the vendors. Open one of your vendors such as a Baker or something. See how it handles everything. You'll notice that the Baker uses <Lists> and not arrays any more. It's a pretty easy fix, and something you'll have to do to a lot of old things you find on here to get it working with a newer core.

Here's My error:

Code:
RunUO - [www.runuo.com] Version 2.1, Build 3964.21635
Core: Running on .NET Framework Version 2.0.50727
Core: Optimizing for 2 processors
Scripts: Compiling C# scripts...failed (1 errors, 10 warnings)
Warnings:
 + Customs/CorpseRetrievalPackage_UsingXMLSpawner.cs:
    CS0108: Line 858: 'Server.CorpseSystem.CorpseBookAtt.Initialize()' hides inh
erited member 'Server.Engines.XmlSpawner2.XmlAttachment.Initialize()'. Use the n
ew keyword if hiding was intended.
 + Customs/Alpha Gold Ledger 2.0/Alpha Gold Ledger.cs:
    CS0429: Line 374: Unreachable expression code detected
 + Customs/Casino Stuff/CEOBlackJack.cs:
    CS0618: Line 894: 'Server.Mobile.CloseGump(System.Type, int)' is obsolete: '
Use CloseGump( Type ) instead.'
    CS0618: Line 936: 'Server.Mobile.CloseGump(System.Type, int)' is obsolete: '
Use CloseGump( Type ) instead.'
    CS0618: Line 978: 'Server.Mobile.CloseGump(System.Type, int)' is obsolete: '
Use CloseGump( Type ) instead.'
    CS0618: Line 991: 'Server.Mobile.CloseGump(System.Type, int)' is obsolete: '
Use CloseGump( Type ) instead.'
    CS0618: Line 1057: 'Server.Mobile.CloseGump(System.Type, int)' is obsolete:
'Use CloseGump( Type ) instead.'
    CS0618: Line 1784: 'Server.Mobile.CloseGump(System.Type, int)' is obsolete:
'Use CloseGump( Type ) instead.'
    CS0618: Line 1788: 'Server.Mobile.CloseGump(System.Type, int)' is obsolete:
'Use CloseGump( Type ) instead.'
 + Customs/Casino Stuff/HiLoCards.cs:
    CS0618: Line 504: 'Server.Mobile.CloseGump(System.Type, int)' is obsolete: '
Use CloseGump( Type ) instead.'
 + Customs/CRIB/CustomRegion.cs:
    CS0219: Line 31: The variable 'toreturn' is assigned but its value is never
used
 + Customs/Knives Chat 3.0 Beta 9/General/MultiConnection.cs:
    CS0168: Line 65: The variable 'e' is declared but never used
    CS0168: Line 134: The variable 'e' is declared but never used
    CS0168: Line 165: The variable 'e' is declared but never used
    CS0168: Line 184: The variable 'e' is declared but never used
    CS0168: Line 201: The variable 'e' is declared but never used
    CS0168: Line 252: The variable 'e' is declared but never used
 + Customs/Knives Chat 3.0 Beta 9/Gumps/Error Reporting/Errors.cs:
    CS0618: Line 91: 'System.Web.Mail.MailMessage' is obsolete: 'The recommended
 alternative is System.Net.Mail.MailMessage. http://go.microsoft.com/fwlink/?lin
kid=14202'
    CS0618: Line 91: 'System.Web.Mail.MailMessage' is obsolete: 'The recommended
 alternative is System.Net.Mail.MailMessage. http://go.microsoft.com/fwlink/?lin
kid=14202'
    CS0618: Line 102: 'System.Web.Mail.SmtpMail' is obsolete: 'The recommended a
lternative is System.Net.Mail.SmtpClient. http://go.microsoft.com/fwlink/?linkid
=14202'
 + Items/Jewels/BaseJewel.cs:
    CS0162: Line 258: Unreachable code detected
 + Customs/Stygian Abyss/SA Customs/Facet Command/FacetGump.cs:
    CS0219: Line 18: The variable 'initialState' is assigned but its value is ne
ver used
 + Customs/Ultima Paintball Beta/PBGameItem.cs:
    CS0168: Line 967: The variable 'PBS' is declared but never used
Errors:
 + Customs/[SVN] Rewards System.cs:
    CS0117: Line 2155: 'Server.Network.NetState' does not contain a definition f
or 'IsPost6017'
    CS0117: Line 2361: 'Server.Network.NetState' does not contain a definition f
or 'IsPost6017'
Scripts: One or more scripts failed to compile or no script files were found.
 - Press return to exit, or R to try again.

I am using RunUO 2.0 SVN 526 + ML Latest + SA 1.5 and it seems that the netstate.cs in the server folder is missing the necessary references to ispost6017. anyone know how to get this to work for me?

I tried editing this:
Code:
 foreach (Container c in containers)
            {
                if (m.NetState != null && m.NetState.IsPost6017)
                    m.Send(new ContainerContent6017(m, c));
                else
                    m.Send(new ContainerContent(m, c));
to:
Code:
foreach (Container c in containers)
            {
               // if (m.NetState != null && m.NetState.IsPost6017)
                  //  m.Send(new ContainerContent6017(m, c));
                //else
                    m.Send(new ContainerContent(m, c));
and this:
Code:
if (m.NetState.IsPost6017)
                    m.Send(new VendorBuyContent6017(m_List));
to:
Code:
//if (m.NetState.IsPost6017)
                   // m.Send(new VendorBuyContent6017(m_List));
it seemed to work, it compiled right, but the vendors had empty menus when i changed access to player and tried to buy something
 

Attachments

  • [SVN] Rewards System.cs
    94.8 KB · Views: 27

Phr3d13

Sorceror
ok, just found out that with the above edits i can use this if i use the jewl gump, but if i switch back to the classic, the items don't show up again
 

Phr3d13

Sorceror
krazeykow, do you care if i post a version fixed for the latest svn?

Edit: It's been a couple of days, here it is, Complete Customizable Vendor xml version for svn
 

Attachments

  • [SVN] Rewards System.cs
    94.8 KB · Views: 112

Pure Insanity

Sorceror
It appears that the SA server still has the 6017 netstate info in it. Just seems that it's been changed completely on how it handles the protocol changes.

But from the looks of your edit...you've noticed the same thing and made the correct changes. So I'm guessing it now works for the old gump too?
 

Phr3d13

Sorceror
James420;864635 said:
It appears that the SA server still has the 6017 netstate info in it. Just seems that it's been changed completely on how it handles the protocol changes.

But from the looks of your edit...you've noticed the same thing and made the correct changes. So I'm guessing it now works for the old gump too?

I didn't make the edits, i asked on orb for help because i was thinking that's where the problem was, and someone there made the edits. But yes, the classic and jewl gumps both work with the new edits
 
Gives me this error


Errors:
+ Customs/[RC2] Rewards System.cs:
CS0115: Line 2344: 'MobileRewardVendor.OnBuyItems(Server.Mobile, System.Coll
ections.ArrayList)': no suitable method found to override

any suggestions please?
 
Top