/** * This is the council treasury inheritable. It does fun stuff! Kudos to * Pinkfish for the deposit/withdrawl stuff, which I shamelessy stole * from /std/bank. * @author Kili * @started Late October 2001 */ inherit "/std/room"; inherit "/std/room/inherit/council_base"; #define TWO_WEEKS (60 * 60 * 24 * 7 * 2) #define READ_LOG 1 #define DEPOSIT 2 #define MAGISTRATE 2 #define CITIZEN 1 #define ANYONE 0 #define COUNCIL_LOG_WITHDRAW_INDEX 0 #define COUNCIL_LOG_DEPOSIT_INDEX 1 #include <money.h> #include <move_failures.h> #include <nomic_system.h> private nosave string _save_file; private nosave string _archive; // One toon. It just makes things easier, all right? =P private int _balance = 200; private int _read; private int _dep; private int *_log; int do_withdraw(int, string, string); int do_deposit(int); int do_check(); class transaction { string person; int amount; string reason; int date; string action; } class transaction *transactions = ({ }); /** * Save the variables for this treasury. */ void save_me() { if (!_save_file) { debug_printf("Error: No save file set.\n"); return; } unguarded((: save_object, _save_file :)); return; } /* save_me() */ /** * Load the variables for this treasury. */ void load_me() { if (!_save_file) return; if (file_size(_save_file + ".o") > 0) { unguarded((: restore_object, _save_file :)); return; } return; } /** * This will check to see if the player attempting an action is allowed to * perform that action. * @param player The player attempting the action * @param type The type of action (deposting, reading logs, etc.). */ int security_check(object player, int type) { int person; int tmp; if (!type) return -1; if (!player) return -1; // Just for testing, no longer needed. // if (player->query_creator()) // return 1; if (NOMIC_HANDLER->is_magistrate_of(query_council_area(), this_player()->query_name())) { person = 2; } if (NOMIC_HANDLER->is_citizen_of(query_council_area(), this_player()->query_name())) { person = 1; } else { person = 0; } // What are they trying to do? Find that out and make tmp equal what // security level it is. if (type == READ_LOG) tmp = _read; if (type == DEPOSIT) tmp = _dep; // Do they need to be a magistrate or a citizen? Are they? switch (tmp) { case MAGISTRATE: return (person == 2); break; case CITIZEN: return (person >= 1); break; case ANYONE: return 1; } } /** * This will check the time of the last transactions, and move them into a * log file if they are over two weeks old. */ void check_time() { string str; while (transactions[0]->date + TWO_WEEKS < time()) { str = capitalize(transactions[0]->person) + " " + transactions[0]->action + " " + MONEY_HAND->money_value_string(transactions[0]->amount, query_property("place")); str += (transactions[0]->action == "withdrew" ? " for " + transactions[0]->reason : ""); str += " on " + amtime(transactions[0]->date) + ".\n"; log_file(_archive, str, 0); transactions = transactions[1..]; } } /* check_time() */ /** * @ignore yes */ void log_action(object player, int amount, string action, string word) { // This bit is actually superfluous, but why not! string reason = (word ? word : "no reason specified"); class transaction new_trans; if (!player) return; if (!amount) return; if (!action) return; new_trans = new (class transaction, person: player->query_name(), amount: amount, reason: reason, date: time(), action:action); transactions += ({ new_trans }); check_time(); save_me(); } /* log_withdrawl */ /** * @ignore yes */ varargs int view_transactions(string player) { int i; int f; string ret; if (!security_check(this_player(), READ_LOG)) { return add_failed_mess("You aren't allowed to view the transactions.\n"); } ret = "A peek at the log book reveals:\nTransactions\n---\n\n"; if (!sizeof(transactions)) { ret += "None so far.\n"; write("$P$Transactions$P$" + ret); return 1; } if(player) { for(i = 0; i <sizeof(transactions); i++) { if (transactions[i]->person != lower_case(player)) { continue; } ret += capitalize(transactions[i]->person) + " " + transactions[i]->action + " " + MONEY_HAND->money_value_string(transactions[i]->amount, query_property("place")) + (transactions[i]->action == "withdrew" ? " for " + transactions[i]->reason : "") + " on " + amtime(transactions[i]->date) + ".\n"; } } else { for (i = 0; i < sizeof(transactions); i++) { ret += capitalize(transactions[i]->person) + " " + transactions[i]->action + " " + MONEY_HAND->money_value_string(transactions[i]->amount, query_property("place")) + (transactions[i]->action == "withdrew" ? " for " + transactions[i]->reason : "") + " on " + amtime(transactions[i]->date) + ".\n"; } } write("$P$Transactions$P$" + ret); return 1; } /* view_transactions */ /** * @ignore yes */ void create() { set_short("council treasury"); set_long("This is the treasury for the council.\n"); ::create(); load_me(); add_help_file( "council_treasury" ); } /* create() */ /** * @ignore yes */ void init() { ::init(); this_player()->add_command("withdraw", this_object(), "<number'amount'> " "<string'type'> for <string'reason'>", (: do_withdraw($4[0], $4[1], $4[2]) :)); this_player()->add_command("deposit", this_object(), "<string>", (: do_deposit($4[0]) :)); this_player()->add_command("check", this_object(), "balance"); this_player()->add_command("view", this_object(), "transactions", (: view_transactions() :)); this_player()->add_command("view", this_object(), "transactions [by] <word'player'>", (: view_transactions($4[0]) :)); } /* init() */ /** * Set the save file for the treasury * @param file The file to save to */ void set_save_file(string file) { _save_file = file; } /* set_save_file() */ /** * Set the location of the treasury, to determine what type of currency to use * @param word The location */ void set_place(string word) { add_property("place", word); } /* set_place() */ /** * @ignore yes */ int do_check() { write("The treasury contains " + MONEY_HAND->money_value_string(_balance, query_property("place")) + ".\n"); return 1; } /* do_check() */ /** * @ignore yes */ int do_withdraw(int number, string type, string reason) { int amount; int best; object money; if (!NOMIC_HANDLER->is_magistrate_of(query_council_area(), this_player()->query_name())) { notify_fail("You must be a magistrate to withdraw funds.\n"); return 0; } if (number <= 0) { notify_fail("You must withdraw something.\n"); return 0; } money = clone_object(MONEY_OBJECT); money->set_money_array((mixed *) MONEY_HAND->query_values_in(query_property("place"))); if ((best = (int) money->find_best_fit(type)) == -1) { notify_fail("That currency is not legal tender here. Sorry.\n"); money->dest_me(); return 0; } type = ((mixed *) money->query_money_array())[best]; amount = number * ((mixed *) money->query_money_array())[best + 1]; if ((amount > _balance) || (amount < 0)) { notify_fail("There isn't that much in the account.\n"); money->dest_me(); return 0; } money->set_money_array(({ type, number })); _balance -= amount; save_me(); this_player()->add_succeeded_mess(this_object(), ({ "You withdraw " + (string) money->short() + ".\n" + "There is " + (string) MONEY_HAND-> money_value_string(_balance, query_property("place")) + " in your account after the withdrawal.\n", "$N withdraws some money from the treasury.\n" }), ({ })); if ((int) money->move(this_player()) != MOVE_OK) { write ("You are too heavily burdened to collect the money, so the teller " + "puts it on the counter for you.\n"); money->move(this_object()); } if (_log[COUNCIL_LOG_WITHDRAW_INDEX]) { log_action(this_player(), amount, "withdrew", reason); } this_player()->save(); return 1; } /* do_withdraw() */ /** * @ignore yes */ int do_deposit(string words) { int amount; //int total; mixed money; object *tender; object legal; object illegal; string howmuch; if (!security_check(this_player(), DEPOSIT)) { return add_failed_mess("You are not allowed to deposit.\n"); } money = (mixed) MONEY_HAND->parse_money(words, this_player(), query_property("place")); if (intp(money)) { switch (money) { case NO_MATCH: return notify_fail("You do not have \"" + words + "\".\n"); case NO_MONEY: return notify_fail("You can only deposit money.\n"); default: return notify_fail("You can only deposit legal tender.\n"); } } // Figure out the legal tender tender = MONEY_HAND->filter_legal_tender(money, query_property("place")); legal = tender[0]; illegal = tender[1]; if (legal) { amount = legal->query_value_in(query_property("place")); // Minimum amount added to prevent depositing 1c 1000 times to avoid // charges. if (amount < 200) { legal->move(this_player()); if (illegal) { illegal->move(this_player()); } add_failed_mess("That is too small an amount to deposit.\n"); return 0; } _balance += amount; save_me(); } // Give them back their illegal money and zap the other stuff. if (illegal) { illegal->move(this_player()); } if (legal) { howmuch = legal->the_short(); legal->move("/room/rubbish"); this_player()->save(); } else { add_failed_mess("Unable to find any legal money to deposit.\n"); return 0; } write("You give the teller " + howmuch + ".\n"); this_player()->add_succeeded_mess(this_object(), ({ "$N $V " + words + ".\n" "This gives a total of " + MONEY_HAND-> money_value_string(_balance, query_property("place")) + " in the treasury.\n", "$N deposits some money into the treasury.\n" }), ({ })); if (_log[COUNCIL_LOG_DEPOSIT_INDEX]) log_action(this_player(), amount, "deposited", ""); return 1; } /* do_deposit() */ /** * This sets what you must be to read the log and deposit cash, and also * wether you are logging withdrawls and deposits. * @param read_log 2 for magistrate, 1 for citizen, 0 for anyone is able to * read the log * @param deposits Same as for read_log, to see who can deposit * @param logging ({withdrwals, deposits}), are we logging? 0 for no, 1 for yes */ void set_security_levels(int read_log, int deposits, int *logging) { _read = read_log; _dep = deposits; _log = logging; } /* set_security_levels() */ /** * This sets the file to which old logs will be transferred after two weeks. * You can then modify the council archives to read the file. * @param word The file to write to */ void set_archive(string word) { _archive = word; } /* set_archive */