I am trying to get Xantho's Auction to work and this is the error I am getting.
Code:
 + Custom Systems/Xanthos/Auction System/AuctionItem.cs:
    CS0246: Line 226: The type or namespace name 'StringList' could not be found
(are you missing a using directive or an assembly reference?)

Here is the Script.
Code:
#region AuthorHeader
//
// Auction version 2.1, by Xanthos and Arya
//
// Based on original ideas and code by Arya
//
#endregion AuthorHeader
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using OpenUO.Ultima;
using System.Text;
using Server;
using Server.Network;
using Server.Accounting;
using Server.Items;
using Server.Mobiles;
using Xanthos.Utilities;
using Xanthos.Interfaces;

namespace Arya.Auction
{
    /// <summary>
    /// Defines situations for pending situations
    /// </summary>
    public enum AuctionPendency : byte
    {
        /// <summary>
        /// The user still has to make a decision
        /// </summary>
        Pending = 0,
        /// <summary>
        /// The user OKs the auction
        /// </summary>
        Accepted = 1,
        /// <summary>
        /// The user didn't accept the auction
        /// </summary>
        NotAccepted = 2
    }

    /// <summary>
    /// Defines what happens with the auction item if the auction is ended by the staff
    /// </summary>
    public enum ItemFate
    {
        /// <summary>
        /// The item is returned to the owner
        /// </summary>
        ReturnToOwner,
        /// <summary>
        /// The item is taken by the staff
        /// </summary>
        ReturnToStaff,
        /// <summary>
        /// The item is deleted
        /// </summary>
        Delete
    }

    /// <summary>
    /// Specifies the type of message that should be dispatched for the buyer or the owner
    /// </summary>
    public enum AuctionMessage : byte
    {
        /// <summary>
        /// No message should be dispatched
        /// </summary>
        None = 0,
        /// <summary>
        /// An information message should be dispatched
        /// </summary>
        Information = 1,
        /// <summary>
        /// A feedback message should be dispatched
        /// </summary>
        Response = 2
    }

    /// <summary>
    /// An auction entry, holds all the information about a single auction process
    /// </summary>
    public class AuctionItem
    {
        #region ItemInfo class

        public class ItemInfo
        {
            private string m_Name;
            private Item m_Item;
            private string m_Props;

            public string Name
            {
                get
                {
                    if ( m_Item != null )
                        return m_Name;
                    else
                        return "N/A";
                }
            }

            public Item Item
            {
                get { return m_Item; }
            }

            public string Properties
            {
                get
                {
                    if ( m_Item != null )
                        return m_Props;
                    else
                        return AuctionSystem.ST[ 146 ];
                }
            }

            public ItemInfo( Item item )
            {
                m_Item = item;

                if ( item.Name != null )
                    m_Name = item.Name;
                else
                    m_Name = m_StringList.Table[ item.LabelNumber ] as string;

                if ( item.Amount > 1 )
                {
                    m_Name = string.Format( "{0} {1}", item.Amount.ToString("#,0" ), m_Name );
                }

                if ( item is MobileStatuette )
                {
                    m_Props = GetCreatureProperties( ( item as MobileStatuette ).ShrunkenPet );
                }
                else
                {
                    m_Props = AuctionItem.GetItemProperties( item );
                }
            }

            private static string GetCreatureProperties( BaseCreature creature )
            {
                StringBuilder sb = new StringBuilder();

                sb.Append( "<basefont color=#FFFFFF>" );

                if ( creature.Name != null )
                {
                    sb.AppendFormat( "Name : {0}<br", creature.Name );
                }

                sb.AppendFormat( AuctionSystem.ST[ 147 ] , creature.ControlSlots );
                sb.AppendFormat( AuctionSystem.ST[ 148 ], creature.IsBondable ? "Yes" : "No" );
                sb.AppendFormat( AuctionSystem.ST[ 149 ] , creature.Str );
                sb.AppendFormat( AuctionSystem.ST[ 150 ] , creature.Dex );
                sb.AppendFormat( AuctionSystem.ST[ 151 ] , creature.Int );

                int index = 0;
                Server.Skill skill = null;

                while ( ( skill = creature.Skills[ index++ ] ) != null )
                {
                    if ( skill.Value > 0 )
                    {
                        sb.AppendFormat( "{0} : {1}<br>", skill.Name, skill.Value );
                    }
                }

                return sb.ToString();
            }

            private ItemInfo()
            {
            }

            public void Serialize( GenericWriter writer )
            {
                // Version 1
                // Version 0
                writer.Write( m_Name );
                writer.Write( m_Item );
                writer.Write( m_Props );
            }

            public static ItemInfo Deserialize( GenericReader reader, int version )
            {
                ItemInfo item = new ItemInfo();

                switch ( version )
                {
                    case 1:
                    case 0:
                        item.m_Name = reader.ReadString();
                        item.m_Item = reader.ReadItem();
                        item.m_Props = reader.ReadString();
                        break;
                }

                return item;
            }

            /// <summary>
            /// Verifies if the mobile referenced by this item is still valid
            /// </summary>
            public void VeirfyIntegrity()
            {
                IShrinkItem shrinkItem = m_Item as IShrinkItem;

                if ( null != shrinkItem && null == shrinkItem.ShrunkenPet )
                {
                    m_Item.Delete();
                    m_Item = null; // This will make this item invalid
                }
            }
        }

        #endregion

        #region Item Properties

        private static StringList m_StringList;

        static AuctionItem()
        {
            Console.WriteLine( "AuctionItem.cs: AuctionItem(): DEBUG: Beginning AuctionItem()" );

            string clilocFolder = null;

            if ( AuctionConfig.ClilocLocation != null && AuctionConfig.ClilocLocation != "" )  // TESTING by Alari - 4/20/2008
            {
                Console.WriteLine( "AuctionItem.cs: AuctionItem(): DEBUG: AuctionConfig.ClilocLocation NOT null! Value: \"{0}\"", AuctionConfig.ClilocLocation );
                clilocFolder = Path.GetDirectoryName( AuctionConfig.ClilocLocation );
                Ultima.Client.Directories.Insert(0, clilocFolder);
                Console.WriteLine( "AuctionItem.cs: AuctionItem(): DEBUG: clilocFolder set to {0}", clilocFolder );
               
            }
            else  // TESTING by Alari - 4:20 AM 4/19/2007
            {
                Console.WriteLine( "AuctionItem.cs: AuctionItem(): DEBUG: AuctionConfig.ClilocLocation is NULL, proceeding with auto-detection..." );
                clilocFolder = Core.FindDataFile( "cliloc.enu" );
                if ( clilocFolder != null )
                {
                    Ultima.Client.Directories.Insert( 0, clilocFolder );
                    Console.WriteLine( "AuctionItem.cs: AuctionItem(): DEBUG: Cliloc detection worked! {0}", clilocFolder );
                }
                else
                {
                    Console.WriteLine( "AuctionItem.cs: AuctionItem(): DEBUG: Cliloc detection failed." );
                }
            }

            m_StringList = new StringList( "ENU" );

            if ( clilocFolder != null )
            {
                Ultima.Client.Directories.RemoveAt( 0 );
            }
        }

