/*
* DS history.
* 30/07/01, Shiannar: Added mail inform.
* 05/08/01, Sandoz : Added refresh inform.
* 31/01/02, Sandoz : Added someone/something expansion for darkness.
*/
/**
* This file contains all the standard event handling code that players
* need. This will handle things like informs, shouts, says, tells,
* whispers. Everything! It formats the message correctly and
* sends it to the player.
* @author Pinkfish
*/
#include <dirs.h>
#include <player.h>
#include <telnet.h>
#include <language.h>
#define SPACES " "
#ifdef OLD_THINGY
inherit "/global/player/play_parse_com";
#else
inherit "/global/player/new_parse";
#endif
inherit "/global/player/communicate";
private int earmuffs, cols, rows;
private mapping my_colours;
/*
* This so that changeing the definitions gets fixed
* when they log in again. Also keeps the save
* file smaller.
*/
private nosave mapping colour_map;
private string term_name = "network";
private string *inform_types;
private mixed tell_history;
private mixed say_history;
private nosave string _cur_term, _last_term;
private nosave object _where, *_had_shorts;
private nosave mixed _eemessages;
private nosave mixed _busy;
private nosave mapping _inform_colours = ([ "default" : "WHITE",
"logon" : "GREEN",
"death" : "RED",
"cheat" : "RED",
"multiplayer" : "RED",
"bad-password" : "RED",
"link-death" : "GREEN",
"friend" : "MAGENTA",
]);
void set_my_colours(string event_type, string colour);
mapping query_my_colours();
string find_rel(string word, int from);
private int set_our_rows(int num);
private int set_our_cols(int num);
private int do_busy(string str);
private int do_busy_player(object *players);
protected varargs int do_tell_his(string, int);
protected varargs int do_say_his(string, int);
void create() {
languages = ({ "common" });
cur_lang = "common";
_eemessages = ({ });
my_colours = ([ ]);
inform_types = ({ });
#ifdef OLD_THINGY
play_parse_com::create();
#else
new_parse::create();
#endif
} /* create() */
/**
* This method returns the current terminal name. If this is set to
* network then the network will be queried for the terminal type
* (using telnet suboption negotiation).
* @return the current terminal name
* @see query_cur_term()
* @see set_term_type()
*/
string query_term_name() { return term_name; }
/**
* This method returns the current terminal type that is being used. This
* will be 0 if the terminal name is set to network and no response has
* been gained from the remote site yet. Otherwise it should be the
* same value as the terminal name.
* @return the current terminal type
* @see query_term_name()
* @see set_term_type()
*/
string query_cur_term() { return _cur_term; }
/**
* This method tells us if the player currently has earmuffs turned on.
* @return 1 if earmuffs are on, 0 if they are not
* @see check_earmuffs()
* @see toggle_earmuffs()
*/
int query_earmuffs() { return earmuffs; }
/**
* This method returns the list of inform types this player can receive.
* @return array of inform types
*/
string *query_inform_types() {
string *types;
types = ({"logon", "birthday", "mail", "friend"});
if( creatorp(TO) ) {
types += ({"link-death", "message", "death", "error", "guild",
"delete", "help", "combat", "skill", "quest",
"multiplayer", "bad-password", "club", "debug",
"changelog", "typolog", "refresh"});
if( lordp(TO) )
types += ({"lord", "enter", "dest", "xp", "rolls", "trans"});
if( adminp(TO) )
types += ({"force", "cheat", "cpu", "ftp", "admin", "calls"});
if( adminp(TO) || DOMAIN_H->query_creator("library", TO->query_name() ) )
types += ({"autodoc"});
}
return types;
} /* query_inform_types() */
/* This is pulled back into this object for security reasons... */
/**
* This is the command to handle the inform stuff.
* It does all the turning on/off and stuff things for the informs.
* @param str the informs to listen to
* @see event_inform()
*/
protected int do_inform(string str) {
string type, *types, *on, *frog, *off, *failed;
int i;
types = query_inform_types();
foreach( type in inform_types )
if( member_array( type, types ) == -1 )
inform_types -= ({ type });
on = sort_array( inform_types || ({ }), 1 );
if( !str )
str = "";
frog = explode( str, " ");
if( !frog )
frog = ({ });
else
frog -= ({"", 0 });
if( !sizeof(frog) ) {
if( TO->query_property("inform repressed") )
write("Your informs are currently being repressed.\n");
if( sizeof(on) )
write("$I$5=You are being informed of "+
query_multiple_short(on)+" events.\n");
if( sizeof( types = sort_array( types -= on, 1 ) ) )
write("$I$5=You are not being informed of "+
query_multiple_short(types)+" events.\n");
return 1;
}
if( sizeof(frog) == 1 ) {
switch( frog[0] ) {
case "on" :
TO->remove_property("inform repressed");
write("You are now being informed. This is true!\n");
write("$I$5=You will be informed of "+
query_multiple_short(on)+" events.\n");
return 1;
case "off":
TO->add_property("inform repressed", 1 );
write("Informs are now repressed.\n");
return 1;
case "all":
on = types;
frog = frog[1..];
break;
case "none" :
on = ({ });
write("You will not be informed of anything.\n");
frog = frog[1..];
break;
}
}
failed = off = ({ });
for( i = 0; i < sizeof(frog); i++ ) {
if( member_array( frog[i], types ) == -1 ) {
failed += ({ frog[i] });
} else {
if( sizeof(frog) > i+1 ) {
switch( frog[i+1] ) {
case "on" :
if( member_array( frog[i], on ) == -1 )
on += ({ frog[i] });
i++;
break;
case "off" :
off += ({ frog[i] });
i++;
break;
default :
if( member_array( frog[i], on ) == -1 )
on += ({ frog[i] });
else
off += ({ frog[i] });
break;
}
} else {
if( member_array( frog[i], on ) == -1 )
on += ({ frog[i] });
else
off += ({ frog[i] });
}
}
}
on -= off;
if( sizeof(failed) )
write("$I$5=There are no "+query_multiple_short(failed)+" events.\n");
if( sizeof(off) )
write("$I$5=You will now not be informed of "+
query_multiple_short(off)+" events.\n");
if( sizeof(on) )
write("$I$5=You will now be informed of "+
query_multiple_short(on)+" events.\n");
inform_types = on;
return 1;
} /* do_inform() */
/**
* This method tests to see if the player can see octarine objects.
* @return 1 if they can see octarine, 0 if they cannot
*/
int query_see_octarine() {
if( creatorp(TO) )
return 1;
return 0;
} /* query_see_octarine() */
/**
* This method will do the octarine checking for you on the message.
* @param str the string to check
* @see query_see_octarine()
* @example
* string query_long_bit() {
* return "Glinting and sharp looking, the long sword is an impressive "
* "weapon in the hands of someone knowledgeable.\n" +
* this_player()->octarine_message("It glows with a fluffy octarine "
* "aura.\n");
* } /\* query_long_bit() *\/
*/
string octarine_message( string str ) {
return ( query_see_octarine() ? str : "" );
} /* octarine_message() */
/**
* This function returns the appropriate colour codes for the given event
* type. It will return the players chosen colour if they've set one or
* the default if not.
*
* @param event_type The type of event
* @return a string of colour codes.
*/
string colour_event( string event_type, string default_colour ) {
if( my_colours[event_type] )
return replace( my_colours[event_type], " ", "" );
return default_colour || "";
} /* colour_event() */
/**
* This method handles the conversersions for the colour mapping which is
* done on Discworld. This also does octarine message expansion, if the
* keyword %\^OCTARINE:message%\^ is embeded into a string then the
* inside section will be replaced with a blank string if the player
* cannot see octarine messages.
* @param str the string to do the conversion on
* @param width the width of the string
* @param indent the size of the indent
* @param args any other arguments
* @return the fixed up string
* @see efun::terminal_colour()
*/
varargs string fix_string( string str, int width, int indent, mixed args ... ) {
string octmess, *bits, bit;
int i;
if( !stringp(str) || str == "" )
return str;
if( indent > width / 3 )
indent = 4;
if( !_cur_term )
_cur_term = ( term_name != "network" ? term_name : "dumb" );
if( !colour_map )
colour_map = (mapping)TERM_H->set_term_type(_cur_term);
if( sizeof(args) )
str = sprintf( str, args ... );
bits = explode( str, "%^OCTARINE:");
foreach( bit in bits ) {
i = strsrch( bit, "%^");
if( i == -1 )
continue;
octmess = bit[0..i-1];
if( query_see_octarine() ) {
str = replace_string( str, sprintf("%%^OCTARINE:%s%%^", octmess ),
octmess );
} else {
str = replace_string( str, sprintf("%%^OCTARINE:%s%%^",
octmess ), "");
}
}
str = terminal_colour( str, colour_map, width, indent );
return str;
} /* fix_string() */
/* Send all the relevant junk down to get the information we want. */
/** @ignore yes */
void player_connected() {
_last_term = 0;
/* Turn on the option */
printf("%c%c%c", IAC, DO, TELOPT_TTYPE );
/* Get them to send us their first terminal type */
printf("%c%c%c%c%c%c", IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE );
/* Get them to send us their window size */
printf("%c%c%c", IAC, DO, TELOPT_NAWS );
} /* player_connected() */
/**
* This method sets the current terminal type for the player. If the type
* is network, then the network will be queried for the terminal type
* and that will be used. This is the distiction between the current
* terminal type and the terminal name. The name will be the value that
* is set by the player and the current type will be the information
* garnered from the network (if the name is network) or the same as the
* name.
* @param str the new terminal type
* @return 1 if the terminal was successful set, 0 if not
* @see set_term()
* @see query_term_name()
* @see query_cur_term()
*/
int set_term_type( string str ) {
if( !str )
return notify_fail( sprintf("%-=*s", cols,
"Syntax: "+query_verb()+" <term_type>\n"+
"Where term type is one of the following: "+
implode((string *)TERM_H->query_term_types(), ", ")+
".\nOr set it to \"network\", and the mud will try to "
"figure it out itself.\n") );
if( str != term_name ) {
if( member_array( str, (string *)TERM_H->query_term_types() ) != -1 ||
str == "network") {
if( str != "network")
colour_map = (mapping)TERM_H->set_term_type(str);
else
player_connected();
term_name = str;
_cur_term = 0;
write("Ok, terminal type set to "+str+".\n");
return 1;
} else {
return notify_fail("No such terminal type as "+str+".\n");
}
}
return notify_fail("Terminal type unchanged as "+str+".\n");
} /* set_term_type() */
/** @ignore yes */
void set_term(string name) {
term_name = name;
_cur_term = 0;
} /* set_term() */
/**
* This method handles the responses from the remote site informing
* us of their terminal type.
* @param name the terminal type gathered from the remote site
* @return 0 if the type was not used, 1 if it was
* @see set_term_type()
* @see query_term_name()
* @see query_cur_term()
*/
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_H->set_network_term_type(name) ) {
_cur_term = name;
return 1;
}
} /* set_network_terminal_type() */
/**
* This method adds all the event commands onto the player.
* This will be called in the player startup sequence.
*/
void event_commands() {
add_command("rows", TO, "", (: set_our_rows(0) :) );
add_command("cols", TO, "", (: set_our_cols(0) :) );
add_command("rows", TO, "<number>", (: set_our_rows($4[0]) :) );
add_command("cols", TO, "<number>", (: set_our_cols($4[0]) :) );
add_command("term", TO, "{"+
implode((string *)TERM_H->query_term_types() +
({"network"}), "|")+"}", (: set_term_type($4[0]) :) );
add_command("term", TO, "", (: set_term_type(0) :) );
add_command("inform", TO, "", (: do_inform(0) :) );
add_command("inform", TO, "<string>", (: do_inform($4[0]) :) );
if( creatorp(TO) ) {
add_command("busy", TO, "{on|off}", (: do_busy($4[0]) :) );
add_command("busy", TO, "<indirect:player>",
(: do_busy_player($1) :) );
}
} /* event_commands() */
/**
* Return function pointer for do_tell_his, for history tell only.
*/
function get_htell_func() {
if( file_name(PO) != "/cmds/player/hi_story" &&
file_name(PO) != "/cmds/lord/hi_story")
return 0;
return (: do_tell_his :);
} /* get_htell_func() */
/**
* This method is the command used to print a players tell history.
*/
protected varargs int do_tell_his(string str, int brief) {
string ret;
mixed bit, *filter_history;
if( str != "")
filter_history = filter( tell_history,
(: strsrch( lower_case($1[0]), $(str) ) > -1 :) );
else filter_history = tell_history;
if( !pointerp(filter_history) || !sizeof(filter_history) )
return notify_fail("You have not been told anything.\n");
if( undefinedp(brief) )
brief = 0;
ret = "$P$Tell History$P$Your tell history is:\n";
foreach( bit in filter_history ) {
if( !brief )
ret += "** "+ctime(bit[2])+" **\n";
ret += fix_string("%s%s\n", cols, strlen(bit[0]), bit[0], bit[1] );
}
write(ret);
return 1;
} /* do_tell_his() */
/**
* Return function pointer for do_say_his, for history say only.
*/
function get_hsay_func() {
if( file_name(PO) != "/cmds/player/hi_story" &&
file_name(PO) != "/cmds/admin/hi_story")
return 0;
return (: do_say_his :);
} /* get_hsay_func() */
/**
* This method is the command used to print a players say history.
*/
protected varargs int do_say_his(string str, int brief) {
string ret;
mixed bit, *filter_history;
if( str != "")
filter_history = filter( say_history,
(: strsrch( lower_case($1[0]), $(str) ) > -1 :) );
else
filter_history = say_history;
if( !pointerp(filter_history) || !sizeof(filter_history) )
return notify_fail("Nobody has said anything.\n");
if( undefinedp(brief) )
brief = 0;
ret = "$P$Say History$P$Your say history is:\n";
foreach( bit in filter_history ) {
if( !brief )
ret += "** "+ctime(bit[2])+" **\n";
ret += fix_string("%s%s\n", cols, strlen(bit[0]), bit[0], bit[1] );
}
write(ret);
return 1;
} /* do_say_his() */
/**
* This method handles setting the busy flag. The busy flag can only
* be set by liaisons and lords, why lords? Just because :) This
* command was inspired by moonchild.
* @param str the on or off string
* @return 1 on success, 0 on failure
*/
int do_busy( string str ) {
_busy = ( str == "on");
write("Busy set to "+str+".\n");
return 1;
} /* do_busy() */
/**
* This method allows creators to set the player for whom they are currently
* busy too.
* @param obs the player to be busy with
* @return 1 on success, 0 on failure
*/
int do_busy_player( object *obs ) {
write("Ok, setting you as busy with "+query_multiple_short(obs)+".\n");
_busy = obs;
return 1;
} /* do_busy_player() */
/**
* This method tells us if the player/creator/lord is currently in busy
* mode. This will be 1 if the creatopr is generaly busy, or
* it will return the array of players they are busy with.
* @return the busy mode flag
*/
mixed query_busy() {
if( pointerp(_busy) )
_busy -= ({ 0 });
if( pointerp(_busy) && !sizeof(_busy) )
_busy = 0;
return _busy;
} /* query_busy() */
/**
* This method will change the current value of the earmuffs on the player.
* @see check_earmuffs()
* @see query_earmuffs()
*/
void toggle_earmuffs() {
earmuffs = !earmuffs;
} /* toggle_earmuffs() */
/**
* This method checks to see if a particular event is earmuffed.
* @param type the type of event to check
* @return 1 if the event is earmuffed and 0 if it is not
* @see toggle_earmuffs()
* @see query_earmuffs()
* @example
* obs = users();
* obs = filter( obs, (: $1->check_earmuffs("shout") :) );
* // Do the shout
*/
int check_earmuffs( string type ) {
string *on;
if( !earmuffs )
return 0;
on = (string *)TO->query_property("earmuffs");
if( !on )
return 0;
return member_array( type, on ) != -1;
} /* check_earmuffs() */
/**
* This method sets the number of rows on the players screen.
* @param i the new number of rows
* @see query_rows()
*/
void set_rows( int i ) {
if( i < 5 )
return;
rows = i;
} /* set_rows() */
/**
* This method returns the current number of rows the player has
* set on their screen.
* @return the number of rows on the screen
* @see set_rows()
*/
int query_rows() { return rows; }
private int set_our_rows(int val) {
if( !val )
return notify_fail("Rows currently set to "+rows+
".\nrows <number> to set.\n");
if( val <= 10 )
return notify_fail("Invalid number of rows.\n");
write("Rows set to "+val+".\n");
rows = val;
return 1;
} /* set_our_rows() */
/**
* This method returns the current number of columns the player has
* set on their screen.
* @return the number of columns on the screen
* @see set_cols()
*/
int query_cols() { return cols; }
/**
* This method sets the current number of columns the player has set on
* their screen.
* @param i the new number of columns
* @see query_cols()
*/
void set_cols( int i ) {
if( i <= 10 || i > 999 )
return;
cols = i;
} /* set_cols() */
private int set_our_cols(int val) {
if( !val )
return notify_fail("Columns currently set to "+cols+
".\ncols <number> to set.\n");
if( val <= 35 || val > 999 )
return notify_fail("Invalid column size.\n");
write("Columns set to "+val+".\n");
cols = val;
return 1;
} /* set_our_cols() */
/**
* This method sets the colour codes for a given event.
* @param event_type the type of event to set the colour for
* @param colour the colour to set
*/
void set_my_colours( string event_type, string colour ) {
if( colour == "default") {
map_delete( my_colours, event_type );
return;
}
if( colour == "none") {
my_colours[event_type] = "";
return;
}
my_colours[event_type] = colour;
} /* set_my_colours() */
/**
* Return a players list of custom colours.
* @return a mapping of the players custom colours for different events.
*/
mapping query_my_colours() { return my_colours; }
void set_looked( object thing ) { _where = thing; }
/**
* This method does all those terrible things with messages and $'s
* turning them into real strings. It is a neat function if somewhat
* complicated :) It was written by Deutha.
* <p>
* The return array has two elements, the first being the reformed
* message and the second being the reformed things array.
* @param message the message to reform
* @param things some bonus things to reform it with
* @return an array consisting of two elements
*/
mixed reform_message( string message, mixed things ) {
int last, number;
string before, middle, after, info;
last = -1;
if( !things )
things = ({ });
if( !_where )
_where = environment();
after = message;
while( sscanf( message, "%s$R$%s$R$%s", before, middle, after ) == 3 ) {
if( sscanf( middle, "[%s]%s", info, middle ) != 2 )
info = "";
switch ( middle[ 0 ] ) {
case '-' :
number = 0;
middle = middle[ 1 .. ];
break;
case '+' :
number = 1;
middle = middle[ 1 .. ];
break;
default :
number = 2;
}
if( number == 2 || _where->query_relative( middle ) ) {
if( creatorp(TO) ) {
message = before + find_rel( middle, number ) +" ("+ middle +
")"+ after;
} else {
message = before + find_rel( middle, number ) + after;
}
} else {
message = before + info + middle + after;
}
}
after = message;
while( sscanf( message, "%s$r$%s$r$%s", before, middle, after ) == 3 ) {
if( sscanf( middle, "[%s]%s", info, middle ) != 2 )
info = "";
switch ( middle[ 0 ] ) {
case '-' :
number = 0;
middle = middle[ 1 .. ];
break;
case '+' :
number = 1;
middle = middle[ 1 .. ];
break;
default :
number = 2;
}
if( number == 2 || _where->query_relative( LENGTHEN[ middle ] ) ) {
if( creatorp(TO) ) {
message = before + SHORTEN[ find_rel( LENGTHEN[ middle ],
number ) ] +" ("+ middle + ")"+ after;
} else {
message = before + SHORTEN[ find_rel( LENGTHEN[ middle ],
number ) ] + after;
}
} else {
message = before + info + middle + after;
}
}
after = message;
while( sscanf( after, "%s$%d$%s", before, number, after ) == 3 )
last = number;
while( sscanf( message, "%s$M$%s$M$%s", before, middle, after ) == 3 ) {
last++;
message = before +"$"+ last +"$"+ after;
things += ({ ({ }) });
if( strsrch(middle, "$") == -1 ) {
things[ last ] += ({ middle });
middle = 0;
} else {
while ( sscanf( middle, "$%s$%s", info, middle ) == 2 )
things[ last ] += ({ "my_"+ info });
}
}
after = message;
message = "";
while( sscanf( after, "%s$%s$%s", before, middle, after ) == 3 ) {
if( sscanf( middle, "%s_short:%s", middle, info ) != 2 ) {
message += before +"$"+ middle;
after = "$"+ after;
continue;
}
last++;
message += before +"$"+ last +"$";
things += ({ ({ "my_"+ middle +"_short:"+ info }) });
}
message += after;
return ({ message, things });
} /* reform_message() */
/**
* This adds a message into the current list of printable messages. This
* will be squided up together and printed out slightly later, this handles
* the concatenating of enter messages, and soul messages. Etc.
* @param message the message to add
* @param things the objects which are involved with the message
* @see reform_message()
*/
void add_message( string message, mixed things ) {
int last;
mixed stuff;
if( !interactive( TO ) )
return;
if( strsrch( message, "$" ) == -1 )
stuff = ({ message, things });
else
stuff = reform_message( message, things );
_where = 0;
if( !sizeof( _eemessages ) ) {
call_out( "print_messages", 2 );
_eemessages = stuff;
} else {
last = sizeof( _eemessages ) - 2;
if( stuff[ 0 ] == _eemessages[ last ] && sizeof( stuff[ 1 ] ) == 1 ) {
if( sizeof( filter( stuff[ 1 ][ 0 ],
(: member_array($1, $2) != -1 :),
_eemessages[ last + 1 ][ 0 ] ) ) ) {
_eemessages += stuff;
} else {
_eemessages[ last + 1 ][ 0 ] += stuff[ 1 ][ 0 ];
}
} else {
_eemessages += stuff;
}
}
} /* add_message() */
/**
* This method checks whether or not the room the
* player is in is dark enough to use 'someone'
* instead of regular shorts.
*/
int query_is_dark( object thing ) {
if( !ENV(TO) || thing == ENV(TO) || ( ENV(thing) && ENV(thing) == TO ) ||
TO->query_property("doing_soul") ||
( creatorp(TO) && !TO->query_property("always_dark") ) )
return 0;
return TO->check_dark( ENV(TO)->query_light() ) != 0;
} /* query_is_dark() */
/**
* @ignore yes
* This method is used for the reform_mesage stuff
*/
string get_pretty_short( object thing ) {
if( !thing->query_visible( TO ) || TO->query_is_dark(thing) )
return ( living( thing ) ? "someone" : "something" );
return (string)thing->pretty_short( TO ) +
(string)thing->hide_invis_string();
} /* get_pretty_short() */
/**
* @ignore yes
* This method is used for the reform_message stuff
*/
string get_pretty_plural( object thing ) {
if( !thing->query_visible( TO ) || TO->query_is_dark(thing) )
return ( living( thing ) ? "people" : "things" );
return (string)thing->pretty_plural( TO ) +
(string)thing->hide_invis_string();
} /* get_pretty_plural() */
/**
* This is a special function for use with the reform message, it allows
* the string to be echoed into the list instead of using the object's
* value itself. This is done specifically to handle objects with
* variable shorts, so we get the short description correct at the
* moment it is queried.
*/
string my_mirror_short( object thing, string arg ) {
return arg;
} /* my_mirror_short() */
/**
* @ignore yes
* This method is used for the reform_mesage stuff
*/
string my_a_short( object thing ) {
string article;
if( !objectp( thing ) )
return "an unknown object";
// forget the article if it's dark.
if( TO->query_is_dark( thing ) )
return (string)TO->get_pretty_short( thing );
if( !article = (string)thing->query_determinate( TO ) )
return add_a( (string)TO->get_pretty_short( thing ) );
return article + (string)TO->get_pretty_short( thing );
} /* my_a_short() */
/**
* @ignore yes
* This method is used for the reform_mesage stuff
*/
string my_the_short( object thing ) {
string article;
if( !objectp( thing ) )
return "the unknown object";
// forget the article if it's dark.
if( TO->query_is_dark( thing ) )
return (string)TO->get_pretty_short( thing );
if( !( article = (string)thing->query_determinate( TO ) ) ||
article == "a " || article == "an " )
return "the "+ (string)TO->get_pretty_short( thing );
return article + (string)TO->get_pretty_short( thing );
} /* my_the_short() */
/** @ignore yes */
int some_more( string word ) {
return sizeof( filter( INV( _where ),
(: $1->query_plural() == $(word) :) ) ) > 1;
} /* some_more() */
/**
* @ignore yes
* This method is used for the reform_mesage stuff
*/
string my_one_short( object thing ) {
string article, its_plural;
if( !objectp( thing ) )
return "one of the unknown objects";
_where = ( ENV(thing) && ENV( thing ) != ENV(TO) ? ENV(thing) :
environment() );
// forget the article if it's dark.
if( TO->query_is_dark( thing ) )
return (string)TO->get_pretty_short( thing );
if( !( article = (string)thing->query_determinate( TO ) ) ||
article == "a " || article == "an " ) {
its_plural = (string)TO->get_pretty_plural( thing );
if( some_more( its_plural ) )
return "one of the "+ its_plural;
return "the "+ (string)TO->get_pretty_short( thing );
}
return article + (string)TO->get_pretty_short( thing );
} /* my_one_short() */
/**
* @ignore yes
* This method is used for the reform_mesage stuff
*/
string my_poss_short( object thing ) {
string article, its_plural, of_whom;
if( !objectp( thing ) )
return "an unknown object";
if( living(thing) ) {
if( thing == TO )
return "your";
_where = ( ENV( thing ) != ENV(TO) ? TO : environment() );
return TO->my_one_short( thing ) + ( some_more(
(string)TO->get_pretty_plural( thing ) ) ?
( TO->query_is_dark( thing ) ? "'s" : "'") : "'s" );
}
if( !_where = environment( thing ) )
return my_a_short( thing );
if( !living( _where ) && !_where->query_corpse() )
return my_a_short( thing );
if( _where == TO ) {
of_whom = "your ";
} else {
// forget the owner if it's dark.
if( TO->query_is_dark( thing ) )
return (string)TO->get_pretty_short( thing );
of_whom = ( member_array( _where, _had_shorts ) != -1 ?
(string)_where->query_possessive() :
my_the_short( _where ) +"'s" ) +" ";
}
if( !article || article == "a " || article == "an " ) {
its_plural = (string)TO->get_pretty_plural( thing );
if( thing->query_holder() ) {
foreach( object ob in thing->query_holder()->query_holding() ) {
if( ob && ob != thing &&
(string)TO->get_pretty_plural( ob ) == its_plural )
return "one of "+ of_whom + its_plural;
}
return of_whom + (string)TO->get_pretty_short( thing );
}
if( some_more( its_plural ) )
return "one of "+ of_whom + its_plural;
}
return of_whom + (string)TO->get_pretty_short( thing );
} /* my_poss_short() */
/**
* @ignore yes
* This method is used for the reform_message stuff
*/
string calc_shorts( string *short_list ) {
int i;
string list, str, desc;
object ob, *things;
// These next two are tied.
string *descs_str;
mixed descs_ob;
mixed parts;
descs_str = ({ });
descs_ob = ({ });
foreach( str in short_list ) {
parts = explode( str, ":" );
if( sizeof(parts) > 1 ) {
ob = find_object( parts[ 1 ] );
} else {
ob = 0;
parts += ({""});
}
if( ob )
_had_shorts = ({ ob }) + _had_shorts;
if( ob == TO )
desc = ( parts[0] == "my_poss_short" ? "your" : "you" );
else if( sizeof(parts) >= 2 )
desc = (string)call_other( TO, parts[0], ob, parts[1] );
else
desc = ( sizeof(parts[0]) ? parts[0] : "something" );
if( ( i = member_array( desc, descs_str ) ) == -1 ) {
descs_str += ({ desc });
descs_ob += ({ ({ ob }) });
} else {
descs_ob[i] += ({ ob });
}
}
if( ( i = member_array( "you", descs_str ) ) != -1 &&
i != sizeof(descs_str) - 1 ) {
descs_str = descs_str[0..i-1] + descs_str[i+1..] + ({ "you" });
descs_ob = descs_ob[0..i-1] + descs_ob[i+1..] + descs_ob[i..i];
}
list = "";
for( i = 0; i < sizeof( descs_str ); i++ ) {
things = descs_ob[ i ];
if( sizeof( things ) == 1 ) {
list += descs_str[ i ];
} else {
things -= ({ 0 });
if( sizeof(things) ) {
list += query_num( sizeof( things ), 20 )+" "+
(string)TO->get_pretty_plural( things[ 0 ] );
} else {
list += query_num( sizeof( things ), 20 ) +" unknown objects";
}
}
if( i == sizeof( descs_str ) - 1 )
continue;
list += ( i == sizeof( descs_str ) - 2 ? " and " : ", " );
}
return list;
} /* calc_shorts() */
/**
* This method fits a message into a the current players screen size. This
* does all sorts of other evil stuff too, like handling indenting and
* all sorts of things! Most of which I do not understand so I won't
* say anything about here.
* @param message the message to fit in
* @return the fitted message
*/
string fit_message( string message ) {
int left, right, space;
string *parts, part;
mixed stuff;
if( strlen( message ) < 6 )
return message;
if( message[0..2] != "$I$" )
message = "$I$0=$C$" + message;
parts = explode( message, "$C$" );
parts = map( parts, (: CAP($1) :) );
parts = explode( implode( parts, "" ), "$I$");
message = "";
foreach( part in parts ) {
if( sscanf( part, "%s=%s", stuff, part ) != 2 ) {
message += fix_string( "$I$"+part, cols );
continue;
}
if( stuff == "") {
message += fix_string( "$I$="+part, cols );
continue;
}
if( stuff[0] == ' ' )
space = !space;
stuff = explode( stuff, "," );
if( sizeof(stuff) && stuff[0] != "" ) {
switch( stuff[0][0] ) {
case '+' :
if( space && left > 0 && part != "")
part = SPACES[0..left-1] + part;
left += to_int( stuff[0][1..] );
break;
case '-' :
left -= to_int( stuff[0][1..] );
if( left < 0 )
left = 0;
if( space && left > 0 && part != "")
part = SPACES[0..left-1] + part;
break;
default :
left = to_int( stuff[0] );
}
} else {
left = 0;
}
if( sizeof( stuff ) > 1 ) {
switch( stuff[1][0] ) {
case '+' :
right += to_int( stuff[1][1..] );
break;
case '-' :
right -= to_int( stuff[1][1..] );
if( right < 0 )
right = 0;
break;
default :
right = to_int( stuff[1] );
}
} else {
right = 0;
}
message += ( left > 0 ?
fix_string( part, cols - right, left ) :
fix_string( part, cols - right ) );
}
return message;
} /* fit_message() */
/**
* This method shows the message to the player.
* @param message the message to show
* @see fit_message()
*/
void show_message( string message ) {
string bit;
if( sscanf( message, "$P$%s$P$%s", bit, message ) == 2 ) {
TO->more_string( fit_message( message ), bit, 1 );
return;
}
efun::tell_object( TO, fit_message( message ) );
} /* show_message() */
/** @ignore yes */
protected void clear_had_shorts() { _had_shorts = ({ }); }
/**
* This is the main evaluation routine. This is the one that
* co-ordinates the works... It is used by the print_messages
* routine to create the message to print out.
* <p>
* The input parameter contains two elements, the first is the
* message and the second is the things array. This corresponds to
* the values returned by the fix_message method.
* @param stuff the message to evaulate
* @return the nice printed out string
* @see print_messages()
*/
string evaluate_message( mixed stuff ) {
int i;
string message, start, finish, verb_sing, verb_plur;
message = stuff[0];
clear_had_shorts();
for( i = 0; i < sizeof( stuff[1] ); i++ ) {
// Things assume this ordering, so do not change.
message = replace_string( message, "$"+i+"$",
calc_shorts( stuff[1][i] ) );
while( sscanf( message, "%s$V$"+ i +"=%s,%s$V$%s", start, verb_sing,
verb_plur, finish ) == 4 ) {
if( sizeof( stuff[1][i] ) == 1 && sizeof(_had_shorts) &&
objectp( _had_shorts[0] ) ) {
if( _had_shorts[0]->query_property("group object") ||
_had_shorts[0]->group_object() ) {
message = start+verb_plur+finish;
} else {
message = start+verb_sing+finish;
}
} else {
message = start+verb_plur+finish;
}
}
}
return message;
} /* evaluate_message() */
/**
* This prints out the messages after the delay, printing out the
* messages in a nice cute way. It still retains the order of the
* messages though. This can be forced to occur by a message
* occuring on the player object which requires something to
* be printed.
* @see evaluate_message()
* @see show_message()
*/
void print_messages() {
int i;
string message;
mixed messages;
remove_call_out( "print_messages" );
messages = _eemessages;
_eemessages = ({ });
for( i = 0; i < sizeof( messages ); i += 2 ) {
message = messages[ i ];
if( sizeof( messages[ i + 1 ] ) )
message = evaluate_message( ({ message, messages[ i + 1 ] }) );
show_message( message );
}
_where = 0;
} /* print_messages() */
/**
* This method will handle doing exciting things to messages and
* returning them as a usable format.
* @param message the message to evaluate
* @return the message in a printable (to the player) format
* @see evaluate_message()
*/
string convert_message( string message ) {
message = evaluate_message( reform_message( message, ({ }) ) );
_where = 0;
return message;
} /* convert_message() */
/**
* This method is called when an inform event is called.
* @param mess the message to print
* @param which the type of inform
* @parm thing the thing associated with the inform
*/
varargs void event_inform( object, mixed mess, string which, object thing ) {
string *on, inform_col;
int is_friend;
on = inform_types || ({ });
if( TO->query_property("inform repressed") || !sizeof( on ) )
return;
if( thing && creatorp(thing) && !thing->query_visible( TO ) )
return;
if( member_array( which, on ) == -1 )
return;
if( thing && member_array("friend", on ) != -1 &&
TO->query_friend( thing->query_name() ) )
is_friend = 1;
if( which == "friend" && !is_friend )
return;
if( which == "logon" && is_friend )
which = "friend";
if( _inform_colours[which] )
inform_col = colour_event( which, _inform_colours[which] );
else
inform_col = colour_event( which, _inform_colours["default"] );
if( functionp(mess) )
mess = evaluate( mess, TO );
TO->add_message( "[%^"+ inform_col +"%^"+mess+"%^RESET%^]\n", ({ }) );
} /* event_inform() */
/**
* This method is called when an object leaves or arrives in
* the room. It prints out
* the message, well adds it to the queue of printable messages.
* @param mess the message to print
* @param thing the thing which is leaving/arriving
* @param going if it is going
*/
protected void enter_exit_mess( string mess, object thing, int going ) {
int i;
string part, verb, *words;
mess = replace_string( mess, "$N", "$0$" );
words = explode( mess, " " );
for ( i = sizeof( words ) - 1; i > -1; i-- ) {
/*
* If $s ends a word, it represents verb conjugation.
* The test of the following letter is to check that it does end the word.
*/
if ( ( sscanf( words[ i ], "%s$s%s", verb, part ) == 2 ) &&
( ( part[ 0 ] < 97 ) || ( part[ 0 ] > 122 ) ) ) {
words[ i ] = "$V$0="+ pluralize( verb ) +","+ verb +"$V$"+ part;
}
/*
* If we have %<verb>%, it represents verb conjugation.
* This is unlikely to get confused with anything else...
*/
if ( sscanf( words[ i ], "%%%s%%%s", verb, part ) == 3 ) {
words[ i ] = "$V$0="+ pluralize( verb ) +","+ verb +"$V$"+ part;
}
}
if( going ) {
TO->add_message( implode( words, " " ) +"\n",
({ ({ "my_the_short:"+ file_name( thing ) }) }) );
} else {
TO->add_message( implode( words, " " ) +"\n",
({ ({ "my_a_short:"+ file_name( thing ) }) }) );
}
} /* enter_exit_mess() */
/**
* This method is called when an object enters the room.
* @param thing the thing entering
* @param mess the message to print on entering
*/
void event_enter( object thing, string mess, object ) {
if( !stringp( mess ) )
return;
thing->sneak_task(TO);
TO->perception_task(thing);
if( !thing->query_visible( TO ) )
return;
enter_exit_mess( mess, thing, 0 );
} /* event_enter() */
/**
* This method is printed when an object exits the room.
* @param thing the object exiting
* @param mess the message to print
* @param to where the object is going to
*/
void event_exit( object thing, string mess, object to ) {
::event_exit( thing, mess, to );
if( !stringp( mess ) )
return;
if( !thing->query_visible( TO ) )
return;
enter_exit_mess( mess, thing, 1 );
} /* event_exit() */
/** @ignore yes */
void event_death( object thing, object *, object killer,
string room_mess, string killer_mess ) {
if( TO == thing )
return;
if( TO == killer && stringp( killer_mess ) ) {
TO->add_message( replace( killer_mess,
"$D",(string)thing->the_short() ), ({ }) );
print_messages();
return;
}
if( stringp( room_mess ) ) {
if( objectp( killer ) ) {
TO->add_message( replace( room_mess, ({
"$D", (string)thing->the_short(),
"$K", (string)killer->the_short() }) ), ({ }) );
} else {
TO->add_message( replace( room_mess, "$D",
(string)thing->the_short() ), ({ }) );
}
print_messages();
}
} /* event_death() */
/**
* This method is called when the 'say' and 'tell_room' simul_efuns is used.
* @param caller the object doing the say
* @param str the message to print
* @param avoid the people to avoid in the say
*/
void event_say(object caller, string str, mixed avoid) {
if( pointerp(avoid) ) {
if( member_array( TO, avoid ) != -1 )
return;
} else if( avoid == TO )
return;
if( !silenced(caller) )
TO->add_message( str, ({ }) );
} /* event_say() */
void event_see( object caller, string words, object thing, mixed avoid ) {
if( !thing->query_visible( TO ) )
return;
event_say( caller, words, avoid );
} /* event_see() */
/**
* This method is called by the simul_efun 'write'.
* @param caller the calling object
* @param str the string to write
*/
void event_write( object caller, string str ) {
TO->add_message( str, ({ }) );
print_messages();
} /* event_write() */
/** @ignore yes */
void do_efun_write( string str ) { event_write( 0, str ); }
/**
* This method is called by the soul to print out the soul messages.
* @param ob the object doing the soul
* @param str the string to print
* @param avoid the people not to print the message to
*/
varargs void event_soul( object ob, string str, mixed avoid ) {
int id;
TO->add_property("doing_soul", 1 );
if( ob != TO ) {
if( silenced(ob) || ( sizeof(avoid) > 1 &&
check_earmuffs("multiple-soul") ) )
return ;
if( !ob->query_visible(TO) )
tell_object( ob, "Warning! "+TO->query_cap_name()+" cannot see "
"you and will not be able to respond.\n");
if( TO->query_property("afk") )
tell_object( ob, TO->query_cap_name()+" is currently %^ORANGE%^"
"AFK%^RESET%^"+( !TO->query_property("afk_string") ? "!" : " "
"because : "+TO->query_property("afk_string") )+"\n");
if( interactive(TO) && ( id = query_idle(TO) ) > TELL_WARN_TIME )
tell_object( ob, TO->query_cap_name()+" has been idle for "+
time_string(id)+".\n");
event_say( ob, colour_event("soul", "")+"$C$"+str+"%^RESET%^",
avoid );
} else
event_write( ob, str+"%^RESET%^");
TO->remove_property("doing_soul");
} /* event_soul() */
/**
* This method is called when someone does an emote.
* @param thing the object doing the emote
* @param mess the emote to print
*/
void event_emote( object thing, string mess ) {
if( thing == TO || silenced(thing) )
return;
TO->add_message( colour_event("emote", "%^CYAN%^")+mess+"%^RESET%^",
({ }) );
} /* event_emote() */
/**
* @ignore yes
* Use this on pain of death :)
*/
void add_say_history(string start, string mess) {
if( !pointerp(say_history) )
say_history = ({ });
say_history += ({ ({ CAP(start), mess, time() }) });
if( sizeof(say_history) > MAX_TELL_HIS )
say_history = say_history[1..];
} /* add_say_history() */
/**
* This method is called when someone says something.
* @param ob the object doing the say
* @param start the start message
* @param mess the message to say
* @param lang the language it is printed in
*/
void event_person_say( object ob, string start, string mess, string lang ) {
string *args;
if( ob == TO || silenced(ob) )
return;
if( lang != "common" )
start = start[0..<3] + " in " + CAP(lang) + ": ";
args = LANGUAGE_H->garble_say( lang, start, mess, TO, ob, SAY_TYPE );
start = args[ 0 ];
mess = args[ 1 ];
add_say_history( TO->convert_message(start), TO->convert_message(mess) );
TO->add_message("$I$5="+colour_event("say", "%^CYAN%^")+"$C$"+start+
mess+"%^RESET%^\n", ({ }) );
} /* event_person_say() */
/**
* @ignore yes
* Use this on pain of death :)
*/
void add_tell_history(string start, string mess) {
if( !pointerp(tell_history) )
tell_history = ({ });
tell_history += ({ ({ start, mess, time() }) });
if( sizeof(tell_history) > MAX_TELL_HIS )
tell_history = tell_history[1..];
} /* add_tell_history() */
/**
* This method is called when a person is told something.
* @param ob the object doing the tell
* @param start the start bit of the message
* @param mess the message itself
*/
void event_person_tell( object ob, string start, string mess ) {
string *args;
int id;
if( silenced(ob) )
return;
if( ( args = TO->query_property("ignoring") ) &&
member_array( ob->query_name(), args ) != -1 && !creatorp(ob) ) {
tell_object( ob, TO->query_cap_name()+" is ignoring you and "
"will not have heard what you said.\n");
return;
}
if( TO->query_property("afk") )
tell_object( ob, TO->query_cap_name()+" is currently %^ORANGE%^"
"AFK%^RESET%^"+( !TO->query_property("afk_string") ? "!" : " "
"because : "+TO->query_property("afk_string") )+"\n");
start = convert_message(start);
if( _busy && ( !pointerp(_busy) || member_array( ob, _busy ) == -1 ) ) {
tell_object( ob, TO->query_cap_name()+" is currently busy with "
"someone else, "+TO->HE+" has heard this message and will get "
"back to you shortly.\n");
start = "[BUSY] "+start;
}
add_tell_history( start, mess );
efun::tell_object( TO, fix_string( replace( colour_event("tell",
"%^YELLOW%^"), "%^", "%%^")+"%s%s%%^RESET%%^\n", cols, 5, CAP(start),
SPEECH_BASE->mangle_tell( mess, ob ) ) );
if( interactive(TO) && ( id = query_idle(TO) ) > TELL_WARN_TIME )
write( TO->query_cap_name()+" has been idle for "+
time_string(id)+".\n");
if( TO->query_property( PASSED_OUT ) )
write("Something tells you that "+TO->query_cap_name()+" will be "
"unable to reply to you just yet.\n" );
} /* event_person_tell() */
/**
* This method is called when the whisper even is generated.
* @param ob the object whispering
* @param start the start of the whisper message
* @param mess the message to print
* @param obs the objects to tell the message to
* @param lang the lanaguage the whisper is in
* @param me the object doing the whispering
*/
void event_whisper( object ob, string start, string mess,
object *obs, string lang, object me ) {
string blue, *args;
blue = "";
if( me == TO || silenced(ob) )
return;
if( lang != "common")
blue = " in "+lang;
args = LANGUAGE_H->garble_say( lang, start, mess, TO, ob, WHISPER_TYPE );
start = args[0];
mess = args[1];
if( member_array( TO, obs ) == -1 ) {
TO->add_message("$I$5="+colour_event("whisper", "%^CYAN%^")+"$C$"+
start+"to "+query_multiple_short( obs )+".%^RESET%^\n", ({ }) );
return;
}
if( sizeof( obs ) == 1 ) {
TO->add_message("$I$5="+colour_event("whisper", "%^CYAN%^")+"$C$"+
start+"to you"+blue+": "+mess+"%^RESET%^\n", ({ }) );
return;
}
TO->add_message("$I$5="+colour_event("whisper", "%^CYAN%^")+"$C$"+
start+"to "+query_multiple_short( obs )+blue+": "+mess+
"%^RESET%^\n", ({ }) );
} /* event_whisper() */
/**
* This method is generated when a shout is done by a player.
* @param thing the thing doing the shout
* @param start the start string to print
* @param mess the message to print
* @param lang the language the shout is in
* @param co_ord the co-ordinate of the shouter
* @param range the range of the shout
*/
void event_person_shout( object thing, string start, string mess, string lang,
int *co_ord, int range ) {
mixed args;
if( TO == TP || silenced(thing) || check_earmuffs("shout") || !ENV(TO) ||
ENV(TO)->query_property("shout zone") !=
ENV(TP)->query_property("shout zone") ||
sizeof( query_ignoring( ({ TP }) ) ) )
return;
if( lang != "common" )
start += " in "+lang;
args = LANGUAGE_H->garble_say( lang, start, mess, TO, thing, SHOUT_TYPE );
start = args[0];
mess = args[1];
if( ENV(TO) == ENV(TP) ) {
TO->add_message("$I$5="+colour_event("shout", "")+"$C$"+
start+": "+mess+"%^RESET%^\n", ({ }) );
return;
}
if( sizeof( co_ord ) != 3 )
return;
BROADCASTER->broadcast_event( ({ TO }), co_ord, start+": "+mess,
range, 1, 0 );
} /* event_person_shout() */
/**
* This event is generated when a newbie chat event is done.
* @param thing the thing generateing the newbie chat
* @param message the message the newbie said
*/
void event_newbie( object thing, string message ) {
if( TP == TO || check_earmuffs("newbie") ||
sizeof( query_ignoring( ({ TP }) ) ) )
return;
efun::tell_object( TO, fix_string("%%^MAGENTA%%^(newbie)%%^RESET%%^ %s\n",
cols, 5, message ) );
} /* event_newbie() */
/**
* This event is generated when a creator tell is done.
* @param ob the object generating the event
* @param start the start bit
* @param mess the message bit
* @param forced if it is forced to occur
*/
void event_creator_tell( object ob, string start, string mess, int forced ) {
if( TP == TO || ob == TO || ( ( sizeof(TO->query_ignoring( ({ ob }) ) ) ||
check_earmuffs("cre")) && !forced ) || !creatorp(TO) )
return;
efun::tell_object( TO, fix_string(replace(
colour_event("cre", "%^CYAN%^"), "%^", "%%^")+
"(cre) %s%s%%^RESET%%^\n", cols, 5, start, mess ) );
} /* event_creator_tell() */
/**
* This event is generated when a creator tell is done.
* @param ob the object generating the event
* @param start the start bit
* @param mess the message bit
* @param forced if it is forced to occur
*/
void event_chat( object ob, string caller, string verb, string text,
int emote, int force ) {
string hdr;
object person;
person = find_player( lower_case(caller) );
hdr = ( emote ? "("+verb+") "+caller+" " :
"("+( force ? "forced-" : "")+verb+") "+caller+": ");
if( !force ) {
if( TO->check_earmuffs("chat-channels") ||
TO->query_property("allchat_off") ||
TO->query_property(verb +"_off") )
return;
if( person )
if( sizeof( TO->query_ignoring( ({ person }) ) ) )
return;
}
efun::tell_object( ob, fix_string( replace( colour_event(
verb, "%^CYAN%^"), "%^", "%%^")+"%s%s%%^RESET%%^\n",
cols, strlen(verb)+2, hdr, text ) );
} /* event_chat() */
/**
* This event is generated when a intermud creator tell is done.
* @param ob the object generating the event
* @param mname the name of the mud
* @param pname the name of the player
* @param mess the message
* @param ig the ignore object
* @param emote if it is an emote
*/
void event_inter_creator_tell( object ob, string mname, string pname,
string mess, object ig, int emote ) {
if( !creatorp(TO) || check_earmuffs("inter-creator-tell") || TO == ig )
return;
efun::tell_object( TO, fix_string("%s@%s%s%s\n", cols,
strlen(mname) + strlen(pname) + 3, pname, mname, ( emote ? " ": ": "),
mess ) );
} /* event_inter_creator_tell() */
/**
* This event is generated when a creator tell is done.
* @param ob the object generating the event
* @param mname the name of the mud
* @param pname the name of the player
* @param mess the message
* @param ig the ignore object
* @param emote if it is an emote
*/
void event_intermud_tell( object ob, string start, string mess, string channel,
object ig, int emote ) {
if( TO->check_earmuffs("chat-channels") ||
TO->query_property("allchat_off") ||
TO->query_property(channel +"_off") )
return;
if( emote )
efun::tell_object( TO, fix_string( replace( colour_event(
channel, "%^CYAN%^"), "%^", "%%^")+"(%s): %s%s%%^RESET%%^\n",
cols, strlen(start)+strlen(channel)+3, channel, start, mess ) );
else
efun::tell_object( TO, fix_string( replace( colour_event(
channel, "%^CYAN%^"), "%^", "%%^")+"%s (%s): %s%%^RESET%%^\n",
cols, strlen(start)+strlen(channel)+3, start, channel, mess ) );
} /* event_intermud_tell() */
/**
* This method is called when an echo to is generated by the player.
* @param ob the object doing the echo to
* @param mess the message being printed
* @param me the person generating the echo to
*/
void event_player_echo_to(object ob, string mess, object me) {
if( lordp( (string)TO->query_name() ) )
TO->add_message("$0$ echos to you:\n",
({ ({ "my_the_short:"+file_name( me ) }) }) );
TO->add_message( colour_event("echo", "")+mess+"%^RESET%^", ({ }) );
} /* event_player_echo_to() */
/**
* This method is called when an emoteall is generated by a player.
* @param ob the object doing the emoteall
* @param mess the message being printed
*/
void event_player_emote_all( object ob, string mess ) {
if( ob == TO )
return;
if( lordp( (string)TO->query_name() ) )
TO->add_message("$0$ emotes to all:\n",
({ ({ "my_the_short:"+file_name( ob ) }) }) );
TO->add_message("$I$5=$C$"+replace_string( mess, "$N", "$0$"),
({ ({ "my_the_short:"+ file_name( ob ) }) }) );
} /* event_player_emote_all() */
/**
* This method is called when an echo is generated by a player.
* @param ob the object doing the echo
* @param mess the message being printed
*/
void event_player_echo( object ob, string mess ) {
if( ob == TO )
return;
if( lordp( (string)TO->query_name() ) )
TO->add_message("$0$ echos:\n",
({ ({ "my_the_short:"+file_name( ob ) }) }) );
TO->add_message( mess, ({ }) );
} /* event_player_echo() */
/**
* This method is generated internally by the driver when this player is
* snooping someone else.
* @param mess the snoop message
*/
void receive_snoop( string mess ) {
tell_object( TO, "] "+mess );
} /* receive_snoop() */
/**
* This is a call back generated by the driver internally to tell us about
* terminal types.
* @param type the terminal type returned
*/
void terminal_type( string type ) {
if( set_network_terminal_type(type) ) {
tell_object( TO, "Setting your network terminal type to "
"\""+type+"\".\n");
} else {
if( term_name == "network") {
if( !_last_term || _last_term != type ) {
_last_term = type;
// Keep going until they repeat twice.
// This is the end of the list.
printf("%c%c%c%c%c%c", IAC, SB, TELOPT_TTYPE,
TELQUAL_SEND, IAC, SE );
} else
tell_object( TO, "Unknown terminal type \""+type+"\".\n");
}
}
} /* terminal_type() */
/**
* This is a call back generated by the driver internally to tell us about
* the window size of the remote machine. This information in this is
* only used if the terminal is a network type.
* @param width the number of columns
* @param height the number of rows
*/
void window_size( int width, int height ) {
if( term_name == "network" ) {
if( width > 10 && width < 256 )
set_cols(width);
if( height > 5 && height < 256 )
set_rows(height);
tell_object( TO, "Your machine told our machine that your "
"terminal has "+height+" rows and "+width+" columns.\n");
}
} /* window_size() */