/* Do not remove the headers from this file! see /USAGE for more info. */ // a room.c // Rust@ZorkMUD, Jan 12, 1994 // Nevyn@GUE 1-14-94 // Cleave@ZorkMUD 2-25-94 Added long(), long default. // Beek@ZorkMud 4-6-94 Added the way cool exit code. Look at the // lfun docs. // Rust wrote in_room stuff to make looking in rooms more interesting // Beek & Rust have both done a bit of work on this since.... // August 24 - Beek added light // Satan@ArcadiaF 10-29-95 Added the OBVIOUS_EXITS_BOTTOM, casue I don't like // the way the exits look on the top, and Beek didn't want to fix it. // Satan@ArcadiaF 10-30-95 Added set_hidden_exits(). This makes a list that // of exits that are hidden from all in the room. // Wizards can see DARK_EXITS as they are denoted with a *name format. // 951113, Deathblade: removed some obsolete vars; made them all private #include <setbit.h> #include <move.h> #include <hooks.h> inherit CONTAINER; inherit M_ITEMS; inherit M_GETTABLE; inherit M_EXIT; inherit __DIR__ "room/roomdesc"; inherit __DIR__ "room/state"; private nosave string array area_names = ({ }); private string listen, smell; private nosave mixed chat_msg; private nosave int chat_period = 15; private nosave int tag; //:FUNCTION stat_me //Returns some debugging info about the object. Shows the container info, //as well as the short and exits. string stat_me() { return sprintf("Room: %s [ %s ]\n\n", short(), implode(query_exit_directions(1), ", ")) + container::stat_me(); } //:FUNCTION set_brief //Set the name of the room seen at the top of the description and in brief mode void set_brief(string str) { set_proper_name(str); } //:FUNCTION can_hold_water //Return 1 if the object can hold water. /* by default, rooms can hold water */ int can_hold_water() { return 1; } void create(array args...) { container::create(); // cloned rooms will already have this stuff happen... We need this // because setup() is the way people configure mudlib objects. // Almost always, except in the case of rooms, game objects are clones. //### Small problem here; some rooms are clones, and this bails for them. //### We really need a better way to test if we should call setup(). //### //### Virtual grids, for example, usually depend on cloned rooms working //### properly. //### //### BTW, contrary to the above, it appears this is *NOT* already done for cloned rooms #if 0 if( !clonep() ) { #endif // initialize the mudlib (default) stuff, then the area coder's mudlib_setup(); this_object()->internal_setup(); setup(args...); #if 0 } #endif } void mudlib_setup() { ::mudlib_setup(); set_light(DEFAULT_LIGHT_LEVEL); /* First add the relation 'in'. */ add_relation("in",1000000); /* Make it the default relation for all rooms */ set_default_relation("in"); add_id_no_plural("here"); add_id("environment"); set_gettable( -1 ); set_flag( ATTACHED ); } //:FUNCTION set_area //Used by m_wander to prevent monsters from wandering to far. //Can either be a string, or an array of strings void set_area(string array names...) { area_names = names; } //:FUNCTION query_area //Find out what 'areas' the room belongs to. See set_area. string array query_area() { return area_names; } string query_name() { return "the ground"; } string get_brief() { return short(); } void possible_light_change(int old_light, int new_light) { if (old_light && !new_light) { tell_from_inside(this_object(), "The room goes dark.\n"); } else if (!old_light && new_light) { tell_from_inside(this_object(), "You can see again.\n"); } } void set_light(int x) { int old = query_light(); ::set_light(x); possible_light_change(old, query_light()); } void adjust_light(int x) { int old = query_light(); ::adjust_light(x); possible_light_change(old, query_light()); } mixed direct_get_obj(object ob) { if( this_object() == environment( this_body())) return "#A surreal idea."; return ::direct_get_obj(ob); } mapping lpscript_attributes() { return ([ "area" : ({ LPSCRIPT_STRING, "setup", "set_area" }), "brief" : ({ LPSCRIPT_STRING, "setup", "set_brief" }), "exits" : ({ LPSCRIPT_MAPPING, "setup", "set_exits" }), "state" : ({ LPSCRIPT_TWO, (: ({ "setup", "set_state_description(\"" + $1 + "\", \"" + $2[0] + "\")" }) :) }), "item" : ({ LPSCRIPT_SPECIAL, (: ({ "setup", "add_item(\"" + $1[0] + "\", \"" + implode($1[1..], " ") + "\")" }) :) }) ]); } /* tweak the base long description to add the state stuff */ string get_base_long() { string base = ::get_base_long(); array fmt; int i; fmt = reg_assoc(base, ({ "\\$[A-Za-z_]*" }), ({ 1 }))[0]; for (i = 1; i < sizeof(fmt); i++) { string tmp; if (tmp = query_state_desc(fmt[i][1..])) fmt[i] = tmp; } base = implode(fmt, ""); if (base[<1] != '\n') base += "\n"; return base; } string long() { #ifdef OBVIOUS_EXITS_BOTTOM string objtally = show_objects(); if( sizeof(objtally)) objtally = "You also see:\n" + objtally; return sprintf("%sObvious Exits: %%^ROOM_EXIT%%^%s%%^RESET%%^\n%s", (dont_show_long() ? "" : simple_long()), show_exits(), objtally); #else return sprintf("%s%s", (dont_show_long() ? "" : simple_long()), show_objects()); #endif } //:FUNCTION long_without_object //This is used by things like furniture, so the furniture can use the //same long as the room, but not see itself in the description. string long_without_object(object o) { #ifdef OBVIOUS_EXITS_BOTTOM return sprintf("%sObvious Exits: %%^ROOM_EXIT%%^%s%%^RESET%%^\n%s", simple_long(), show_exits(), show_objects(o)); #else return sprintf("%s%s", simple_long(), show_objects(o)); #endif } void set_listen(string str) { listen = str; } string query_listen() { return listen; } void set_smell(string str) { smell = str; } string query_smell() { return smell; } void do_listen() { if(listen) write(listen); else write( "You hear nothing unusual.\n" ); } void do_pray() { write( "Nothing special happens.\n" ); } void do_smell() { if(smell) write(smell); else write( "You smell nothing unusual.\n" ); } int listeners() { object array inv = all_inventory(this_object()); return sizeof(filter(inv, (: $1->query_link() :) ) ); } void check_anybody_here() { if(listeners()) { tag = call_out("room_chat", chat_period, chat_msg); } else { remove_call_out(tag); tag = 0; } } void room_chat() { if(stringp(chat_msg)) tell_from_outside(this_object(), chat_msg + "\n"); else if(arrayp(chat_msg)) tell_from_outside(this_object(), choice(chat_msg) + "\n"); else if(functionp(chat_msg)) tell_from_outside(this_object(), evaluate(chat_msg) + "\n"); check_anybody_here(); } void departure(object who) { call_out("check_anybody_here",0); } void arrival(object who) { if(!listeners()) tag = call_out("room_chat", chat_period, chat_msg); } void set_room_chat(mixed chat, int interval) { chat_msg = chat; chat_period = interval; add_hook("object_arrived", (: arrival :) ); add_hook("object_left", (: departure :) ); if(tag) { remove_call_out(tag); tag = 0; } call_out("check_anybody_here",0); }