        /// <summary>
        /// Gets an html formatted string with all the properies for the item
        /// </summary>
        /// <returns>A string object containing the html structure corresponding to the item properties</returns>
        private static string GetItemProperties( Item item )
        {
            if ( item == null || item.PropertyList == null )
            {
                return AuctionSystem.ST[ 78 ];
            }

            if ( Core.AOS )
            {
                #region AoS
                ObjectPropertyList plist = new ObjectPropertyList( item );
                item.GetProperties( plist );

                byte[] data = plist.UnderlyingStream.UnderlyingStream.ToArray();
                ArrayList list = new ArrayList();

                int index = 15; // First localization number index

                while ( true )
                {
                    uint number = 0;

                    if ( index + 4 >= data.Length )
                    {
                        break;
                    }

                    number = (uint) ( data[ index++ ] << 24 | data[ index++ ] << 16 | data[ index++ ] << 8 | data[ index++ ] );
                    ushort length = 0;

                    if ( index + 2 > data.Length )
                    {
                        break;
                    }

                    length = (ushort) ( data[ index++ ] << 8 | data[ index++ ] );

                    // Read the string
                    int end = index + length;

                    if ( end >= data.Length )
                    {
                        end = data.Length - 1;
                    }

                    System.Text.StringBuilder s = new System.Text.StringBuilder();
                    while ( index + 2 <= end + 1 )
                    {
                        short next = (short) ( data[ index++ ] | data[ index++ ] << 8 );

                        if ( next == 0 )
                            break;

                        s.Append( System.Text.Encoding.Unicode.GetString( BitConverter.GetBytes( next ) ) );
                    }

                    list.Add( ComputeProperty( (int) number, s.ToString() ) );
                }

                System.Text.StringBuilder sb = new System.Text.StringBuilder();
                sb.Append( "<basefont color=#FFFFFF><p>" );

                foreach( string prop in list )
                {
                    sb.AppendFormat( "{0}<br>", prop );
                }

                return sb.ToString();
                #endregion
            }
            else
            {
                #region Non AoS
                StringBuilder sb = new StringBuilder();
                sb.Append( "<basefont color=#FFFFFF><p>" );

                // Get the item name
                if ( item.Name != null && item.Name.Length > 0 )
                {
                    sb.AppendFormat( "{0}<br>", item.Name );
                }
                else
                {
                    sb.AppendFormat( "{0}<br>", Capitalize( m_StringList.Table[ item.LabelNumber ] as string ) );
                }

                // Amount
                if ( item.Amount > 1 )
                {
                    sb.AppendFormat( AuctionSystem.ST[ 152 ] , item.Amount.ToString("#,0" ) );
                }

                // Loot type
                if ( item.LootType != LootType.Regular )
                {
                    sb.AppendFormat( "{0}<br>", item.LootType.ToString() );
                }

                if ( item is IUsesRemaining )
                {
                    sb.AppendFormat( AuctionSystem.ST[ 153 ] , ( item as IUsesRemaining ).UsesRemaining );
                }

                // Manage item types

                if ( item is BaseWand )
                {
                    #region Wands
                    BaseWand bw = item as BaseWand;
                    sb.AppendFormat( AuctionSystem.ST[ 154 ] , bw.Effect.ToString() );
                    sb.AppendFormat( AuctionSystem.ST[ 155 ] , bw.Charges );
                    #endregion
                }
                else if ( item is BaseArmor )
                {
                    #region Armor
                    BaseArmor ba = item as BaseArmor;

                    if ( ba.PlayerConstructed )
                    {
                        if ( ba.Crafter != null )
                        {
                            sb.AppendFormat( AuctionSystem.ST[ 156 ] , ba.Crafter.Name );
                        }
                        sb.AppendFormat( AuctionSystem.ST[ 157 ] , ba.Resource.ToString() );
                    }

                    sb.AppendFormat( AuctionSystem.ST[ 158 ] , ba.Quality.ToString() );
                    sb.AppendFormat( AuctionSystem.ST[ 159 ] , ba.HitPoints, ba.MaxHitPoints );

                    if ( ba.Durability != ArmorDurabilityLevel.Regular )
                    {
                        sb.AppendFormat( AuctionSystem.ST[ 160 ] , ba.Durability.ToString() );
                    }

                    if ( ba.ProtectionLevel != ArmorProtectionLevel.Regular )
                    {
                        sb.AppendFormat( AuctionSystem.ST[ 161 ] , ba.ProtectionLevel.ToString() );
                    }
                    #endregion
                }
                else if ( item is BaseWeapon )
                {
                    #region Weapons
                    BaseWeapon bw = item as BaseWeapon;

                    if ( bw.PlayerConstructed )
                    {
                        if ( bw.Crafter != null )
                        {
                            sb.AppendFormat( AuctionSystem.ST[ 156 ] , bw.Crafter.Name );
                        }
                        sb.AppendFormat( AuctionSystem.ST[ 157 ] , bw.Resource.ToString() );
                    }

                    sb.AppendFormat( AuctionSystem.ST[ 158 ] , bw.Quality.ToString() );
                    sb.AppendFormat( AuctionSystem.ST[ 159 ], bw.HitPoints, bw.MaxHitPoints );

                    if ( bw.PoisonCharges > 0 )
                    {
                        sb.AppendFormat( AuctionSystem.ST[ 162 ] , bw.PoisonCharges, bw.Poison.ToString() );
                    }

                    if ( item is BaseRanged )
                    {
                        sb.AppendFormat( AuctionSystem.ST[ 163 ] , bw.MaxRange.ToString() );
                    }

                    if ( bw.DamageLevel != WeaponDamageLevel.Regular )
                    {
                        sb.AppendFormat( AuctionSystem.ST[ 164 ] , bw.DamageLevel.ToString() );
                    }

                    if ( bw.DurabilityLevel != WeaponDurabilityLevel.Regular )
                    {
                        sb.AppendFormat( AuctionSystem.ST[ 160 ] , bw.DurabilityLevel.ToString() );
                    }

                    if ( bw.AccuracyLevel != WeaponAccuracyLevel.Regular )
                    {
                        if ( bw.AccuracyLevel == WeaponAccuracyLevel.Accurate )
                        {
                            sb.AppendFormat( AuctionSystem.ST[ 165 ] );
                        }
                        else
                        {
                            sb.AppendFormat( AuctionSystem.ST[ 166 ] , bw.AccuracyLevel.ToString() );
                        }
                    }

                    if ( bw.Slayer != SlayerName.None )
                    {
                        sb.AppendFormat( AuctionSystem.ST[ 167 ] , bw.Slayer.ToString() );
                    }
                    #endregion
                }
                else if ( item is TreasureMap )
                {
                    #region Treasure Map
                    TreasureMap tm = item as TreasureMap;
                    sb.AppendFormat( AuctionSystem.ST[ 168 ] , tm.ChestMap );
                    #endregion
                }
                else if ( item is Spellbook )
                {
                    #region Spellbook
                    Spellbook sp = item as Spellbook;
                    sb.AppendFormat( AuctionSystem.ST[ 169 ] , sp.SpellCount );
                    #endregion
                }
                else if ( item is PotionKeg )
                {
                    #region Potion Keg
                    PotionKeg pk = item as PotionKeg;

                    int number;

                    if ( pk.Held <= 0 )
                        number = 502246; // The keg is empty.
                    else if ( pk.Held < 5 )
                        number = 502248; // The keg is nearly empty.
                    else if ( pk.Held < 20 )
                        number = 502249; // The keg is not very full.
                    else if ( pk.Held < 30 )
                        number = 502250; // The keg is about one quarter full.
                    else if ( pk.Held < 40 )
                        number = 502251; // The keg is about one third full.
                    else if ( pk.Held < 47 )
                        number = 502252; // The keg is almost half full.
                    else if ( pk.Held < 54 )
                        number = 502254; // The keg is approximately half full.
                    else if ( pk.Held < 70 )
                        number = 502253; // The keg is more than half full.
                    else if ( pk.Held < 80 )
                        number = 502255; // The keg is about three quarters full.
                    else if ( pk.Held < 96 )
                        number = 502256; // The keg is very full.
                    else if ( pk.Held < 100 )
                        number = 502257; // The liquid is almost to the top of the keg.
                    else
                        number = 502258; // The keg is completely full.

                    sb.AppendFormat( Capitalize( m_StringList.Table[ number ] as string ) );
                    #endregion
                }

                return sb.ToString();

                #endregion
            }
        }

        /// <summary>
        /// Capitalizes each word in a string
        /// </summary>
        /// <param name="property">The input string</param>
        /// <returns>The output string </returns>
        private static string Capitalize( string property )
        {

            string[] parts = property.Split( ' ' );
            StringBuilder sb = new StringBuilder();

            for ( int i = 0; i < parts.Length; i++ )
            {
                string part = parts[ i ];

                if ( part.Length == 0 )
                {
                    continue;
                }

                char c = char.ToUpper( part[ 0 ] );

                part = part.Substring( 1 );
                sb.AppendFormat( "{0}{1}", string.Concat( c, part ), i < parts.Length - 1 ? " " : "" );
            }

            return sb.ToString();
        }

        /// <summary>
        /// Converts a localization number and its arguments to a valid string
        /// </summary>
        /// <param name="number">The localization number of the label</param>
        /// <param name="arguments">The arguments for the label</param>
        /// <returns>The translated string</returns>
        private static string ComputeProperty( int number, string arguments )
        {
            string prop = m_StringList.Table[ number ] as string;

            if ( prop == null )
            {
                return AuctionSystem.ST[ 170 ] ;
            }

            if ( arguments == null || arguments.Length == 0 )
            {
                return Capitalize( prop );
            }

            string[] args = arguments.Split( '\t' );
            Regex reg = new Regex( @"~\d+\w*~", RegexOptions.None );
            MatchCollection matches = reg.Matches( prop, 0 );

            if ( matches.Count == args.Length )
            {
                // Valid
                for ( int i = 0; i < matches.Count; i++ )
                {
                    if ( args[ i ].StartsWith( "#" ) )
                    {
                        int loc = -1;

                        try
                        {
                            loc = int.Parse( args[ i ].Substring( 1 ) );
                        }
                        catch {}

                        if ( loc != -1 )
                        {
                            args[ i ] = m_StringList.Table[ loc ] as string;
                        }
                    }

                    Match m = matches [ i ];

                    prop = prop.Replace( m.Value, args[ i ] );
                }

                return Capitalize( prop );
            }
            else
            {
                return AuctionSystem.ST[ 171 ] ;
            }
        }

