/* * *$Id* * */ /** * Newspaper subscription room * This room handles subscriptions for one specific newspaper. * @see /obj/handlers/newspaper * @see help:subscription_room * @author Wirble * @started August 2001 */ #define USE_LOGIN 1 /** The newspaper-include. */ #include <room/newspaper.h> /** The include file for moving. */ #include <move_failures.h> /** The mailer include-file. */ #include <mail.h> /** The money include-file. */ #include <money.h> /** The player-handler-include. */ #include <player_handler.h> /** The number of issues newspaper boxes are purchased with. */ #define ISSUES_PER_BOX 12 inherit "/std/room/basic_room"; /* variables */ private mapping _subscribers; private string _region; private string _paper; private string _parcel; private nosave string _savefile; /** @ignore */ void create() { ::create(); add_help_file( "newspaper_subscription" ); if( !_subscribers ) { _subscribers = ([ ]); } } /* void create() */ /** * This queries the prices for subscriptions and boxes. * @return price per issue to parcel subscribers */ int query_price_per_issue_subscriber() { int deposit_cost = 400; return deposit_cost + ( NEWSPAPER_HANDLER->query_paper_cost( _paper ) * 2 ); } /* query_price_per_issue_subscriber() */ /** * This method queries the cost per issue for boxes. * @return cost per issue for a box */ int query_price_per_issue_box() { return NEWSPAPER_HANDLER->query_paper_cost( _paper ); } /* query_price_per_issue_box() */ /** * This returns the base cost of the newspaper box. * @return the base cost of the newspaper box. */ int query_price_newspaper_box() { return load_object( NEWSPAPER_SUBSCRIPTION_OB )->query_value() + ISSUES_PER_BOX * NEWSPAPER_HANDLER->query_paper_cost( _paper ); } /* query_price_newspaper_box() */ /** * This returns the base cost of the international newspaper box. * @return the base cost of the international newspaper box. */ int query_price_international_newspaper_box() { return (load_object( NEWSPAPER_SUBSCRIPTION_OB )->query_value() + ISSUES_PER_BOX * NEWSPAPER_HANDLER->query_paper_cost( _paper )) * 2; } /* query_price_international_newspaper_box() */ /** @ignore */ private void load_me() { if( !_savefile || ( file_size( _savefile ) <= 0 && file_size( _savefile + ".o" ) <= 0 ) ) { return; } unguarded( (: restore_object( _savefile + ".o", 1 ) :) ); } /* private void load_me() */ /** @ignore */ private void save_me() { if( !_savefile ) { return; } unguarded( (: save_object( _savefile, 1 ) :) ); } /* private void save_me() */ /** @ignore */ void dest_me() { save_me(); ::dest_me(); } /* void dest_me() */ /** @ignore */ private void send_termination_mail( string name, string mess ) { object player; if( ( player = find_living( name ) ) && environment( player ) ) { tell_room( environment( player ), "An imp zips past " + player->the_short() + " screaming \"You " "have mail!\" in its high-pitched voice.\n" ); } AUTO_MAILER->auto_mail( name, _paper, "Your subscription for " + _paper, 0, "Greetings.\n" "\n" "Your subscription for " + _paper + " has ended.\n" "\n" + mess + "\n" ); } /* private void send_termination_mail() */ /** @ignore */ private int withdraw_from_account( string name, int price ) { string bank; int amount = 0; int amount_in_account; foreach( bank in BANK_HANDLER->query_accounts( name ) ) { if( BANK_HANDLER->query_account( name, bank ) >= price ) { BANK_HANDLER->adjust_account( name, bank, -price ); return 1; } else { amount += BANK_HANDLER->query_account( name, bank ); } } if( amount >= price ) { foreach( bank in BANK_HANDLER->query_accounts( name ) ) { amount_in_account = BANK_HANDLER->query_account( name, bank ); if( amount_in_account < amount ) { amount -= amount_in_account; BANK_HANDLER->adjust_account( name, bank, -amount_in_account ); } else { BANK_HANDLER->adjust_account( name, bank, -amount ); return 1; } } } send_termination_mail( name, "You failed to pay for an issue of " + _paper + "." ); return 0; } /* private int withdraw_from_account() */ /** @ignore */ private void deliver_issue( string name, int issue ) { int* editions; object player; object ob; editions = PLAYER_HANDLER->test_property( name, "Paper " + _paper ); if( !editions ) { editions = ({ }); } if( member_array( issue, editions ) == -1 ) { editions += ({ issue }); #ifdef USE_LOGIN "/secure/login"->special_add_property( name, "Paper " + _paper, editions ); #endif #ifdef USE_PLAYER_HANDLER PLAYER_HANDLER->special_add_property( name, "Paper " + _paper, editions ); #endif NEWSPAPER_HANDLER->add_edition_paper_sold( _paper, issue, NEWSPAPER_HANDLER->query_paper_cost( _paper ) ); } else { NEWSPAPER_HANDLER->add_edition_revenue( _paper, issue, NEWSPAPER_HANDLER->query_paper_cost( _paper ) ); } ob = clone_object( NEWSPAPER_OB ); ob->set_paper( _paper ); ob->set_edition( issue ); if( _parcel ) { MAIL_PARCEL_HANDLER->deposit( name, _paper, _parcel, ({ ob }) ); } if( ( player = find_living( name ) ) && environment( player ) ) { tell_room( environment( player ), "An imp rushes up to " + player->the_short() + " and squeaks " "something that very much sounds like \"You have mail!\" " "before zipping away again.\n" ); } AUTO_MAILER->auto_mail( name, _paper, "A new issue of " + _paper, 0, "Greetings.\n" "\n" "Issue " + issue + " of " + _paper + " has been " "deposited for you at the " + _parcel + " post-office.\n" "\n" "Enjoy.\n" ); } /* private void deliver_issue() */ /** * This function has to be called whenever a new issue of the paper is * released. */ void event_publish_paper(string paper) { string name; int issues; int price; int last_issue = NEWSPAPER_HANDLER->query_last_edition_num( _paper ); if (paper != _paper) { return ; } price = query_price_per_issue_subscriber(); if( _subscribers ) { foreach( name in keys( _subscribers ) ) { if( !PLAYER_HANDLER->test_user( name ) ) { map_delete( _subscribers, name ); } else { issues = _subscribers[ name ]; if( issues == -1 ) { if( withdraw_from_account( name, price ) ) { deliver_issue( name, last_issue ); } else { map_delete( _subscribers, name ); } } else if( issues >= 1 ) { deliver_issue( name, last_issue ); _subscribers[ name ]--; if( _subscribers[ name ] == 0 ) { map_delete( _subscribers, name ); send_termination_mail( name, "All issues of " + _paper + " that " "you have paid for have been " "delivered." ); } } } } } } /* void publish_issue() */ /** * This sets the region the newspaper is in. i.e. Ankh-Morpork or Klatch. This * will be used for determining the correct currency. * @param new_region The region to use. */ void set_money_place( string new_region ) { _region = new_region; } /* void set_money_place() */ /** * This method returns the money place for the newsper. * @return the money place for the newspaper */ string query_money_place() { return _region; } /* query_money_place() */ /** * This sets the paper this particular room is for. * @param new_paper The paper's official name with correct capitalization. */ protected void set_paper( string new_paper ) { if (_paper) { NEWSPAPER_HANDLER->remove_newspaper_inform(_paper, file_name(this_object())); } _paper = new_paper; NEWSPAPER_HANDLER->add_newspaper_inform(_paper, file_name(this_object())); } /* protected void set_paper() */ /** * This sets the savefile for the room. * @param filename The full filename to use */ protected void set_savefile( string filename ) { _savefile = filename; if (_savefile) { load_me(); } } /* protected void set_savefile() */ /** * This sets the parcel region for the room and thereby determines to which post * office the newspapers will be delivered, i.e. Ankh-Morpork. * @param parcel_region The region to use. */ protected void set_parcel( string parcel_region ) { _parcel = parcel_region; } /* protected void set_parcel() */ /** @ignore */ int do_subscribe( int numbers ) { string name; int price; string mess; if( !numbers || !this_player() || numbers < -1 ) { return 0; } name = this_player()->query_name(); price = query_price_per_issue_subscriber(); if( !_subscribers ) { _subscribers = ([ ]); } if( !undefinedp( _subscribers[ name ] ) && _subscribers[ name ] == -1 ) { add_failed_mess( "You already have a subscription for " + _paper + ", so there is no need to re-subscribe.\n" ); return 0; } if( numbers == -1 ) { _subscribers[ name ] = -1; add_succeeded_mess( ({"You subscribe to " + _paper + ".\n" "Your bank-account(s) will be billed whenever a " "new issue is released, until you unsubscribe.\n", "$N fill$s out a subscription form.\n" }) ); save_me(); return 1; } price *= numbers; if( this_player()->query_value_in( _region ) < price ) { add_failed_mess( "You cannot afford to pay for this many issues of " + _paper + ". It would cost you " + MONEY_HAND->money_value_string( price, _region ) + ".\n" ); return 0; } if( undefinedp( _subscribers[ name ] ) ) { _subscribers[ name ] = numbers; if( numbers == 1 ) { mess = "one issue "; } else { mess = numbers + " issues "; } } else { _subscribers[ name ] += numbers; if( numbers == 1 ) { mess = "an additional issue "; } else { mess = "an additional " + numbers + " issues "; } } this_player()->pay_money( MONEY_HAND->create_money_array( price, _region ), _region ); add_succeeded_mess( ({"You subscribe to " + mess + "of " + _paper + " and pay " + MONEY_HAND->money_value_string( price, _region ) + ".\n", "$N fill$s out a subscription form.\n" }) ); save_me(); return 1; } /* int do_subscribe() */ /** @ignore */ int do_unsubscribe() { if( undefinedp( _subscribers[ this_player()->query_name() ] ) ) { add_failed_mess( "You don't have a subscription for " + _paper + ", so you cannot unsubscribe.\n" ); return 0; } map_delete( _subscribers, this_player()->query_name() ); add_succeeded_mess( ({"You successfully unscubscribe from " + _paper + ".\n", "$N fill$s out a subscription form.\n" }) ); save_me(); return 1; } /* int do_unsubscribe() */ /** @ignore */ int do_buy( int international ) { object box; int price; if( international == 1 ) { price = query_price_international_newspaper_box(); } else { price = query_price_newspaper_box(); } if( !this_player() ) { return 0; } if( this_player()->query_value_in( _region ) < price ) { add_failed_mess( "You are too poor to afford this.\n" ); return 0; } else { this_player()->pay_money( MONEY_HAND->create_money_array( price, _region ), _region ); add_succeeded_mess( "$N purchase$s a newspaper box.\n" ); box = clone_object( NEWSPAPER_SUBSCRIPTION_OB ); box->set_paper( _paper ); box->set_international( international ); box->set_issues_left( ISSUES_PER_BOX ); box->set_last_issue( NEWSPAPER_HANDLER->query_last_edition_num( _paper )); if( box->move( this_player() ) != MOVE_OK ) { box->move( environment( this_player() ) ); write( "You cannot carry the box. It has been put on the " "floor.\n" ); } return 1; } } /* int do_buy() */ /** @ignore */ int do_check() { int i; if( !this_player() ) { return 0; } if( undefinedp( _subscribers[ this_player()->query_name() ] ) ) { add_succeeded_mess( ({"You have no subscription for " + _paper + ".\n", "$N check$s something on a list.\n" }) ); return 1; } i = _subscribers[ this_player()->query_name() ]; if( i == -1 ) { add_succeeded_mess( ({"Your subscription for " + _paper + " will continue until you unsubscribe again.\n", "$N check$s something on a list.\n" }) ); return 1; } else if( i == 1 ) { add_succeeded_mess( ({"Your subscription for " + _paper + " will expire after the next issue.\n", "$N check$s something on a list.\n" }) ); return 1; } else { add_succeeded_mess( ({ "Your subscription for " + _paper + " covers " + i + " more issues.\n", "$N check$s something on a list.\n" }) ); return 1; } } /* int do_check() */ /** @ignore */ int do_list( string subscription_type ) { string* subscriber_list; string name; subscriber_list = ({ }); if( !this_player() || !subscription_type ) { return 0; } if( subscription_type == "all" ) { foreach( name in keys( _subscribers ) ) { subscriber_list += ({ name }); } } else if( subscription_type == "pre-paid" ) { foreach( name in keys( _subscribers ) ) { if( _subscribers[ name ] > 0 ) { subscriber_list += ({ name }); } } } else if( subscription_type == "unlimited" ) { foreach( name in keys( _subscribers ) ) { if( _subscribers[ name ] == -1 ) { subscriber_list += ({ name }); } } } if( sizeof( subscriber_list ) == 0 ) { subscriber_list += ({ "none" }); } add_succeeded_mess( ({"The following people have a this kind of " "subscription for " + _paper + ":\n" + query_multiple_short( subscriber_list ) + "\n", "$N check$s some lists.\n" }) ); return 1; } /* int do_list() */ /** @ignore */ void init() { string _office; object office = 0; add_command( "subscribe", "[to] <number> [issue|issues] of " + _paper, (: do_subscribe( $4[0] ) :) ); add_command( "subscribe", "[to] " + _paper, (: do_subscribe( -1 ) :) ); add_command( "unsubscribe", "[from] " + _paper, (: do_unsubscribe() :) ); add_command( "buy", "[a] newspaper box", (: do_buy( 0 ) :) ); add_command( "buy", "[an] international newspaper box", (: do_buy( 1 ) :) ); add_command( "check", "subscription", (: do_check() :) ); /* This if for the listing of the subscriptions */ if( _office = NEWSPAPER_HANDLER->query_paper_office( _paper ) ) { office = load_object( _office ); } if( this_player()->query_creator() || ( office && office->is_editor(this_player()->query_name()) ) ) { add_command( "list", "{all|unlimited|pre-paid} subscriptions", (: do_list( $4[0] ) :) ); } /* This is for error-handling */ if( !this_player()->query_creator() ) { return; } if( !_parcel ) { write("%^WHITE%^%^BOLD%^Warning: This room's _parcel - variable " "isn't set.%^RESET%^\n" ); } if( !_region ) { write("%^WHITE%^%^BOLD%^Warning: This room's _region - variable " "isn't set.%^RESET%^\n" ); } if( !_paper ) { write("%^WHITE%^%^BOLD%^Warning: This room's _paper - variable " "isn't set.%^RESET%^\n" ); } if( !_savefile ) { tell_object( this_player(), "%^WHITE%^%^BOLD%^Warning: This room's _savefile - variable " "isn't set.%^RESET%^\n" ); } ::init(); } /* void init() */