/* Do not remove the headers from this file! see /USAGE for more info. */ /* * Handler for simple string exits. For anything more complex than what is * provided here, look at M_COMPLEX_EXIT. With it, one is better able to * utilize the abilities of OBJ and the parser to really flesh out an exit * and make it spectacular. */ /* Major revamp done in Tigran's Great Exit Rewrite of 1999 */ #include <hooks.h> inherit "/std/classes/move"; private mapping exits = ([]); private string array hidden_exits = ({}); private string default_error; private string default_desc; private mixed default_exit_message; private mixed default_enter_message; private mixed default_check; private mixed default_desc; private nosave mixed base=(:file_name(this_object())[0..strsrch(file_name(this_object()),'/',-1)] :); varargs mixed call_hooks(string tag,mixed func,mixed start,array args...); mixed query_exit_check(string); mapping debug_exits(); string array query_hidden_exits(); /* * DEFAULTS AND ERRORS */ //:FUNCTION query_default_exit_message //Return the default exit message string query_default_exit_message() { return evaluate(default_exit_message); } //:FUNCTION query_default_enter_message //Return the default enter message string query_default_enter_message() { return evaluate(default_enter_message); } //:FUNCTION set_default_exit_message //Set the default exit message for all exits. //The argument can be a string, or function pointer void set_default_exit_message(mixed arg) { default_exit_message = arg; } //:FUNCTION set_default_enter_message //Set the default enter message for all exits //The argument can be a string or function pointer void set_default_enter_message(mixed arg) { default_enter_message = arg; } //:FUNCTION set_default_check //Set the default check for all exits //The argument can be a 0, 1, string, or function pointer returning one of //those void set_default_check(mixed arg) { default_check = arg; } //:FUNCTION query_default_check //Return the defaut check mixed query_default_check() { return evaluate(default_check); } //:FUNCTION set_default_error //Set the default error message (the message given when someone goes a //direction with no exit). This should be a string or a function ptr //returning a string. void set_default_error(mixed value) { default_error = value; } //:FUNCTION has_default_error //Return true if the room has a default exit error int has_default_error() { return !!default_error; } //:FUNCTION query_default_error //Returns the error default error message. string query_default_error() { if (has_default_error()) return evaluate(default_error); return( "It doesn't appear possible to go that way.\n"); } /* * EXIT DIRECTIONS */ //:FUNCTION query_exit_directions //Return all of the exit directions controlled by the exit object //The optional argument determines whether hidden exits are included in this //list. If nonnull, they are included varargs string array query_exit_directions(int show_hidden) { string array dirs = keys( exits ); object exit_obs=filter(all_inventory(this_object()), (: $1->is_exit() && $1->query_obvious_description() :) ); foreach(object exit_ob in exit_obs) { if(show_hidden|| !exit_ob->query_hidden() ) dirs+=({ exit_ob->query_direction() }); } if (show_hidden) return dirs; else return dirs - hidden_exits; } //:FUNCTION show_exits //Return a string giving the names of exits for the obvious exits line string show_exits() { string exit_str; string array exit_names; exit_names = query_exit_directions(0); exit_str = ((sizeof(exit_names)) ? implode(exit_names,", ") :"none"); #ifdef WIZARDS_SEE_HIDDEN_EXITS if ( wizardp(this_user()) && sizeof(query_hidden_exits()) ) { exit_str += ", *" + implode(query_hidden_exits(), ", *"); } #endif return exit_str; } /* * EXIT MESSAGES */ //:FUNCTION query_enter_msg //Return the enter messages of a given exit string query_enter_msg(string direction) { object which=present(direction); int i; if(which && which->is_exit()) return which->query_method_exit_messages("go"); i=sizeof(exits[direction]->enter_messages); if(!i) return query_default_exit_message(); return evaluate(exits[direction]->enter_messages[random(i)]); } //:FUNCTION set_enter_msg //Set the enter message of a given exit. //This message will be displayed in the destination room. //The message can be a fucntion pointer or a string. //If multiple messages are passed, a random one will be selected when invoked void set_enter_msg(string direction, mixed array message...) { object which=present(direction); if(which && which->is_exit()) { which->set_method_enter_messages("go",message...); return; } exits[direction]->enter_messages = message; } //:FUNCTION add_enter_msg //Add an additional enter message to a given exit. //The message can be a function pointer or a string //If multiple messages are passed, a random one will be selected when invoked void add_enter_msg(string direction, mixed array message...) { object which=present(direction); if(which && which->is_exit()) { which->add_method_enter_messages("go",message...); return; } exits[direction]->enter_messages+=message; } //:FUNCTION remove_enter_msg //Remove an enter emssage from a given exit. void remove_enter_msg(string direction, mixed array message...) { object which=present(direction); if(which && which->is_exit()) { which->remove_method_enter_messages("go",message...); return; } exits[direction]->enter_messages-=message; } //:FUNCTION list_enter_msgs //Return all possible enter messages for a given exit mixed array list_enter_msgs(string direction) { object which=present(direction); if(which && which->is_exit()) return which->list_method_enter_messages("go"); return exits[direction]->enter_messages; } //:FUNCTION query_exit_msg //Return the exit messages of a given exit string query_exit_msg(string direction) { int i=sizeof(exits[direction]->exit_messages); object which=present(direction); if(which && which->is_exit()) return which->query_method_exit_messages("go"); if(i) return evaluate(exits[direction]->exit_messages[random(i)]); return query_default_exit_message(); } //:FUNCTION set_exit_msg //Set the exit message of a given exit. //This message will be displayed in the room the body is leaving void set_exit_msg(string direction, mixed array message...) { object which=present(direction); if(which && which->is_exit()) { which->set_method_exit_messages("go",message...); return; } exits[direction]->exit_messages = message; } //:FUNCTION add_exit_msg //Add an additional exit message to a given exit. //The message can be a function pointer or a string void add_exit_msg(string direction, mixed array message...) { object which=present(direction); if(which && which->is_exit()) { which->add_method_exit_messages("go",message...); return; } exits[direction]->exit_messages+=message; } //:FUNCTION remove_exit_msg //Remove an exit emssage from a given exit. void remove_exit_msg(string direction, mixed array message...) { object which=present(direction); if(which && which->is_exit()) { which->remove_method_exit_messages("go",message...); return; } exits[direction]->exit_messages-=message; } //:FUNCTION list_exit_msgs //List all of the possible exit messages for an exit mixed array list_exit_msgs(string direction) { object which=present(direction); if(which && which->is_exit()) return which->list_method_exit_messages("go"); return exits[direction]->exit_messages; } /* * EXIT DESTINATIONS */ /* eval_dest() returns the full pathname of the destination of the exit, or an * error. */ private string eval_dest(mixed arg) { mixed tmp; if(!arg||arg=="") return 0; tmp=(class move_data)exits[arg]->destination; tmp = evaluate(tmp); if (!stringp(tmp)) return 0; if (tmp[0] == '#') return tmp; return absolute_path(tmp,evaluate(base)); } //:FUNCTION query_exit_destination //Return the destination path of the given exit. varargs string query_exit_destination(string arg) { object which=present(arg); if(which && which->is_exit()) return which->query_method_destination("go"); return eval_dest(arg); } /* * EXIT DESCRIPTIONS */ //:FUNCTION query_exit_description //Returns the description of the given exit. string query_exit_description(string direction) { object which = present(direction); if(which && which->is_exit()) return which->query_method_description("go"); if(exits[direction]) return evaluate(exits[direction]->description); return 0; } //:FUNCTION set_exit_description //Set the description of an exit. void set_exit_description(string direction, mixed description) { object which=present(direction); if(which && which->is_exit()) { which->set_long(description); return; } exits[direction]->description = description; } /* * EXIT CHECKS */ //:FUNCTION query_exit_check //Return whether or not the exit can be passed through mixed query_exit_check(string direction) { if(member_array(direction,keys(exits))==-1) return; return exits[direction]->checks; } //:FUNCTION set_exit_check //Function setting the check funciton for the exit void set_exit_check(string direction, function f) { object which=present(direction); if(which && which->is_exit()) { which->set_method_check("go",f); return; } exits[direction]->checks = f; } /* * EXIT ADDITION AND REMOVAL */ //:FUNCTION delete_exit //Remove a single exit from the room. The direction should be an exit //name. void delete_exit(mixed direction) { object which=present(direction); if(which && which->is_exit()) destruct(which); map_delete(exits, direction); } //:FUNCTION add_exit //Add an exit to the object with a destination. . //Add the value should be a filename or a more complex structure as //described in the exits doc. varargs void add_exit(mixed direction, mixed destination) { #ifdef USE_COMPLEX_EXITS object exit_ob=new(COMPLEX_EXIT_OBJ); exit_ob->add_method(direction,destination); return; #else class move_data new_exit=new(class move_data); new_exit->description=default_desc; new_exit->enter_messages=({}); new_exit->exit_messages=({}); new_exit->destination=destination; if (stringp(destination) && strlen(destination) == 0) error("Bogus exit passed into add_exit"); if (stringp(destination) && destination[0] == '#') new_exit->checks = destination[1..]; else new_exit->checks = 1; exits[direction] = new_exit; #endif } //:FUNCTION set_exits //Sets the exit mapping of a room. The keys should be exit names, the values //should be either filenames or more complex structures described in the //exits doc void set_exits( mapping new_exits ) { mixed key; if ( mapp(new_exits) ) foreach(string direction,mixed destination in new_exits) add_exit(direction,destination); } /* * HIDDEN EXITS */ //:FUNCTION set_hidden_exits //This is the list of exits to NOT be shown to the mortals in the room. //If "all" is any of the arguements in exits_list all exits for the object //will be marked as hidden regardless to the rest of the arguments. void set_hidden_exits( string array exits_list ... ) { if(member_array("all",exits_list)>-1) hidden_exits=keys(exits); else hidden_exits = exits_list; } //:FUNCTION add_hidden_exit //Make a given exit direction a hidden exit. See set_hidden_exits void add_hidden_exit( string array exits_list ... ) { if( sizeof( exits_list ) == 1 && exits_list[0] == "all" ) hidden_exits = query_exit_directions(1); else hidden_exits += exits_list; } //:FUNCTION remove_hidden_exit //Make a given exit direction no longer a hidden exit. See set_hidden_exits void remove_hidden_exit( string array exits_list ... ) { if( sizeof( exits_list ) == 1 && exits_list[0] == "all" ) hidden_exits = 0; else hidden_exits -= exits_list; } //:FUNCTION query_hidden_exits //Return all of the hidden exits controlled by the exit object string array query_hidden_exits() { string exit_obs=filter(all_inventory(this_object()), (: $1->is_exit() && $1->query_hidden() :) ); return hidden_exits + exit_obs->query_direction(); } /* * VERB RULES */ /* Called by the go verb * The return value determines whether or not the exit can be used. A * string returned is an error, 0 is simple failure (parser makes the * error, and 1 is success */ mixed can_go_str(string arg) { mixed ret=evaluate(query_exit_check(arg)); if(!stringp(ret) && ret!=1 && is_normal_direction(arg)) return query_default_error(); return ret; } void do_go_str(string dir) { class move_data exit=new(class move_data); if (call_hooks("block_" + dir, HOOK_LOR, 0, dir) || call_hooks("block_all", HOOK_LOR, 0, dir)) return; exit->destination=query_exit_destination(dir); exit->exit_messages=query_exit_msg(dir); exit->enter_messages=query_enter_msg(dir); exit->exit_dir=dir; if (!this_body()->query_driving_vehicle()) { if(!exit->exit_messages) exit->exit_messages=this_body()->query_msg("leave"); if(!exit->enter_messages) exit->enter_messages=this_body()->query_msg("enter"); /* Normal movement, which should be the scope of this module should * always send to the method "in" */ exit->who = this_body(); this_body()->move_to(exit); } else { exit->who = environment(this_body()); environment(this_body())->move_to(exit); } } /* * DEBUGGING */ //:FUNCTION debug_exits //Return all of the exit info contained within the object mapping debug_exits() { return copy(exits); } //:FUNCTION query_base //Return the evaluated string which is the directory the object is in. string query_base() { return evaluate(base); } //:FUNCTION set_base //Set the base directory to be used by the exits of the environment. void set_base(mixed what) { base=what; } mapping lpscript_attributes() { return (["exits" : ({ LPSCRIPT_MAPPING, "setup", "set_exits" }), "hidden_exits" : ({ LPSCRIPT_LIST, "setup", "set_hidden_exits" }), "default_exit_message" : ({ LPSCRIPT_STRING, "setup", "set_default_exit_message" }), "default_enter_message" : ({ LPSCRIPT_STRING, "setup", "set_default_enter_message" }), "wrong_exit" : ({ LPSCRIPT_STRING, "setup", "set_default_error"}), "enter_msg" : ({ LPSCRIPT_TWO, (: ({ "setup", "set_enter_msg(\""+$1+"\",\""+$2[0]+"\")" }) :) }), "exit_msg" : ({ LPSCRIPT_TWO, (: ({ "setup", "set_exit_msg(\""+$1+"\",\""+$2[0]+"\")" }) :) }), "exit_description" : ({ LPSCRIPT_TWO, (: ({ "setup", "set_exit_description(\""+$1+"\",\""+$2[0]+"\")" }) :) }), ]); }