#pragma save_binary inherit "/global/play_parse_com"; inherit "/global/communicate"; #include "player.h" #include "term.h" #include "process_str.h" #define SHOUT_DISTANCE 1000 int earmuffs, cols, rows; static mapping colour_map; string term_name = "network"; mixed *tell_history; static string new_line = "", cur_term; static mixed *eemessages; void create() { languages = ({ "common" }); cur_lang = "common"; eemessages = ({ }); play_parse_com::create(); } string query_term_name() { return term_name; } string query_cur_term() { return cur_term; } int query_earmuffs() { return earmuffs; } string read_message( string str, string type, string lang ) { mixed bing; if( member_array( lang, languages ) == -1 ) if( (bing = (mixed)LANGUAGE_HAND->query_garble_object( lang )) ) if( LANGUAGE_HAND->query_language_magic( lang ) ) return( string ) bing->garble_text( str, previous_object() ); else if( (bing = (mixed)bing->garble_text( str, previous_object() )) ) return "You cannot read the writing " + bing + (type ? " written in " + type : "") + "\n"; else return "You could have sworn there was writing there...\n"; else return "You cannot read the writing " + (type ? " written in " + type : "") + "\n"; if( LANGUAGE_HAND->query_language_magic( lang ) ) if( (bing = (mixed)LANGUAGE_HAND->query_garble_object( lang )) ) return( string ) bing->magical_text( str, previous_object() ); else return "Error : Missing or invalid langauge interpreter.\n"; if( !type ) return str + "\n"; return "'" + str + "' written in " + type + "\n"; } string fix_string( string ret ) { string *st; int i; if( !cur_term ) if( term_name != "network" ) cur_term = term_name; else cur_term = "dumb"; if( !colour_map ) colour_map = (mapping)TERM_HANDLER->set_term_type( cur_term ); if( !stringp( ret ) || ret == "" ) return ret; st = explode( ret, "%^" ); ret = ""; for( i = 0; i < sizeof( st ); i++ ) if( stringp( colour_map[ st[ i ] ] ) ) ret += colour_map[ st[ i ] ]; else ret += st[ i ]; return ret + colour_map[ "RESET" ]; } int set_term_type( string str ) { if( !str ) { notify_fail( "Syntax: " + query_verb() + " <term_type>\n" + "Where term type is one of :-\n " + implode( (string *)TERM_HANDLER->query_term_types(), ", " ) + ".\n" ); return 0; } if( str != term_name ) { if( member_array( str, ( string * )TERM_HANDLER->query_term_types() ) == -1 ) { notify_fail( "No such terminal type as " + str + ".\n" ); return 0; } if( str != "network" ) colour_map = (mapping)TERM_HANDLER->set_term_type( str ); else this_object()->player_connected(); term_name = str; cur_term = 0; write( "Ok, terminal type set to " + str + ".\n" ); return 1; } else { notify_fail( "Terminal type unchanged as " + str + ".\n" ); return 0; } } int set_network_terminal_type( string name ) { if( term_name != "network" ) return 0; if( !name ) { cur_term = "dumb"; colour_map = 0; } if( colour_map = (mapping)TERM_HANDLER->set_network_term_type( name ) ) { cur_term = name; return 1; } } void event_commands() { add_action( "earmuffs", "ear*muffs" ); add_action( "inform", "inf*orm" ); add_action( "set_our_rows", "rows" ); add_action( "set_our_cols", "cols" ); add_action( "set_term_type", "term" ); add_action( "do_new_line", "new_*line" ); add_action( "do_tell_his", "ht*ell" ); if( this_object()->query_property( NO_LINE_PROP ) ) new_line = ""; else new_line = "\n"; } int do_tell_his( string str ) { int i; if( !pointerp( tell_history ) || !sizeof( tell_history ) ) { notify_fail( "You have not been told anything.\n" ); return 0; } write( "Your tell history is:\n" ); for( i = 0; i < sizeof( tell_history ); i++ ) { if( sizeof( tell_history[ i ] ) > 2 ) write( "** " + ctime( tell_history[ i ][ 2 ] ) + " **\n" ); efun::tell_object( this_object(), fix_string( sprintf( "%s%-=*s\n", tell_history[ i ][ 0 ], cols - strlen( tell_history[ i ][ 0 ] ), tell_history[ i ][ 1 ] ) ) ); } return 1; } int earmuffs( string str ) { string s1, s2, *types, *on; types = ({ "shout" }); if( this_object()->query_creator() ) types += ({ "creator-tell", "multiple-soul", "remote-soul", "inter-creator-tell" }); if( this_object()->query_lord() ) types += ({ "lord-tell" }); if( !(on = (string *)this_object()->query_property( "earmuffs" )) ) on = ({ }); if( !str ) { if( earmuffs ) write( "Your earmuffs are on.\n" ); else write( "Your earmuffs are off.\n" ); if( sizeof( on ) ) printf( "Earmuffed events : %-=*s", cols - 20, implode( on, ", " ) + ".\n" ); on = types - on; if( on && sizeof( on ) ) printf( "Audible events : %-=*s", cols - 18, implode( on, ", " ) + ".\n" ); return 1; } if( sscanf( str, "%s %s", s1, s2 ) == 2 ) { if( member_array( s1, types ) == -1 ) { notify_fail( "You cannot earmuff " + s1 + " events.\n" ); return 0; } switch( s2 ) { case "on": if( member_array( s1, on ) == -1 ) on += ({ s1 }); write( "Your " + s1 + " events will now be earmuffed.\n" ); break; case "off": on = on - ({ s1 }); write( "Your " + s1 + " events will not be earmuffed.\n" ); break; default: if( member_array( s1, on ) == -1 ) { write( "Your " + s1 + " events will be earmuffed.\n" ); on += ({ s1 }); } else { write( "Your " + s1 + " events will not be earmuffed.\n" ); on = on - ({ s1 }); } break; } } else switch( str ) { case "on": earmuffs = 1; write( "Ear muffs turned on.\n" ); break; case "off": earmuffs = 0; write( "Ear muffs turned off.\n" ); break; case "all": on = types; break; case "none": on = ({ }); write( "Nothing will be ear muffed any more.\n" ); break; default: if( member_array( str, types ) == -1 ) { notify_fail( "You cannot earmuff " + str + " events.\n" ); return 0; } if( member_array( str, on ) == -1 ) { write( "Your " + str + " events will be earmuffed.\n" ); on += ({ str }); } else { write( "Your " + str + " events will not be earmuffed.\n" ); on = on - ({ str }); } break; } this_player()->add_property( "earmuffs", on ); return 1; } int check_earmuffs( string type ) { string *on; if( !earmuffs ) return 0; if( !(on = (string *)this_object()->query_property( "earmuffs" )) ) return 0; if( member_array( type, on ) == -1 ) return 0; return 1; } int inform( string str ) { string *types, *on, s1, s2; types = ({ "logon" }); if( this_object()->query_creator() ) types += ({ "link-death", "message", "call", "death", "guild" }); if( this_object()->query_lord() ) types += ({ "force", "enter", "dest", "cheat", "xp" }); if( !(on = (string *)this_object()->query_property( "inform" )) ) on = ({ }); if( !str ) { if( this_object()->query_property( "inform repressed" ) ) write( "Your informs are currently being repressed.\n" ); if( sizeof( on ) ) printf( "Informed events : %-=*s", cols - 19, implode( on, ", " ) + ".\n" ); on = types - on; if( on && sizeof( on ) ) printf( "Uninformed events : %-=*s", cols - 21, implode( on, ", " ) + ".\n" ); return 1; } if( sscanf( str, "%s %s", s1, s2 ) == 2 ) { if( member_array( s1, types ) == -1 ) { notify_fail( "You cannot be informed of " + s1 + " events.\n" ); return 0; } switch( s2 ) { case "on": if( member_array( s1, on ) == -1 ) on += ({ s1 }); write( "You will now be informed of " + s1 + " events.\n" ); break; case "off": on = on - ({ s1 }); write( "You will now not be informed of " + s1 + " events.\n" ); break; default: if( member_array( s1, on ) == -1 ) { write( "You will now not be informed of " + s1 + " events.\n" ); on += ({ s1 }); } else { write( "You will now not be informed of " + s1 + " events.\n" ); on = on - ({ s1 }); } break; } } else switch( str ) { case "on": this_object()->remove_property( "inform repressed" ); write( "You are now being informed.\n" ); break; case "off": this_object()->add_property( "inform repressed", 1 ); write( "Inform is now repressed.\n" ); break; case "all": on = types; break; case "none": on = ({ }); write( "You will not be informed of anything.\n" ); break; } this_object()->add_property( "inform", on ); return 1; } void set_rows( int i ) { rows = i; } int query_rows() { return rows; } int set_our_rows( string str ) { int val; if( !str ) { notify_fail( "Rows currently set to " + rows + ".\nrows <number> to set.\n" ); return 0; } if( !sscanf( str, "%d", val ) || val <= 10 ) { notify_fail( "Invalid number of rows.\n" ); return 0; } write( "Rows set to " + val + ".\n" ); rows = val; return 1; } int query_cols() { return cols; } void set_cols( int i ) { cols = i; } int set_our_cols( string str ) { int val; if( !str ) { notify_fail( "Columns currently set to " + cols + ".\ncols <number> to set.\n" ); return 0; } if( !sscanf( str, "%d", val ) || val <= 35 ) { notify_fail( "Invalid column size.\n" ); return 0; } write( "Columns set to " + val + ".\n" ); cols = val; return 1; } int do_new_line( string str ) { switch( str ) { case 0: if( new_line == "" ) new_line = "\n"; else new_line = ""; break; case "off": new_line = ""; break; case "on": new_line = "\n"; break; default: notify_fail( "Syntax: new_line <on|off>\n" ); return 0; } if( new_line == "" ) { this_object()->add_property( NO_LINE_PROP, 1 ); write( "New lines after everything switched off.\n" ); } else { this_object()->remove_property( NO_LINE_PROP ); write( "New lines after everything switched on.\n" ); } return 1; } void add_message( object ob, string mess, int mangle ) { if( !sizeof( eemessages ) ) { call_out( "print_messages", 0 ); eemessages = ({ mess, ({ mangle, ob }) }); return; } if( eemessages[ sizeof( eemessages ) - 2 ] == mess && eemessages[ sizeof( eemessages ) - 1 ] ) eemessages[ sizeof( eemessages ) - 1 ] += ({ ob }); else eemessages += ({ mess, ({ mangle, ob }) }); } void event_inform( object ob, string mess, string type ) { string *on, inform_col; if( !(on = (string *)this_object()->query_property( "inform" )) ) on = ({ }); if( this_object()->query_property( "inform repressed" ) || (ob->query_invis() && !this_object()->query_creator()) || ((int)ob->query_invis() == 2 && !this_object()->query_lord()) || !sizeof( on ) ) return; if( member_array( type, on ) == -1 ) return; add_message( ob, "[" + sprintf( "%-=*s", cols - 2, mess ) + "]\n", 0 ); } void event_enter( object ob, string mess, object from ) { if( stringp( mess ) ) add_message( ob, mess + "\n", 1 ); } void event_exit( object ob, string mess, object to ) { ::event_exit( ob, mess, to ); if( mess ) add_message( ob, mess + "\n", 1 ); } void print_messages() { mixed * bing; string *bits; int i, j; bing = eemessages; eemessages = ({ }); tell_object( this_object(), new_line ); for( i = 0; i < sizeof( bing ); i += 2 ) { /* Do squidging of two wide patterns. */ while( i + 6 < sizeof( bing ) && bing[ i ] == bing[ i + 4 ] && bing[ i + 2 ] == bing[ i + 6 ] && bing[ i + 1 ][ 0 ] && bing[ i + 3 ][ 0 ] && bing[ i + 5 ][ 0 ] && bing[ i + 7 ][ 0 ] ) { /* Squidge... */ bing[ i + 1 ] += bing[ i + 5 ][ 1..10900 ]; bing[ i + 3 ] += bing[ i + 7 ][ 1..10000 ]; bing = delete( bing, i + 4, 4 ); } /* Three wide patterns. */ while( i + 10 < sizeof( bing ) && bing[ i ] == bing[ i + 6 ] && bing[ i + 2 ] == bing[ i + 8 ] && bing[ i + 4 ] == bing[ i + 10 ] && bing[ i + 1 ][ 0 ] && bing[ i + 3 ][ 0 ] && bing[ i + 9 ][ 0 ] && bing[ i + 11 ][ 0 ] && bing[ i + 5 ][ 0 ] && bing[ i + 7 ][ 0 ] ) { /* Squidge... */ bing[ i + 1 ] += bing[ i + 7 ][ 1..10900 ]; bing[ i + 3 ] += bing[ i + 9 ][ 1..10000 ]; bing[ i + 5 ] += bing[ i + 11 ][ 1..10000 ]; bing = delete( bing, i + 6, 6 ); } if( sizeof( bing[ i + 1 ] ) > 2 ) tell_object( this_object(), fix_string( sprintf( "%-=*s", cols, (bing[ i + 1 ][ 0 ] ? replace( bing[ i ], ({ "$s", "", "%", "", "$N", query_multiple_short( bing[ i + 1 ][ 1..10000 ], 1 ) }) ) : bing[ i ]) ) ) ); else if( bing[ i + 1 ][ 0 ] && bing[ i + 1 ][ 1 ] ) { bits = explode( "!" + bing[ i ] + "!", "%" ); if( sizeof( bits ) > 1 ) { for( j = 1; j < sizeof( bits ); j += 2 ) bits[ j ] = pluralize( bits[ j ] ); bing[ i ] = implode( bits, "" ); bing[ i ] = bing[ i ][ 1..strlen( bing[ i ] ) - 2 ]; } tell_object( this_object(), fix_string( sprintf( "%-=*s", cols, replace( bing[ i ], ({ "$s", "s", "$N", bing[ i + 1 ][ 1 ]->short() }) ) ) ) ); } else tell_object( this_object(), fix_string( sprintf( "%-=*s", cols, bing[ i ] ) ) ); } } void event_say( object caller, string str, mixed avoid ) { if( pointerp( avoid ) ) { if( member_array( this_object(), avoid ) != -1 ) return; } else if( avoid == this_object() ) return; if( stringp( str ) ) add_message( caller, (string)PROCESS_STR->do_process( str ), 0 ); } /* event_say() */ void event_write( object caller, string str ) { if( sizeof( eemessages ) ) print_messages(); efun::tell_object( this_object(), fix_string( str ) ); } void do_efun_write( string str ) { if( sizeof( eemessages ) ) print_messages(); if( stringp( str ) && cols ) efun::tell_object( this_object(), fix_string( sprintf( "%-=*s", cols, (string)PROCESS_STR->do_process( str ) ) ) ); } void event_soul( object ob, string str, mixed avoid ) { if( ob != this_object() ) { if( sizeof( avoid ) > 1 && check_earmuffs( "multiple-soul" ) ) return; event_say( ob, str, avoid ); } else do_efun_write( str ); } void event_person_say( object ob, string start, string mess, string lang ) { if( member_array( lang, languages ) == -1 ) { mixed str; if( !(str = (mixed)LANGUAGE_HAND->query_garble_object( lang )) ) return; if( !(str = (mixed)str->garble_say( start, mess )) ) return; start = str[ 0 ]; mess = str[ 1 ]; } else if( ob == this_object() ) return; add_message( ob, sprintf( "%s%-=*s\n", start, cols - strlen( start ), mess ), 0 ); } void event_person_tell( object ob, string start, string mess, string lang ) { mixed str; int id; if( member_array( lang, languages ) == -1 ) { if( !(str = (mixed)LANGUAGE_HAND->query_garble_object( lang )) ) return; if( !(str = (mixed)str->garble_say( start, mess )) ) return; start = str[ 0 ]; mess = str[ 1 ]; } else if( !pointerp( tell_history ) ) tell_history = ({ }); tell_history += ({ ({ start, mess, time() }) }); if( sizeof( tell_history ) > MAX_TELL_HIS ) tell_history = tell_history[ 1..1000 ]; add_message( ob, sprintf( "%s%-=*s\n", start, cols - strlen( start ), mess ), 0 ); if( (id = query_idle( this_object() )) > TELL_WARN_TIME ) { str = ({ }); if( id / (60 * 60) ) str += ({ (id / (60 * 60)) + " hours" }); if( (id / 60) % 60 ) str += ({ ((id / 60) % 60) + " minutes" }); if( id % 60 ) str += ({ (id % 60) + " seconds" }); write( this_object()->query_cap_name() + " has been idle for " + query_multiple_short( str ) + ".\n" ); } } void event_whisper( object ob, string start, string mess, object *obs, string lang ) { string people; mixed str; people = ""; if( member_array( lang, languages ) == -1 ) { if( !(str = (mixed)LANGUAGE_HAND->query_garble_object( lang )) ) return; if( !(str = (mixed)str->garble_whisper( start, mess )) ) return; start = str[ 0 ]; mess = str[ 1 ]; people = ": "; } else people = ""; if( member_array( this_object(), obs ) == -1 ) add_message( ob, start + "to " + query_multiple_short( obs ) + people + "\n", 0 ); else if( sizeof( obs ) == 1 ) add_message( ob, sprintf( "%s%-=*s\n", start + "to you " + people + ": ", cols - strlen( start ) - 10, mess ), 0 ); else add_message( ob, sprintf( "%s%-=*s\n", start + "to ", cols - strlen( start ) - 10, query_multiple_short( obs + ({ "you" }) ) + people + ": " + mess ), 0 ); } int abs( int i ) { if( i < 0 ) return -i; return i; } void event_person_shout( object ob, string start, string mess, string lang ) { int * co_ord1, *co_ord2, d, dx, dy; string dir; mixed str; if( ob == this_object() ) return; if( check_earmuffs( "shout" ) ) return; if( member_array( lang, languages ) == -1 ) { if( !(str = (mixed)LANGUAGE_HAND->query_garble_object( lang )) ) return; if( !(str = (mixed)str->garble_say( start, mess )) ) return; start = str[ 0 ]; mess = str[ 1 ]; } if( environment( ob ) && environment() ) { co_ord1 = (mixed *)environment( ob )->query_co_ord(); co_ord2 = (mixed *)environment()->query_co_ord(); if( !co_ord1 || !co_ord2 ) return; dx = co_ord1[ 0 ] - co_ord2[ 0 ]; dy = co_ord1[ 1 ] - co_ord2[ 1 ]; d = co_ord1[ 2 ] - co_ord2[ 2 ]; d += abs( dx ) + abs( dy ); if( d > SHOUT_DISTANCE * 5 / 4 ) return; if( dy || dx ) { if( dy > 0 ) dir = "south"; else dir = "north"; if( 3 * abs( dx ) > abs( dy ) ) if( dx > 0 ) dir = "west"; else dir = "east"; else if( 3 * abs( dy ) < abs( dx ) ) if( dx > 0 ) dir += "west"; else dir += "east"; if( d > SHOUT_DISTANCE ) str = "In the distance to the " + dir + " " + start + " something you cannot make out."; if( d < SHOUT_DISTANCE / 4 ) str = "Nearby to the " + dir + " " + start + ": " + mess; else if( d > SHOUT_DISTANCE / 2 ) str = "In the distance to the " + dir + " " + start + ": " + mess; else str = "To the " + dir + " " + start + ": " + mess; } else str = start + ": " + mess; } else str = start + ": " + mess; if( strlen( str ) > 20 ) add_message( ob, sprintf( "%-s%-=*s\n", str[ 0..19 ], cols - 20, str[ 20..10000 ] ), 0 ); else add_message( ob, str + "\n", 0 ); } void event_creator_tell( object ob, string start, string mess, int forced ) { if( ob == this_object() || (check_earmuffs( "creator-tell" ) && !forced) || !this_object()->query_creator() ) return; efun ::tell_object( this_object(), new_line + fix_string( sprintf( "%s%-=*s\n", start, cols - strlen( start ), mess ) ) ); } void event_lord_tell( object ob, string start, string mess, int forced ) { if( ob == this_object() || (check_earmuffs( "lord-tell" ) && !forced) || !"secure/master"->query_lord( (string)this_object()->query_name() ) ) return; efun ::tell_object( this_object(), new_line + fix_string( sprintf( "%s%-=*s\n", start, cols - strlen( start ), mess ) ) ); } void event_inter_creator_tell( object ob, string mname, string pname, string mess, object ig, int emote ) { if( !this_object()->query_creator() || check_earmuffs( "inter-creator-tell" ) || this_object() == ig ) return; efun ::tell_object( this_object(), new_line + fix_string( sprintf( "%s@%s%s%-=*s\n", pname, mname, ( emote ? " " : ": " ), cols - strlen( mname ) - strlen( pname ) - 3, mess ) ) ); } void event_player_echo_to( object ob, string mess ) { if( this_object()->query_lord() ) efun::tell_object( this_object(), ob->query_cap_name() + " echo to's:\n" ); efun::tell_object( this_object(), new_line + fix_string( sprintf( "%-=*s\n", cols, mess ) ) ); } void event_player_emote_all( object ob, string mess ) { if( ob == this_object() ) return; if( this_object()->query_lord() ) add_message( ob, ob->query_cap_name() + " emote all's:\n", 0 ); add_message( ob, sprintf( "%-=*s\n", cols, mess ), 0 ); } void event_player_echo( object ob, string mess ) { if( ob == this_object() ) return; if( this_object()->query_lord() ) add_message( ob, ob->query_cap_name() + " echo's:\n", 0 ); add_message( ob, sprintf( "%-=*s\n", cols, mess ), 0 ); }