Added public files
Roughly added all public files. Probably missed some, though.
diff --git a/obj/doormaster.c b/obj/doormaster.c
new file mode 100644
index 0000000..46e9364
--- /dev/null
+++ b/obj/doormaster.c
@@ -0,0 +1,469 @@
+#include <properties.h>
+#include <defines.h>
+#include <moving.h>
+#include <language.h>
+
+#define NEED_PROTOTYPES
+#include <doorroom.h>
+
+inherit "/std/thing";
+
+#pragma strong_types
+
+private mapping door_status;
+private int id_zaehler;
+// Format: "filename1:filename2":status
+
+int oeffnen (string str);
+
+mapping QueryAllDoors() {return door_status;}
+
+int QueryDoorStatus(string dest) {
+ string source,dkey;
+ object env;
+
+ if (!dest) return 0;
+ if (!objectp(env=previous_object())) return 0;
+ source=object_name(env);
+ dkey=(source<dest)?(source+":"+dest):(dest+":"+source);
+ return door_status[dkey];
+}
+
+void SetDoorStatus(string dest, int x) {
+ string source,dkey;
+ object env;
+
+ if (!dest) return;
+ if (!objectp(env=previous_object())) return;
+ source=object_name(env);
+ dkey=(source<dest)?(source+":"+dest):(dest+":"+source);
+ door_status[dkey]=x;
+}
+
+protected void create() {
+ door_status=([]);
+ id_zaehler=0;
+ if (IS_CLONE(this_object())) remove();
+}
+
+varargs int remove(int silent) {return 0;}
+
+varargs int NewDoor(string|string* cmds, string dest, string|string* ids,
+ mapping|<int|string|string*>* props)
+{
+ object env;
+ string source,dkey,sec_id;
+ mixed *info2,zw;
+ mapping info;
+ int i;
+
+ if (!objectp(env=previous_object())) return 0;
+ if (!cmds || !dest) return 0;
+ if (!ids) ids=({"tuer"});
+ if (stringp(cmds)) cmds=({cmds});
+ if (stringp(ids)) ids=({ids});
+ if (!pointerp(cmds) || !pointerp(ids)) return 0;
+ if (dest[0..0]!="/") dest="/"+dest;
+ id_zaehler++;
+ sec_id=sprintf("secure_id:door%d",id_zaehler);
+
+ info=([D_DEST : dest,
+ D_CMDS : cmds,
+ D_IDS : ({ sec_id }) + ids,
+ D_FLAGS : (DOOR_CLOSED|DOOR_RESET_CL),
+ D_LONG : "Eine Tuer.\n",
+ D_SHORT : "Eine %se Tuer. ",
+ D_NAME : "Tuer",
+ D_GENDER : FEMALE]);
+ source=object_name(env);
+ dkey=(source<dest)?(source+":"+dest):(dest+":"+source);
+
+ if (pointerp(props)) {
+ for (i=0;i<sizeof(props)-1;i+=2)
+ if (intp(props[i]) && props[i]>=D_MINPROPS && props[i]<=D_MAXPROPS)
+ info[props[i]]=props[i+1];
+ }
+ else if(mappingp(props)){
+ info += props;
+ }
+
+ if (!door_status[dkey]) {
+ // Nur initialisieren, wenn Tuer noch nicht existiert.
+ if (info[D_FLAGS] & DOOR_OPEN)
+ door_status[dkey]=D_STATUS_OPEN;
+ if (info[D_FLAGS] & DOOR_CLOSED)
+ door_status[dkey]=
+ ((info[D_FLAGS] & DOOR_NEEDKEY) ? D_STATUS_LOCKED : D_STATUS_CLOSED);
+ }
+ info2=env->QueryProp(P_DOOR_INFOS);
+ if (!pointerp(info2))
+ info2=({info});
+ else
+ info2+=({info});
+ env->SetProp(P_DOOR_INFOS,info2);
+
+ if(mappingp(info[D_LONG]) && pointerp(zw=m_indices(info[D_LONG])) &&
+ sizeof(zw) && intp(zw[0]))
+ env->AddSpecialDetail(ids,"special_detail_doors");
+ else if(info[D_LONG] && info[D_LONG]!="")
+ env->AddDetail(ids,info[D_LONG]);
+
+ return 1;
+}
+
+void init_doors () {
+ object env;
+ mixed *info;
+ string source,dest,dkey;
+ int i;
+
+ if (!objectp(env=previous_object())) return;
+ info=env->QueryProp(P_DOOR_INFOS);
+ if (!pointerp(info)) return;
+
+ source=object_name(env);
+ for (i=sizeof(info)-1;i>=0;i--) {
+ if (!mappingp(info[i])) continue;
+ dest=info[i][D_DEST];
+ dkey=(source<dest)?(source+":"+dest):(dest+":"+source);
+ env->set_doors(info[i][D_CMDS],(door_status[dkey]>0));
+ }
+}
+
+string look_doors () {
+ object env;
+ mixed *info, ds;
+ string source,dkey,dest,res;
+ int i, st;
+
+ if (!objectp(env=previous_object())) return "";
+ info=env->QueryProp(P_DOOR_INFOS);
+ if (!pointerp(info)) return "";
+ init_doors(); // Aktueller Zustand soll auch bei den Exits angezeigt werden
+
+ source=object_name(env);res="";
+ for (i=sizeof(info)-1;i>=0;i--) {
+ if (!mappingp(info[i])) continue;
+ dest=info[i][D_DEST];
+ dkey=(source<dest)?(source+":"+dest):(dest+":"+source);
+ if (stringp(info[i][D_SHORT])) {
+ res+=sprintf(info[i][D_SHORT],
+ ((door_status[dkey]>=D_STATUS_OPEN)?"geoeffnet":
+ ((door_status[dkey]!=D_STATUS_CLOSED)?"ab":"")+"geschlossen"));
+ if (sizeof(res) && res[<1]!='\n')
+ res+=" ";
+ }
+ else if(mappingp(ds=info[i][D_SHORT])){
+ st=door_status[dkey];
+ if((st==D_STATUS_LOCKED) && !ds[D_STATUS_LOCKED])
+ st=D_STATUS_CLOSED;
+ if(stringp(ds[st])){
+ res += ds[st];
+ if(sizeof(ds[st]) && res[<1]!='\n')res+=" ";
+ }
+ }
+ }
+ if (res && res!="")
+ return break_string(res,78,0,1);
+ return res;
+}
+
+static void door_message(object room, string dname, int dgender, string msg) {
+ object ob;
+
+ // printf("%O,%O,%O,%O\n",room,dname,dgender,msg);
+ if (!room || !dname || !msg) return;
+ ob=this_object();
+ ob->SetProp(P_NAME,dname);
+ ob->SetProp(P_GENDER,dgender);
+ ob->SetProp(P_ARTICLE,1);
+ tell_room(room,capitalize(ob->name(WER))+msg+"\n");
+}
+
+static void door_message_other(string source, string dest, string msg) {
+ mixed info;
+ object env;
+ int i;
+
+ // printf("%O %O %O\n",source,dest,msg);
+ if (!source || !dest || !msg) return;
+ if (!objectp(env=find_object(dest))) return;
+ if (!pointerp(info=env->QueryProp(P_DOOR_INFOS))) return;
+ for (i=sizeof(info)-1;i>=0;i--) {
+ if (!mappingp(info[i])) continue;
+ if (info[i][D_DEST]!=source) continue; // Andere Tuer zu diesem Raum
+ door_message(env,info[i][D_NAME],info[i][D_GENDER],msg);
+ }
+}
+
+void reset_doors () {
+ object env;
+ mixed *info;
+ string source,dest,dkey,msg;
+ int i,j;
+
+ if (!objectp(env=previous_object())) return;
+ info=env->QueryProp(P_DOOR_INFOS);
+ if (!pointerp(info)) return;
+
+ source=object_name(env);
+ for (i=sizeof(info)-1;i>=0;i--) {
+ if (!mappingp(info[i])) continue;
+ dest=info[i][D_DEST];
+ dkey=(source<dest)?(source+":"+dest):(dest+":"+source);
+
+// if (door_status[dkey]>-2 && door_status[dkey]<2) {
+// if (door_status[dkey]>0)
+// door_status[dkey]=2;
+// else
+// door_status[dkey]=-2;
+// continue; // nur jeder 2. Reset wird ausgefuehrt.
+// }
+
+ if (info[i][D_FLAGS] & DOOR_RESET_CL) {
+ // Tuer muss bei Reset geschlossen werden
+ if (door_status[dkey] >= D_STATUS_OPEN) {
+ if(!msg=info[i][D_RESET_MSG])msg=" schliesst sich.";
+ door_message(env,info[i][D_NAME],info[i][D_GENDER],msg);
+ door_message_other(source,dest,msg);
+ }
+ if (door_status[dkey]!=D_STATUS_LOCKED)
+ door_status[dkey]=
+ ((info[i][D_FLAGS] & DOOR_NEEDKEY) ? D_STATUS_LOCKED : D_STATUS_CLOSED);
+ }
+ if (info[i][D_FLAGS] & DOOR_RESET_OP) {
+ // Tuer muss bei Reset geoeffnet werden
+ if (door_status[dkey] < D_STATUS_OPEN) {
+ if(!msg=info[i][D_RESET_MSG])msg=" oeffnet sich.";
+ door_message(env,info[i][D_NAME],info[i][D_GENDER],msg);
+ door_message_other(source,dest,msg);
+ }
+ door_status[dkey]=D_STATUS_OPEN;
+ }
+ }
+ init_doors();
+}
+
+static varargs int exec_func2(string dest, mixed func) {
+ if (!stringp(dest) || !stringp(func)) return 1;
+ call_other(dest,func);
+ return 1;
+}
+
+varargs int go_door (string str) {
+ object env,pl,ob;
+ mixed *info;
+ string source,dest,dkey;
+ int i;
+
+ if (!str) return 0;
+ if (!objectp(env=previous_object())) return 0;
+ if (!objectp(pl=this_player())) return 0;
+ info=env->QueryProp(P_DOOR_INFOS);
+ if (!pointerp(info)) return 0;
+
+ source=object_name(env);
+ ob=this_object();
+ ob->SetProp(P_ARTICLE,1);
+ for (i=sizeof(info)-1;i>=0;i--) {
+ if (!mappingp(info[i])) continue;
+ if (member(info[i][D_CMDS],str)<0) continue;
+ dest=info[i][D_DEST];
+ dkey=(source<dest)?(source+":"+dest):(dest+":"+source);
+ ob->SetProp(P_NAME,info[i][D_NAME]);
+ ob->SetProp(P_GENDER,info[i][D_GENDER]);
+ notify_fail(capitalize(ob->name(WER,1))+" ist geschlossen.\n");
+ if((door_status[dkey]<=0) &&
+ !info[i][D_OPEN_WITH_MOVE]) continue; // Tuer geschlossen
+ if(door_status[dkey]<=0){
+ // In diesem Fall versuchen, die Tuer zu oeffnen.
+ oeffnen(info[i][D_IDS][0]);
+ }
+ notify_fail(capitalize(ob->name(WER,1))+" ist geschlossen.\n");
+ if (door_status[dkey]<=0) continue; // Tuer immer noch zu.
+ if (stringp(info[i][D_TESTFUNC]))
+ if (call_other(env,info[i][D_TESTFUNC]))
+ return 1; // Durchgang von der Tuer nicht erlaubt.
+ if (stringp(info[i][D_FUNC]))
+ call_other(env,info[i][D_FUNC]);
+ if (stringp(info[i][D_MSGS])) {
+ if (pl->move(dest,M_GO,info[i][D_MSGS])>0)
+ return exec_func2(dest,info[i][D_FUNC2]);
+ else
+ return 1;
+ }
+ if (pointerp(info[i][D_MSGS]) && sizeof(info[i][D_MSGS])>=3) {
+ if (pl->move(dest,M_GO,info[i][D_MSGS][0],
+ info[i][D_MSGS][1],info[i][D_MSGS][2]))
+ return exec_func2(dest,info[i][D_FUNC2]);
+ else
+ return 1;
+ }
+ if (pl->move(dest,M_GO,"nach "+capitalize(str)))
+ return exec_func2(dest,info[i][D_FUNC2]);
+ return 1;
+ }
+ return 0;
+}
+
+int oeffnen (string str) {
+ object env,schl,ob;
+ mixed *info,s2;
+ string source,dkey,dest,s1;
+ int i;
+
+ notify_fail("WAS willst Du oeffnen?\n");
+ if (!str || !this_player()) return 0;
+ notify_fail("Das kannst Du nicht oeffnen.\n");
+ str=lower_case(str);
+ if (sscanf(str,"%s mit %s",s1,s2)!=2)
+ {s1=str;s2=0;}
+ if (s2) {
+ if (!(schl=present(lower_case(s2),this_player()))) {
+ notify_fail("So einen Schluessel hast Du nicht.\n");
+ return 0;
+ } else {
+ s2=schl->QueryDoorKey();
+ if (stringp(s2)) s2=({s2});
+ }
+ }
+
+ if (!objectp(env=previous_object())) return 0;
+ info=env->QueryProp(P_DOOR_INFOS);
+ if (!pointerp(info)) return 0;
+
+ source=object_name(env);
+ ob=this_object();
+ ob->SetProp(P_ARTICLE,1);
+ for (i=sizeof(info)-1;i>=0;i--) {
+ if (!mappingp(info[i])) continue;
+ if (member(info[i][D_IDS],s1)<0) continue; // Falsche Tuer
+ ob->SetProp(P_NAME,info[i][D_NAME]);
+ ob->SetProp(P_GENDER,info[i][D_GENDER]);
+ dest=info[i][D_DEST];
+ dkey=(source<dest)?(source+":"+dest):(dest+":"+source);
+ notify_fail(capitalize(ob->name(WER,1))+" ist doch schon geoeffnet!\n");
+ if (door_status[dkey]>0)
+ continue; // Eine andere Tuer koennte gemeint sein.
+ if ((info[i][D_FLAGS] & DOOR_NEEDKEY)
+ && door_status[dkey] == D_STATUS_LOCKED) { // abgeschlossen
+ notify_fail("Du brauchst einen Schluessel, um "+ob->name(WEN,1)+" zu oeffnen.\n");
+ if (!schl) continue; // Eine andere Tuer koennte gemeint sein.
+ notify_fail(capitalize(schl->name(WER))+" passt nicht!\n");
+ if (!pointerp(s2)) continue;
+ if (member(s2,dkey)<0) continue; // Koennte an einer anderen passen.
+ }
+ door_status[dkey]=1;
+ init_doors();
+ write("Du oeffnest "+ob->name(WEN)+".\n");
+ say(capitalize(ob->name(WER))+" wird von "+this_player()->name(WEM)+
+ " geoeffnet.\n");
+ door_message_other(source,dest," wird von der anderen Seite geoeffnet.");
+ return 1;
+ }
+ return 0;
+}
+
+int schliessen (string str) {
+ object env,schl,ob;
+ mixed *info,s2;
+ string source,dkey,dest,s1;
+ int i,abg;
+
+ notify_fail("WAS willst Du schliessen?\n");
+ if (!str || !this_player()) return 0;
+ notify_fail("Das kannst Du nicht schliessen.\n");
+ str=lower_case(str);
+ if (sscanf(str,"%s mit %s",s1,s2)!=2)
+ {s1=str;s2=0;}
+ if (s2) {
+ if (!(schl=present(lower_case(s2),this_player()))) {
+ notify_fail("So einen Schluessel hast Du nicht.\n");
+ return 0;
+ } else {
+ s2=schl->QueryDoorKey();
+ if (stringp(s2)) s2=({s2});
+ }
+ }
+
+ if (!objectp(env=previous_object())) return 0;
+ info=env->QueryProp(P_DOOR_INFOS);
+ if (!pointerp(info)) return 0;
+
+ source=object_name(env);
+ ob=this_object();
+ ob->SetProp(P_ARTICLE,1);
+ abg=0;
+ for (i=sizeof(info)-1;i>=0;i--) {
+ if (!mappingp(info[i])) continue;
+ if (member(info[i][D_IDS],s1)<0) continue; // Falsche Tuer
+ ob->SetProp(P_NAME,info[i][D_NAME]);
+ ob->SetProp(P_GENDER,info[i][D_GENDER]);
+ dest=info[i][D_DEST];
+ dkey=(source<dest)?(source+":"+dest):(dest+":"+source);
+ if (schl) {
+ notify_fail(capitalize(ob->name(WER,1))+" ist doch schon abgeschlossen!\n");
+ if (door_status[dkey]<=0
+ && door_status[dkey] == D_STATUS_LOCKED)
+ continue; // Eine andere Tuer koennte gemeint sein.
+ if (info[i][D_FLAGS] & DOOR_CLOSEKEY) { // Schluessel noetig?
+ notify_fail(capitalize(schl->name(WER))+" passt nicht!\n");
+ if (!pointerp(s2)) continue;
+ if (member(s2,dkey)<0) continue; // Koennte an einer anderen passen.
+ door_status[dkey]=D_STATUS_LOCKED;
+ abg=1; // Tuer wird richtig abgeschlossen
+ }
+ else {
+ // ohne Schluessel abschliessbar
+ door_status[dkey]=
+ ((info[i][D_FLAGS] & DOOR_NEEDKEY) ? D_STATUS_LOCKED : D_STATUS_CLOSED);
+ }
+ }
+ else {
+ notify_fail(capitalize(ob->name(WER,1))+" ist doch schon geschlossen!\n");
+ if (door_status[dkey] < D_STATUS_OPEN)
+ continue; // Eine andere Tuer koennte gemeint sein.
+ if ((info[i][D_FLAGS] & DOOR_NEEDKEY) &&
+ !(info[i][D_FLAGS] & DOOR_CLOSEKEY))
+ door_status[dkey]=D_STATUS_LOCKED; // Abschliessbar, aber dazu schluessel unnoetig
+ else
+ door_status[dkey]=D_STATUS_CLOSED;
+ }
+ init_doors();
+ write("Du schliesst "+ob->name(WEN)+
+ (abg?" ab":"")+".\n");
+ say(capitalize(ob->name(WER))+" wird von "+this_player()->name(WEM)+
+ (abg?" ab":" ")+"geschlossen.\n");
+ door_message_other(source,dest," wird von der anderen Seite "+
+ (abg?"ab":"")+"geschlossen.");
+ return 1;
+ }
+ return 0;
+}
+string special_detail_doors(string key){
+ object env;
+ mixed *info;
+ mapping dl;
+ int i, st;
+ string source, dest, dkey;
+
+ if(!objectp(env=previous_object()))return 0;
+ if(!pointerp(info=env->QueryProp(P_DOOR_INFOS)))return 0;
+ source=object_name(env);
+
+ for(i=sizeof(info)-1;i>=0;i--){
+ if(!mappingp(info[i]))continue;
+ if(member(info[i][D_IDS],key)<0)continue;
+ if(stringp(info[i][D_LONG]))return info[i][D_LONG];
+ if(!mappingp(info[i][D_LONG]))continue;
+ dl=info[i][D_LONG];
+ dest=info[i][D_DEST];
+ dkey=(source<dest)?(source+":"+dest):(dest+":"+source);
+ st=door_status[dkey];
+ if((st==D_STATUS_LOCKED) && !dl[D_STATUS_LOCKED])
+ st=D_STATUS_CLOSED; /* Falls keine eigene Beschreibung
+ * fuer abgeschlossene Tuer vorhanden */
+ return dl[st];
+ }
+ return 0;
+}