/*
* /std/vendor.c
* from the Nightmare Mudlib
* a standard object that sells things in shops
* created by Descartes of Borg 921024
* rewritten by Descartes 931108
* minor change by Bohemund 940403
*/
#include <std.h>
#include <money.h>
#define MAX_ITEMS 75
inherit MONSTER;
private mapping __Eco, __Values, __Costs, __Discriminate;
private string *__ItemTypes;
static int __CheckDiscrimination();
static int __SellAll();
static int convert(int x);
string *query_item_types();
static int cost_bargaining(object who, int x);
static int value_bargaining(object who, int x);
static int __AlreadyThere(object ob);
void init() {
::init();
add_action("__Buy", "buy");
add_action("__Sell", "sell");
add_action("__Show", "show");
add_action("__List", "list");
add_action("__Value", "value");
add_action("__Cost", "cost");
}
void create() {
::create();
__Eco = ([]);
__Values = ([]);
__Costs = ([]);
__Discriminate = ([]);
__ItemTypes = ({ "weapon" });
}
int __Buy(string str) {
object ob;
string tmp;
int worth, val, x;
if(!__Eco["storage object"])
__Eco["storage object"] = load_object(__Eco["storage file"]);
if(!(x = __CheckDiscrimination())) return 1;
if(!str) {
this_object()->force_me("speak Buy what?");
return 1;
}
if(!(ob = present(str, __Eco["storage object"])) &&
!(ob = parse_objects(__Eco["storage object"]))) {
this_object()->force_me("speak I have nothing like that to sell.");
return 1;
}
if(__Costs[tmp = (string)this_player()->query_name()])
worth = __Costs[tmp][ob];
if(!worth) {
if(!(worth = (int)ob->query("value"))) worth = 1;
if(worth > (val = cost_bargaining(this_player(), worth))) val = worth;
val = convert(val);
}
else {
map_delete(__Costs[tmp], ob);
if(!__Costs[tmp] || !sizeof(__Costs[tmp])) map_delete(__Costs, tmp);
val = worth;
}
if((int)this_player()->query_money(__Eco["currency"]) < val) {
this_object()->force_me("speak "+(string)this_player()->query_cap_name()+
", you are too poor for that!");
return 1;
}
this_object()->force_me("speak Here is your "+str+" for "+val+" "+
__Eco["currency"]+"!");
message("other_action", query_cap_name()+" hands "+
(string)this_player()->query_cap_name()+" "+
(string)ob->query_short()+".",
environment(this_object()), ({ this_player(), this_object() }));
message("other_action", query_cap_name()+" hands you "+
(string)ob->query_short()+".", this_player());
this_player()->add_money(__Eco["currency"], -val);
if(ob->move(this_player())) {
message("my_action", "You drop it as fast as you get it!", this_player());
message("other_action", (string)this_player()->query_cap_name()+
" drops "+(string)ob->query_short()+".",
environment(this_object()), ({ this_player() }));
ob->move(environment(this_object()));
}
return 1;
}
int __Sell(string str) {
object ob;
string tmp;
int worth, val, x;
if(!(x = __CheckDiscrimination())) return 1;
if(!str) {
this_object()->force_me("speak Sell what?");
return 1;
}
if(!__Eco["storage object"])
__Eco["storage object"] = load_object(__Eco["storage file"]);
if(sizeof(all_inventory(__Eco["storage object"])) >= MAX_ITEMS) {
this_object()->force_me("speak I cannot get rid of what I have "
"to sell right now!");
return 1;
}
if(str == "all") return __SellAll();
if(!(ob = present(str, this_player()))) {
this_object()->force_me("speak You do not have that to sell!");
return 1;
}
if(member_array((string)ob->query_vendor_type(), query_item_types()) == -1) {
/* the following code is to allow for the selling of items
with the "magic item" property */
if(!(ob->query_property("magic item") &&
member_array("magic", query_item_types()) != -1)) {
this_object()->force_me(sprintf("speak I do not buy %s goods.",
(string)ob->query_vendor_type()));
return 1;
}
}
if(__Values[tmp = (string)this_player()->query_name()])
worth = __Values[tmp][ob];
if(!worth) {
if(!(worth = (int)ob->query("value"))) {
this_object()->force_me("speak That thing is worthless.");
return 1;
}
if(worth < (val = value_bargaining(this_player(), worth))) val = worth;
if(val > 2000) {
this_object()->force_me("speak I am low on money.");
val = 1000 + random(1000);
}
val = convert(val);
}
else {
val = worth;
map_delete(__Values[tmp], ob);
if(!__Values[tmp] || !sizeof(__Values[tmp]))
map_delete(__Values, tmp);
}
this_player()->add_money(__Eco["currency"], val);
this_player()->add_skill_points("bargaining",
random(query_skill("bargaining")));
message("other_action", (string)this_player()->query_cap_name()+
" sells "+(string)ob->query_short()+".", environment(this_object()),
({ this_player() }));
message("my_action", "You sell "+(string)ob->query_short()+" for "+
val + " " + __Eco["currency"]+".", this_player());
if(ob->query_destroy()) ob->remove();
else if(__AlreadyThere(ob)) ob->remove();
else {
ob->move(__Eco["storage object"]);
return 1;
}
if(ob) destruct(ob);
return 1;
}
int __Show(string str) {
object ob;
if(!__CheckDiscrimination()) return 1;
if(!str) {
this_object()->force_me("Show you what?");
return 1;
}
if(!__Eco["storage object"])
__Eco["storage object"] = load_object(__Eco["storage file"]);
if(!(ob = present(str, __Eco["storage object"])) &&
!(ob = parse_objects(__Eco["storage object"]))) {
this_object()->force_me("speak I do not have that here to show you.");
return 1;
}
message("other_action", query_cap_name()+" shows you "+
(string)ob->query_short()+".", this_player());
message("info", (string)ob->query_long(), this_player());
return 1;
}
int __List(string str) {
object *inv;
string *tmp;
int i, x;
if(!__CheckDiscrimination()) return 1;
if(!__Eco["storage object"]) {
this_object()->force_me("speak I have nothing to sell right now.");
return 1;
}
i = sizeof(inv = filter_array(all_inventory(__Eco["storage object"]),
"filter_list", this_object(), str));
if(!i) {
this_object()->force_me("speak I have nothing like that to sell.");
return 1;
}
message("info", arrange_string("Item", 55) +
"approximate value", this_player());
message("info", "_________________________________________________"
"________________________", this_player());
for(x=0, tmp = ({}); x<i; x++)
tmp += ({ arrange_string((string)inv[x]->query_short(), 55) +
"%^RESET%^"+convert((int)inv[x]->query("value"))+ " "+
__Eco["currency"] });
this_player()->more(tmp);
return 1;
}
int __Value(string str) {
object ob;
string tmp, cn;
int worth, val;
if(!__CheckDiscrimination()) return 1;
if(!str) {
this_object()->force_me("speak The value of what?");
return 1;
}
if(!(ob = present(str, this_player()))) {
if(!(ob = parse_objects(this_player(), str))) {
this_object()->force_me("speak You don't have that!");
return 1;
}
}
message("other_action", (cn=(string)this_player()->query_cap_name())+
" asks for an appraisal.", environment(this_object()),
({this_object(),this_player()}));
if(__Values[tmp=(string)this_player()->query_name()] &&
__Values[tmp][ob]) {
this_object()->force_me("speak You have my offer!");
return 1;
}
if(!(worth = (int)ob->query("value"))) {
this_object()->force_me("speak That thing is worthless!");
return 1;
}
if(worth < (val = value_bargaining(this_player(), worth))) val = worth;
if(val > 2000) {
this_object()->force_me("speak I am low on money.");
val = 1000 + random(1000);
}
val = convert(val);
if(!__Values[tmp]) __Values[tmp] = ([]);
__Values[tmp][ob] = val;
if(cn == "Someone") cn = "Invisible person";
this_object()->force_me("speak "+cn+", I will offer you "+val+" "+
__Eco["currency"]+" for it.");
return 1;
}
int __Cost(string str) {
object ob;
string cn, tmp;
int val, worth;
if(!__Eco["storage object"])
__Eco["storage object"] = load_object(__Eco["storage file"]);
if(!__CheckDiscrimination()) return 1;
if(!str) {
this_object()->force_me("speak The cost of what?");
return 1;
}
if(!(ob = present(str, __Eco["storage object"])) &&
!(ob = parse_objects(__Eco["storage object"], str))) {
this_object()->force_me("speak I do not have any "+str+" to sell.");
return 1;
}
message("other_action", (cn=(string)this_player()->query_cap_name())+
"asks about the cost of an item for sale.",
environment(this_object()), ({ this_object(), this_player() }));
if(__Costs[tmp = (string)this_player()->query_name()] && __Costs[tmp][ob]) {
this_object()->force_me("speak I will charge no less!");
return 1;
}
if(!(worth = (int)ob->query("value"))) worth = 1;
if(worth > (val = cost_bargaining(this_player(), worth))) val = worth;
val = convert(val);
if(!__Costs[tmp]) __Costs[tmp] = ([]);
__Costs[tmp][ob] = val;
if(cn == "Someone") cn == "Invisible person";
this_object()->force_me("speak "+cn+", I will take "+val+" "+
__Eco["currency"]+" for it.");
return 1;
}
int filter_list(object ob, string str) {
if(!str || str == "") return 1;
switch(str) {
case "weapon": case "weapons": return (int)ob->is_weapon();
case "armor": case "armour": case "armors": case "armours":
return (int)ob->is_armour();
case "bag": case "bags": return (int)ob->is_bag();
case "other": return (!((int)ob->is_weapon()) &&
!((int)ob->is_armour()));
default:
return ((string)ob->query_type() == str || ob->id(str));
}
return 0; // just to be safe... Did I just comment some code?
// i would have to say so... ;)
}
static int __SellAll() {
object *inv;
int i, worth, val, total;
string tmp;
total = 0;
if(!(i = sizeof(inv = all_inventory(this_player())))) {
this_object()->force_me("speak You have nothing to sell!");
return 1;
}
while(i--) {
if(!(worth = (int)inv[i]->query("value"))) {
this_object()->force_me("speak "+(string)inv[i]->query_short()+
" is worthless.");
continue;
}
if(member_array((string)inv[i]->query_vendor_type(),
query_item_types()) == -1) {
this_object()->force_me(sprintf("speak %s is a %s item, and "
"I do not buy those.",
(string)inv[i]->query_short(),
(string)inv[i]->query_vendor_type()));
continue;
}
if(worth < (val = value_bargaining(this_player(), worth))) val = worth;
if(val > 2000) val= 1000 + random(1000);
val = convert(val);
total += val;
this_player()->add_money(__Eco["currency"], val);
message("my_action", "You sell "+(string)inv[i]->query_short()+".",
this_player());
message("other_action", (string)this_player()->query_cap_name()+
" sells "+(string)inv[i]->query_short()+".",
environment(this_object()), ({ this_player() }));
if(inv[i]->query_destroy()) inv[i]->remove();
else if(__AlreadyThere(inv[i])) inv[i]->remove();
else inv[i]->move(__Eco["storage object"]);
}
if(total)
this_object()->force_me(sprintf("speak Your total comes to %d %s.",
total, __Eco["currency"]));
/* Kalinash 1-14-94 */
this_object()->force_me("speak Thank you for your business!");
return 1;
}
static int cost_bargaining(object who, int x) {
int val, vend, pl, cha;
pl = (int)who->query_skill("bargaining");
cha = (int)who->query_stats("bargaining");
val = (2*x) + ((x*10)/100) + ((query_skill("bargaining")-cha)*x)/200;
val -= (pl*x)/200;
return val;
}
static int value_bargaining(object who, int x) {
int val, pl, cha;
pl = (int)who->query_skill("bargaining");
cha = (int)who->query_stats("charisma");
val = x + ((pl*x)/200) - ((query_skill("bargaining")-cha)*x)/200;
return val;
}
static int __AlreadyThere(object ob) {
object *inv;
int i;
if(!(i = sizeof(inv = all_inventory(__Eco["storage object"])))) return 0;
while(i--)
if((string)inv[i]->query_short() == (string)ob->query_short()) return 1;
return 0;
}
static int __CheckDiscrimination() {
int x, tmp, i;
string *dis;
if(__Discriminate["class"] &&
member_array((string)this_player()->query_class(),
__Discriminate["class"]) == -1) {
this_object()->force_me("speak I do not do business with people "
"like you.");
return 0;
}
if(__Discriminate["race"] &&
member_array((string)this_player()->query_class(),
__Discriminate["race"]) == -1) {
this_object()->force_me("speak I do not do business with people "
"like you.");
return 0;
}
if(__Discriminate["language"] && i = sizeof(__Discriminate["language"])) {
while(i--)
if(x < (tmp = (int)this_player()->query_lang_prof
(__Discriminate["language"][i]))) x = tmp;
if(!x) {
this_object()->force_me("speak I do not understand you.");
return 0;
}
return x;
}
return 10;
}
static int convert(int x) {
if(!x) return 0;
return 1 + to_int(x * __Eco["exchange rate"]);
}
varargs void set_currency(string str, float wert) {
int x;
__Eco["currency"] = str;
__Eco["exchange rate"] =currency_rate(str);
}
void set_discriminate(string who, string *which) {
__Discriminate[who] = which;
}
void set_storage_room(string str) {
__Eco["storage object"] =load_object(__Eco["storage file"] = str);
}
string query_currency() { return __Eco["currency"]; }
object query_storage_room() { return __Eco["storage object"]; }
void set_item_types(mixed val) {
if(stringp(val)) val = ({ val });
else if(!pointerp(val)) error("Bad argument 1 set_item_types().\n");
__ItemTypes = val;
}
void add_item_type(string str) { __ItemTypes += ({ str }); }
string *query_item_types() { return __ItemTypes; }