/** * The standard inheritable object for player-run shop manager offices. * * <p><b>Description</b></p> * <p>The managers' office provides a front-end to the manager commands, * although these are mainly handled by the _office_. It also provides a * place of refuge for managers since only they have access to this room, * as well as allowing them to send and read their mail. Finally, it allows * them to claim a manager's handbook. * </p> * <p>From here, managers can vote on employment applications and policy * suggestions. They can make personnel decisions such as commendations, * warnings, bonus suspensions, firing and demoting employees. They can * place employees on leave for a certain period if they know that employee * is away. They can view the ordinary, accounts, personnel and chart logs. * They can rent or remove additional stock cabinets. They can ban or unban * people from the shop. They can transfer monies between the profit account, * bonus account and cash register (see below). Finally, they can retire and * stay on as a retired manager, taking no further active role in the shop * other than voting on policy suggestions. * </p> * * <p><b>Accounts</b></p> * <p>There are three accounts in the shop, the first of which is the * register. This contains the 'float' - the money used for buying and * selling stock. The register is located behind the counter and is * accessible to every employee. * </p> * <p>The profit account contains the funds used to pay operating expenses * such as cabinet rentals and employee pay. * </p> * <p>The bonus account holds the funds used to pay the monthly bonus. * </p> * <p>Monies can be transferred between all three accounts at any time, as * long as none would go negative as a result. * </p> * * @example * #include "path.h" * * inherit "/std/shops/player_shop/mgr_office"; * * void setup() * { * set_light(60); * set_office( PATH+ "office" ); * * set_short( "Tarnach Fendertwin's office" ); * set_long( "This room is the office of Tarnach Fendertwin himself. " * "Since he rarely visits this branch of the chain, it is more " * "commonly used by the shop's managers.\n" ); * add_exit( "north", PATH +"office", "door" ); * } * * @see /include/player_shop.h * @see /std/shops/player_shop/office.c * @see /std/shops/player_shop/counter.c * @see /std/shops/player_shop/storeroom.c * @see /std/shops/player_shop/shop_front.c * @see /std/shops/player_shop/shopkeeper.c * @author Ringo * @started 1st August 1999 */ inherit "/std/room/basic_room"; #include <player_shop.h> #include <mail.h> #include <move_failures.h> #include <money.h> #include "patterns.h" private nosave string _office = "", _place = "", _shop_front = "", _counter = "", _storeroom = ""; private nosave object _notice = 0; private string cap_name(string); private int do_accounts(); private int do_ban(mixed *); private int do_check(); private int do_claim(); private int do_commend(string); private int do_demote(string); private int do_fire(mixed *); private int do_leave(mixed *); private int do_list(mixed *); private int do_logs(mixed *, string); private int do_mail(string); private int do_memo(); private int do_office(); private int do_policies(); private int do_policy(mixed *,string); private int do_project(string); private int do_query(string); private int do_remove(); private int do_rent(); private int do_retire(); private int do_set(mixed *, string); private int do_suspend(mixed *); private int do_transfer(mixed *); private int do_unban(string); private int do_view(string,string); private int do_vote(mixed *, string); private int do_warn(mixed *); private void end_memo(string,string); private void end_policy_suggest(string,string,int); private void send_memo(string, string, string); protected void set_office(string); private void write_memo(string); /** @ignore yes */ void create() { do_setup++; ::create(); do_setup--; add_property("determinate", ""); if (!do_setup) { this_object()->setup(); this_object()->reset(); } add_help_file("player_shop_mgr_office"); } /* create() */ /** @ignore yes */ void init() { ::init(); if (!_office || _office == "") return; if ( !_office->query_manager(this_player()->query_name()) && !_office->query_retired(this_player()->query_name()) && !this_player()->query_creator()) return; add_command("list", ({LIST_BLANK, LIST_CHOICE}), (: do_list($4) :)); add_command("memo", "", (: do_memo() :)); add_command("office", "", (: do_office() :)); add_command("claim", "", (: do_claim() :)); add_command("accounts", "", (: do_accounts() :)); add_command("logs", ({LOG_BLANK, LOG_NUMBER, LOG_MGR}), (: do_logs($4,$5) :)); add_command("mail", ({"", "<string>"}), (: do_mail($4) :)); add_command("query", "{pay|employees}", (: do_query($4[0]) :)); add_command("view", ({VIEW_EMP, VIEW_APP}), (: do_view($4[0],$5) :)); add_command("project", "{pay|bonus}", (: do_project($4[0]) :)); add_command("vote", VOTE_POLICY, (: do_vote($4,$5) :)); add_command("policy", ({POLICY_SUGGEST, POLICY_REMOVE}), (: do_policy($4,$5) :)); add_command("policies", "", (: do_policies() :)); if (_office->query_retired(this_player()->query_name())) return; add_command("rent", "cabinet", (: do_rent() :)); add_command("remove", "cabinet", (: do_remove() :)); add_command("retire", "", (: do_retire() :)); add_command("vote", VOTE_APPLICANT, (: do_vote($4,$5) :)); add_command("check", "votes", (: do_check() :)); add_command("commend", "<word'employee'>", (: do_commend($4[0]) :)); add_command("fire", "<word'employee'> [for] <string'reason'>", (: do_fire($4) :)); add_command("warn", "<word'employee'> [for] <string'reason'>", (: do_warn($4) :)); add_command("demote", "<word'employee'>", (: do_demote($4[0]) :)); add_command("suspend", "<word'employee'> [for] <number> [months]", (: do_suspend($4) :)); add_command("leave", "<word'employee'> [for] <number> [days]", (: do_leave($4) :)); add_command("ban", "<word'person'> [for] <string'reason'>", (: do_ban($4) :)); add_command("unban", "<word'person'>", (: do_unban($4[0]) :)); add_command("set", ({SET_EMPS, SET_PAY}), (: do_set($4,$5) :)); add_command("transfer", "<number'amount'> <string'type'> [from] " "{register|bonus|profit} [to] {register|bonus|profit}", (: do_transfer($4) :)); } /* init() */ /** @ignore yes */ private string cap_name(string name) { if (test_player(name)) return PLAYER_HANDLER->query_cap_name(name); else return capitalize(name); } /** @ignore yes */ void dest_me() { if (_notice) _notice->dest_me(); ::dest_me(); } /* dest_me() */ /** @ignore yes */ private int do_accounts() { tell_object(this_player(), "The shop's accounts are as follows:\n"+ sprintf(" Cash : %s\n Bonus : %s\n Profit : %s\n", MONEY_HAND->money_value_string(_counter->query_register(), _place), MONEY_HAND->money_value_string(_office->query_bonus(), _place), MONEY_HAND->money_value_string(_office->query_profit(), _place))); return 1; } /* do_accounts() */ /** @ignore yes */ private int do_ban(mixed *args) { return _office->do_ban(args); } /** @ignore yes */ private int do_check() { string results, name = this_player()->query_name(); mapping applicants; add_succeeded_mess(""); applicants = _office->get_applicants(); applicants = filter(applicants, (: $(applicants)[$1][APP_TYPE] == 1 :)); if (this_player()->query_creator()) { results = "The following votes have been cast:\n\n"; foreach (string word in sort_array(keys(applicants), 1)) { results += cap_name(word)+ " - applied " + ctime(applicants[word][APP_TIME] )+ "\n Votes for: "; foreach (string vote in applicants[word][APP_FOR]) results += cap_name(vote) + " "; results += "\n Votes against: "; foreach (string vote in applicants[word][APP_AGAINST]) results += cap_name(vote) + " "; results += "\n Abstentions: "; foreach (string vote in applicants[word][APP_ABSTAIN]) results += cap_name(vote) + " "; results += "\n\n"; } tell_object(this_player(), "$P$Votes cast$P$"+ results); return 1; } results = "You have cast the following votes:\n\nFor: "; foreach (string vote in sort_array(keys(applicants), 1)) if (member_array(name, applicants[vote][APP_FOR]) != -1) results += cap_name(vote)+ " "; results += "\nAgainst: "; foreach (string vote in sort_array(keys(applicants), 1)) if (member_array(name, applicants[vote][APP_AGAINST]) != -1) results += cap_name(vote)+ " "; results += "\nAbstentions: "; foreach (string vote in sort_array(keys(applicants), 1)) if (member_array(name, applicants[vote][APP_ABSTAIN]) != -1) results += cap_name(vote)+ " "; tell_object(this_player(), results + "\n"); return 1; } /* do_check() */ /** @ignore yes */ private int do_claim() { object thing; if (!_office || _office == "") return 0; thing = clone_object(MGR_BOOK); thing->set_read_mess("\n "+ _office->query_shop_name()+ "\n\n" " Manager's Handbook\n\n This handbook belongs to: "+ this_player()->query_short()+ "\n\n", "common", 100); thing->set_office(_office); if (thing->move(this_player()) != MOVE_OK) { thing->move(this_object()); tell_object(this_player(), "You drop your handbook as you're carrying too much.\n"); } add_succeeded_mess("$N $V a new handbook.\n"); return 1; } /* do_claim() */ /** @ignore yes */ private int do_commend(string emp) { return _office->do_commend(emp); } /** @ignore yes */ private int do_demote(string emp) { return _office->do_demote(emp); } /** @ignore yes */ private int do_fire(mixed *args) { return _office->do_fire(args); } /** @ignore yes */ private int do_leave(mixed *args) { return _office->do_leave(args); } /** @ignore yes */ private int do_list(mixed *args) { string results, word; mapping baddies, applicants; string *applied, *hired, *awaiting; if (!sizeof(args)) args = ({"employees"}); add_succeeded_mess(""); switch (args[0]) { case "applicants" : results = " Applications for employment as at " + ctime(time()) + "\n\n"; applicants = _office->get_applicants(); if (!applicants || applicants == ([])) { tell_object(this_player(), results+ "No applications outstanding.\n"); return 1; } applied = sort_array(keys(filter(applicants, (: $(applicants)[$1][APP_TYPE] == APPLIED :))), (: $(applicants)[$1][APP_TIME] - $(applicants)[$2][APP_TIME] :)); hired = sort_array(keys(filter(applicants, (: $(applicants)[$1][APP_TYPE] == HIRED :))), (: $(applicants)[$1][APP_TIME] - $(applicants)[$2][APP_TIME] :)); awaiting = sort_array(keys(filter(applicants, (: $(applicants)[$1][APP_TYPE] == AWAITING :))), (: $(applicants)[$1][APP_TIME] - $(applicants)[$2][APP_TIME] :)); if ( sizeof(awaiting)) { results += "Applicants awaiting vacancies:\n"; foreach (word in awaiting) results += " "+ cap_name(word)+ " - confirmed employment " + ctime(applicants[word][1])+ "\n"; results += "\n"; } if (sizeof(hired)) { results += "Applicants yet to confirm their employment:\n"; foreach (word in hired) results += " "+ cap_name(word)+ " - voted in " + ctime(applicants[word][1])+ "\n"; results += "\n"; } if (sizeof(applied)) { results += "Applicants yet to be hired or rejected. Vote now!\n"; foreach (word in applied) { results += " "+ cap_name(word)+ " - applied " + ctime(applicants[word][1])+ "\n"; results += sprintf(" %-12s%-5d%-16s%-5d%-13s%-5d\n", "Votes for:", sizeof(applicants[word][APP_FOR]), "Votes against:", sizeof(applicants[word][APP_AGAINST]), "Abstentions:", sizeof(applicants[word][APP_ABSTAIN])); } } tell_object(this_player(), "$P$Applications list$P$"+ results); break; case "baddies" : if (!m_sizeof(baddies = _office->get_baddies())) { tell_object(this_player(), "There are no people on the list at the moment.\n"); return 1; } results = "This is a list of people banned from the shop:\n\n"; foreach (word in sort_array(keys(baddies), 1)) { results += cap_name(word)+ " banned by "+ baddies[word][BAD_BANNER]+ " on "+ ctime(baddies[word][BAD_TIME] )+ ".\n Banned for "+ baddies[word][BAD_REASON]+ ".\n\n"; } tell_object(this_player(), "$P$Baddies$P$\n"+ results); break; default : return _office->do_list(); } return 1; } /* do_list() */ /** @ignore yes */ private int do_logs(mixed *args, string pattern) { return _office->do_logs(args, pattern); } /* do_logs() */ /** @ignore yes */ private int do_mail(string words) { return MAIL_TRACK->mail(words); } /** @ignore yes */ private int do_memo() { tell_object(this_player(), "Subject: (hit enter for general memo)\n"); input_to((: write_memo($1) :), 0); add_succeeded_mess(""); return 1; } /* do_memo() */ /** @ignore yes */ private int do_office() { int retired = _office->query_retired(this_player()->query_name()); string result = (retired)? "As a retired manager, you can use the following commands:\n": "As a manager, you can use the following commands:\n"; result += " accounts - view register, bonus & profit accounts\n" " claim - claim a manager's handbook\n" " list - list employees, applicants or banned people\n" " logs - review the shop's logs\n" " mail - read / send mail\n" " memo - send a message to the other managers\n" " policy - suggest a new (or remove an old) policy for the shop\n" " policies - check on the proposed policies\n" " project - view anticipated paypacket & bonus values\n" " query - query pay amount or number of employees\n" " view - view a person's history with this shop\n" " or an applicant's application form\n" " vote - vote for a policy to be implemented into the shop\n"; if (!retired) result += " or for an applicant to work for the shop\n" " (un)ban - (un)ban a person from the shop for "+ BAN_LENGTH+ " days\n" " rent - rent storeroom cabinets\n" " remove - remove storeroom cabinets\n" " check - check votes you have made on applications\n" " commend - reward an outstanding employee\n" " demote - demote an employee\n" " fire - end someone's employment\n" " leave - place an employee on leave for up to "+ MAX_LEAVE+ " days\n" " retire - end your active employment at the shop\n" " set - set number of employees, and pay amount\n" " suspend - suspend an employee's bonus entitlement\n" " transfer - transfer money between register, bonus & profit\n" " warn - issue a formal warning to an employee\n"; tell_object(this_player(), result+ "\n"); add_succeeded_mess(""); return 1; } /* do_office() */ /** @ignore yes */ private int do_policies() { mapping policies = _office->get_new_policies(); if (!m_sizeof(policies)) tell_object(this_player(), "There are no policies awaiting sanction.\n"); else { int i = 1; tell_object(this_player(), "The following policies have been suggested." " Policies in existence are proposed to be overturned.\n"); foreach(string policy in m_indices(policies)) tell_object(this_player(), sprintf("%d. %s - %s [%s]. %s\n", i++, (policies[policy][POLICY_TYPE])?"MGR":"EMP", policy, policies[policy][POLICY_MGR], policies[policy][POLICY_TEXT])); } return 1; } /* do_policies() */ /** @ignore yes */ private int do_policy(mixed *args, string pattern) { string *managers, mgr; if (pattern == POLICY_SUGGEST) { if (_office->query_policy(args[1])) { tell_object(this_player(), "This name is already in use.\n"); return 1; } this_player()->do_edit(0, (: end_policy_suggest($1, $(lower_case(args[1])),$((args[0] == "manager")?1:0)) :)); add_succeeded_mess(""); return 1; } if (_office->query_policy(args[0]) < 2) { tell_object(this_player(), "This policy does not exist.\n"); return 1; } args[0] = lower_case(args[0]); tell_object(this_player(), "You suggest that the "+ args[0]+ " policy should be removed.\n"); mgr = this_player()->query_name(); managers = _office->get_managers(); managers += _office->get_retired(); managers += ({_office->query_creator()}); managers -= ({mgr}); AUTO_MAILER->auto_mail(implode(managers, ","), mgr, "TFQC policy suggestion", "", "Please note that I would like you to vote on removing the "+ args[0]+ " policy.\n", 0, 0); _office->add_policy_suggest(args[0], "", mgr); return 1; } /* do_policy() */ /** @ignore yes */ private int do_project(string projection) { add_succeeded_mess(""); switch (projection) { case "bonus" : _office->calc_bonus(); break; case "pay" : tell_object(this_player(), "For the month to date, the staff wages total "+ MONEY_HAND->money_value_string( _office->calc_pay(), _place)+ ".\n"); break; } return 1; } /* do_project() */ /** @ignore yes */ private int do_query(string query) { add_succeeded_mess(""); switch(query) { case "pay" : tell_object(this_player(), "The pay is currently set at "+ MONEY_HAND->money_value_string(_office->query_pay(), _place)+ ".\n"); break; case "employees" : tell_object(this_player(), "The maximum number of employees is currently "+ _office->query_maxemp()+ ".\n"); break; default : } return 1; } /* do_query() */ /** @ignore yes */ private int do_remove() { return _office->do_remove(); } /** @ignore yes */ private int do_rent() { return _office->do_rent(); } /** @ignore yes */ private int do_retire() { return _office->do_retire(); } /** @ignore yes */ private int do_set(mixed *args, string pattern) { return _office->do_set(args, pattern); } /* do_set() */ /** @ignore yes */ private int do_suspend(mixed *args) { return _office->do_suspend(args); } /** @ignore yes */ private int do_transfer(mixed *args) { return _office->do_transfer(args); } /** @ignore yes */ private int do_unban( string person ) { return _office->do_unban(person); } /** @ignore yes */ private int do_view(string person, string pattern) { _office->view_record(person, pattern); return 1; } /* do_view() */ /** @ignore yes */ private int do_vote(mixed *args, string pattern) { return _office->do_vote(args, pattern); } /* do_vote() */ /** @ignore yes */ private int do_warn(mixed *args) { return _office->do_warn(args); } /** @ignore yes */ private void end_memo(string text, string subject) { if (!text) { tell_object(this_player(), "Aborted.\n"); return; } tell_object(this_player(), "Do you want to keep a copy of the memo? "); input_to((: send_memo($1,$(subject),$(text)) :), 0); } /* end_memo() */ /** @ignore yes */ private void end_policy_suggest(string text, string name, int type) { string mgr, *managers; if (!text) { tell_object(this_player(), "Aborted.\n"); return; } /* Remove newlines */ text = replace_string(text, "\n", " "); text = replace_string(text, " ", " "); mgr = this_player()->query_name(); managers = _office->get_managers(); managers += _office->get_retired(); managers += ({_office->query_creator()}); managers -= ({lower_case(mgr)}); AUTO_MAILER->auto_mail(implode(managers, ","), mgr, _office->shop_very_short()+ " policy suggestion", "", "Please note that there is a new policy, "+ name+ ", on which I would like you to vote.\n", 0, 0); _office->add_policy_suggest(name, text, mgr, type); } /* end_policy_suggest() */ /** @ignore yes */ void event_death(object k, object *o, object k2, string r, string k3) { _office->event_death(k, o, k2, r, k3); } /* event_death() */ /** @ignore yes */ void event_enter(object ob, string message, object from) { _office->event_enter(ob, message, from); } /* event_enter() */ /** @ignore yes */ private void send_memo(string ans, string subject, string text) { string *managers; ans = lower_case(ans); if (strlen(ans) < 1 || (ans[0] != 'y' && ans[0] != 'n')) { tell_object(this_player(), "Do you want to keep a copy of the memo? (Yes or No)? "); input_to((: send_memo($1,$(subject),$(text)) :), 0); return; } managers = _office->get_managers(); managers += _office->get_retired(); if ( this_player()->query_creator() && this_player()->query_name() != _office->query_creator()) managers += ({lower_case(this_player()->query_name())}); managers += ({_office->query_creator()}); if ( ans[0] == 'n' ) managers -= ({lower_case(this_player()->query_name())}); if (!sizeof(managers)) { tell_object(this_player(), "\nNo recipients!\n"); return; } tell_object(this_player(), "\nSending your memo.\n"); subject = (subject && subject != "")?" - "+ subject:""; AUTO_MAILER->auto_mail(implode(managers, ","), this_player()->query_name(), _office->shop_very_short()+ " manager memo" + subject, "", text, 0, 0); } /* send_memo() */ /** @ignore yes */ protected void set_long(string long_desc) { long_desc += "Managers can use their own \"office\" commands " "from in here. There is a management policy notice on the wall.\n"; ::set_long( long_desc ); } /* set_long() */ /** * Set the path of the main office. * @example set_office( PATH+ "office" ); * @param path The full path & filename. */ protected void set_office(string path) { _office = path; _place = _office->query_place(); _shop_front = _office->query_shop_front(); _counter = _office->query_counter(); _storeroom = _office->query_storeroom(); /****************************** * Add the shop's policy notice *****************************/ _notice = clone_object(SHOP_NOTICE); _notice->set_office(_office); _notice->set_type(1); add_hidden_object(_notice); } /* set_office() */ /** @ignore yes */ private void write_memo(string text) { this_player()->do_edit(0, (: end_memo($1,$(text)) :)); } /* write_memo() */