// std/room/door.c // This object is unusual -- it affects the inventory of two objects (rooms). // Currently, that is handled by having two nearly identical objects. // The creation and destruction require careful handling. // When open, it must be open on both sides. // However, may be locked from only one side. (maybe???) // Isthar@Aurora 16-Jun 1994, added stuff for invis players // 1995 Jul 20 Laggard removed defines now in room.h. // 1995 Jul 27 Laggard extensive revision to stop forcing room loads. #include "parse_command.h" #include "room.h" #include "door.h" // debugging logs #define DOOR_BUG_LOG "room_doors.bug" #define ROOM_BUG_LOG "room_bugs.log" // protected variables: private string my_long, my_short, *my_adjectives, *my_plurals, *my_names, key_prop; private mixed *unlock_func, *open_func, *picked; // file_names instead of objects allows reload when rooms clean_up. private string room_one; // the creating room_file_name private string exit_one; // the creating exit_name private string room_two; // the other room_file_name (set when valid) private string exit_two; // the other exit_name (set by other room) private string exit_type = "door"; private int locked, diff, open; int do_unlock(object *obs); void create() { my_adjectives = ({ }); my_plurals = ({ "doors" }); my_names = ({ "door" }); key_prop = "generic_key"; my_long = ""; } void set_key_prop(string p) { key_prop = p; } string query_key_prop() { return key_prop; } void set_difficulty(int i) { diff = i; } int query_difficulty() { return diff; } void set_other_id(string s) { exit_two = s; } string query_other_id() { return exit_two; } void set_open_func(mixed *bing) { open_func = bing; } mixed *query_open_func() { return open_func; } void set_unlock_func(mixed *bing) { unlock_func = bing; } mixed *query_unlock_func() { return unlock_func; } void set_locked(int i) { locked = i; } int query_locked() { return locked; } void set_open(int i) { open = i; } int query_open() { return open; } void init() { this_player()->add_command("open", this_object(), "%D"); this_player()->add_command("close", this_object(), "%D"); this_player()->add_command("lock", this_object(), "%D %p %I"); this_player()->add_command("unlock", this_object(), "%D %p %I"); } string short() { return my_short; } string pretty_short() { return short(); } string query_plural() { return pluralize(my_short); } string pretty_plural() { return query_plural(); } string long() { string ret; if (open) ret = "The " + my_short + " is open.\n"; else { ret = "The " + my_short + " is closed.\n"; if (locked) ret += "The " + my_short + " is locked.\n"; } return my_long+ret; } void set_long(string s) { my_long = s; } string query_long() { return my_long; } string query_short() { return my_short; } void set_short(string str) { string *bits; bits = explode(str, " "); my_adjectives += bits[0..sizeof(bits)-2]; my_names += ({ bits[sizeof(bits)-1] }); my_short = str; } int drop() { return 1; } int get() { return 1; } // returns the values needed for setup {Laggard} mixed query_door_values() { return ({ open, locked, key_prop, diff, exit_one, }); } // called immediately after door is cloned void setup_door( string directive, object this_side, mixed other_side, mixed *values, string kind ) { string *bits, s; exit_one = directive; room_one = file_name(this_side); if ( stringp(other_side) ) { room_two = other_side; } else if ( objectp(other_side) ) { room_two = file_name(other_side); } else { log_file( ROOM_BUG_LOG, ctime(time()) +" invalid door setup: " + other_side +", [" + directive +"] " + file_name(this_side) +"\n"); } if ( kind ) { exit_type = kind; } if (directive[0..5] == "enter ") my_short = directive[6..1000] +" " + exit_type; else my_short = directive + " " + exit_type; my_names = ({ }); my_plurals = ({ }); bits = explode(my_short, " "); my_names += ({ (s=bits[sizeof(bits)-1]) }); my_plurals += ({ pluralize(s) }); my_adjectives += bits; open = values[D_OPEN]; locked = values[D_LOCKED]; diff = values[D_DIFFICULTY]; key_prop = values[D_KEY]; exit_two = values[D_OTHER]; picked = ({ }); } void add_alias(string nam) { string *bits, s; bits = explode(nam, " "); my_names += ({ (s=bits[sizeof(bits)-1]) }); my_plurals += ({ pluralize(s) }); my_adjectives += bits; } int do_close() { if (!open) return 0; if (open_func) { if (!call_other(open_func[0], open_func[1], 0)) return 0; } /* Ok... now close it... */ room_one->modify_exit(exit_one, ({ "open", 0 })); if (exit_two) { room_two->modify_exit(exit_two, ({ "open", 0 })); room_two->tell_door(exit_two, "The %D closed.\n"); } return 1; } int do_open() { if (open) return 0; if (locked) if (!do_unlock(all_inventory(this_player()))) return 0; if (open_func) { if (!call_other(open_func[0], open_func[1], 1)) return 0; } /* Ok... now open it... */ room_one->modify_exit(exit_one, ({ "open", 1 })); if (exit_two) { room_two->modify_exit(exit_two, ({ "open", 1 })); room_two->tell_door(exit_two, "The %D opened.\n"); } return 1; } int test_key(object ob) { return (int)ob->query_property(key_prop); } int do_lock(object *obs) { int ret; if (open) return 0; if (locked) return 0; if (unlock_func) { if (!(ret = call_other(unlock_func[0], unlock_func[1], 0))) return 0; } if (ret != 2) if (!sizeof(obs = filter_array(obs, "test_key", this_object()))) return 0; /* Ok... now lock it... */ room_one->modify_exit(exit_one, ({ "locked", 1 })); if (exit_two) { room_two->modify_exit(exit_two, ({ "locked", 1 })); room_two->tell_door(exit_two, "The %D clicked.\n"); } this_player()->add_succeeded(obs[0]); return 1; } int do_unlock(object *obs) { int ret; notify_fail("You cannot unlock the " + exit_type + ".\n"); if (!locked) return 0; if (unlock_func) { if (!(ret = call_other(unlock_func[0], unlock_func[1], 1))) return 0; } if (ret != 2) if (!sizeof(obs = filter_array(obs, "test_key", this_object()))) return 0; /* Ok... now unlock it... */ room_one->modify_exit(exit_one, ({ "locked", 0 })); if (exit_two) { room_two->modify_exit(exit_two, ({ "locked", 0 })); room_two->tell_door(exit_two, "The %D clicked.\n"); } this_player()->add_succeeded(obs[0]); return 1; } int query_key() { if (key_prop != "generic_key") return 1; return 0; } void pick_lock(mixed pc) { picked += ({ ({ pc, 1 }) }); set_locked(1); } void pick_unlock(mixed pc) { picked += ({ ({ pc, 0 }) }); set_locked(0); } string *parse_command_id_list() { return my_names; } string *parse_command_plural_id_list() { return my_plurals; } string *parse_command_adjectiv_id_list() { return my_adjectives; } object query_parse_id(mixed *arr) { string *bits; mixed stuff; int i; if (arr[P_THING] == 0) { bits = explode(arr[P_STR], " "); return this_object(); } if (arr[P_THING] < 0) { /* specific object case */ arr[P_THING]++; if (arr[P_THING] != 0) return 0; arr[P_THING] = -10321; return this_object(); } arr[P_THING]--; /* lots of objects case */ if (arr[P_THING] != 0) return this_object(); arr[P_THING] = -10786; return this_object(); } void dest_me() { destruct(this_object()); return ; } void dwep() { destruct(this_object()); return ; } int move() { return 1; } int moveing_close(object who) { string oshrt; if (!exit_two) { // no door on other side, or move_player failed. #ifdef DOOR_BUG_LOG if ( exit_type != "portal" ) { log_file( DOOR_BUG_LOG, ctime(time()) +" return door missing in " + room_two + " [" + exit_one + "] " + room_one +"\n"); } #endif return 0; } if (!room_two->call_door(exit_two, "do_close")) return 0; oshrt = (string)room_two->call_door(exit_two, "query_short"); tell_object(who, "You close the "+oshrt+".\n"); // Isthar@Aurora 16-Jun 1994, keep hidden invis people // Laggard@RotD not that hidden! if (who->query_invis() == 0) { tell_room(find_object(room_two), who->query_cap_name()+" closed the "+oshrt+".\n", ({who})); } else { tell_room(find_object(room_two), "The "+oshrt+" closed.\n", ({who})); } return 1; } int moveing_open(object who) { if (!do_open()) return 0; tell_object(who, "You open the "+my_short+".\n"); // Isthar@Aurora 16-Jun 1994, keep hidden invis people if (who->query_invis() == 0) { tell_room(find_object(room_one), who->query_cap_name()+" opened the "+my_short+".\n",({who})); } else { tell_room(find_object(room_one), "The "+my_short+" opened.\n", ({who})); } return 1; } int moveing_lock(object who) { string oshrt; if (!exit_two) { // no door on other side, or move_player failed. #ifdef DOOR_BUG_LOG if ( exit_type != "portal" ) { log_file( DOOR_BUG_LOG, ctime(time()) +" return door missing in " + room_two + " [" + exit_one + "] " + room_one +"\n"); } #endif return 0; } if (!room_two->call_door(exit_two, "do_lock", all_inventory(who))) return 0; oshrt = (string)room_two->call_door(exit_two, "query_short"); tell_object(who, "You lock the "+oshrt+".\n"); // Isthar@Aurora 16-Jun 1994, keep hidden invis people // Laggard@RotD not that hidden! if (who->query_invis() == 0) { tell_room(find_object(room_two), who->query_cap_name()+" locked the "+oshrt+".\n", ({who})); } else { tell_room(find_object(room_two), "The "+oshrt+" clicked.\n", ({who})); } return 1; } int moveing_unlock(object who) { if (!do_unlock(all_inventory(who))) return 0; tell_object(who, "You unlock the "+my_short+".\n"); // Isthar@Aurora 16-Jun 1994, keep hidden invis people if (who->query_invis() == 0) { tell_room(find_object(room_one), who->query_cap_name()+" unlocked the "+my_short+".\n",({who})); } else { tell_room(find_object(room_one), "The "+my_short+" clicked.\n", ({who})); } return 1; } void tell_door(string str) { // Laggard@RotD removed the names from the messages, // since this_player() isn't in the room anyway.... tell_room(find_object(room_one), replace(str, "%D", my_short), ({ this_player() })); }