/**
* The vault handler keeps track of inventories and other
* properties of players' vaults. It also deals with the
* monthly fees.
* @author Sandoz, 2002.
*/
#include <login.h>
#include <origin.h>
#define VAULT_SAVE_DIR SAVE_DIR "/vaults/"
#define SAVE_FILE VAULT_SAVE_DIR "main.o"
#define VAULT_CONTAINER STD_OBJECT_DIR "/vault_container"
#define VAULT_SIZE 0
#define VAULT_COST 1
#define DAY (60*60*24)
#define MONTH (30*DAY)
#define MS(x,y) (string)MONEY_H->money_value_string(x,y)
/**
* This class is used to store the data for a specific vault.
* @member sizes the vault sizes available in the specified vault
* @member vaults the players' vaults
*/
class vault_data {
string *sizes;
mapping vaults;
}
/**
* This class is used to store the properties and contents
* of a player's vault.
* @member size the size of the vault
* @member expiry_time the expiry time of the player's vault account
* @member new_vault whether the player has visited their vault yet
*/
class player_vault_data {
string size;
int expiry_time;
int new_vault;
}
private mapping vaults, warned;
private nosave mapping vault_sizes, returnables;
private void clean_vault( string *vault_names );
private void expire_vaults();
private void do_player_logon( object player );
private void save_me() {
unguarded( (: save_object, SAVE_FILE :) );
} /* save_me() */
/** @ignore yes */
void create() {
if( !unguarded( (: dir_exists, VAULT_SAVE_DIR :) ) )
unguarded( (: mkdir, VAULT_SAVE_DIR :) );
if( unguarded( (: file_exists, SAVE_FILE :) ) )
unguarded( (: restore_object, SAVE_FILE :) );
vault_sizes = ([ "small" : ({ 500, -1 }),
"medium-sized" : ({ 1000, 6000 }),
"large" : ({ 1800, 12000 }),
"very large" : ({ 3000, 30000 }),
]);
if( !mapp(vaults) )
vaults = ([ ]);
if( !mapp(warned) )
warned = ([ ]);
expire_vaults();
} /* create() */
/** @ignore yes */
string normalize_name( string name ) {
int i;
name = lower_case(name);
for( i = 0; i < strlen(name); i++ ) {
if( name[i] == ''' ) {
name = name[0..i-1] + name[i+1..];
i--;
continue;
}
if( name[i] < 'a' || name[i] > 'z')
name[i] = '_';
}
return implode( explode( name, "_") - ({ 0, "" }), "_");
} /* normalize_name() */
/** @ignore yes */
string query_vault_save_dir( string name ) {
name = normalize_name( name );
return VAULT_SAVE_DIR+name+"/";
} /* query_vault_save_dir() */
/**
* This method queries if the specified vault exists.
* @param name the name of the vault to test
* @return 1 if it exists, 0 if not
*/
int query_vault( string name ) { return !undefinedp( vaults[name] ); }
/**
* This method is called by the refresh handler.
* @param name the name of the player being refreshed
*/
void player_refreshed( string name ) {
string vault, file;
if( !sizeof(vaults) )
return;
if( origin() != ORIGIN_LOCAL && base_name(PO) != REFRESH_H )
error("Bad origin for player_refreshed.\n");
foreach( vault in keys(vaults) ) {
if( !undefinedp( vaults[vault]->vaults[name] ) ) {
file = query_vault_save_dir(vault)+name+".o";
if( unguarded( (: file_exists, file :) ) )
unguarded( (: rm, file :) );
}
map_delete( vaults[vault]->vaults, name );
}
map_delete( vaults[vault]->vaults, name );
if( pointerp( warned[vault] ) )
warned[vault] -= ({ name });
save_me();
file = query_vault_save_dir("quest_rewards")+name+".o";
if( unguarded( (: file_exists, file :) ) )
unguarded( (: rm, file :) );
log_file("VAULTS", "%s refreshed - %s\n", CAP(name), ctime(time()) );
} /* player_refreshed() */
/** @ignore yes */
int query_vault_max_weight( string size ) {
if( vault_sizes[size] )
return vault_sizes[size][VAULT_SIZE];
return 0;
} /* query_vault_max_weight() */
/**
* This method creates a container for the actual vault room.
* @param player the player we are creating the container for
* @param size the size of the container to create
* @return the container object
*/
object make_container( string player, string size ) {
object cont;
cont = clone_object(VAULT_CONTAINER);
if( size )
cont->set_max_weight( query_vault_max_weight(size) );
cont->set_open();
cont->set_stuck( 1 );
cont->reset_get();
if( player )
cont->set_ownership( player );
return cont;
} /* make_container() */
/**
* This method restores the returnables mapping for
* the specified player.
* @param name the name of the player to restore the
* returnables mapping for
*/
private void restore_returnables( string name ) {
string stuff;
stuff = unguarded( (: read_file,
query_vault_save_dir("quest_rewards")+name+".o" :) );
if( stringp(stuff) )
returnables = restore_variable( stuff );
} /* restore_returnables() */
/**
* This method removes the returnables file for the specified player.
* @param name the name of the player whose returnables to delete
*/
private void remove_returnables( string name ) {
unguarded( (: rm, query_vault_save_dir("quest_rewards")+name+".o" :) );
} /* remove_returnables() */
/**
* This method saves the returnables mapping for the specified player.
* @param name the name of the player whose returnables to save
*/
private void save_returnables( string name ) {
string d;
d = query_vault_save_dir("quest_rewards");
if( !unguarded( (: dir_exists, d :) ) )
unguarded( (: mkdir, d :) );
unguarded( (: write_file, d+name+".o", save_variable(returnables), 1 :) );
returnables = 0;
} /* remove_returnables() */
/**
* This method does the actual returning of quest items.
* @param player the player to return the items to
* @param vault the name of the vault the items are from
* @param things the things to return to the player
*/
private void do_return( object player, string vault, object *things ) {
tell_object( player, "An errand runner from "+
vault+" approaches you and returns "+
query_multiple_short(things)+" to you, for your vault "
"account has been closed down for overdue rent.\n");
things = filter( things, (: $1->move($2) :), player );
if( sizeof( things ) ) {
tell_object( player, "He places "+query_multiple_short( things,
"the")+" "+( ENV(player)->query_property("here") ||
"on the ground")+" for you are too burdened to accept "+
({"it", "them"})[query_group(things)]+".\n");
things->move( ENV(player) );
}
} /* do_return() */
/**
* This method recycles the things in an expired vault,
* and deletes the account from the vaults mapping.
* Items with the "quest_reward" property will be given
* back to players, while the rest should end up in
* general stores.
*/
private void do_recycle( string vault, string name ) {
string dir;
dir = query_vault_save_dir( vault );
if( unguarded( (: file_exists, dir+name+".o" :) ) ) {
object *qrs, cont, tmp;
cont = make_container( 0, 0 );
cont->set_save_file( dir + name );
cont->set_no_save( 1 );
unguarded( (: rm, dir+name+".o" :) );
qrs = filter( deep_inventory(cont),
(: $1->query_property("quest_reward") :) );
if( sizeof(qrs) ) {
if( ( tmp = find_player(name) ) && ENV(tmp) ) {
do_return( tmp, vault, qrs );
} else {
tmp = make_container( name, 0 );
restore_returnables( name );
if( mapp(returnables) ) {
if( returnables[vault] )
tmp->init_dynamic_arg( returnables[vault] );
} else {
returnables = ([ ]);
}
qrs->move(tmp);
returnables[vault] = tmp->query_dynamic_auto_load();
save_returnables( name );
LOGIN_H->add_static_login_call( name, "do_login_call",
base_name(TO) );
tmp->dest_me();
if( tmp )
destruct(tmp);
}
}
deep_inventory(cont)->move("/room/rubbish");
cont->dest_me();
if( cont )
destruct(cont);
}
map_delete( vaults[vault]->vaults, name );
if( pointerp( warned[vault] ) )
warned[vault] -= ({ name });
log_file("VAULTS", "%s - account recycled in %s - %s\n",
CAP(name), vault, ctime(time()) );
} /* do_recycle() */
/**
* This method queries whether or not the specified player
* has an account in the specified vault.
* @param vault the name of the vault to test
* @param name the name of the player to test
* @return 1 if the player has an account in the vault, 0 if not
*/
int query_account_in( string vault, string name ) {
if( !undefinedp( vaults[vault] ) &&
!undefinedp( vaults[vault]->vaults[name] ) ) {
if( vaults[vault]->vaults[name]->expiry_time &&
vaults[vault]->vaults[name]->expiry_time < time() ) {
do_recycle( vault, name );
save_me();
return 0;
} else {
return 1;
}
}
return 0;
} /* query_account_in() */
/**
* This method returns the expiry time of the specified vault
* for the specified player.
* @param vault the name of the vault to get the expiry time for
* @param name the name of the player to get the expiry time for
* @return the expiry time of the player's vault, or 0 if none
*/
int query_expiry_time( string vault, string name ) {
if( query_account_in( vault, name ) )
return vaults[vault]->vaults[name]->expiry_time;
return 0;
} /* query_expiry_time() */
/**
* This method returns the vault upkeep cost for one month
* for the specified player.
* @param vault the vault name to get the cost for
* @param name the name of the player to get the cost for
* @return the renting cost of one month
*/
int query_vault_rent( string vault, string name ) {
if( query_account_in( vault, name ) )
return vault_sizes[ vaults[vault]->vaults[name]->size ][VAULT_COST];
return 0;
} /* query_vault_rent() */
/**
* This method returns all available vault sizes.
*/
string *query_vault_sizes() { return keys(vault_sizes); }
/**
* This method returns the player's vault size in the specified vault.
* This will be a string representation of the vault size,
* ie. "small", "large".
* @param vault the vault to get the vault size for
* @param player the player to get the vault size for
* @return the player's vault size in the specified vault
*/
string query_player_vault_size( string vault, string player ) {
if( query_account_in( vault, player ) )
return vaults[vault]->vaults[player]->size;
return 0;
} /* query_player_vault_size() */
/**
* This method is called by the login handler and it initiates
* the process of returning quest rewards to players whose vaults
* have expired.
* @param player the player logging in
* @param type the type of login
*/
void do_login_call( mixed player, string type ) {
if( type == LOGIN && ( player = find_player(player) ) )
call_out( (: do_player_logon :), 10, player );
} /* do_login_calls() */
/**
* This method returns quest rewards from expired vaults to
* their owners upon logon.
* @param player the player logging on
*/
private void do_player_logon( object player ) {
string vault, name;
if( !player )
return;
name = player->query_name();
if( !unguarded( (: file_exists,
query_vault_save_dir("quest_rewards")+name+".o" :) ) )
return;
if( !ENV(player) ) {
tell_object( player, "An errand runner approaches you to return "
"some items to you, but decides not to, for you seem to "
"have no environment.\n");
return;
}
log_file("VAULTS", "%s reclaimed returnables - %s\n",
CAP(name), ctime(time()) );
restore_returnables(name);
remove_returnables(name);
if( mapp(returnables) ) {
object cont;
cont = make_container( name, 0 );
foreach( vault in keys(returnables) ) {
INV(cont)->dest_me();
cont->init_dynamic_arg( returnables[vault] );
do_return( player, vault, INV(cont) );
}
cont->dest_me();
if( cont )
destruct(cont);
}
returnables = 0;
LOGIN_H->remove_static_login_call( name, "do_login_call", base_name(TO) );
} /* do_player_logon() */
/** @ignore yes */
private void clean_vault( string *vault_names ) {
string vault, name;
int time, expiry;
vault = vault_names[0];
vault_names = vault_names[1..];
time = time();
foreach( name in keys( vaults[vault]->vaults ) ) {
if( !PLAYER_H->test_user( name ) ) {
if( unguarded( (: file_exists,
query_vault_save_dir(vault)+name+".o" :) ) )
unguarded( (: rm, query_vault_save_dir(vault)+name+".o" :) );
map_delete( vaults[vault]->vaults, name );
log_file("VAULTS", "%s lost account in %s (no user) - %s\n",
CAP(name), vault, ctime(time()) );
continue;
}
expiry = vaults[vault]->vaults[name]->expiry_time;
if( expiry ) {
if( expiry < time ) {
do_recycle( vault, name );
continue;
}
if( expiry - MONTH / 2 < time && ( !pointerp(warned[vault]) ||
member_array( name, warned[vault] ) == -1 ) ) {
string who;
if( !pointerp(warned[vault]) )
warned[vault] = ({ name });
else
warned[vault] += ({ name });
switch( PLAYER_H->test_gender(name) ) {
case 1 :
who = "Sir";
break;
case 2 :
who = "Madam";
break;
default :
who = CAP(name);
}
MAIL_H->do_mail_message( name, "the vault manager",
"Your vault space.", "", "Dear "+who+",\n\nYour vault "
"account in "+vault+" is going to expire on "+
ctime(expiry)+". We urge you to pay a visit to us and "
"remedy the situation in a timely manner. If you have "
"not extended your lease by "+ctime(expiry)+", we will "
"be forced to dispose of all items within your vault.\n\n"
"Management,\n"+vault, 0, 0 );
continue;
}
}
}
save_me();
if( sizeof( vault_names ) )
call_out( (: clean_vault :), 60, vault_names );
else
call_out( (: expire_vaults :), DAY );
} /* clean_vault() */
/** @ignore yes */
private void expire_vaults() {
string *vault_names;
if( sizeof( vault_names = keys(vaults) ) )
clean_vault(vault_names);
} /* expire_vaults() */
/**
* This method adds a new vault into the handler.
* @param name the name of the vault to add
* @param sizes the available vault sizes
*/
void add_vault( string name, string *sizes ) {
int i;
string *bad;
if( !name || name == "") {
printf("No vault name specified.\n");
return;
}
if( i = sizeof( bad = filter( sizes, (: !$2[$1] :), vault_sizes ) ) ) {
printf("Bad vault size%s : %s.\n", i == 1 ? "" : "s",
query_multiple_short(bad) );
return;
}
if( query_vault( name ) ) {
vaults[name]->sizes = sizes;
} else {
vaults[name] = new( class vault_data,
sizes : sizes,
vaults : ([ ]) );
}
save_me();
name = query_vault_save_dir(name);
if( !dir_exists( name ) )
unguarded( (: mkdir, name :) );
} /* add_vault() */
/**
* This method removes a vault and all associated data,
* along with all vault content. Use with care.
* @param name the name of the vault to remove
* @return 1 if successfully removed, 0 if not
*/
int remove_vault( string name ) {
string dir;
if( !adminp( previous_object(-1) ) ) {
printf("Sorry, only admin can remove vaults.\n");
return 0;
}
if( !query_vault(name) ) {
printf("No such vault.\n");
return 0;
}
map_delete( vaults, name );
map_delete( warned, name );
save_me();
dir = query_vault_save_dir(name);
map( unguarded( (: get_dir, dir :) ),
(: unguarded( (: rm, $2 + $1 :) ) :), dir );
unguarded( (: rmdir, dir :) );
log_file("VAULTS", "%s REMOVED %s - %s\n",
CAP( TP->query_name() ), name, ctime(time()) );
return 1;
} /* remove_printer() */
/**
* This method returns the cost of a single visit for the
* specified vault size.
* @param vault the vault to get the vault size for
* @param name the name of the player to get the visiting cost for
* @param visit_cost the set visit cost from the vault room
* @return the visit cost
*/
int query_visit_cost( string vault, string name, int visit_cost ) {
if( vault_sizes[vaults[vault]->vaults[name]->size][VAULT_COST] == -1 &&
!vaults[vault]->vaults[name]->new_vault )
return visit_cost;
return 0;
} /* query_player_vault_size() */
/** @ignore yes */
void event_visit( string vault, string name ) {
if( vaults[vault]->vaults[name]->new_vault ) {
vaults[vault]->vaults[name]->new_vault = 0;
save_me();
}
} /* event_visit() */
/** @ignore yes */
private string price_line( string size, string place, int open_cost,
int visit_cost, int flag ) {
int cost;
cost = vault_sizes[size][VAULT_COST];
size = CAP( add_a(size) )+" vault";
if( cost == -1 )
cost = open_cost;
else
visit_cost = 0;
if( flag ) {
if( visit_cost )
return sprintf("%-=*s%s\n", 26, size+":",
indent("Opening: "+MS( cost, place )+"\n"
"Visiting: "+MS( visit_cost, place ), 26, 79 )[26..] );
return sprintf("%-=*s%s\n", 26, size+":",
indent("Opening: "+MS( 3*cost, place )+"\n"
"Monthly fee: "+MS( cost, place ), 26, 79 )[26..] );
}
if( visit_cost )
return size+" with no upkeep fees, but an opening cost of "+
MS( cost, place )+" and a visiting cost of "+
MS( visit_cost, place )+".";
return size+" with no visiting costs, but an opening cost of "+
MS( 3 * cost, place )+" and a monthly upkeep fee of "+
MS( cost, place )+".";
} /* price_line() */
/**
* This method returns the price list for a specific vault.
* @param vault the name of the vault to get the price list for
* @param place the place for price calculations
* @param open_cost the opening cost of an account with no upkeep costs
* @param visit_cost the visiting cost of a vault with no upkeep costs
* @param flag if the flag is true, the price list will be
* formatted so that it would look better on signs etc.
*/
string query_pricing( string vault, string place, int open_cost,
int visit_cost, int flag ) {
if( query_vault( vault ) )
return implode( map( vaults[vault]->sizes,
(: price_line( $1, $2, $3, $4, $5 ) :), place, open_cost,
visit_cost, flag ), ( !flag ? " " : "\n") );
return 0;
} /* query_pricing() */
/**
* This method deposits a certain amount of money onto a player's
* vault account.
* @param vault the name of the vault we are depositing into
* @param months the number of months we want to pay the rent for
* @param prop the proprietor NPC
* @param place the place for money calculations
* @return 1 upon success, 0 upon failure
*/
int do_pay( string vault, int months, object prop, string place ) {
int amount, cost;
string name;
name = TP->query_name();
if( !query_account_in( vault, name ) ) {
prop->do_command("'You have not rented any vault space here.");
return 1;
}
if( !amount = query_vault_rent( vault, name ) ) {
prop->do_command("'Something has gone wrong with calculating your "
"monthly upkeep costs. Please talk to a creator, or file a bug "
"report.");
return 1;
}
if( amount == -1 ) {
prop->do_command("'Your vault doesn't have upkeep costs.");
return 1;
}
if( !months ) {
prop->do_command("'You have to specify the number of months you wish "
"to pay the rent for.");
return 1;
}
if( months < 0 ) {
prop->do_command("'I'm afraid we don't refund rent for vaults.");
return 1;
}
cost = amount * months;
if( (int)TP->query_value_in( place ) < cost ) {
prop->do_command("'You do not have the "+MS( cost, place )+" that "
"it would cost to pay your vault rent for "+
query_num(months)+" month"+( months == 1 ? "" : "s")+".");
return 1;
}
prop->do_command("'Very well, that'll be "+MS( cost, place )+" for "+
query_num(months)+" month"+( months > 1 ? "s" : "")+", please.");
TP->pay_money( MONEY_H->create_money_array( cost, place ), place );
vaults[vault]->vaults[name]->expiry_time += MONTH * months;
if( pointerp( warned[vault] ) )
warned[vault] -= ({ name });
save_me();
tell_room( ENV(TP), TP->the_short()+" $V$0=hands,hand$V$ some coins to "+
prop->the_short()+".\n", TP );
tell_object( TP, "You hand the coins to "+prop->the_short()+".\n"
"The rent for your vault has been paid until "+
ctime( vaults[vault]->vaults[name]->expiry_time )+".\n");
prop->do_command("'Thank you.");
return 1;
} /* do_pay() */
/**
* This method opens an account for a player.
* @param vault the name of the vault
* @param size the size of the vault we wish to apply for
* @param prop the proprietor NPC
* @param place the place for money calculations
* @param open_cost the opening cost of an account with no upkeep costs
* @param visit_cost the visiting cost of a vault with no upkeep costs
*/
int do_rent( string vault, string size, object prop, string place,
int open_cost, int visit_cost ) {
int cost, no_fee;
class player_vault_data data;
string name;
name = TP->query_name();
if( query_account_in( vault, name ) ) {
prop->do_command("'You are already renting vault space here!");
return 1;
}
if( !cost = vault_sizes[size][VAULT_COST] ) {
prop->do_command("'Something has gone wrong with calculating the "
"cost of the vault space you requested. Please talk to a "
"creator, or file a bug report.");
return 1;
}
if( cost == -1 ) {
no_fee = 1;
cost = open_cost;
} else {
cost = 3 * cost;
}
if( (int)TP->query_value_in( place ) < cost ) {
prop->do_command("'You do not have the "+MS( cost, place )+" that "
"it would cost to rent "+add_a(size)+" vault"+( no_fee ? "" :
" for three months")+".");
return 1;
}
if( no_fee ) {
prop->do_command("'The vault you requested doesn't have any upkeep "
"costs, however an initial payment of "+MS( cost, place )+" is "
"necessary, plus an entry fee of "+MS( visit_cost, place )+" each "
"time you wish to visit the vault.");
} else {
prop->do_command("'Very well, that'll be "+MS( cost, place )+". "
"This will be considered as down payment for three months.");
}
TP->pay_money( MONEY_H->create_money_array( cost, place ), place );
data = new( class player_vault_data,
size : size,
expiry_time : ( no_fee ? 0 : time() + 3 * MONTH ),
new_vault : 1 );
vaults[vault]->vaults[name] = data;
if( pointerp( warned[vault] ) )
warned[vault] -= ({ name });
save_me();
tell_object( TP, "You hand the coins to "+prop->the_short()+".\n");
tell_room( ENV(TP), TP->the_short()+" $V$0=hands,hand$V$ some coins to "+
prop->the_short()+".\n", TP );
if( !no_fee ) {
tell_object( TP, "The rent for your vault has been paid until "+
ctime( vaults[vault]->vaults[name]->expiry_time )+".\n");
prop->do_command("'Please keep in mind that once your rent runs out, "
"any items in the vault will be discarded, and you will lose the "
"vault space. For your convenience try to ensure adequate funds "
"on your vault account at all times.");
}
if( sizeof( vaults[vault]->sizes ) > 1 )
prop->do_command("'Should you wish to switch to a different vault "
"size at a later date, then you are most welcome to do so.");
log_file("VAULTS", "%s rented %s vault in %s - %s\n",
CAP(name), add_a(size), vault, ctime(time()) );
prop->do_command("'Thank you.");
return 1;
} /* do_rent() */
/** @ignore yes */
int sort_by_weight( object ob1, object ob2 ) {
int i, j;
i = ob1->query_weight();
j = ob2->query_weight();
if( i < j )
return -1;
if( i > j )
return 1;
return 0;
} /* sort_by_weight() */
/**
* This method switches a player's vault size.
* @param vault the name of the vault
* @param size the new size of the vault
* @param prop the proprietor NPC
* @param place the place for money calculations
* @param open_cost the opening cost of an account with no upkeep costs
* @param visit_cost the visiting cost of a vault with no upkeep costs
*/
int do_switch( string vault, string size, object prop, string place,
int open_cost, int visit_cost ) {
int tmp, cost, no_fee, i;
string name, ret, cur_size;
name = TP->query_name();
if( !query_account_in( vault, name ) ) {
prop->do_command("'You have not rented any vault space here.");
return 1;
}
cur_size = vaults[vault]->vaults[name]->size;
if( cur_size == size ) {
prop->do_command("'You are already renting "+add_a(size)+" vault.");
return 1;
}
if( tmp = vaults[vault]->vaults[name]->expiry_time )
tmp = to_int( to_float( tmp - time() ) / MONTH *
vault_sizes[cur_size][VAULT_COST] );
if( !cost = vault_sizes[size][VAULT_COST] ) {
prop->do_command("'Something has gone wrong with calculating the "
"cost of the vault space you requested. Please talk to a "
"creator, or file a bug report.");
return 1;
}
if( cost == -1 ) {
no_fee = 1;
cost = open_cost;
} else {
cost = 3 * cost;
}
cost -= tmp;
if( cost > 0 ) {
if( (int)TP->query_value_in( place ) < cost ) {
prop->do_command("'You do not have the additional "+
MS( cost, place )+" that it would cost to change your vault "
"from "+cur_size+" to "+add_a(size)+" one.");
return 1;
}
prop->do_command("'You have to pay an additional "+
MS( cost, place )+" to switch your vault from "+cur_size+" to "+
add_a(size)+" one.");
TP->pay_money( MONEY_H->create_money_array( cost, place ), place );
vaults[vault]->vaults[name]->expiry_time = time() + 3 * MONTH;
tell_object( TP, "You hand the coins to "+prop->the_short()+".\n");
tell_room( ENV(TP), TP->the_short()+" $V$0=hands,hand$V$ some coins "
"to "+prop->the_short()+".\n", TP );
} else {
prop->do_command("'You have paid enough rent for your current vault "
"to switch your vault from "+cur_size+" to "+
add_a(size)+" one without any additional costs.");
tmp = -tmp;
tmp = to_int( to_float(tmp) / vault_sizes[size][VAULT_COST] * MONTH );
vaults[vault]->vaults[name]->expiry_time = time() + 3 * MONTH + tmp;
}
i = vault_sizes[size][VAULT_SIZE];
if( i < vault_sizes[cur_size][VAULT_SIZE] ) {
object cont, *inv, *failed;
string dir;
dir = query_vault_save_dir( vault );
cont = make_container( name, cur_size );
cont->set_save_file( dir + name, TP );
if( cont->query_loc_weight() > i ) {
object tmp_cont;
tmp_cont = clone_object("/std/container");
inv = sort_array( INV(cont), (: sort_by_weight :) );
while( cont->query_loc_weight() > i && sizeof(inv) ) {
inv[0]->move(tmp_cont);
inv = inv[1..];
}
cont->set_max_weight( i );
inv = filter( INV(tmp_cont), (: !$1->move($2) :), cont );
cont->do_save();
cont->dest_me();
if( cont )
destruct(cont);
if( sizeof( inv = INV(tmp_cont) ) ) {
if( sizeof( failed = filter( inv, (: $1->move(TP) :) ) ) ) {
failed->move( ENV(TP) );
inv -= failed;
}
if( sizeof(inv) )
ret = query_multiple_short(inv)+" did not fit into your "
"new vault and "+
({"has", "have"})[query_group(inv)]+" been returned "
"to you";
if( sizeof(failed) ) {
if( !ret )
ret = query_multiple_short(failed)+" did not fit "
"into your new vault and "+
({"has", "have"})[query_group(failed)]+" been "
"placed on the floor because you are too "
"burdened to accept "+
({"it", "them"})[query_group(failed)];
else
ret += ", while "+query_multiple_short(failed)+" "+
({"has", "have"})[query_group(failed)]+" been "
"placed on the floor because you are too "
"burdened to accept "+
({"it", "them"})[query_group(failed)];
}
tell_object( TP, ret+".\n");
}
tmp_cont->dest_me();
if( tmp_cont )
destruct(tmp_cont);
}
}
tell_object( TP, ( !ret ? "Your" : "The rest of your")+" things have all "
"been moved over to the new vault.\n");
if( no_fee ) {
vaults[vault]->vaults[name]->expiry_time = 0;
prop->do_command("'Although the vault you are switching to doesn't "
"have any upkeep costs, you must pay an entry fee of "+
MS( visit_cost, place )+" each time you wish to visit the "
"vault.");
} else {
tell_object( TP, "The rent for your vault has been paid until "+
ctime( vaults[vault]->vaults[name]->expiry_time )+".\n");
prop->do_command("'Please keep in mind that once your rent runs out, "
"any items in the vault will be discarded, and you will lose the "
"vault space. For your convenience try to ensure adequate funds "
"on your vault account at all times.");
}
vaults[vault]->vaults[name]->size = size;
if( pointerp( warned[vault] ) )
warned[vault] -= ({ name });
save_me();
log_file("VAULTS", "%s switched account in %s from %s to %s - %s\n",
CAP(name), vault, cur_size, size, ctime(time()) );
prop->do_command("'Thank you.");
return 1;
} /* do_switch() */
/**
* This method tells the player for how long they have payed their rent.
* @param vault the vault name to get their rent for
* @param prop the proprietor NPC to do the speaking
* @return always returns 1
*/
int do_check_rent( string vault, object prop ) {
string name;
name = (string)TP->query_name();
if( !query_account_in( vault, name ) ) {
prop->do_command("'You have not rented any vault space here.");
return 1;
}
if( !vaults[vault]->vaults[name]->expiry_time )
prop->do_command("'Your vault space doesn't have any upkeep costs, "
"however you have to pay separately for each visit.");
else
prop->do_command("'The rent for your vault has been paid until "+
ctime( vaults[vault]->vaults[name]->expiry_time )+".");
return 1;
} /* do_check_rent() */
/**
* This method returns all vaults and their data.
* @return all data for vaults
*/
mapping query_vaults() { return vaults; }
/**
* This method returns the mapping of warned players.
* @return all data for warned players
*/
mapping query_warned() { return warned; }
/** @ignore yes */
string query_name() { return "The Vault Handler"; }
/** @ignore yes */
mixed stats() {
return ({
({"vaults", sizeof(vaults) }), }) + map( keys(vaults),
(: ({ $1, sizeof( $2[$1]->vaults ) || "none" }) :), vaults );
} /* stats() */