/**
* Auction Room Inheritable
* This room will give you everything you need to make an auction
* room.
* @author Terano
* @started 3 October, 1998
* @changed 24 March, 1999 Many exciting things. Terano.
*/
#include <money.h>
#include <move_failures.h>
#include <mail.h>
#define CASE "/obj/misc/case"
#define LOT_ID "lot number"
#define COLOUR_ID "colour code"
#define AUCTION_PLAYER_NAME 0
#define AUCTION_PLAYER_BID 1
#define COLOURS ({ "red", "orange", "yellow", "blue", "green", "indigo",\
"violet", "crimson", "puce", "emerald", "ochre", "tangerine", "aquamarine",\
"silver", "gold", "copper", "lilac" })
#define NO_COLOURS sizeof( COLOURS )
nosave inherit ROOM_OBJ; //Why save all those evil room variables?
inherit "/global/player/auto_load";
class lot_details {
string seller;
int expiration_time;
int reserve_price;
mapping bids;
int lot_id;
mixed *lot_autoload;
mixed *current_bid;
string *auto_bids;
string desc;
}
class lot_details *lots = ({ }); //Array of lots
class lot_details *expired_lots = ({ });
mapping payments = ([ ]); //Stored as ([ "name": amount ]);
int lot_count;
nosave string *used_colours = ({ });
nosave string currency = "default";
nosave string location;
nosave string *case_desc = ({ });
nosave object *cases = ({ });
nosave int admin_cost = 2000; //defaults to AM$5
nosave float commission = ( 5.0/100.0 ); //Default to 5%
void save_file();
void load_file();
void load_inv();
void set_location( string loc );
void set_currency( string cur );
void set_admin_cost( int value );
void set_commission( int percent );
void set_case_desc( string *bits );
int do_deposit( object *things, int auction_time, string time_type,
string res_price );
int do_bid( string offer, object *boxes );
int do_collect( string pattern );
int do_list();
int do_withdraw( object *cases );
int do_describe( object *cases, string int_desc );
void remove_lot( object _case );
void end_auction( string name, object *items, int cost,
string location, int status );
void adjust_money( int amount, object player );
mixed *query_min_bid( object _case );
void check_lots();
void create() {
do_setup++;
::create();
do_setup--;
if ( !do_setup ) {
TO->setup();
TO->reset();
}
add_extra_look( TO );
call_out( "load_file", 1 ); //To give time for location data to be restored
call_out( "load_inv", 2 ); //To give time for save data to be restored
call_out( "check_lots", 5 );
}
void init() {
TP->add_command( "bid", TO,
"<string> {on|for} <indirect:object:here>",
(: do_bid( $4[0], $1 ) :) );
TP->add_command( "collect", TO,
({ "successful bids", "money", "expired lots",
"all" }),
(: do_collect( $5 ) :) );
TP->add_command( "deposit", TO,
"<indirect:object:me> for <number> "
"{minute|hour|day} auction" ,
(: do_deposit( $1, $4[1], $4[2], "" ) :) );
TP->add_command( "deposit", TO,
"<indirect:object:me> for <number> "
"{minute|hour|day} "
"auction with [a] reserve price of <string>",
(: do_deposit( $1, $4[1], $4[2], $4[3] ) :) );
TP->add_command( "list", TO, "" );
TP->add_command( "withdraw", TO,
"<indirect:object> from auction",
(: do_withdraw( $1 ) :) );
TP->add_command( "scrawl", TO,
"<string> on <indirect:object>",
(: do_describe( $1, $4[0] ) :) );
}
/**
* This function allows an object to deposit an item for auction,
* Things are the items to auction, auction length is the length in seconds,
* function_cb and object_cb are function names and object paths to allow a
* call back to be scheduled for when the auction is over, res price is
* the reserve price and int_desc is a description that will be written on
* the case.
*/
int automated_deposit( object *things, int auction_length,
string function_cb, string object_cb,
int res_price, string int_desc ) {
string colour;
object box;
class lot_details temp;
string *avail_colours = COLOURS - used_colours;
if ( !sizeof( avail_colours ) )
return -1; //No Space
if ( !sizeof( things ) || auction_length < 0 )
return -2; //Invalid Param
if ( !objectp( load_object( object_cb ) ) )
return -3; //Invalid callback ob
colour = avail_colours[ random( sizeof( avail_colours ) ) ];
lot_count ++;
box = clone_object( CASE );
box->add_property( LOT_ID, lot_count );
box->add_property( COLOUR_ID, colour );
things->move( box );
box->add_adjective( colour );
temp = new( class lot_details, seller: "Auto", reserve_price: res_price,
expiration_time: time() + auction_length, bids: ([ ]),
lot_id: lot_count, current_bid: allocate( 2 ),
lot_autoload: create_auto_load( ({ box }), 0 ),
auto_bids: ({ function_cb, object_cb }), desc: int_desc );
lots += ({ temp });
box->move( TO );
box->add_extra_look( TO );
box->add_property( "there", "sitting in the center of the room" );
box->set_short( colour + " case" );
cases += ({ box });
if ( sizeof( case_desc ) ) box->setup_case( case_desc );
return lot_count;
}//End automated_deposit
int do_deposit( object *things, int auction_time,
string time_type, string res_price ) {
string *avail_colours = COLOURS - used_colours;
string colour;
object *auctioned = ({ });
object *unauctionable = ({ });
object box;
class lot_details temp;
int finishtime, value = 0;
if ( auction_time <= 0 || ( time_type == "day" && auction_time > 10 )
|| ( time_type == "minute" && auction_time > 59 ) ||
( time_type == "hour" && auction_time > 23 ) ) {
TP->add_failed_mess( TO,
"That's not a valid length.\n" );
return 0;
}
if ( sizeof( res_price ) ) {
value = MONEY_HAND->value_from_string( res_price, currency );
if ( value == 0 ) {
TP->add_failed_mess( TO,
res_price +" isn't a valid reserve price.\n" );
return 0;
}
}
if ( !sizeof( avail_colours ) ) {
TP->add_failed_mess( TO, "The auction house "
"doesn't have any display cases left to auction your item.\n" );
return 0;
}
colour = avail_colours[ random( sizeof( avail_colours ) ) ];
switch( time_type ) {
case "minute":
finishtime = time() + ( auction_time * 60 );
break;
case "hour":
finishtime = time() + ( auction_time * 60 * 60 );
break;
case "day":
finishtime = time() + ( auction_time * 60 * 60 * 24 );
break;
default:
return 0;
}
box = clone_object( CASE );
auctioned = filter_array( things,
(: $1->move( $(box) ) == MOVE_OK :) );
unauctionable = things - auctioned;
if ( sizeof( unauctionable ) ) {
auctioned->move( TP );
TP->add_failed_mess( TO,
"You can't $V $I.\n", unauctionable );
return 0;
}
lot_count ++;
used_colours += ({ colour });
box->add_property( LOT_ID, lot_count );
box->add_property( COLOUR_ID, colour );
temp = new( class lot_details, seller: TP->query_name(),
reserve_price: value, expiration_time: finishtime,
bids: ([ ]), lot_id: lot_count, current_bid: allocate( 2 ),
lot_autoload: create_auto_load( ({ box }), 0 ),
auto_bids: ({ }), desc: "" );
lots += ({ temp });
box->move( TO );
box->add_extra_look( TO );
box->add_property("there", "sitting in the center of the room");
box->set_short( colour + " case" );
box->add_adjective( colour );
cases += ({ box });
if ( sizeof( case_desc ) ) box->setup_case( case_desc );
save_file();
if ( strlen( res_price ) )
TP->add_succeeded_mess( TO, "$N $V $I for "+
add_a( query_num( auction_time, 5000 ) ) + " " + time_type +
" auction, with a reserve price of "+
MONEY_HAND->money_value_string( value, currency ) +".\n",
auctioned );
else
TP->add_succeeded_mess( TO, "$N $V $I for a "+
query_num( auction_time, 5000 ) + " " + time_type +
" auction, with no reserve price.\n", auctioned );
return 1;
}
int do_list() {
object _case;
if ( !sizeof( cases ) ) {
TP->add_failed_mess( TO, "There are "
"no cases to peruse at the moment.\n" );
return 0;
}
printf( "Items currently for auction:\n" );
foreach( _case in cases ) {
if ( !objectp( _case ) ) continue;
printf( " %s: %s.\n", capitalize( _case->query_short() ),
capitalize("/global/events"->convert_message(
query_multiple_short(all_inventory( _case ) ) ) ) );
}
return 1;
}
int do_bid( string offer, object *boxes ) {
object box;
int value, temp_lot_id;
class lot_details *filtered_lots;
class lot_details current_lot;
if ( sizeof( boxes ) > 1 ) {
TP->add_failed_mess( TO,
"You can only $V on one case at "
"a time.\n" );
return 0;
}
box = boxes[0];
if ( member_array( box, cases ) == -1 ) {
TP->add_failed_mess( TO,
"$I isn't being auctioned here.\n", ({ box }) );
return 0;
}
temp_lot_id = box->query_property( LOT_ID );
filtered_lots = filter( lots, (: $1->lot_id == $(temp_lot_id) :) );
if ( sizeof( filtered_lots ) != 1 ) {
printf( "Please inform a creator, there are %d records to "
"match this case.\n", sizeof( filtered_lots ) );
return 1;
}
current_lot = filtered_lots[0];
if ( time() > current_lot->expiration_time ) {
TP->add_failed_mess(TO,
"The bidding on this item is finished.\n" );
return 0;
}
value = MONEY_HAND->value_from_string( offer, currency );
if ( value == 0 ) {
TP->add_failed_mess( TO,
offer +" isn't worth anything here.\n" );
return 0;
}
if ( TP->query_value_in( currency ) < value ) {
TP->add_failed_mess( TO, "You don't "
"have that much.\n" );
return 0;
}
if ( current_lot->reserve_price != 0 &&
value < current_lot->reserve_price ) {
TP->add_failed_mess( TO,
"The reserve price for this lot is "+
MONEY_HAND->money_value_string(
current_lot->reserve_price,
currency ) +".\n" );
return 0;
}
if ( sizeof( current_lot->current_bid ) &&
current_lot->current_bid[ AUCTION_PLAYER_BID ] >= value ) {
TP->add_failed_mess(TO,
"Someone else has already bid more than "
"that.\n");
return 0;
}
if ( sizeof( current_lot->current_bid ) &&
( ( value - current_lot->current_bid[ AUCTION_PLAYER_BID ] ) <
( current_lot->current_bid[ AUCTION_PLAYER_BID ] / 20 ) ) ) {
TP->add_failed_mess( TO, "You must bid 5% "
"more then the current bid.\n" );
return 0;
}
current_lot->bids[ TP->query_name() ] = value;
current_lot->current_bid[0] = TP->query_name();
current_lot->current_bid[1] = value;
TP->add_succeeded_mess(TO, "$N $V "+ offer +" for "+
query_multiple_short(all_inventory(box)) +
".\n" );
save_file();
return 1;
}
mixed *query_bid_info( object _case ) {
int temp_lot_id;
class lot_details *filtered_lots;
if ( member_array( _case, cases ) == -1 )
return 0;
temp_lot_id = _case->query_property( LOT_ID );
filtered_lots = filter( lots, (: $1->lot_id == $(temp_lot_id) :) );
if ( sizeof( filtered_lots ) != 1 )
return 0;
return ({ ( ( filtered_lots[0]->current_bid[ AUCTION_PLAYER_BID ] ) ?
filtered_lots[0]->current_bid[ AUCTION_PLAYER_BID ] :
filtered_lots[0]->reserve_price ), currency,
filtered_lots[0]->expiration_time - time() });
}
void adjust_money( int amount, object player ) {
object money;
if ( amount < 0 ) { //Taking money
player->pay_money(MONEY_HAND->create_money_array(-amount, currency ));
return;
}
money = MONEY_HAND->create_money_array( amount, currency );
player->adjust_money( money, currency );
}
void load_file() {
if ( !stringp( location ) ) return;
if ( file_size( location +".o" ) < 0 ) return;
unguarded( (: restore_object, location :) );
return;
}
void save_file() {
if ( !stringp( location ) ) return;
unguarded( (: save_object, location :) );
return;
}
void check_lots() {
object _case;
mixed *info;
call_out( "check_lots", 60 );
if ( !sizeof( cases ) ) return;
foreach( _case in cases ) {
info = query_bid_info( _case );
if ( !arrayp( info ) || info[2] < 0 )
remove_lot( _case );
}
}
/**
* Function that is called when bidding expires on an item,
* mask it if you want to do something interesting.
* Remember to put in ::remove_lot though, otherwise auctions will not end!
*/
void remove_lot( object _case ) {
class lot_details *temp_lots, lot;
int temp_lot_id = _case->query_property( LOT_ID );
cases -= ({ _case });
temp_lots = filter( lots, (: $1->lot_id == $(temp_lot_id) :) );
foreach( lot in temp_lots ) { //Do call backs on auto items
if ( sizeof( lot->auto_bids ) ) {
call_other( lot->auto_bids[1], lot->auto_bids[0], temp_lot_id,
stringp( lot->current_bid[ AUCTION_PLAYER_NAME ] ), lot->current_bid[ AUCTION_PLAYER_NAME ], all_inventory( _case ) );
}
}
end_auction( ( sizeof( lot->current_bid[ AUCTION_PLAYER_NAME ] ) ?
lot->current_bid[ AUCTION_PLAYER_NAME ] :
lot->seller ),
all_inventory(_case ),
lot->current_bid[ AUCTION_PLAYER_BID ],
query_short(),
stringp( lot->current_bid[ AUCTION_PLAYER_NAME ] ) );
lots -= temp_lots;
if ( lot->seller != "Auto" && !stringp( lot->current_bid[ AUCTION_PLAYER_NAME ] ) )
expired_lots += temp_lots;
call_out( (: $(_case)->dest_me() :), 2 );
}
string extra_look( object ob ) {
class lot_details temp, *temp2;
mixed bid_info;
string ret;
int temp_lot_id;
if ( member_array( ob, cases ) == -1 ) return "";
temp_lot_id = ob->query_property( LOT_ID );
temp2 = filter( lots, (: $1->lot_id == $(temp_lot_id) :) );
if ( sizeof( temp2 ) != 1 ) return "Not found in lot array!\n";
temp = temp2[0];
bid_info = temp->current_bid;
ret = "";
if ( !stringp( bid_info[ AUCTION_PLAYER_NAME ] ) ) {
if ( temp->reserve_price ) {
ret += "Reserve price is: ";
ret += MONEY_HAND->money_value_string( temp->reserve_price, currency
);
ret += ".\n";
}
else
ret += "No bid as of yet.\n";
}
else
ret += "The current bid is "+ MONEY_HAND->money_value_string(
bid_info[1],
currency ) +
", made by "+ capitalize( bid_info[ AUCTION_PLAYER_NAME ] ) +".\n";
ret += "The bidding on this lot stops at "+ mudtime( temp->expiration_time )+
".\n";
if ( sizeof( temp->desc ) ) {
ret += "Neatly lettered on the case is: ";
ret += temp->desc;
ret += ".\n";
}
return ret;
}
void load_inv() {
class lot_details temp_lot;
object _case;
string colour;
if ( !sizeof( lots ) ) return;
foreach( temp_lot in lots ) {
if ( temp_lot->expiration_time < time() ) {
expired_lots += ({ temp_lot });
lots -= ({ temp_lot });
continue;
}
cases += load_auto_load_to_array( temp_lot->lot_autoload, TP );
}
foreach( _case in cases ) {
colour = _case->query_property( COLOUR_ID );
_case->add_adjective( colour );
_case->set_short( colour + " case" );
_case->add_property( "there", "sitting in the center of the room" );
used_colours += ({ colour });
}
call_out( (: cases->add_extra_look( TO ) :), 2 );
call_out( (: cases->move( TO ) :), 2 );
}
void dest_me() {
save_file();
if ( sizeof( cases ) ) cases->dest_me();
::dest_me();
}
void set_save_path( string path ) { location = path; }
void set_currency( string cur ) { currency = cur; }
void set_admin_cost( int value ) { admin_cost = value; }
void set_commission( int percent ) { commission = percent/100.0; }
void set_case_desc( string *bits ) { case_desc = bits; }
class lot_details *query_lots() { return lots; }
class lot_details *query_expired_lots() { return expired_lots; }
mapping query_payments() { return payments; }
int do_collect( string pattern) {
int amount;
class lot_details lot_pending, *lots_pending = ({ });
object box, *boxes = ({ }), *items = ({ }), itemsnomove;
string *names = ({ });
if ( pattern == "all" ) {
do_collect( "money" );
do_collect( "successful bids" );
do_collect( "expired lots" );
return 1;
}
if ( pattern == "money" ) {
lots_pending = filter( expired_lots, (: ( $1->seller == $2 ) && (
stringp( $1->current_bid[ AUCTION_PLAYER_NAME ] ) ) :),
TP->query_name() );
if ( undefinedp( payments[ TP->query_name() ] ) ) {
if ( sizeof( lots_pending ) ) {
foreach( class lot_details tempy in lots_pending ) { names += ({
tempy->current_bid[ AUCTION_PLAYER_NAME ] }); }
write( query_multiple_short( names ) +
" must pay for the items they bid on before you can collect "
"the money for them!\n" );
return 0;
}
}
if ( undefinedp( payments[ TP->query_name() ] ) ) {
TP->add_failed_mess( TO,
"You aren't owed any money.\n" );
return 0;
}
amount = payments[ TP->query_name() ];
adjust_money( amount - to_int( amount * commission ), TP );
printf( "You recieve %s, minus %s commission.\n",
MONEY_HAND->money_value_string( amount, currency ),
MONEY_HAND->money_value_string( to_int( amount * commission ),
currency ) );
map_delete( payments, TP->query_name() );
TP->add_succeeded_mess( TO, "$N $V some money from $D.\n" );
save_file();
return 1;
}
if ( pattern == "successful bids" ) {
//Items that have expired with the player as the current bid,
lots_pending = filter( expired_lots,
(: $1->current_bid[ AUCTION_PLAYER_NAME ] == $2 :),
TP->query_name() );
if ( !sizeof( lots_pending ) ) {
TP->add_failed_mess( TO,
"You aren't expecting any items.\n" );
return 0;
}
foreach( lot_pending in lots_pending )
amount += lot_pending->current_bid[ 1 ];
if ( TP->query_value_in( currency ) < amount ) {
printf( "You have %d %s waiting, for a total cost of %s.\n"
"You don't have enough money.\n",
sizeof( lots_pending ),
sizeof( lots_pending ) > 1 ? "lots" : "lot",
MONEY_HAND->money_value_string( amount, currency ) );
TP->add_failed_mess( TO, "" );
return 0;
}
adjust_money( -amount, TP );
foreach( lot_pending in lots_pending ) {
boxes += load_auto_load_to_array( lot_pending->lot_autoload,
TP );
if ( undefinedp( payments[ lot_pending->seller ] ) )
payments[ lot_pending->seller ] =
lot_pending->current_bid[ AUCTION_PLAYER_BID ];
else
payments[ lot_pending->seller ] +=
lot_pending->current_bid[ AUCTION_PLAYER_BID ];
expired_lots -= ({ lot_pending });
}
foreach( box in boxes )
items += all_inventory( box );
printf( "You collect %s.\n", query_multiple_short( items ) );
itemsnomove = filter( items, (: $1->move( TP ) != MOVE_OK :)
);
if ( sizeof( itemsnomove ) ) {
printf( "Unfortunately, you couldn't carry %s and it was left "
"on the floor for you.\n",
query_multiple_short( itemsnomove ) );
itemsnomove->move( TO );
}
printf( "You had %d %s waiting, for a total cost of %s.\nYou "
"hand over the money.\n",
sizeof( lots_pending ),
sizeof( lots_pending ) > 1 ? "lots" : "lot",
MONEY_HAND->money_value_string( amount, currency ) );
return 1;
}
if ( pattern == "expired lots" ) {
//Items that have expired with the player as the current bid,
lots_pending = filter( expired_lots,
(: !stringp( $1->current_bid[ AUCTION_PLAYER_NAME ] ) && $1->seller == $2 :),
TP->query_name() );
if ( !sizeof( lots_pending ) ) {
TP->add_failed_mess( TO, "You aren't expecting "
"any items.\n" );
return 0;
}
amount = admin_cost * sizeof( lots_pending );
if ( TP->query_value_in( currency ) < amount ) {
printf( "You have %d %s waiting, for a total administration "
"cost of %s.\n"
"You don't have enough money.\n",
sizeof( lots_pending ),
sizeof( lots_pending ) > 1 ? "lots" : "lot",
MONEY_HAND->money_value_string( amount, currency ) );
return 0;
}
adjust_money( -amount, TP );
foreach( lot_pending in lots_pending ) {
boxes += load_auto_load_to_array( lot_pending->lot_autoload, TP );
expired_lots -= ({ lot_pending });
}
foreach( box in boxes )
items += all_inventory( box );
printf( "You collect %s.\n", query_multiple_short( items ) );
itemsnomove = filter( items, (: $1->move( TP ) != MOVE_OK :)
);
if ( sizeof( itemsnomove ) ) {
printf( "Unfortunately, you couldn't carry %s and it was "
"left on the floor for you.\n",
query_multiple_short( itemsnomove ) );
itemsnomove->move( TO );
}
printf( "You had %d %s waiting, for a total administration "
"cost of %s.\n"
"You hand over the money.\n",
sizeof( lots_pending ), sizeof( lots_pending ) > 1 ?
"lots" : "lot",
MONEY_HAND->money_value_string( amount, currency ) );
return 1;
}
}
int do_withdraw( object *boxes ) {
object box, *items, *itemsnomove;
class lot_details *filtered_lots;
class lot_details current_lot;
int temp_lot_id;
if ( sizeof( boxes ) > 1 ) {
TP->add_failed_mess( TO,
"You can only $V on one case at "
"a time.\n" );
return 0;
}
box = boxes[0];
if ( member_array( box, cases ) == -1 ) {
TP->add_failed_mess( TO,
"$I isn't being auctioned here.\n",
({ box }) );
return 0;
}
temp_lot_id = box->query_property( LOT_ID );
filtered_lots = filter( lots, (: $1->lot_id == $(temp_lot_id) :) );
if ( sizeof( filtered_lots ) != 1 ) {
printf( "Please inform a creator, there are %d records to "
"match this case.\n", sizeof( filtered_lots ) );
return 1;
}
current_lot = filtered_lots[0];
if ( TP->query_name() != current_lot->seller &&
!creatorp(TP) ) {
TP->add_failed_mess( TP, "This isn't your "
"lot to withdraw!\n" );
return 0;
}
lots -= filtered_lots;
items = all_inventory( box );
printf( "You collect %s.\n", query_multiple_short( items ) );
itemsnomove = filter( items, (: $1->move( TP ) != MOVE_OK :) );
if ( sizeof( itemsnomove ) ) {
printf( "Unfortunately, you couldn't carry %s and it was "
"left on the floor for you.\n",
query_multiple_short( itemsnomove ) ) ;
itemsnomove->move( TO );
}
cases -= ({ box });
box->dest_me();
TP->add_succeeded_mess( TO, "" );
return 1;
}
int do_describe( object *boxes, string int_desc ) {
object box;
class lot_details *filtered_lots;
class lot_details current_lot;
int temp_lot_id;
if ( sizeof( boxes ) > 1 ) {
TP->add_failed_mess( TO,
"You can only $V on one case at "
"a time.\n" );
return 0;
}
box = boxes[0];
if ( member_array( box, cases ) == -1 ) {
TP->add_failed_mess( TO,
"$I isn't being auctioned here.\n",
({ box }) );
return 0;
}
temp_lot_id = box->query_property( LOT_ID );
filtered_lots = filter( lots, (: $1->lot_id == $(temp_lot_id) :) );
if ( sizeof( filtered_lots ) != 1 ) {
printf( "Please inform a creator, there are %d records to "
"match this case.\n", sizeof( filtered_lots ) );
return 1;
}
current_lot = filtered_lots[0];
if ( TP->query_name() != current_lot->seller &&
!creatorp(TP) ) {
TP->add_failed_mess( TP, "This isn't your "
"lot to describe!\n" );
return 0;
}
current_lot->desc = int_desc;
printf( "You neatly letter %s on the case.\n", int_desc );
TP->add_succeeded_mess( TO, "" );
return 1;
}
/**
* This function is called when an auction ends, it is designed to
* be masked so you can do something funky, like mail the successful
* bidder at the end of an auction.
* @param name The succesful bidders name
* @param objects The items succesfully bid for
* @param price The amount paid
* @param location The short of the location
* @param status 1 if the item was sold, 0 if it wasn't
*/
void end_auction( string name, object *items, int amount, string location,
int status ) {
if ( !LOGIN_OBJ->test_user( name ) )
return; //Lets not mail any not real players.
if ( status ) {
AUTO_MAILER->auto_mail( name, location, "Your successful purchase!",
"","Congratulations! You have succesfully purchased "+
"/global/events"->convert_message( query_multiple_short( items ) ) +
" with a bid of "+ MONEY_HAND->money_value_string( amount, currency )+
".\n\nPlease come and collect your items promptly.\n", 0, 0 );
return;
}
AUTO_MAILER->auto_mail( name, location, "Your unsuccesful sale!",
"", "Dear "+ name +",\nIt is with some regret that I inform you "
"that we were unable to sell " +
"/global/events"->convert_message( query_multiple_short( items ) ) +
".\n\nPlease come and collect your items promptly.\n", 0, 0 );
return;
}
mixed stats() {
return ::stats() +
({ ({ "lots", sizeof(lots) }),
({ "expired lots", sizeof(expired_lots) }),
({ "payments", sizeof(payments) }),
({ "lot count", lot_count }),
});
}