/**
* This is the file containing extra controls for the player run
* craft shop. We will assume that all player run craft shops will be
* rooms and not npcs.
* @author Pinkfish
* @started Fri Apr 21 13:37:44 PDT 2000
*/
inherit "/std/shops/inherit/craft_shop_category";
inherit "/std/shops/inherit/expression_util";
inherit "/std/shops/inherit/person_expressions";
inherit "/std/shops/inherit/object_expressions";
#include <player.h>
#include <money.h>
#include <move_failures.h>
#include <shops/craft_shop.h>
#include <player_handler.h>
#include <clubs.h>
#define EXPRESSION_NO_CLASSES
#include <expressions.h>
#include <mail.h>
#include <nroff.h>
#include <player_handler.h>
//#define PRESTO_DEBUG
#define PLAYER_CRAFT_SHOP_CHECK_PROP "player craft shop check"
#define PLAYER_CRAFT_SHOP_SELL 1
#define PLAYER_CRAFT_SHOP_SELL_AUTO 2
#define PLAYER_CRAFT_SHOP_BUY 3
#define PLAYER_CRAFT_SHOP_APPROVE 4
#define PLAYER_CRAFT_SHOP_EXPR_DENY 1
#define PLAYER_CRAFT_SHOP_EXPR_ACCEPT 2
class approval_item {
mixed value;
string list_name;
int markup;
int final_cost;
}
class expression_type {
int type;
class parse_node* condition;
class parse_node* value;
string list_name;
}
class approval {
mixed hairy;
class expression_type* expressions;
int low_cost;
int high_cost;
mapping items;
int num_allowed;
int high_cost_deny;
}
class approval_obs {
string seller;
string category;
int value;
string name;
int* saved;
int enter_time;
int* checkout;
string* shorts;
}
#if USE_TRANSACTIONS
class shop_transaction {
int time;
string person;
string objects;
string name_cat;
int type;
int amount;
mixed extra;
}
#endif
class shop_stats {
int num_sold;
int value_sold;
string seller;
string name;
}
class helper_stats {
int num_approved;
int total_cost;
int num_rejected;
mapping items_approved;
}
class item_stats {
int num_sold;
int total_cost;
int total_made;
int num_bought;
}
class weekly_stats {
int num_sold;
int total_cost;
int total_made;
int num_bought;
mapping items;
mapping helper;
}
class seller_information {
int max_sellable;
int value_limit;
int deny_value_limit;
}
private class approval_obs* _waiting_for_approval;
private class approval_obs* _approved;
private class approval _automatic_approval;
// This is the list of allowable list names.
private string* _list_names;
private int _automatic_percentage;
private int _current_save_num;
private int _total_outgoing;
private int _total_ingoing;
private int _time_of_mail;
private class parse_node *_tax_expression;
#if USE_TRANSACTIONS
private class shop_transaction* _transactions;
#endif
private mapping _sold_stats;
private int _stats_start;
private mapping _sellers;
private mapping _num_checked_so_far;
private string* _helpers;
private class weekly_stats _weekly_stats;
private nosave string _parcel_post;
private nosave int _something_checkedout;
private nosave int _maximum_inventory;
private nosave int _round_value;
private nosave int _max_list_names;
private nosave int _max_items_in_queue;
protected void confirm_approval(string answer, class approval_obs approve, int final_cost);
private object* variable_objects(string seller, int cost, object* ob);
private int variable_sale_cost(string seller, int cost, object* ob, string name, string category);
private string variable_sale_name(string seller, int cost, object* ob, string name, string category);
private string variable_sale_category(string seller, int cost, object* ob, string name, string category);
private int function_inventory_number(string short, string seller, int cost, object* ob);
/*
* This methods must be defined in an upper level class.
*/
string query_owner();
int is_allowed(string person);
void event_save(object thing);
int is_open_for(string type, string name);
void create() {
_round_value = 1;
if (!_waiting_for_approval) {
_waiting_for_approval = ({ });
}
if (!_approved) {
_approved = ({ });
}
if (!_list_names) {
_list_names = ({ });
}
if (!_automatic_approval) {
_automatic_approval = new(class approval);
//_automatic_approval->sellers = ({ });
//_automatic_approval->categories = ([ ]);
_automatic_approval->expressions = ({ });
_automatic_approval->items = ([ ]);
}
if (!_automatic_percentage) {
_automatic_percentage = 10;
}
#if USE_TRANSACTIONS
if (!_transactions) {
_transactions = ({ });
}
#endif
if (!_sold_stats) {
_sold_stats = ([ ]);
}
if (!_helpers) {
_helpers = ({ });
}
if (!_stats_start) {
_stats_start = time();
}
if (!_sellers) {
_sellers = ([ ]);
}
if (!_num_checked_so_far) {
_num_checked_so_far = ([ ]);
}
if (!_tax_expression) {
_tax_expression = ({ });
}
if (!_weekly_stats) {
_weekly_stats = new(class weekly_stats);
_weekly_stats->items = ([ ]);
_weekly_stats->helper = ([ ]);
}
//
// Set it up so that selling it the normal way gets no money.
//
set_cut(100);
_max_items_in_queue = 100;
craft_shop_category::create();
expression_util::create();
set_always_ask_price(1);
add_allowed_variable("objects", EXPRESSION_TYPE_OBJECT +
EXPRESSION_TYPE_ARRAY_OFFSET,
(: variable_objects :) );
add_allowed_variable("salecost", EXPRESSION_TYPE_MONEY,
(: variable_sale_cost :) );
add_allowed_variable("salename", EXPRESSION_TYPE_STRING,
(: variable_sale_name :) );
add_allowed_variable("salencategory", EXPRESSION_TYPE_STRING,
(: variable_sale_category :) );
set_expression_type("shop");
object_expressions::create();
person_expressions::create();
set_no_royalty_commands(1);
} /* create() */
/**
* This method checks to see if the specifgied person is a helper in the
* shop or not.
* @param person the person to check if they are a helper
* @return 1 if they are a helper, 0 if not
*/
int is_helper(string person) {
if (!_helpers) {
_helpers = ({ });
}
return member_array(person, _helpers) != -1 ||
is_allowed(person);
} /* is_helper() */
/**
* This method strips off enclosing quotation marks, if any
* @param str the srtring to strip of quotes
* @return the string stripped of quotes
*/
private string strip_quotes(string str) {
if (str) {
if (str[0] == '\"') str = str[1 .. ];
if (str[<1] == '\"') str = str[0 .. <2];
}
return str;
}
/**
* This method sets the maximum inventory size for the shop.
* @param size the maximum inventory size
*/
void set_maximum_waiting_queue_size(int size) {
_max_items_in_queue = size;
} /* set_maximum_waiting_queue_size() */
/**
* This method returns the maximum inventory size for the shop.
* @return the maximum inventory size
*/
int query_maximum_waiting_queue_size() {
return _max_items_in_queue;
} /* query_maximum_waiting_queue_size() */
/**
* This method sets the maximum inventory size for the shop.
* @param size the maximum inventory size
*/
void set_maximum_inventory_size(int size) {
_maximum_inventory = size;
} /* set_maximum_inventory_size() */
/**
* This method returns the maximum inventory size for the shop.
* @return the maximum inventory size
*/
int query_maximum_inventory_size() {
return _maximum_inventory;
} /* query_maximum_inventory_size() */
/**
* This method sets the parcel post to use for rejecting items.
* @param parcel the parcel post office
*/
void set_parcel_post(string parcel) {
_parcel_post = parcel;
} /* set_parcel_post() */
/**
* This method tells us the current parcel post used for rejecting items.
* @return the current parcel post
*/
string query_parcel_post() {
return _parcel_post;
} /* query_parcel_post() */
/**
* This method figures out the royalty.
* @return the royalty
*/
int query_royalty(string person) {
return query_controller()->query_royalty(person);
} /* query_royalty() */
/**
* This method figures out the owner's money.
* @return the owners money
*/
int query_owners_money() {
return query_royalty(query_owner());
} /* query_owners_money() */
/**
* This method changes the royalty.
* @param person the person to change
* @param amount the amount to change by
*/
void adjust_royalty(string person, int amount) {
query_controller()->adjust_royalty(person, amount);
} /* query_royalty() */
/**
* This method adjusts out the owner's money.
* @param amount the amount to adjust it by
*/
int adjust_owners_money(int amount) {
return adjust_royalty(query_owner(), amount);
} /* adjust_owners_money() */
/**
* THis method sets the amount to round all the sell values for. THis is
* deal with annoying currencies like AM money which does not have a
* '1' item.
* @param round the price to round at
*/
void set_round_price(int round) {
_round_value = round;
} /* set_round_price() */
/**
* This method returns the amount to round all sell values for.
* @return the round price
*/
int query_round_prices() {
return _round_value;
} /* query_round_prices() */
/**
* This method returns the current approval list for the shop.
*/
class approval_obs* query_approval_list(int approved) {
if (approved) {
return _approved;
} else {
return _waiting_for_approval;
}
} /* query_approval_list() */
/**
* This method returns the number of items currently in the shop by
* the specified person. This includes items waiting for approval.
*/
int query_number_of_items_listed(string name) {
int num;
class approval_obs bing;
name = lower_case(name);
num = sizeof(query_controller()->query_owner_sellables(name));
foreach (bing in _waiting_for_approval) {
if (lower_case(bing->seller) == name) {
num += sizeof(bing->saved);
}
}
return num;
} /* query_number_of_items_listed() */
/**
* This method checks to see if the specified item is approved.
* @param seller the name of the seller
* @param value the amount it is sold for
* @param name the name of the item being solde
* @param sellables the sold items
* @param category the category of the sold item
* @param final_cost the final cost of the item
* @return 1 if is approved, 0 if not, -1 if denied, string if it is approved
* with a list name
*/
mixed is_item_approved(string seller, int value, string name, object* sellables,
string category, int ref final_cost) {
string short;
object ob;
int item_approval;
class expression_type bing;
class parse_node frog;
int cost;
mixed item;
final_cost = ((value * (100 + _automatic_percentage)) / 100);
value = value - (cost % _round_value);
if (is_allowed(seller) ||
is_helper(seller)) {
// Owners sell for the exact amount the specified.
final_cost = value;
return 1;
}
//
// This is the value we don't automatically accept at.
//
seller = lower_case(seller);
if (_sellers[seller] &&
_sellers[seller]->deny_value_limit) {
if (_sellers[seller]->deny_value_limit < value) {
return -1;
}
} else if (_automatic_approval->high_cost_deny &&
_automatic_approval->high_cost_deny <= value) {
return -1;
}
//
// Check through the automatic approval stuff to see if we should
// approve it.
//
foreach (ob in sellables) {
if (!ob) {
// Always deny things with broken objects references.
return -1;
}
short = ob->query_short();
if (_automatic_approval->items[short]) {
if (classp(_automatic_approval->items[short])) {
item = ((class approval_item)_automatic_approval->items[short])->value;
} else {
item = _automatic_approval->items[short];
}
if (pointerp(item)) {
frog = evaluate_expression(item,
seller,
value,
({ ob }),
name,
category);
cost = frog->value - (frog->value % _round_value);
if (cost < value) {
item_approval = 0;
break;
}
item_approval++;
} else if (item < value) {
item_approval = 0;
break;
} else {
item_approval++;
}
}
}
if (item_approval) {
if (classp(_automatic_approval->items[short])) {
class approval_item womble;
womble = _automatic_approval->items[short];
if (sizeof(womble) == 3) {
_automatic_approval->items[short] = new(class approval_item,
markup : womble->markup,
value : womble->value,
list_name : womble->list_name,
final_cost : 0);
womble = _automatic_approval->items[short];
}
if (womble->markup) {
final_cost = ((value * (100 + womble->markup)) / 100);
} else if (womble->final_cost) {
final_cost = womble->final_cost;
}
if (womble->list_name) {
return womble->list_name;
} else {
return 1;
}
} else {
return 1;
}
}
//
// Then check any setup expressions.
//
if (!pointerp(_automatic_approval->expressions)) {
_automatic_approval->expressions = ({ });
}
foreach (bing in _automatic_approval->expressions) {
if (evaluate_expression(bing->condition,
seller,
value,
sellables,
name,
category)->value) {
if (bing->type == PLAYER_CRAFT_SHOP_EXPR_ACCEPT) {
frog = evaluate_expression(bing->value,
seller,
value,
sellables,
name,
category);
cost = frog->value - (frog->value % _round_value);
if (cost >= value) {
if (bing->list_name) {
return bing->list_name;
} else if (classp(_automatic_approval->items[short])) {
return ((class approval_item)_automatic_approval->items[short])->list_name;
} else {
return 1;
}
}
} else {
return -1;
}
}
}
if (_sellers[seller] &&
_sellers[seller]->value_limit) {
if (_sellers[seller]->value_limit < value) {
return 0;
} else if (classp(_automatic_approval->items[short])) {
return ((class approval_item)_automatic_approval->items[short])->list_name;
}
else return 1;
} else if (_automatic_approval->high_cost &&
_automatic_approval->high_cost < value) {
return 0;
}
if (_automatic_approval->low_cost &&
_automatic_approval->low_cost >= value) {
if (classp(_automatic_approval->items[short])) {
return ((class approval_item)_automatic_approval->items[short])->list_name;
}
else return 1;
}
return 0;
} /* is_item_approved() */
/**
* This method checks to see if the shop is a closed shop and then checks
* to see if the person is allowed.
* @param person the person to check to see if they are allowed
* @return 1 if they are allowed, 0 if not
*/
int is_allowed_to_use_shop(string person) {
return (is_allowed(person) || is_helper(person) ||
is_open_for("use", person));
} /* is_allowed_to_use_shop() */
/**
* @ignore yes
*/
int check_open(object player, string type) {
if (!::check_open(player)) {
return 0;
}
// Make sure that can only sell stuff if the waiting list is not full.
if (type == "sell") {
if (sizeof(query_approval_list(0)) + sizeof(query_approval_list(1)) >= _max_items_in_queue) {
add_failed_mess("Unable to sell things, the shop is full.\n");
return 0;
}
}
if (!is_allowed_to_use_shop(player->query_name())) {
add_failed_mess("The shop is currently closed.\n");
return 0;
}
return 1;
} /* check_open() */
/**
* @ignore yes
*/
void set_controller(string name) {
::set_controller(name);
query_controller()->set_dont_use_name(1);
} /* set_controller() */
/**
* @ignore yes
*/
int is_allowed_to_sell(object *obs, string name, string *sellable_names) {
int num;
int max;
if (_automatic_approval->num_allowed ||
_sellers[name]) {
num = query_number_of_items_listed(name) + sizeof(obs);
if (_sellers[name] && _sellers[name]->max_sellable) {
max = _sellers[name]->max_sellable;
} else {
max = _automatic_approval->num_allowed;
}
if (num > max) {
add_failed_mess("You cannot have more than " + max + " items "
"listed at " + the_short() + ", with this sale you "
"would have " +
num + ".\n");
return 0;
}
}
if (sizeof(filter(obs, (: $1->query_property("money") :))) > 0) {
add_failed_mess("You cannot sell money.\n");
return 0;
}
//
// Otherwise see if we are over the shops total maximum size.
//
num = sizeof(query_controller()->query_sell_list_obs());
if (num + sizeof(obs) > query_maximum_inventory_size()) {
add_failed_mess("The shop is full, it can only hold " +
query_maximum_inventory_size() + " items and it currently "
"holds " + num + " items.\n");
return 0;
}
return 1;
} /* is_allowed_to_sell() */
/**
* This method finds out the maximum value that this item is allowed
* to be sold for based on the current settings of the shop.
* @param person the person doing the selling
* @param items the item being sold
* @return ({ queue limit, deny limit })
*/
int* query_maximum_sale_value_both(string person, object item) {
int max_deny;
int max_accept;
string short;
class expression_type stuff;
mixed app_item;
if (_sellers[person]) {
if (_sellers[person]->value_limit) {
max_accept = _sellers[person]->value_limit;
}
if (_sellers[person]->deny_value_limit) {
max_deny = _sellers[person]->deny_value_limit;
}
}
if (!max_accept) {
max_accept = _automatic_approval->high_cost;
}
if (!max_deny) {
max_deny = _automatic_approval->high_cost_deny;
}
if (!item) {
return ({ 0, 0 });
}
short = item->query_short();
if (_automatic_approval->items[short]) {
if (classp(_automatic_approval->items[short])) {
app_item = ((class approval_item)_automatic_approval->items[short])->value;
} else {
app_item= _automatic_approval->items[short];
}
if (pointerp(app_item)) {
max_accept = evaluate_expression(app_item,
person, 0, ({ item }), 0, 0)->value;
} else if (app_item < max_deny) {
max_accept = app_item;
}
}
foreach (stuff in _automatic_approval->expressions) {
if (evaluate_expression(stuff->condition, person, 0, ({ }), 0, 0)->value) {
if (stuff->type == PLAYER_CRAFT_SHOP_EXPR_DENY) {
max_deny = evaluate_expression(stuff->value, person, 0, ({ item }), 0, 0)->value;
} else {
max_accept = evaluate_expression(stuff->value, person, 0, ({ item }), 0, 0)->value;
}
}
}
max_accept -= max_accept % _round_value;
max_deny -= max_deny % _round_value;
return ({ max_accept, max_deny });
} /* query_maximum_sale_value() */
/**
* This method will return the maximum value at which the set of items
* will be denied.
* @param person the person selling the item
* @param obs the set of objects
* @return the deny value
*/
int query_maximum_sale_value(string person, object* obs) {
int* stuff;
object ob;
int cur_deny;
foreach (ob in obs) {
stuff = query_maximum_sale_value_both(person, ob);
if (!cur_deny && stuff[1]) {
cur_deny = stuff[1];
} else if (cur_deny && cur_deny > stuff[1]) {
cur_deny = stuff[1];
}
}
return cur_deny;
} /* query_maximum_sale_value() */
/** @ignore yes */
string query_extra_price_information(string seller, object *obs) {
int* max;
int* max_tmp;
string ret;
string place;
object ob;
max = ({ 0, 0 });
foreach (ob in obs) {
max_tmp = query_maximum_sale_value_both(seller, ob);
if (max_tmp[0] && max[0] > max_tmp[0]) {
max[0] = max_tmp[0];
}
if (max_tmp[1] && max[1] > max_tmp[1]) {
max[1] = max_tmp[1];
}
}
ret = "";
place = query_property("place");
if (!place) {
place = "default";
}
if (max[0]) {
ret += "the maximum price you can sell this straight into the "
"inventory for is " +
MONEY_HAND->money_value_string(max[0], place);
}
if (max[1]) {
if (max[0]) {
ret += " and ";
}
ret += "the maximum price you can sell the item for at all is " +
MONEY_HAND->money_value_string(max[1], place);
}
return capitalize(ret) + ".\n";
} /* query_extra_price_information() */
/**
* This method creates a save file for the specified objects autoloading
* capability. If the number to write to is non-null then it will
* write to that object.
* @param ob the object to get an autoload number for
* @param fixed_num the file number to write to
* @return the auto load number
* @see save_it()
*/
protected int create_auto_load_file(mixed ob, int fixed_num) {
mixed *auto_load;
string tmp;
if (objectp(ob)) {
if (this_player()) {
catch(auto_load = this_player()->create_auto_load(({ ob })));
}
if (!auto_load) {
catch(auto_load = PLAYER_OB->create_auto_load(({ ob })));
}
if (!auto_load) {
// Make it error on the last one...
auto_load = AUTO_LOAD_OB->create_auto_load(({ ob }));
}
} else if (pointerp(ob)) {
auto_load = ob;
} else {
printf("Error! Dammit!\n");
}
if (!fixed_num) {
do {
tmp = do_read_file(CRAFT_SHOP_DATA_SAVE_FILE,
"app_" + _current_save_num);
if (tmp) {
_current_save_num++;
}
} while (tmp);
fixed_num = _current_save_num;
}
do_save_file(CRAFT_SHOP_DATA_SAVE_FILE,
auto_load,
"app_" + fixed_num);
return fixed_num;
} /* create_auto_load_file() */
/**
* This method creates a real object from the save file number.
* @param num the save file number
* @return the nice shiny new object
* @see create_auto_load_file()
*/
protected object create_real_auto_load_object(int num, object player) {
string auto_load;
object *obs;
auto_load = do_read_file(CRAFT_SHOP_DATA_SAVE_FILE,
"app_" + num);
if (userp(player)) {
obs = player->load_auto_load_to_array(auto_load, player);
} else if (this_player()) {
obs = this_player()->load_auto_load_to_array(auto_load, player);
} else {
obs = PLAYER_OB->load_auto_load_to_array(auto_load, player);
}
if (sizeof(obs)) {
return obs[0];
}
return 0;
} /* create_object_from_auto_load() */
/**
* This method turns all the specified id into an item to be checked.
* @param id the id of the object to create
* @param player the player to use for autoloading
*/
object create_checkout_object(class approval_obs approve,
int id,
object player) {
object ob;
int i;
ob = create_real_auto_load_object(id, player);
if (ob) {
ob->add_effect("/std/effects/object/no_save");
ob->add_property(PLAYER_CRAFT_SHOP_CHECK_PROP, ({ approve, id }));
i = member_array(id, approve->saved);
approve->checkout[i] = 1;
event_save(this_object());
_something_checkedout++;
}
return ob;
} /* create_checkout_object() */
/**
* This method updates the checked out item and changes to to be what
* we now have...
* @param ob the object to destroy
*/
int destroy_checkout_object(object ob) {
int id;
int *ids;
int i;
class approval_obs approve;
if (!ob) {
return 0;
}
// Make sure we don't end up recursively messing with the same object.
ob->add_property("destroy checkout object", 1, 2);
if (ob->move("/room/rubbish") != MOVE_OK) {
return 0;
}
debug_printf("Destroying the checkout object %O\n", ob);
//
// Zap the effect too.
//
ids = ob->effects_matching("/std/effects/object/no_save"->query_classification());
foreach (id in ids) {
ob->delete_effect(id);
}
id = ob->query_property(PLAYER_CRAFT_SHOP_CHECK_PROP)[1];
approve = ob->query_property(PLAYER_CRAFT_SHOP_CHECK_PROP)[0];
i = member_array(id, approve->saved);
approve->checkout[i] = 0;
ob->remove_property(PLAYER_CRAFT_SHOP_CHECK_PROP);
create_auto_load_file(ob, id);
event_save(this_object());
_something_checkedout--;
if (_something_checkedout < 0) {
_something_checkedout = 0;
}
return 1;
} /* destroy_checkout_object() */
/**
* This method checks to see if the specified item is a checked out
* item.
* @param ob the object to check
* @return 1 if it is, 0 if not
*/
int is_checkout_object(object ob) {
return ob->query_property(PLAYER_CRAFT_SHOP_CHECK_PROP);
} /* is_checkout_object() */
/**
* This method adds an item to the list of items that need to be approved.
* @param seller name of the player
* @param sellables the list of items to sell
* @param value the cost of the item
* @param name the name of the items
* @param category the category of the item
* @param approved a flag to say if this was approved or not
* @return obs the objects we bought
*/
object* add_to_approval_list(string seller, object* sellables, int value,
string name, string category, int approved) {
class approval_obs stuff;
object ob;
object* obs;
obs = ({ });
foreach (stuff in query_approval_list(approved)) {
if (lower_case(stuff->name) == lower_case(name) &&
stuff->seller == seller &&
stuff->value == value) {
stuff->category = category;
foreach (ob in sellables) {
if (ob->move("/room/rubbish") == MOVE_OK) {
stuff->saved += ({ create_auto_load_file(ob, 0) });
stuff->checkout += ({ 0 });
stuff->shorts += ({ ob->query_short() });
obs += ({ ob });
}
}
if (sizeof(obs)) {
event_save(this_object());
}
return obs;
}
}
stuff = new(class approval_obs);
stuff->seller = seller;
stuff->value = value;
stuff->name = name;
stuff->category = category;
stuff->saved = ({ });
stuff->shorts = ({ });
stuff->enter_time = time();
foreach (ob in sellables) {
if (ob->move("/room/rubbish") == MOVE_OK) {
stuff->saved += ({ create_auto_load_file(ob, 0) });
stuff->shorts += ({ ob->query_short() });
obs += ({ ob });
}
}
stuff->checkout = allocate(sizeof(stuff->saved));
if (sizeof(obs)) {
if (approved) {
_approved += ({ stuff });
} else {
_waiting_for_approval += ({ stuff });
}
event_save(this_object());
}
return obs;
} /* add_to_approval_list() */
/**
* This method removes the item from the approval list.
* @param approve the item to remove
*/
void remove_from_approval_list(class approval_obs approve) {
int i;
int pos;
for (i = 0; i < sizeof(_approved); i++) {
if (_approved[i] == approve) {
//
// Zap the files...
//
foreach (pos in approve->saved) {
do_save_file(CRAFT_SHOP_REMOVE_DATA_SAVE_FILE,
0,
"app_" + pos);
}
_approved = _approved[0..i-1] + _approved[i+1..];
event_save(this_object());
return ;
}
}
for (i = 0; i < sizeof(_waiting_for_approval); i++) {
if (_waiting_for_approval[i] == approve) {
//
// Zap the files...
//
foreach (pos in approve->saved) {
do_save_file(CRAFT_SHOP_REMOVE_DATA_SAVE_FILE,
0,
"app_" + pos);
}
_waiting_for_approval = _waiting_for_approval[0..i-1] + _waiting_for_approval[i+1..];
event_save(this_object());
return ;
}
}
} /* remove_from_approval_list() */
/**
* This method adds in transaction into the transaction list.
* @param person the person doing the thing
* @param objects the string name of the objects
* @param type the type of the transaction
* @param amount the cost of the transaction
* @param name_cat the name/category of the item
* @param extra anything extra about the transaction
*/
void add_transaction(string person, object* objects, int type, int amount,
string name_cat, mixed extra) {
#if USE_TRANSACTIONS
class shop_transaction bing;
string str;
str = query_multiple_short(objects, 0, 1);
bing = new(class shop_transaction);
bing->time = time();
bing->person = person;
bing->objects = str;
bing->type = type;
bing->amount = amount;
bing->name_cat = name_cat;
bing->extra = extra;
_transactions += ({ bing });
event_save(this_object());
#endif
} /* add_transaction() */
#if USE_TRANSACTIONS
/**
* This method truns a transaction into a string.
* @param trans the transaction
* @return the transaction as a string
*/
string query_transaction_string(class shop_transaction trans) {
string ret;
string amt;
string place;
place = query_property("place");
if (!place) {
place = "default";
}
amt = MONEY_HAND->money_value_string(trans->amount, place);
ret = ctime(trans->time)[4..<9] + ": " + trans->person;
switch (trans->type) {
case PLAYER_CRAFT_SHOP_SELL :
ret += " sells " + trans->objects + " (" + trans->name_cat +
") for " + amt;
break;
case PLAYER_CRAFT_SHOP_SELL_AUTO :
ret += " sells " + trans->objects + " (" + trans->name_cat +
") [accepted] for " + amt;
break;
case PLAYER_CRAFT_SHOP_APPROVE :
ret += " approves " + trans->objects + " (" + trans->name_cat +
") sold by " + trans->extra + " for " + amt;
break;
case PLAYER_CRAFT_SHOP_BUY :
ret += " buys " + trans->objects + " (" + trans->name_cat +
") sold by " + trans->extra + " for " + amt;
break;
}
return ret;
} /* query_transaction_string() */
#endif
/**
* This method is called to complete the sale completely. It is split
* up into a second function to allow the extra sell stuff
* to work neatly.
* @param value the value of the objects to sell
* @param name the list name
* @param sellable the list of objects to sell
* @param category the category of the object, 0 if none
* @ignore yes
*/
protected void complete_sale(int value, string name, object *sellable,
string category) {
string place;
object *bought;
mixed approve;
int final_cost;
place = query_property("place");
if (!place) {
place = "default";
}
//
// Make sure we mess with the price before we do any of the approval
// things.
//
_num_checked_so_far = ([ ]);
approve = is_item_approved(this_player()->query_name(),
value, name, sellable, category, ref final_cost);
if (approve == -1) {
write("This item is denied sale here, it is not something the "
"owner wishes to buy.\n");
say(this_player()->query_cap_name() + " finished attempting to sell " +
query_multiple_short(sellable) + " to " + the_short() + ".\n");
return ;
}
if (approve == 1 || stringp(approve)) {
if (stringp(approve)) {
name = approve;
}
}
write("Waiting for approval from the shop owner for the items " +
query_multiple_short(sellable) + " with the name '" +
name + "' selling for " +
MONEY_HAND->money_value_string(value, place) +
" in category " + category + ".\nIf the item is accepted the "
"money will be paid into your royalty pool.\n");
bought = add_to_approval_list(this_player()->query_cap_name(), sellable,
value, name, category, approve != 0);
if (sizeof(bought)) {
add_transaction(this_player()->query_name(),
bought,
PLAYER_CRAFT_SHOP_SELL,
value * sizeof(sellable),
name + " in " + category,
0);
if (sizeof(bought) != sizeof(sellable)) {
write("Unable to sell " + query_multiple_short(sellable - bought) +
" to " + the_short() + ".\n");
}
say(this_player()->the_short() + " completes selling something "
"to the shop.\n");
} else {
write("Unable to sell " + query_multiple_short(sellable) + " to " +
the_short() + ".\n");
}
} /* complete_sale() */
/**
* This method returns the position as a two letter value.
* @param pos the position to mangle
* @return the letter value
*/
string query_letter_value(int pos) {
return sprintf("%c%c", 'A' + (pos / 26), 'A' + (pos % 26));
} /* query_letter_value() */
/**
* This method goes from a letter value to a number.
* @param letter the letters
* @return the number
*/
int query_number_value(string letter) {
if (!strlen(letter)) {
return -1;
}
letter = lower_case(letter);
if (strlen(letter) < 2) {
if (letter[0] >= 'a' && letter[0] <= 'z') {
return letter[0] - 'a';
}
}
if (strlen(letter) > 2) {
return -1;
}
if (letter[0] >= 'a' && letter[0] <= 'z') {
if (letter[1] >= 'a' && letter[1] <= 'z') {
return (letter[0] - 'a') * 26 + (letter[1] - 'a');
}
}
return -1;
} /* query_number_value() */
/**
* This method returns the approval class from the string name. THis is
* assumed to be called from inside a command.
* @param name the string name
* @param approved from the approved or waiting list
* @return the approval object
*/
class approval_obs query_approval_class(string name) {
int pos;
if (name[0] == '-') {
pos = query_number_value(name[1..]);
} else {
pos = query_number_value(name);
}
if (pos == -1) {
add_failed_mess(name + " is not a valid number.\n");
return 0;
}
if (name[0] == '-') {
if (!sizeof(query_approval_list(0))) {
add_failed_mess("There is nothing in the approval list currently.\n");
return 0;
}
if (pos >= sizeof(query_approval_list(0))) {
add_failed_mess("The " + name + " is out of range, must be "
"between -AA and -" +
query_letter_value(sizeof(query_approval_list(0)) - 1) +
".\n");
return 0;
}
return query_approval_list(0)[pos];
}
if (pos >= sizeof(query_approval_list(1))) {
add_failed_mess("The " + name + " is out of range, must be between AA-" +
query_letter_value(sizeof(query_approval_list(1)) - 1) +
".\n");
return 0;
}
return query_approval_list(1)[pos];
} /* query_approval_class() */
/** @ignore yes */
int ownership_change(string old_owner, string new_owner) {
class parse_node* expr;
if (old_owner == new_owner) {
return 0;
}
//
// Setup all the defaults.
//
_automatic_approval = new(class approval);
//_automatic_approval->sellers = ({ });
//_automatic_approval->categories = ([ ]);
_automatic_approval->items = ([ ]);
_automatic_approval->expressions = ({ });
_automatic_percentage = 10;
#if USE_TRANSACTIONS
_transactions = ({ });
#endif
_sold_stats = ([ ]);
_stats_start = time();
_sellers = ([ ]);
expr = parse_boolean_string("false");
} /* ownership_change() */
/** @ignore yes */
void inform_of_buy(int value, object *obs, object player, string *sellers,
string *names, string *cats, int *values) {
string name_cat;
int i;
class shop_stats stat;
_total_ingoing += value;
adjust_royalty(query_owner(), value);
for (i = 0; i < sizeof(obs); i++) {
name_cat = names[i] + " in " + cats[i];
add_transaction(this_player()->query_name(),
obs[i..i],
PLAYER_CRAFT_SHOP_BUY,
values[i],
name_cat,
sellers[i]);
if (!_sold_stats) {
_sold_stats = ([ ]);
}
stat = _sold_stats[sellers[i] + " - " + name_cat];
if (!stat) {
stat = new(class shop_stats);
stat->name = name_cat;
stat->seller = sellers[i];
}
stat->num_sold++;
stat->value_sold += values[i];
_sold_stats[sellers[i] + " - " + name_cat] = stat;
// Weekly stats.
/*
if (!_weekly_stats->items[names[i]]) {
_weekly_stats->items[names[i]] = new(class item_stats);
}
_weekly_stats->items[names[i]]->num_sold++;
_weekly_stats->items[names[i]]->total_made += values[i];
*/
}
//
// Weekly stats data management.
//
_weekly_stats->total_made += value;
} /* inform_of_buy() */
/** @ignore yes */
object* check_for_checkout(object ob) {
object* obs = ({ });
if (_something_checkedout && ob) {
//
// Give them a look.
//
if (living(ob)) {
obs = filter(deep_inventory(ob), (: is_checkout_object($1) :));
if (sizeof(obs)) {
foreach (ob in obs) {
if (!destroy_checkout_object(ob)) {
obs -= ({ ob });
}
}
}
} else {
if (is_checkout_object(ob)) {
call_out("verify_destroy_checkout_object", 2, ob);
//obs = ({ ob });
}
}
return obs;
}
return ({ });
} /* check_for_checkout() */
/** @ignore yes */
void verify_destroy_checkout_object(object ob) {
// If it is destroyed, tell people about it.
if (destroy_checkout_object(ob)) {
tell_room(environment(), ob->the_short() +
" magically checks itself back in.\n");
}
}
/** @ignore yes */
void event_exit(object ob, string message, object to) {
object *obs;
// Already being checked
if (ob->query_property("destroy checkout object")) {
return ;
}
obs = check_for_checkout(ob);
if (sizeof(obs)) {
tell_object(ob, "You suddenly find the uncheckout items " +
query_multiple_short(obs) + " check themselves "
"back in.\n");
obs->move("/room/rubbish");
}
} /* event_exit() */
/** @ignore yes */
void event_dest_me(object ob) {
check_for_checkout(ob);
} /* event_dest_me() */
/**
* This method returns all the checkedout objects to the shop.
*/
void return_all_checkedout_objects() {
object ob;
object* obs;
if (_something_checkedout) {
obs = filter(deep_inventory(this_object()), (: is_checkout_object($1) :));
if (sizeof(obs)) {
foreach (ob in obs) {
destroy_checkout_object(ob);
}
}
tell_room(this_object(), query_multiple_short(obs) +
" mysteriously check themselves back in.\n");
}
} /* return_all_checkedout_objects() */
/** @ignore yes */
void dest_me() {
::dest_me();
} /* dest_me() */
/**
* @ignore yes
* In a player run shop we change this so that only allowed people can change
* an item once it is sold.
*/
int is_able_to_change(object ob) {
return is_allowed(this_player()->query_name()) ||
is_helper(this_player()->query_name());
} /* is_able_change_ob() */
/**
* @ignore yes
*/
int do_buy(object *obs, int force) {
if (!is_open_for("buy", this_player()->query_name()) ||
!is_open_for("use", this_player()->query_name())) {
add_failed_mess("You cannot buy anything at this shop.\n");
return 0;
}
return ::do_buy(obs, force);
} /* do_buy() */
/**
* This method runs through the objects and checks to see what sort of levels
* they are allowed to sell them for to this shop.
* @return 1 on success, 0 on failure
*/
int do_check_sell(object *obs) {
int *stuff;
object ob;
string ret;
string place;
place = query_property("place");
if (!place) {
place = "default";
}
ret = "";
foreach (ob in obs) {
stuff = query_maximum_sale_value_both(this_player()->query_name(), ob);
ret += "$I$5=$C$" + the_short() + ": ";
if (stuff[0]) {
ret += "will be queued for more than " +
MONEY_HAND->money_value_string(stuff[0], place);
}
if (stuff[0] && stuff[1]) {
ret += " and ";
}
if (stuff[1]) {
ret += "will be denied for more than " +
MONEY_HAND->money_value_string(stuff[1], place);
}
ret += ".\n";
}
write("$P$Check Sell$P$" + ret);
add_succeeded_mess(({ "", "$N checks the sale of $I.\n" }), obs);
return 1;
} /* do_check_sell() */
/**
* List the items for approval.
*/
int do_list_approval(int approved) {
class approval_obs approve;
int pos;
int shown;
int allowed;
int checkout;
string place;
string ret;
object* obs;
object *current;
object* result;
string *possible_names;
string start;
mapping result_type;
int i;
int fluff;
place = query_property("place");
if (!place) {
place = "default";
}
allowed = is_allowed(this_player()->query_name()) ||
is_helper(this_player()->query_name());
if (!allowed) {
approved = 1;
}
if (!approved) {
start = "-";
} else {
start = "";
}
result_type = ([ ]);
ret = "";
while (allowed || approved) {
if (approved == 2) {
approved = 0;
start = "-";
}
foreach (approve in query_approval_list(approved)) {
if (lower_case(approve->seller) == this_player()->query_name() ||
allowed) {
checkout = sizeof(filter(approve->checkout, (: $1 :)));
/*
if (sizeof(approve) == 7) {
possible_names = ({ "womble" });
} else {
possible_names = approve->shorts;
}
*/
obs = ({ });
for (i = 0; i < sizeof(approve->saved); i++) {
fluff = approve->saved[i];
obs += ({ create_real_auto_load_object(fluff, this_player()) });
}
obs -= ({ 0 });
possible_names = obs->query_short();
obs->move("/room/rubbish");
if (!result_type[lower_case(approve->name)]) {
if (!current) {
current = map(query_controller()->query_sell_list_obs(),
(: query_controller()->query_short_of_shop_object($1) :));
}
// Intersection.
result = current & possible_names;
/*
filter(current,
(: member_array($1->query_short(),
$(possible_names)) > -1 :));
*/
result_type[lower_case(approve->name)] = sizeof(result);
}
ret += start + query_letter_value(pos) + ") " +
approve->seller + "'s " + approve->name + " for " +
MONEY_HAND->money_value_string(approve->value, place) +
" in " + approve->category + ", " +
sizeof(approve->saved) + " objects (" +
query_multiple_short(obs) + ") " +
result_type[lower_case(approve->name)] + " in stock";
if (checkout) {
ret += " and " + checkout + " checked out.\n";
} else {
ret += ".\n";
}
shown++;
}
pos++;
}
if (!allowed && approved) {
approved = 2;
pos = 0;
} else {
break;
}
}
if (sizeof(current)) {
current->dest_me();
}
if (!shown) {
add_failed_mess("No items to approve at the moment.\n");
return 0;
}
write("$P$Approval list$P$The current approval items are:\n" + ret);
return 1;
} /* do_list_approval() */
/**
* This method returns the item to the person that started to sell it.
* This only works before the item has been approved.
* @param name the name of the item to return
*/
int do_return(string name) {
object *obs;
object *ok;
object *here;
object *fail;
object *checkout;
object money;
class approval_obs approve;
object ob;
int pos;
int i;
int value;
string place;
approve = query_approval_class(name);
if (!approve) {
return 0;
}
if (lower_case(approve->seller) != this_player()->query_name()) {
add_failed_mess("You must be the one that sold the item to return "
"it.\n");
return 0;
}
obs = ({ });
checkout = ({ });
if (sizeof(filter(approve->checkout, (: $1 :))) > 0 &&
_something_checkedout) {
//
// Try and return it.
//
return_all_checkedout_objects();
}
for (i = 0; i < sizeof(approve->saved); i++) {
pos = approve->saved[i];
if (!approve->checkout[i]) {
obs += ({ create_real_auto_load_object(pos, this_player()) });
} else {
checkout += ({ create_real_auto_load_object(pos, this_player()) });
}
}
obs -= ({ 0 });
checkout -= ({ 0 });
if (sizeof(checkout)) {
place = query_property("place");
if (!place) {
place = "default";
}
write("The items " + query_multiple_short(checkout) +
" are currently checked out. You are reimbused the amount "
"they would have cost to sell.\n");
value = approve->value * sizeof(checkout);
money = MONEY_HAND->make_new_amount( value, place);
money->move(this_player());
_total_outgoing += approve->value * sizeof(checkout);
}
ok = ({ });
here = ({ });
fail = ({ });
foreach (ob in obs) {
if (ob->move(this_player()) == MOVE_OK) {
ok += ({ ob });
} else if (ob->move(environment(this_player()))) {
here += ({ ob });
} else {
fail += ({ ob });
}
}
remove_from_approval_list(approve);
if (sizeof(ok)) {
add_succeeded_mess("$N return$s $I.\n", map(ok, (: $1->poss_short() :)));
}
if (sizeof(here)) {
add_succeeded_mess("$N $V their $I and they get put on the floor.\n",
map(ok, (: $1->poss_short() :)));
}
if (sizeof(fail)) {
add_succeeded_mess( ({ "You find that $I do not want to be moved.\n",
"" }), fail);
}
return 1;
} /* do_return() */
/**
* This method approves the specified item.
*/
int do_approve_item(string name, string money_str) {
int cost;
object *obs;
class approval_obs approve;
string place;
int final_cost;
int num;
if (!is_allowed(this_player()->query_name()) &&
!is_helper(this_player()->query_name())) {
add_failed_mess("You are not allowed to approve items.\n");
return 0;
}
approve = query_approval_class(name);
if (!approve) {
return 0;
}
place = query_property("place");
if (!place) {
place = "default";
}
if (query_owners_money() < 0) {
add_failed_mess("You cannot do this until the shop's deficit is payed "
"off.\n");
return 0;
}
num = sizeof(query_controller()->query_sell_list_obs());
if (num + sizeof(approve->saved) > query_maximum_inventory_size()) {
add_failed_mess("You cannot approve anything, the shop is already "
"at the maximum number allowed.\n");
return 0;
}
cost = approve->value * sizeof(obs);
if (this_player()->query_value_in(place) < cost) {
add_failed_mess("You need at least " +
MONEY_HAND->money_value_string(cost, place) +
" to put this into the shop.\n");
return 0;
}
if (money_str) {
final_cost = MONEY_HAND->value_from_string(money_str, place);
if (!final_cost) {
add_failed_mess("The amount " + money_str + " is not a valid "
"money cost.\n");
return 0;
}
}
if (sizeof(filter(approve->checkout, (: $1 :))) > 0 &&
_something_checkedout) {
//
// Try and return it.
//
write("One of these objects is still checkedout, do you wish to "
"continue this without these items? ");
input_to("confirm_approval", 0, approve, final_cost);
add_succeeded_mess( ({ "", "$N approves something in the shop.\n" }) );
return 1;
}
confirm_approval("y", approve, final_cost);
return 1;
} /* do_approve_item() */
/**
* This method resets all the weekly stats information back to zero.
*/
void reset_weekly_status() {
_weekly_stats = new(class weekly_stats);
_weekly_stats->num_sold = 0;
_weekly_stats->total_cost = 0;
_weekly_stats->total_made = 0;
_weekly_stats->num_bought = 0;
//_weekly_stats->items = ([ ]);
_weekly_stats->helper = ([ ]);
} /* reset_weekly_stats() */
/**
* This method returns a nice string representation of the weekly stats.
* @return the string representation of the weekly stats
*/
string query_weekly_status_string() {
string ret;
string place;
string player;
class helper_stats helpers;
class item_stats items;
string* item_bits;
string item;
int num;
place = query_property("place");
ret = "$I$0=Total Outgoing : " +
MONEY_HAND->money_value_string(_weekly_stats->total_cost, place) + "\n";
ret += "$I$0=Total Incoming : " +
MONEY_HAND->money_value_string(_weekly_stats->total_made, place) + "\n";
if (_weekly_stats->total_made > _weekly_stats->total_cost) {
ret += "$I$0=Profit of : " +
MONEY_HAND->money_value_string(_weekly_stats->total_made - _weekly_stats->total_cost, place) + "\n";
} else {
ret += "$I$0=Loss of : " +
MONEY_HAND->money_value_string(-(_weekly_stats->total_made - _weekly_stats->total_cost), place) + "\n";
}
ret += "$I$0=Items : " +
_weekly_stats->num_sold + " sold and " +
_weekly_stats->num_bought + " bought.\n";
ret += "\n$I$0=Player summaries:\n";
foreach (player, helpers in _weekly_stats->helper) {
item_bits = ({ });
if (sizeof(helpers->items_approved)) {
foreach (item, num in helpers->items_approved) {
item_bits += ({ num + " " + item });
}
} else {
item_bits = ({ "nothing" });
}
ret += "$I$6= " + player + ": " + helpers->num_approved +
" approved, " + helpers->num_rejected + " rejected, " +
MONEY_HAND->money_value_string(helpers->total_cost, place) +
" approved " + query_multiple_short(item_bits) + "\n";
}
/*
ret += "\n$I$0=Item Summaries:\n";
foreach (item, items in _weekly_stats->items) {
ret += "$I$6= " + item + ": " + items->num_sold + " sold, " +
items->num_bought + " bought. Cost " +
MONEY_HAND->money_value_string(items->total_cost, place) +
", made " +
MONEY_HAND->money_value_string(items->total_made, place) +
", profit " +
MONEY_HAND->money_value_string(items->total_made - items->total_cost, place) + "\n";
}
*/
return ret;
} /* query_weekly_stats_string() */
/**
* This method is called when an item is approved so people can do whatever
* they want to about it. In this case, we keep track of statistics.
* @param name the name of the peron doing the approval
* @param cost the cost it ws approved for
* @param approve the approval class
*/
protected void inform_of_approved_item(string name,
int cost,
class approval_obs approve) {
string str;
//
// Weekly stats data management.
//
if (!_weekly_stats) {
_weekly_stats = new(class weekly_stats);
_weekly_stats->items = ([ ]);
_weekly_stats->helper = ([ ]);
}
_weekly_stats->total_cost += cost;
str = approve->name; // + " in " + approve->category;
/*
if (!_weekly_stats->items[str]) {
_weekly_stats->items[str] = new(class item_stats);
}
_weekly_stats->items[str]->num_bought++;
_weekly_stats->items[str]->total_cost += cost;
*/
name = this_player()->query_name();
if (!_weekly_stats->helper[name]) {
_weekly_stats->helper[name] = new(class helper_stats);
_weekly_stats->helper[name]->items_approved = ([ ]);
}
_weekly_stats->helper[name]->num_approved++;
_weekly_stats->helper[name]->total_cost += cost;
if (!mapp(_weekly_stats->helper[name]->items_approved)) {
_weekly_stats->helper[name]->items_approved = ([ ]);
}
_weekly_stats->helper[name]->items_approved[str]++;
} /* inform_of_approved_items() */
/**
* This method is called when an item is rejected so people can do whatever
* they want to about it. In this case, we keep track of statistics.
* @param name the name of the peron doing the rejection
* @param approve the approval class
*/
protected void inform_of_rejected_item(string name,
class approval_obs approve) {
//
// Weekly stats data management.
//
if (!_weekly_stats) {
_weekly_stats = new(class weekly_stats);
_weekly_stats->items = ([ ]);
_weekly_stats->helper = ([ ]);
}
name = this_player()->query_name();
if (!_weekly_stats->helper[name]) {
_weekly_stats->helper[name] = new(class helper_stats);
}
_weekly_stats->helper[name]->num_rejected++;
} /* inform_of_rejected_items() */
/** @ignore yes */
protected void confirm_approval(string answer,
class approval_obs approve,
int final_cost) {
int pos;
int i;
int bing;
int cost;
object *obs;
object *bought;
object *checkout;
string place;
if (strlen(answer) < 1 || lower_case(answer)[0] != 'y') {
write("Ok, canceled the approval of the item.\n");
return ;
}
place = query_property("place");
if (!place) {
place = "default";
}
//
// Approval means we create all the objects, remove them, and then
// send them off to the main engine...
//
obs = ({ });
checkout = ({ });
for (i = 0; i < sizeof(approve->saved); i++) {
pos = approve->saved[i];
if (!approve->checkout[i]) {
obs += ({ create_real_auto_load_object(pos, this_player()) });
} else {
checkout += ({ create_real_auto_load_object(pos, this_player()) });
}
}
obs -= ({ 0 });
checkout -= ({ 0 });
if (sizeof(checkout)) {
write("The items " + query_multiple_short(checkout) + " were "
"checked out and therefore lost.\n");
}
if (!final_cost) {
final_cost = ((approve->value * (100 + _automatic_percentage)) / 100);
}
final_cost -= final_cost % _round_value;
obs->remove_property("dropped");
bought = query_controller()->buy_objects(obs, approve->name,
final_cost,
approve->seller, approve->category, 1);
if (sizeof(bought)) {
cost = approve->value * (sizeof(obs) + sizeof(checkout));
cost -= cost % _round_value;
_total_outgoing += cost;
remove_from_approval_list(approve);
adjust_royalty(lower_case(approve->seller), cost);
//
// Try and remove from the cash float first.
//
if (query_owners_money() > 0) {
if (query_owners_money() > cost) {
adjust_owners_money(-cost);
cost = 0;
} else {
cost -= query_owners_money();
adjust_owners_money(-query_owners_money());
}
}
if (cost > 0) {
if (this_player()->query_value_in(place) > 0) {
bing = this_player()->query_value_in(place);
if (bing > cost) {
bing = cost;
cost = 0;
} else {
cost -= bing;
}
if (bing) {
this_player()->pay_money(MONEY_HAND->create_money_array(bing, place), place);
}
}
if (cost > 0) {
adjust_owners_money(-cost);
}
}
write("You approve " + query_multiple_short(obs) + " to be sold as " +
approve->name + " in " + approve->category + " for " +
MONEY_HAND->money_value_string(approve->value, place) + ".\n");
add_succeeded_mess( ({ "", "$N approves something in the shop.\n" }) );
// Statistics collection.
cost = approve->value * (sizeof(obs) + sizeof(checkout));
cost -= cost % _round_value;
inform_of_approved_item(this_player()->query_name(),
cost, approve);
add_transaction(this_player()->query_name(),
obs,
PLAYER_CRAFT_SHOP_APPROVE,
approve->value * (sizeof(obs) + sizeof(checkout)),
approve->name + " in " + approve->category,
approve->seller);
} else {
write("Unable to move the items into the shops inventory, you "
"will need to reject this item.\n");
}
return ;
} /* do_approve_item() */
/**
* This method rejects the specified item.
*/
int do_approve_reject(string name, string mess, int reject_pos) {
object *obs;
object *ok;
object *here;
object *checkout;
object ob;
object play;
class approval_obs approve;
int pos;
int i;
int ret;
string ob_mess;
approve = query_approval_class(name);
if (!approve) {
return 0;
}
if (lower_case(approve->seller) == this_player()->query_name()) {
//
// Return the stuff to them.
//
return do_return(name);
}
if (!is_allowed(this_player()->query_name()) &&
!is_helper(this_player()->query_name())) {
add_failed_mess("You're not allowed to reject items.\n");
return 0;
}
if (sizeof(filter(approve->checkout, (: $1 :))) > 0 &&
_something_checkedout) {
//
// Try and return it.
//
return_all_checkedout_objects();
}
if (reject_pos != -1 &&
(reject_pos <= 0 ||
reject_pos > sizeof(approve->saved))) {
add_failed_mess("You cannot reject the item of position " + reject_pos +
" since there are only " + sizeof(approve->saved) +
" items.\n");
return 0;
}
if (reject_pos != -1) {
reject_pos--;
}
//
// Approval means we create all the objects, remove them, and then
// send them off to the main engine...
//
obs = ({ });
checkout = ({ });
for (i = 0; i < sizeof(approve->saved); i++) {
if (reject_pos == -1 ||
reject_pos == i) {
pos = approve->saved[i];
if (!approve->checkout[i]) {
obs += ({ create_real_auto_load_object(pos, this_player()) });
} else {
checkout += ({ create_real_auto_load_object(pos, this_player()) });
}
}
}
obs = filter(obs, (: $1 && objectp($1) :));
checkout = filter(checkout, (: $1 && objectp($1) :));
if (member_array(0, obs) != -1) {
add_failed_mess("There seems to be a problem with this rejection set, "
"one of the items is 0.\n");
return 0;
}
if (reject_pos != -1 && sizeof(checkout)) {
add_failed_mess("The item $I has been checked out, you cannot reject "
"it.\n", checkout);
return 0;
}
if (sizeof(checkout)) {
write("The items " + query_multiple_short(checkout) + " were "
"checked out and lost.\n");
adjust_royalty(lower_case(approve->seller),
approve->value * sizeof(checkout));
AUTO_MAILER->auto_mail(lower_case(approve->seller),
this_player()->query_name(),
"Rejected items", "",
sprintf("%-=75s",
this_player()->query_name() + " lost your " +
query_multiple_short(checkout, "the", 1) +
",so you have been paid but the items "
"were not returned.\n"));
}
inform_of_rejected_item(this_player()->query_name(), approve);
if (!sizeof(obs)) {
write("Nothing to give back or send off.\n");
} else {
//
// They are here, so give it back.
//
play = find_player(lower_case(approve->seller));
if (play && environment(play) == this_object()) {
ok = ({ });
here = ({ });
foreach (ob in obs) {
if (ob) {
if (ob->move(play) == MOVE_OK) {
ok += ({ ob });
} else if (ob->move(environment(play)) == MOVE_OK) {
here += ({ ob });
}
}
}
if (sizeof(ok)) {
tell_object(play, "Your items: " +
query_multiple_short(obs) + " have been rejected "
"and placed in your inventory.\n");
}
if (sizeof(here)) {
tell_object(play, "Your items: " +
query_multiple_short(obs) + " have been rejected "
"and placed on the floor here.\n");
}
write("You reject the item.\n");
} else {
if (!query_parcel_post()) {
add_failed_mess("Eeek! No parcel post defined on this room.\n");
return 0;
} else if(!load_object(query_parcel_post())) {
add_failed_mess("Eeek! Parcel post cannot be loaded.\n");
return 0;
}
ob_mess = "The shop " + this_player()->convert_message(the_short()) +
" rejected " + query_multiple_short(obs, "the", 1) +
" because:\n";
if (!mess) {
mess = "They didn't want to add a reject message.";
}
ret = query_parcel_post()->deposit_parcel(obs, lower_case(approve->seller), 1);
if (ret != 1) {
if (ret == -5) {
write("The player " + approve->seller + " has been denied use "
"of the parcel post system, tossing objects away.\n");
obs->move("/room/rubbish");
if (mess) {
write("Still sending the message to the person.\n");
mess += "\nYou were denied use of the parcel post system "
"so your objects were thrown away.\n";
}
} else if (ret == -4) {
write("You have been denied use of the postal system, perhaps "
"you could try clearing this up with the creators?\n");
obs->move("/room/rubbish");
return 1;
} else if (ret == -2) {
write("The player " + approve->seller + " no longer exists, "
"tossing objects away.\n");
obs->move("/room/rubbish");
} else {
add_failed_mess("Unable to send the parcel for some reason (" +
ret + ").\n");
obs->move("/room/rubbish");
return 0;
}
}
if (ret != -2) {
if (mess) {
AUTO_MAILER->auto_mail(approve->seller, this_player()->query_name(),
"Rejected items", "",
ob_mess + mess);
} else {
write("You reject the item and it is parcel posted back to the "
"person who "
"sent it.\nWould you like to send them a note about it as well? ");
obs -= ({ 0 });
input_to("check_reject_note", 0, ob_mess,
approve->seller);
}
}
}
}
if (reject_pos != -1) {
approve->saved = approve->saved[0..reject_pos-1] + approve->saved[reject_pos+1..];
event_save(this_object());
if (!sizeof(approve->saved)) {
reject_pos = -1;
}
}
if (reject_pos == -1) {
remove_from_approval_list(approve);
}
add_succeeded_mess(({ "", "$N reject$s a sellable object.\n" }));
return 1;
} /* do_approve_reject() */
/**
* @ignore yes
*/
void check_reject_note(string str, string ob_str, string name) {
str = lower_case(str);
if (!strlen(str) ||
(str[0] != 'y' &&
str[0] != 'n')) {
write("Please answer yes or no.\nWould you like to send them "
"a note about it as well?");
input_to("check_reject_note", 0, ob_str, name);
return ;
}
if (str[0] == 'n') {
write("ok, bye then!\n");
return ;
}
this_player()->do_edit("Your items " + ob_str + " were rejected "
"from " + the_short() + ".\n\n",
"send_reject_note", this_object(), 0, name);
} /* check_reject_note() */
/** @ignore yes */
void send_reject_note(string mess, string name) {
if (!mess) {
write("Aborted.\n");
return ;
}
//write("Sending to " + name + ".\n");
AUTO_MAILER->auto_mail(name, this_player()->query_name(),
"Rejected items", "", mess);
} /* send_reject_note() */
/**
* This method browses the specified item.
*/
int do_approve_browse(string name) {
object *obs;
object ob;
string read;
string ret;
string bits;
class approval_obs approve;
int pos;
string place;
approve = query_approval_class(name);
if (!approve) {
return 0;
}
if (lower_case(approve->seller) == this_player()->query_name()) {
//
// Return the stuff to them.
//
return do_return(name);
}
if (!is_allowed(this_player()->query_name()) &&
!is_helper(this_player()->query_name())) {
add_failed_mess("You are not allowed to reject items.\n");
return 0;
}
if (query_owners_money() < 0) {
add_failed_mess("You cannot do this until the shop's deficit is payed "
"off.\n");
return 0;
}
place = query_property("place");
if (!place) {
place = "default";
}
//
// Create the objects, browse them, kill them.
//
obs = ({ });
foreach (pos in approve->saved) {
obs += ({ create_real_auto_load_object(pos, this_player()) });
}
obs -= ({ 0 });
ret = "";
foreach (ob in obs) {
ret += ob->the_short() + ": (Base cost " +
MONEY_HAND->money_value_string(ob->query_base_value(), place) +
"; scaled cost " +
MONEY_HAND->money_value_string(ob->query_value(), place) +
")\n" + ob->long();
read = ob->query_readable_message();
if (read) {
bits = ob->query_read_short(this_player());
if (!bits) {
bits = "$name$";
}
ret += "You read " +
replace_string(ob->query_read_short(this_player()), "$name$",
ob->a_short()) + ":\n" +
ob->query_readable_message();
}
}
obs->move("/room/rubbish");
write("$P$Browse list$P$" + ret);
add_succeeded_mess("$N browse$s an item waiting for approval.\n");
return 1;
} /* do_approve_browse() */
/**
* This method checks out the specified item.
*/
int do_approve_checkout(string name) {
object *obs;
object *bad;
object *checkout;
object ob;
class approval_obs approve;
int pos;
int i;
approve = query_approval_class(name);
if (!approve) {
return 0;
}
if (lower_case(approve->seller) == this_player()->query_name() &&
lower_case(approve->seller) != "pinkfish") {
//
// Return the stuff to them.
//
return do_return(name);
}
if (!is_allowed(this_player()->query_name()) &&
!is_helper(this_player()->query_name())) {
add_failed_mess("You are not allowed to reject items.\n");
return 0;
}
if (query_owners_money() < 0) {
add_failed_mess("You cannot do this until the shop's deficit is payed "
"off.\n");
return 0;
}
//
// Create the objects, browse them, kill them.
//
obs = ({ });
checkout = ({ });
for (i = 0; i < sizeof(approve->saved); i++) {
pos = approve->saved[i];
if (!approve->checkout[i]) {
ob = create_checkout_object(approve, pos, this_player());
if (!ob) {
write("Unable to create " + pos + approve->name + ", weird...\n");
} else {
obs += ({ ob });
}
} else {
checkout += ({ create_checkout_object(approve, pos, this_player()) });
}
}
checkout->move("/room/rubbish");
if (!sizeof(obs) &&
sizeof(checkout)) {
if (sizeof(checkout) > 0) {
add_failed_mess("$I are already checked out.\n", checkout);
} else {
add_failed_mess("$I is already checked out.\n", checkout);
}
return 0;
}
bad = ({ });
foreach (ob in obs) {
if (ob->move(this_player()) != MOVE_OK) {
bad += ({ ob });
destroy_checkout_object(ob);
}
}
if (sizeof(bad)) {
write("Unable to move " + query_multiple_short(bad) + " into your "
"inventory for you to check.\n");
}
obs -= bad;
if (sizeof(obs)) {
write("Moved " + query_multiple_short(obs) + " into your inventory "
"for you to check.\n");
add_succeeded_mess("$N check$s out $I.\n", obs);
}
return 1;
} /* do_approve_checkout() */
/**
* This method checks in a checked out object.
*/
int do_approve_checkin(object* obs) {
object ob;
object* ok;
ok = ({ });
foreach (ob in obs) {
if (is_checkout_object(ob)) {
destroy_checkout_object(ob);
ok += ({ ob });
}
}
if (!sizeof(ok)) {
add_failed_mess("None of $I have been checked out.\n", obs);
return 0;
}
add_succeeded_mess("$N check$s $I back in.\n", ok);
return 1;
} /* do_approve_checkin() */
/**
* This method changes the name of the item to be approved.
* @param name the reference
* @param new_name the new name for the item
*/
int do_approve_name_change(string name, string new_name) {
class approval_obs approve;
if (!is_allowed(this_player()->query_name()) &&
!is_helper(this_player()->query_name())) {
add_failed_mess("You are not allowed to approve items.\n");
return 0;
}
if (query_owners_money() < 0) {
add_failed_mess("You cannot do this until the shop's deficit is payed "
"off.\n");
return 0;
}
approve = query_approval_class(name);
if (!approve) return 0;
write("You change the name of the item waiting to be approved from " +
approve->name + " to " + new_name + ".\n");
approve->name = new_name;
add_succeeded_mess( ({ "", "$N messes with the approval items.\n" }));
event_save(this_object());
return 1;
} /* do_approve_name_change() */
/**
* This method changes the category of the item waiting to be approved.
* @param name the reference
* @param new_category the new category for the item
*/
int do_approve_category_change(string name, string new_category) {
class approval_obs approve;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to approve items.\n");
return 0;
}
approve = query_approval_class(name);
if (!approve) {
return 0;
}
if (query_owners_money() < 0) {
add_failed_mess("You cannot do this until the shop's deficit is payed "
"off.\n");
return 0;
}
new_category = query_real_category_name(new_category);
if (!new_category ||
!query_controller()->is_valid_category(new_category)) {
add_failed_mess("You must choose a category that exists.\n");
return 0;
}
approve->category = new_category;
add_succeeded_mess(({
"You change the category of the approval item " + name + ".\n",
"$N messes with the approval items.\n" }));
event_save(this_object());
return 1;
} /* do_approve_category_change() */
/**
* This method sets the automatic low acception level.
* @param cost the cost to use a low level
*/
int do_approve_auto_low(string cost) {
string place;
int value;
place = query_property("place");
if (!place) {
place = "default";
}
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to set automatic approval items.\n");
return 0;
}
if (query_owners_money() < 0) {
add_failed_mess("You cannot do this until the shop's deficit is payed "
"off.\n");
return 0;
}
value = value_from_string(cost, place);
_automatic_approval->low_cost = value;
event_save(this_object());
if (!value) {
add_succeeded_mess(({ "You disable the automatic acception of items of "
"low value.\n",
"$N fiddle$s with something in the shop.\n" }) );
return 1;
}
add_succeeded_mess(({ "You set the shop to automatically accept any item "
"costing less than " +
MONEY_HAND->money_value_string(value, place) + ".\n",
"$N fiddle$s with something in the shop.\n" }) );
return 1;
} /* do_approve_auto_low() */
/**
* This method sets the automatic high cut off level.
* @param cost the cost to use a high cut off level
*/
int do_approve_auto_high(string cost) {
string place;
int value;
place = query_property("place");
if (!place) {
place = "default";
}
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to set automatic approval items.\n");
return 0;
}
if (query_owners_money() < 0) {
add_failed_mess("You cannot do this until the shop's deficit is payed "
"off.\n");
return 0;
}
value = value_from_string(cost, place);
if (!value) {
_automatic_approval->high_cost = value;
add_succeeded_mess(({ "You disable the automatic placing items into the "
"approve list of items of high value.\n",
"$N fiddle$s with something in the shop.\n" }) );
return 1;
}
_automatic_approval->high_cost = value;
event_save(this_object());
add_succeeded_mess(({ "You set the shop to automatically put any item "
"costing more than " +
MONEY_HAND->money_value_string(value, place) +
" into the approve list.\n",
"$N fiddle$s with something in the shop.\n" }) );
return 1;
} /* do_approve_auto_high() */
/**
* This method sets the automatic high cut off level for denying sales.
* @param cost the cost to use a high cut off level
*/
int do_approve_auto_high_deny(string cost) {
string place;
int value;
place = query_property("place");
if (!place) {
place = "default";
}
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to set automatic approval items.\n");
return 0;
}
if (query_owners_money() < 0) {
add_failed_mess("You cannot do this until the shop's deficit is payed "
"off.\n");
return 0;
}
value = value_from_string(cost, place);
if (!value) {
_automatic_approval->high_cost_deny = 0;
add_succeeded_mess(({ "You disable the automatic denying of items of "
"high value.\n",
"$N fiddle$s with something in the shop.\n" }) );
return 1;
}
_automatic_approval->high_cost_deny = value;
event_save(this_object());
add_succeeded_mess(({ "You set the shop to automatically deny any item "
"costing more than " +
MONEY_HAND->money_value_string(value, place) + ".\n",
"$N fiddle$s with something in the shop.\n" }) );
return 1;
} /* do_approve_auto_high() */
/**
* This method sets the automatic items to allow.
* @param item the items short to allow
*/
int do_approve_auto_item_add(string item, string money, string list_name,
int markup, string money_str) {
int value;
string place;
int final_cost;
mixed app_item;
class approval_item new_app_item;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to set automatic approval items.\n");
return 0;
}
if (query_owners_money() < 0) {
add_failed_mess("You cannot do this until the shop's deficit is payed "
"off.\n");
return 0;
}
place = query_property("place");
if (!place) {
place = "default";
}
value = value_from_string(money, place);
if (!value) {
add_failed_mess("The value " + money + " is invalid.\n");
return 0;
}
if (markup < 0) {
markup = 0;
}
item = strip_quotes(item);
list_name = strip_quotes(list_name);
if (classp(_automatic_approval->items[item])) {
app_item = ((class approval_item)_automatic_approval->items[item])->value;
} else {
app_item = _automatic_approval->items[item];
}
if (app_item == value) {
add_failed_mess("The item " + item + " already has a cut off "
"value of " +
MONEY_HAND->money_value_string(value, place) + ".\n");
return 0;
}
if (money_str) {
final_cost = MONEY_HAND->value_from_string(money_str, place);
if (!final_cost) {
add_failed_mess(money_str + " is an invalid money value.\n");
return 0;
}
}
new_app_item = new(class approval_item);
new_app_item->list_name = list_name;
new_app_item->value = value;
new_app_item->markup = markup;
new_app_item->final_cost = final_cost;
_automatic_approval->items[item] = new_app_item;
place = query_property("place");
event_save(this_object());
add_succeeded_mess(({ "You set the shop to automatically accept any item "
"with a short of " + item + " up to a cost "
"of " + MONEY_HAND->money_value_string(value, place) +
(list_name ? " as \"" + list_name + "\"" : "") +
(markup ? " with a markup of " + markup + "%" : "") +
(final_cost ? " with a final cost of " +
MONEY_HAND->money_value_string(final_cost, place) + "" : "") +
".\n",
"$N fiddle$s with something in the shop.\n" }) );
return 1;
} /* do_approve_auto_item_add() */
/**
* This method sets the automatic items to allow.
* @param item the items short to allow
*/
int do_approve_auto_item_add_object(object *obs, string money,
string list_name, int markup,
string money_str) {
int value;
string place;
object ob;
string name;
object *ok;
object *bad;
mixed item;
class approval_item new_item;
int final_cost;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to set automatic approval items.\n");
return 0;
}
if (query_owners_money() < 0) {
add_failed_mess("You cannot do this until the shop's deficit is payed "
"off.\n");
return 0;
}
place = query_property("place");
if (!place) {
place = "default";
}
value = value_from_string(money, place);
if (!value) {
add_failed_mess("The value " + money + " is invalid.\n");
return 0;
}
if (money_str) {
final_cost = MONEY_HAND->value_from_string(money_str, place);
if (!final_cost) {
add_failed_mess(money_str + " is an invalid money value.\n");
return 0;
}
}
if (markup < 0) {
markup = 0;
}
bad = ({ });
ok = ({ });
list_name = strip_quotes(list_name);
foreach (ob in obs) {
name = ob->query_short();
if (classp(_automatic_approval->items[name])) {
item = ((class approval_item)_automatic_approval->items[name])->value;
} else {
item = _automatic_approval->items[name];
}
if (item == value) {
bad += ({ name });
} else {
new_item = new(class approval_item);
new_item->value = value;
new_item->list_name = list_name;
new_item->markup = markup;
new_item->final_cost = final_cost;
_automatic_approval->items[name] = new_item;
ok += ({ name });
}
}
event_save(this_object());
if (sizeof(ok)) {
add_succeeded_mess(({ "You set the shop to automatically accept any of "
"$I up to a cost "
"of " + MONEY_HAND->money_value_string(value, place) +
(list_name ? " as \"" + list_name + "\"" : "") +
(markup ? " with a markup of " + markup + "%" : "") +
(final_cost ? " with a final cost of " +
MONEY_HAND->money_value_string(final_cost, place) + "" : "") +
".\n",
"$N fiddle$s with something in the shop.\n" }), ok );
return 1;
} else {
add_failed_mess("You cannot set $I to a value limit of " +
MONEY_HAND->money_value_string(value, place) +
" since it already has this limit.\n");
return 0;
}
} /* do_approve_auto_item_add_object() */
/**
* This method sets the automatic items to allow.
* @param item the items short to allow
*/
int do_approve_auto_item_add_expr(string item, string expr,
string list_name, int markup,
string money_str) {
class approval_item new_app_item;
class parse_node* value;
string place;
int final_cost;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to set automatic approval items.\n");
return 0;
}
if (query_owners_money() < 0) {
add_failed_mess("You cannot do this until the shop's deficit is payed "
"off.\n");
return 0;
}
place = query_property("place");
if (!place) {
place = "default";
}
value = parse_money_string(expr);
if (!sizeof(value)) {
add_failed_mess(query_last_expression_error() + ".\n");
return 0;
}
if (money_str) {
final_cost = MONEY_HAND->value_from_string(money_str, place);
if (!final_cost) {
add_failed_mess(money_str + " is an invalid money value.\n");
return 0;
}
}
if (markup < 0) {
markup = 0;
}
item = strip_quotes(item);
list_name = strip_quotes(list_name);
new_app_item = new(class approval_item);
new_app_item->list_name = list_name;
new_app_item->value = value;
new_app_item->markup = markup;
new_app_item->final_cost = final_cost;
_automatic_approval->items[item] = new_app_item;
event_save(this_object());
add_succeeded_mess(({ "You set the shop to automatically accept any item "
"with a short of " + item + " with an expression "
"of " + query_expression_string(value, 1) +
(list_name ? " as \"" + list_name + "\"" : "") +
(markup ? " with a markup of " + markup + "%" : "") +
(final_cost ? " with a final cost of " +
MONEY_HAND->money_value_string(final_cost, place) + "" : "") +
".\n",
"$N fiddle$s with something in the shop.\n" }) );
return 1;
} /* do_approve_auto_item_add_expr() */
/**
* This method sets the automatic items to allow.
* @param item the items short to allow
*/
int do_approve_auto_item_add_object_expr(object *obs, string expr,
string list_name, int markup, string money_str) {
class parse_node* value;
object ob;
string name;
class approval_item new_item;
int final_cost;
string place;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to set automatic approval items.\n");
return 0;
}
if (query_owners_money() < 0) {
add_failed_mess("You cannot do this until the shop's deficit is payed "
"off.\n");
return 0;
}
value = parse_money_string(expr);
if (!sizeof(value)) {
add_failed_mess(query_last_expression_error() + ".\n");
return 0;
}
if (money_str) {
place = query_property("place");
final_cost = MONEY_HAND->value_from_string(money_str, place);
if (!final_cost) {
add_failed_mess(money_str + " is an invalid money value.\n");
return 0;
}
}
if (markup < 0) {
markup = 0;
}
list_name = strip_quotes(list_name);
foreach (ob in obs) {
name = ob->query_short();
new_item = new(class approval_item);
new_item->value = value;
new_item->list_name = list_name;
new_item->markup = markup;
new_item->final_cost = final_cost;
_automatic_approval->items[name] = new_item;
}
event_save(this_object());
add_succeeded_mess(({ "You set the shop to automatically accept any of "
"$I with an expression "
"of " + query_expression_string(value, 1) +
(list_name ? " as \"" + list_name + "\"" : "") +
(markup ? " with a markup of " + markup + "%" : "") +
(final_cost ? " with a final cost of " +
MONEY_HAND->money_value_string(final_cost, place) + "" : "") +
".\n",
"$N fiddle$s with something in the shop.\n" }), obs );
return 1;
} /* do_approve_auto_item_add_object_expr */
/**
* This method checks to see if the specified object can really be sold or
* not automatically.
* @param obs the objects to test
*/
int do_approve_auto_item_test(object* obs) {
object ob;
string place;
mixed cost;
int found;
int allowed;
class expression_type stuff;
class parse_node frog;
allowed = is_allowed(this_player()->query_name()) ||
is_helper(this_player()->query_name());
place = query_property("place");
if (!place) {
place = "default";
}
foreach (ob in obs) {
found = 0;
cost = _automatic_approval->items[ob->query_short()];
if (classp(cost)) {
cost = ((class approval_item)cost)->value;
}
if (cost) {
if (pointerp(cost)) {
frog = evaluate_expression(cost, this_player()->query_name(),
0, ({ ob }), 0, 0);
if (allowed) {
write("$I$5=The item " + ob->the_short() + " can be sold if it "
"costs less than " +
query_expression_string(cost, 1) +
";\n" + ob->query_short() + " - " +
MONEY_HAND->money_value_string(frog->value, place) +
".\n");
} else {
write("$I$5=The item " + ob->the_short() + " can be sold if it "
"costs less than " +
" " + MONEY_HAND->money_value_string(frog->value, place) +
".\n");
}
} else {
write("$I$5=The item " + ob->the_short() + " can be sold if it "
"costs less than " +
MONEY_HAND->money_value_string(cost, place) +
" (" + ob->query_short() + ").\n");
}
found |= 1;
}
foreach (stuff in _automatic_approval->expressions) {
frog = evaluate_expression(stuff->condition,
this_player()->query_name(),
0, ({ ob }), 0, 0);
if (frog->value) {
if (stuff->type == PLAYER_CRAFT_SHOP_EXPR_ACCEPT) {
frog = evaluate_expression(stuff->value,
this_player()->query_name(),
0, ({ ob }), 0, 0);
if (allowed) {
write("$I$5=The item " + ob->the_short() +
" can be sold if it "
"costs less than " +
query_expression_string(stuff->value, 1) +
";\n" + ob->query_short() + " - " +
MONEY_HAND->money_value_string(frog->value, place) +
".\n");
} else {
write("$I$5=The item " + ob->the_short() +
" can be sold if it "
"costs less than " +
MONEY_HAND->money_value_string(frog->value, place) +
".\n");
}
found |= 2;
} else {
// Denied!
found |= 4;
}
}
}
if (found & 4) {
write("$I$5=The item " + ob->the_short() + " will be denied sale.\n");
}
else if (!found) {
write("$I$5=The item " + ob->the_short() + " will not be "
"automatically accepted.\n");
}
}
add_succeeded_mess(({ "",
"$N fiddle$s with something in the shop.\n" }) );
return 1;
} /* do_approve_auto_item_test() */
/**
* This method sets the automatic items to allow.
* @param item the item to accept
*/
int do_approve_auto_item_remove(string item) {
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to set automatic approval items.\n");
return 0;
}
if (query_owners_money() < 0) {
add_failed_mess("You cannot do this until the shop's deficit is payed "
"off.\n");
return 0;
}
item = strip_quotes(item);
if (!_automatic_approval->items[item]) {
add_failed_mess("The item " + item + " is not in the list.\n");
return 0;
}
map_delete(_automatic_approval->items, item);
event_save(this_object());
add_succeeded_mess(({ "You remove the item " + item +
" from the list of automatically accepted items.\n",
"$N fiddle$s with something in the shop.\n" }) );
return 1;
} /* do_approve_auto_item_remove() */
/**
* This method sets the automatic items to allow.
* @param item the item to accept
*/
int do_approve_auto_item_remove_object(object *obs) {
object ob;
object *bad;
object *ok;
string name;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to set automatic approval items.\n");
return 0;
}
if (query_owners_money() < 0) {
add_failed_mess("You cannot do this until the shop's deficit is payed "
"off.\n");
return 0;
}
ok = ({ });
bad = ({ });
foreach (ob in obs) {
name = ob->query_short();
if (!_automatic_approval->items[name]) {
bad += ({ ob });
} else {
ok += ({ ob });
map_delete(_automatic_approval->items, name);
}
}
event_save(this_object());
if (sizeof(ok)) {
add_succeeded_mess(({ "You remove $I from the list of "
"automatically accepted items.\n",
"$N fiddle$s with something in the shop.\n" }), ok );
return 1;
}
add_failed_mess("None of $I are in the shops allow item list for you "
"to remove.\n", bad);
return 0;
} /* do_approve_auto_item_remove() */
/**
* This method sets the automatic expressions to allow.
* @param expression the expressions short to allow
*/
int do_approve_auto_expression_add(string expression, string value_str,
int type, string list_name) {
class parse_node* expr;
class parse_node* value;
class expression_type bing;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to set automatic approval items.\n");
return 0;
}
if (query_owners_money() < 0) {
add_failed_mess("You cannot do this until the shop's deficit is payed "
"off.\n");
return 0;
}
expr = parse_boolean_string(expression);
if (!sizeof(expr)) {
add_failed_mess(query_last_expression_error() + ".\n");
return 0;
}
if (type == PLAYER_CRAFT_SHOP_EXPR_ACCEPT) {
value = parse_money_string(value_str);
if (!sizeof(value)) {
add_failed_mess(query_last_expression_error() + ".\n");
return 0;
}
}
list_name = strip_quotes(list_name);
bing = new(class expression_type);
bing->type = type;
bing->condition = expr;
bing->value = value;
bing->list_name = list_name;
_automatic_approval->expressions += ({ bing });
event_save(this_object());
if (type == PLAYER_CRAFT_SHOP_EXPR_ACCEPT) {
add_succeeded_mess(({ "You set the shop to automatically accept any item "
"matching the expression " +
query_expression_string(expr, 0) + " with a cost "
"of " + query_expression_string(value, 0) +
" as '" + list_name + "'.\n",
"$N fiddle$s with something in the shop.\n" }) );
} else {
add_succeeded_mess(({ "You set the shop to automatically deny any item "
"matching the expression " +
query_expression_string(expr, 0) + ".\n",
"$N fiddle$s with something in the shop.\n" }) );
}
return 1;
} /* do_approve_auto_expression_add() */
/**
* This method removes an allowed expression
* @param id the expression id to remove
*/
int do_approve_auto_expression_remove(string idstr) {
class expression_type expr;
int id;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to set automatic approval items.\n");
return 0;
}
if (query_owners_money() < 0) {
add_failed_mess("You cannot do this until the shop's deficit is payed "
"off.\n");
return 0;
}
id = query_number_value(idstr);
if (id == -1 || id >= sizeof(_automatic_approval->expressions)) {
add_failed_mess("The id " + idstr + " is invalid.\n");
return 0;
}
expr = _automatic_approval->expressions[id];
_automatic_approval->expressions = _automatic_approval->expressions[0..id - 1] +
_automatic_approval->expressions[id + 1..];
event_save(this_object());
add_succeeded_mess(({ "You remove the expression " +
query_expression_string(expr->condition, 1) +
" cost: " +
query_expression_string(expr->value, 1) +
" from the list of allowed expressions.\n",
"$N fiddle$s with something in the shop.\n" }) );
return 1;
} /* do_approve_auto_item_remove() */
/**
* This method sets the percentage to add to the sell price.
* @param num the number to set the percentage to
*/
int do_approve_percentage(mixed num) {
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to set automatic approval items.\n");
return 0;
}
if (query_owners_money() < 0) {
add_failed_mess("You cannot do this until the shop's deficit is payed "
"off.\n");
return 0;
}
if (num <= 0) {
add_failed_mess("The percentage to add must be greator than 0.\n");
return 0;
}
_automatic_percentage = num;
add_succeeded_mess(({ "You set the percentage to add to the sale price "
"to " + _automatic_percentage + ".\n",
"$N fiddle$s with something in the shop.\n" }) );
return 1;
} /* do_approve_percentage() */
/**
* This method sets the limit on number of items sellable by all the players.
* @param limit the default limit
*/
int do_approve_limit(string limit) {
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to set any limits on selling "
"items.\n");
return 0;
}
if (limit == "disable") {
_automatic_approval->num_allowed = 0;
add_succeeded_mess(({ "You disable the default number of sold items "
"per person.\n",
"$N fiddle$s with something in the shop.\n" }) );
return 1;
}
else if (to_int(limit) > 0) {
_automatic_approval->num_allowed = to_int(limit);
add_succeeded_mess(({ "You set the default number of sold items per "
"person to " + _automatic_approval->num_allowed + ".\n",
"$N fiddle$s with something in the shop.\n" }) );
return 1;
}
return 0;
} /* do_approve_limit() */
/**
* This method sets the limit per person to be a specified value.
* @param person the person to set a limit on
* @param value the limit to set
*/
int do_approve_limit_person_items(string name, string value) {
int amt;
class seller_information info;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to set any limits on selling "
"items.\n");
return 0;
}
name = lower_case(name);
if (!PLAYER_HANDLER->test_user(name)) {
add_failed_mess("The person " + name + " does not exist.\n");
return 0;
}
amt = to_int(value);
info = _sellers[name];
if (!info) {
info = new(class seller_information);
}
info->max_sellable = amt;
if (info->value_limit || info->max_sellable || info->deny_value_limit) {
_sellers[name] = info;
} else {
map_delete(_sellers, name);
}
if (amt)
add_succeeded_mess(({ "You set the maximum number of items sellable by " +
name + " to " + info->max_sellable + ".\n",
"$N fiddle$s with something in the shop.\n" }) );
else
add_succeeded_mess(({ "You remove the limit for the maximum number of "
"items sellable by " + name + ".\n",
"$N fiddle$s with something in the shop.\n" }));
return 1;
} /* do_approve_limit_person_items() */
/**
* This method sets the limit at which a person can automatically sell
* to the shop.
* @param person the person to set a limit on
* @param money the limit to set it to
*/
int do_approve_limit_person_value(string name, string money) {
class seller_information info;
int value;
string place;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to set any limits on selling "
"items.\n");
return 0;
}
name = lower_case(name);
if (!PLAYER_HANDLER->test_user(name)) {
add_failed_mess("The person " + name + " does not exist.\n");
return -1;
}
money = lower_case(money);
if (money == "disable" || money == "0") {
value = 0;
} else {
place = query_property("place");
if (!place) {
place = "default";
}
value = value_from_string(money, place);
if (!value) {
add_failed_mess("The value " + value + " is invalid, please use "
"'disable' to disable this feature for the person.\n");
return 0;
}
}
info = _sellers[name];
if (!info) {
info = new(class seller_information);
}
info->value_limit = value;
if (info->value_limit || info->max_sellable || info->deny_value_limit) {
_sellers[name] = info;
} else {
map_delete(_sellers, name);
}
if (value) {
add_succeeded_mess(({ "You set the maximum cost of items automatically "
"approved by " +
name + " to " +
MONEY_HAND->money_value_string(info->value_limit, place) +
".\n",
"$N fiddle$s with something in the shop.\n" }) );
} else {
add_succeeded_mess(({ "You disable the maximum cost of items "
"automatically approved by " +
name + ".\n",
"$N fiddle$s with something in the shop.\n" }) );
}
return 1;
} /* do_approve_limit_person_value() */
/**
* This method sets the limit at which a person can automatically sell
* to the shop (deny limit).
* @param person the person to set a limit on
* @param money the limit to set it to
*/
int do_approve_limit_person_value_deny(string name, string money) {
class seller_information info;
int value;
string place;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to set any limits on selling "
"items.\n");
return 0;
}
name = lower_case(name);
if (!PLAYER_HANDLER->test_user(name)) {
add_failed_mess("The person " + name + " does not exist.\n");
return -1;
}
money = lower_case(money);
if (money == "disable" || money == "0") {
value = 0;
} else {
place = query_property("place");
if (!place) {
place = "default";
}
value = value_from_string(money, place);
if (!value) {
add_failed_mess("The value " + value + " is invalid, please use "
"'disable' to disable this feature for the person.\n");
return 0;
}
}
info = _sellers[name];
if (!info) {
info = new(class seller_information);
}
info->deny_value_limit = value;
if (info->deny_value_limit || info->max_sellable || info->value_limit) {
_sellers[name] = info;
} else {
map_delete(_sellers, name);
}
if (value) {
add_succeeded_mess(({ "You set the maximum cost of items accepted by " +
name + " to " +
MONEY_HAND->money_value_string(info->deny_value_limit, place) +
".\n",
"$N fiddle$s with something in the shop.\n" }) );
} else {
add_succeeded_mess(({ "You disable the maximum cost of items to be sold by " +
name + ".\n",
"$N fiddle$s with something in the shop.\n" }) );
}
return 1;
} /* do_approve_limit_person_value() */
/**
* This method removes any limits set on the player.
* @param person the person to remove the limit on
*/
int do_approve_limit_person_remove(string name) {
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to remove limits "
"off someone.\n");
return 0;
}
name = lower_case(name);
if (!_sellers[name]) {
add_failed_mess("The person " + name + " does not have any limits placed "
"on them.\n");
return 0;
}
map_delete(_sellers, name);
event_save(this_object());
add_succeeded_mess(({ "You remove any limits set on " + name + ".\n",
"$N fiddle$s with something in the shop.\n" }) );
return 1;
} /* do_approve_limit_person_remove() */
/**
* This method shows the current status of the shop.
* @param hint show the hints
* @return return main status string
*/
string query_main_status(int hint) {
string ret;
string place;
string name;
class seller_information stuff;
string *bits;
if (!is_allowed(this_player()->query_name()) &&
!is_helper(this_player()->query_name())) {
add_failed_mess("You are not allowed to see the status of this store.\n");
return 0;
}
place = query_property("place");
if (!place) {
place = "default";
}
ret = "$I$0=" + the_short() + "\n";
ret += "$I$6= The current percentage to automatically add to the buy price is: " +
_automatic_percentage + "%\n";
if (hint) {
ret += "$I$0= Hint: markup <percent>\n";
}
ret += "$I$6= Limits on what can be sold.\n";
ret += "$I$6= Maximum number of items allowed in the shop : ";
if (query_maximum_inventory_size()) {
ret += query_maximum_inventory_size() + " currently " +
sizeof(query_controller()->query_sell_list_obs()) + " (fixed).\n";
} else {
ret += "disabled (fixed).\n";
}
ret += "$I$6= Maximum number of items allowed per player : ";
if (_automatic_approval->num_allowed) {
ret += _automatic_approval->num_allowed + ".\n";
} else {
ret += "disabled.\n";
}
if (hint) {
ret += "$I$0= Hint: set max number <number|disable>\n";
}
ret += "$I$6= Automatically queue sales more than : ";
if (_automatic_approval->high_cost) {
ret += MONEY_HAND->money_value_string(_automatic_approval->high_cost, place) +
".\n";
} else {
ret += "disabled.\n";
}
if (hint) {
ret += "$I$0= Hint: set high queue cost <cost|disable>\n";
}
ret += "$I$6= Automatically deny sales more than : ";
if (_automatic_approval->high_cost_deny) {
ret += MONEY_HAND->money_value_string(_automatic_approval->high_cost_deny, place) +
".\n";
} else {
ret += "disabled.\n";
}
if (hint) {
ret += "$I$0= Hint: set high deny cost <cost|disable>\n";
}
ret += "$I$6= Helpers : ";
if (sizeof(_helpers)) {
ret += query_multiple_short(_helpers) + "\n";
} else {
ret += "None at all.\n";
}
if (hint) {
ret += "$I$0= Hint: helper add <name>\n";
ret += "$I$0= Hint: helper remove <name>\n";
ret += "$I$0= Hint: helper list\n";
}
if (sizeof(_sellers)) {
ret += "$I$6= Limits set per player.\n";
ret += sprintf(" %-15s %-15s %-20s %s\n", "Name", "Max Sellable",
"Approve Limit", "Deny limit (per item)");
bits = sort_array(keys(_sellers), 0);
foreach (name in bits) {
stuff = _sellers[name];
ret += sprintf(" %-15s %-15s %-20s %s\n", name,
(stuff->max_sellable?stuff->max_sellable+"":"disabled"),
(stuff->value_limit?MONEY_HAND->money_value_string(stuff->value_limit, place):"disabled"),
(stuff->deny_value_limit?MONEY_HAND->money_value_string(stuff->deny_value_limit, place):"disabled"));
}
} else {
ret += "$I$6= No limits set per player.\n";
}
if (hint) {
ret += "$I$0= Hint: set max number <max sellable|disable> for <player>\n";
ret += "$I$0= Hint: set high queue cost <cost|disable> for <player>\n";
ret += "$I$0= Hint: set high deny cost <cost|disable> for <player> to <cost|disable>\n";
//ret += "$I$0= Hint: approve limit remove <player>\n";
}
ret += "\n$I$6= Automatically approve sales less than : ";
if (_automatic_approval->low_cost) {
ret += MONEY_HAND->money_value_string(_automatic_approval->low_cost, place) +
".\n";
} else {
ret += "disabled.\n";
}
if (hint) {
ret += "$I$0= Hint: set low approve cost <cost|disable>\n";
}
ret += "$I$0=Use 'expressions' to see the expressions.\n";
ret += "$I$0=Use 'functions shop' to see the user defined "
"functions.\n";
return ret;
} /* query_main_status() */
/**
* Returns all the rexpression stuff as a string.
* @param hint show the hitns
* @return a string with the expression status in it
*/
string query_expression_status(int hint) {
string ret;
string place;
mixed expr;
string str;
int pos;
class expression_type bing;
class expression_type binger;
class approval_item approval;
place = query_property("place");
if (!place) {
place = "default";
}
ret = "";
if (sizeof(_automatic_approval->items)) {
ret += "$I$0=%^BOLD%^Automatically accept sales of items%^RESET%^\n";
foreach (str, expr in _automatic_approval->items) {
if (classp(expr)) {
approval = (class approval_item)expr;
expr = ((class approval_item)expr)->value;
} else {
approval = new(class approval_item);
}
if (pointerp(expr) && intp(expr[0])) {
map_delete(_automatic_approval->items, str);
} else {
ret += sprintf("$I$10= %-20s", "* " + str);
if (sizeof(approval) == 3) {
approval = new(class approval_item,
markup : approval->markup,
value : approval->value,
list_name : approval->list_name,
final_cost : 0);
}
if (approval->list_name) {
ret += " listed as '" + approval->list_name + "'";
}
if (approval->markup) {
ret += " markup of " + approval->markup;
}
if (approval->final_cost) {
ret += " final cost of " +
MONEY_HAND->money_value_string(approval->final_cost, place);
}
ret += " max value:";
if (pointerp(expr)) {
str = query_expression_string(expr, 0);
if (strsrch(str, "\n") != -1) {
ret += "\n" + str;
} else {
ret += str;
}
} else {
ret += MONEY_HAND->money_value_string(expr, place);
}
ret += "\n";
}
}
} else {
ret += "Automatically accept sales of : (none setup)\n";
}
if (hint) {
ret += "$I$0= Hint: auto add name <name> up to <value>\n";
ret += "$I$0= Hint: auto add name <name> up to <value> as <list name>\n";
ret += "$I$0= Hint: auto add name <name> up to <value> with markup <percentage>\n";
ret += "$I$0= Hint: auto add name <name> up to <value> with value <final cost>\n";
ret += "$I$0= Hint: auto add name <name> up to <value> as <list name> with markup <percentage>\n";
ret += "$I$0= Hint: auto add name <name> up to <value> as <list name> with value <final cost>\n";
ret += "$I$0= Hint: auto add name <name> with <expression>\n";
ret += "$I$0= Hint: auto add name <name> with <expression> as <list name>\n";
ret += "$I$0= Hint: auto add name <name> with <expression> and markup <percentage>\n";
ret += "$I$0= Hint: auto add name <name> with <expression> and value <final cost>\n";
ret += "$I$0= Hint: auto add name <name> with <expression> as <list name> with markup <percentage>\n";
ret += "$I$0= Hint: auto add object <object> up to <value>\n";
ret += "$I$0= Hint: auto add object <object> up to <value> as <list name>\n";
ret += "$I$0= Hint: auto add object <object> up to <value> with markup <percentage>\n";
ret += "$I$0= Hint: auto add object <object> up to <value> with value <final cost>\n";
ret += "$I$0= Hint: auto add object <object> up to <value> as <list name> with markup <percentage>\n";
ret += "$I$0= Hint: auto add object <object> up to <value> as <list name> with value <final cost>\n";
ret += "$I$0= Hint: auto add item object <object> with <expression>\n";
ret += "$I$0= Hint: auto add item object <object> with <expression> as <list name>\n";
ret += "$I$0= Hint: auto add item object <object> with <expression> with markup <percentage>\n";
ret += "$I$0= Hint: auto add item object <object> with <expression> with value <final cost>\n";
ret += "$I$0= Hint: auto add item object <object> with <expression> as <list name> with markup <percentage>\n";
ret += "$I$0= Hint: auto add item object <object> with <expression> as <list name> with value <final cost>\n";
ret += "$I$0= Hint: auto remove name <name>\n";
ret += "$I$0= Hint: auto remove object <object>\n";
}
ret += "\n$I$0=%^BOLD%^Automatic approval expressions.%^RESET%^\n";
if (sizeof(_automatic_approval->expressions)) {
//ret += "$I$0=Automatic approval expressions (if any of these evaluate as "
//"true the item is accepted):\n";
pos = 0;
foreach (bing in _automatic_approval->expressions) {
if (sizeof(bing) == 3) {
binger = new(class expression_type);
binger->type = bing->type;
binger->condition = bing->condition;
binger->value = bing->value;
bing = binger;
event_save(this_object());
}
if (bing->type != PLAYER_CRAFT_SHOP_EXPR_DENY) {
str = query_expression_string(bing->value, 0);
if (strsrch(str, "\n") != -1) {
str = "\n" + str;
}
str = " accept value: " + str;
if (bing->list_name) {
str += " as " + bing->list_name;
}
} else {
str = " -- deny item";
}
ret += "$I$5=" + query_letter_value(pos) + ") " +
query_expression_string(bing->condition, 0) + str + ".\n";
pos++;
}
} else {
ret += "$I$0=No automatic approval expressions setup.\n";
}
if (hint) {
ret += "$I$0= Hint: auto add approve expression <condition> cost <value> as <list name>\n";
ret += "$I$0= Hint: auto deny expression <expression>\n";
ret += "$I$0= Hint: auto remove expression <id>\n";
}
ret += "\n$I$0=";
ret += "$I$0=Use 'functions shop' to see the user defined "
"functions.\n";
return ret;
} /* query_expression_status() */
/**
* This method prints out the main status.
*/
int do_main_status(int hint) {
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("Cannot do that!\n");
return 0;
}
write("$P$Status$P$" + query_main_status(hint));
add_succeeded_mess(({ "",
"$N fiddle$s with something in the shop.\n" }) );
return 1;
} /* do_main_status() */
/**
* This method prints out the expressions status.
*/
int do_expression_status(int hint) {
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("Cannot do that!\n");
return 0;
}
write("$P$Status$P$" + query_expression_status(hint));
add_succeeded_mess(({ "",
"$N fiddle$s with something in the shop.\n" }) );
return 1;
} /* do_expression_status() */
/**
* This method pays off the cash deficit (if one exists).
*/
int do_approve_pay_deficit() {
int cost;
string place;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to pay off the deficit for " +
the_short() + ".\n");
return 0;
}
if (query_owners_money() >= 0) {
add_failed_mess("There is no deficit here to pay off.\n");
return 0;
}
place = query_property("place");
if (!place) {
place = "default";
}
cost = -query_owners_money();
if (this_player()->query_value_in(place) >= cost) {
adjust_royalty(query_owner(), cost);
this_player()->pay_money(MONEY_HAND->create_money_array(cost, place), place);
add_succeeded_mess("$N pay$s off the deficit in " + the_short() + ".\n");
return 1;
}
add_failed_mess("You do not have enough money to pay off the deficit "
"of " + MONEY_HAND->money_value_string(cost, place) +
".\n");
return 0;
} /* do_approve_pay_deficit() */
/**
* This method allows the player to add a new category to the list.
* @param category the new category name
*/
int do_category_description(string category, string desc) {
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to add categories.\n");
return 0;
}
if (!query_controller()->is_valid_category(category)) {
add_failed_mess("The category doesn't exists.\n");
return 0;
}
set_category_description(category, desc);
add_succeeded_mess("$N set$s the description of " + category + ".\n");
return 1;
} /* do_add_new_category() */
/**
* This method allows the player to add a new category to the list.
* @param category the new category name
*/
int do_category_information(string category, string desc) {
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to add categories.\n");
return 0;
}
if (!query_controller()->is_valid_category(category)) {
add_failed_mess("The category doesn't exists.\n");
return 0;
}
set_category_information(category, desc);
add_succeeded_mess("$N set$s the description of " + category + ".\n");
return 1;
} /* do_add_new_category() */
/**
* This method allows the player to add a new category to the list.
* @param category the new category name
*/
int do_add_new_category(string category) {
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to add categories.\n");
return 0;
}
if (query_controller()->is_valid_category(category)) {
add_failed_mess("The category already exists.\n");
return 0;
}
add_shop_category(category);
add_succeeded_mess("$N add$s a new category.\n");
return 1;
} /* do_add_new_category() */
/**
* This method allows the player to remove a category from the list.
* @param category the category to remove
*/
int do_remove_category(string category) {
object* obs;
string old_cat;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to remove categories.\n");
return 0;
}
old_cat = category;
category = query_real_category_name(category);
if (!category ||
!query_controller()->is_valid_category(category)) {
add_failed_mess("The category " + old_cat + " does not exist.\n");
return 0;
}
if (category == query_default_category()) {
add_failed_mess("You cannot remove the default category.\n");
return 0;
}
obs = query_controller()->query_sell_list_obs();
obs = filter(obs, (: query_controller()->query_category_of_shop_object($1) == $2:), category );
if (sizeof(obs)) {
add_failed_mess("The category '" + category + "' is not empty "
"and cannot be removed.\n");
return 0;
}
write("Do you wish to remove the category " + category + " from " +
the_short() + " (y/n)?");
input_to("check_remove_category", 0, category);
add_succeeded_mess(({ "", "$N removes a category from the shop.\n" }));
return 1;
} /* do_remove_category() */
/**
* This method allows the player to remove a category from the list.
* @param category the category to rename
* @param new_category the new name of a category
*/
int do_rename_category(string category, string new_category) {
object* obs;
object ob;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to rename categories.\n");
return 0;
}
category = query_real_category_name(category);
if (!category ||
!query_controller()->is_valid_category(category)) {
add_failed_mess("The category " + category + " does not exist.\n");
return 0;
}
if (category == query_default_category()) {
add_failed_mess("You cannot remove the default category.\n");
return 0;
}
add_shop_category(new_category);
obs = query_controller()->query_sell_list_obs();
obs = filter(obs, (: query_controller()->query_category_of_shop_object($1) == $2:), category );
if (sizeof(obs)) {
foreach (ob in obs) {
query_controller()->change_category_of_shop_object(ob, new_category);
}
}
remove_shop_category(category);
add_succeeded_mess("$N rename$s category " + category + " to " +
new_category + ".\n");
return 1;
} /* do_rename_category() */
/**
* This method is called into to check to see if we can remove the category.
* @param answer their answer
* @param category the category to remove
*/
protected void check_remove_category(string answer, string category) {
class approval_obs approve;
if (!strlen(answer) ||
lower_case(answer)[0] != 'y') {
write("Aborting deleting the category " + category + ".\n");
return ;
}
remove_shop_category(category);
write("Removed the shop category " + category + ".\n");
foreach (approve in query_approval_list(0)) {
if (approve->category == category) {
approve->category = query_default_category();
}
}
foreach (approve in query_approval_list(1)) {
if (approve->category == category) {
approve->category = query_default_category();
}
}
event_save(this_object());
return ;
} /* check_remove_category() */
/**
* This method sets the default category for the place.
* @param default_cat the default category
*/
int do_set_default_category(string default_cat) {
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to set the default category.\n");
return 0;
}
default_cat = query_real_category_name(default_cat);
if (!default_cat ||
!query_controller()->is_valid_category(default_cat)) {
add_failed_mess("The category " + default_cat + " does not exist.\n");
return 0;
}
set_default_category(default_cat);
add_succeeded_mess("$N set$s the default category for " + the_short() +
".\n");
event_save(this_object());
return 1;
} /* do_set_default_category() */
/**
* This method lists the current categories and shows us which one is
* currently the default.
*/
int do_list_categories() {
string cat;
string ret;
ret = "";
foreach (cat in query_controller()->query_categories()) {
if (cat == query_default_category()) {
ret += cat + " (default)\n";
} else {
ret += cat + "\n";
}
}
write("$P$Category list$P$The current categories are:\n" + ret);
add_succeeded_mess(({ "", "$N browses the categories.\n" }));
return 1;
} /* do_list_categories() */
/**
* This method shows the stats on all the sold items, the number and value
* of each one sold.
* @param type the type of sorting to do
*/
int do_stats_items(int type) {
class shop_stats stat;
string ret;
string *bits;
string place;
string name;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You cannot read " + the_short() + "'s ledger.\n");
return 0;
}
if (!sizeof(_sold_stats)) {
add_failed_mess("Nothing has been sold in this transaction section "
"yet.\n");
return 0;
}
place = query_property("place");
if (!place) {
place = "default";
}
switch (type) {
case 1:
bits = sort_array(keys(_sold_stats), (: _sold_stats[$1]->num_sold - _sold_stats[$2]->num_sold :));
break;
case 2:
bits = sort_array(keys(_sold_stats), (: _sold_stats[$1]->value_sold - _sold_stats[$2]->value_sold :));
break;
case 3 :
bits = sort_array(keys(_sold_stats), (: strcmp(((class shop_stats)_sold_stats[$1])->seller, ((class shop_stats)_sold_stats[$1])->seller) :));
break;
case 4 :
bits = sort_array(keys(_sold_stats), (: strcmp(((class shop_stats)_sold_stats[$1])->name, ((class shop_stats)_sold_stats[$1])->name) :));
break;
default :
bits = sort_array(keys(_sold_stats), 0);
break;
}
ret = "Statistics for items sold since " + ctime(_stats_start) + ".\n";
foreach (name in bits) {
stat = _sold_stats[name];
ret += name + ": " + stat->num_sold + " for " +
MONEY_HAND->money_value_string(stat->value_sold, place) + ".\n";
}
write("$P$Sold stats$P$" + ret);
add_succeeded_mess(({ "", "$N looks at the ledger.\n" }));
return 1;
} /* do_stats_items() */
#if USE_TRANSACTIONS
/**
* This method shows a list of all the transactions that have occured in the
* shop.
*/
int do_stats_transactions() {
class shop_transaction bing;
string ret;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You cannot read " + the_short() + "'s ledger.\n");
return 0;
}
ret = "Statistics for transactions since " + ctime(_stats_start) + ".\n";
foreach (bing in _transactions) {
ret += "$I$5=" + query_transaction_string(bing) + "\n";
}
write("$P$Sold stats$P$" + ret);
add_succeeded_mess(({ "", "$N looks at the ledger.\n" }));
return 1;
} /* do_stats_transactions() */
#endif
/**
* This method shows stats about money and stuff in the shop.
*/
int do_stats_money() {
string ret;
int stock_value;
string place;
object ob;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You cannot read " + the_short() + "'s ledger.\n");
return 0;
}
place = query_property("place");
if (!place) {
place = "default";
}
ret = "";
ret += "\nCurrent money spent " +
MONEY_HAND->money_value_string(_total_outgoing, place) +
" and money made " +
MONEY_HAND->money_value_string(_total_ingoing, place) + ".\n";
foreach (ob in query_controller()->query_sell_list_obs()) {
stock_value += ob->query_value();
}
ret += "The current stock value is " +
MONEY_HAND->money_value_string(stock_value, place) +
".\n";
ret += "\n";
if (query_owners_money() > 0) {
ret += "The owner current has a cash float (royalties) of " +
MONEY_HAND->money_value_string(query_owners_money(), place) +
".\n";
} else if (query_owners_money() < 0) {
ret += "The owner current has a cash deficit of " +
MONEY_HAND->money_value_string(-query_owners_money(), place) +
".\n";
}
write(ret);
add_succeeded_mess(({ "", "$N looks at the ledger.\n" }));
return 1;
} /* do_stats_money() */
/** @ignore yes */
int do_helper_list() {
write("$I$3=The current helpers are: " +
query_multiple_short(_helpers) + ".\n");
return 1;
} /* do_helper_list() */
/** @ignore yes */
int do_helper_add(string helper) {
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to mess with the helpers.\n");
return 0;
}
helper = lower_case(helper);
if (is_helper(helper)) {
add_failed_mess(capitalize(helper) + " is already a helper.\n");
return 0;
}
if (!PLAYER_HANDLER->test_user(helper)) {
add_failed_mess(capitalize(helper) + " is not a player.\n");
return 0;
}
_helpers += ({ helper });
add_succeeded_mess("$N add$s " + capitalize(helper) +
" as a helper.\n");
return 1;
} /* do_helper_add() */
/** @ignore yes */
int do_helper_remove(string helper) {
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to mess with the helpers.\n");
return 0;
}
helper = lower_case(helper);
if (!is_helper(helper)) {
add_failed_mess(capitalize(helper) + " is not a helper to remove.\n");
return 0;
}
_helpers -= ({ helper });
add_succeeded_mess("$N remove$s " + capitalize(helper) +
" as a helper.\n");
return 1;
} /* do_helper_remove() */
private object* variable_objects(string seller, int cost, object* obs) {
return obs;
} /* function_object_type() */
private string variable_sale_name(string seller, int cost, object* ob, string name, string category) {
if (name) {
return lower_case(name);
}
return "";
} /* variable_sale_name() */
private string variable_sale_category(string seller, int cost, object* ob, string name, string category) {
if (category) {
return lower_case(category);
}
return "";
} /* variable_sale_category() */
private int variable_sale_cost(string seller, int cost, object* ob, string name, string category) {
return cost;
} /* variable_sale_category() */
void init() {
expression_util::init();
craft_shop_category::init();
add_command("waiting", "", (: do_list_approval(1) :));
add_command("waiting", "unapproved", (: do_list_approval(0) :));
add_command("reject", "<string'id'>",
(: do_approve_reject($4[0], 0, -1) :));
add_command("retrieve", "<string'id'>", (: do_return($4[0]) :) );
add_command("return", "<string'id'>", (: do_return($4[0]) :) );
add_command("value", "<indirect:object>",
(: do_approve_auto_item_test($1) :));
if (!is_helper(this_player()->query_name())) {
return ;
}
add_command("approve", "<string'id'>", (: do_approve_item($4[0], 0) :));
add_command("approve", "<string'id'> for <string'value'>",
(: do_approve_item($4[0], $4[1]) :));
add_command("reject", "<string'id'> position <number>",
(: do_approve_reject($4[0], 0, $4[1]) :));
add_command("reject", "<string'id'> message <string'reject message'>",
(: do_approve_reject($4[0], $4[1], -1) :));
add_command("reject", "<string'id'> position <number> message <string'reject message'>",
(: do_approve_reject($4[0], $4[2], $4[1]) :));
add_command("browse", "waiting <string'id'>",
(: do_approve_browse($4[0]) :));
add_command("checkout", "<string'id'>",
(: do_approve_checkout($4[0]) :));
add_command("checkin", "<indirect:object:me-here>",
(: do_approve_checkin($1) :));
if (!is_allowed(this_player()->query_name())) {
return ;
}
add_command("set", "low approve cost <string'cost|disable'>",
(: do_approve_auto_low($4[0]) :));
add_command("auto", "add approve expression <string'condition'> cost <string'value'> as <string'list name'>",
(: do_approve_auto_expression_add($4[0], $4[1],
PLAYER_CRAFT_SHOP_EXPR_ACCEPT, $4[2]) :));
add_command("auto", "add deny expression <string'condition'>",
(: do_approve_auto_expression_add($4[0], 0,
PLAYER_CRAFT_SHOP_EXPR_DENY, 0) :));
add_command("auto", "remove expression <string'id'>",
(: do_approve_auto_expression_remove($4[0]) :));
add_command("markup", "<number'percentage'>",
(: do_approve_percentage($4[0]) :));
add_command("auto", "add name <string'name'> up to <string'value'>",
(: do_approve_auto_item_add($4[0], $4[1], 0, 0, 0) :));
add_command("auto", "add name <string'name'> up to <string'value'> with value <string'final cost'>",
(: do_approve_auto_item_add($4[0], $4[1], 0, 0, $4[2]) :));
add_command("auto", "add name <string'name'> up to <string'value'> with markup <number'percentage'>",
(: do_approve_auto_item_add($4[0], $4[1], 0, $4[2], 0) :));
add_command("auto", "add name <string'name'> up to <string'value'> as <string'list name'>",
(: do_approve_auto_item_add($4[0], $4[1], $4[2], 0, 0) :));
add_command("auto", "add name <string'name'> up to <string'value'> as <string'list name'> with value <string'final cost'>",
(: do_approve_auto_item_add($4[0], $4[1], $4[2], 0, $4[3]) :));
add_command("auto", "add name <string'name'> up to <string'value'> as <string'list name'> with markup <number'percentage'>",
(: do_approve_auto_item_add($4[0], $4[1], $4[2], $4[3], 0) :));
add_command("auto", "add name <string'name'> with <string'expression'>",
(: do_approve_auto_item_add_expr($4[0], $4[1], 0, 0, 0) :));
add_command("auto", "add name <string'name'> with <string'expression'> and markup <number'percentage'>",
(: do_approve_auto_item_add_expr($4[0], $4[1], 0, $4[2], 0) :));
add_command("auto", "add name <string'name'> with <string'expression'> and value <string'final cost'>",
(: do_approve_auto_item_add_expr($4[0], $4[1], 0, 0, $4[2]) :));
add_command("auto", "add name <string'name'> with <string'expression'> as <string'list name'>",
(: do_approve_auto_item_add_expr($4[0], $4[1], $4[2], 0, 0) :));
add_command("auto", "add name <string'name'> with <string'expression'> as <string'list name'> and markup <number'percentage'>",
(: do_approve_auto_item_add_expr($4[0], $4[1], $4[2], $4[3], 0) :));
add_command("auto", "add name <string'name'> with <string'expression'> as <string'list name'> and value <string'final cost'>",
(: do_approve_auto_item_add_expr($4[0], $4[1], $4[2], 0, $4[3]) :));
add_command("auto", "add object <indirect:object> up to <string'value'>",
(: do_approve_auto_item_add_object($1, $4[1], 0, 0, 0) :));
add_command("auto", "add object <indirect:object> up to <string'value'> with markup <number'percentage'>",
(: do_approve_auto_item_add_object($1, $4[1], 0, $4[2], 0) :));
add_command("auto", "add object <indirect:object> up to <string'value'> with value <string'final cost'>",
(: do_approve_auto_item_add_object($1, $4[1], 0, 0, $4[2]) :));
add_command("auto", "add object <indirect:object> up to <string'value'> as <string'list name'>",
(: do_approve_auto_item_add_object($1, $4[1], $4[2], 0, 0) :));
add_command("auto", "add object <indirect:object> up to <string'value'> as <string'list name'> with markup <number'percentage'>",
(: do_approve_auto_item_add_object($1, $4[1], $4[2], $4[3], 0) :));
add_command("auto", "add object <indirect:object> up to <string'value'> as <string'list name'> with value <string'final cost'>",
(: do_approve_auto_item_add_object($1, $4[1], $4[2], 0, $4[3]) :));
add_command("auto", "add object <indirect:object> with <string'expression'>",
(: do_approve_auto_item_add_object_expr($1, $4[1], 0, 0, 0) :));
add_command("auto", "add object <indirect:object> with <string'expression'> and markup <number'percentage'>",
(: do_approve_auto_item_add_object_expr($1, $4[1], 0, $4[2], 0) :));
add_command("auto", "add object <indirect:object> with <string'expression'> and value <string'final cost'>",
(: do_approve_auto_item_add_object_expr($1, $4[1], 0, 0, $4[2]) :));
add_command("auto", "add object <indirect:object> with <string'expression'> as <string'list name'>",
(: do_approve_auto_item_add_object_expr($1, $4[1], $4[2], 0, 0) :));
add_command("auto", "add object <indirect:object> with <string'expression'> as <string'list name'> and markup <number'percentage'>",
(: do_approve_auto_item_add_object_expr($1, $4[1], $4[2], $4[3], 0) :));
add_command("auto", "add object <indirect:object> with <string'expression'> as <string'list name'> and value <string'final cost'>",
(: do_approve_auto_item_add_object_expr($1, $4[1], $4[2], 0, $4[3]) :));
add_command("auto", "remove name <string'name'>",
(: do_approve_auto_item_remove($4[0]) :));
add_command("auto", "remove object <indirect:object>",
(: do_approve_auto_item_remove_object($1) :));
add_command("set", "high queue cost <string'cost|disable'>",
(: do_approve_auto_high($4[0]) :));
add_command("set", "high deny cost <string'cost|disable'>",
(: do_approve_auto_high_deny($4[0]) :));
add_command("set", "max number <string'max sellable|disable'>",
(: do_approve_limit($4[0]) :));
add_command("set", "max number <string'max sellable|disable'> for <string'player'>",
(: do_approve_limit_person_items($4[1], $4[0]) :));
add_command("set", "high queue cost <string'cost|disable'> for <string'player'>",
(: do_approve_limit_person_value($4[1], $4[0]) :));
add_command("set", "high deny cost <string'cost|disable'> for <string'player'>",
(: do_approve_limit_person_value_deny($4[1], $4[0]) :));
add_command("approve", "limit remove <string'player'>",
(: do_approve_limit_person_remove($4[0]) :));
add_command("expressions", "",
(: do_expression_status(0) :));
add_command("expressions", "hints",
(: do_expression_status(1) :));
add_command("pay", "deficit",
(: do_approve_pay_deficit() :));
add_command("stats", "items by name", (: do_stats_items(4) :));
add_command("stats", "items by seller", (: do_stats_items(3) :));
add_command("stats", "items by number", (: do_stats_items(1) :));
add_command("stats", "items by value", (: do_stats_items(2) :));
#if USE_TRANSACTIONS
add_command("stats", "transactions", (: do_stats_transactions() :));
#endif
add_command("stats", "money", (: do_stats_money() :));
add_command("status", "<direct:object>", (: do_main_status(0) :));
add_command("status", "<direct:object> hints", (: do_main_status(1) :));
add_command("check", "sell <indirect:object>",
(: do_check_sell($1) :));
add_command("category", "list", (: do_list_categories() :));
add_command("category", "default <string'category'>",
(: do_set_default_category($4[0]) :));
add_command("category", "add <string'category'>",
(: do_add_new_category($4[0]) :));
add_command("category", "description <string'category'> <string:quoted'description'>",
(: do_category_description($4[0], $4[1]) :));
add_command("category", "description <string'category'> remove",
(: do_category_description($4[0], 0) :));
add_command("category", "information <string'category'> <string:quoted'information'>",
(: do_category_information($4[0], $4[1]) :));
add_command("category", "information <string'category'> remove",
(: do_category_information($4[0], 0) :));
add_command("category", "remove <string'category'>",
(: do_remove_category($4[0]) :));
add_command("category", "rename <string'category'> to <string'category'>",
(: do_rename_category($4[0], $4[1]) :));
add_command("helper", "list",
(: do_helper_list() :));
add_command("helper", "add <string'helper'>",
(: do_helper_add($4[0]) :));
add_command("helper", "remove <string'helper'>",
(: do_helper_remove($4[0]) :));
add_command("buy", "force <indirect:object:" +
file_name(query_controller()->query_sell_list()) + ">",
(: do_buy($1, 1) :));
} /* init() */