/* -*- LPC -*- */
/*
* $Locker: $
* $Id: peddler.c,v 1.33 2003/04/23 09:36:04 runtime Exp $
*
*/
/**
* This is the peddler object, it acts as a walking talking item
* shop.
* Added event_enter so to stop food from decaying when the peddler
* sells it. Siel, October 2001
*
*/
#include <armoury.h>
#include <money.h>
#include <move_failures.h>
#include <virtual.h>
#define MAX_PROP "max per reset"
#define TYPE "item shop type"
#define NUM_SOLD "number removed this reset"
#define DISPLAY "display in shop"
inherit "/obj/monster";
inherit "/std/shops/inherit/clone_on_demand";
private string _none_left_mess;
private string _out_of_item_mess;
private string _show_item_mess;
private string _missing_punter_mess;
private string _dont_sell_mess;
private string _all_out_mess;
private string _list_mess;
private string _list_item_mess;
private string _no_stock_mess;
private string _too_poor_mess;
private string _too_heavy_mess;
private string _in_combat_mess;
private string _busy_mess;
private int busy;
void create() {
_none_left_mess = "I'm afraid I don't have any of those.";
_out_of_item_mess = "We are right out of $item$.";
_show_item_mess = "$item$ is priced at $cost$. Let me show it to "
"you.";
_missing_punter_mess = "Hey... Where'd the fellow go? Anyway...";
_dont_sell_mess = "I'm afraid I don't have any $item$.";
_all_out_mess = "I'm afraid I have no $item$ left.";
_list_mess = "I have the following items for sale:";
_list_item_mess = "I have $num_left$ $display$ for $cost$.";
_no_stock_mess = "I am afraid I have nothing for sale.";
_too_poor_mess = "I'm afraid you can't afford to buy $item$.";
_too_heavy_mess = "Well, here's $item$, but you can't carry it at "
"the moment. I'll put it on the floor.";
_in_combat_mess = "Can't you see I'm a bit preoccupied right "
"now?";
_busy_mess = "Sorry, I can only handle one purchase at a "
"time!" ;
monster::create();
} /* create() */
/** @ignore yes */
void init() {
object cont = query_cont();
::init();
if( cont ) {
this_player()->add_command( "browse", this_object(),
"<indirect:object:" + file_name(cont) +
"> {from|of} <direct:living:here>" );
this_player()->add_command( "buy", this_object(),
"<indirect:object:" + file_name(cont) +
"> from <direct:living:here>" );
this_player()->add_command( "list", this_object(),
"goods {from|of} <direct:living:here>" );
}
} /* init() */
/** @ignore yes */
void check_cont() {
object cont;
::check_cont();
cont = query_cont();
cont->set_name( "peddler_store" );
} /* check_cont() */
/**
* This method returns the cost of the specified item to the buyer.
* @param thing the thing to cost
* @param buyer who is buying it
* @return the cost of the item
*/
int query_cost( object thing, object buyer ) {
if( thing->query_property("cost here") ) {
return (int)thing->query_property("cost here");
}
else {
return (int)thing->query_value_at( this_object() );
}
} /* query_cost() */
/**
* This method returns the costs of the item as a string.
* @param thing the thing to buy
* @param place the money area it is being bought in
* @param buyer the person who is buying the object
* @return the string money value
*/
string cost_string( object thing, string place, object buyer ) {
return (string)MONEY_HAND->money_value_string(
query_cost( thing, buyer ), place );
} /* cost_string() */
/**
* The main entrace to the browse for things command.
* @return 1 on success, 0 on failure
*/
int do_browse( mixed indirect_obs, string dir_match, string indir_match,
string *words ) {
int num_left;
int i;
string place;
object *things;
string custom_string;
if( this_object()->query_fighting() ) {
queue_command( "sayto " + file_name(this_player()) + " " +
_in_combat_mess, 2 );
this_player()->add_succeeded_mess( this_object(), "$N ask$s $D "
"about browsing an item.\n", ({ }) );
return 1;
}
place = query_property( "place" );
if ( !place || ( place == "" ) ) {
place = "default";
}
check_cont();
things = indirect_obs;
if( !sizeof( things ) ) {
queue_command( "sayto " + file_name(this_player()) + " " +
_none_left_mess, 2 );
}
else {
for ( i = 0; i < sizeof( things ); i++ ) {
num_left = things[i]->query_property( MAX_PROP ) -
things[i]->query_property( NUM_SOLD );
if (num_left <= 0) {
custom_string = replace( _out_of_item_mess, ({
"$item$", things[i]->one_short()
}) );
queue_command( "sayto " + file_name(this_player()) +
custom_string);
continue;
}
custom_string = replace( _show_item_mess, ({
"$item$", "$C$" +
strip_colours((string)things[i]->the_short()),
"$cost$", cost_string( things[i], place,
this_player() )
}) );
queue_command( "sayto " + file_name(this_player()) + " " +
custom_string, 4 * i + 2 );
// Added in by Oaf 11/99 - peddler doesn't have item in
// inventory, so just tell the player the long() of the item.
queue_command( "whisper " +
things[i]->one_short()+":\n"+things[i]->long() + " to " +
file_name(this_player()) );
/*
init_command("show " + things[i]->query_name() + " to " +
this_player()->query_name(), 4*i+3);
*/
/*
call_out("show_it", 4*i+3, evaluate(things[i]->the_short()),
evaluate(things[ i ]->long()));
*/
}
}
this_player()->add_succeeded_mess( this_object(), "$N ask$s $D "
"about "+ query_multiple_short(things) +".\n", ({ }) );
return 1;
} /* do_browse() */
/**
* This method shows the object in question to the player.
* @param short the short description
* @param long the long description
void show_it(string short, string long){
if(environment(this_player()) != environment(this_object())){
queue_command("'" + _missing_punter_mess);
return;
}
tell_room(environment(this_object()), capitalize(evaluate(the_short()))+
" shows "+this_player()->the_short()+" "+short+ ".\n");
tell_object(this_player(), long);
} * show_it() */
/**
* The main entrace to the buy things command.
* @return 1 on success, 0 on failure
*/
int do_buy( mixed indirect_obs, string dir_match, string indir_match,
string *words ) {
int i, num_left;
object *things;
string custom_string;
if(busy) {
do_command("'" + _busy_mess);
this_player()->add_succeeded_mess( this_object(), "$N confuse$s "
"$D, who is busy making business.\n", ({ }));
return 1;
}
busy = 1;
check_cont();
things = indirect_obs;
if ( !sizeof( things ) ) {
custom_string = replace( _dont_sell_mess, ({
"$item$", indir_match
}) );
queue_command( "sayto " + file_name(this_player()) + " " +
custom_string);
}
else {
if( this_object()->query_fighting() ) {
queue_command( "sayto " + file_name(this_player()) + " " +
_in_combat_mess, 2 );
this_player()->add_succeeded_mess( this_object(), "$N ask$s $D "
"about buying "+ query_multiple_short(things) +".\n", ({ }) );
busy = 0;
return 1;
}
for ( i = 0; i < sizeof( things ); ++i ) {
num_left = (int)things[ i ]->query_property( MAX_PROP ) -
(int)things[ i ]->query_property( NUM_SOLD );
if ( num_left < 1 ) {
custom_string = replace( _all_out_mess, ({
"$item$", strip_colours((string)things[i]->query_plural())
}) );
init_command( "sayto " + file_name(this_player()) + " " +
custom_string, 2 * i + 2 );
busy = 0;
continue;
}
call_out( "sell_thing", 2 * i, this_player(), things[ i ] );
}
}
this_player()->add_succeeded_mess( this_object(), "$N ask$s $D "
"about buying "+ query_multiple_short(things) +".\n", ({ }) );
return 1;
} /* do_buy() */
/**
* The main entrace to the list stuff command.
* @return 1 on success, 0 on failure
*/
int do_list() {
int num_left;
string place;
object thing;
int first;
object cont;
string display;
string custom_string;
if( this_object()->query_fighting() ) {
queue_command( "sayto " + file_name(this_player()) + " " +
_in_combat_mess, 2 );
this_player()->add_succeeded_mess( this_object(), "" );
return 1;
}
place = query_property( "place" );
if ( !place || ( place == "" ) ) {
place = "default";
}
check_cont();
cont = query_cont();
thing = first_inventory( cont );
first = 1;
while ( thing ) {
num_left = (int)thing->query_property( MAX_PROP ) -
(int)thing->query_property( NUM_SOLD );
if ( num_left < 1 ) {
thing = next_inventory( thing );
continue;
}
if (first) {
queue_command( "sayto " + file_name(this_player()) + " " +
_list_mess);
first = 0;
}
/* Make it use the display property added with add_object, if it
exists. Else use the short. Pluralize if neccessary */
display = (string)thing->query_property( DISPLAY );
if ( !stringp( display ) && thing->short()) {
if( num_left > 1 ) {
display = (string)thing->query_plural();
}
else {
display = (string)thing->a_short();
}
}
else {
if( num_left > 1 ) {
display = pluralize( display );
}
}
custom_string = replace( _list_item_mess, ({
"$num_left$", (num_left > 1 ? query_num (num_left) : ""),
// "$num_left$", query_num (num_left),
"$display$", display,
"$cost$", cost_string( thing, place, this_player() ) +
(num_left > 1 ? " each" : "" )
}) );
queue_command( "sayto " + file_name( this_player() ) +
" " + custom_string );
thing = next_inventory( thing );
}
if ( first ) {
queue_command( "say " + _no_stock_mess);
}
this_player()->add_succeeded_mess( this_object(), "" );
return 1;
} /* do_list() */
/**
* The main entrace to the sell stuff command.
* @return 1 on success, 0 on failure
*/
void sell_thing( object player, object thing ) {
int value;
string item_name, place;
object copy;
string custom_string;
if ( !player ) {
busy = 0;
return;
}
if ( environment( player ) != environment( this_object() ) ) {
busy = 0;
return;
}
if ( !thing ) {
busy = 0;
return;
}
place = query_property( "place" );
if ( !place || ( place == "" ) ) {
place = "default";
}
value = (int)player->query_value_in( place );
if ( place != "default" ) {
value += (int)player->query_value_in( "default" );
}
// Make sure we are making a cost based on the non-cloned object.
if ( (int)this_object()->query_cost( thing, player ) > value ) {
custom_string = replace( _too_poor_mess, ({
"$item$", (string)thing->a_short()
}) );
queue_command( "sayto " + file_name(player) + " " +
custom_string );
busy = 0;
return;
}
// So the copy is only made if the item is actually sold.
copy = (object)this_object()->create_real_object( thing );
if ( !copy ) {
switch ( (string)thing->query_property( TYPE ) ) {
case "armour" :
case "weapon" :
case "armoury item":
copy = ARMOURY->request_item( item_name,
80 + random( 20 ) );
break;
case "object" :
copy = clone_object( item_name );
break;
}
}
if ( !copy ) {
copy = clone_object( explode( file_name( thing ), "#" )[ 0 ] );
}
if ( !copy ) {
busy = 0;
return;
}
thing->add_property( NUM_SOLD, (int)thing->query_property( NUM_SOLD ) +
1 );
player->pay_money( (mixed *)MONEY_HAND->create_money_array(
(int)this_object()->query_cost( copy, player ), place ), place );
tell_object( player, "You pay "+ the_short() +" "+
cost_string( copy, place, player ) +".\n" );
tell_room( environment(), (string)player->one_short() +
" gives "+ the_short() +" some money.\n", player );
if ( (int)copy->move( player ) != MOVE_OK ) {
custom_string = replace( _too_heavy_mess, ({
"$item$", (string)copy->the_short()
}) );
queue_command( "sayto " + file_name(player) + " " + custom_string );
copy->move( environment() );
queue_command( ":puts "+ (string)copy->a_short() +" on the ground." );
}
else {
tell_room( environment(), the_short() +" gives "+
(string)player->one_short() +" "+ (string)copy->a_short() +
".\n" );
}
busy = 0;
} /* sell_thing() */
void event_enter(object ob, string mess, object from) {
if (ob->query_food_object()) { ob->set_decay_speed(0); }
} /* event_enter() */
void event_exit(object ob, string message, object to) {
if (ob->query_food_object()) { ob->set_decay_speed(8000); }
} /* event_exit() */
void dest_me() {
if(query_cont())
log_file("PEDDLER", "Cont: %s\n", file_name(query_cont()));
clone_on_demand::dest_me();
monster::dest_me();
} /* dest_me() */
/* CHAT OVERRIDE FUNCTIONS, Dasquian 8/7/02 */
/**
* Overrides the default reply to having none left
* @param s the chat to replace the default with
*/
void set_none_left_mess(string s) {
_none_left_mess = s;
} /* set_none_left_mess() */
/**
* Overrides the default chat of being out of an item that is browsed
* @param s the chat to replace the default with. Must include $item$, which
* will be replaced by the item short.
*/
void set_out_of_item_mess(string s) {
_out_of_item_mess = s;
} /* set_out_of_item_mess() */
/**
* Overrides the default chat of showing an item to a player
* @param s the chat to replace the default with. Must include $item$ and
* $cost$, which will be replaced by the item short and the cost of the item
* respectively.
*/
void set_show_item_mess(string s) {
_show_item_mess = s;
} /* set_show_item_mess() */
/**
* Overrides the default chat to the player having wandered off
* @param s the chat to replace the default with
*/
void set_missing_punter_mess(string s) {
_missing_punter_mess = s;
} /* set_missing_punter_mess() */
/**
* Overrides the default chat of the peddler not selling an item
* @param s the chat to replace the default with. Must include $item$, which
* will be replaced by the item short.
*/
void set_dont_sell_mess(string s) {
_dont_sell_mess = s;
} /* set_dont_sell_mess() */
/**
* Overrides the default chat of the item being out of stock when a player
* tries to buy it
* @param s the chat to replace the default with. Must include $item$, which
* will be replaced by the item short.
*/
void set_all_out_mess(string s) {
_all_out_mess = s;
} /* set_all_out_mess() */
/**
* Overrides the default chat to announcing the stock list
* @param s the chat to replace the default with
*/
void set_list_mess(string s) {
_list_mess = s;
} /* set_list_mess() */
/**
* Overrides the default chat of listing a stock item's price and stock
* @param s the chat to replace the default with. Must include $num_left$,
* $display$ and $cost$, which will be replaced by the appropriate
* strings.
*/
void set_list_item_mess(string s) {
_list_item_mess = s;
} /* set_list_item_mess() */
/**
* Overrides the default reply to having no listable stock
* @param s the chat to replace the default with
*/
void set_no_stock_mess(string s) {
_no_stock_mess = s;
} /* set_no_stock_mess() */
/**
* Overrides the default chat of the player being too poor to buy an item
* @param s the chat to replace the default with. Must include $item$, which
* will be replaced by the item short.
*/
void set_too_poor_mess(string s) {
_too_poor_mess = s;
} /* set_too_poor_mess() */
/**
* Overrides the default chat of the player being too burdened to carry an
* item
* @param s the chat to replace the default with. Must include $item$, which
* will be replaced by the item short.
*/
void set_too_heavy_mess(string s) {
_too_heavy_mess = s;
} /* set_too_heavy_mess() */
/**
* Overrides the default chat of the peddler being in combat and hence unable
* to sell his wares!
* @param s the chat to replace the default with
*/
void set_in_combat_mess(string s) {
_in_combat_mess = s;
} /* set_in_combat_mess() */
/**
* Overrides the default chat of the peddler being busy selling
* something already.
* @param s the chat to replace the default with
*/
void set_busy_mess(string s) {
_busy_mess = s;
} /* set_busy_mess() */