/**
* This is the file that is the basic inheritable for commercial
* properties. The only different between commercial properties and
* player housing properties is that commerical ones can deal with
* signs and commercial furniture.
* @author Pinkfish
* @started Fri Apr 21 13:37:44 PDT 2000
*/
#include <player.h>
#include <move_failures.h>
#include <expressions.h>
#include <money.h>
#include <player_handler.h>
#include <mail.h>
inherit "/std/room/player_housing";
inherit "/std/shops/inherit/expression_util";
inherit "/std/shops/inherit/person_expressions";
#define COMMERCIAL_WEEKLY_STATS_TIME (7 * 24 * 60 * 60)
#define COMMERCIAL_ROYALTY_TIMEOUT_PERIOD (7 * 24 * 60 * 60)
class float_withdrawls {
string person;
int amount;
int withdrawl_time;
}
class weekly_status {
int total_incoming;
int total_outgoing;
class float_withdrawls* withdrawls;
}
class royalty_data {
int value;
int last_withdrawl;
}
private string* _auto_load_sign_str;
private int _broken_sign;
private string _property_name;
private mapping _royalties;
private class parse_node* _use_expression;
private class parse_node* _entry_cost;
private int _entry_time_limit;
private mapping _use_type_expressions;
private string* _black_list;
private int _last_stats;
private class weekly_status _weekly_status;
private int _commercial_id;
private nosave object _sign_ob;
private nosave string _parcel_post;
private nosave object* _commercial_things;
private nosave string _use_type;
private nosave string _commercial_type;
private nosave string _save_dir;
private nosave int _property_size;
private nosave string _language;
#define COMMERCIAL_SALESPERSON "/obj/monster/commercial"
private string variable_use_type(string seller);
void create() {
_commercial_things = ({ });
_royalties = ([ ]);
_use_type_expressions = ([ ]);
_property_size = 25;
_black_list = ({ });
_last_stats = time();
_weekly_status = new(class weekly_status);
_weekly_status->withdrawls = ({ });
_language = "common";
expression_util::create();
player_housing::create();
// This is pointless, since setup hasn't been called yet, so it won't
// have loaded the data yet and will never have a property name for us
// to use.
//
// Instead, we handle it by masking short() (the other solutions were
// fairly vile). Leaving it here in case other code in this method
// needs similar treatment, and a generally more satisfactory solution
// is found for this problem too.
//
// if (_property_name) {
// set_short(_property_name);
// add_property("determinate", "");
// }
person_expressions::create();
add_allowed_variable("type", EXPRESSION_TYPE_STRING,
(: variable_use_type :));
set_expression_type("room");
add_help_file("commercial");
if (!_use_expression) {
_use_expression = parse_boolean_string("false");
}
if (!_black_list) {
_black_list = ({ });
}
if (!_last_stats) {
_last_stats = time();
}
if (_last_stats + COMMERCIAL_WEEKLY_STATS_TIME - time() < 0) {
call_out("mail_weekly_status", 0);
}
else {
call_out("mail_weekly_status", _last_stats +
COMMERCIAL_WEEKLY_STATS_TIME - time());
}
} /* create() */
/**
* This gets round the problems with setting the property name before
* we have a save file.
*/
string short() {
if (_property_name) {
set_short(_property_name);
add_property("determinate", "");
}
return ::short();
} /* short() */
/**
* This gets round the problems with setting the property name before
* we have a save file.
*/
string long(string word, int dark) {
if (_property_name) {
set_short(_property_name);
add_property("determinate", "");
}
return ::long(word, dark);
} /* long() */
/**
* This method is called to try and see if the property is open for
* the specific type of thingy attempted.
* @param type the type of thing
*/
int is_open_for(string type, string person) {
class parse_node ret;
if (is_allowed(person)) {
return 1;
}
// People black listed cannot use the property.
if (member_array(person, _black_list) != -1) {
return 0;
}
// Check and see what the use expressions are setup as.
_use_type = type;
ret = evaluate_expression(_use_expression, this_player()->query_name());
if (ret->value) {
if (_use_type_expressions[type]) {
ret = evaluate_expression(_use_type_expressions[type],
this_player()->query_name());
}
}
return ret->value;
} /* is_open_for() */
/**
* This method checks returns the main room. THis is used when the
* property can have multiple sub-rooms.
* @return the main room
*/
object query_main_room() {
return this_object();
} /* query_main_room() */
/**
* This method adds a commercial thing into the list of current
* commercial things.
* @param thing the thing to add
*/
void add_commercial_thing(object ob) {
_commercial_things += ({ ob });
// Make them load themselves after they are in the room.
ob->load_me();
} /* add_commercial_thing() */
/**
* This method removes a commercil thing from the list of current
* commercial things.
* @param thing the thing to remove
*/
void remove_commercial_thing(object thing) {
// Finish saving any extra needed data after they are removed.
thing->save_me();
_commercial_things -= ({ thing });
} /* remove_commercial_thing() */
/**
* This method returns the current list of commercial things in
* the room.
* @return the list of commercial things
*/
object* query_commercial_things() {
return _commercial_things;
} /* query_commercial_things() */
/**
* This method figures out how much float the owner has in the current
* property.
* @return the current float
*/
int query_owners_money() {
if (classp(_royalties[query_owner()])) {
return ((class royalty_data)_royalties[query_owner()])->value;
}
return 0;
} /* query_owners_money() */
/**
* This method adds money into the specified person's royalty
* float.
* @param person the person to add the royalty to
* @param amount the amount to add
*/
void adjust_royalty(string person, int amount) {
if (is_allowed(person)) {
if (!_weekly_status) {
_weekly_status = new(class weekly_status);
_weekly_status->withdrawls = ({ });
}
if (amount > 0) {
_weekly_status->total_incoming += amount;
} else {
_weekly_status->total_outgoing += -amount;
}
if (!classp(_royalties[query_owner()])) {
_royalties[query_owner()] = new(class royalty_data,
value : amount + _royalties[query_owner()],
last_withdrawl : time());
} else {
if (((class royalty_data)_royalties[query_owner()])->value == 0) {
((class royalty_data)_royalties[query_owner()])->last_withdrawl = time();
}
((class royalty_data)_royalties[query_owner()])->value += amount;
}
} else {
if (!classp(_royalties[person])) {
_royalties[person] = new(class royalty_data,
value : amount + _royalties[person],
last_withdrawl : time());
} else {
if (((class royalty_data)_royalties[person])->value == 0) {
((class royalty_data)_royalties[person])->last_withdrawl = time();
}
((class royalty_data)_royalties[person])->value += amount;
}
}
event_save(this_object());
} /* adjust_royalty() */
/**
* This method returns the amount of money in the specified person's
* royalty float.
*/
int query_royalty(string person) {
if (classp(_royalties[person])) {
return ((class royalty_data)_royalties[person])->value;
}
return 0;
} /* query_royalty() */
/**
* This method returns the float of the property. The float is the
* owner's current royalty balance.
* @return the float of the property
*/
int query_float() {
return query_owners_money();
} /* query_float() */
/**
* This method returns true for any commercial property.
* @return 1 for commercial property
*/
int query_commercial_property() {
return 1;
} /* query_commercial_property() */
/**
* 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 sets the language items in the shop should be displayed in,
* if a language is required.
* @param language the language to use
*/
void set_language(string language) {
_language = language;
}
/**
* This method returns the language items in the shop should use if they
* need to use a language.
*/
string query_language() {
return _language;
}
/**
* This method sets the commercial type of the property.
* @param name the commecial type
*/
void set_commercial_type(string name) {
_commercial_type = name;
} /* set_commercial_type() */
/**
* This method returns the commercial type of the property.
* @return the commercial type of the property
*/
string query_commercial_type() {
return _commercial_type;
} /* query_commercial_type() */
/**
* This method sets the name of the property.
* @param name the name of the property
*/
void set_property_name(string name) {
if(strsrch(name, "%^") != -1)
return 0;
_property_name = name;
add_property("determinate", "");
set_short(_property_name);
} /* set_property_name() */
/**
* This method returns the name of the property.
* @return the name of the property
*/
string query_property_name() {
return _property_name;
} /* query_property_name() */
/** @ignore yes */
void event_dest_me(object ob) {
if (_sign_ob) {
_sign_ob->dest_me();
}
} /* event_dest_me() */
/**
* This method returns the current sign object for the property.
* @return the current sign object
*/
object query_sign_object() {
object* obs;
if (!_sign_ob && _auto_load_sign_str && !_broken_sign) {
if (catch(obs = (PLAYER_OB)->load_auto_load_to_array(_auto_load_sign_str))) {
_broken_sign = 1;
} else {
if (sizeof(obs)) {
_sign_ob = obs[0];
_sign_ob->reset_get();
} else {
_broken_sign = 1;
}
}
}
return _sign_ob;
} /* query_sign_object() */
/**
* This method sets the current sign object.
* @param sign the new sign object
*/
void set_sign_object(object ob) {
if (ob) {
_auto_load_sign_str = (PLAYER_OB)->create_auto_load(({ ob }));
ob->reset_get();
} else {
_auto_load_sign_str = 0;
}
_sign_ob = ob;
event_save(this_object());
} /* set_sign_object() */
/** @ignore yes */
void set_save_file(string str) {
printf("ERROR! Do not use set_save_file.\n");
} /* set_save_file() */
/**
* This method sets the save directory for the the room.
* @param dir the directory to save stuff in
*/
void set_save_dir(string dir) {
if (dir[<1] != '/') {
dir += "/";
}
_save_dir = dir;
::set_save_file(dir + "_main");
} /* set_save_dir() */
/**
* This method returns the save directory for the room. This should be
* used as a reference point for other save stuff.
* @return the save directory
*/
string query_save_dir() {
return _save_dir;
} /* query_save_dir() */
/**
* This method finds a unique commercial id in the room to use as new
* save file.
* @return a unique commercial id for the room
*/
int find_next_commercial_id() {
object *obs;
obs = all_inventory();
while (file_size(query_save_dir() + _commercial_id) >= 0 ||
file_size(query_save_dir() + _commercial_id + ".o") >= 0 ||
file_size(query_save_dir() + _commercial_id + ".o.gz") >= 0 ||
sizeof(filter(obs,
(: $1->query_commercial_id() == _commercial_id :)))) {
_commercial_id++;
}
event_save(this_object());
return _commercial_id;
} /* find_next_commercial_id() */
/**
* This method sets the size of the property. The property size ranges
* from 0 (no size) to 100 (big shop).
* @param size the new size of the property
*/
void set_property_size(int size) {
_property_size = size;
} /* set_property_size() */
/**
* This method returns the size of the property. The property size ranges
* from 0 (no size) to 100 (big shop).
* @return the property size
*/
int query_property_size() {
return _property_size;
} /* query_property_size() */
/**
* This method resets the weekly status when the stats are mailed out.
* It will also reset all the commercial objects.
*/
void reset_weekly_status() {
object ob;
_weekly_status = new(class weekly_status);
_weekly_status->withdrawls = ({ });
foreach (ob in _commercial_things) {
if (ob) {
ob->reset_weekly_status();
}
}
} /* reset_weekly_status() */
/**
* This method returns the string that will be sent to the owners at the
* end of the week.
* @return the weekly status
*/
string query_weekly_status_string() {
string place;
string ret;
string str;
object ob;
class float_withdrawls withdrawl;
place = query_property("place");
if (!_weekly_status) {
_weekly_status = new(class weekly_status);
_weekly_status->withdrawls = ({ });
}
ret = "";
ret += "\n$I$0=---=== " + the_short() + " ===---\n";
ret += "Total outgoing : " +
MONEY_HAND->money_value_string(_weekly_status->total_outgoing, place) + "\n";
ret += "Total incoming : " +
MONEY_HAND->money_value_string(_weekly_status->total_incoming, place) + "\n";
if (sizeof(_weekly_status->withdrawls)) {
ret += "Float withdrawls:\n";
foreach (withdrawl in _weekly_status->withdrawls) {
ret += "$I$6= " + ctime(withdrawl->withdrawl_time)[0..11] + " " +
withdrawl->person + " for " +
MONEY_HAND->money_value_string(withdrawl->amount, place) + "\n";
}
} else {
ret += "No withdrawls from the float.\n";
}
foreach (ob in _commercial_things) {
if (ob) {
str = ob->query_weekly_status_string();
if (str) {
ret += "\n$I$0=---=== " + ob->the_short() + " ===---\n";
ret += str;
}
}
}
return ret;
} /* query_weekly_status_string() */
/**
* This method will mail out the weekly status for the shop.
*/
protected void mail_weekly_status() {
string str;
string ret;
class royalty_data data;
string person;
if(!query_owner()) {
return;
}
foreach (person, data in _royalties) {
if (classp(data)) {
if (person != query_owner() &&
data->value > 0 &&
data->last_withdrawl +
COMMERCIAL_ROYALTY_TIMEOUT_PERIOD - time() < 0) {
AUTO_MAILER->auto_mail(person,
the_short(),
"Lost royalties.",
0,
"You took too long to collect your "
"royalties and they vanished.\n\n"
"Good luck!\n"
"Administrator.");
map_delete(_royalties, person);
}
}
}
ret = catch(str = query_weekly_status_string());
if (ret) {
AUTO_MAILER->auto_mail(query_owner(),
the_short(),
"Weekly Statistics " + ctime(time()),
implode(query_allowed(), ","),
"The weekly stats generated an error: " + ret + "\n");
AUTO_MAILER->auto_mail("pinkfish",
the_short(),
"Weekly Statistics " + ctime(time()),
0,
"The weekly stats generated an error: " +
ret + "\nin room: " + file_name(this_object()) + "\n");
} else {
str = PLAYER_OB->convert_message(str);
AUTO_MAILER->auto_mail(query_owner(),
the_short(),
"Weekly Statistics " + ctime(time()),
implode(query_allowed(), ","),
str);
}
_last_stats = time();
// Now, update the costs.
foreach (object ob in _commercial_things) {
adjust_royalty(query_owner(), -ob->query_weekly_upkeep_cost());
}
event_save(this_object());
reset_weekly_status();
event_save(this_object());
} /* mail_weekly_status() */
/**
* This function will try and track down a specific type of commercial
* object in the current location. It will look into 'partitioned'
* rooms for the item as well.
* @param type the type to look for
* @return the object found
*/
object* find_commercial_items(string type) {
object* obs;
obs = filter(all_inventory(this_object()),
(: $1->query_commercial_name() == $2 :), type);
return obs;
} /* query_object_found() */
/**
* This registers a set of use types so they can be seen and controlled.
* @param types the list of types to register
*/
void register_use_types(string* types) {
string bing;
if (!_use_type_expressions) {
_use_type_expressions = ([ ]);
}
foreach (bing in types) {
if (!_use_type_expressions[bing]) {
_use_type_expressions[bing] = parse_boolean_string("true");
}
}
} /* register_use_types() */
/**
* This method gives the property a name.
*/
int do_name_property(string name) {
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You cannot set the name of " + the_short() + ".\n");
return 0;
}
set_property_name(name);
add_succeeded_mess("$N set$s the property name to '" + name + "'.\n");
return 1;
} /* do_name_property() */
/**
* This method sets the sign you wish to use for your property.
* The sign will be displayed outside the property for passer bys.
* @param obs the sign
*/
int do_set_sign(object* obs) {
object ob;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You cannot set the sign for the property.\n");
return 0;
}
if (sizeof(obs) > 1) {
add_failed_mess("You must only specifiy one sign.\n");
return 0;
}
if (living(obs[0])) {
add_failed_mess("You have to wait till " + obs[0]->the_short() +
" dies first.\n");
return 0;
}
if (obs[0]->get()) {
add_failed_mess("Cannot set something as a sign that you cannot get.\n");
return 0;
}
ob = query_sign_object();
if (obs[0]->move("/room/rubbish") == MOVE_OK) {
set_sign_object(obs[0]);
} else {
add_failed_mess("Unable to move $I off you.\n", obs[0..0]);
return 0;
}
if (query_sign_object() != ob) {
if (ob) {
ob->set_get();
if (ob->move(this_player()) != MOVE_OK) {
ob->move(this_object());
}
add_succeeded_mess(({ "You remove the sign " +ob->the_short() +
" and set " + obs[0]->the_short() +
" as your property sign.\n",
"$N sets the sign for outside " + the_short() +
".\n" }));
} else {
add_succeeded_mess(({ "You set " + obs[0]->the_short() +
" as your property sign.\n",
"$N sets the sign for outside " + the_short() +
".\n" }));
}
return 1;
} else {
obs[0]->move(this_player());
add_failed_mess("You cannot set the sign for some reason.\n");
return 0;
}
} /* do_set_sign() */
/**
* This method removes the sign from the property.
*/
int do_remove_sign() {
object ob;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You cannot set the sign for the property.\n");
return 0;
}
if (!query_sign_object()) {
add_failed_mess("You cannot remove the sign since there is no sign.\n");
return 0;
}
ob = query_sign_object();
ob->set_get();
if (ob->move(this_player()) == MOVE_OK) {
add_succeeded_mess("$N $V $I from " + the_short() +
".\n", ({ ob }));
set_sign_object(0);
return 1;
} else {
ob->reset_get();
add_failed_mess("You cannot remove the sign, unable to hold it?\n");
return 0;
}
} /* do_remove_sign() */
/** @ignore yes */
int do_status(int hint) {
string ret;
object ob;
string str;
string place;
string fluff;
class parse_node* expr;
if (!is_allowed(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");
ret = "";
ret += "$I$5=The owner of the property is " + query_owner() + ".\n";
ret += "$I$5=The name of the property is " + _property_name + ".\n";
if (hint) {
ret += "$I$0= Hint: name property <name>\n";
}
if (sizeof(_black_list)) {
ret += "$I$5=The black list is " +
query_multiple_short(_black_list) + ".\n";
} else {
ret += "$I$5=The black list is empty.\n";
}
if (hint) {
ret += "$I$0= Hint: blacklist add <name>\n";
ret += "$I$0= Hint: blacklist add ignore\n";
ret += "$I$0= Hint: blacklist remove <name>\n";
}
if (query_sign_object()) {
ret += "$I$5=The property currently has a sign set.\n";
} else {
ret += "$I$5=The property does not currently have a sign set.\n";
}
if (hint) {
ret += "$I$0= Hint: set sign <object>\n";
ret += "$I$0= Hint: remove sign\n";
}
if (sizeof(query_allowed())) {
ret += "$I$5=People allowed to change the property are " +
query_multiple_short(sort_array(query_allowed(), 0)) + ".\n";
} else if (hint) {
ret += "$I$5=Only the owner can change the property.\n";
}
ret += "$I$5=Current float is " +
MONEY_HAND->money_value_string(query_float(), place) + ".\n";
if (sizeof(_use_expression)) {
ret += "$I$5=Use condition: " + query_expression_string(_use_expression, 0) +
".\n";
} else {
ret += "$I$5=Anyone can use the shop.\n";
}
foreach (fluff, expr in _use_type_expressions) {
ret += "$I$5= Use " + fluff + " condition: " +
query_expression_string(expr, 0) + ".\n";
}
ret += "$I$0=\n";
foreach (ob in _commercial_things) {
if (ob) {
str = ob->query_main_status(hint);
if (str) {
ret += str;
}
}
}
write("$P$Status$P$" + ret);
return 1;
} /* do_status() */
/** @ignore yes */
int do_weekly_status() {
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to see the status of this store.\n");
return 0;
}
write("$P$Weekly Status$P$" + query_weekly_status_string());
return 1;
} /* do_weekly_status() */
/**
* This method sets up the expression to use when calculating the
* ability to use the shop.
*/
int do_use_expression(string str) {
class parse_node* expr;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to add restrictions to the property.\n");
return 0;
}
if (str == "disable") {
_use_expression = ({ });
add_succeeded_mess(({ "You disable checking to see if "
"someone can use the property.\n",
"$N fiddle$s about with " + the_short() + " a bit.\n" }));
return 1;
}
expr = parse_boolean_string(str);
if (!sizeof(expr)) {
add_failed_mess(query_last_expression_error() + ".\n");
return 0;
} else {
_use_expression = expr;
add_succeeded_mess(({ "You set the expression to use when checking "
"to see if someone can use the property to " +
query_expression_string(expr, 1) +
".\n",
"$N fiddle$s about with " + the_short() +
" a bit.\n" }));
event_save(this_object());
}
return 1;
} /* do_use_expression() */
/**
* This method sets up the expression to use when calculating the
* ability to use the shop.
*/
int do_use_expression_type(string type, string str) {
class parse_node* expr;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to add restrictions to the property.\n");
return 0;
}
if (!_use_type_expressions[type]) {
add_failed_mess("The type '" + type + "' is invalid, must be one "
"of " +
query_multiple_short(keys(_use_type_expressions)) +
".\n");
return 0;
}
if (str == "disable") {
_use_type_expressions[type] = ({ });
add_succeeded_mess(({ "You disable checking to see if "
"someone can use the property for " + type + ".\n",
"$N fiddle$s about with " + the_short() + " a bit.\n" }));
return 1;
}
expr = parse_boolean_string(str);
if (!sizeof(expr)) {
add_failed_mess(query_last_expression_error() + ".\n");
return 0;
} else {
_use_type_expressions[type] = expr;
add_succeeded_mess(({ "You set the expression to use when checking "
"to see if someone can use the property for " +
type + " to " +
query_expression_string(expr, 1) +
".\n",
"$N fiddle$s about with " + the_short() +
" a bit.\n" }));
event_save(this_object());
}
return 1;
} /* do_use_expression_type() */
/**
* This method shows any royalties that you might be able to collect.
* @return 1 on succes, 0 on failure
*/
int do_royalties() {
string place;
class royalty_data data;
// Check to make sure the shop is open.
if (!is_open_for("royalty", this_player()->query_name())) {
add_failed_mess(the_short() + " is not currently open for "
"customers.\n");
return 0;
}
if (!classp(_royalties[this_player()->query_name()]) &&
_royalties[this_player()->query_name()] != 0) {
data = new(class royalty_data,
value : _royalties[this_player()->query_name()],
last_withdrawl : time());
_royalties[this_player()->query_name()] = data;
}
data = _royalties[this_player()->query_name()];
if (!data) {
add_failed_mess("You have no money owed to you here.\n");
return 0;
}
if (this_player()->query_name() != query_owner() && data->value > 0) {
if (data->last_withdrawl + COMMERCIAL_ROYALTY_TIMEOUT_PERIOD - time() < 0) {
write("Your royalties timed out before you could claim them.\n");
map_delete(_royalties, this_player()->query_name());
}
}
if (data->value < 0) {
add_failed_mess("You owe money to " + the_short() + ".\n");
return 0;
}
if (data->value == 0) {
map_delete(_royalties, this_player()->query_name());
}
place = query_property("place");
if (!place) {
place = "default";
}
add_succeeded_mess(({ "You have " +
MONEY_HAND->money_value_string(data->value, place) +
" in royalties currently which will timeout in " +
query_time_string(data->last_withdrawl + COMMERCIAL_ROYALTY_TIMEOUT_PERIOD - time(), 2) + ".\n",
"$N checks $p royalties.\n" }));
return 1;
} /* do_royalites() */
/**
* This method shows any royalties that you might be able to collect.
* @return 1 on succes, 0 on failure
*/
int do_royalty_list() {
string place;
mixed value;
class royalty_data data;
string person;
string ret;
// Check to make sure the shop is open.
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("Only the property owners can do this.\n");
return 0;
}
if (!sizeof(_royalties)) {
add_failed_mess("No one has royalties here currently.\n");
return 0;
}
place = query_property("place");
ret = "";
foreach (person in sort_array(keys(_royalties), 0)) {
value = _royalties[person];
if (!classp(value)) {
data = new(class royalty_data, value : value, last_withdrawl : time());
} else {
data = value;
}
if (PLAYER_HANDLER->test_user(person)) {
ret += capitalize(person) + " " +
MONEY_HAND->money_value_string(data->value, place);
if (person != query_owner()) {
ret += " (Timeout: " + query_time_string(data->last_withdrawl +
COMMERCIAL_ROYALTY_TIMEOUT_PERIOD - time(), 2) + ")\n";
} else {
ret += "\n";
}
} else {
map_delete(_royalties, person);
}
}
place = query_property("place");
if (!place) {
place = "default";
}
write("$P$Royalties$P$" + ret);
return 1;
} /* do_royalites() */
/**
* This method shows the current royalties you can pick up.
*/
int do_collect() {
string place;
string name;
class royalty_data data;
if (!is_open_for("royalty", this_player()->query_name())) {
add_failed_mess(the_short() + " is not currently open for "
"customers.\n");
return 0;
}
place = query_property("place");
if (!place) {
place = "default";
}
name = this_player()->query_name();
if (!classp(_royalties[this_player()->query_name()]) &&
_royalties[this_player()->query_name()] != 0) {
data = new(class royalty_data,
value : _royalties[this_player()->query_name()],
last_withdrawl : time());
_royalties[this_player()->query_name()] = data;
}
data = _royalties[name];
if (!data) {
add_failed_mess("You have no royalties to collect.\n");
return 0;
}
if (name != query_owner() && data->value > 0) {
if (data->last_withdrawl + COMMERCIAL_ROYALTY_TIMEOUT_PERIOD - time() < 0) {
write("Your royalties timed out before you could claim them.\n");
map_delete(_royalties, name);
return 1;
}
}
if (data->value == 0) {
map_delete(_royalties, this_player()->query_name());
}
if (this_player()->query_refresh_time() &&
this_player()->query_refresh_time() > data->last_withdrawl) {
add_failed_mess("You have refreshed since your last collection.\n");
map_delete(_royalties, name);
return 0;
}
if ((!data || !data->value) && is_allowed(this_player()->query_name())) {
name = query_owner();
data = _royalties[name];
}
if (data->value > 0) {
this_player()->adjust_money(MONEY_HAND->create_money_array(data->value, place));
if (name == query_owner()) {
_weekly_status->withdrawls += ({ new(class float_withdrawls, amount : data->value,
person : name,
withdrawl_time : time() ) });
}
event_save(this_object());
add_succeeded_mess(({ "You collect " +
MONEY_HAND->money_value_string(data->value, place) +
" in royalties.\n",
"$N collects some royalties.\n" }));
data->value = 0;
if (!data->value && name != query_owner()) {
map_delete(_royalties, name);
}
return 1;
} else if (!data->value) {
add_failed_mess("You have no royalties to collect.\n");
} else {
if (this_player()->query_value_in(place) < -data->value) {
add_failed_mess("You do not have enough money to pay off "
"your debts.\n");
return 0;
}
this_player()->pay_money(MONEY_HAND->create_money_array(-data->value, place),
place);
add_succeeded_mess(({ "You pay off " +
MONEY_HAND->money_value_string(data->value, place) +
" in debt.\n",
"$N pays off some debt.\n" }));
if (name != query_owner()) {
map_delete(_royalties, name);
} else {
data->value = 0;
}
return 1;
}
} /* do_collect() */
/**
* This method collects royalities up to a certain amount. This is
* only usable by the owner of the shop.
* @param amount the amount to collect
* @return 1 on success, 0 on failure
*/
int do_collect_partial_royalties(string amount) {
int amt;
string place;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("Only the owners can do this.\n");
return 0;
}
place = query_property("place");
if (!place) {
place = "default";
}
amt = MONEY_HAND->value_from_string(amount, place);
if (!amt) {
add_failed_mess("The value " + amount + " is not a valid money "
"amount.\n");
return 0;
}
if (amt > query_owners_money()) {
add_failed_mess("You cannot collect more money than you have.\n");
return 0;
}
this_player()->adjust_money(MONEY_HAND->create_money_array(amt, place));
((class royalty_data)_royalties[query_owner()])->value -= amt;
if (!((class royalty_data)_royalties[query_owner()])->value) {
map_delete(_royalties, query_owner());
}
if (!_weekly_status) {
_weekly_status = new(class weekly_status);
_weekly_status->withdrawls = ({ });
}
_weekly_status->withdrawls += ({ new(class float_withdrawls, amount : amt,
person : this_player()->query_name(),
withdrawl_time : time() ) });
event_save(this_object());
add_succeeded_mess(({ "You collect " +
MONEY_HAND->money_value_string(amt, place) +
" in royalties.\n",
"$N collects some money in royalties.\n" }));
return 1;
} /* do_collect_partial_royalites() */
/**
* This method lets the person pay for entry into the premesis.
*/
int do_pay_entry() {
string place;
class parse_node ret;
if (!_entry_cost) {
add_failed_mess("Entry into " + the_short() + " is free.\n");
return 0;
}
if (!is_open_for("entry", this_player()->query_name())) {
add_failed_mess(the_short() + " is not currently open for "
"customers.\n");
return 0;
}
ret = evaluate_expression(_entry_cost, this_player()->query_name());
if (this_player()->query_value_in(place) < ret->value) {
add_failed_mess("You do not have the " +
MONEY_HAND->money_value_string(ret->value, place) +
" needed to enter.\n");
return 0;
}
this_player()->pay_money(MONEY_HAND->create_money_array(ret->value, place),
place);
// Time limit is in hours.
this_player()->add_property(file_name(this_object()),
_entry_time_limit * 60 * 60);
add_succeeded_mess("$N pay$s " +
MONEY_HAND->money_value_string(ret->value, place) +
" for entry into " + the_short() + ".\n");
return 1;
} /* do_pay_entry() */
/**
* Adds money into the float for the shop.
* @param amount the amount to add to the float
*/
int do_add_royalties(string amount) {
int amt;
string place;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You cannot add to the float.\n");
return 0;
}
place = query_property("place");
if (!place) {
place = "default";
}
amt = MONEY_HAND->value_from_string(amount, place);
if (!amt) {
add_failed_mess("The value " + amount + " is not a valid money "
"amount.\n");
return 0;
}
if (this_player()->query_value_in(place) < amt) {
add_failed_mess("You do not have " +
MONEY_HAND->money_value_string(amt, place) +
" to add to the float.\n");
return 0;
}
this_player()->pay_money(MONEY_HAND->create_money_array(amt, place),
place);
if (!classp(_royalties[query_owner()])) {
int value;
value = _royalties[query_owner()];
_royalties[query_owner()] = new(class royalty_data,
value : value,
last_withdrawl : time());
}
((class royalty_data)_royalties[query_owner()])->value += amt;
add_succeeded_mess(({ "You add " +
MONEY_HAND->money_value_string(amt, place) +
" to " + poss_short() + " float.\n",
"$N fiddles about in " + the_short() + ".\n" }));
return 1;
} /* do_add_royalties() */
/**
* This methof calls ups the estate person to purchase stuff off.
*/
int do_purchase() {
object ob;
ob = clone_object(COMMERCIAL_SALESPERSON);
ob->move(this_object(), "$N arrives in a flash.\n");
ob->set_commercial_type(query_commercial_type());
ob->do_start_speil(this_player());
return 1;
} /* do_purchase() */
/**
* This method deposits money into the float
* @param obs the objects which could be money
*/
int do_deposit(object* obs) {
object* monies;
object money;
string place;
monies = filter(obs, (: $1->id(MONEY_ALIAS) :));
if (!sizeof(monies)) {
add_failed_mess("YOu cannot deposit any of $I.\n", obs);
return 0;
}
money = monies[0];
place = query_property("place");
monies = MONEY_HAND->filter_legal_tender(money, place);
if (monies[1]) {
monies[1]->move(this_player());
//write(monies[0]->the_short());
}
if (!monies[0]) {
add_failed_mess("You must use legal tender.\n");
return 0;
}
adjust_royalty(query_owner(), monies[0]->query_value_in(place));
monies[0]->move("/room/rubbish");
add_succeeded_mess(({ "$N $V $I into " + the_short() + ".\n",
"$N $V some money into " + the_short() + ".\n" }),
monies[0..0]);
event_save(this_object());
return 1;
} /* do_deposit() */
/**
* This method adds the person to the black list.
* @param person the person to add to the black list
*/
int do_black_list_add(string name) {
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to add people to the black list.\n");
return 0;
}
name = lower_case(name);
if (!PLAYER_HANDLER->test_user(name)) {
add_failed_mess("Sorry, " + name + " does not play here.\n");
return 0;
}
if (is_allowed(name)) {
add_failed_mess("This person is in the list of people allowed to use "
"the shop. They cannot be put on a black list.\n");
return 0;
}
if (member_array(name, _black_list) != -1) {
add_failed_mess("The person " + name + " is already in the "
"black list.\n");
return 0;
}
_black_list += ({ name });
event_save(this_object());
add_succeeded_mess(({ "You add " + name + " to the black list.\n",
"$N fiddle$s with something in the shop.\n" }) );
return 1;
} /* do_black_list_add() */
/**
* This method adds their ignore list to the black list
*/
int do_black_list_add_ignore() {
string *people;
string *bad;
string *ok;
string name;
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to add people to the black list.\n");
return 0;
}
people = this_player()->query_property("ignoring");
if (!people) {
add_failed_mess("You are not ignoring anyone.\n");
return 0;
}
bad = ({ });
ok = ({ });
foreach (name in people) {
name = lower_case(name);
if (!PLAYER_HANDLER->test_user(name)) {
bad += ({ name });
} else if (member_array(name, _black_list) != -1) {
bad += ({ name });
} else {
_black_list += ({ name });
ok += ({ name });
}
}
event_save(this_object());
if (!sizeof(ok)) {
add_failed_mess("Your ignore list is already added to the black list.\n");
return 0;
}
add_succeeded_mess(({ "You add " + query_multiple_short(ok) + " to the "
"black list.\n",
"$N fiddle$s with something in the shop.\n" }) );
return 1;
} /* do_black_list_add() */
/**
* This method removes the person from the black list.
* @param person the person to remove from the black list
*/
int do_black_list_remove(string name) {
if (!is_allowed(this_player()->query_name())) {
add_failed_mess("You are not allowed to remove people from "
"the black list.\n");
return 0;
}
name = lower_case(name);
if (member_array(name, _black_list) == -1) {
add_failed_mess("The person " + name + " is not in the black list.\n");
return 0;
}
_black_list -= ({ name });
event_save(this_object());
add_succeeded_mess(({ "You remove " + name + " from the black list.\n",
"$N fiddle$s with something in the shop.\n" }) );
return 1;
} /* do_black_list_remove() */
private string variable_use_type(string seller) {
return _use_type;
} /* variable_player_guild() */
int do_measure() {
this_player()->add_succeeded_mess( this_object(),
({
"$N $V up the size of the property and calculate that it is "
"about " + query_num(query_property_size()) + " square yards.\n",
"$N $V up the size of the property.\n"
}), ({ }) );
return 1;
} /* do_measure() */
void init() {
if (!_royalties) {
_royalties = ([ ]);
}
player_housing::init();
expression_util::init();
add_command("collect", "royalties", (: do_collect() :));
add_command("royalties", "", (: do_royalties() :));
add_command("royalty", "", (: do_royalties() :));
add_command("measure", "property", (: do_measure() :) );
// The following commands are owner-only
if (!is_allowed(this_player()->query_name())) {
return ;
}
add_command("royalty", "list", (: do_royalty_list() :));
add_command("royalties", "list", (: do_royalty_list() :));
add_command("collect", "royalties of <string'amount'>",
(: do_collect_partial_royalties($4[0]) :));
add_command("royalty", "add <string'amount'> to float",
(: do_add_royalties($4[0]) :));
add_command("deposit", "[to] float <indirect:object>",
(: do_deposit :));
add_command("status", "room",
(: do_status(0) :));
add_command("status", "room {hint|hints}",
(: do_status(1) :));
add_command("status", "room weekly",
(: do_weekly_status() :));
add_command("name", "property <string'property name'>",
(: do_name_property($4[0]) :));
add_command("set", "use expression <string'expression'>",
(: do_use_expression($4[0]) :));
add_command("set",
"use expression for <string'type'> as <string'expression'>",
(: do_use_expression_type($4[0], $4[1]) :));
add_command("set", "sign <indirect:object'sign'>",
(: do_set_sign($1) :) );
add_command("remove", "sign",
(: do_remove_sign() :) );
add_command("blacklist", "add <string'person'>",
(: do_black_list_add($4[0]) :));
add_command("blacklist", "add ignore",
(: do_black_list_add_ignore() :));
add_command("blacklist", "remove <string'person'>",
(: do_black_list_remove($4[0]) :));
add_command("purchase", "stuff", (: do_purchase() :));
} /* init() */