/* /lib/door.c * from the Dead Souls LPC Library * the standard door, window, rock object * created by Descartes of Borg 950410 * with many thanks to Balack@Phoenix and Deathblade@ZorkMUD for their ideas * Version: @(#) door.c 1.8@(#) * Last modified: 97/01/01 */ #include <lib.h> #include "include/door.h" inherit LIB_DAEMON; inherit LIB_SEAL; inherit LIB_KNOCK; inherit LIB_SCRATCH; private mapping Sides; private static int Hidden = 1; private static int Opacity = 100; private static int Perforated = 0; int GetOpacity(){ return Opacity; } int SetOpacity(int x){ Opacity = x; return Opacity; } int GetPerforated(){ return Perforated; } int SetPerforated(int x){ Perforated = x; return Perforated; } int CanPeer(){ if(!GetClosed() || !Opacity) return 1; return 0; } int SetHiddenDoor(int i){ if(i) Hidden = 1; else Hidden = 0; return Hidden; } int GetHiddenDoor(){ return Hidden; } string *GetSides(){ return keys(Sides); } /* *************** /lib/door.c driver applies *************** */ static void create(){ daemon::create(); parse_init(); SetNoClean(0); SetLockStrength(50); Sides = ([]); } /* *************** /lib/door.c modals ************** */ /* method: CanLock() * args: * object who - the person doing the locking * object key - the key being used for the locking * * returns: 1 on success, 0 or failure string on failure * * Tests to see if a certain player can lock the door with a given * key */ mixed CanLock(object who, string foo){ object room; if( !(room = environment(who)) ) return 0; foreach(string side, mapping val in Sides){ if( member_array(room, val["Rooms"]) != -1 ){ if( !GetLockable(side) ) return 0; else return seal::CanLock(who); } } return 0; } /* method: CanUnlock() * args: * object who - the person doing the unlocking * object key - the key being used for the unlocking * * returns: 1 on success, 0 or failure string on failure * * Tests to see if a certain player can unlock the door with a given * key */ mixed CanUnlock(object who){ object room; if( !(room = environment(who)) ) return 0; foreach(string side, mapping val in Sides){ if( member_array(room, val["Rooms"]) != -1 ){ if( !GetLockable(side) ) return 0; else return seal::CanUnlock(who); } } return 0; } /* *************** /lib/door.c events ************** */ /* eventClose() * object who - who is closing it * * returns 1,0, or an error string based on parser conditions * * Check to be certain the door is not already closed before calling so * you may issue the appropriate message */ varargs mixed eventClose(object who){ object room,whom; string tmp; if(!GetClosed()){ SetClosed(1); if(who) room = environment(who); else room = environment(this_player()); if(!who) whom = this_player(); else whom = who; foreach(string side, mapping val in Sides){ if( member_array(environment(whom), val["Rooms"]) != -1 ) tmp = side; if(who) filter(val["Rooms"], (: $1 && ($1 != $(room)):))->eventPrint(capitalize(GetShort(side)) + " closes."); else (val["Rooms"])->eventPrint(capitalize(GetShort(side)) + " closes."); } if(who){ who->eventPrint("You close " + GetShort(tmp) + "."); room->eventPrint((string)who->GetName() + " closes " + GetShort(tmp) + ".", who); } } return 1; } /* eventLock() * object who - the agent responsible for locking it * object key - the key being used to lock it * returns 1, 0 or a string according to parser conditions * * Check to make sure the door is closed and unlocked before calling this * Also check to see that the door is lockable from this side * object by is required here */ varargs mixed eventLock(object who, mixed key, mixed foo){ object room; room = environment(who); foreach(string side, mapping val in Sides){ if( member_array(room, val["Rooms"]) != -1 ){ string tmp; tmp = GetShort(side); if( !(sizeof(key->GetId() & GetKeys(side))) ){ who->eventPrint("You fail to lock " + tmp + " with " + (string)key->GetShort()+"."); room->eventPrint((string)who->GetName() + " attempts to " "lock " + tmp + " with " + (string)key->GetShort() + ", but fails.",who); return 1; } SetLocked(1); who->eventPrint("You lock " + tmp + " with " + (string)key->GetShort()+"."); room->eventPrint((string)who->GetName() + " locks " + tmp + " with " + (string)key->GetShort() + ".", who); return 1; } } return 0; } /* eventOpen() * object by - The room from which the door is being open * object agent - The living thing responsible for it opening * * returns 1, 0, or an error string depending on parser circumstances * * Used for actually opening the door * Before calling this, you should check if the door is locked and * check if it is already open so you can issue the appropriate messages */ varargs int eventOpen(object who, object tool){ object room, whom; string tmp; if(GetClosed()){ SetClosed(0); if(who) room = environment(who); else room = environment(this_player()); if(!who) whom = this_player(); else whom = who; foreach(string side, mapping val in Sides){ if( member_array(environment(whom), val["Rooms"]) != -1 ) tmp = side; if(who) filter(val["Rooms"], (: $1 && ($1 != $(room)) :))->eventPrint(capitalize(GetShort(side)) + " opens."); else (val["Rooms"])->eventPrint(capitalize(GetShort(side)) + " opens."); } if(who){ who->eventPrint("You open " + GetShort(tmp) + "."); room->eventPrint((string)who->GetName() + " opens " + GetShort(tmp) + ".", who); } } return 1; } /* eventRegisterSide() * string side - directional exit identifying which side of the door this room * exits in * * returns 1 on success, 0 on failure * * never should be called manually * this is called by SetDoor() in exits.c to tell the door there is a room * which is observing it */ int eventRegisterSide(string side){ string array id = GetId(side); Sides[side]["Rooms"] = distinct_array(Sides[side]["Rooms"] + ({ previous_object() })); previous_object()->AddItem(id, (: GetLong($(side)) :)); foreach(object ob in all_inventory(previous_object())){ if( !ob->isDummy() ){ continue; } if( sizeof(id & ob->GetId()) ){ if(!ob->GetDoor()) ob->SetDoor(file_name(this_object()), side); } } return 1; } /* method: eventUnlock() * args: * object who - the person unlocking the door * object key - the key being used to unlock it * * returns: 1 on success, 0 or failure string on failure * * Check to make sure the door is closed and locked before calling this * Also check to see that the door is lockable from this side * object by is required here */ mixed eventUnlock(object who, object key){ object room; string *key_id = key->GetId(); room = environment(who); foreach(string side, mapping val in Sides){ if( member_array(room, val["Rooms"]) != -1 ){ string tmp; tmp = GetShort(side); if(!sizeof((key_id & (GetKeys(side) || ({}))))){ who->eventPrint("You fail to unlock " + tmp + " with " + (string)key->GetShort()+"."); room->eventPrint((string)who->GetName() + " attempts to " "unlock " + tmp + " with " + (string)key->GetShort() + ", but fails.",who); return 1; } SetLocked(0); who->eventPrint("You unlock " + tmp + "."); room->eventPrint((string)who->GetName() + " unlocks " + tmp + " with " + (string)key->GetShort() + ".", who); return 1; } } return 0; } /* ************** /lib/door.c data functions ************** */ void SetSide(string side, mapping mp){ mapping new_side = ([ "Rooms" : ({}) ]); if( stringp(mp["id"]) ) new_side["Ids"] = ({ mp["id"] }); else new_side["Ids"] = mp["id"]; new_side["Short"] = mp["short"]; new_side["Long"] = mp["long"]; if( stringp(mp["keys"]) ) new_side["Keys"] = ({ mp["keys"] }); else new_side["Keys"] = mp["keys"]; new_side["Lockable"] = mp["lockable"]; Sides[side] = new_side; } mapping GetSide(string side){ mapping RetMap = ([]); if(!sizeof(Sides[side])) return ([]); RetMap["id"] = Sides[side]["Ids"]; RetMap["short"] = Sides[side]["Short"]; RetMap["long"] = Sides[side]["Long"]; RetMap["keys"] = Sides[side]["Keys"]; RetMap["lockable"] = Sides[side]["Lockable"]; return copy(RetMap); } int SetLockable(string side, int x){ if( !Sides[side] ) Sides[side] = ([ "Rooms" : ({}) ]); return Sides[side]["Lockable"] = x; } int GetLockable(string side){ return Sides[side]["Lockable"]; } varargs string *SetId(string side, mixed *args...){ if( !Sides[side] ) Sides[side] = ([ "Rooms" : ({}) ]); Sides[side]["Ids"] = ({}); foreach(mixed val in args){ if( stringp(val) ) Sides[side]["Ids"] += ({ val }); else Sides[side]["Ids"] += val; } return Sides[side]["Ids"]; } string *GetId(string side){ if(!Sides[side]) return ({}); return Sides[side]["Ids"]; } mixed SetShort(string side, mixed short){ if( !Sides[side] ) Sides[side] = ([ "Rooms" : ({}) ]); return Sides[side]["Short"] = short; } varargs string GetShort(string side){ if( !side){ /* let's hack a side */ object room; side = previous_object()->GetDoorSide(); if( !this_player() ) room = previous_object(); else room = environment(this_player()); foreach(string s, mapping val in Sides){ if(!side) side = s; if( member_array(room, val["Rooms"]) != -1 ) break; } } if( stringp(Sides[side]["Short"]) ) return Sides[side]["Short"]; else return (string)evaluate(Sides[side]["Short"], side); } string GetDefiniteShort(){ string tmp = GetShort(); return add_article(tmp, 1); } mixed SetLong(string side, mixed long){ if( !Sides[side] ) Sides[side] = ([ "Rooms" : ({}) ]); return Sides[side]["Long"] = long; } string GetLong(string side){ string tmp; if( GetClosed() ) tmp = "It is closed."; else tmp = "It is open."; if( stringp(Sides[side]["Long"] ) ) return Sides[side]["Long"] + "\n" + tmp; else return (string)evaluate(Sides[side]["Long"], side); } varargs string *SetKeys(string side, mixed *args...){ if( !Sides[side] ) Sides[side] = ([ "Rooms" : ({}) ]); Sides[side]["Keys"] = ({}); foreach(mixed val in args){ if( stringp(val) ) Sides[side]["Keys"] += ({ val }); else Sides[side]["Keys"] += val; } return Sides[side]["Keys"]; } string *GetKeys(string side){ return Sides[side]["Keys"]; } object *GetRooms(string side){ return Sides[side]["Rooms"]; } int get_closed(){ return GetClosed(); } varargs mixed eventKnock(object who, mixed what){ object room,whom; string tmp; if(GetClosed()){ if(who) room = environment(who); else room = environment(this_player()); if(!who) whom = this_player(); else whom = who; foreach(string side, mixed val in Sides){ if( member_array(environment(whom), val["Rooms"]) != -1 ) tmp = side; if(who) filter(val["Rooms"], (: $1 && ($1 != $(room)):))->eventPrint( "There is a knock at the "+remove_article(GetShort(side)) + "."); else (val["Rooms"])->eventPrint( "There is a knock at the "+remove_article(GetShort(side)) + "."); } if(who){ who->eventPrint("You knock on the " + remove_article(GetShort(tmp)) + "."); room->eventPrint((string)who->GetName() + " knocks on the " + remove_article(GetShort(tmp)) + ".", who); } } else write("It isn't closed!"); return 1; } varargs mixed eventScratch(object who, mixed what){ object room,whom; string tmp; if(GetClosed()){ if(who) room = environment(who); else room = environment(this_player()); if(!who) whom = this_player(); else whom = who; foreach(string side, mixed val in Sides){ if( member_array(environment(whom), val["Rooms"]) != -1 ) tmp = side; if(who) filter(val["Rooms"], (: $1 && ($1 != $(room)):))->eventPrint( "There is a scratch at the "+remove_article(GetShort(side)) + "."); else (val["Rooms"])->eventPrint( "There is a scratch at the "+remove_article(GetShort(side)) + "."); } if(who){ who->eventPrint("You scratch on the " + remove_article(GetShort(tmp)) + "."); room->eventPrint((string)who->GetName() + " scratches on the " + remove_article(GetShort(tmp)) + ".", who); } } else write("It isn't closed!"); return 1; } void init(){ }