        #endregion

        #region Variables

        private Item m_Item;
        private Mobile m_Owner;
        private DateTime m_StartTime;
        private DateTime m_EndTime;
        private TimeSpan m_Duration = TimeSpan.FromDays( 7 );
        private int m_MinBid = 100;
        private int m_Reserve = 100;
        private string m_Description = "";
        private ArrayList m_Bids;
        private string m_WebLink = "";
        private string m_ItemName;
        private bool m_Pending;
        private ItemInfo[] m_Items;
        private Guid m_ID;
        private AuctionPendency m_OwnerPendency = AuctionPendency.Pending;
        private AuctionPendency m_BuyerPendency = AuctionPendency.Pending;
        private AuctionMessage m_OwnerMessage = AuctionMessage.None;
        private AuctionMessage m_BuyerMessage = AuctionMessage.None;
        private DateTime m_PendingEnd;
        private int m_BuyNow = 0;

        #region Props

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// States whether this auction allows the buy now feature
            /// </summary>
        public bool AllowBuyNow
        {
            get { return m_BuyNow > 0; }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// Gets the buy now value
            /// </summary>
        public int BuyNow
        {
            get { return m_BuyNow; }
            set { m_BuyNow = value; }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// Gets the date and time corrsponding to the moment when the pending situation will automatically end
            /// </summary>
        public DateTime PendingEnd
        {
            get { return m_PendingEnd; }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// Gets the item being sold at the auction
            /// </summary>
        public Item Item
        {
            get { return m_Item; }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// Gets the owner of the item
            /// </summary>
        public Mobile Owner
        {
            get { return m_Owner; }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// Gets the starting time for this auction
            /// </summary>
        public DateTime StartTime
        {
            get { return m_StartTime; }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// Gets the end time for this auction
            /// </summary>
        public DateTime EndTime
        {
            get { return m_EndTime; }
        }

        /// <summary>
        /// Gets the running length of the auction for this item
        /// </summary>
        public TimeSpan Duration
        {
            get { return m_Duration; }
            set
            {
                try
                {
                    m_Duration = value;
                }
                catch
                {
                    m_Duration = TimeSpan.Zero;
                }
            }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// Gets the time to live left for this auction
            /// </summary>
        public TimeSpan TimeLeft
        {
            get
            {
                return m_EndTime - DateTime.Now;
            }
        }

        /// <summary>
        /// Gets or sets the minimum bid allowed for this item
        /// </summary>
        public int MinBid
        {
            get { return m_MinBid; }
            set { m_MinBid = value; }
        }

        /// <summary>
        /// Gets or sets the reserve price for the item
        /// </summary>
        public int Reserve
        {
            get { return m_Reserve; }
            set { m_Reserve = value; }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// Gets or sets the description for this item
            /// </summary>
        public string Description
        {
            get { return m_Description; }
            set { m_Description = value; }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// A web link associated with this auction item
            /// </summary>
        public string WebLink
        {
            get { return m_WebLink; }
            set
            {
                if ( value != null && value.Length > 0 )
                {
                    if ( value.ToLower().StartsWith( "http://" ) && value.Length > 7 )
                    {
                        value = value.Substring( 7 );
                    }
                }

                m_WebLink = value;
            }
        }

        /// <summary>
        /// Gets or sets the list of existing bids
        /// </summary>
        public ArrayList Bids
        {
            get { return m_Bids; }
            set { m_Bids = value; }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// Gets the account that's selling this item
            /// </summary>
        public Account Account
        {
            get
            {
                if ( m_Owner != null && m_Owner.Account != null )
                {
                    return m_Owner.Account as Account;
                }
                else
                {
                    return null;
                }
            }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// Gets or sets the name of the item being sold
            /// </summary>
        public string ItemName
        {
            get { return m_ItemName; }
            set { m_ItemName = value; }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// True if the auction is over but the reserve hasn't been met and the owner still haven't decided
            /// if to sell the item or not. This value makes no sense before the auction is over.
            /// </summary>
        public bool Pending
        {
            get { return m_Pending; }
        }

        /// <summary>
        /// Gets the definitions of the items sold
        /// </summary>
        public ItemInfo[] Items
        {
            get { return m_Items; }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// Gets the number of items sold
            /// </summary>
        public int ItemCount
        {
            get { return m_Items.Length; }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// Gets the unique ID of this auction
            /// </summary>
        public Guid ID
        {
            get { return m_ID; }
        }

        #endregion

        #endregion

        #region Serialization

        /// <summary>
        /// Saves the auction item into the world file
        /// </summary>
        /// <param name="writer"></param>
        public void Serialize( GenericWriter writer )
        {
            // Version 1
            writer.Write( m_BuyNow );

            // Version 0
            writer.Write( m_Owner );
            writer.Write( m_StartTime );
            writer.Write( m_Duration );
            writer.Write( m_MinBid );
            writer.Write( m_Reserve );
            writer.Write( m_Duration );
            writer.Write( m_Description );
            writer.Write( m_WebLink );
            writer.Write( m_Pending );
            writer.Write( m_ItemName );
            writer.Write( m_Item );
            writer.Write( m_ID.ToString() );
            writer.WriteDeltaTime( m_EndTime );
            writer.Write( (byte) m_OwnerPendency );
            writer.Write( (byte) m_BuyerPendency );
            writer.Write( (byte) m_OwnerMessage );
            writer.Write( (byte) m_BuyerMessage );
            writer.WriteDeltaTime( m_PendingEnd );

            writer.Write( m_Items.Length );
            // Items
            foreach( ItemInfo ii in m_Items )
            {
                ii.Serialize( writer );
            }

            // Bids
            writer.Write( m_Bids.Count );
            foreach( Bid bid in m_Bids )
            {
                bid.Serialize( writer );
            }
        }

        /// <summary>
        /// Loads an AuctionItem
        /// </summary>
        /// <returns>An AuctionItem</returns>
        public static AuctionItem Deserialize( GenericReader reader, int version )
        {
            AuctionItem auction = new AuctionItem();

            switch ( version )
            {
                case 1:
                    auction.m_BuyNow = reader.ReadInt();
                    goto case 0;

                case 0:
                    auction.m_Owner = reader.ReadMobile();
                    auction.m_StartTime = reader.ReadDateTime();
                    auction.m_Duration = reader.ReadTimeSpan();
                    auction.m_MinBid = reader.ReadInt();
                    auction.m_Reserve = reader.ReadInt();
                    auction.m_Duration = reader.ReadTimeSpan();
                    auction.m_Description = reader.ReadString();
                    auction.m_WebLink = reader.ReadString();
                    auction.m_Pending = reader.ReadBool();
                    auction.m_ItemName = reader.ReadString();
                    auction.m_Item = reader.ReadItem();
                    auction.m_ID = new Guid( reader.ReadString() );
                    auction.m_EndTime = reader.ReadDeltaTime();
                    auction.m_OwnerPendency = (AuctionPendency) reader.ReadByte();
                    auction.m_BuyerPendency = (AuctionPendency) reader.ReadByte();
                    auction.m_OwnerMessage = (AuctionMessage) reader.ReadByte();
                    auction.m_BuyerMessage = (AuctionMessage) reader.ReadByte();
                    auction.m_PendingEnd = reader.ReadDeltaTime();

                    int count = reader.ReadInt();
                    auction.m_Items = new ItemInfo[ count ];

                    for ( int i = 0; i < count; i++ )
                    {
                        auction.m_Items[ i ] = ItemInfo.Deserialize( reader, version );
                    }

                    count = reader.ReadInt();

                    for ( int i = 0; i < count; i++ )
                    {
                        auction.Bids.Add( Bid.Deserialize( reader, version ) );
                    }
                    break;
            }

            return auction;
        }

        #endregion

        #region Properties

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// Gets the minimum increment required for the auction
            /// </summary>
        public int BidIncrement
        {
            get
            {
                if ( m_MinBid <= 100 )
                    return 50; //return 10;

                if (m_MinBid <= 250)
                    return 75;

                if ( m_MinBid <= 500 )
                    return 100; //return 20;

                if (m_MinBid <= 750)
                    return 200;

                if ( m_MinBid <= 1000 )
                    return 300; //return 50;

                if (m_MinBid <= 2500)
                    return 400;

                if ( m_MinBid <= 5000 )
                    return 500; //return 100;

                if (m_MinBid <= 7500)
                    return 600;

                if ( m_MinBid <= 10000 )
                    return 700; //return 200;

                if (m_MinBid <= 15000)
                    return 800;

                if ( m_MinBid <= 20000 )
                    return 1000; //return 250;

                if (m_MinBid <= 30000)
                    return 1500;

                if (m_MinBid <= 40000)
                    return 2000;

                if ( m_MinBid <= 50000 )
                    return 3000; //return 500;

                return 4000;
            }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// States whether an item has at least one bid
            /// </summary>
        public bool HasBids
        {
            get { return m_Bids.Count > 0; }
        }

        /// <summary>
        /// Gets the highest bid for this item
        /// </summary>
        public Bid HighestBid
        {
            get
            {
                if ( m_Bids.Count > 0 )
                    return m_Bids[ 0 ] as Bid;
                else
                    return null;
            }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
        public Mobile HighestBidder
        {
            get
            {
                if ( m_Bids.Count > 0 )
                    return ( m_Bids[ 0 ] as Bid ).Mobile;
                else
                    return null;
            }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
        public int HighestBidValue
        {
            get
            {
                if ( m_Bids.Count > 0 )
                    return ( m_Bids[ 0 ] as Bid ).Amount;
                else return 0;
            }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// States whether the reserve has been met for this item
            /// </summary>
        public bool ReserveMet
        {
            get { return HighestBid != null && HighestBid.Amount >= m_Reserve; }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// States whether this auction has expired
            /// </summary>
        public bool Expired
        {
            get { return DateTime.Now > m_EndTime; }
        }

        /// <summary>
        /// Gets the minimum bid that a player can place
        /// </summary>
        public int MinNewBid
        {
            get
            {
                if ( HighestBid != null )
                    return HighestBid.Amount;
                else
                    return m_MinBid;
            }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// Gets the next deadline required by this auction
            /// </summary>
        public DateTime Deadline
        {
            get
            {
                if ( ! Expired )
                {
                    return m_EndTime;
                }
                else if ( m_Pending )
                {
                    return m_PendingEnd;
                }
                else
                {
                    return DateTime.MaxValue;
                }
            }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// Specifies if the pending period has timed out
            /// </summary>
        public bool PendingExpired
        {
            get
            {
                return DateTime.Now >= m_PendingEnd;
            }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// Gets the time left before the pending period expired
            /// </summary>
        public TimeSpan PendingTimeLeft
        {
            get { return m_PendingEnd - DateTime.Now; }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// States whether this auction is selling a pet
            /// </summary>
        public bool Creature
        {
            get { return m_Item is MobileStatuette; }
        }

        [ CommandProperty( AccessLevel.Administrator ) ]
            /// <summary>
            /// Gets the BaseCreature sold through this auction. This will be null when selling an item.
            /// </summary>
        public BaseCreature Pet
        {
            get
            {
                if ( Creature )
                {
                    return ((MobileStatuette)m_Item).ShrunkenPet;
                }

                return null;
            }
        }

        #endregion

        /// <summary>
        /// Creates a new AuctionItem
        /// </summary>
        /// <param name="item">The item being sold</param>
        /// <param name="owner">The owner of the item</param>
        public AuctionItem( Item item, Mobile owner )
        {
            m_ID = Guid.NewGuid();
            m_Item = item;
            m_Owner = owner;
            m_Bids = new ArrayList();

            if ( ! Creature )
            {
                m_Item.Visible = false;
                m_Owner.SendMessage( AuctionConfig.MessageHue, AuctionSystem.ST[ 172 ] );
            }

            // Item name
            if ( m_Item.Name != null && m_Item.Name.Length > 0 )
            {
                m_ItemName = m_Item.Name;
            }
            else
            {
                m_ItemName = m_StringList.Table[ m_Item.LabelNumber ] as string;
            }

            if ( m_Item.Amount > 1 )
            {
                m_ItemName = string.Format( "{0} {1}", m_Item.Amount.ToString("#,0" ), m_ItemName );
            }
        }

        /// <summary>
        /// Creates an AuctionItem - for use in deserialization
        /// </summary>
        private AuctionItem()
        {
            m_Bids = new ArrayList();
        }

        [ System.Runtime.CompilerServices.IndexerName( "SoldItem" ) ]
            /// <summary>
            /// Gets the item info corresponding to the index value
            /// </summary>
        public ItemInfo this[int index]
        {
            get
            {
                if ( index > -1 && index < m_Items.Length )
                {
                    return m_Items[ index ];
                }
                else
                {
                    return null;
                }
            }
        }

        /// <summary>
        /// Confirms the auction item and adds it into the system
        /// </summary>
        public void Confirm()
        {
            m_StartTime = DateTime.Now;
            m_EndTime = m_StartTime + m_Duration;

            if ( Creature && Pet != null )
            {
                Pet.ControlTarget = null;
                Pet.ControlOrder = OrderType.Stay;
                Pet.Internalize();

                Pet.SetControlMaster( null );
                Pet.SummonMaster = null;
            }

            // Calculate all the ItemInfo
            if ( m_Item is Container && m_Item.Items.Count > 0 )
            {
                // Container with items
                m_Items = new ItemInfo[ m_Item.Items.Count ];

                for ( int i = 0; i < m_Items.Length; i++ )
                {
                    m_Items[ i ] = new ItemInfo( m_Item.Items[ i ] as Item );
                }
            }
            else
            {
                m_Items = new ItemInfo[ 1 ];

                m_Items[ 0 ] = new ItemInfo( m_Item );
            }

            AuctionSystem.Add( this );
            AuctionScheduler.UpdateDeadline( m_EndTime );

            AuctionLog.WriteNewAuction( this );
        }

        /// <summary>
        /// Cancels the new auction and returns the item to the owner
        /// </summary>
        public void Cancel()
        {
            if ( !Creature )
            {
                m_Item.Visible = true;
                m_Owner.SendMessage( AuctionConfig.MessageHue, AuctionSystem.ST[ 173 ] );
            }
            else
            {
                ( m_Item as MobileStatuette ).GiveCreatureTo( m_Owner );
                m_Owner.SendMessage( AuctionConfig.MessageHue, AuctionSystem.ST[ 174 ] );
            }
        }

        /// <summary>
        /// Sends the associated web link to a mobile
        /// </summary>
        /// <param name="m">The mobile that should receive the web link</param>
        public void SendLinkTo( Mobile m )
        {
            if ( m != null && m.NetState != null )
            {
                if ( m_WebLink != null && m_WebLink.Length > 0 )
                {
                    m.LaunchBrowser( string.Format( "http://{0}", m_WebLink ) );
                }
            }
        }

        /// <summary>
        /// Verifies if a mobile can place a bid on this item
        /// </summary>
        /// <param name="m">The Mobile trying to bid</param>
        /// <returns>True if the mobile is allowed to bid</returns>
        public bool CanBid( Mobile m )
        {
            if ( m.AccessLevel > AccessLevel.Player )
                return false; // Staff shoudln't bid. This will also give the bids view to staff members.

            if ( this.Account == ( m.Account as Account ) ) // Same account as auctioneer
                return false;

            if ( Creature )
            {
                return ( Pet != null && Pet.CanBeControlledBy( m ) );
            }

            return true;
        }

        /// <summary>
        /// Verifies if a mobile is the owner of this auction (checks accounts)
        /// </summary>
        /// <param name="m">The mobile being checked</param>
        /// <returns>True if the mobile is the owner of the auction</returns>
        public bool IsOwner( Mobile m )
        {
            return ( this.Account == ( m.Account as Account ) );
        }

        /// <summary>
        /// Places a new bid
        /// </summary>
        /// <param name="from">The Mobile bidding</param>
        /// <param name="amount">The bid amount</param>
        /// <returns>True if the bid has been added and accepted</returns>
        public bool PlaceBid( Mobile from, int amount )
        {
            if ( ! CanBid( from ) )
                return false;

            if ( HighestBid != null )
            {
                if ( amount <= HighestBid.Amount )
                {
                    from.SendMessage( AuctionConfig.MessageHue, AuctionSystem.ST[ 176 ] );
                    return false;
                }
            }
            else if ( amount < m_MinBid )
            {
                from.SendMessage( AuctionConfig.MessageHue, AuctionSystem.ST[ 177 ] );
                return false;
            }

            int delta = 0;

            if ( HighestBid != null )
                delta = amount - HighestBid.Amount;
            else
                delta = amount - m_MinBid;

            if (BidIncrement > delta && HasBids)
            {
                from.SendMessage( AuctionConfig.MessageHue, AuctionSystem.ST[ 204 ], BidIncrement );
                return false;
            }

            // Ok, do bid
            Bid bid = Bid.CreateBid( from, amount );

            if ( bid != null )
            {
                if ( HighestBid != null )
                {
                    HighestBid.Outbid( this ); // Return money to previous highest bidder
                }

                World.Broadcast(0x35, true, "A {0} just recieved a {1} bid on [Myauction ", m_ItemName, amount);
                         
                m_Bids.Insert( 0, bid );
                AuctionLog.WriteBid( this );

                // Check for auction extension
                if ( AuctionConfig.LateBidExtention > TimeSpan.Zero )
                {
                    TimeSpan timeLeft = m_EndTime - DateTime.Now;

                    if ( timeLeft < TimeSpan.FromMinutes( 5.0 ) )
                    {
                        m_EndTime += AuctionConfig.LateBidExtention;
                        bid.Mobile.SendMessage( AuctionConfig.MessageHue, AuctionSystem.ST[ 230 ] );
                    }
                }
            }

            return bid != null;
        }

        /// <summary>
        /// Forces the end of the auction when the item or creature has been deleted
        /// </summary>
        public void EndInvalid()
        {
            AuctionSystem.Auctions.Remove( this );

            if ( HighestBid != null )
            {
                AuctionGoldCheck gold = new AuctionGoldCheck( this, AuctionResult.ItemDeleted );
                GiveItemTo( HighestBid.Mobile, gold );
            }

            // The item has been deleted, no need to return it to the owner.
            // If it's a statuette, delete it
            if ( Creature && m_Item != null )
            {
                m_Item.Delete();
            }

            AuctionLog.WriteEnd( this, AuctionResult.ItemDeleted, null, null );

            // Over.
        }

        /// <summary>
        /// Forces the end of the auction and removes it from the system
        /// </summary>
        /// <param name="m">The staff member deleting the auction</param>
        /// <param name="itemfate">Specifies what should occur with the item</param>
        public void StaffDelete( Mobile m, ItemFate itemfate )
        {
            if ( AuctionSystem.Auctions.Contains( this ) )
                AuctionSystem.Auctions.Remove( this );
            else if ( AuctionSystem.Pending.Contains( this ) )
                AuctionSystem.Pending.Remove( this );

            if ( HighestBid != null )
            {
                AuctionGoldCheck gold = new AuctionGoldCheck( this, AuctionResult.StaffRemoved );
                GiveItemTo( HighestBid.Mobile, gold );
            }

            AuctionItemCheck check = new AuctionItemCheck( this, AuctionResult.StaffRemoved );
            string comments = null;

            switch( itemfate )
            {
                case ItemFate.Delete :

                    check.Delete();
                    comments = "The item has been deleted";
                    break;

                case ItemFate.ReturnToOwner:

                    GiveItemTo( m_Owner, check );
                    comments = "The item has been returned to the owner";
                    break;

                case ItemFate.ReturnToStaff:

                    GiveItemTo( m, check );
                    comments = "The item has been claimed by the staff";
                    break;
            }

            AuctionLog.WriteEnd( this, AuctionResult.StaffRemoved, m, comments );

            // OVer.
        }

        /// <summary>
        /// Ends the auction.
        /// This function is called by the auction system during its natural flow
        /// </summary>
        /// <param name="m">The Mobile eventually forcing the ending</param>
        public void End( Mobile m )
        {
            AuctionSystem.Auctions.Remove( this );

            if ( HighestBid == null )
            {
                // No bids, simply return the item
                AuctionCheck item = new AuctionItemCheck( this, AuctionResult.NoBids );
                GiveItemTo( m_Owner, item );

                // Over, this auction no longer exists
                AuctionLog.WriteEnd( this, AuctionResult.NoBids, m, null );
            }
            else
            {
                // Verify that all items still exist too, otherwise make it pending
                if ( IsValid() && ReserveMet )
                {
                    // Auction has been succesful
                    AuctionCheck item = new AuctionItemCheck( this, AuctionResult.Succesful );
                    GiveItemTo( HighestBid.Mobile, item );

                    AuctionCheck gold = new AuctionGoldCheck( this, AuctionResult.Succesful );
                    GiveItemTo( m_Owner, gold );

                    // Over, this auction no longer exists m_Auction.ItemName
                    AuctionLog.WriteEnd(this, AuctionResult.Succesful, m, null);

                    if (HighestBid != null)
                    {
                        World.Broadcast(95, true, "{0} just sold for {1} gold with {2} bids", this.ItemName, HighestBid.Amount, Bids.Count);
                    }
                }
                else
                {
                    // Reserve hasn't been met or auction isn't valid, this auction is pending
                    m_Pending = true;
                    m_PendingEnd = DateTime.Now + TimeSpan.FromDays( AuctionConfig.DaysForConfirmation );
                    AuctionSystem.Pending.Add( this );

                    DoOwnerMessage();
                    DoBuyerMessage();

                    Mobile owner = GetOnlineMobile( m_Owner );
                    Mobile buyer = GetOnlineMobile( HighestBid.Mobile );

                    SendMessage( owner );
                    SendMessage( buyer );

                    AuctionScheduler.UpdateDeadline( m_PendingEnd );

                    AuctionLog.WritePending( this, ReserveMet ? "Item deleted" : "Reserve not met" );
                }
            }
        }

        /// <summary>
        /// Gets the online mobile belonging to a mobile's account
        /// </summary>
        private Mobile GetOnlineMobile( Mobile m )
        {
            if ( m == null || m.Account == null )
                return null;

            if ( m.NetState != null )
                return m;

            Account acc = m.Account as Account;

            for ( int i = 0; i < 5; i++ )
            {
                Mobile mob = acc[ i ];

                if ( mob != null && mob.NetState != null )
                {
                    return mob;
                }
            }

            return null;
        }

        /// <summary>
        /// Ends the auction.
        /// This function is called when the system is being disbanded and all auctions must be forced close
        /// The item will be returned to the original owner, and the highest bidder will receive the money back
        /// </summary>
        public void ForceEnd()
        {
            AuctionSystem.Auctions.Remove( this );

            // Turn the item into a deed and give it to the auction owner
            AuctionCheck item = new AuctionItemCheck( this, AuctionResult.SystemStopped );

            if ( item != null )
                GiveItemTo( m_Owner, item ); // This in case the item has been wiped or whatever

            if ( HighestBid != null )
            {
                HighestBid.AuctionCanceled( this );
            }

            AuctionLog.WriteEnd( this, AuctionResult.SystemStopped, null, null );
        }

        /// <summary>
        /// This function will put an item in a player's backpack, and if full put it inside their bank.
        /// If the mobile is null, this will delete the item.
        /// </summary>
        /// <param name="m">The mobile receiving the item</param>
        /// <param name="item">The item being given</param>
        private static void GiveItemTo( Mobile m, Item item )
        {
            if ( m == null || item == null )
            {
                if ( item != null )
                    item.Delete();

                return;
            }

            if ( m.Backpack == null || !m.Backpack.TryDropItem( m, item, false ) )
            {
                if ( m.BankBox != null )
                {
                    m.BankBox.AddItem( item );
                }
                else
                {
                    item.Delete(); // Sucks to be you
                }
            }
        }

        /// <summary>
        /// Verifies if all the items being sold through this auction still exist
        /// </summary>
        /// <returns>True if all the items still exist</returns>
        public bool IsValid()
        {
            bool valid = true;

            foreach( ItemInfo info in m_Items )
            {
                if ( info.Item == null )
                    valid = false;
            }

            return valid;
        }

        /// <summary>
        /// Defines what kind of message the auction owner should receive. Doesn't send any messages.
        /// </summary>
        public void DoOwnerMessage()
        {
            if ( m_Owner == null || m_Owner.Account == null )
            {
                // If owner deleted the character, accept the auction by default
                m_OwnerPendency = AuctionPendency.Accepted;
            }
            else if ( !IsValid() && ReserveMet )
            {
                // Assume the owner will sell even if invalid when reserve is met
                m_OwnerPendency = AuctionPendency.Accepted;
            }
            else if ( !ReserveMet )
            {
                m_OwnerPendency = AuctionPendency.Pending;
                m_OwnerMessage = AuctionMessage.Response; // This is always reserve not met for the owner
            }
            else if ( !IsValid() )
            {
                m_OwnerPendency = AuctionPendency.Accepted;
                m_OwnerMessage = AuctionMessage.Information; // This is always about validty for the owner
            }
        }

        /// <summary>
        /// Defines what kind of message the buyer should receive. Doesn't send any messages.
        /// </summary>
        public void DoBuyerMessage()
        {
            if ( HighestBid.Mobile == null || HighestBid.Mobile.Account == null )
            {
                // Buyer deleted the character, accept the auction by default
                m_BuyerPendency = AuctionPendency.Accepted;
            }
            else if ( ! IsValid() )
            {
                // Send the buyer a message about missing items in the auction
                m_BuyerMessage = AuctionMessage.Response;
                m_BuyerPendency = AuctionPendency.Pending;
            }
            else if ( !ReserveMet )
            {
                // Assume the buyer will buy even if the reserve hasn't been met
                m_BuyerPendency = AuctionPendency.Accepted;
                // Send the buyer a message to inform them of the reserve issue
                m_BuyerMessage = AuctionMessage.Information;
            }
        }

        /// <summary>
        /// Validates the pending status of the auction. This method should be called whenever a pendency
        /// value is changed. If the auction has been validated, it will finalize items and remove the auction from the system.
        /// This is the only method that should be used to finalize a pending auction.
        /// </summary>
        public void Validate()
        {
            if ( ! AuctionSystem.Pending.Contains( this ) )
                return;

            if ( m_OwnerPendency == AuctionPendency.Accepted && m_BuyerPendency == AuctionPendency.Accepted )
            {
                // Both parts confirmed the auction
                m_Pending = false;
                AuctionSystem.Pending.Remove( this );

                AuctionCheck item = new AuctionItemCheck( this, AuctionResult.PendingAccepted );
                AuctionCheck gold = new AuctionGoldCheck( this, AuctionResult.PendingAccepted );

                if ( item != null )
                {
                    GiveItemTo( HighestBid.Mobile, item ); // Item to buyer
                }

                GiveItemTo( m_Owner, gold ); // Gold to owner

                // Over, this auction no longer exists
                AuctionLog.WriteEnd( this, AuctionResult.PendingAccepted, null, null );
            }
            else if ( m_OwnerPendency == AuctionPendency.NotAccepted || m_BuyerPendency == AuctionPendency.NotAccepted )
            {
                // At least one part refused
                m_Pending = false;
                AuctionSystem.Pending.Remove( this );

                AuctionCheck item = new AuctionItemCheck( this, AuctionResult.PendingRefused );
                AuctionCheck gold = new AuctionGoldCheck( this, AuctionResult.PendingRefused );

                if ( item != null )
                {
                    GiveItemTo( m_Owner, item ); // Give item back to owner
                }

                GiveItemTo( HighestBid.Mobile, gold ); // Give gold to highest bidder

                // Over, this auction no longer exists
                AuctionLog.WriteEnd( this, AuctionResult.PendingRefused, null, null );
            }
        }

        /// <summary>
        /// Sends any message this auction might have in store for a given mobile
        /// </summary>
        /// <param name="to">The Mobile logging into the server</param>
        public void SendMessage( Mobile to )
        {
            if ( ! m_Pending || to == null )
                return;

            if ( to == m_Owner || ( m_Owner != null && to.Account.Equals( m_Owner.Account ) ) )
            {
                // This is the owner loggin in
                if ( this.m_OwnerMessage != AuctionMessage.None )
                {
                    // Owner needs a message
                    if ( m_OwnerMessage == AuctionMessage.Information )
                    {
                        // Send information message about validity condition
                        AuctionMessaging.SendInvalidMessageToOwner( this );
                    }
                    else if ( m_OwnerMessage == AuctionMessage.Response )
                    {
                        // Send reserve not met confirmation request
                        AuctionMessaging.SendReserveMessageToOwner( this );
                    }
                }
            }
            else if ( to == HighestBid.Mobile || ( HighestBid.Mobile != null && to.Account.Equals( HighestBid.Mobile.Account ) ) )
            {
                // This is the buyer logging in
                if ( m_BuyerMessage != AuctionMessage.None )
                {
                    // Buyer should receive a message
                    if ( m_BuyerMessage == AuctionMessage.Information )
                    {
                        // Send message about reserve not met condition
                        AuctionMessaging.SendReserveMessageToBuyer( this );
                    }
                    else if ( m_BuyerMessage == AuctionMessage.Response )
                    {
                        // Send request to confirm invalid items auction
                        AuctionMessaging.SendInvalidMessageToBuyer( this );
                    }
                }
            }
        }

        /// <summary>
        /// Confirms an information message
        /// </summary>
        /// <param name="owner">True if the message was sent to the owner, false if to the buyer</param>
        public void ConfirmInformationMessage( bool owner )
        {
            if ( owner )
            {
                // Owner
                m_OwnerMessage = AuctionMessage.None; // Don't resent
            }
            else
            {
                // Buyer
                m_BuyerMessage = AuctionMessage.None;
            }
        }

        /// <summary>
        /// Gives a response to a message
        /// </summary>
        /// <param name="owner">True if the message was sent to the owner, false if to the buyer</param>
        /// <param name="ok">The response to the message</param>
        public void ConfirmResponseMessage( bool owner, bool ok )
        {
            if ( owner )
            {
                if ( ok )
                {
                    m_OwnerPendency = AuctionPendency.Accepted;
                }
                else
                {
                    m_OwnerPendency = AuctionPendency.NotAccepted;
                }
            }
            else
            {
                if ( ok )
                {
                    m_BuyerPendency = AuctionPendency.Accepted;
                }
                else
                {
                    m_BuyerPendency = AuctionPendency.NotAccepted;
                }
            }

            Validate();
        }

        /// <summary>
        /// The pending period has timed out and the auction must end unsuccesfully
        /// </summary>
        public void PendingTimeOut()
        {
            AuctionSystem.Pending.Remove( this );

            m_OwnerPendency = AuctionPendency.NotAccepted;
            m_BuyerPendency = AuctionPendency.NotAccepted;
            m_OwnerMessage = AuctionMessage.None;
            m_BuyerMessage = AuctionMessage.None;

            AuctionCheck item = new AuctionItemCheck( this, AuctionResult.PendingTimedOut );
            AuctionCheck gold = new AuctionGoldCheck( this, AuctionResult.PendingTimedOut );

            if ( item != null )
                GiveItemTo( m_Owner, item );
            GiveItemTo( HighestBid.Mobile, gold );

            // Over, this auction no longer exists
            AuctionLog.WriteEnd( this, AuctionResult.PendingTimedOut, null, null );
        }

        /// <summary>
        /// Verifies is a mobile has bid on this auction
        /// </summary>
        public bool MobileHasBids( Mobile m )
        {
            ArrayList bids = new ArrayList( m_Bids );

            foreach( Bid bid in bids )
            {
                if ( bid.Mobile == m )
                    return true;
            }

            return false;
        }

        /// <summary>
        /// Outputs relevant information about this auction
        /// </summary>
        public void Profile( StreamWriter writer )
        {
            writer.WriteLine( "ID : {0}", m_ID );
            writer.WriteLine( "Name : {0}", m_ItemName );

            if ( m_Owner != null && m_Owner.Account != null )
                writer.WriteLine( "Owner : {0} [ Account {1} - Serial {2} ]",
                    m_Owner.Name,
                    ( m_Owner.Account as Account ).Username,
                    m_Owner.Serial );
            else
                writer.WriteLine( "Owner : no longer existing" );

            writer.WriteLine( "Starting bid: {0}", m_MinBid );
            writer.WriteLine( "Reserve : {0}", m_Reserve );

            writer.WriteLine( "Created on {0} at {1}", m_StartTime.ToShortDateString(), m_StartTime.ToShortTimeString() );
            writer.WriteLine( "Duration: {0}", m_Duration.ToString() );
            writer.WriteLine( "End Time: {0} at {1}", m_EndTime.ToShortDateString(), m_EndTime.ToShortTimeString() );

            writer.WriteLine( "Expired : {0}", Expired.ToString() );
            writer.WriteLine( "Pending : {0}", Pending.ToString() );
            writer.WriteLine( "Next Deadline : {0} at {1}", Deadline.ToShortDateString(), Deadline.ToShortTimeString() );

            writer.WriteLine();

            if ( Creature )
            {
                writer.WriteLine( "** This auction is selling a pet" );

                // Pet
                if ( m_Item != null && Pet != null )
                {
                    writer.WriteLine( "Creature: {0}", Pet.Serial );
                    writer.WriteLine( "Statuette : {0}", m_Item.Serial );
                    writer.WriteLine( "Type : {0}", m_Item.Name );
                }
                else
                {
                    writer.WriteLine( "Pet deleted, this auction is invalid" );
                }
            }
            else
            {
                // Items
                writer.WriteLine( "{0} Items", m_Items.Length );

                foreach( ItemInfo item in m_Items )
                {
                    writer.Write( "- {0}", item.Name );

                    if ( item.Item != null )
                        writer.WriteLine( " [{0}]", item.Item.Serial );
                    else
                        writer.WriteLine( " [Deleted]" );
                }
            }

            writer.WriteLine();
            writer.WriteLine( "{0} Bids", m_Bids.Count );

            foreach ( Bid bid in m_Bids )
            {
                bid.Profile( writer );
            }

            writer.WriteLine();
        }

        /// <summary>
        /// Attempts to buy now
        /// </summary>
        /// <param name="m">The user trying to purchase</param>
        /// <returns>True if the item has been sold</returns>
        public bool DoBuyNow( Mobile m )
        {
            if ( !Banker.Withdraw( m, m_BuyNow ) )
            {
                m.SendMessage( AuctionConfig.MessageHue, AuctionSystem.ST[ 211 ] );
                return false;
            }

            AuctionSystem.Auctions.Remove( this );

            if ( HighestBid != null )
            {
                HighestBid.Outbid( this );
            }

            // Simulate bid
            Bid bid = new Bid( m, BuyNow );
            m_Bids.Insert( 0, bid );

            AuctionGoldCheck gold = new AuctionGoldCheck( this, AuctionResult.BuyNow );
            AuctionItemCheck item = new AuctionItemCheck( this, AuctionResult.BuyNow );

            GiveItemTo( m, item );
            GiveItemTo( m_Owner, gold );

            // Over.
            AuctionLog.WriteEnd( this, AuctionResult.BuyNow, m, null );

            return true;
        }

        /// <summary>
        /// Verifies if the eventual pets in this auction are gone
        /// </summary>
        public void VeirfyIntergrity()
        {
            foreach( ItemInfo ii in this.m_Items )
                ii.VeirfyIntegrity();
        }
    }
}
 
That error is because the 'StringList' it's looking for is from the old Ultima.dll that was replaced by OpenUO in favor for the newer client file support.

I'm sure OpenUO has some kind of support for reading the Clilocs built into it but I haven't looked into OpenUO at all. Will have to dig around in it and get back to you on that one. There are a couple alternatives still if not.
 
Yeah I'm not having any luck reading the clilocs with OpenUO. Maybe @Insanity or @Voxpire can shed some light on how to? I tried messing with the ClilocFactory in OpenUOSDK as well as some of the Adapters straight from the dll file but I seem to not be using them right. OpenUO needs documentation :)
 
Well, since I wrote the clilocs adapter for OpenUO, I think I can shed some light on it.


You create a new instance of the cliloc factory.
Then create a new instance of the Container (IContainer) provided by OpenUO.
Then create a new instance of the cliloc adapter and register the factory type with the container.
Then you can use the factory to retrieve cliloc info.

I'll write in more detail at some point, it's late right now :)

OpenUO is quite hard to get started with, gives me a slight headache remembering the correct logic to instantiate a new factory/adapter, lol.
 
Yeah I directed the question towards you because I seen you made the commit for the clillocs ;)

I'll play around with your instructions above. At least I have a starting point now. Just looking at it made no sense to me on what all was needed for it. I get that 'slight headache' too lol.
 
@Voxpire a proper example would be really nice when you get the time. I tried following what you said above but all I can do is bang my head on my keyboard.

That aside, I was able to load cliloc info using OpenUO doing this:
Code:
ClientLocalizations clientLocalizations = new ClientLocalizations();
clientLocalizations.Load(new FileInfo(OpenUOSDK.ClientDataPath + @"\Cliloc.enu"));
string clilocInfo = clientLocalizations.Lookup(myItem.LabelNumber).Text;
Now correct me if I'm wrong but couldn't I just create a static copy of ClientLocaliztions somewhere and reuse it for getting the clilocs like this? Seems like a much shorter route than creating all the above methods.
 
Clilocs are client files that store a bunch of text based on a number value. The client and server communicate using the number so less info is transfered and then use that number to look up the text.

Xanthos Auction System you are trying to use is using this info to get item names based off their cliloc number.
 
Oh WOW that is intense! I guess learning it is just something that I will have to do soon, would downloading the OpenUO help me learn it any?
 
Well it's not something that is used a lot for normal scripting needs. I'm sure Xanthos Auciton system could be redone in a different way that doesn't involve reading the clilocs and letting the client handle it instead. I don't know anything about the auction system though and don't plan to rewrite it. Just trying to come up with a simple fix to resolve the way it's setup now ;)

If you are interested in looking into OpenUO the source can be found here https://github.com/fdsprod/OpenUO
 
Well it's not something that is used a lot for normal scripting needs. I'm sure Xanthos Auciton system could be redone in a different way that doesn't involve reading the clilocs and letting the client handle it instead. I don't know anything about the auction system though and don't plan to rewrite it. Just trying to come up with a simple fix to resolve the way it's setup now ;)
If you are interested in looking into OpenUO the source can be found here https://github.com/fdsprod/OpenUO

Ahh I see, well I do eventually plan on being able to learn how to use the clilocs and what not, but for now I am just trying to learn C# to at least be able to fix/merge non-working scripts to ServUO for my shard.

I was downloading it as you posted it, I am looking through it now and I am just lost haha!

Thanks!
IanE
 
I am looking through it now and I am just lost haha!
Haha don't feel bad. I'm totally lost with it too. Just seems to go over my head with what's trying to go on there. So far my only luck is what I posted above, bypassing all the crazy stuff I don't understand and going straight for the class that handles the work I need.
 
Haha don't feel bad. I'm totally lost with it too. Just seems to go over my head with what's trying to go on there. So far my only luck is what I posted above, bypassing all the crazy stuff I don't understand and going straight for the class that handles the work I need.

HAHA yeah, it's not in super need of attention, I already have it Running on my RunUO core. I just came over to ServUO recently, and it seems to be better, just more things to learn. I will eventually have my whole server ServUO!
 
@IanE try this file I attached. I updated the code you posted at the top of the thread with my fix above. Should fix the auction system for you. Just let me know how it works out after you do some testing as I don't use that system.
 

Attachments

  • AuctionItem.cs
    48.8 KB · Views: 33
That may have worked, I get this when I put that in and debug in Visual Studio
Error 22 Cannot implicitly convert type 'System.DateTime' to 'long' ..\Scripts\Custom Systems\Xanthos\EVO System\Mercenary\Mercenary.cs 447 23 Scripts

Code:
        public void GrabItems( bool ignoreNoteriety )
        {
            ArrayList items = new ArrayList();
            bool rejected = false;
            bool lootAdded = false;

            Emote( "*Rummages through items on the ground.*" );

            foreach ( Item item in GetItemsInRange( 2 ) )
            {
                if ( item.Movable )
                    items.Add( item );
                else if ( item is Corpse )
                {    // Either criminally loot any corpses or loot only corpses that we have rights to
                    if ( ignoreNoteriety || NotorietyHandlers.CorpseNotoriety( this, (Corpse)item ) != Notoriety.Innocent )
                    {
                        Emote( "*Rummages through items in a corpse.*" );
                        foreach ( Item corpseItem in ((Corpse)item).Items )
                            items.Add( corpseItem );
                    }
                }
            }
            foreach ( Item item in items )
            {
                if ( !Backpack.CheckHold( this, item, false, true ) )
                    rejected = true;
                else
                {
                    bool isRejected;
                    LRReason reason;

                    NextActionTime = DateTime.Now;
                    Lift( item, item.Amount, out isRejected, out reason );

                    if ( !isRejected )
                    {
                        Drop( this, Point3D.Zero );
                        lootAdded = true;
                    }
                    else
                    {
                        rejected = true;
                    }
                }
            }
            if ( lootAdded )
                PlaySound( 0x2E6 ); //drop gold sound
            if ( rejected )
                Say( "I could not pick up all of the items." );
        }

Thanks a ton!
 
I'm confused. The auction system works? The Mercenary error is from my update or is that just another problem you are having with another script?
 
Well, most of the credit goes to the fix that @Kalamus did, my change just fixed an issue with the EVO system, his actually fixed the auction system.

You just thought it was me because that had to be fixed before your server compiled :)
 
Well, most of the credit goes to the fix that @Kalamus did, my change just fixed an issue with the EVO system, his actually fixed the auction system.
You just thought it was me because that had to be fixed before your server compiled :)

HAHA Don't worry I know I couldn't have done it with out you both, I was mainly confused as to why something I didn't even touch was messing up haha...

Why is it "Core.TickCount" now instead of "DateTime.Now" now?
 
Why is it "Core.TickCount" now instead of "DateTime.Now" now?

Voxpire was nice enough to post his conversation with Mark about this over on RunUO forums. Good stuff. Thanks @Voxpire
[21:39:07] (Voxpire) Mark_ what actual unit of time does Core.TickCount represent?
[22:13:27] (@Mark_) its unitless
[22:13:32] (@Mark_) well
[22:13:36] (@Mark_) i should say
[22:13:39] (@Mark_) theres no point of reference
[22:13:40] (@Mark_) its milliseconds
[22:13:51] (@Mark_) they arent directly comparable from system to system
[22:13:55] (@Mark_) its basically the system uptime
[22:15:26] (Voxpire) ahh ok
[22:16:49] (Voxpire) just that timestamp thing i mentioned, i seem to be having issues with it converting Core.TickCount to relative time
[22:17:12] (@Mark_) its only useful for counting elapsed time
[22:17:28] (@Mark_) its faster and higher resolution compared to datetime.now though
[22:17:32] (@Mark_) but its only useful for short intervals
[22:17:35] (@Mark_) not serialized things
[22:17:49] (@Mark_) the problem with datetime.utcnow is that daylight savings changes and such completely ruin a shard
[22:17:53] (@Mark_) or if someone sets the system time
[22:18:01] (Voxpire) i'm using it to detect the time between UtcNow and Spell.BeginCastTime
[22:18:14] (Voxpire) in order to find elapsed time
[22:19:44] (@Mark_) its useless compared to utcnow
[22:19:47] (Voxpire) but I'm trying to use a timeStamp as a mediator between RunUO where things like Spell.BeginCastTime are either DateTime or Int64
[22:19:58] (@Mark_) not possible to have a 1:1 correlation
[22:20:14] (@Mark_) datetime.utcnow is the actual system time, timestamp is the system uptime
[22:20:50] (@Mark_) the system time has things like ntp gradually tweaking the time, etc
[22:20:59] (@Mark_) someone manually setting the system time, etc
[22:21:12] (@Mark_) changing to utcnow fixes the daylight savings/timezone change issue but the system clock is still a bad reference for an application
[22:21:15] (Voxpire) i'm using a custom TimeStamp struct which represents a Unix TimeStamp, seconds since jan 1 1970
[22:21:24] (@Mark_) but why?
[22:21:31] (@Mark_) C# DateTime is seconds since 0000
[22:21:32] (@Mark_) err
[22:21:34] (@Mark_) ticks
[22:21:47] (@Mark_) and tickcount is referenceless, its ticks since uptime
[22:22:06] (@Mark_) but theres other caveats
[22:22:20] (@Mark_) like
[22:22:26] (@Mark_) are you trying to write a script thats agnostic from 2.3 to 2.4?
[22:22:40] (Voxpire) overall, so I can do new TimeStamp(Spell.BeginCastTime) where on RunUO 2.3 it's DateTime and in RunUO 2.4+ it's Int64
[22:22:42] (Voxpire) yeah
[22:23:05] (@Mark_) you could detect which is which
[22:23:12] (@Mark_) based on the size of the long
[22:23:21] (@Mark_) utcnow is going to be a significantly larger number
[22:23:31] (Voxpire) about 6 0's bigger i think
[22:23:42] (@Mark_) i mean this is really really hackish
[22:23:45] (@Mark_) and many pitfalls
[22:23:45] (@Mark_) but
[22:23:50] (@Mark_) you could pull the system startup time
[22:23:56] (@Mark_) and perhaps subtract utcnow from that
[22:23:58] (@Mark_) convert to ms
[22:24:02] (@Mark_) and compare with tickcount
[22:24:19] (Voxpire) that's how you made the timers work with tickcount isn't it? :D
[22:26:56] (@Mark_) no
[22:27:20] (@Mark_) i just fixed the few spots where someone was using the next firing time in a script i think
[22:27:28] (@Mark_) anyway
[22:27:35] (@Mark_) wouldnt it just be easier if i made an option
[22:27:44] (@Mark_) so people could use datetime.utcnow for tickcount instead
[22:27:53] (@Mark_) dunno
[22:28:27] (Voxpire) hmm i'm not sure
[22:31:13] (Voxpire) basically what i'm trying to do is create a progress bar that has current and maximum value and I figured I could use time as the relative reference like, the current value will always represent DateTime.Now and the max value would be Spell.BeginCastTime + Spell.GetCastDelay(), which would be fine if Spell.BeginCastTime was a datetime
[22:32:01] (Voxpire) the bar is refreshed every 100ms too, so current value would increment by 100
[22:32:05] (@Mark_) err
[22:32:15] (@Mark_) yea id just detect what value was being used
[22:32:27] (@Mark_) and either do castdelay - tickcount or castdelay - now based on that
[22:32:37] (@Mark_) using two different references, just determine which to use
[22:33:01] (Voxpire) got it, thanks :) i'll go mess with that now
[22:33:14] (Voxpire) i didn't think of that before so will probably work hehe
[22:33:48] (@Mark_) core.tickcount will error on compile
[22:33:54] (Voxpire) the part that makes it hard is that I can't directly reference Core.TickCount, otherwise there's be no issues
[22:33:55] (Voxpire) yeah
[22:33:55] (@Mark_) makes things tricky too
[22:33:59] (@Mark_) yea
[22:35:22] (@Mark_) since you're heavily modding though could always just add another variable yourself
[22:37:17] (Voxpire) i have limitations, this progress bar is actually an animated gump that displays the spell you're currently casting, i've written it in the form of a CoreModule for Vita-Nex: Core so it can be drag/drop with no edits, so I have those limitations too, that's also why I want to support all RunUO versions as much as possible :)
[22:38:50] (Voxpire) i assumed because of the way core.tickcount was implemented that it repreneted DateTime.UtcNow (in ticks) at any given time it was accessed.
[22:39:11] (Voxpire) i was wrong of course :p
[22:39:17] (@Mark_) thats the fallback for mono
[22:39:34] (@Mark_) but the whole point of doing tickcount was to move away from system clock dep
[22:40:15] (Voxpire) ahh, i thought it was to reduce the overhead of using DateTime.*Now
[22:40:53] (Voxpire) like, I thought the initial value of TickCount was DateTime.UtcNow.Ticks, then the system just increased that relative thereafter
[22:41:40] (@Mark_) datetime.utcnow is actually faster than queryperformancecounter
[22:41:52] (@Mark_) datetime.now is 3x slower than datetime.utcnow
[22:42:14] (@Mark_) qpc isnt that much slower than datetime.utcnow though
[22:44:08] (Voxpire) i think the easy road for this would be to just assume the start cast delay as DateTime.UtcNow as soon as the SpellCastRequest event is fired and the user's spell changes value
[22:44:40] (@Mark_) good idea
[22:44:53] (Voxpire) the cast bar doesn't have to be totally accurate to the nanosecond hehe
[22:44:54] (@Mark_) close enough to not matter at least
[22:44:57] (Voxpire) yeah
[22:45:05] (@Mark_) those timers are only good to a ms or so anyway
[22:45:59] (Voxpire) the fastest timer I use is 10ms, which is actually the timer I use to poll the queue for cast bar requests hehe
[22:46:24] (Voxpire) spell request -> bar queue -> dequeue -> handle request -> send gump
[22:46:57] (Voxpire) since the core updates, they have been much more efficient
[22:47:04] (@Mark_) nice

Edit: Well Insanity beat me to it above. He just summed it up nicely.
 
This system was working, however, an entry in the Assemblies.cfg file has been removed and it is also not found in the Ultima.dll file anymore, breaking the system. Unless someone goes through and rewrites this system to work without this entry, its not going to work with the latest ServUO release and likely the latest RunUO as well.
 
here is the complete Xanthos auction We are using it for the savings account everthing in it works but when You put a item on auction it has invalid propertys in the gump list has anybody messed with updating this ?? I struggle at scriptin and understanding them reading and looking for a fix best option I could find was to go to AOS which is not a option for Us,,, is there a simple work around to get the propertys to show ????
 

Attachments

  • Auction System.zip
    76.9 KB · Views: 10
I have been away for quite some time, I am in the middle of moving. In about a month or so I plan to revisit all of the scripts I have posted and see if they are still working and try to fix what isn't.

I also took a break because for the refactoring of the ServUO files. If I should still wait someone let me know please :p
 
I have been away for quite some time, I am in the middle of moving. In about a month or so I plan to revisit all of the scripts I have posted and see if they are still working and try to fix what isn't.

I also took a break because for the refactoring of the ServUO files. If I should still wait someone let me know please :p
I believe the structure in the latest repo, is the way it's going to be, but don't quote me, as I'm not one of the Devs. I can say that, like you, I've got quite a few older scripts and they depend on the old Ultima.dll, which is hard to find (someone did upload it to ServUO though!). For whatever reason, some things were left out of the next Ultima.dll version. My plan is to try and merge together a new dll, so it includes all the things that were left out.
 
that would be awesome I can help with something not sure what tho maybe testing or something :) Ive never realy messed with a DLL file
 
I haven't done much with dlls or even looked too much into the Ultimate.dll, but I will be reading a lot while I am away from the computer. Maybe I will have learned enough to help.

Or maybe you will have finished it already, either way...
 
Back