Full Version : Auction Script Help
xmlspawner >>Scripting Support >>Auction Script Help
<< Prev | Next >>
Haazen- 07-29-2006
Can anyone see the probelm in this script. It seems to work fine and can even add items to the suction system. Buy and sell and bid. But as soon as we reboot, the AuctionControl has errors loading saved item and so it gets deleted. My suspiscion is the the count numbers are wrong and therefore loading the arrays are the error. But please just look and see if there is some other syntax or coding error I am missing. This system worked for a very long time on version 1.0. It's just on 2.0 where I get the errors.

CODE
#region AuthorHeader // // Auction version 1.16, by Xanthos and Arya // // Based on original ideas and code by Arya
//
#endregion AuthorHeader
using System;
using System.Collections;
using Server;
namespace Arya.Auction
{
/// <summary>
/// This is the auction control stone. This item should NOT be deleted
/// </summary>
public class AuctionControl : Item
{
/// <summary>
/// This item holds all the current auctions
/// </summary>
private ArrayList m_Auctions;
/// <summary>
/// This lists all auctions whose reserve hasn't been met
/// </summary>
private ArrayList m_Pending;
/// <summary>
/// Flag used to force the deletion of the system
/// </summary>
private bool m_Delete = false;
/// <summary>
/// The max number of concurrent auctions for each account
/// </summary>
private int m_MaxAuctionsParAccount = 5;
/// <summary>
/// The minimum number of days an auction must last
/// </summary>
private int m_MinAuctionDays = 1;
/// <summary>
/// The max number of days an auction can last
/// </summary>
private int m_MaxAuctionDays = 14;
/// <summary>
/// Gets or sets the list of current auction entries
/// </summary>
public ArrayList Auctions
{
get { return m_Auctions; }
set { m_Auctions = value; }
}
/// <summary>
/// Gets or sets the pending auction entries
/// </summary>
public ArrayList Pending
{
get { return m_Pending; }
set { m_Pending = value; }
}
[ CommandProperty( AccessLevel.GameMaster, AccessLevel.Administrator ) ]
/// <summary>
/// Gets or sets the max number of auctions a single account can have
/// </summary>
public int MaxAuctionsParAccount
{
get { return m_MaxAuctionsParAccount; }
set { m_MaxAuctionsParAccount = value; }
}
[ CommandProperty( AccessLevel.GameMaster, AccessLevel.Administrator ) ]
/// <summary>
/// Gets or sets the minimum days an auction must last
/// </summary>
public int MinAuctionDays
{
get { return m_MinAuctionDays; }
set { m_MinAuctionDays = value; }
}
[ CommandProperty( AccessLevel.GameMaster, AccessLevel.Administrator ) ]
/// <summary>
/// Gets or sets the max number of days an auction can last
/// </summary>
public int MaxAuctionDays
{
get { return m_MaxAuctionDays; }
set { m_MaxAuctionDays = value; }
}
public AuctionControl() : base( 4484 )
{
Name = "Auction System";
Visible = false;
Movable = false;
m_Auctions = new ArrayList();
m_Pending = new ArrayList();
AuctionSystem.ControlStone = this;
}
public AuctionControl( Serial serial ) : base( serial )
{
m_Auctions = new ArrayList();
m_Pending = new ArrayList();
}
#region Serialization
public override void Serialize(GenericWriter writer)
{
base.Serialize (writer);
writer.Write( (int) 1 ); // Version
// Version 1 : changes in AuctionItem
// Version 0
writer.Write( m_MaxAuctionsParAccount );
writer.Write( m_MinAuctionDays );
writer.Write( m_MaxAuctionDays );
writer.Write( m_Auctions.Count );
foreach( AuctionItem auction in m_Auctions )
{
auction.Serialize( writer );
}
writer.Write( m_Pending.Count );
foreach( AuctionItem auction in m_Pending )
{
auction.Serialize( writer );
}
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize (reader);
int version = reader.ReadInt();
switch ( version )
{
case 1:
case 0:
m_MaxAuctionsParAccount = reader.ReadInt();
m_MinAuctionDays = reader.ReadInt();
m_MaxAuctionDays = reader.ReadInt();
int count = reader.ReadInt();
for ( int i = 0; i < count; i++ )
{
m_Auctions.Add( AuctionItem.Deserialize( reader, version ) );
}
count = reader.ReadInt();
for ( int i = 0; i < count; i++ )
{
m_Pending.Add( AuctionItem.Deserialize( reader, version ) );
}
break;
}
AuctionSystem.ControlStone = this;
}
#endregion
public override void OnDelete()
{
// Don't allow users to delete this item unless it's done through the control gump
if ( !m_Delete )
{
AuctionControl newStone = new AuctionControl();
newStone.m_Auctions.AddRange( this.m_Auctions );
newStone.MoveToWorld( this.Location, this.Map );
newStone.Items.AddRange( Items );
Items.Clear();
foreach( Item item in newStone.Items )
{
item.Parent = newStone;
}
newStone.PublicOverheadMessage( Server.Network.MessageType.Regular, 0x40, false, AuctionSystem.ST[ 121 ] );
}
base.OnDelete ();
}
/// <summary>
/// Deletes the item from the world without triggering the auto-recreation
/// This function also closes all current auctions
/// </summary>
public void ForceDelete()
{
m_Delete = true;
Delete();
}
public override void GetProperties(ObjectPropertyList list)
{
base.GetProperties (list);
list.Add( AuctionSystem.Running ? 3005117 : 3005118 ); // [Active] - [Inactive]
}
}
}

Thank you for viewing my post.
ArteGordon- 07-30-2006
I think you need to post the AuctionItem script as well since that is probably where the problem is.
Haazen- 07-31-2006
Here is AuctionItem.

CODE
#region AuthorHeader // // Auction version 1.16, by Xanthos and Arya // // Based on original ideas and code by Arya
//
#endregion AuthorHeader
using System;
using System.Collections;
using System.IO;
using System.Text.RegularExpressions;
using 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;
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()
{
string clilocFolder = null;
if ( AuctionConfig.ClilocLocation != null )
{
clilocFolder = Path.GetDirectoryName( AuctionConfig.ClilocLocation );
Ultima.Client.Directories.Insert( 0, clilocFolder );
}
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 = 1000;
private int m_Reserve = 2000;
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
#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 10;
if ( m_MinBid <= 500 )
return 20;
if ( m_MinBid <= 1000 )
return 50;
if ( m_MinBid <= 5000 )
return 100;
if ( m_MinBid <= 10000 )
return 200;
if ( m_MinBid <= 20000 )
return 250;
if ( m_MinBid <= 50000 )
return 500;
return 1000;
}
}
[ 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 )
{
if ( Pet != null && Pet.CanBeControlledBy( m ) )
return true;
else
return false;
}
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 )
{
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
}
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.ForceDelete();
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
AuctionLog.WriteEnd( this, AuctionResult.Succesful, m, null );
}
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
AuctionMessag

ArteGordon- 07-31-2006
where are m_Auctions and m_Pending initialized?
Haazen- 07-31-2006
I should have posted the whole script in the first post. I have edited the post so now it is the whole script. Thx. Not sure it is needed but I added the whoel set of scripts.