Added public files
Roughly added all public files. Probably missed some, though.
diff --git a/d/seher/haeuser/moebel/access_rights.c b/d/seher/haeuser/moebel/access_rights.c
new file mode 100644
index 0000000..255cd58
--- /dev/null
+++ b/d/seher/haeuser/moebel/access_rights.c
@@ -0,0 +1,5 @@
+int access_rights(string user, string file) {
+ if(user == "swift" && file!="autoloadertruhe.c")
+ return 1; // Swift hat auf die Moebel Zugriff.
+ return 0;
+}
diff --git a/d/seher/haeuser/moebel/autoloadertruhe.c b/d/seher/haeuser/moebel/autoloadertruhe.c
new file mode 100644
index 0000000..e22ce17
--- /dev/null
+++ b/d/seher/haeuser/moebel/autoloadertruhe.c
@@ -0,0 +1,1015 @@
+//--------------------------------------------------------------------------------
+// Name des Objects: Aufbewahrungtruhe fuer Autoload-Objekte
+//
+// Magier: Zesstra
+//--------------------------------------------------------------------------------
+#pragma strong_types,rtt_checks
+
+#include "schrankladen.h"
+inherit LADEN("swift_std_container");
+
+//#include <ansi.h>
+#include <class.h>
+#include <wizlevels.h>
+#include "/d/seher/haeuser/haus.h"
+
+#define IDS 0
+#define NAME 1
+#define ALDATA 2
+
+#define LOG(x,y) log_file(x,sprintf("%s [%s, %O, %O]: %s\n",dtime(time()),\
+ (uuid?uuid:" "),PL,object_name(ME),y))
+#define STORELOG(x) LOG("zesstra/ALTRUHE_STORE.log",x)
+#define PICKLOG(x) LOG("zesstra/ALTRUHE_PICK.log",x)
+
+#define ITEMLOG(x) log_file("zesstra/ALTRUHE_ITEMS.log",\
+ sprintf("%s [%O]: %s\n",dtime(time()),\
+ this_interactive()||PL,x))
+
+#define ERRLOG(x) LOG("zesstra/ALTRUHE.ERR",x)
+
+#undef BS
+#define BS(x) break_string(x,78)
+
+#define VERSION_OBJ "5"
+
+#ifdef MAINTAINER
+#undef MAINTAINER
+#endif
+#define MAINTAINER ({"zesstra"})
+
+// Savefile der Blueprint
+#ifdef SAVEFILE
+#undef SAVEFILE
+#endif
+#define SAVEFILE __FILE__[..<3]
+
+#define DEBUG(x) if (funcall(symbol_function('find_player),MAINTAINER[0]))\
+ tell_object(funcall(symbol_function('find_player),MAINTAINER[0]),\
+ "ALTruhe: "+x+"\n")
+
+#define ACCESS (my_secure_level() >= ARCH_LVL)
+
+// Diese 4 sind fuer die Blueprint (Master aller Truhen)
+mapping whitelist=([]); // erlaubte Autoloader, alle anderen nicht erlaubt.
+mapping blacklist=([]); // bereits explizit durch EM+ abgelehnte Autoloader
+mapping vorschlaege=m_allocate(1,2); // vorschlaege der Spieler
+mapping data=([]); // hier speichert die BP alle Daten der Truhen
+ // WICHTIG: dieses Mapping wird in /secure/memory
+ // abgelegt und muss auch beim Neuladen ggf. von dort
+ // wieder abgeholt werden. Ausserdem teilen sich alle
+ // Truhen eines Spielers und diese Blueprint die Mappings
+ // darin, damit Aenderungen sofort in allen Truhen und dem
+ // Master bekannt sind.
+
+/* die einzelnen Truhen speichern in autoloader. Format:
+ 3 Werte pro Key, Keys sind die Namen der Blueprints der Objekte:
+ ([<blueprint>: <P_IDS>; <ob->name()>; <P_AUTOLOADOBJ> ])
+ */
+nosave mapping autoloader=m_allocate(1,3);
+nosave string uuid; // UUID des Eigentuemers
+nosave object ob_in_bewegung; // uebler Hack eigentlich. :-(
+
+void NotifyInsert(object ob, object oldenv);
+static mapping QueryData();
+static mapping SetData(mixed data);
+protected void save_me();
+protected void check_content();
+
+nomask private int my_secure_level(); //Args.
+
+protected void create() {
+
+ // Ja, es is Absicht, dass das create der BP erst spaeter abgebrochen wird!
+ swift_std_container::create();
+
+ seteuid(getuid(ME));
+
+ // falls dies die BP ist:
+ // 1. das Savefile zu laden.
+ // 2. versuchen, die truhendaten von /secure/memory zu holen, damit nach dem
+ // Neuladen der Master und die Client immer nach _dieselben_ Mappings
+ // haben.
+ if (!clonep(ME))
+ {
+ // Savefile restaurieren (auch wenn data im Memory ist, muss das sein,
+ // damit die anderen Variablen wieder eingelesen sind).
+ restore_object(SAVEFILE);
+ // jetzt Daten aus Memory holen, sofern verfuegbar
+ mapping tmp = "/secure/memory"->Load("truhendaten");
+ if (mappingp(tmp))
+ {
+ // Daten aus Savefile durch die vom Memory ersetzen
+ data = tmp;
+ }
+ else
+ {
+ // Keine Daten in Memory. Jetzt in jedem Fall den Pointer auf das Mapping data in
+ // /secure/memory ablegen
+ if ("/secure/memory"->Save("truhendaten",data) != 1)
+ {
+ raise_error("Could not save memory to /secure/memory.");
+ }
+ }
+ }
+ else
+ {
+ // brauchen Clones nicht.
+ set_next_reset(-1);
+ data=0; // brauchen Clones nicht.
+ }
+
+ SetProp(P_SHORT, "Eine kleine, magische Holztruhe");
+ SetProp("cnt_version_obj", VERSION_OBJ);
+ SetProp(P_NAME, "Holztruhe");
+ SetProp(P_GENDER, FEMALE);
+ SetProp(P_NAME_ADJ,({"klein", "magisch"}));
+ SetProp(P_LONG, BS(
+ "Die kleine Holztruhe ist aus stabilem Eichenholz gefertigt. Eigentlich "
+ "saehe sie recht unscheinbar aus, waeren da nicht die vielen kunstvollen "
+ "Runen an den Seiten und auf dem Deckel.")
+ +"@@cnt_status@@");
+
+ AddId(({"autoloadertruhe", "holztruhe", "truhe"}));
+
+ // den Rest vom Create braucht die BP nicht.
+ if (!clonep(ME)) return;
+
+ SetProp(P_LOG_FILE,"zesstra/ALTRUHE.rep");
+
+ SetProp(P_WEIGHT, 3000); // Gewicht 5 Kg
+ // die drei hier sind in diesme Fall eigentlich voellig ohne Bedeutung
+ SetProp(P_MAX_WEIGHT, 1000000); // Es passen fuer 1000 kg Sachen rein.
+ SetProp(P_WEIGHT_PERCENT, 100);
+ SetProp(P_MAX_OBJECTS, 100); // sind eh immer 0 echte Objekte drin.
+
+ SetProp(P_VALUE, 0); // Kein materieller Wert. Ist eh nicht verkaufbar.
+ SetProp(P_NOBUY, 1); // Wird im Laden zerstoert, falls er verkauft wird.
+ SetProp(P_NOGET, "Das geht nicht. "+Name(WER,1)+" haftet wie magisch am Boden.\n");
+ SetProp(P_MATERIAL, ([MAT_OAK:49, MAT_MISC_MAGIC:50, MAT_JOFIUM: 1]) );
+ SetProp(P_INFO, BS("In diese stabile Truhe kannst Du bestimmte "
+ "Autoload-Objekte hineinlegen und sie lagern, wenn Du sie gerade "
+ "nicht brauchst. (Mit 'deponiere <was>' kannst Du etwas in der "
+ "Truhe zur Aufbewahrung deponieren, mit 'entnehme <was> oder "
+ "'nimm <was> aus truhe' kannst Du einen Gegenstand wieder "
+ "herausnehmen.)"));
+
+ // Prop fuer rebootfeste Moebel
+ // Der endgueltige Wert (UUID des Spielers) wird per SetBesitzer() gesetzt,
+ // sobald die Truhe das erste Mal in ein Seherhaus bewegt wurde.
+ SetProp(H_FURNITURE, 1);
+
+ AD(({"platz","groesse"}),
+ BS("Die Truhe ist recht klein, aber merkwuerdigerweise "
+ "scheint sie viel mehr an Gegenstaenden aufnehmen zu koennen, als "
+ "es von ihrer Groesse her scheint."));
+ AD(({"gegenstand","gegenstaende"}),
+ BS("Die Truhe scheint zwar vielen Gegenstaenden Platz zu bieten, aber "
+ "dafuer nimmt sie nicht jeden Gegenstand auf."));
+ AD(({"holz","eichenholz"}),
+ BS("Das Eichenholz ist sehr stabil. Es ist ganz glatt geschliffen und "
+ "traegt viele kunstvolle Runen in sich."));
+ AD(({"seiten","seite"}),
+ BS("Die Truhe hat 4 Seiten, die allesamt mit Runen verziert sind."));
+ AD(({"boden"}),
+ BS("Der Boden der Truhe traegt keinerlei Runen."));
+ AD(({"deckel"}),
+ BS("Auch der Deckel der Truhe ist mit Runen verziert."));
+ AD(({"runen","rune"}),
+ BS("Die Runen bedecken alle 4 Seiten und den Deckel der Truhe. Man "
+ "hat sie zweifellos in muehsamer Arbeit aus dem harten Holz "
+ "geschnitzt. Anschliessend wurden sie offenbar mit einem "
+ "Metall gefuellt. Du verstehst zwar ueberhaupt nicht, was "
+ "die Runen bedeuten, aber sie sind bestimmt magisch, denn wann immer "
+ "Du den Deckel oeffnest oder schliesst oder Gegenstaende hineinlegst "
+ "oder herausnimmst, leuchten die Runen hell auf."));
+ AD(({"metall"}),
+ BS("Was das wohl fuer ein Metall sein mag? Zweifellos hat es auch was "
+ "mit Magie zu tun."));
+ AD(({"magie"}),
+ BS("In dieser Truhe scheint viel Magie zu stecken, wenn selbst ein "
+ "Weltuntergang ihr nichts anhaben kann."));
+ AD(({"arbeit","fertigung"}),
+ BS("Die Fertigung dieser Truhe muss sehr aufwendig gewesen sein. "
+ "Kein Wunder, dass die Truhe so teuer ist."));
+ AD(({"wunder"}),
+ BS("Ein Wunder scheint es zu sein."));
+ AD(({"weltuntergang","armageddon"}),
+ BS("Dir schaudert beim Gedanken an den Weltuntergang."));
+ AD(({"gedanken"}),
+ BS("Denk doch lieber an was anderes..."));
+
+ AddCmd("deponier|deponiere&@PRESENT","cmd_deponiere",
+ "Was moechtest Du in der Eichenholztruhe deponieren?");
+ AddCmd("entnimm|entnehme|entnehm","cmd_entnehmen");
+
+ // bei dieser Truhe waere das Erlauben voellig sinnlos. ;-)
+ RemoveCmd(({"serlaube"}));
+
+}
+
+// keine Truhen zerstoeren, die irgendeinen INhalt haben.
+int zertruemmern(string str) {
+ // aus swift_std_container
+ string nf_str;
+ nf_str="Syntax: zertruemmer [Objekt-Id]\n"
+ +"Bsp.: zertruemmer "+QueryProp(P_IDS)[1]+"\n";
+ notify_fail("Fehler: Ohne Parameter klappt das nicht.\n"+nf_str);
+ if(!str) return 0;
+ notify_fail("Fehler: Du musst eine gueltige Objekt-Id angeben!\n"+nf_str);
+ if(present(str)!=TO) // Ueberpruefe, ob auch dieses Objekt gemeint ist!
+ return 0;
+ if( QueryHausbesitzer() != QueryTP() && !QueryProp("test") )
+ {
+ write( BS("Nur "+QueryHausbesitzer()+" darf "+name(WEN,1)+" zertruemmern!"));
+ return 1;
+ }
+ // Objekte enthalten? Wenn ja, abbruch.
+ if (sizeof(autoloader)) {
+ tell_object(PL,BS("Du willst gerade zum Schlag ausholen, um "
+ +name(WEN,1)+ " zu zertruemmern, als Dir einfaellt, dass "
+ +QueryPronoun(WER)+ " ja gar nicht leer ist! Nene, wer weiss, ob "
+ "Du das nicht noch brauchen koenntest."));
+ return 1;
+ }
+ // sonst geerbten Kram ausfuehren.
+ return ::zertruemmern(str);
+}
+
+// Zesstra, 1.7.07, fuers Hoerrohr
+string GetOwner() {return "zesstra";}
+
+// Prueft das Objekt auf Eignung fuer die Truhe, speichert seine Daten und
+// zerstoert es anschliessend. NODROP-Objekte koennen nur so in die Truhe
+// gelegt werden, alle anderen koennen auch mit "stecke ... in truhe"
+// deponiert werden, woraufhin ebenfalls PreventInsert() und NotifyInsert()
+// durchlaufen werden.
+protected int cmd_deponiere(string cmd, mixed args) {
+ if (!objectp(PL)) return 0;
+
+ notify_fail(Name(WER,1)+" ist doch geschlossen!\n");
+ if(QueryProp(P_CNT_STATUS)!=CNT_STATUS_OPEN) return 0;
+
+ notify_fail("Was moechtest Du in der Eichenholztruhe deponieren?\n");
+ if (!stringp(cmd) || !sizeof(cmd)
+ || !pointerp(args) || !sizeof(args)) return 0;
+ object ob=args[0];
+ if (!objectp(ob)) return 0;
+ // wuerde die Truhe das Objekt ueberhaupt aufnehmen? Fehlerausgabe durch
+ // PrevenInsert()
+ if (PreventInsert(ob)) return 1;
+ // Ausziehen... Schade, dass DoUnwear nix vernuenftiges an Rueckgabewert
+ // hat. :-(
+ if (objectp(ob->QueryProp(P_WORN))) {
+ ob->DoUnwear();
+ if (objectp(ob->QueryProp(P_WORN))) {
+ tell_object(PL, BS("Du musst "+ ob->name(WEN,1)+ "zunaechst einmal "
+ "ausziehen!"));
+ return 1;
+ }
+ }
+ // wegstecken
+ if (objectp(ob->QueryProp(P_WIELDED))) {
+ ob->DoUnwield();
+ if (objectp(ob->QueryProp(P_WIELDED))) {
+ tell_object(PL, BS("Du musst "+ ob->name(WEN,1)+ "zunaechst einmal "
+ "wegstecken!"));
+ return 1;
+ }
+ }
+ // NO_CHECK und Silent-Bewegung, Meldungen an den Spieler selber machen.
+ tell_object(PL, BS("Du steckst "+ ob->name(WEN,1) + " in " + name(WEN,1) +
+ "."));
+
+ tell_room(environment(),BS(PL->Name(WER) + " legt " + ob->name(WEN,0) +
+ " in " + name(WEN,1) + " hinein."),({PL}));
+ ob->move(ME, M_NOCHECK|M_SILENT);
+ return 1;
+}
+
+// alternative zum "nimm bla aus truhe". Spieler wollten was kurzes dafuer
+// haben.
+protected int cmd_entnehmen(string cmd) {
+ int res;
+ mixed noget;
+
+ if (!objectp(PL)) return 0;
+
+ notify_fail(Name(WER,1)+" ist doch geschlossen!\n");
+ if(QueryProp(P_CNT_STATUS)!=CNT_STATUS_OPEN) return 0;
+
+ notify_fail(BS("Was moechtest Du aus "+name(WEM,1)+ " entnehmen?\n"));
+ if (!stringp(cmd) || !sizeof(cmd)) return 0;
+
+ object *obs=present_objects(cmd);
+
+ if (!sizeof(obs) || !objectp(obs[0]))
+ return 0;
+
+ // NOGET ist hier bloed. So ist es zwar auch nicht richtig doll... *seufz*
+ // Die hier ist/waere aber nen uebler Hack, erstmal auskommentiert lassen.
+ // also, P_NOGET sichern.
+ /*if (!closurep(noget=ob->Query(P_NOGET,F_QUERY_METHOD))) {
+ noget=ob->Query(P_NOGET,F_VALUE);
+ ob->Set(P_NOGET,0,F_VALUE);
+ }
+ else {
+ ob->Set(P_NOGET,0,F_QUERY_METHOD);
+ }*/
+ // nehmen.
+ res=PL->pick_obj(obs[0]);
+ // P_NOGET zurueckschreiben. (Ja, wenn eine Closure als F_VALUE drinsteht,
+ // landet die jetzt als F_QUERY_METHOD im Objekt.
+ /*if (closurep(noget)) {
+ ob->Set(P_NOGET,noget,F_QUERY_METHOD);
+ }
+ else
+ ob->Set(P_NOGET,noget,F_VALUE);
+*/
+ return(res);
+}
+
+// Hier wird auch das PreventInsert() von der Blueprint gerufen. Das
+// erleichtert es, die Liste an erlaubten Objekten zu aendern, ohne dass man
+// alle Clones ersetzen muss.
+varargs int PreventInsert(object ob) {
+ string oname;
+ // Das Objekt, was die Truhe gerade selber bewegt, wird ignoriert.
+ if (!objectp(ob) || ob_in_bewegung==ob) return 0;
+
+ oname=BLUE_NAME(ob);
+
+ // Pruefung in Clonen:
+ if (clonep(ME))
+ {
+ // nur Eigentuemer
+ if (!stringp(uuid) || !sizeof(uuid)) {
+ if (objectp(PL))
+ tell_object(PL,BS(sprintf("%s gehoert Dir nicht, daher kannst Du "
+ "auch keine Gegenstaende in %s legen.",
+ Name(WER,1),QueryPronoun(WEN))));
+ return 1;
+ }
+ if (!objectp(PL) || getuuid(PL)!=uuid) {
+ if (objectp(PL))
+ tell_object(PL,BS(sprintf("Nur %s darf Gegenstaende in %s "
+ "hineinlegen.",capitalize(explode(uuid,"_")[0]),name(WEN,1))));
+ return 1;
+ }
+ // jedes Objekt nur einmal.
+ if (member(autoloader,oname)) {
+ if (objectp(PL))
+ tell_object(PL,BS(Name(WER,1)+ " kann von einem Gegenstand jeweils "
+ "nur ein Exemplar aufnehmen, es ist aber bereits "
+ +ob->name(WER,0) + " in " + QueryPronoun(WEM) + "."));
+ return 1;
+ }
+ // jetzt Erlaubnisliste der BP fragen.
+ if (objectp(blueprint(ME)))
+ return blueprint(ME)->PreventInsert(ob);
+ else
+ return load_object(load_name(ME))->PreventInsert(ob);
+ }
+ // Ende fuer Pruefung fuer Clone.
+
+ // ab hier jetzt die Pruefung durch die BP.
+ // Keine (freigegebener) Autoloader? Hat in diesem Container nix verloren!
+ if( !ob->QueryProp(P_AUTOLOADOBJ) ) {
+ if (objectp(PL))
+ tell_object(PL,BS("In "+name(WEN,1)
+ +" kannst Du nur Autoload-Objekte hineinlegen. "));
+ return 1;
+ }
+ else if (member(blacklist,oname)) {
+ if (objectp(PL))
+ tell_object(PL,BS("In "+name(WEN,1)
+ +" kannst Du nur dafuer erlaubte Autoload-Objekte hineinlegen. "
+ +ob->Name(WER,1) + " wurde explizit als nicht erwuenscht "
+ "befunden."));
+ return 1;
+ }
+ else if (!member(whitelist,oname)) {
+ if (!member(vorschlaege,oname)) {
+ vorschlaege[oname,0]=ob->name(WER,0) || "";
+ vorschlaege[oname,1]=ob->short() || "";
+ }
+ if (objectp(PL))
+ tell_object(PL,BS("In "+name(WEN,1)
+ +" kannst Du nur dafuer erlaubte Autoload-Objekte hineinlegen. "
+ +ob->Name(WER,1) + " ist momentan nicht auf der Liste. Der "
+ "Gegenstand wurde jetzt als Vorschlag gespeichert. Bitte hab "
+ "etwas Geduld, bis sich jemand den Gegenstand angeschaut hat."));
+ // ggf. reset reaktivieren und Maintainer informieren.
+ if (!query_next_reset())
+ set_next_reset(1);
+ return 1;
+ }
+ // getragenes?
+ if (ob->QueryProp(P_WORN)) {
+ ob->DoUnwear(0);
+ if (ob->QueryProp(P_WORN)) { //ARGL. GRUMMEL.
+ if (objectp(PL))
+ tell_object(PL,BS("Willst Du "+ob->name(WEN,1) + " nicht erstmal "
+ "ausziehen?"));
+ return 1;
+ }
+ }
+ // enthaelt es irgendwelche anderen Objekte?
+ if (sizeof(all_inventory(ob))) {
+ if (objectp(PL))
+ tell_object(PL,BS(ob->Name(WER,1) + " ist nicht leer."));
+ return 1;
+ }
+
+ // andere Einschraenkungen, als hier geprueft werden, gibt es nicht.
+ return 0;
+}
+
+// hier ist das Objekt jetzt in der Truhe, d.h. Daten speichern und Objekt
+// destructen. ;)
+void NotifyInsert(object ob, object oldenv) {
+
+ // Das Objekt, was die Truhe gerade selber bewegt, wird ignoriert.
+ if (!objectp(ob) || ob==ob_in_bewegung)
+ return;
+ STORELOG(sprintf("%s deponiert %s [%O], Daten: %O",getuid(PL),ob->name(WEN,0),
+ ob,ob->QueryProp(P_AUTOLOADOBJ)));
+ // noetig sind die IDs, den Namen und die AUTOLOADOBJ-Daten des Objekts.
+ // ;-)
+ autoloader[BLUE_NAME(ob),ALDATA]=ob->QueryProp(P_AUTOLOADOBJ);
+ autoloader[BLUE_NAME(ob),IDS]=ob->QueryProp(P_IDS);
+ // Objekte, die 0 als short liefern, kriegen eine Standard-Short und werden
+ // sichtbar gemacht, da sie sonst nicht wiederzufinden sind. Objekte, die
+ // unsichtbar sein sollen, duerfen nicht erlaubt werden.
+ // TODO eine ID als Short nehmen?
+ autoloader[BLUE_NAME(ob),NAME]=capitalize((ob->short()||"<Unbekannt>.\n")[..<3]);
+ // nach dem Move die realen Objekte destructen.
+ call_out(#'check_content, 0);
+ save_me();
+}
+
+// Objekt wurde entnommen, also aus der Liste der enthaltenen Autoloader
+// loeschen. Ausserdem Objekt konfigurieren. Dies wird erst hier gemacht und
+// nicht in create_object(), damit es so aehnlich wie moeglich zum clonen der
+// Autoloader beim erstellen des Spielerobjektes wird (dort wird erst bewegt,
+// dann konfiguriert).
+void NotifyLeave(object ob, object dest) {
+ string error, oname;
+
+ if (!objectp(ob))
+ return;
+
+ oname=BLUE_NAME(ob);
+ if (!member(autoloader,oname)) {
+ // Das sollte definitiv nicht passieren.
+ ERRLOG(sprintf("Gegenstand (%O) wurde entnommen, der nicht "
+ "gespeichert war!",ob));
+ return;
+ }
+
+ // wenn kein Fehler: Objekt aus Liste loeschen. Sonst wird das Objekt
+ // zerstoert. Damit bleiben die Autoloader-Daten hier erhalten und der
+ // Spieler hat kein disfunktionales Objekt im Inventar.
+ if (error) {
+ ERRLOG(sprintf("Fehler beim Konfigurieren von %O. Fehlermeldung: %O."
+ "Daten: %O",ob,error,autoloader[oname,ALDATA]));
+ ob->remove(1);
+ if (objectp(ob))
+ destruct(ob);
+ }
+ else {
+ PICKLOG(sprintf("Objekt (%O) wurde entnommen.",ob));
+ m_delete(autoloader,oname);
+ // speichern
+ save_me();
+ }
+}
+
+protected void check_content() {
+ // wenn Objekte noch in der Truhe sind, also nicht erfolgreich in
+ // einen Spieler bewegt wurden, werden zerstoert. Datenverlust gibt es
+ // hierbei nicht, weil die Daten der Autoloader nur durch NotifyLeave()
+ // geloescht werden.
+ foreach(object ob: all_inventory()) {
+ ob->remove(1);
+ if (objectp(ob)) destruct(ob);
+ }
+}
+
+// hier nochmal schauen, ob das Objekt auch in den richtigen Spieler bewegt
+// wird... Falls das move dann hier abgebrochen wird, wird das Objekt im
+// naechsten HB von der Truhe zerstoert. (chk_contents())
+varargs int PreventLeave(object ob, mixed dest) {
+ object ob2;
+
+ //DEBUG(sprintf("PreventLeave(): Ob: %O, Dest: %O (%O)",
+ // ob,dest,(objectp(dest)?"Objekt":"Non-Object")));
+
+ if (!objectp(ob)) return 0;
+ // falls string uebergeben, erstmal zug. Spieler finden.
+ if (stringp(dest) && sizeof(dest))
+ dest=find_player(dest);
+
+ // richtiges INteractive? Dann darf das Objekt raus. Sonst nicht. ;-)
+ if (!objectp(dest) || !interactive(dest) || getuuid(dest)!=uuid)
+ return 1;
+
+ // pruefen, ob der Spieler schon ein Objekt dieser Blueprint dabei hat. Wenn
+ // ja, Abbruch, das koennte sonst zuviele Probleme geben.
+ if (objectp(ob2=present_clone(ob,dest))) {
+ tell_object(dest,BS("Du hast bereits "+ob2->name(WEN,0) +
+ " dabei. Zwei Gegenstaende dieser Art kannst du nicht gleichzeitig "
+ "mit Dir herumtragen."));
+ return 1; //nicht rausnehmen.
+ }
+ return 0;
+}
+
+// Objekte ausgeben, die hier angeblich drin sind. ;-) Gibt aber nur die
+// Autoloader aus, keine echten Objekt, die Container sind. Allerdings sollte
+// sowas eh nicht vorkommen. ;-)
+// flags: 1 - return array, 2 - don't collect equal objects '
+// flags: 4 - don't append infos for wizards
+varargs mixed make_invlist(object viewer, mixed inv, int flags) {
+ int iswiz;
+ mixed objs;
+
+ iswiz = IS_LEARNER( viewer ) && viewer->QueryProp(P_WANTS_TO_LEARN);
+ // Mapping benutzen, um multiplen Overhead fuer allokation im foreach() zu
+ // vermeiden.
+ objs=m_allocate(sizeof(autoloader),1);
+ foreach(string oname, string *ids, string sh: autoloader) {
+ if (iswiz && !(flags & 4))
+ objs[oname]=sh + ". ["+oname+"]";
+ else
+ objs[oname]=sh + ".";
+ }
+ if(flags & 1) return(m_values(objs)-({""}));
+ if(!sizeof(autoloader)) return "";
+ return sprintf("%"+(sizeof(objs) > 6 ? "#" : "=")+"-78s",
+ implode(m_values(objs)-({""}), "\n")) + "\n";
+}
+
+// erzeugt das benannte Objekt und liefert es zurueck. Liefert 0 im Fehlerfall.
+// ausserdem bewegt es das Objekt in die Truhe, damit es ein Env hat und die
+// Truhe via NotifyLeave() mitkriegt, dass es tatsaechlich entnommen wurde.
+private object create_object(string oname) {
+ string error;
+ object ob;
+ mixed noget;
+ if (!member(autoloader,oname)) return 0;
+
+ //Blueprint finden (ja, das ist nicht unbedingt noetig, man koennte auch
+ //direkt clonen)
+ if (error=catch(ob=load_object(oname);publish) ||
+ !objectp(ob)) {
+ ERRLOG(sprintf("Konnte %s nicht laden/finden. Fehler: %O",
+ oname,error));
+ return 0;
+ }
+ // clonen
+ if (error=catch(ob=clone_object(oname);publish) ||
+ !objectp(ob)) {
+ ERRLOG(sprintf("Konnte %s nicht clonen. Fehler: %O",
+ oname,error));
+ return 0;
+ }
+ // konfigurieren
+ error=catch(ob->SetProp(P_AUTOLOADOBJ,autoloader[oname,ALDATA]);publish);
+
+ //Objekt bewegen, dabei Objekt in glob. Var. merken, damit PreventInsert()
+ //und NotifyInsert() es ignorieren. *seufz*
+ ob_in_bewegung=ob;
+ ob->move(ME,M_NOCHECK);
+ ob_in_bewegung=0;
+
+ // jetzt noch nen Callout starten, damit das Objekt zerstoert wird, wenn es
+ // nicht wirklich in einen Spieler bewegt wird.
+ call_out(#'check_content,1);
+
+ return(ob);
+}
+
+// Schauen, ob die truhe ein Objekt mit passender ID enthaelt. Wenn
+// ja, das Objekt erzeugen und zurueckliefern.
+// Diese Funktion hat eine Reihe von Nachteilen bzw. Defiziten ggue. der
+// normalerweise in Containern definierten Funktion:
+// - Nur das erste Objekt, auf das id passt. Ich hab erstmal keine Lust,
+// hier mehrere Objekte zu erzeugen. Mal schauen, ob es so geht. Auch waere
+// es ein Problem, wenn viele Objekt die Evalgrenze bzw. nicht alle in den
+// Spieler bewegt werden, nachdem sie erzeugt wurden.
+// - keine komplexen Ausdruecke, nur reine IDs.
+// Ich halte den Aufwand fuer nicht gerechtfertigt.
+object *present_objects( string complex_desc ) {
+ object ob;
+ if (!stringp(complex_desc) || !sizeof(complex_desc))
+ return ({});
+ // diese Funktion liefert nur Objete zurueck, wenn der richtige Interactive
+ // versucht, sie zu entnehmen. ;-)
+ if (!objectp(this_interactive()) ||
+ getuuid(this_interactive())!=uuid)
+ return ({});
+
+ // "alles" liefert das erstbeste Objekt.
+ if (complex_desc=="alles" && sizeof(autoloader))
+ {
+ string oname=m_indices(autoloader)[0];
+ ob=create_object(oname);
+ if (objectp(ob)) return ({ob});
+ }
+
+ // ueber alle Eintraege gehen, bis eine ID stimmt, erstes passendes Objekt
+ // erzeugen und in einem Array zurueckliefern.
+ foreach(string oname, string *ids: autoloader) {
+ if (member(ids,complex_desc)==-1) continue;
+ ob=create_object(oname);
+ break; //objekt gefunden, fertig hier
+ }
+ if (objectp(ob)) return ({ob});
+ return ({}); // nix gefunden
+}
+
+
+
+// ******************* Verwaltung *********************************
+
+// registriert die Truhe auf den jeweiligen Eigentuemer.
+protected void SetBesitzer(string unused, string newuuid) {
+ if (!stringp(newuuid) || !sizeof(newuuid)) return;
+ // wenn schon registriert, abbrechen
+ if (stringp(uuid) && sizeof(uuid)) return;
+
+ uuid=newuuid;
+ Set(H_FURNITURE,uuid,F_VALUE); //Setmethode umgehen, sonst Rekursion
+ // ab jetzt nur noch von der Truhe selber.
+ Set(H_FURNITURE,SECURED,F_MODE_AS);
+
+ // Daten fuer den Benutzer aus der Blueprint holen (BP liefert KEINE Kopie
+ // und es darf KEINE gemacht werden!):
+ autoloader=(mapping)load_name()->GetData(uuid);
+
+ // keine Daten gekriegt? -> Fehler loggen
+ if (!mappingp(autoloader))
+ {
+ ERRLOG(sprintf("Keine gueltigen Daten vom Truhenmaster (BP) erhalten. "
+ "initialisiere mit leerem Mapping. :-("));
+ raise_error(sprintf(
+ "Keine gueltigen Daten vom Truhenmaster (BP) fuer UUID %s "
+ "erhalten.\n",uuid));
+ }
+}
+
+// Set-Funktion
+string _set_h_furniture(mixed arg) {
+ if (stringp(arg))
+ {
+ SetBesitzer(0,arg); // bricht ab, wenn bereits registriert.
+ }
+ return(uuid);
+}
+
+// Falls das Speichern in der BP nicht klappte, rufen die Clones diese
+// Funktion. Schreiben der Daten in in Logfile zur Restaurieren per Hand.
+private void EmergencyStore(int res) {
+ ERRLOG(sprintf("EmergencyStore() called. Rueckgabewert des "
+ "Truhenmaster (BP) war: %O. Speichere Daten in Logfile. ",res));
+ write_file(__DIR__+"ALTRUHE.NOTFALLDATEN",
+ sprintf("Daten fuer %O:\n%O\n",uuid,autoloader));
+}
+
+protected void save_me() {
+ int res;
+ // nur BP speichern
+ if (!clonep(ME))
+ save_object(SAVEFILE);
+ else
+ {
+ if (objectp(blueprint(ME)))
+ res=(int)blueprint(ME)->StoreData(uuid,autoloader);
+ else
+ res=(int)load_object(load_name(ME))->StoreData(uuid,autoloader);
+
+ if (res!=1)
+ EmergencyStore(res); // Daten in einem Notfall-Logfile ablegen.
+ }
+}
+
+
+// diese Funktion wird vom Seherhausraum gerufen, sobald ein rebootfestes
+// Moebelstueck erzeugt und konfiguriert wurde.
+void post_create() {
+ if (!clonep()) return;
+
+ // wenn jetzt kein Env: destructen
+ if (!objectp(environment())) {
+ remove(1);
+ return;
+ }
+ //beim Schrankmaster registrieren
+ SCHRANKMASTER->RegisterCnt(ME, QueryProp("cnt_version_std")
+ +":"+QueryProp("cnt_version_obj"), environment()->QueryOwner(),
+ environment());
+}
+
+// diese Funktion wird vom Schrankmaster gerufen, wenn dieser meint, dass
+// dieses Objekt neu erstellt werden sollte.
+int UpdateMe()
+{
+ if (!clonep())
+ return 0;
+ if (!objectp(environment()))
+ return 1;
+ object ob=clone_object(load_name(ME));
+ if (objectp(ob)) {
+ object oldenv=environment();
+ // UUID uebertragen
+ ob->SetProp(H_FURNITURE, uuid);
+ // hierhier bewegen, dabei werden UUID und Daten von der neuen Truhe meist
+ // automatisch geholt.
+ ob->move(oldenv,M_NOCHECK);
+ // jetzt erst post_create() rufen!
+ ob->post_create();
+ // dieses Objekt rausbewegen (damit das Seherhaus es austraegt).
+ move("/room/void",M_NOCHECK);
+ // Seherhausraum speichern (koennte teuer sein!)
+ oldenv->Save(1);
+ // selbstzerstoeren
+ // __INT_MAX__ bedeutet: nicht speichern, die neue Truhe hat die daten
+ // schon aus der BP abgefragt.
+ remove(__INT_MAX__);
+ }
+ return(1);
+}
+
+// bei Selbstzerstoerung speichern bzw. Daten an die Blueprint uebermitteln
+// und beim Schrankmaster abmelden.
+varargs int remove(int silent) {
+ string uid="";
+
+ // Blueprint speichern im Savefile, Clones uebertragen die Daten hier an die
+ // Blueprint. Clones nur, wenn nicht __INT_MAX__ uebergeben wurde.
+ if (silent!=__INT_MAX__ || !clonep())
+ save_me();
+
+ if (clonep()) {
+ // Clone melden sich beim Schrankmaster ab.
+ if (objectp(environment())) {
+ uid=environment()->QueryOwner();
+ }
+ //beim Schrankmaster deregistrieren
+ SCHRANKMASTER->RemoveCnt(ME,uid);
+ }
+ return(::remove(silent));
+}
+
+// ***************** NUR BLUEPRINTS *********************************
+
+// neuen Autoloader zulassen (nur EM+!)
+varargs int AddAutoloader(string path,string nam) {
+ object ob;
+ if (clonep(ME)) return 0;
+ if (!stringp(path) || !sizeof(path)) return -1;
+ if (!ACCESS) return -2;
+ //if (!ARCH_SECURITY) return -2;
+ if (member(whitelist,path)) return -3;
+ if (catch(ob=load_object(path);publish)
+ || !objectp(ob))
+ return -4;
+ // wenn Name nicht angegeben und auch nicht aus BP ermittelbar: Abbruch.
+ if (!stringp(nam) || !sizeof(nam)) {
+ nam=ob->name(WER,0);
+ if (!stringp(nam) || !sizeof(nam)) return -5;
+ }
+ ITEMLOG(sprintf("%s erlaubt: %s (%s)\n",getuid(this_interactive()),
+ path,nam));
+ whitelist+=([path:capitalize(nam)]);
+ if (member(vorschlaege,path))
+ m_delete(vorschlaege,path);
+ save_me();
+ return(1);
+}
+
+// Autoloader aus Erlaubnisliste entfernen (nur EM+!)
+int RemoveAutoloader(string path) {
+ if (clonep(ME)) return 0;
+ if (!stringp(path) || !sizeof(path)) return -1;
+ if (!ACCESS) return -2;
+ //if (!ARCH_SECURITY) return -2;
+ if (!member(whitelist,path)) return -3;
+ ITEMLOG(sprintf("%s widerruft Erlaubnis: %s (%s)\n",getuid(this_interactive()),
+ path,whitelist[path]));
+ whitelist-=([path]);
+ save_me();
+ return(1);
+}
+
+// erlaubte Autoloader abfragen
+mapping QueryAutoloader() {
+ return(copy(whitelist));
+}
+
+// neuen Autoloader in Blacklist eintragen (nur EM+!)
+varargs int AddBlacklist(string path, string nam) {
+ object ob;
+ if (clonep(ME)) return 0;
+ if (!stringp(path) || !sizeof(path)) return -1;
+ if (!ACCESS) return -2;
+ //if (!ARCH_SECURITY) return -2;
+
+ if (member(blacklist,path)) return -3;
+
+ if (catch(ob=load_object(path);publish)
+ || !objectp(ob))
+ return -4;
+ // wenn Name nicht angegeben und auch nicht aus BP ermittelbar: Abbruch.
+ if (!stringp(nam) || !sizeof(nam)) {
+ nam=ob->name(WER,0);
+ if (!stringp(nam) || !sizeof(nam)) return -5;
+ }
+ // ggf. erlaubten entfernen.
+ if (member(whitelist,path))
+ RemoveAutoloader(path);
+ ITEMLOG(sprintf("%s verbietet: %s (%s)\n",getuid(this_interactive()),
+ path,nam));
+
+ blacklist+=([path:capitalize(nam)]);
+
+ if (member(vorschlaege,path))
+ m_delete(vorschlaege,path);
+
+ save_me();
+ return(1);
+}
+
+// Autoloader aus Blacklist entfernen (nur EM+!)
+int RemoveBlacklist(string path) {
+ if (clonep(ME)) return 0;
+ if (!stringp(path) || !sizeof(path)) return -1;
+ if (!ACCESS) return -2;
+ //if (!ARCH_SECURITY) return -2;
+ if (member(blacklist,path)==-1) return -3;
+ ITEMLOG(sprintf("%s loescht: %s (%s) von Blacklist\n",getuid(this_interactive()),
+ path,blacklist[path]));
+ blacklist-=([path]);
+ save_me();
+ return(1);
+}
+
+// gesperrte Autoloader abfragen
+mapping QueryBlacklist() {
+ return(copy(blacklist));
+}
+
+// vorschlaege abfragen
+varargs mixed QueryVorschlaege(int format) {
+ string res="\n";
+ if (!format) return(copy(vorschlaege));
+
+ foreach(string oname, string nam, string sh: vorschlaege) {
+ res+=sprintf("%.78s:\n %.37s,%.37s\n",oname,nam,sh);
+ }
+
+ if (format==2 && objectp(PL))
+ tell_object(PL,res);
+ else
+ return res;
+ return 0;
+}
+
+// Wird diese funktion in der Blueprint gerufen, liefert sie die Daten fuer
+// eine Truhe mit dieser UUID zurueck. Aber nur dann, wenn die auch von einer
+// truhe abgerufen wird und keinem beliebigen anderen Objekt oder wenn ein EM
+// abfragt.
+mapping GetData(string uid) {
+ if (clonep(ME)) return 0;
+ if (extern_call())
+ {
+ if (!objectp(previous_object())) return 0;
+ if (blueprint(previous_object()) != ME
+ && load_name(previous_object()) != __FILE__[..<3]
+ && !ACCESS)
+ return(0);
+ }
+ if (!stringp(uid)) return ([]);
+
+ if (!member(data, uid))
+ data[uid] = m_allocate(1,3);
+
+ // Absichtlich keine Kopie, damit die Truhen (falls jemand mehrere kauft)
+ // sich alle eine Kopie des Mappings teilen.
+ return data[uid];
+}
+
+// Loest die Speicherung der Daten im Savefile aus, denn irgendwelche Daten
+// haben sich in einem Clone geaendert, welche noch auf die Platte muessen.
+// Diese Funktion speicherte frueher Daten aus den Clones wieder im Mapping
+// des Masters (der Blueprint). Dies ist heute nicht mehr so, weil alle Truhen
+// (eines Benutzers) sich data[uid] teilen. Daher wird hier ein Fehler
+// ausgeloest, wenn es von einer Truhe ein Mapping kriegt, welches nicht
+// identisch (!) mit dem data[uid] ist.
+// liefert 0 im Fehlerfall!
+int StoreData(string uid, mapping tmp) {
+
+ if (clonep(ME)) return 0;
+
+ // Aber nur dann, wenn die auch von einer truhe abgerufen wird und keinem
+ // beliebigen anderen Objekt oder wenn ein EM setzt.
+ if (extern_call())
+ {
+ if (!objectp(previous_object()))
+ return 0;
+ if (blueprint(previous_object()) != ME
+ && load_name(previous_object()) != __FILE__[..<3]
+ && !ACCESS)
+ return 0;
+ }
+ if (!stringp(uid) || !mappingp(tmp))
+ return(0);
+
+ // tmp muss auf _dasselbe_ Mapping zeigen wie data[uid]. Wenn das nicht der
+ // Fall ist, ist was schiefgelaufen. Jedenfalls wird dann hier nen Fehler
+ // ausgeloest.
+ if (tmp != data[uid])
+ {
+// if(program_time(previous_object()) < 1400525694)
+// data[uid]=tmp;
+// else
+ raise_error("StoreData() gerufen und Daten sind nicht identisch "
+ "mit den bereits bekannten.\n");
+ }
+
+ // Absichtlich keine Kopie, damit sich alle Truhen das Mapping teilen.
+ //data[uid]=tmp;
+
+ // Savefile muss natuerlich geschrieben werden, fuer den naechsten Reboot.
+ if (find_call_out(#'save_me)==-1)
+ call_out(#'save_me,10); // Speichervorgaenge ggf. sammeln (upd -ar ...)
+ return(1);
+}
+
+// Maintainer ueber Truhenvorschlaege informieren
+void reset() {
+
+ if (clonep() || !sizeof(vorschlaege)) {
+ // ohne Vorschlaege ist auch kein reset noetig.
+ set_next_reset(-1);
+ return;
+ }
+ set_next_reset(12000); // alle 3-4h reicht.
+ foreach(string uid: MAINTAINER) {
+ object pl=find_player(uid);
+ if (objectp(pl) && query_idle(pl) < 1800)
+ tell_object(pl,BS("Es gibt neue Objektvorschlaege fuer die "
+ "Autoloadertruhe. Bitt schau da doch bei Gelegenheit mal drueber."));
+ }
+}
+
+
+// *************************************************************************
+
+// **************** SONSTIGES **********************************************
+
+// *seufz*
+// secure_level() aus der simul_efun ist hier momentan nicht brauchbar, weil
+// dort auch p/seher/moebel/autoloadertruhe in der Callerkette steht und das
+// ein levle von 0 hat. *seufz*
+nomask private int my_secure_level() {
+ int *level;
+ //kette der Caller durchlaufen, den niedrigsten Level in der Kette
+ //zurueckgeben. Zerstoerte Objekte (Selbstzerstoerer) fuehren zur Rueckgabe
+ //von 0.
+ //caller_stack(1) fuegt dem Rueckgabearray this_interactive() hinzu bzw. 0,
+ //wenn es keinen Interactive gibt. Die 0 fuehrt dann wie bei zerstoerten
+ //Objekten zur Rueckgabe von 0, was gewuenscht ist, da es hier einen
+ //INteractive geben muss.
+ level=map(caller_stack(1),function int (object caller)
+ {if (objectp(caller))
+ return(query_wiz_level(geteuid(caller)));
+ return(0); // kein Objekt da, 0.
+ } );
+ return(min(level)); //den kleinsten Wert im Array zurueckgeben (ggf. 0)
+}
+
+
+// debugkram
+mixed _query_content() {
+ //deep_copy, damit nicht jemand einfach so an den Daten rumbasteln kann.
+ return(deep_copy(autoloader));
+}
+
+mixed _query_owner() {
+ return(uuid);
+}
+
+int DeleteData(string uid) {
+ if (clonep(ME)) return 0;
+ if (!stringp(uid) || !sizeof(uid)) return -1;
+ if (!ACCESS) return -2;
+ //if (!ARCH_SECURITY) return -2;
+ m_delete(data,uid);
+ save_me();
+ return(1);
+}
+
+mixed testfun() {return "bin da\n";}
+
diff --git a/d/seher/haeuser/moebel/kleiderschrank.c b/d/seher/haeuser/moebel/kleiderschrank.c
new file mode 100644
index 0000000..79209b4
--- /dev/null
+++ b/d/seher/haeuser/moebel/kleiderschrank.c
@@ -0,0 +1,208 @@
+//--------------------------------------------------------------------------------
+// Name des Objects: Kleiderschrank
+// Letzte Aenderung: 17.03.2001
+// Magier: Swift
+//--------------------------------------------------------------------------------
+#pragma strong_types,rtt_checks
+
+#include "schrankladen.h"
+#include <ansi.h>
+inherit LADEN("swift_std_container");
+
+#define VERSION_OBJ "3"
+
+string strall;
+
+protected void create()
+{
+ if (!clonep(TO)) return;
+ swift_std_container::create();
+ SetProp(P_SHORT, "Ein Kleiderschrank");
+ SetProp(P_LONG, BS(
+ "In diesem massiven Holzschrank kannst Du die Ausruestung fuer eine "
+ +"halbe Armee unterbringen. Mehrere Regale sorgen dafuer, dass alles "
+ +"seinen geordneten Platz findet, damit Du es auch schnell "
+ +"wiederfindest.")+"@@cnt_status@@");
+ AddId(({"kleiderschrank", "holzschrank", "schrank"}));
+ SetProp("cnt_version_obj", VERSION_OBJ);
+ SetProp(P_NAME, "Kleiderschrank");
+ SetProp(P_GENDER, MALE);
+ SetProp(P_WEIGHT, 5000); // Gewicht 5 Kg
+ SetProp(P_MAX_WEIGHT, 1000000); // Es passen fuer 1000 kg Sachen rein.
+ SetProp(P_WEIGHT_PERCENT, 100); // Dafuer macht er auch nix leichter :)
+ SetProp(P_MAX_OBJECTS, 100); // Mehr sollte nicht sein, lt. Tiamak.
+ SetProp(P_VALUE, 0); // Kein materieller Wert. Ist eh nicht verkaufbar.
+ SetProp(P_NOBUY, 1); // Wird im Laden zerstoert, falls er verkauft wird.
+ SetProp(P_NOGET, "Das geht nicht. "+Name(WER,1)+" haftet wie magisch am Boden.\n");
+ SetProp(P_MATERIAL, ({MAT_MISC_WOOD, MAT_MISC_MAGIC}) );
+ SetProp(P_INFO, "Versuchs mal mit: \"skommandos "+QueryProp(P_IDS)[1]+"\" !\n");
+ SetProp("obj_cmd", "sliste [Objekt-Id] [Kleidungs-/Ruestungstyp|\"alles\"]\n"
+ +" Kleidungs-/Ruestungstypen: Helme, Umhaenge, Ruestungen, Hosen, Schuhe,\n"
+ +" Handschuhe, Guertel, Amulette, Ringe, Koecher,\n"
+ +" Schilde, Sonstiges\n");
+ AD(({"regal", "regale"}), BS("Durch die Regale kommt etwas Ordnung in die "
+ +"vielen Sachen, die man in den Schrank stecken kann. Du kannst Dir z.B. "
+ +"eine Liste bestimmter Kleidungs-/Ruestungstypen des Schrankinhaltes "
+ +"mit dem Befehl \"sliste\" anschauen. (Das geht natuerlich nur bei "
+ +"offenem Schrank!"));
+
+ AddCmd(({"sliste"}), "auflistung");
+}
+
+varargs int PreventInsert(object ob)
+{
+ // Nur Ruestung/Kleidung hat in diesem Container was verloren!
+ if ((ob->IsClothing() || ob->QueryProp(P_ARMOUR_TYPE))
+ && !ob->QueryProp(P_WEAPON_TYPE) )
+ {
+ return ::PreventInsert(ob);
+ }
+
+ write( BS("In "+name(WEN,1)+" kannst Du nur Ruestungs-/Kleidungsstuecke legen!"));
+ return 1;
+}
+
+int auflistung2(string was, string nf_str1, string nf_str2, int alles)
+{
+ string obshort, suche, *strs;
+ object *obs;
+ int i;
+ mapping suchobs;
+ switch(was)
+ {
+ case "helme" : suche=AT_HELMET; break;
+ case "umhaenge" : suche=AT_CLOAK; break;
+ case "ruestungen" : suche=AT_ARMOUR; break;
+ case "hosen" : suche=AT_TROUSERS; break;
+ case "schuhe" : suche=AT_BOOT; break;
+ case "handschuhe" : suche=AT_GLOVE; break;
+ case "guertel" : suche=AT_BELT; break;
+ case "amulette" : suche=AT_AMULET; break;
+ case "ringe" : suche=AT_RING; break;
+ case "koecher" : suche=AT_QUIVER; break;
+ case "schilde" : suche=AT_SHIELD; break;
+ case "sonstiges" : suche=AT_MISC; break;
+ default : write("Fehler: Ungueltiger Kleidungs-/Ruestungstyp. "
+ +"Folgende Typen gibt es:\n"+nf_str1+nf_str2);
+ return 1; break;
+ }
+ obs=all_inventory();
+ suchobs=([]);
+ for(i=0;i<sizeof(obs);i++)
+ {
+ obshort=obs[i]->QueryProp(P_SHORT);
+ if(obshort=="Nichts besonderes") // keine P_SHORT ?
+ obshort=obs[i]->Name(WER); // Hoffen wir mal dass das Obj. nen Namen hat.
+ if(obs[i]->QueryProp(P_ARMOUR_TYPE)==suche) // Gesuchter ArmourType gefunden...
+ {
+ if(suchobs[obshort]) // P_SHORT des Obj. schon im mapping?
+ {
+ if( obs[i]->QueryProp(P_AMOUNT) )
+ suchobs[obshort]+=obs[i]->QueryProp(P_AMOUNT); // Dann den Zaehler um Amount hoch!
+ else
+ suchobs[obshort]+=1; // Dann den Zaehler um 1 hoch!
+ }
+ else
+ {
+ if( obs[i]->QueryProp(P_AMOUNT) )
+ suchobs+=([obshort: obs[i]->QueryProp(P_AMOUNT)]);
+ else
+ suchobs+=([obshort: 1]);
+ }
+ }
+ }
+ strs=m_indices(suchobs);
+ if(sizeof(strs))
+ {
+ if(!alles)
+ {
+ strall+=Name(WER,1)+" enthaelt folgende "+CAP(was)+":\n";
+ strall+="------------------------------------------------------------\n";
+ }
+ else
+ strall+=ANSI_BOLD+"=== "+CAP(was)+":\n"+ANSI_NORMAL;
+ for(i=0;i<sizeof(strs);i++)
+ {
+ if(suchobs[strs[i]] > 1)
+ strall+=strs[i]+". ("+suchobs[strs[i]]+")\n";
+ else
+ strall+=strs[i]+".\n";
+ }
+ }
+ else
+ if(!alles)
+ strall+=Name(WER,1)+" enthaelt keine "+CAP(was)+"!\n";
+ return 1;
+}
+
+int auflistung(string str)
+{
+ string *strs, ob_id, was, nf_str1,nf_str2;
+ strall="";
+ nf_str1=" (Helme, Umhaenge, Ruestungen, Hosen, Schuhe, Handschuhe,\n"
+ +" Guertel, Amulette, Ringe, Koecher, Schilde, Sonstiges)\n";
+ nf_str2="Syntax: sliste [Objekt-Id] [Kleidungs-/Ruestungstyp|\"alles\"]\n"
+ +"Bsp.: sliste "+QueryProp(P_IDS)[1]+" "+"helme\n"
+ +" sliste "+QueryProp(P_IDS)[1]+" alles\n";
+ notify_fail("Fehler: Ohne Parameter klappt das nicht.\n"+nf_str2);
+ if(!str) return 0;
+ if(present(str)==TO) // Ueberpruefe, ob dieses Objekt gemeint ist!
+ {
+ write("Fehler: Es fehlt ein Kleidungs-/Ruestungstyp. Folgende Typen gibt es:\n"
+ +nf_str1+nf_str2);
+ return 1;
+ }
+ strs=old_explode(str, " ");
+ notify_fail("Fehler: Du musst eine gueltige Objekt-Id angeben!\n"
+ +nf_str2);
+ if( sizeof(strs) < 2 ) return 0; // Nur 1 Par. und der ist nicht die Objekt-Id
+ if( sizeof(strs) == 2 ) // Anzahl Par. = 2
+ {
+ ob_id=strs[0];
+ was=strs[1];
+ if( IST_ZAHL(was) ) // Objekt-Id z.B. mit "schrank 2" angesprochen?
+ if(present(ob_id+" "+was)==TO) // Falls dieses Objekt gemeint ist und kein 3. Par!
+ {
+ write("Fehler: Es fehlt ein Kleidungs-/Ruestungstyp. Folgende Typen gibt es:\n"
+ +nf_str1+nf_str2);
+ return 1;
+ }
+ else
+ return 0;
+ }
+ else if( sizeof(strs) == 3 )
+ {
+ ob_id=strs[0]+" "+strs[1];
+ was=strs[2];
+ }
+ else // Anzahl erforderlicher Parameter ueberschritten!
+ return 0;
+ if(present(ob_id)!=TO) // Ueberpruefe, ob auch dieses Objekt gemeint ist!
+ return 0;
+ if(QueryProp(P_CNT_STATUS)!=CNT_STATUS_OPEN)
+ {
+ write("Dazu muesste "+name(WER,1)+" geoeffnet sein.\n");
+ return 1;
+ }
+//--- Hier ist Parameterpruefung zu Ende.
+ was=LOWER(was);
+ if(was!="alles")
+ auflistung2(was, nf_str1, nf_str2, 0);
+ else
+ {
+ auflistung2("helme", nf_str1, nf_str2, 1);
+ auflistung2("umhaenge", nf_str1, nf_str2, 1);
+ auflistung2("ruestungen", nf_str1, nf_str2, 1);
+ auflistung2("hosen", nf_str1, nf_str2, 1);
+ auflistung2("schuhe", nf_str1, nf_str2, 1);
+ auflistung2("handschuhe", nf_str1, nf_str2, 1);
+ auflistung2("guertel", nf_str1, nf_str2, 1);
+ auflistung2("amulette", nf_str1, nf_str2, 1);
+ auflistung2("ringe", nf_str1, nf_str2, 1);
+ auflistung2("koecher", nf_str1, nf_str2, 1);
+ auflistung2("schilde", nf_str1, nf_str2, 1);
+ auflistung2("sonstiges", nf_str1, nf_str2, 1);
+ }
+ TP->More(strall);
+ return 1;
+}
diff --git a/d/seher/haeuser/moebel/kommode.c b/d/seher/haeuser/moebel/kommode.c
new file mode 100644
index 0000000..dea2b50
--- /dev/null
+++ b/d/seher/haeuser/moebel/kommode.c
@@ -0,0 +1,40 @@
+//--------------------------------------------------------------------------------
+// Name des Objects: Kommode
+// Letzte Aenderung: 17.03.2001
+// Magier: Swift
+//--------------------------------------------------------------------------------
+#pragma strong_types,rtt_checks
+
+#include "schrankladen.h"
+inherit LADEN("swift_std_container");
+
+#define VERSION_OBJ "3"
+
+protected void create()
+{
+ if (!clonep(TO)) return;
+ swift_std_container::create();
+ SetProp(P_SHORT, "Eine Kommode");
+ SetProp(P_LONG, BS(
+ "Diese robuste Kommode aus Eichenholz passt einfach in jeden Raum. "
+ +"Man kann jede Menge Zeug darin verstauen, und die vielen Schubladen "
+ +"lassen es einfach verschwinden. So ein Moebelstueck gehoert einfach "
+ +"in jedes Haus!")+"@@cnt_status@@");
+ AddId(({"kommode"}));
+ SetProp("cnt_version_obj", VERSION_OBJ);
+ SetProp(P_NAME, "Kommode");
+ SetProp(P_GENDER, FEMALE);
+ SetProp(P_WEIGHT, 5000); // Gewicht 5 Kg
+ SetProp(P_MAX_WEIGHT, 1000000); // Es passen fuer 1000 kg Sachen rein.
+ SetProp(P_WEIGHT_PERCENT, 100); // Dafuer macht er auch nix leichter :)
+ SetProp(P_MAX_OBJECTS, 100); // Mehr sollte nicht sein, lt. Tiamak.
+ SetProp(P_VALUE, 0); // Kein materieller Wert. Ist eh nicht verkaufbar.
+ SetProp(P_NOBUY, 1); // Wird im Laden zerstoert, falls er verkauft wird.
+ SetProp(P_NOGET, "Das geht nicht. "+Name(WER,1)+" haftet wie magisch am Boden.\n");
+ SetProp(P_MATERIAL, ({MAT_OAK, MAT_MISC_MAGIC}) );
+ SetProp(P_INFO, "Versuchs mal mit: \"skommandos "+QueryProp(P_IDS)[1]+"\" !\n");
+
+ AD(({"schubladen"}), BS("Es sind viele, aber zum Glueck musst Du sie nicht "
+ +"einzeln ansprechen. Du kannst einfach alles in "+name(WEN,1)+" stecken."));
+ AD(({"moebelstueck"}), BS(Name(WER,1)+" ist gemeint."));
+}
diff --git a/d/seher/haeuser/moebel/kuehlschrank.c b/d/seher/haeuser/moebel/kuehlschrank.c
new file mode 100644
index 0000000..7bf1df4
--- /dev/null
+++ b/d/seher/haeuser/moebel/kuehlschrank.c
@@ -0,0 +1,45 @@
+//--------------------------------------------------------------------------------
+// Name des Objects: Kuehlschrank
+// Letzte Aenderung: 17.03.2001
+// Magier: Swift
+//--------------------------------------------------------------------------------
+#pragma strong_types,rtt_checks
+
+#include "schrankladen.h"
+inherit LADEN("swift_std_container");
+
+#define VERSION_OBJ "3"
+
+protected void create()
+{
+ if (!clonep(TO)) return;
+ swift_std_container::create();
+ SetProp(P_SHORT, "Ein Kuehlschrank");
+ SetProp(P_LONG, BS(
+ "Dieser strahlendweisse Kuehlschrank der Firma Brosch ueberzeugt durch "
+ +"ein leises Summen von seiner Funktion, auch wenn Du nicht weisst, woher "
+ +"er den Strom dafuer nimmt. Vermutlich auf magische Weise. Aber Du kennst "
+ +"das ja, mit Magie laesst sich fast alles erklaeren. Gut dass der "
+ +"Kuehlschrank so gross ist, man koennte einen ausgewachsenen Eisbaeren "
+ +"darin unterbringen - aber der duerfte wohl was dagegen haben.")
+ +"@@cnt_status@@");
+ AddId(({"kuehlschrank", "schrank"}));
+ SetProp("cnt_version_obj", VERSION_OBJ);
+ SetProp(P_NAME, "Kuehlschrank");
+ SetProp(P_GENDER, MALE);
+ SetProp(P_WEIGHT, 5000); // Gewicht 5 Kg
+ SetProp(P_MAX_WEIGHT, 1000000); // Es passen fuer 1000 kg Sachen rein.
+ SetProp(P_WEIGHT_PERCENT, 100); // Dafuer macht er auch nix leichter :)
+ SetProp(P_MAX_OBJECTS, 100); // Mehr sollte nicht sein, lt. Tiamak.
+ SetProp(P_VALUE, 0); // Kein materieller Wert. Ist eh nicht verkaufbar.
+ SetProp(P_NOBUY, 1); // Wird im Laden zerstoert, falls er verkauft wird.
+ SetProp(P_NOGET, "Das geht nicht. "+Name(WER,1)+" haftet wie magisch am Boden.\n");
+ SetProp(P_MATERIAL, ({MAT_MISC_METAL, MAT_MISC_MAGIC}) );
+ SetProp(P_INFO, "Versuchs mal mit: \"skommandos "+QueryProp(P_IDS)[1]+"\" !\n");
+
+ AD(({"strom"}), BS("Keine Ahnung, wo "+name(WER,1)+" den hernimmt, aber "
+ +"wie gesagt, bestimmt ist Magie im Spiel."));
+
+ AddSounds(({"summen"}), BS("Das Summen des Kuehlschranks ueberzeugt Dich davon, "
+ +"dass er an ist."));
+}
diff --git a/d/seher/haeuser/moebel/lesepult.c b/d/seher/haeuser/moebel/lesepult.c
new file mode 100644
index 0000000..4eb8300
--- /dev/null
+++ b/d/seher/haeuser/moebel/lesepult.c
@@ -0,0 +1,559 @@
+// Einiger Code wurde aus dem Questtagebuch des Tempels uebernommen.
+// Da man das Buch, sobald es im aufgestellten Lesepult des Spielers
+// abgelegt wurde, auch lesen koennen muss, sind die Funktionen und
+// Details auch weiterhin sinnvoll. Kaufen kann es jeder Seher, aber
+// nutzen kann man es nur mit dem von Hels Avatar ueberreichten Buch.
+
+#include <properties.h>
+#include <moving.h>
+#include <language.h>
+#include <wizlevels.h>
+#include "/d/seher/haeuser/moebel/moebel.h"
+#include "/d/seher/haeuser/haus.h"
+#include "/d/anfaenger/ark/knochentempel/files.h"
+#pragma strong_types,rtt_checks
+
+inherit LADEN("swift_std_container");
+
+static string owner;
+string le(string key);
+string in(string key);
+int cmd_eintragen(string str);
+int cmd_lesen(string str);
+int take_page(string str);
+int drop_book(string str);
+int cmd_blaettern(string str);
+int cmd_oeffnen(string str);
+int cmd_schliessen(string str);
+void AddTheOldDetails();
+
+protected void create()
+{
+ if(!clonep(this_object()))
+ {
+ set_next_reset(-1);
+ return;
+ }
+
+ ::create();
+
+owner="Anonymus";
+
+AddDetail("finger",BS(
+"Deine Finger sollten schon vorsichtig sein, wenn sie das Zeder"+
+"nholz beruehren. Einerseits, damit Du Dich nicht verletzt, and"+
+"ererseits, damit Du nichts beschmutzt.",78));
+AddDetail(({"holz","zedernholz","zeder"}),BS(
+"Aus einem einzigen starken Stamm einer Zeder bearbeitet, ist d"+
+"ieses edle Lesepult schon etwas sehr Feines und Dekoratives.",78));
+AddDetail(({"stamm","zedernstamm","holzstamm"}),BS(
+"Der Zedernstamm ist wahrlich kunstvoll veredelt worden, sein k"+
+"raeftiges Braun wurde hervorragend zur Geltung gebracht.",78));
+AddDetail(({"braun","dunkelbraun"}),BS(
+"Der dunkelbraune Stamm glaenzt wunderschoen, wenn Licht auf ih"+
+"n faellt. Ein sehr angenehmes Holz, das fuer das Lesepult verw"+
+"endet wurde.",78));
+AddDetail("geltung",BS(
+"Ja, dieses Holz gefaellt Dir sehr, das ganze Pult ist ein beme"+
+"rkenswertes Kunstwerk.",78));
+AddDetail(({"kunst","werk","kunstwerk"}),BS(
+"Immer wieder faellt Dein bewundernder Blick auf das Lesepult.",78));
+AddDetail("blick",BS(
+"Wachsam und flink wie immer, hat er jedoch ein wenig pausiert,"+
+" indem er muessig auf dem Lesepult ruht.",78));
+AddDetail(({"feines","dekoratives"}),BS(
+"Das teilweise eckige und dann wieder sanft geschwungene, runde"+
+" Lesepult sieht schon ziemlich repraesentativ aus.",78));
+AddDetail("zeder",BS(
+"Von ihr ist nurmehr das Pult geblieben, allerdings findest Du,"+
+" dass es nicht der schlechteste Teil ist.",78));
+AddDetail("teil",BS(
+"Du siehst nur den bearbeiteten Teil der Zeder vor Dir.",78));
+AddDetail("exemplar",BS(
+"Es ist ganz klar zu sehen, dass es sich nur um eine Zeder hand"+
+"elt, aus der dieses Pult entstand.",78));
+AddDetail(({"handwerk","kunst"}),BS(
+"Tatsaechlich ist dieses Lesepult ein sehr schoenes Beispiel ho"+
+"echster handwerklicher Kunst.",78));
+AddDetail("beispiel",BS(
+"Ein weiteres steht hier dummerweise nicht herum.",78));
+
+ SetProp("cnt_version_obj","1");
+ SetProp(P_NAME,"Lesepult");
+ SetProp(P_GENDER,NEUTER);
+ SetProp(P_NEVERDROP,1);
+ SetProp(P_VALUE,10);
+ SetProp(P_WEIGHT,500000);
+ SetProp(P_NOGET,"Das Lesepult ist Dir viel zu schwer.\n");
+ SetProp(P_NOSELL,"Du behaeltst das Lesepult lieber.\n");
+ SetProp(P_MATERIAL,([MAT_CEDAR:100]));
+ SetProp(H_FURNITURE,1);
+ SetProp(P_INFO,BS(
+ "Auf dieses Lesepult kann man ein ganz bestimmtes schwarzes Bu"+
+ "ch legen. Dort liegt es perfekt, um darin zu blaettern und zu"+
+ " lesen. Ausserdem birgt es sicher noch Geheimnisse.",78));
+
+ AddId(({"pult","lesepult","\nlesepult_ark"}));
+
+ AddCmd("eintragen&quest|aufgabe|loesung|erlebnis|abenteuer",
+ #'cmd_eintragen,"Was willst Du hier denn eintragen ?\n");
+ AddCmd(({"lies","lese","les"}),#'cmd_lesen);
+ AddCmd("nimm",#'take_page);
+ AddCmd(({"lege","leg"}),#'drop_book);
+ AddCmd("blaetter|blaettre|blaettere&in&buch|tagebuch|"
+ "tempeltagebuch",#'cmd_blaettern,"Worin willst Du blaettern ?|"
+ "Willst Du im Tagebuch blaettern ?");
+ AddCmd("oeffne&@ID|buch|tagebuch|tempeltagebuch",#'cmd_oeffnen,
+ "Was willst Du oeffnen?\n");
+ AddCmd("schliesse|schliess&@ID|buch|tagebuch|tempeltagebuch",
+ #'cmd_schliessen,"Was willst Du schliessen?\n");
+
+ if (MQTBMASTER->QueryTagebuchAufPult(this_player()))
+ AddTheOldDetails();
+}
+
+void SetOwner(string str)
+{
+ owner=str;
+}
+
+string QueryOwner()
+{
+ return owner;
+}
+
+string _query_short()
+{
+ if ((owner=="Anonymus")||
+ !this_player()||
+ !(MQTBMASTER->QueryTagebuchAufPult(this_player())))
+ return "Ein wunderschoenes Lesepult aus dunkelbraunem Zedernholz";
+ if (getuid(this_player())==owner)
+ return
+ "Ein wunderschoenes Lesepult, auf dem Dein Tagebuch des Tempels ruht";
+ else return
+ "Ein wunderschoenes Lesepult, das ein gueldenes Buch traegt";
+}
+
+string _query_long()
+{
+ if ((owner=="Anonymus")||
+ !this_player()||
+ !(MQTBMASTER->QueryTagebuchAufPult(this_player())))
+ return BS(
+ "Vorsichtig faehrst Du mit den Fingern ueber das dunkelbraune Holz."+
+ " Was Du spuerst, fuehlt sich kuehl und angenehm an, die Zeder, die"+
+ " fuer dieses bestaunenswerte Lesepult herhalten musste, wurde vors"+
+ "ichtig und aeusserst kunstfertig bearbeitet. Ein wirklich schoenes"+
+ " Exemplar holzhandwerklicher Kunst.",78);
+ if (getuid(this_player())==owner)
+ {
+ if (MQTBMASTER->QueryTagebuchAufPult(this_player()))
+ return BS(
+ "Vorsichtig faehrst Du mit den Fingern ueber das dunkelbraune Holz"+
+ ". Was Du spuerst, fuehlt sich kuehl und angenehm an, die Zeder, d"+
+ "ie fuer dieses bestaunenswerte Lesepult herhalten musste, wurde v"+
+ "orsichtig und aeusserst kunstfertig bearbeitet. Ein wirklich scho"+
+ "enes Exemplar holzhandwerklicher Kunst, Du bist froh, dieses Lese"+
+ "pult erstanden zu haben. Auf dem Lesepult siehst Du Dein schwarze"+
+ "s Tagebuch des Knochentempels, in dem Du nun nur noch lesen kanns"+
+ "t, denn Deine Abenteuer dort sind vollstaendig zu Papier gebracht"+
+ ". Allerdings kannst Du auch noch ein wenig weiter drin herumblaet"+
+ "tern, wenn Du magst.",78);
+ return BS(
+ "Vorsichtig faehrst Du mit den Fingern ueber das dunkelbraune Holz"+
+ ". Was Du spuerst, fuehlt sich kuehl und angenehm an, die Zeder, d"+
+ "ie fuer dieses bestaunenswerte Lesepult herhalten musste, wurde v"+
+ "orsichtig und aeusserst kunstfertig bearbeitet. Ein wirklich scho"+
+ "enes Exemplar holzhandwerklicher Kunst, Du bist froh, dieses Lese"+
+ "pult erstanden zu haben. Ein wenig gruebeln laesst Dich die Tatsa"+
+ "che, dass das Lesepult leer ist. Was man dort wohl platzieren kan"+
+ "n ?",78);
+ }
+ return BS(
+ "Vorsichtig faehrst Du mit den Fingern ueber das dunkelbraune Holz."+
+ ". Was Du spuerst, fuehlt sich kuehl und angenehm an, die Zeder, di"+
+ "e fuer dieses bestaunenswerte Lesepult herhalten musste, wurde vor"+
+ "sichtig und aeusserst kunstfertig bearbeitet. Ein wirklich schoene"+
+ "s Exemplar holzhandwerklicher Kunst, Du bist ein wenig neidisch."+
+ ""+(MQTBMASTER->QueryTagebuchAufPult(this_player())?" Auf dem Lesep"+
+ "ult wurde ein schwarzes Buch abgelegt, das sehr wertvoll aussieht.":
+ " Das Lesepult sieht ohne dazugehoeriges Buch ein wenig einsam aus.")+".",78);
+}
+
+void AddTheOldDetails()
+{
+ AddDetail(({"buch","buechlein","tagebuch"}),BS(
+ "Dies ist ein kleines Buechlein aus Gold, auf dem ein Name in "+
+ "schwarzen Lettern steht. Ansonsten ist der Einband schlicht, "+
+ "das Papier schon ausfuehrlich beschrieben und vom vielen Blae"+
+ "ttern hier und da auch schon ein wenig geknickt.",78));
+ AddDetail("blaettern",BS(
+ "Ja, das schoene Buechlein ist von haeufigem Blaettern nicht s"+
+ "choener geworden, aber irgendetwas Magisches hat es schon an "+
+ "sich. Ab und an magst Du immer wieder einmal herumblaettern.",78));
+ AddDetail("magisches",BS(
+ "Es ist nicht so einfach zu ergruenden, indem man einmal genau"+
+ "er hinsieht.",78));
+ AddDetail("leder",BS(
+ "Das Leder ist glatt und vollkommen guelden. Nur die schwarzen"+
+ " Lettern geben einen angenehmen Kontrast ab. Irgendwie seltsa"+
+ "m, denn Du findest, dass Schwarz und Gold eigentlich umgekehr"+
+ "t mehr Sinn machen.",78));
+ AddDetail("sinn",BS(
+ "Vielleicht ist aber auch alles bestens, und nur Dein Verstand"+
+ " will das nicht nachvollziehen.",78));
+ AddDetail("verstand",BS(
+ "Ja, auch Du kannst ihm nicht immer folgen, also wundere Dich "+
+ "nicht, warum dieses Leder hier golden verfaerbt ist und die B"+
+ "uchstaben darauf schwarz.",78));
+ AddDetail(({"lettern","buchstaben"}),BS(
+ "Du kannst sie lesen.",78));
+ AddDetail(({"name","namen"}),BS(
+ "Man kann ihn genauso lesen wie die Buchstaben.",78));
+ AddDetail("kontrast",BS(
+ "Die Buchstaben heben sich wirklich deutlich vom gueldenen Led"+
+ "er des Einbands ab.",78));
+ AddDetail("einband",BS(
+ "Es ist kein aufwaendiger Einband, fuerwahr. Dennoch faszinier"+
+ "t die Pracht, die mit den schwarzen Lettern kontrastiert.",78));
+ AddDetail("pracht",BS(
+ "So muss man den goldenen Einband wohl nennen.",78));
+ AddDetail(({"papier","seiten","buchseiten","seite","buchseite"}),BS(
+ "Das Papier ist von guter Qualitaet, die Buchseiten lassen sic"+
+ "h sicher einfach beschreiben.",78));
+ AddDetail(({"schwarze buchseiten","schwarze buchseite",
+ "schwarze buchseite"}),BS(
+ "Tatsaechlich, beim Blaettern siehst Du einige schwarze Buchse"+
+ "iten, die unbeschrieben sind. Was hat dies zu bedeuten ?",78));
+ AddDetail("qualitaet",BS(
+ "Du siehst, dass das Papier fest und bluetenweiss ist.",78));
+ AddReadDetail(({"buch","buechlein","tagebuch"}),BS(
+ "Das Buch hat ein Inhaltsverzeichnis. Wenn dort etwas steht, k"+
+ "annst Du das oder die Kapitel sicher lesen.",78));
+ AddDetail("kapitel",BS(
+ "Lies nur im Inhaltsverzeichnis nach, vielleicht hat das Buch "+
+ "bereits ein oder mehrere Kapitel.",78));
+ AddReadDetail("kapitel",BS(
+ "Welches Kapitel willst Du denn lesen ? Sie sind sicher durchn"+
+ "ummeriert, wenn man schon etwas im Buch niedergeschrieben hat.",78));
+ AddReadDetail(({"name","namen","buchstaben","lettern"}),#'le);
+ AddReadDetail(({"inhalt","inhaltsverzeichnis"}),#'in);
+ SetProp(P_MATERIAL,([MAT_LEATHER:10,MAT_PAPER:15,MAT_CEDAR:75]));
+}
+
+int drop_book(string str)
+{
+ if (!stringp(str))
+ return 0;
+ if (strstr(lower_case(str),"pult",0)==-1)
+ return 0;
+ notify_fail(BS(
+ "Willst Du etwas auf das Pult legen ? Ein Buch waere passend, "+
+ "aber es sollte schon etwas Besonderes sein.",78));
+ if (strstr(lower_case(str),"buch",0)==-1&&
+ strstr(lower_case(str),"buechlein",0)==-1)
+ return 0;
+ notify_fail(BS(
+ "Das ist nicht Dein Lesepult, Du laesst es besser in Ruhe.",78));
+ if (getuid(this_player())!=owner)
+ return 0;
+ notify_fail(BS(
+ "Auf dem Pult liegt schon ein goldenes Buch.",78));
+ if (MQTBMASTER->QueryTagebuchAufPult(this_player()))
+ return 0;
+ notify_fail(BS(
+ "Entweder hast Du Dich noch nicht als wuerdig erwiesen, indem "+
+ "Du alle Aufgaben im Knochentempel erfuellt hast oder Du hast "+
+ "dem Avatar des Waechters der Nacht, Mhun'dae Hel, noch nicht "+
+ "Deine Aufwartung gemacht und ihm gezeigt, dass Du wuerdig bis"+
+ "t, ein geeignetes Buch zu empfangen. Auf alle Faelle kannst D"+
+ "u hier noch nichts auf das Pult legen.",78));
+ if (!present_clone(OBJ("buechlein_invers"),this_player()))
+ return 0;
+ MQTBMASTER->AddBuchAufPult(this_player());
+ this_player()->ReceiveMsg(BS(
+ "Vorsichtig schlaegst Du Dein gueldenes Tagebuch auf, das Dir "+
+ "Mhun'dae Hel, das Avatar des Waechters der Nacht, ueberreicht"+
+ " hat. Du legst es sachte auf das Pult und merkst, dass es sof"+
+ "ort eine magische Verbindung mit dem Lesepult eingeht. Es ist"+
+ " nun untrennbar mit diesem verbunden.",78),MT_MAGIC,MA_USE);
+ tell_room(environment(),BS(
+ this_player()->Name(WER)+" legt vorsichtig ein gueldenes Buch "+
+ "mit schwarzen Lettern aufgeschlagen auf dem Lesepult ab und b"+
+ "etrachtet dieses dann ehrfuerchtig und zutiefst zufrieden.",78),
+ ({this_player()}));
+ return 1;
+}
+
+int cmd_blaettern(string str)
+{
+ notify_fail(BS(
+ "Auf dem Lesepult liegt doch gar kein Tagebuch.",78));
+ if (!(MQTBMASTER->QueryTagebuchAufPult(find_player(owner))))
+ return 0;
+ notify_fail(BS(
+ "Das ist nicht Dein Tagebuch, Du laesst es lieber in Frieden.",78));
+ if (getuid(this_player())!=owner)
+ return 0;
+ this_player()->ReceiveMsg(BS(
+ "Du blaetterst ein wenig durch Dein Tagebuch und stoesst auf e"+
+ "inige raetselhafte schwarze Seiten. Was mag es damit auf sich"+
+ " haben ? Ob Du sie herausnehmen kannst ?",78),MT_LOOK,MA_LOOK);
+ return 1;
+}
+
+int take_page(string str)
+{
+ if (!stringp(str))
+ return 0;
+ if (present(str,environment()))
+ return 0;
+ notify_fail(BS(
+ "Wo siehst Du denn hier ein Buch ?",78));
+ if (!(MQTBMASTER->QueryTagebuchAufPult(this_player()))&&
+ strstr(lower_case(str),"buch")!=-1)
+ return 0;
+ if ((owner!=getuid(this_player()))&&
+ strstr(lower_case(str),"buch")!=-1)
+ notify_fail(BS(
+ "Dies ist nicht Dein Lesepult oder Dein Buch darauf, deshalb l"+
+ "aesst Du es vorsichtshalber liegen.",78));
+ return 0;
+ if ((owner!=getuid(this_player()))&&
+ strstr(lower_case(str),"seite")!=-1)
+ notify_fail(BS(
+ "Die Eigentuemerin oder der Eigentuemer des Lesepults haette s"+
+ "icher etwas dagegen, wenn Du das Buch zerstoerst, also laesst"+
+ " Du es lieber.",78));
+ return 0;
+ // Heilung 1x alle 6 Stunden.
+ if (this_player()->check_and_update_timed_key(21600,"Ark_Hels_Schwarzes_Buch")==-1)
+ {
+ object o;
+ this_player()->ReceiveMsg(BS(
+ "Du reisst erst vorsichtig eine schwarze Seite und dann eine"+
+ " weitere aus dem goldenen Buch. Dann ueberfaellt Dich eine "+
+ "kleine Schwaeche, die Dich vor weiterem Zerstoeren innehalt"+
+ "en laesst. Du solltest Hels Grosszuegigkeit nicht ueberscha"+
+ "etzen.",78),MT_FEEL,MA_TAKE);
+ tell_room(environment(),BS(
+ this_player()->Name(WER)+" reisst zwei Seiten aus dem Buch, "+
+ "das auf dem Pult liegt. Dann haelt "+this_player()->QueryPronoun(WER)+""+
+ " inne, wahrscheinlich folgt "+this_player()->QueryPronoun(WER)+""+
+ " einer klugen Eingebung.",78));
+ o=clone_object(OBJ("reg_seite"));
+ if (o->move(this_player())!=MOVE_OK)
+ {
+ o->remove(1);
+ this_player()->ReceiveMsg(BS(
+ "Du kannst die erste Seite nicht mehr tragen, sie loest sic"+
+ "h einfach auf.",78),MT_MAGIC,MA_REMOVE);
+ }
+ // Die erste Seite behandelt, hier, falls man auch die zweite
+ // Seite nicht tragen kann oder mit der ersten am Limit ist.
+ o=clone_object(OBJ("reg_seite"));
+ if (o->move(this_player())!=MOVE_OK)
+ {
+ o->remove(1);
+ this_player()->ReceiveMsg(BS(
+ "Du kannst die zweite Seite nicht mehr tragen, sie loest si"+
+ "ch einfach auf.",78),MT_MAGIC,MA_REMOVE);
+ }
+ return 1;
+ }
+ this_player()->ReceiveMsg(BS(
+ "Vergeblich reisst Du mehr oder weniger vorsichtig an einigen"+
+ " schwarzen Seiten im Buch herum, doch sie bleiben stoerrisch"+
+ ". Es wird wohl ein wenig dauern, bis Du das wieder versuchen"+
+ " kannst.",78),MT_MAGIC,MA_USE);
+ tell_room(environment(),BS(
+ this_player()->Name(WER)+" reisst im Buch auf dem Lesepult he"+
+ "rum.",78),({this_player()}));
+ return 1;
+}
+
+int cmd_lesen(string str)
+{
+int k;
+ if(!str) return 0;
+ if (owner=="Anonymus")
+ {
+ write (BS(
+ "Dieses Lesepult scheint niemandem zu gehoeren ... es loest s"+
+ "ich daher einfach auf, als Du darauf etwas lesen willst.",78));
+ remove(1);
+ return 1;
+ }
+ if (getuid(this_player())!=owner)
+ {
+ notify_fail(BS(
+ "Dieses Tagebuch gehoert "+capitalize(owner)+", nicht Dir, Du"+
+ " bist eigentlich nicht so recht an dem interessiert, was man"+
+ " in dem Buch niedergeschrieben hat. Sicher ist es uebertrieb"+
+ "en langatmig formuliert und stimmt nicht genau mit dem ueber"+
+ "ein, was wirklich geschah. Man kennt das ja.",78));
+ return 0;
+ }
+ if (strstr(lower_case(str),"kapitel",0)!=-1&&
+ sscanf(lower_case(str),"kapitel %d",k)!=1)
+ {
+ write (BS(
+ "Willst Du ein Kapitel aus dem Buch lesen ? Dann gib bitte ei"+
+ "ne Ziffer an.",78));
+ return 1;
+ }
+ if (k>0)
+ {
+ MQTBMASTER->LiesQuest(k,this_player());
+ return 1;
+ }
+ return 0;
+}
+
+int cmd_eintragen(string str)
+{
+int i;
+ if (!(MQTBMASTER->QueryTagebuchAufPult(this_player())))
+ {
+ notify_fail(BS(
+ "Du findest hier nichts, worin Du etwas eintragen koenntest.",78));
+ return 0;
+ }
+ if (getuid(this_player())!=owner)
+ {
+ notify_fail(BS(
+ "Dieses Tagebuch gehoert "+capitalize(owner)+", nicht Dir, Du"+
+ " kannst darin nichts eintragen.",78));
+ return 0;
+ }
+ notify_fail(BS(
+ "Deine Missionen im Knochentempel ... besser gesagt, dem Wyrmt"+
+ "empel, sie sind allesamt tapfer von Dir erfuellt worden. Du k"+
+ "annst hier nichts weiter mehr eintragen, sicher aber von der "+
+ "arkanen Macht des Buches profitieren, wenn Du es einmal durch"+
+ "blaetterst.",78));
+ return 0;
+}
+
+string calc_name()
+{
+string *nam;
+string res;
+int i,j;
+ res="";
+ if (owner=="")
+ return "";
+ nam=explode(upperstring(owner),"");
+ if (j=sizeof(nam))
+ {
+ switch(j)
+ {
+ case 3..4:
+ res=" ";
+ break;
+ case 5:
+ res=" ";
+ break;
+ case 7:
+ res=" ";
+ break;
+ case 9:
+ res=" ";
+ break;
+ default:
+ res=" ";
+ }
+ for (i=0;i<j;i++)
+ {
+ res+=nam[i]+" ";
+ }
+ }
+ return res;
+}
+
+string le(string key)
+{
+ return "\n"+
+ " De Templum Os Hel\n\n"+
+ calc_name()+"\n\n";
+}
+
+string in(string key)
+{
+ if (owner!=getuid(this_player()))
+ return "Dort steht allerdings nichts. Seltsam.\n";
+ return MQTBMASTER->LiesInhalt(find_player(owner));
+}
+
+// Das hier bezeichnet den Urheber des Moebelstuecks.
+// Nicht meine Idee!
+string GetOwner() { return "Ark"; }
+
+int cmd_oeffnen(string str)
+{
+ if (strstr(lower_case(str),"pult")!=-1)
+ {
+ this_player()->ReceiveMsg(
+ "Du kannst das Pult nicht oeffnen, nur etwas zum Lesen darauflegen.",
+ MT_LOOK,MA_FEEL);
+ return 1;
+ }
+ if (strstr(lower_case(str),"buch")!=-1)
+ {
+ if (!(MQTBMASTER->QueryTagebuchAufPult(this_player())))
+ return 0;
+ this_player()->ReceiveMsg(
+ "Das schwarze Buch ist doch schon geoeffnet.",MT_LOOK,MA_FEEL);
+ return 1;
+ }
+ // Alles andere per Default.
+ return 0;
+}
+
+int cmd_schliessen(string str)
+{
+ if (strstr(lower_case(str),"pult")!=-1)
+ {
+ this_player()->ReceiveMsg(
+ "Du kannst das Pult nicht schliessen.",MT_LOOK,MA_FEEL);
+ return 1;
+ }
+ if (strstr(lower_case(str),"buch")!=-1)
+ {
+ if (!(MQTBMASTER->QueryTagebuchAufPult(this_player())))
+ return 0;
+ this_player()->ReceiveMsg(
+ "Das Buch bleibt trotz Deiner Bemuehungen einfach offen.",MT_LOOK,MA_FEEL);
+ return 1;
+ }
+ else return 0;
+}
+
+mixed _query_noget()
+{
+ if (getuid(this_player())!=owner)
+ return BS(
+ "Dies ist offensichtlich nicht Dein Pult, deshalb laesst "+
+ "Du es auch besser liegen.",78);
+ return 0;
+}
+
+string _query_autoloadobj()
+{
+ return QueryOwner();
+}
+
+string _set_autoloadobj(string s)
+{
+ return QueryOwner();
+}
+
+// Beim Kauf setzen wir erstmal nur den Eigentuemer.
+// Ist aus Swifts Container, der diese Funktion im
+// NotifyMove() aufruft.
+protected void SetBesitzer(string uid, string uuid)
+{
+ SetOwner(uid);
+ MQTBMASTER->AddLesepult(find_player(uid)||find_netdead(uid));
+}
diff --git a/d/seher/haeuser/moebel/moebel.h b/d/seher/haeuser/moebel/moebel.h
new file mode 100644
index 0000000..debc474
--- /dev/null
+++ b/d/seher/haeuser/moebel/moebel.h
@@ -0,0 +1,13 @@
+#ifndef _SEHERMOEBEL_H_
+#define _SEHERMOEBEL_H_
+
+#define LADEN(x) "/d/seher/haeuser/moebel/"+x
+#define RAUM_VOR_LADEN "/d/unterwelt/wurzel/dorf/nstr2"
+#define IDEEN_LOG "ideen.log"
+#define SHVERWALTER "/d/seher/haeuser/hausverwalter"
+#define VERANTWORTLICHER_MAGIER "Seleven"
+// Der Erhaelt Bug-Mails der Spieler!
+#define SCHRANKMASTER load_object(LADEN("schrankmaster"))
+
+#endif // _SEHERMOEBEL_H_
+
diff --git a/d/seher/haeuser/moebel/muellcontainer.c b/d/seher/haeuser/moebel/muellcontainer.c
new file mode 100644
index 0000000..1e95d18
--- /dev/null
+++ b/d/seher/haeuser/moebel/muellcontainer.c
@@ -0,0 +1,92 @@
+//--------------------------------------------------------------------------------
+// Name des Objects: Muellcontainer
+// Letzte Aenderung: 17.03.2001
+// Magier: Swift
+//--------------------------------------------------------------------------------
+
+#include "schrankladen.h"
+inherit LADEN("swift_std_container");
+
+#define VERSION_OBJ ".003"
+
+create()
+{
+ if (!clonep(TO)) return;
+ swift_std_container::create();
+ SetProp(P_SHORT, "Ein Muellcontainer");
+ SetProp(P_LONG, BS(
+ "Ein grosser Container aus Stahl, aus dem es nicht gerade angenehm duftet. "
+ +"Offensichtlich werden dort alle Sachen entsorgt, die Seher nicht gerne in "
+ +"ihrem Haus oder auf der Strasse herumliegen sehen.")
+ +"@@cnt_status@@");
+ AddId(({"muellcontainer", "container"}));
+ SetProp("cnt_version_obj", VERSION_OBJ);
+ SetProp(P_NAME, "Muellcontainer");
+ SetProp(P_GENDER, MALE);
+ SetProp(P_WEIGHT, 5000); // Gewicht 5 Kg
+ SetProp(P_MAX_WEIGHT, 1000000); // Es passen fuer 1000 kg Sachen rein.
+ SetProp(P_WEIGHT_PERCENT, 100); // Dafuer macht er auch nix leichter :)
+ SetProp(P_MAX_OBJECTS, 100); // Mehr sollte nicht sein, lt. Tiamak.
+ SetProp(P_VALUE, 0); // Kein materieller Wert. Ist eh nicht verkaufbar.
+ SetProp(P_NOBUY, 1); // Wird im Laden zerstoert, falls er verkauft wird.
+ SetProp(P_NOGET, "Das geht nicht. "+Name(WER,1)+" haftet wie magisch am Boden.\n");
+ SetProp(P_MATERIAL, ({MAT_STEEL, MAT_MISC_MAGIC}) );
+ SetProp(P_INFO, "Versuchs mal mit: \"skommandos "+QueryProp(P_IDS)[1]+"\" !\n");
+
+ AddSmells(({"container", "duft", "gestank"}), BS("Aus "+name(WEM,1)+" stinkt es "
+ +"schon ganz schoen, aber Deine Nase ist ja allerhand gewoehnt."));
+
+ AddCmd(({"wirf", "werf", "werfe"}), "wegwerfen");
+}
+
+int wegwerfen(string str)
+{
+ string was,inwas;
+ notify_fail("Was willst Du wo hinein werfen?\n");
+ if(!str) return 0;
+ if( sscanf(str, "%s in %s", was, inwas) != 2)
+ return 0;
+ if( present(inwas)==TO ) // Dies Objekt ist gemeint!
+ {
+ TP->command_me("stecke "+str);
+ return 1;
+ }
+ return 0;
+}
+
+varargs int PreventInsert(object ob)
+{
+ if( living(ob) )
+ {
+ write( BS("Lebewesen kannst Du nicht in "+name(WEN,1)+" werfen!"));
+ return 1;
+ }
+ else if( ob->QueryProp(P_VALUE) )
+ {
+ write( BS("Nur Dinge ohne materiellen Wert lassen sich in "
+ +name(WEN,1)+" werfen."));
+ return 1;
+ }
+ else if( ob->QueryProp(P_CURSED) )
+ {
+ write( BS("Verfluchte Dinge kannst Du nicht in "+name(WEN,1)+" werfen!"));
+ return 1;
+ }
+ else
+ return ::PreventInsert(ob);
+}
+
+void reset()
+{
+ int i;
+ object *inv;
+ ::reset();
+ inv=all_inventory(TO);
+ if(inv && sizeof(inv))
+ {
+ for(i=sizeof(inv)-1;i>=0;i--)
+ destruct(inv[i]);
+ tell_room(ETO, BS("Aus "+name(WEM,1)+" ertoent kurz ein Knistern und Knacken, "
+ +"dann ist wieder Ruhe."));
+ }
+}
diff --git a/d/seher/haeuser/moebel/preisliste.txt b/d/seher/haeuser/moebel/preisliste.txt
new file mode 100644
index 0000000..05e7839
--- /dev/null
+++ b/d/seher/haeuser/moebel/preisliste.txt
@@ -0,0 +1,102 @@
+
+=====================================================
+D E R S C H R A E N K E R - P R E I S L I S T E
+=====================================================
+
+Herzlich willkommen im SCHRAENKER. Bei uns finden Sie
+das ideale Mobiliar fuer Ihr Seherhaus. Weg mit der
+Unordnung zuhaus, bringen Sie ihre Ausruestung ueber-
+sichtlich und wohlsortiert in unseren edlen Moebel-
+stuecken unter. Wir hoffen, unsere Auswahl findet
+Ihren Gefallen.
+
+ANMERKUNG: Die Waren, die hier aufgelistet sind, sind NICHT REBOOTFEST !
+ Evtl. werden wir dies zu einem spaeteren Zeitpunkt ins Auge
+ fassen, im Moment ist es nicht so, wir versuchen lieber, die
+ Moebelstuecke zu verbessern, um sie auch an die ungewoehnlichsten
+ Objekte im MorgenGrauen anzupassen.
+
+Art.-Nr. Name Beschreibung Preis
+-----------------------------------------------------------------------------
+ 1 Kommode Eine robuste Kommode aus Eichenholz. Sie 3.799
+ passt in jeden Raum und bietet jede Menge
+ Platz zum Verstauen von Dingen aller Art.
+
+ 2 Kleiderschrank Ein massiver Holzschrank, in dem Sie 5.899
+ Kleider und Ruestungen aller Art unter-
+ bringen koennen. Der Schrank verfuegt
+ ueber ein Kommando zur Auflistung von
+ Ruestungstypen.
+
+ 3 Spind Ein grosser, einfacher Stahlschrank. Darin 5.299
+ lassen sich Kleider und Ruestungen aller
+ Art unterbringen. Der Spind verfuegt ueber
+ ein Kommando zur Auflistung von Ruestungs-
+ typen.
+
+ 4 Kuehlschrank Ein strahlendweisser Kuehlschrank aus dem 3.499
+ Hause Brosch. Passt in jede Kueche. Darin
+ bleiben Ihre Speisen und Getraenke frisch!
+
+ 5 Waffenschrank Ein massiver Holzschrank mit Faechern fuer 5.899
+ Waffen aller Art. Jede Waffengattung hat
+ ihren einenen Platz, es gibt ein Kommando
+ zur Auflistung von Waffentypen.
+
+ 6 Waffentruhe Eine Stahltruhe mit verschiedenen Faechern 5.399
+ zur Aufnahme von Waffen aller Art. Die
+ Truhe verfuegt ueber ein Kommando zur
+ Auflistung von Waffentypen.
+
+ 7 Tresor Sichern Sie Ihr Vermoegen gegen Einbruch 4.499
+ und Diebstahl. Wie? Ganz einfach: Mit
+ diesem stabilen, feuersicheren Tresor
+ sind Ihre Wertsachen sicher.
+
+ 8 Zauberkiste Sind Sie Zauberer? Oder einfach nur Sammler 7.999
+ hier von Zauberer-Komponenten? Dann haben
+ wir ein Moebelstueck fuer Sie, das Sie haben
+ muessen! Aus magischem Birnbaumholz gefertigt.
+
+ 9 Muellcontainer Der Ersatz fuer den Muellschlucker. 999
+ Nie mehr brauchen Sie einen Laden aufsuchen,
+ nur um wertlosen Plunder loszuwerden.
+
+10 Schluesselbrett Sie haben durch Ihre Abenteuer einen Sack 499
+ voll Schluessel? Dieses Brett schafft
+ Ordnung.
+
+11 Duschkabine Endlich auch fuer Ihr Zuhause: 3.499
+ Eine ultramoderne Waschgelegenheit. Sie
+ koennen sogar selbst einstellen, womit Sie
+ Sich waschen wollen!
+
+12 mag. Holztruhe Haben auch Sie Probleme mit einem ueber- 74.999
+ vollen Inventar? Wir haben jetzt die
+ Loesung fuer Sie: diese kleine Holztruhe
+ nimmt ihre ewigen Objekte auf und
+ bewahrt sie sicher ueber den naechsten
+ Weltuntergang hinaus auf!
+
+13 Vitrine Gehoeren Sie auch zu den tapferen Helden, 49.999
+ die sich bereits Pokale verdient haben?
+ Dann sollten Sie sich diese Vitrine
+ zulegen, damit Ihre Pokale eine passende
+ Umgebung erhalten und auch beim Welt-
+ untergang geschuetzt sind.
+
+14 Lesepult Das hat man sich redlich verdient! Eine 60.000
+ schoene Belohnung, wenn man schliesslich
+ den knoechernen Tempel mal so richtig
+ aufgeraeumt hat. Und zwar vollstaendig,
+ so dass selbst der Totengott staunt.
+ Endlich koennen Sie, wenn er es denn dann
+ auch zufrieden ist, das Tagebuch hierauf
+ ablegen und in aller Ruhe blaettern.
+-----------------------------------------------------------------------------
+Anm. der Geschaeftsleitung:
+Wir bemuehen uns, Ihrem Geschmack und Ihren Beduerfnissen gerecht zu werden.
+Falls Sie Verbesserungsvorschlaege haben, oder falls Sie Moebelstuecke fuer Ihr
+Haus in unserem Angebot vermissen, so setzen Sie doch bitte eine entsprechende
+Idee im Laden ab.
+-----------------------------------------------------------------------------
diff --git a/d/seher/haeuser/moebel/schluesselbrett.c b/d/seher/haeuser/moebel/schluesselbrett.c
new file mode 100644
index 0000000..93bace6
--- /dev/null
+++ b/d/seher/haeuser/moebel/schluesselbrett.c
@@ -0,0 +1,679 @@
+//---------------------------------------------------------------------------
+// Name des Objects: Schluesselbrett
+// Letzte Aenderung: 02.06.2001
+// Original: Swift
+// Neue Version: Seleven
+// Übernommen: 23.01.2006
+//---------------------------------------------------------------------------
+/* Changelog
+ * 21.06.2007, Zesstra
+ im inherit abs. Pfad durch LADEN(x) ersetzt.
+ * 01.07.2007, Zesstra
+ GetOwner() definiert.
+ * 11.05.2015, Arathorn
+ weitraeumig ueberarbeitet zur Behebung von Fehlfunktionen
+*/
+#pragma strong_types, rtt_checks
+
+#include "/d/seher/haeuser/moebel/schrankladen.h"
+#include <ansi.h>
+inherit LADEN("swift_std_container");
+
+#define VERSION_OBJ "3"
+// Zur Indizierung des Mappings <haken>
+#define HOOK_OB 0
+#define HOOK_LABEL 1
+
+private varargs string KeyDescription(int keynum);
+private int IsValidKey(object ob);
+private int GetNextFreeSlot();
+private object GetKeyForLabel(string label);
+private int GetHookNumberForKey(object ob);
+private void ConsolidateInventory();
+
+// Struktur: ([ haken_nr : objekt; beschriftung ])
+private mapping haken=([:2]);
+private int hooklist_long = 0;
+
+protected void create() {
+ if (!clonep(TO)) {
+ set_next_reset(-1);
+ return;
+ }
+ ::create();
+
+ foreach(int i: 1..16) {
+ m_add(haken, i);
+ }
+
+ // DEBUG! Sonst funktioniert's ausserhalb von Seherhaeusern nicht.
+ SetProp("test",1);
+ SetProp(P_SHORT, "Ein Schluesselbrett");
+ Set(P_LONG, function string () {
+ string text = BS(
+ "Ein kleines Brett aus Holz, an dem in 2 Reihen je 8 Haken befestigt "
+ "sind, an die man insgesamt 16 Schluessel haengen kann. Um die "
+ "Uebersicht nicht zu verlieren, befindet sich ueber jedem der Haken "
+ "ein kleines Schildchen aus Schiefer, das sich beschriften laesst. "
+ "Auf diese Weise geht der Sinn und Zweck des Schluessels, der an "
+ "diesem Haken ruht, nicht verloren. Praktischerweise haengt an einer "
+ "Schnur ein Stueck Kreide von dem Brett herab, mit dem Du die "
+ "Schildchen beschriften kannst.");
+ text += KeyDescription(0);
+ return text;
+ }, F_QUERY_METHOD);
+
+ AddId(({"schluesselbrett","brett"}));
+ SetProp("cnt_version_obj", VERSION_OBJ);
+ SetProp(P_CNT_STATUS, 0);
+ SetProp(P_NAME, "Schluesselbrett");
+ SetProp(P_GENDER, NEUTER);
+ SetProp(P_WEIGHT, 1000); // Gewicht 1 Kg
+ SetProp(P_MAX_WEIGHT, 1000000); // Es passen fuer 1000 kg Sachen rein.
+ SetProp(P_WEIGHT_PERCENT, 100); // Dafuer macht er auch nix leichter :)
+ SetProp(P_MAX_OBJECTS, 16);
+ // Man soll nichts ueber den normalen Mechanismus reinstecken oder
+ // rausnehmen koennen. Wird von put_and_get.c geprueft.
+ SetProp(P_CONTAINER, 0);
+ SetProp(P_NOINSERT_MSG, BS("An das Schluesselbrett kannst Du nur "
+ "Schluessel haengen.\nSyntax: 'haenge <schluessel> an brett'."));
+ SetProp(P_NOGET, "Das geht nicht. "+Name(WER,1)+
+ " laesst sich nicht bewegen.\n");
+ SetProp(P_MATERIAL, ({MAT_OAK, MAT_MISC_MAGIC}) );
+ SetProp(P_INFO, "Versuch's mal mit: \"skommandos schluesselbrett\".\n");
+
+ AD(({"holz"}), BS("Echte, robuste Eiche."));
+
+ RemoveCmd(({"schliesse","schliess","oeffne"}));
+
+ AddCmd(({"unt", "untersuche", "betrachte", "betracht", "betr",
+ "schaue", "schau"}), "unt_haken");
+ AddCmd(({"haeng", "haenge"}), "schluessel_an_haken_haengen");
+ AddCmd(({"nimm"}), "schluessel_von_haken_nehmen");
+ AddCmd("sbeschrifte", "cmd_beschriften");
+ AddCmd("sliste", "cmd_sliste");
+}
+
+/***** KOMMANDOFUNKTIONEN *****/
+
+// Konfiguration der Schluesselliste, entweder "alle" anzeigen oder nur die
+// belegten Haken.
+static int cmd_sliste(string str) {
+ notify_fail("Syntax: 'sliste alle|belegte'.\n");
+ if ( !stringp(str) || !sizeof(str) )
+ return 0;
+
+ if ( str == "alle" ) {
+ if ( !hooklist_long ) {
+ tell_object(TP, BS("Ok, es werden jetzt immer alle Haken "
+ "aufgelistet."));
+ hooklist_long = 1;
+ }
+ else
+ tell_object(TP, BS("Die Einstellung war schon 'alle'."));
+ }
+ else if ( str == "belegte" ) {
+ if ( hooklist_long ) {
+ tell_object(TP, BS("Ok, es werden jetzt nur die belegten Haken "
+ "aufgelistet."));
+ hooklist_long =0;
+ }
+ else
+ tell_object(TP, BS("Die Einstellung war schon 'belegte'."));
+ }
+ else
+ return 0;
+ return 1;
+}
+
+// Haken untersuchen. Ohne Angabe der Nummer werden alle ausgegeben,
+// ansonsten der gewuenschte, sofern es diesen gibt.
+static int unt_haken(string str) {
+ if ( !stringp(str) || !sizeof(str) || strstr(str, "haken") == -1 )
+ return 0;
+
+ int hakennr;
+ if ( sscanf(str, "haken %d", hakennr) != 1 ) {
+ string det = KeyDescription(hakennr);
+ tell_object(TP, sizeof(det) ? det : "Die Haken sind alle leer.\n");
+ return 1;
+ }
+
+ notify_fail("Welchen Haken moechtest Du untersuchen? Es gibt nur die "
+ "Haken 1 bis 16.\n");
+ if( hakennr<1 || hakennr > 16 )
+ return 0;
+
+// ausgabe_haken(hakennr);
+ tell_object(TP, KeyDescription(hakennr));
+ return 1;
+}
+
+// Schluessel aufhaengen.
+static int schluessel_an_haken_haengen(string str) {
+ notify_fail("Was willst Du woran haengen?\n");
+ if(!stringp(str) || !sizeof(str))
+ return 0;
+
+ notify_fail("Das darfst Du nicht.\n");
+ if(!erlaubt())
+ return 0;
+
+ string was, woran;
+ notify_fail("Folgende Syntax versteht Dein Schluesselbrett:\n"
+ " \"haenge <schluesselname> an haken [nr]\" oder\n"
+ " \"haenge <schluesselname> an [schluessel]brett\".\n");
+ if ( sscanf(str, "%s an %s", was, woran) != 2 )
+ return 0;
+
+ notify_fail("Was moechtest Du an das Schluesselbrett haengen?\n");
+ if ( !stringp(was) )
+ return 0;
+
+ notify_fail("Woran willst Du das denn haengen?\n");
+ if ( strstr(woran, "haken", 0)==-1 && !id(woran) )
+ return 0;
+
+ // Test, ob es Objekte dieses Namens gibt.
+ object *obs = TP->find_obs(was, PUT_GET_NONE);
+ // Aus der Liste der gefundenen Objekte alle rausfiltern, die keine
+ // Schluessel sind. Als Schluessel gelten hier alle Objekte, die die
+ // ID "schluessel" haben oder die mittels QueryDoorKey() einer bestimmten
+ // Tuer zugeordnet sind.
+ obs = filter(obs, #'IsValidKey);
+ notify_fail("Keine(n) Schluessel mit dem Namen gefunden.\n");
+ if ( !sizeof(obs) )
+ return 0;
+
+ int nr = GetNextFreeSlot();
+ notify_fail("Am Schluesselbrett ist kein Haken mehr frei.\n");
+ if ( !nr )
+ return 0;
+
+ // Wenn nur ein Schluessel gefunden wurde, wird genauer geschaut, ob
+ // der Spieler gesagt hat, wo der hinsoll.
+ if ( sizeof(obs) == 1 ) {
+ if ( woran != "haken" || !id(woran) )
+ sscanf(woran, "haken %d", nr);
+ }
+
+ notify_fail("Es gibt nur die Haken 1 bis 16.\n");
+ if ( nr < 1 || nr > 16 )
+ return 0;
+
+ notify_fail("Der Haken ist nicht mehr frei.\n");
+ if ( objectp(haken[nr,HOOK_OB]) )
+ return 0;
+
+ // Alle gefundenen Schluesselobjekte ans Brett haengen.
+ foreach( object key : obs ) {
+ switch (key->move(ME, M_PUT)) {
+ // Die Kapazitaet ist ueber P_MAX_OBJECTS begrenzt. Alle
+ // Schleifendurchlaeufe, die die Kapazitaetsgrenze erreichen, landen
+ // in default und beenden damit die Schleife. Daher muessen sie
+ // nicht gesondert behandelt werden.
+ case MOVE_OK :
+ // Falls das Brett voll sein sollte, aber faelschlicherweise
+ // dennoch ein weiterer Schluessel hineinbewegt wurde, ist nr==0,
+ // und es wird ein Fehler ausgeloest, damit nicht hinterher ein
+ // Schluessel an Haken 0 haengt.
+ if ( !nr ) {
+ raise_error("Fehler: Haken 0 darf nicht belegt werden.");
+ break;
+ }
+ tell_object(TP, BS("Du haengst "+obs[0]->name(WEN,1)+" an Haken "+
+ nr+"."));
+ // Nur wenn ein Schluessel erfolgreich drangehaengt wurde, wird er
+ // in die Liste eingetragen. Etwaige Beschriftungen bleiben bestehen,
+ haken[nr, HOOK_OB] = key;
+ // und nur dann wird der naechste Slot probiert. Wenn nur ein
+ // Schluessel verarbeitet wird, ist das hier unschaedlich, weil es
+ // nicht nochmal ausgewertet wird.
+ nr = GetNextFreeSlot();
+ // Schluessel wurde verarbeitet und Meldung ausgegeben
+ obs -= ({key});
+ break;
+ case ME_CANT_LEAVE_ENV :
+ case ME_CANT_BE_INSERTED :
+ case ME_CANT_BE_DROPPED :
+ // Schluessel wurde nicht erfolgreich drangehaengt.
+ tell_object(TP, BS(key->Name(WER,1)+" weigert sich, ans "
+ "Schluesselbrett gehaengt zu werden."));
+ // Meldung wurde ausgegeben, nichts weiter zu tun.
+ obs -= ({key});
+ break;
+ // TOO_MANY_OBJECTS wird nicht hier behandelt, sondern weiter unten,
+ // um eine Auflistung der Schluesselnamen ausgeben zu koennen, statt
+ // eine Zeile pro Schluessel. Die anderen Rueckgabewerte von move()
+ // sind bei dieser Art der Bewegung nicht zu erwarten.
+ default: break;
+ }
+ }
+ // Fuer alle uebrigen war wohl TOO_MANY_OBJECTS der Rueckgabewert, denn
+ // das Schluesselbrett erlaubt nur P_MAX_OBJECTS = 16.
+ if ( sizeof(obs) ) {
+ tell_object(TP, BS("Fuer "+CountUp(obs->name(WEN))+" ist leider kein "
+ "Haken mehr am Schluesselbrett frei."));
+ }
+ return 1;
+}
+
+// Schluessel abnehmen
+static int schluessel_von_haken_nehmen(string str) {
+ if( !stringp(str) || !sizeof(str) )
+ return 0;
+
+ string was, woraus;
+ if ( sscanf(str, "%s aus %s", was, woraus) != 2 &&
+ sscanf(str, "%s von %s", was, woraus) != 2 )
+ return 0;
+
+ notify_fail("Das darfst Du nicht!\n");
+ if(!erlaubt())
+ return 0;
+
+ notify_fail("Woraus willst Du das denn nehmen?\n");
+ if ( !id(woraus) && strstr(woraus, "haken", 0) == -1 )
+ return 0;
+
+ notify_fail("Was willst Du denn vom Schluesselbrett nehmen?\n");
+ if( !stringp(was) )
+ return 0;
+
+ notify_fail("Das Schluesselbrett ist doch aber leer.\n");
+ if ( !sizeof(all_inventory(ME)) )
+ return 0;
+
+ int hakennr;
+ object *keys = ({});
+ // Es muessen auch Schluessel von bestimmten Haken abgenommen
+ // werden koennen, nicht nur jeweils der erste mit der angegebenen ID.
+ // Dies hat auch Prio gegenueber der allgemeinen Begriffssuche mit
+ // find_obs().
+ if ( sscanf(woraus, "haken %d", hakennr) == 1 ) {
+ notify_fail("Es gibt nur die Haken 1 bis 16.\n");
+ if ( hakennr < 1 || hakennr > 16 )
+ return 0;
+ notify_fail("An diesem Haken haengt aber doch kein Schluessel.\n");
+ if ( !objectp(haken[hakennr,HOOK_OB]) )
+ return 0;
+
+ keys += ({ haken[hakennr,HOOK_OB] });
+ }
+
+ // Keiner gefunden? Vielleicht ist ja einer mit einer bestimmten
+ // Beschriftung gemeint?
+ if ( !sizeof(keys) ) {
+ // Schluessel mit dem angegebenen Namen suchen
+ keys = TP->find_obs(was+" in brett in raum");
+ // Hakennummer ermitteln, wenn eine Beschriftung angegeben wurde.
+ string wanted_desc;
+ sscanf(was, "schluessel fuer %s", wanted_desc);
+ object wanted_key = GetKeyForLabel(wanted_desc);
+ if ( objectp(wanted_key) )
+ keys += ({wanted_key});
+ }
+ // Immer noch nix gefunden? Dann muss sich der Spieler was anderes
+ // einfallen lassen.
+ notify_fail("Am Schluesselbrett haengt kein solcher Schluessel.\n");
+ if ( !sizeof(keys) )
+ return 0;
+
+ // Alle gefundenen Schluessel verarbeiten. Alle, die nicht bewegt werden
+ // koennen, verbleiben in der Liste.
+ foreach( object key : keys ) {
+ int current_hook = GetHookNumberForKey(key);
+ if ( key->move(TP,M_GET) == MOVE_OK ) {
+ keys -= ({ key });
+ tell_object(TP, BS("Du nimmst "+key->name(WEN,1)+" von Haken "+
+ current_hook+" ab."));
+ // Schluessel austragen; bestehende Beschriftungen bleiben erhalten
+ haken[current_hook, HOOK_OB] = 0;
+ }
+ }
+ // Von allen nicht vom Haken genommenen Schluesseln die Namen ermitteln
+ // und auflisten.
+ if ( sizeof(keys) ) {
+ tell_object(TP, BS(capitalize(CountUp(keys->name(WER,1)))+" "+
+ (sizeof(keys)==1?"konnte":"konnten")+" nicht vom Schluesselbrett "
+ "abgenommen werden."));
+ }
+ return 1;
+}
+
+// Verfuegbare Kommandos auflisten.
+varargs int skommandos(string str) {
+ notify_fail( "Fehler: Dieser Befehl benoetigt eine gueltige Objekt-Id als "
+ +"Parameter.\nBeispiel: skommandos [schluessel]brett\n");
+
+ if( !id(str) ) return 0;
+
+ write(
+ "==================================================================="
+ "==========\n"
+ "Aktuelle Version: "+QueryProp("cnt_version_std")+
+ QueryProp("cnt_version_obj")+"\n"+
+ BS(Name(WER,1)+" kann nur in diesem Seherhaus verwendet werden, "
+ "da "+QueryPronoun(WER)+" speziell dafuer gekauft wurde. "+
+ CAP(QueryPronoun(WER))+" verfuegt ueber folgende Kommandos:")+
+ "----------------------------------------------------------------------"
+ "-------\n"
+ "serlaube [schluessel]brett [spielername|\"hausfreunde\"|\"zweities\"]\n"
+ " Erlaubt Personen, "+name(WEN,1)+" mitzubenutzen.\n"
+ " serlaube ohne Angabe eines Arguments listet alle Personen mit Zugriff "
+ "auf\n "+name(WEN,1)+" auf.\n\n"
+ "verschiebe [schluessel]brett nach [ausgang]\n"
+ " Damit kannst Du "+name(WEN,1)+" innerhalb Deines Seherhauses "
+ "verschieben.\n\n"
+ "sverstecke [schluessel]brett\n"
+ " Damit machst Du "+name(WEN,1)+" unsichtbar.\n"
+ "shole [schluessel]brett hervor\n"
+ " Damit machst Du "+name(WEN,1)+" wieder sichtbar.\n"
+ "zertruemmer [schluessel]brett\n"
+ " Damit zerstoerst Du das Schluesselbrett.\n"
+ "sbeschrifte haken <nr> mit <text>|nichts\n"
+ " Eine Beschriftung an einem Haken anbringen oder loeschen.\n"
+ "sliste lang|kurz\n"
+ " Schluesselanzeige konfigurieren: alle oder nur belegte auflisten.\n"
+ "haenge <schluesselname> an haken [nr]\n"
+ "haenge <schluesselname> an [schluessel]brett\n"
+ " Damit haengst Du einen Schluessel an das Brett.\n"
+ "nimm schluessel von haken <nr>\n"
+ "nimm <schluesselname> von [schluessel]brett\n"
+ "nimm schluessel fuer <beschriftung> von [schluessel]brett.\n"
+ " Damit nimmst Du einen Schluessel vom Schluesselbrett.\n"
+ "==================================================================="
+ "==========\n");
+ return 1;
+}
+
+static int erlaubnis_liste()
+{
+ if( QueryHausbesitzer() != QueryTP() && !QueryProp("test") )
+ {
+ tell_object(TP, BS("Nur "+QueryHausbesitzer()+" darf Berechtigungen "
+ +name(WESSEN,1)+" abfragen!"));
+ return 1;
+ }
+
+ string *strs;
+ string str =
+ "==================================================================="
+ "==========\n";
+ if ( hauserlaubnis ) {
+ strs = SHVERWALTER->HausProp(LOWER(QueryHausbesitzer()), 2);
+ str += "Folgende Freunde Deines Hauses duerfen "+name(WEN,1)+
+ " mitbenutzen:\n";
+ if(sizeof(strs)) {
+ str += BS(CountUp(strs));
+ }
+ else {
+ str += BS("Du hast keiner Person Zugriff auf Dein Haus gewaehrt...");
+ }
+ }
+ else {
+ str+= BS("Die Freunde Deines Hauses duerfen "+name(WEN,1)+
+ " nicht mitbenutzen.");
+ }
+
+ str +=
+ "-------------------------------------------------------------------"
+ "----------\n";
+
+ if( zweitieerlaubnis!="" ) {
+ if( zweitieerlaubnis==geteuid(TP) )
+ str += BS("Alle Deine Zweities duerfen "+name(WEN,1)+" mitbenutzen.");
+ else
+ str += BS("Alle Zweities von "+CAP(zweitieerlaubnis)+" duerfen "
+ +name(WEN,1)+" mitbenutzen.");
+ str +=
+ "-------------------------------------------------------------------"
+ "----------\n";
+ }
+
+ strs=QueryProp("cnt_erlaubnis");
+
+ if(sizeof(strs)) {
+ str += BS("Folgende sonstige Personen duerfen "+name(WEN,1)+
+ " mitbenutzen:");
+ str += CountUp(strs);
+ }
+ else {
+ str += BS("Es gibt keine sonstigen Personen, die "+name(WEN,1)+
+ " mitbenutzen duerfen.");
+ }
+ str +=
+ "==================================================================="
+ "==========\n";
+
+ return 1;
+}
+
+// Haken beschriften.
+static int cmd_beschriften(string str) {
+ string nfm = "Syntax: sbeschrifte haken <hakennummer> mit "
+ "<text>|nichts\n"
+ "Fuer <text> kannst Du einen beliebigen Text mit bis zu 30 Zeichen "
+ "angeben,\n"
+ "'nichts' loescht die Beschriftung eines Schildes.\n";
+
+ notify_fail("Das darfst Du nicht!\n");
+ if(!erlaubt())
+ return 0;
+
+ string text;
+ int hnr;
+ str = TP->_unparsed_args(0);
+ notify_fail(nfm);
+ if ( !stringp(str) || !sizeof(str) )
+ return 0;
+ if ( sscanf(str,"haken %d mit %s", hnr, text)!=2 )
+ return 0;
+
+ notify_fail("Welchen Haken moechtest Du beschriften?\n"+nfm);
+ if(!hnr)
+ return 0;
+
+ notify_fail("Es gibt nur die Haken 1 bis 16.\n");
+ if ( hnr < 1 || hnr > 16 )
+ return 0;
+
+ notify_fail("Womit moechtest Du den Haken beschriften?\n"+nfm);
+ if( !stringp(text) || !sizeof(text) )
+ return 0;
+
+ notify_fail("Der Text sollte nicht laenger als 30 Zeichen sein.\n");
+ if(sizeof(text) > 30)
+ return 0;
+
+ if ( lower_case(text) == "nichts" ) {
+ if ( stringp(haken[hnr,HOOK_LABEL]) ) {
+ tell_object(TP, BS("Sorgfaeltig wischst Du die Beschriftung des "
+ "Hakens "+hnr+" weg."));
+ haken[hnr,HOOK_LABEL]=0;
+ }
+ else {
+ tell_object(TP, BS("Du musst Dich geirrt haben. Haken "+hnr+" ist "
+ "gar nicht beschriftet."));
+ }
+ }
+ else if ( lower_case(text) == "schluessel" ) {
+ tell_object(TP, BS(
+ "Du solltest Dir etwas Aussagekraeftigeres einfallen lassen."));
+ }
+ else {
+ tell_object(TP, BS("Du beschriftest das Schildchen ueber Haken "+hnr+
+ " mit "+text+"."));
+ tell_room(environment(), BS(
+ TP->Name(WER)+" schreibt etwas ans Schluesselbrett."), ({TP}));
+ haken[hnr,HOOK_LABEL] = text;
+ }
+ return 1;
+}
+
+/***** HILFSFUNKTIONEN *****/
+
+// Beschreibung eines Hakens erzeugen. Wenn <keynum> angegeben wird,
+// wird nur der gesuchte Haken angezeigt, egal ob leer oder nicht.
+// Ansonsten werden die belegten Haken angezeigt, ausser wenn
+// <hooklist_long> gesetzt ist. Dann werden alle Haken aufgelistet.
+private varargs string KeyDescription(int keynum) {
+ string desc="";
+ mapping keylist=([:2]);
+
+ // Liste derHaken auf den/die gesuchten einschraenken.
+ // Nur ein Haken soll angeschaut werden. Dies hat immer Prioritaet,
+ // d.h. auch bei <sliste alle> wird nur ein Haken gelistet.
+ if ( keynum ) {
+ m_add(keylist, keynum, m_entry(haken, keynum)...);
+ }
+ // Wenn <sliste alle> gesetzt ist, alle ausgeben.
+ else if ( hooklist_long ) {
+ keylist = haken;
+ }
+ // Ansonster nur die belegten.
+ else {
+ keylist = filter(haken,
+ function int (int num, <string|object>* values) {
+ return objectp(values[0]);
+ });
+ }
+
+ // Ueber das Mapping mit den selektierten Haken laufen und Ausgaben
+ // erzeugen.
+ foreach(int num : 1..16) {
+ // Hier wird der aktuelle Wert uebersprungen, wenn er nicht enthalten
+ // ist, da die Zuweisung in <key> und <keydesc> auch dann eine 0 ergeben
+ // wuerde, und somit Keys mit leeren Values nicht von nicht existierenden
+ // Keys zu unterscheiden waeren.
+ if ( member(m_indices(keylist), num) == -1 )
+ continue;
+ string keydesc = keylist[num, HOOK_LABEL];
+ object key = keylist[num, HOOK_OB];
+ desc += "Haken " + num + (stringp(keydesc)?" ["+keydesc+"]: " : ": ");
+ desc += (objectp(key) ? key->short() : "leer\n");
+ }
+ return desc;
+}
+
+// Rueckgabewert: 1, wenn es sich um ein Schluesselobjekt handelt, sonst 0.
+// Schluessel werden anhand der ID "schluessel" erkannt oder daran, dass
+// QueryDoorKey() einen Wert zurueckgibt, d.h. dass dieses Objekt eine
+// Standard-Doormaster-Tuer oeffnet.
+private int IsValidKey(object ob) {
+ return (objectp(ob) && (ob->id("schluessel") || ob->QueryDoorKey()!=0));
+}
+
+// Gibt die Nummer des naechsten freien Hakens zurueck oder 0, wenn
+// keiner frei ist. Da Mappings nicht sortiert sind, muss von 1-16 numerisch
+// iteriert werden, damit immer der erste freie Haken gefunden wird und nicht
+// irgendeiner.
+// Rueckgabewert: Hakennummer von 1-16 oder 0, wenn kein Haken frei ist.
+private int GetNextFreeSlot() {
+ int slot;
+ foreach(int i : 1..16) {
+ if ( !objectp(haken[i,HOOK_OB]) ) {
+ slot = i;
+ break;
+ }
+ }
+ return slot;
+}
+
+// Gibt zu einer Schild-Beschriftung die zugehoerige Hakenposition aus.
+// Es wird die kleingeschriebene Variante gesucht, so dass Spieler zwar
+// Grossschreibung in den Beschriftungen verwenden koennen, diese aber
+// nicht beruecksichtigt wird. Ansonsten koennte es zu Schwierigkeiten mit
+// Dopplungen wie "Vesray" und "vesray" kommen.
+// Rueckgabewert: Hakennummer von 1-16 oder 0, wenn der Text nicht gefunden
+// wurde.
+private object GetKeyForLabel(string label) {
+ if ( label )
+ label = lower_case(label);
+ foreach(int i: 1..16) {
+ if ( haken[i, HOOK_LABEL] && label &&
+ lower_case(haken[i,HOOK_LABEL]) == label )
+ return haken[i,HOOK_OB];
+ }
+ return 0;
+}
+
+// Gibt zu dem uebergebenen Objekt die Nummer des Hakens zurueck, an dem
+// es haengt.
+private int GetHookNumberForKey(object ob) {
+ foreach(int num, object key : haken) {
+ if ( key == ob )
+ return num;
+ }
+ return 0;
+}
+
+// Bereinigt Datenstruktur in <haken> und das Inventar des Brettes, indem
+// a) geprueft wird, ob alle in <haken> eingetragenen Objekte sich auch im
+// Brett befinden und
+// b) geprueft wird, ob alle im Inventar befindlichen Objekte auch korrekt in
+// <haken> eingetragen sind.
+// Ueberzaehlige Objekte werden rausgeworfen.
+private void ConsolidateInventory() {
+ foreach(int i, object ob : haken) {
+ // Objekt existiert, ist aber nicht im Schluesselbrett? Dann austragen.
+ if (objectp(ob) && environment(ob) != ME) {
+ m_delete(haken, i);
+ // Wird auch vom reset() aus gerufen, dann ist TP == 0.
+ if ( objectp(TP) )
+ tell_object(TP, BS("Hoppla! "+ob->Name(WER,1)+" scheint vom "
+ "Schluesselbrett verschwunden zu sein!"));
+ }
+ }
+ object *resterampe = all_inventory(ME) - m_values(haken, HOOK_OB);
+ if (sizeof(resterampe)) {
+ resterampe->move(environment(),M_PUT);
+ tell_room(environment(), BS("Ploetzlich faellt etwas vom "
+ "Schluesselbrett zu Boden, das Du zuvor gar nicht gesehen hattest."));
+ }
+}
+
+string short() {
+ string sh=QueryProp(P_SHORT);
+
+ // Unsichtbar? Dann gibts nichts zu sehen ...
+ if ( QueryProp(P_INVIS) || !sh )
+ return 0;
+ if ( QueryProp("versteckt") == 1 )
+ sh = "";
+ else
+ sh += ".";
+
+ return process_string(sh)+"\n";
+}
+
+// Im Reset vorsichtshalber auch mal aufraeumen.
+void reset() {
+ ConsolidateInventory();
+ return ::reset();
+}
+
+varargs int PreventInsert(object ob) {
+ // Kein Schluessel? Hat in diesem Container nix verloren!
+ if( !IsValidKey(ob )) {
+ return 1;
+ }
+ ConsolidateInventory();
+ return ::PreventInsert(ob);
+}
+
+// Wenn ein Schluessel sich aufloest, muss die Liste abgeglichen werden.
+void NotifyRemove(object ob) {
+ tell_room(environment(ME), BS("Hoppla! "+ob->Name(WER,1)+" hat sich "
+ "gerade in Wohlgefallen aufgeloest."));
+ // Das Objekt <ob> zerstoert sich erst nach dem Aufruf dieser Funktion,
+ // daher per call_out() aufraeumen.
+ call_out(#'ConsolidateInventory, 1);
+}
+
+// Zesstra, 1.7.07, fuers Hoerrohr
+// Darf ich da Arathorn eintragen? ;-)
+string GetOwner() {
+ return "seleven";
+}
+
diff --git a/d/seher/haeuser/moebel/schraenker_gutschein.c b/d/seher/haeuser/moebel/schraenker_gutschein.c
new file mode 100644
index 0000000..9c89204
--- /dev/null
+++ b/d/seher/haeuser/moebel/schraenker_gutschein.c
@@ -0,0 +1,44 @@
+//--------------------------------------------------------------------------------
+// Name des Objects: Schraenger-Gutschein
+// Letzte Aenderung: 05.05.2001
+// Magier: Swift
+//--------------------------------------------------------------------------------
+
+#include "schrankladen.h"
+#include <ansi.h>
+inherit "std/thing";
+
+create()
+{
+ if (!clonep(TO)) return;
+ ::create();
+ SetProp(P_SHORT, "Ein Gutschein");
+ SetProp(P_LONG, "@@longtext@@");
+ AddId(({"gutschein"}));
+ SetProp(P_NAME, "Gutschein");
+ SetProp(P_GENDER, MALE);
+ SetProp(P_WEIGHT, 5); // Gewicht 5g
+ SetProp(P_VALUE, 0); // Kein materieller Wert. Ist eh nicht verkaufbar.
+ SetProp(P_NOBUY, 1); // Wird im Laden zerstoert, falls er verkauft wird.
+ SetProp(P_MATERIAL, ({MAT_PAPER}) );
+ SetProp(P_INFO, "Dieser Gutschein ist nur fuer einen Seher mit Eigenheim von Interesse!\n");
+ SetProp(P_AUTOLOADOBJ, 1);
+}
+
+string longtext()
+{
+ string str,aussteller,inhaber,text;
+ int wert;
+ aussteller="Seleven";
+ inhaber="Filli";
+ wert=5000;
+ text="";
+ str="***********************************************************************\n\n"
+ +" D E R S C H R A E N K E R\n\n"
+ +" E I N K A U F S - G U T S C H E I N .\n\n"
+ +" Ausgestellt von "+aussteller+" fuer "+inhaber+".\n\n"
+ +" Wert: "+to_string(wert)+" Muenzen.\n\n"
+ +text
+ +"***********************************************************************\n";
+ return str;
+}
diff --git a/d/seher/haeuser/moebel/schrankladen.c b/d/seher/haeuser/moebel/schrankladen.c
new file mode 100644
index 0000000..bcaf25c
--- /dev/null
+++ b/d/seher/haeuser/moebel/schrankladen.c
@@ -0,0 +1,436 @@
+//----------------------------------------------------------------------------
+// Name des Objects: SCHRAENKER
+// Letzte Aenderung: 06.04.2006 P_LOG_FILE (Seleven)
+// Magier: Swift
+//----------------------------------------------------------------------------
+#pragma strong_types,rtt_checks
+inherit "/std/room";
+
+#include <properties.h>
+#include <language.h>
+#include "schrankladen.h"
+
+
+protected void create()
+{
+ ::create();
+ SetProp(P_LOG_FILE,"seleven/schraenker"); // Seleven 06.04.2006
+ SP(P_INT_SHORT, "Im SCHRAENKER");
+ SP(P_INT_LONG, BS(
+ "Du stehst in einem gemuetlichen kleinen Laden. Ein flauschiger "
+ +"Teppichboden daempft Deine Schritte, und der Geruch verschiedener "
+ +"Hoelzer kitzelt angenehm in der Nase. Irgendwoher erklingt eine "
+ +"leise, beruhigende Melodie. An den Waenden haengen Bilder und "
+ +"Zeichnungen verschiedenster Art, sowie eine grosse Preisliste. "
+ +"Wenn Du nicht den Eindruck haettest, dass man hier an Deine Boerse "
+ +"moechte, koenntest Du Dich hier richtig wohl fuehlen.",78));
+
+ SP(P_LIGHT, 1);
+ SP(P_INDOORS, 1);
+
+ AD( ({"zeit"}), BS(
+ "Die aktuelle Zeit: "+ctime(time()),78));
+ AD( ({"ausgang"}), BS(
+ "Nach Osten geht's raus.",78));
+ AD( ({"ausgaenge"}), BS(
+ "So sehr Du auch suchst, mehr als den einen Ausgang findest Du "
+ +"einfach nicht.",78));
+ AD( ({"geldboerse", "boerse"}), BS(
+ "Man redet halt von Boerse, auch wenn Du keine dabeihast. Es geht "
+ +"halt um Dein Geld!",78));
+ AD( ({"geld"}), BS(
+ "Irgendwo wirst Du schon Kohle haben! :)",78));
+ AD( ({"kohle", "zaster", "moneten", "piepen", "maeuse"}), BS(
+ "Kohle, Zaster, Moneten, Piepen, Maeuse... alles dasselbe! :)",78));
+ AD( ({"boden"}), BS(
+ "Ein flauschiger, aber auch sehr strapazierfaehiger Teppich bedeckt "
+ +"den ganzen Boden des Ladens. Billig sieht er nicht aus.",78));
+ AD( ({"teppich", "teppichboden"}), BS(
+ "Es handelt sich um einen echten Vorberg-Teppich. Er wurde "
+ +"von einem Fachmann verlegt und scheint aus einem einzigen grossen "
+ +"Stueck zu sein.",78));
+ AD( ({"stueck"}), BS(
+ "Der Teppich scheint aus einem einzigen grossen Stueck zu sein. So gut "
+ +"kann das eigentlich nur ein Fachmann.",78));
+ AD( ({"fachmann"}), BS("Es ist keiner zu sehen, aber es ist anzunehmen, dass "
+ +"es sich um einen professionellen Teppichleger handelte."));
+ AD( ({"teppichleger"}), "Wie gesagt, keiner zu sehen. Der Teppich liegt ja "
+ +"schon, und der wird auch noch eine Weile halten.\n");
+ AD( ({"weile"}), "Schon noch ein paar Jaehrchen!\n");
+ AD( ({"jaehrchen"}), "Teppiche der Firma Vorberg koennen lange halten.\n");
+ AD( ({"vorberg", "vorbergteppich", "vorberg-teppich"}), BS(
+ "Die Firma Vorberg stellt, im Gegensatz zur Firma Hinterberg, sehr gute "
+ +"Teppiche her, wie jeder weiss.",78));
+ AD( ({"gegensatz"}), "Das weiss wirklich Jeder!\nDu koenntest Ihn fragen, "
+ +"waere er nicht gebanisht. :)\n");
+ AD( ({"ihn"}), BS("Wen IHN ? Meinst Du Jeder? Der ist doch gebanisht. Aus gutem "
+ +"Grund. Wenn irgendwo was wegkommt, dann koennte das Jeder gewesen sein. "
+ +"Das reicht doch, um ihn zu banishen, oder? :)"));
+ AD( ({"hinterberg", "hinterbergteppich", "hinterberg-teppich"}), BS(
+ "Das hier ist ein Teppich der Firma Vorberg. Niemand mit Geschmack wuerde "
+ +"den billigen Abklatsch der Firma Hinterberg kaufen.",78));
+ AD( ({"jeder"}), BS(
+ "Der ist nicht da. Siehst Du ihn etwa?",78));
+ AD( ({"grund", "gruende"}), BS(
+ "Gruende lassen sich immer finden, sei also vorsichtig! :)",78));
+ AD( ({"geschmack"}), BS(
+ "Ueber den laesst sich bekanntlich streiten.",78));
+ AD( ({"teppiche"}), BS(
+ "Du siehst hier einen. Der aber fuellt den ganzen Raum aus.",78));
+ AD( ({"abklatsch"}), BS(
+ "Vorberg-Teppiche sind halt das einzig Wahre!",78));
+ AD( ({"laden"}), BS(
+ "Der Laden ist bekannt unter dem Namen \"SCHRAENKER\". Aber das weisst "
+ +"Du sicher.",78));
+ AD( ({"namen"}), BS(
+ "Der Namen des Ladens ist \"SCHRAENKER\".",78));
+ AD( ({"schraenker"}), BS(
+ "Ja, schau Dich nur um!",78));
+ AD( ({"melodie"}), BS(
+ "Lausche ihr besser.",78));
+ AD( ({"geruch"}), BS(
+ "Sehen kannst Du den nicht. Vielleicht solltest Du Deine Nase benutzen?",78));
+ AD( ({"schritte"}), BS(
+ "Du gehst testweise ein paar Schritte, der Teppich daempft sie tatsaechlich "
+ +"so gut, dass Du nicht das geringste hoeren kannst.",78));
+ AD( ({"schritt"}), BS(
+ "Mach das doch irgendwo, wo es keiner sieht!",78));
+ AD( ({"nase"}), BS(
+ "Du fasst Dir an die Nase. Ein Glueck, sie ist noch da!",78));
+ AD( ({"glueck"}), BS(
+ "Ohne Nase koenntest Du hier gar nichts riechen, stell Dir das nur "
+ +"mal vor!",78));
+ AD( ({"raum", "ort"}), BS(
+ "Du stehst in einem noblen Laden. Mach einfach \"schau\".",78));
+ AD( ({"firma"}), BS(
+ "Du stehst hier in einem Laden. Natuerlich ist das eine Firma, und der "
+ +"Ladeninhaber ist ebenso natuerlich der Firmenbesitzer. Hattest Du denn "
+ +"etwas anderes erwartet?",78));
+ AD( ({"eindruck"}), BS(
+ "Es ist ein Laden. Er sieht nobel aus, Preise wie bei ALDI wird's hier also "
+ +"wohl nicht geben. Und ausserdem ist der erste Eindruck meist der richtige.",78));
+ AD( ({"aldi"}), BS(
+ "NEIN, Du bist hier NICHT bei ALDI !!!",78));
+ AD( ({"preis", "preise", "liste", "preisliste"}), BS(
+ "An der Wand haengt eine grosse Preisliste. Vielleicht solltest Du sie "
+ +"lesen?",78));
+ AD( ({"inhaber", "ladeninhaber", "besitzer", "firmenbesitzer", "verkaeufer"}), BS(
+ "Ist der denn gerade nicht da? Das ist sehr verwunderlich, echt ehrlich.",78));
+ AD( ({"elf", "elfen", "person"}), BS(
+ "Schau Dir halt das Portrait an!",78));
+ AD( ({"darstellung", "darstellungen"}), BS(
+ "Die Bilder zeigen Moebelstuecke, hauptsaechlich Schraenke.",78));
+ AD( ({"reihe"}), BS(
+ "Bei den meisten Bildern handelt es sich um Darstellung von Moebelstuecken. "
+ +"Nur ein einziges Portrait ist dabei, das eine Person zeigt.",78));
+ AD( ({"art"}), BS(
+ "Bei den meisten Bildern handelt es sich um Darstellungen von Moebelstuecken, "
+ +"zumeist von Schraenken. Ein Portrait faellt Dir allerdings auf, das nicht in "
+ +"die Reihe der anderen Bilder passt.",78));
+ AD( ({"bilder"}), BS(
+ "Es gibt mehrere Darstellungen von verschiedenen Moebelstuecken. Zumeist "
+ +"handelt es sich dabei um Schraenke verschiedener Bauweise. Ausserdem ist "
+ +"da noch ein Portrait.",78));
+ AD( ({"bauart", "bauweise", "moebelstueck", "moebelstuecke", "arten"}), BS(
+ "Es gibt Waffenschraenke, Kleiderschraenke, Kuehlschraenke (JA!), Kommoden, "
+ +"sonstige Schraenke (Du kannst ihren Zweck nicht mal erahnen) und einige "
+ +"Truhen, die zwar keine Schraenke im eigentlichen Sinne sind, aber Zeug "
+ +"bringt man darin mit Sicherheit auch unter. Sogar eine Vitrine siehst "
+ +"Du.",78));
+ AD( ({"zweck"}), BS(
+ "Stauraum fuer irgendwelches Zeugs. Das muss es sein. Was fuer einen "
+ +"Zweck koennte es sonst noch geben?",78));
+ AD( ({"vitrine"}), BS("Die Vitrine ist leer, aber das aendert sich sicher, "
+ +"sobald Du eine gekauft hast.",78));
+ AD( ({"kleiderschrank", "kleiderschraenke"}), BS(
+ "Sicher eignet sich solch ein Schrank sehr gut, um darin Ruestungen "
+ +"aufzubewahren.",78));
+ AD( ({"waffenschrank", "waffenschraenke"}), BS(
+ "In einem Waffenschrank kannst Du eine Menge verschiedener Waffen "
+ +"unterbringen, und der Vorteil dabei ist, dass sie dann auch sauber "
+ +"sortiert im Schrank haengen.",78));
+ AD( ({"kommoden"}), BS(
+ "Die kann man nicht nur in einen Flur stellen, sondern auch in jeden "
+ +"anderen Raum!",78));
+ AD( ({"flur"}), BS(
+ "Die meisten Haeuser haben einen.",78));
+ AD( ({"haeuser"}), BS(
+ "HIER ???",78));
+ AD( ({"menge"}), BS(
+ "Mehr als Du brauchst, es sei denn Du bist Sammler.",78));
+ AD( ({"zeugs", "dinge"}), BS(
+ "Dinge halt.",78));
+ AD( ({"waffen"}), BS(
+ "Du kannst sie in einem Waffenschrank unterbringen, wenn Du einen "
+ +"besitzt. Wenn nicht kannst Du ja einen kaufen.",78));
+ AD( ({"waffe"}), BS(
+ "Welche Waffe meinst Du?",78));
+ AD( ({"ruestungen"}), BS(
+ "Du kannst sie in einem Kleiderschrank unterbringen, wenn Du einen "
+ +"besitzt. Wenn nicht koenntest Du Dir einen zulegen.",78));
+ AD( ({"ruestung"}), BS(
+ "Von welcher Ruestung redest Du?",78));
+ AD( ({"vorteil"}), BS(
+ "Jeder ist doch auf seinen persoenlichen Vorteil bedacht.",78));
+ AD( ({"kuehlschrank", "kuehlschraenke"}), BS(
+ "In so einem Kuehlschrank kann man eigentlich alles reinstecken, aber "
+ +"natuerlich bietet er sich besonders fuer Getraenke und Speisen aller "
+ +"Art an. Wie z.B. Schnellhaerter, Broetchen usw.",78));
+ AD( ({"getraenke", "speisen"}), BS(
+ "Das hier ist keine Kneipe. Sowas gibt's hier nicht!",78));
+ AD( ({"kneipe"}), BS(
+ "Das hier ist KEINE Kneipe !!!",78));
+ AD( ({"truhe", "truhen"}), BS(
+ "Es gibt grosse und kleine, aus verschiedenem Material.",78));
+ AD( ({"material"}), BS(
+ "Total verschieden, wirklich.",78));
+ AD( ({"schnellhaerter", "broetchen"}), BS(
+ "Besorg Dir welche, bevor Du sie untersuchen willst!",78));
+ AD( ({"sammler"}), BS(
+ "Bist Du einer?",78));
+ AD( ({"sicherheit"}), BS(
+ "Jo, in so eine Truhe passt viel Zeug rein.",78));
+ AD( ({"zeug"}), BS(
+ "Alles, was Du so mit Dir rumschleppst. Das meiste davon brauchst "
+ +"Du sowieso nie.",78));
+ AD( ({"bild"}), BS(
+ "Es gibt mehrere Darstellungen von verschiedenen Moebelstuecken und ein "
+ +"Portrait. Welches Bild meinst Du?",78));
+ AD( ({"portrait"}), BS(
+ "Es zeigt einen Elf mit strahlend blauen Augen und den typisch spitzen "
+ +"Elfenohren, die frech aus einer beeindruckenden, silbergrauen Loewenmaehne "
+ +"hervorschauen. Der Spitzhut, der ihm auf dem Kopf sitzt, laesst darauf "
+ +"schliessen, dass es sich um einen Zauberer handelt. Unten in der rechten "
+ +"Bildecke ist eine Widmung angebracht.",78));
+ AD( ({"sinn", "sinne"}), BS(
+ "Schraenke und Truhen sehen schon etwas veschieden aus.",78));
+ AD( ({"swift"}), BS(
+ "Siehst Du ihn hier etwa gerade?",78));
+ AD( ({"bildecke"}), BS(
+ "Unten in der rechten Bildecke ist eine Widmung angebracht.",78));
+ AD( ({"augen"}), BS(
+ "Der Elf auf dem Portrait hat strahlend blaue Augen.",78));
+ AD( ({"widmung"}), BS(
+ "Sieht aus als ob man die sogar lesen kann!",78));
+ AD( ({"maehne", "loewenmaehne"}), BS(
+ "Der Elf auf dem Bild hat eine silbergraue Loewenmaehne.",78));
+ AD( ({"zauberer", "zauberhut", "zaubererhut", "spitzhut"}), BS(
+ "Der Zauberhut macht den Elfen auf dem Portrait erst zu einem waschechten "
+ +"Zauberer.",78));
+ AD( ({"ohren", "elfenohren"}), BS(
+ "Die Ohren des Elfen auf dem Portrait sind so spitz, wie man das von "
+ +"einem Elfen erwartet.",78));
+ ARD( ({"widmung"}),
+ "Dank an Geordi fuer diese grossartige Geschaeftsidee.\n"
+ +"Moegen Dir Deine Zauber gelingen und die Spellpunkte niemals ausgehen.\n"
+ +"(Darunter hat jemand unterschrieben, aber das Gekrakel kannst Du nicht "
+ +"identifizieren)\n");
+ AD( ({"unterschrift"}), BS(
+ "Meinst Du das Gekrakel?",78));
+ AD( ({"rotfaerbung", "farbe"}), BS(
+ "Das Holz hat eine leicht roetliche Farbe.",78));
+ AD( ({"ruhe"}), BS(
+ "Aaaahhhhh. Ruhe tut gut. Und dank der leisen Melodie entspannst Du "
+ +"Dich allmaehlich.",78));
+ AD( ({"chaosdaemon"}), BS(
+ "Keiner da. Weder Swift noch ein anderer. Glueck fuer Dich!",78));
+ AD( ({"sachen"}), BS(
+ "Was auch immer.",78));
+ AD( ({"klaue"}), BS(
+ "Wahrscheinlich kann Swift damit andere Sachen besser erledigen als "
+ +"schreiben. Schliesslich ist er ein Chaosdaemon.",78));
+ AD( ({"gekrakel"}), BS(
+ "Du nimmst Dir Zeit und schaust die Unterschrift doch nochmal in aller "
+ +"Ruhe an. Endlich kommt Dir die Erleuchtung. Das soll \"Swift\" heissen. "
+ +"Mann, hat der ne Klaue! (Naja, bei einem Chaosdaemonen wundert das "
+ +"eigentlich nicht)",78));
+ AD( ({"erleuchtung"}), BS(
+ "Sie fand in Deinem Kopf statt. Den muesstet Du schon oeffnen, wenn Du "
+ +"die Erleuchtung physisch untersuchen moechtest. Und das kann sich "
+ +"negativ auf Deine Gesundheit auswirken. Lass es lieber!",78));
+ AD( ({"gesundheit"}), BS(
+ "Mit Kopf bist Du gesund. Das ist gewiss.",78));
+ AD( ({"wand", "waende"}), BS(
+ "Die Waende bestehen aus einem feinen, exotischen Holz mit leichter "
+ +"Rotfaerbung. Sieht sehr edel aus. Mehrere Bilder wurden an den Waenden "
+ +"aufgehaengt und verteilen sich gleichmaessig ueber den Raum.",78));
+ AD( ({"kopf"}), BS(
+ "Ein Glueck, er ist noch dran. Genauso wie bei dem Elfen auf dem "
+ +"Portrait!",78));
+ AD( ({"schrank", "schraenke"}), BS(
+ "Es gibt verschiedene Arten von Schraenken.",78));
+ AD( ({"zeichnung"}), BS(
+ "Es gibt mehrere davon.",78));
+ AD( ({"zeichnungen"}), BS(
+ "Sie zeigen - teilweise skizzenhaft - den Aufbau verschiedener "
+ +"Moebelstuecke - vorzugsweise Schraenke.",78));
+ AD( ({"aufbau", "zusammensetzung"}), BS(
+ "Mit dem Aufbau ist die Zusammensetzung gemeint - und umgekehrt.",78));
+ AD( ({"holz", "hoelzer"}), BS(
+ "Schon hier im Raum wurde mit verschiedensten Hoelzern gearbeitet, "
+ +"ihr edler Duft vermischt sich und bietet einen erhebenden Geruch. "
+ +"Leider sind die meisten Holzarten so exotisch, dass Du beim besten "
+ +"Willen nicht sagen kannst, um was fuer einen Baum es sich da mal "
+ +"gehandelt hat.",78));
+ AD( ({"holzart", "holzarten"}), BS(
+ "Sehr exotische Holzarten. Du bist kein Experte fuer sowas, und "
+ +"vermutlich hast Du auch keine Lust, einer zu werden.",78));
+ AD( ({"experte"}), BS(
+ "Keiner da.",78));
+ AD( ({"lust"}), BS(
+ "Wenn jemand seine Lust untersucht/ueberprueft, bekundet er damit "
+ +"eigentlich schon in Wirklichkeit seine Unlust.",78));
+ AD( ({"unlust"}), BS(
+ "Tja, Unlust kennzeichnet den Faulpelz.",78));
+ AD( ({"faulpelz"}), BS(
+ "Du bist gemeint!",78));
+ AD( ({"wirklichkeit", "realitaet"}), BS(
+ "Die Wirklichkeit ist die Realitaet - und andersrum. Meistens "
+ +"jedenfalls.",78));
+ AD( ({"meistens"}), BS(
+ "Hier schon.",78));
+ AD( ({"hier"}), BS(
+ "Hier halt!",78));
+ AD( ({"baum", "baeume"}), BS(
+ "Hier gibt es keine Baeume. Die wurden bereits alle verarbeitet.",78));
+ AD( ({"duft"}), BS(
+ "Rieche halt mal!",78));
+ AD( ({"wille", "willen"}), BS(
+ "Dein Wille ist stark...",78));
+ AD( ({"decke"}), BS(
+ "Maechtige Balken bilden die Decke. Es koennte sich um Eiche handeln, aber "
+ +"genausogut koennte es irgendeine aehnliche, exotische Holzart sein. "
+ +"Ein herrlicher Kronleuchter haengt von der Mitte herab.",78));
+ AD( ({"eiche", "eichenbalken"}), BS(
+ "Es ist nicht sicher, dass es sich um Eichenbalken handelt, aber Balken "
+ +"sind's auf jeden Fall.",78));
+ AD( ({"fall"}), BS(
+ "Echt ehrlich.",78));
+ AD( ({"balken"}), BS(
+ "Sie bilden die Decke. Ein herrlich anzusehender Kronleuchter haengt "
+ +"daran herab.",78));
+ AD( ({"kronleuchter"}), BS(
+ "Er haengt von der Decke herab und muss ein Vermoegen wert sein. Reines "
+ +"Bergkristall mit einer Unzahl von Kerzen. Was das fuer ein Aufwand sein "
+ +"muss, die immer am Brennen zu halten.",78));
+ AD( ({"vermoegen"}), BS(
+ "Mehr als Du tragen kannst.",78));
+ AD( ({"bergkristall"}), BS(
+ "Nur Bergkristall hat diesen Glanz.",78));
+ AD( ({"brennen"}), BS(
+ "Die Kerzen flackern munter vor sich hin.",78));
+ AD( ({"unzahl"}), BS(
+ "1, 2, ...viele!",78));
+ AD( ({"glanz"}), BS(
+ "Herrlich!",78));
+ AD( ({"mitte"}), BS(
+ "Von der Mitte der Decke haengt ein Kronleuchter herab.",78));
+ AD( ({"kerzen"}), BS(
+ "Dir faellt auf, dass die Kerzen sich gar nicht verbrauchen. Es muss "
+ +"sich um magische Kerzen handeln.",78));
+ AD( ({"aufwand"}), BS(
+ "Entsetzt denkst Du . o O (Das schlaegt sich bestimmt auf den Preis nieder.)",78));
+ AD( ({"ecken"}), BS(
+ "In den Ecken entdeckst Du kleine, edle Lautsprecher, aus denen die "
+ +"Melodie zu kommen scheint.",78));
+ AD( ({"lautsprecher"}), BS(
+ "Du wusstest gar nicht, dass sowas im MorgenGrauen schon erfunden wurde.",78));
+ AD( ({"morgengrauen"}), BS(
+ "Tust Du das nicht schon die ganze Zeit?",78));
+
+ AddSmells(SENSE_DEFAULT, "Es riecht hier angenehm nach verschiedenen "
+ +"Hoelzern.\n");
+ AddSmells(({"hoelzer", "holz", "holzarten"}), BS("Du kannst nicht sagen, "
+ +"um was fuer Holzarten es sich handelt, aber der Geruch laesst auf viele "
+ +"verschiedene schliessen. Eine Trennung des Geruchs ist Dir nicht moeglich.") );
+ AddSmells(({"geruch", "gerueche"}), BS("Es riecht nach verschiedenen "
+ +"Holzarten.") );
+
+ AddSounds(SENSE_DEFAULT, "Ganz leise hoerst Du eine angenehme, beruhigende "
+ +"Melodie.\n");
+ AddSounds(({"melodie"}), "Sie scheint von allen Ecken des Ladens zu kommen.\n");
+
+ AddItem( LADEN("verkaeufer"), REFRESH_DESTRUCT);
+
+ AddCmd(({"oeffne"}), "kopf_oeffnen");
+ AddCmd(({"lies", "les", "lese"}), "preisliste_lesen");
+ AddCmd(({"idee"}), "idee_loggen");
+ AddCmd(({"trenn", "trenne"}), "gerueche_trennen");
+ AddCmd(({"werd", "werde"}), "experte_werden");
+ AddCmd(({"zaehl", "zaehle"}), "kerzen_zaehlen");
+
+ AddSpecialExit("osten", "rausgehen");
+}
+
+int kerzen_zaehlen(string str)
+{
+ notify_fail("Was moechtest Du zaehlen?\n");
+ if(!str) return 0;
+ if(str!="kerzen") return 0;
+ write("1..2..viele.\n");
+ return 1;
+}
+
+int rausgehen(string dir)
+{
+ return TP->move(RAUM_VOR_LADEN, M_GO, 0,
+ "verlaesst den Laden", "kommt aus dem Laden");
+}
+
+varargs string GetExits( object viewer )
+{
+ return "Der Ausgang befindet sich im Osten.\n";
+}
+
+int kopf_oeffnen(string str)
+{
+ notify_fail("Was moechtest Du oeffnen?\n");
+ if(!str) return 0;
+ if(str!="kopf" && str!="meinen kopf" && str!="deinen kopf")
+ return 0;
+ write( BS("Neugierig, wie Du bist, greifst Du Dir an den Kopf. Da faellt Dir "
+ +"ein, dass das oeffnen Deines Kopfes evtl. eine Copyright-Verletzung "
+ +"darstellen koennte, Du heisst ja schliesslich nicht Hannibal. Also laesst "
+ +"Du es dann doch bleiben."));
+ return 1;
+}
+
+int preisliste_lesen(string str)
+{
+ notify_fail("Was moechtest Du lesen?\n");
+ if(!str) return 0;
+ if(str!="preisliste" && str!="liste")
+ return 0;
+ TP->More( read_file(LADEN("preisliste.txt")) );
+ return 1;
+}
+
+int idee_loggen(string str)
+{
+ string txt;
+ str=TP->_unparsed_args();
+ txt=BS(str, 78, CAP(geteuid(TP))+"............."[0..12], BS_INDENT_ONCE);
+ write_file( LADEN(IDEEN_LOG), txt+"\n");
+ write("Vielen Dank fuer Deine Idee!\n");
+ return 1;
+}
+
+int gerueche_trennen(string str)
+{
+ notify_fail("Was willst Du trennen?\n");
+ if(!str) return 0;
+ if(str!="geruch" && str!="gerueche")
+ return 0;
+ write("Du versuchst es, aber Du schaffst es einfach nicht.\n");
+ return 1;
+}
+
+int experte_werden(string str)
+{
+ notify_fail("Was willst Du werden?\n");
+ if(!str) return 0;
+ if(str!="experte" && str!="fachmann")
+ return 0;
+ write("Tja, so einfach geht das nicht, aber das haettest Du Dir denken koennen.\n");
+ return 1;
+}
diff --git a/d/seher/haeuser/moebel/schrankladen.h b/d/seher/haeuser/moebel/schrankladen.h
new file mode 100644
index 0000000..1fc76a9
--- /dev/null
+++ b/d/seher/haeuser/moebel/schrankladen.h
@@ -0,0 +1,36 @@
+#include "moebel.h"
+
+#define SCHRANKMASTER2 "/players/swift/workroom"
+
+#include <language.h>
+#include <defines.h>
+#include <combat.h>
+#include <properties.h>
+#include <wizlevels.h>
+#include <moving.h>
+#include <rooms.h>
+
+#define BS break_string
+#define ENV(x) environment(x)
+#define ETO environment(this_object())
+#define ETP environment(this_player())
+#define TP this_player()
+#define TO this_object()
+
+#define SP SetProp
+#define QP QueryProp
+#define AD AddDetail
+#define ARD AddReadDetail
+
+#define SUID seteuid(getuid(this_object()))
+
+//#define CAP(x) capitalize(x)
+#define LOWER(x) lower_case(x)
+
+#define CLONEME(x) clone_object(x)->move(ME)
+#define CLONEOB(x) clone_object(x)
+#define CLONE(x,y) clone_object(x)->move(y)
+#define IST_ZAHL(x) (string)to_int(x)==x
+
+#define RIGHT(x,y) (y>sizeof(x)?x:extract(x,sizeof(x)-y,sizeof(x)-1))
+#define LEFT(x,y) (y>sizeof(x)?x:extract(x,0,y-1))
diff --git a/d/seher/haeuser/moebel/schrankmaster.c b/d/seher/haeuser/moebel/schrankmaster.c
new file mode 100644
index 0000000..c602ddc
--- /dev/null
+++ b/d/seher/haeuser/moebel/schrankmaster.c
@@ -0,0 +1,233 @@
+//--------------------------------------------------------------------------------
+// Name des Objects: Schrankmaster
+// Letzte Aenderung: 19.03.2001
+// Magier: wurzel
+//--------------------------------------------------------------------------------
+/* Changelog:
+ * 21.06.2007, Zesstra
+ call_out ohne Verzoegerung beim Updaten durch eines mit 2s Verzoegerung ersetzt.
+*/
+#pragma strong_types,rtt_checks
+
+inherit "/std/room";
+
+#include <properties.h>
+#include <language.h>
+#include "schrankladen.h"
+
+mapping schraenke;
+string *cnts;
+int update_laeuft;
+int reset_laeuft;
+
+protected void create()
+{
+ ::create();
+ SP(P_INT_SHORT, "Irgendwo und Nirgends");
+ SP(P_INT_LONG,
+ "Dies ist der Master-Raum fuer den SCHRAENKER.\n"
+ +"Hier merkt sich August die Anzahl der verkauften Container.\n"
+ +"Davon sind momentan @@ANZAHL@@ registrierte im Umlauf!\n"
+ +"Folgende Befehle sind verfuegbar:\n"
+ +" schrankliste.........Listet registrierte, im Spiel befindliche Container.\n"
+ +" schrankupdate........Fuehrt ein Update aller registrierten Container durch.\n");
+
+ SP(P_LIGHT, 1);
+ SP(P_INDOORS, 1);
+ if( SCHRANKMASTER2->QueryProp("schraenke") ) // Der Sicherungsraum hat Daten?
+ schraenke=SCHRANKMASTER2->QueryProp("schraenke"); // Daten holen...
+ else
+ schraenke=([]);
+ SetProp("schraenke", schraenke );
+
+ update_laeuft=0;
+
+ // unnoetig, SCHRANKMASTER2 ist jetzt schon geladen, s.o.
+ //load_object(SCHRANKMASTER2);
+ set_next_reset(3600); // Reset 1 x pro Std.
+
+ AddCmd(({"schrankliste"}), "Schrankliste");
+ AddCmd(({"schrankupdate"}), "SchrankUpdate");
+}
+
+public int clean_up(int ref) {return 0;} // verhindert Ausswappen des Raumes
+
+public varargs string GetExits( object viewer )
+{
+ return "";
+}
+
+string ANZAHL()
+{
+ return to_string( sizeof(schraenke) );
+}
+
+
+// cnt = Object des Containers
+// ver = Version des Containers (VERSION_STD+VERSION_OBJ von std.cont. + objekt...)
+// seher=Der Besitzer/Kaeufer
+// standort=Raum in dem der Container steht
+void RegisterCnt(mixed cnt, mixed ver, mixed seher, mixed standort)
+{
+ if (objectp(standort)) standort=object_name(standort);
+ if( !objectp(cnt) || !stringp(ver) || !stringp(seher) || !stringp(standort) )
+ {
+ log_file("swift/schraenker/bugs.log", "schrankmaster (RegisterCnt) *"
+ +to_string(cnt)+"*"+to_string(ver)+"*"+to_string(seher)+"*"
+ +to_string(standort)+"*\n");
+ return;
+ }
+ m_delete(schraenke,object_name(cnt));
+ schraenke+=([object_name(cnt): ver; seher; to_string(standort)]);
+ SetProp("schraenke", schraenke );
+ SCHRANKMASTER2->SetProp("schraenke", schraenke );
+}
+
+void RemoveCnt(mixed cnt, mixed seher)
+{
+ if( !objectp(cnt) || !stringp(seher) )
+ {
+ log_file("swift/schraenker/bugs.log", "schrankmaster (RemoveCnt) *"
+ +to_string(cnt)+"*"+to_string(seher)+"*\n");
+ return;
+ }
+ schraenke-=([object_name(cnt)]);
+ SetProp("schraenke", schraenke );
+ SCHRANKMASTER2->SetProp("schraenke", schraenke );
+}
+
+string fn(string was)
+{
+ string str,*strs;
+ strs=old_explode( was, "/" );
+ str=strs[sizeof(strs)-1];
+ strs=old_explode( str, "#" );
+ str=strs[0];
+ return str;
+}
+
+int Schrankliste()
+{
+ int i;
+ string str, *strs;
+ object cnt;
+ if(update_laeuft && !reset_laeuft) // Nicht waehrend eines Updates der Schraenke!
+ {
+ write("Update wird durchgefuehrt. Bitte bis zum Ende warten!\n");
+ return 1;
+ }
+ str="----------------------------------------------------------------------\n";
+ strs=m_indices(schraenke);
+ for(i=0;i<sizeof(strs);i++)
+ {
+ if( cnt=find_object(strs[i]) )
+ {
+ str+=(fn(object_name(cnt))+"....................")[0..20]+" ";
+ str+=schraenke[strs[i], 0]+" ";
+ str+=(schraenke[strs[i], 1]+"....................")[0..20]+" ";
+ str+=fn(schraenke[strs[i], 2])+"\n";
+ }
+ else
+ {
+ str+="Nicht auffindbaren Container aus Liste geloescht!\n";
+ schraenke-=([strs[i]]);
+ SetProp("schraenke", schraenke );
+ SCHRANKMASTER2->SetProp("schraenke", schraenke );
+ }
+ }
+ str+="----------------------------------------------------------------------\n";
+ if( TP && present(TP) ) //wurzel 19.03.01
+ TP->More(str);
+ return 1;
+}
+
+void Update_naechster_Schrank()
+{
+ int i;
+ object cnt, cnt_neu, *inv;
+ if( sizeof(cnts) ) // Es gibt noch Schraenke zum abarbeiten...
+ {
+ cnt=find_object(cnts[0]); // Schrank auswaehlen + Objekt suchen
+ if(cnt)
+ {
+ // Autoloadertruhe ist etwas spezieller zu updaten... Daher alternativer
+ // Mechanismus: UpdateMe() im Moebelstueck aufrufen. Wenn die Funktion
+ // etwas != 0 liefert, wird angenommen, dass diese Funktion das Update
+ // gemacht hat oder sich in Kuerze darum kuemmert. Sonst wird das alte
+ // Update gemacht.
+ // Das neue Moebelobjekt ist dafuer verantwortlich, sich beim
+ // Schrankmaster zu (de-)registrieren!
+ object oldenv=environment(cnt);
+ if (cnt->UpdateMe())
+ {
+ tell_room(TO, "...Update "+CAP(fn(cnts[0]))
+ +" in " + object_name(oldenv) + "\n" );
+ }
+ else
+ {
+ tell_room(TO, CAP(fn(cnts[0]))
+ +" in " + object_name(oldenv)
+ + " hat kein UpdateMe()!\n" );
+ }
+ }
+ else
+ {
+ tell_room(TO, "Nicht auffindbaren Container aus Liste geloescht!\n");
+ schraenke-=([cnts[0]]);
+ }
+ cnts-=({cnts[0]}); // Schrank aus Liste nehmen
+ call_out("Update_naechster_Schrank", 2); // Nur 1 Schrank-Update pro heart_beat!
+ }
+ else // Alle Schraenke abgearbeitet:
+ {
+ tell_room(TO, "*** Update abgeschlossen.\n");
+ SetProp("schraenke", schraenke );
+ SCHRANKMASTER2->SetProp("schraenke", schraenke );
+ update_laeuft=0;
+ }
+}
+
+int SchrankUpdate()
+{
+ if(update_laeuft) // Nicht waehrend eines Updates der Schraenke!
+ {
+ write("Update wird durchgefuehrt. Bitte bis zum Ende warten!\n");
+ return 1;
+ }
+ update_laeuft=1; // Ab sofort laeuft Update!
+ cnts=m_indices(schraenke);
+ tell_room(TO, "*** Update wird gestartet...\n");
+ Update_naechster_Schrank();
+ return 1;
+}
+
+
+void reset()
+{
+ reset_laeuft=1;
+ set_next_reset(3600); // Reset 1 x pro Std.
+ ::reset();
+ // Wirft Schraenke aus der Liste, die aus welchem Grund auch immer nicht mehr existieren
+ Schrankliste();
+ if( !(schraenke==QueryProp("schraenke")==SCHRANKMASTER2->QueryProp("schraenke")) )
+ log_file("swift/schraenker/reset.log", "schrankmaster (reset) "
+ +sizeof(schraenke)+" "
+ +sizeof(QueryProp("schraenke"))+" "
+ +sizeof(SCHRANKMASTER2->QueryProp("schraenke"))+"\n");
+ if( present("Interactive") )
+ tell_room(TO, "*** RESET ***\n");
+ reset_laeuft=0;
+}
+
+/*
+// Veraltete Funktionen, um Fehler abzufangen. Kann nach dem naechsten Reboot
+// geloescht werden !!!
+void AddCnt(mixed cnt, mixed ver, mixed seher, mixed standort)
+{
+ log_file("swift/schraenker/verloren.log", to_string(cnt)+"\n");
+}
+void EditCnt(mixed cnt, mixed ver, mixed seher, mixed standort)
+{
+ log_file("swift/schraenker/verloren.log", to_string(cnt)+"\n");
+}
+*/
diff --git a/d/seher/haeuser/moebel/spind.c b/d/seher/haeuser/moebel/spind.c
new file mode 100644
index 0000000..7473b10
--- /dev/null
+++ b/d/seher/haeuser/moebel/spind.c
@@ -0,0 +1,208 @@
+//--------------------------------------------------------------------------------
+// Name des Objects: Spind
+// Letzte Aenderung: 17.03.2001
+// Magier: Swift
+//--------------------------------------------------------------------------------
+#pragma strong_types,rtt_checks
+
+#include "schrankladen.h"
+#include "ansi.h"
+inherit LADEN("swift_std_container");
+
+#define VERSION_OBJ "3"
+
+string strall;
+
+protected void create()
+{
+ if (!clonep(TO)) return;
+ swift_std_container::create();
+ SetProp(P_SHORT, "Ein Spind");
+ SetProp(P_LONG, BS(
+ "Dieser Stahlschrank ist vor allem fuer spartanische Raeume gedacht. Ebenso "
+ +"wie sein Gegenstueck, der Kleiderschrank, verfuegt er ueber eine Menge "
+ +"Regale, in denen er riesige Ausruestungsmengen aufnehmen kann.")
+ +"@@cnt_status@@");
+ AddId(({"spind", "schrank", "stahlschrank"}));
+ SetProp("cnt_version_obj", VERSION_OBJ);
+ SetProp(P_NAME, "Spind");
+ SetProp(P_GENDER, MALE);
+ SetProp(P_WEIGHT, 5000); // Gewicht 5 Kg
+ SetProp(P_MAX_WEIGHT, 1000000); // Es passen fuer 1000 kg Sachen rein.
+ SetProp(P_WEIGHT_PERCENT, 100); // Dafuer macht er auch nix leichter :)
+ SetProp(P_MAX_OBJECTS, 100); // Mehr sollte nicht sein, lt. Tiamak.
+ SetProp(P_VALUE, 0); // Kein materieller Wert. Ist eh nicht verkaufbar.
+ SetProp(P_NOBUY, 1); // Wird im Laden zerstoert, falls er verkauft wird.
+ SetProp(P_NOGET, "Das geht nicht. "+Name(WER,1)+" haftet wie magisch am Boden.\n");
+ SetProp(P_MATERIAL, ({MAT_MISC_METAL, MAT_MISC_MAGIC}) );
+ SetProp(P_INFO, "Versuchs mal mit: \"skommandos "+QueryProp(P_IDS)[1]+"\" !\n");
+ SetProp("obj_cmd", "sliste [Objekt-Id] [Kleidungs-/Ruestungstyp]\n"
+ +" Kleidungs-/Ruestungstypen: Helme, Umhaenge, Ruestungen, Hosen, Schuhe,\n"
+ +" Handschuhe, Guertel, Amulette, Ringe, Koecher,\n"
+ +" Schilde, Sonstiges\n");
+ AD(({"regal", "regale"}), BS("Durch die Regale kommt etwas Ordnung in die "
+ +"vielen Sachen, die man in den Schrank stecken kann. Du kannst Dir z.B. "
+ +"eine Liste bestimmter Kleidungs-/Ruestungstypen des Schrankinhaltes "
+ +"mit dem Befehl \"sliste\" anschauen. (Das geht natuerlich nur bei "
+ +"offenem Schrank!"));
+
+ AddCmd(({"sliste"}), "auflistung");
+}
+
+varargs int PreventInsert(object ob)
+{
+ // Nur Ruestung/Kleidung hat in diesem Container was verloren!
+ if ((ob->IsClothing() || ob->QueryProp(P_ARMOUR_TYPE))
+ && !ob->QueryProp(P_WEAPON_TYPE) )
+ {
+ return ::PreventInsert(ob);
+ }
+
+ write( BS("In "+name(WEN,1)+" kannst Du nur Ruestungs-/Kleidungsstuecke legen!"));
+ return 1;
+}
+
+int auflistung2(string was, string nf_str1, string nf_str2, int alles)
+{
+ string obshort, suche, *strs;
+ object *obs;
+ int i;
+ mapping suchobs;
+ switch(was)
+ {
+ case "helme" : suche=AT_HELMET; break;
+ case "umhaenge" : suche=AT_CLOAK; break;
+ case "ruestungen" : suche=AT_ARMOUR; break;
+ case "hosen" : suche=AT_TROUSERS; break;
+ case "schuhe" : suche=AT_BOOT; break;
+ case "handschuhe" : suche=AT_GLOVE; break;
+ case "guertel" : suche=AT_BELT; break;
+ case "amulette" : suche=AT_AMULET; break;
+ case "ringe" : suche=AT_RING; break;
+ case "koecher" : suche=AT_QUIVER; break;
+ case "schilde" : suche=AT_SHIELD; break;
+ case "sonstiges" : suche=AT_MISC; break;
+ default : write("Fehler: Ungueltiger Kleidungs-/Ruestungstyp. "
+ +"Folgende Typen gibt es:\n"+nf_str1+nf_str2);
+ return 1; break;
+ }
+ obs=all_inventory();
+ suchobs=([]);
+ for(i=0;i<sizeof(obs);i++)
+ {
+ obshort=obs[i]->QueryProp(P_SHORT);
+ if(obshort=="Nichts besonderes") // keine P_SHORT ?
+ obshort=obs[i]->Name(WER); // Hoffen wir mal dass das Obj. nen Namen hat.
+ if(obs[i]->QueryProp(P_ARMOUR_TYPE)==suche) // Gesuchter ArmourType gefunden...
+ {
+ if(suchobs[obshort]) // P_SHORT des Obj. schon im mapping?
+ {
+ if( obs[i]->QueryProp(P_AMOUNT) )
+ suchobs[obshort]+=obs[i]->QueryProp(P_AMOUNT); // Dann den Zaehler um Amount hoch!
+ else
+ suchobs[obshort]+=1; // Dann den Zaehler um 1 hoch!
+ }
+ else
+ {
+ if( obs[i]->QueryProp(P_AMOUNT) )
+ suchobs+=([obshort: obs[i]->QueryProp(P_AMOUNT)]);
+ else
+ suchobs+=([obshort: 1]);
+ }
+ }
+ }
+ strs=m_indices(suchobs);
+ if(sizeof(strs))
+ {
+ if(!alles)
+ {
+ strall+=Name(WER,1)+" enthaelt folgende "+CAP(was)+":\n";
+ strall+="------------------------------------------------------------\n";
+ }
+ else
+ strall+=ANSI_BOLD+"=== "+CAP(was)+":\n"+ANSI_NORMAL;
+ for(i=0;i<sizeof(strs);i++)
+ {
+ if(suchobs[strs[i]] > 1)
+ strall+=strs[i]+". ("+suchobs[strs[i]]+")\n";
+ else
+ strall+=strs[i]+".\n";
+ }
+ }
+ else
+ if(!alles)
+ strall+=Name(WER,1)+" enthaelt keine "+CAP(was)+"!\n";
+ return 1;
+}
+
+int auflistung(string str)
+{
+ string *strs, ob_id, was, nf_str1,nf_str2;
+ strall="";
+ nf_str1=" (Helme, Umhaenge, Ruestungen, Hosen, Schuhe, Handschuhe,\n"
+ +" Guertel, Amulette, Ringe, Koecher, Schilde, Sonstiges)\n";
+ nf_str2="Syntax: sliste [Objekt-Id] [Kleidungs-/Ruestungstyp|\"alles\"]\n"
+ +"Bsp.: sliste "+QueryProp(P_IDS)[1]+" "+"helme\n"
+ +" sliste "+QueryProp(P_IDS)[1]+" alles\n";
+ notify_fail("Fehler: Ohne Parameter klappt das nicht.\n"+nf_str2);
+ if(!str) return 0;
+ if(present(str)==TO) // Ueberpruefe, ob dieses Objekt gemeint ist!
+ {
+ write("Fehler: Es fehlt ein Kleidungs-/Ruestungstyp. Folgende Typen gibt es:\n"
+ +nf_str1+nf_str2);
+ return 1;
+ }
+ strs=old_explode(str, " ");
+ notify_fail("Fehler: Du musst eine gueltige Objekt-Id angeben!\n"
+ +nf_str2);
+ if( sizeof(strs) < 2 ) return 0; // Nur 1 Par. und der ist nicht die Objekt-Id
+ if( sizeof(strs) == 2 ) // Anzahl Par. = 2
+ {
+ ob_id=strs[0];
+ was=strs[1];
+ if( IST_ZAHL(was) ) // Objekt-Id z.B. mit "schrank 2" angesprochen?
+ if(present(ob_id+" "+was)==TO) // Falls dieses Objekt gemeint ist und kein 3. Par!
+ {
+ write("Fehler: Es fehlt ein Kleidungs-/Ruestungstyp. Folgende Typen gibt es:\n"
+ +nf_str1+nf_str2);
+ return 1;
+ }
+ else
+ return 0;
+ }
+ else if( sizeof(strs) == 3 )
+ {
+ ob_id=strs[0]+" "+strs[1];
+ was=strs[2];
+ }
+ else // Anzahl erforderlicher Parameter ueberschritten!
+ return 0;
+ if(present(ob_id)!=TO) // Ueberpruefe, ob auch dieses Objekt gemeint ist!
+ return 0;
+ if(QueryProp(P_CNT_STATUS)!=CNT_STATUS_OPEN)
+ {
+ write("Dazu muesste "+name(WER,1)+" geoeffnet sein.\n");
+ return 1;
+ }
+//--- Hier ist Parameterpruefung zu Ende.
+ was=LOWER(was);
+ if(was!="alles")
+ auflistung2(was, nf_str1, nf_str2, 0);
+ else
+ {
+ auflistung2("helme", nf_str1, nf_str2, 1);
+ auflistung2("umhaenge", nf_str1, nf_str2, 1);
+ auflistung2("ruestungen", nf_str1, nf_str2, 1);
+ auflistung2("hosen", nf_str1, nf_str2, 1);
+ auflistung2("schuhe", nf_str1, nf_str2, 1);
+ auflistung2("handschuhe", nf_str1, nf_str2, 1);
+ auflistung2("guertel", nf_str1, nf_str2, 1);
+ auflistung2("amulette", nf_str1, nf_str2, 1);
+ auflistung2("ringe", nf_str1, nf_str2, 1);
+ auflistung2("koecher", nf_str1, nf_str2, 1);
+ auflistung2("schilde", nf_str1, nf_str2, 1);
+ auflistung2("sonstiges", nf_str1, nf_str2, 1);
+ }
+ TP->More(strall);
+ return 1;
+}
diff --git a/d/seher/haeuser/moebel/swift_std_container.c b/d/seher/haeuser/moebel/swift_std_container.c
new file mode 100644
index 0000000..90f4986
--- /dev/null
+++ b/d/seher/haeuser/moebel/swift_std_container.c
@@ -0,0 +1,611 @@
+//----------------------------------------------------------------------------
+// Name des Objects: Standard_Container
+// Letzte Aenderung: 21.03.2001
+// Magier: Swift
+// Dieses File wird anstelle von /std/container inherited, so dass dem Objekt
+// erweiterte Moeglichkeiten zur Verfuegung stehen.
+//
+// 07.12.2005 (Seleven): Kurzbeschreibung ausblendbar gemacht
+// 30.06.2007 (Zesstra): create der BP wird nicht mehr abgebrochen. Auf die
+// Art wird es dem Nutzer dieses Standardobjekt ueberlassen, ob er die BP
+// initialisieren will oder nicht.
+// 01.07.2007 (Zesstra): Update der Moebel ruft erstmal UpdateMe() in den
+// Moebeln auf. Wenn das != 0 liefert, ist UpdateMe() fuer das Update
+// zustaendig und muss das machen.
+// Ausserdem kleine Aenderung im Registrieren (nimmt auch Obekte als
+// Standort)
+// Weiterhin Moebel umgezogen nach /p/seher/moebel/ und in diesem File
+// GetOwner() definiert, welches "Swift" zurueckgibt. Wer hiervon erbt,
+// sollte damit also sein eigenes GetOwner() definieren.
+// glob. Variablen auf 'nosave' geaendert.
+//----------------------------------------------------------------------------
+
+
+// Fuer Testzwecke ist es moeglich, dem entsprechenden Objekt die Property
+// "test" auf 1 zu setzen, damit ist dann so ziemlich alles erlaubt.
+// Man sollte die Property aber unbedingt wieder entfernen, sonst ist es z.B.
+// moeglich, einen Schrank von Seherhaus A nach Seherhaus B oder sogar hinaus
+// zu verschieben !!!
+
+#pragma strong_types,save_types,rtt_checks
+
+#include <container.h>
+inherit "/std/container";
+
+#include "schrankladen.h"
+
+#define VERSION_STD "9"
+
+nosave int hauserlaubnis;
+nosave string zweitieerlaubnis;
+nosave string *erlaubnis;
+
+int erlaubt();
+
+protected void create()
+{
+ //if (!clonep(TO)) return;
+ ::create();
+ SetProp(P_SHORT, "Ein Standard_Container von Swift");
+ SetProp(P_CNT_STATUS,CNT_STATUS_CLOSED);
+ SetProp(P_TRANSPARENT, 0);
+ SetProp(P_LOG_FILE,"seleven/schraenker"); // Seleven 06.04.2006
+ SetProp("cnt_hausfreunde", ({}) );
+ SetProp("cnt_erlaubnis", ({}) );
+ SetProp("cnt_zweitieerlaubnis", "" );
+ SetProp("cnt_version_std", VERSION_STD);
+
+ hauserlaubnis=0;
+ zweitieerlaubnis="";
+ erlaubnis=({});
+
+ set_next_reset(3600); // 1 x pro Std. Reset!
+
+ AddCmd(({"oeffne"}), "oeffnen");
+ AddCmd(({"schliess", "schliesse"}), "schliessen");
+ AddCmd(({"serlaube"}), "erlaubnis");
+ AddCmd(({"skommandos"}), "skommandos");
+ AddCmd(({"verschieb", "verschiebe"}), "verschieben");
+ AddCmd(({"zertruemmer", "zertruemmere"}), "zertruemmern");
+ //Seleven 07.12.2005:
+ AddCmd(({"sverstecke","sversteck"}),"verstecken");
+ AddCmd(({"shole","shol"}),"zeigen");
+}
+
+// Zesstra, 1.7.07, fuers Hoerrohr
+string GetOwner() {return "swift";}
+
+static string QueryHausbesitzer()
+{
+ return CAP(to_string(ETO->QueryOwner())); // z.B.: Swift
+}
+
+
+
+static string QueryTP()
+{
+ return CAP(geteuid(TP)); // z.B.: Swift
+}
+
+int oeffnen(string str)
+{
+ notify_fail("Was moechtest Du oeffnen?\n");
+ if(!str) return 0;
+ if(present(str)!=TO) // Ueberpruefe, ob auch dieses Objekt gemeint ist!
+ return 0;
+ if(QueryProp(P_CNT_STATUS)==CNT_STATUS_OPEN)
+ {
+ write(Name(WER,1)+" ist doch schon geoeffnet!\n");
+ return 1;
+ }
+ if( !erlaubt() )
+ {
+ write("Ein magisches Kraftfeld verhindert das Oeffnen "+name(WESSEN,1)+"!\n");
+ return 1;
+ }
+ write("Du oeffnest "+name(WEN)+".\n");
+ say(TP->Name(WER)+" oeffnet "+name(WEN)+".\n", ({TP}) );
+ SetProp(P_CNT_STATUS,CNT_STATUS_OPEN);
+ SetProp(P_TRANSPARENT, 1);
+ return 1;
+}
+
+int schliessen(string str)
+{
+ notify_fail("Was moechtest Du schliessen?\n");
+ if(!str) return 0;
+ if(present(str)!=TO) // Ueberpruefe, ob auch dieses Objekt gemeint ist!
+ return 0;
+ if(QueryProp(P_CNT_STATUS)==CNT_STATUS_CLOSED)
+ {
+ write(Name(WER,1)+" ist doch schon geschlossen!\n");
+ return 1;
+ }
+ if( !erlaubt() )
+ {
+ write("Ein magisches Kraftfeld verhindert das Schliessen "+name(WESSEN,1)+"!\n");
+ return 1;
+ }
+ write("Du schliesst "+name(WEN)+".\n");
+ say(TP->Name(WER)+" schliesst "+name(WEN)+".\n", ({TP}) );
+ SetProp(P_CNT_STATUS,CNT_STATUS_CLOSED);
+ SetProp(P_TRANSPARENT, 0);
+ return 1;
+}
+
+string cnt_status()
+{
+ return Name(WER,1)+" ist "
+ +(QueryProp(P_CNT_STATUS)?"geschlossen":"geoeffnet")+".\n";
+}
+
+int erlaubt()
+{
+ if( QueryProp("test") ) return 1; // Zu Testzwecken!
+ if( QueryHausbesitzer()=="0" ) // Schrank steht nicht in einem Seherhaus!
+ {
+ tell_room(ETO, Name(WER,1)+" sollte nicht ausserhalb eines Seherhauses stehen.\n"
+ +"Bitte Mail an "+VERANTWORTLICHER_MAGIER+"!\n");
+ return 0;
+ }
+ if( QueryTP() == QueryHausbesitzer() ) // Der Besitzer des Hauses selbst
+ return 1;
+ if(hauserlaubnis)
+ {
+ if( member(SHVERWALTER->HausProp(LOWER(QueryHausbesitzer()), 2),
+ QueryTP()) != -1 ) // Hausfreunde
+ return 1;
+ }
+ if(zweitieerlaubnis!="") // Zweities
+ {
+ if( TP->QueryProp(P_SECOND) == zweitieerlaubnis )
+ return 1;
+ }
+ if( sizeof(erlaubnis) )
+ {
+ if( member(erlaubnis, QueryTP()) != -1 ) // Sonstige Personen die berechtigt sind
+ return 1;
+ }
+ return 0;
+}
+
+void cnt_open()
+{
+ SetProp(P_CNT_STATUS,CNT_STATUS_OPEN);
+ SetProp(P_TRANSPARENT, 1);
+}
+
+int erlaubnis_liste()
+{
+ int i;
+ string *strs,str;
+ if( QueryHausbesitzer() != QueryTP() && !QueryProp("test") )
+ {
+ write( BS("Nur "+QueryHausbesitzer()+" darf Berechtigungen "
+ +name(WESSEN,1)+" abfragen!"));
+ return 1;
+ }
+ write("=============================================================================\n");
+ if(hauserlaubnis)
+ {
+ strs=SHVERWALTER->HausProp(LOWER(QueryHausbesitzer()), 2);
+ write(BS("Folgende Freunde Deines Hauses duerfen "+name(WEN,1)
+ +" oeffnen/schliessen:"));
+ str="";
+ if(sizeof(strs))
+ {
+ for(i=0;i<sizeof(strs);i++)
+ {
+ str+=strs[i];
+ if(i<sizeof(strs)-1)
+ str+=", ";
+ }
+ }
+ else
+ str="Du hast keiner Person Zugriff auf Dein Haus gewaehrt...\n";
+ write(BS(str));
+ }
+ else
+ write(BS("Die Freunde Deines Hauses duerfen "+name(WEN,1)
+ +" nicht oeffnen/schliessen."));
+ write("-----------------------------------------------------------------------------\n");
+ if(zweitieerlaubnis!="")
+ {
+ if( zweitieerlaubnis==geteuid(TP) )
+ write(BS( "Alle Deine Zweities duerfen "+name(WEN,1)+" oeffnen/schliessen."));
+ else
+ write(BS( "Alle Zweities von "+CAP(zweitieerlaubnis)+" duerfen "+name(WEN,1)
+ +" oeffnen/schliessen."));
+ write("-----------------------------------------------------------------------------\n");
+ }
+ strs=QueryProp("cnt_erlaubnis");
+ if(sizeof(strs))
+ {
+ write(BS("Folgende sonstige Personen duerfen "+name(WEN,1)
+ +" oeffnen/schliessen:"));
+ str="";
+ for(i=0;i<sizeof(strs);i++)
+ {
+ str+=strs[i];
+ if(i<sizeof(strs)-1)
+ str+=", ";
+ }
+ write(BS(str));
+ }
+ else
+ write(BS("Es gibt keine sonstigen Personen, die "+name(WEN,1)
+ +" oeffnen/schliessen duerfen."));
+ write("=============================================================================\n");
+ return 1;
+}
+
+int erlaubnis(string str)
+{
+ string *strs,wen,nf_str;
+ nf_str="Syntax: serlaube [Objekt-Id] [Spielername|\"hausfreunde\"|\"zweities\"]\n"
+ +"Bsp.: serlaube "+QueryProp(P_IDS)[1]+" hausfreunde\n"
+ +" serlaube "+QueryProp(P_IDS)[1]+" zweities\n"
+ +" serlaube "+QueryProp(P_IDS)[1]+" geordi\n"
+ +" serlaube "+QueryProp(P_IDS)[1]+" (Listet Spieler mit Erlaubnis)\n";
+ notify_fail("Fehler: Ohne Parameter klappt das nicht.\n"+nf_str);
+ if(!str) return 0;
+ if(present(str)==TO) // Falls Par==Obj. und kein 2./3. Par.
+ {
+ erlaubnis_liste(); // Liste der Erlaubten ausgeben!
+ return 1;
+ }
+ notify_fail("Fehler: Du musst eine gueltige Objekt-Id angeben!\n"+nf_str);
+ strs=old_explode(str, " ");
+ if( sizeof(strs) < 2 ) // Falls nur 1 Par.
+ return 0; // Anzahl erforderlicher Parameter unterschritten!
+ else if( sizeof(strs) == 2 )
+ {
+ str=strs[0];
+ wen=strs[1];
+ if( IST_ZAHL(wen) )
+ if(present(str+" "+wen)==TO) // Falls 2 Par. und dies das Obj. ist ohne 3. Par.
+ {
+ erlaubnis_liste(); // Liste der Erlaubten ausgeben!
+ return 1;
+ }
+ else
+ return 0;
+ }
+ else if( sizeof(strs) == 3 )
+ {
+ str=strs[0]+" "+strs[1];
+ wen=strs[2];
+ }
+ else // Anzahl erforderlicher Parameter ueberschritten!
+ return 0;
+ if(present(str)!=TO) // Ueberpruefe, ob auch dieses Objekt gemeint ist!
+ return 0;
+ if( !erlaubt() && !QueryProp("test") )
+ {
+ write( BS("Nur "+QueryHausbesitzer()+" darf Berechtigungen "
+ +name(WESSEN,1)+" aendern!"));
+ return 1;
+ }
+ if(wen=="hausfreunde")
+ {
+ if(hauserlaubnis)
+ {
+ hauserlaubnis=0;
+ SetProp("cnt_hausfreunde", ({}) );
+ }
+ else
+ {
+ hauserlaubnis=1;
+ SetProp("cnt_hausfreunde", SHVERWALTER->HausProp(LOWER(QueryHausbesitzer()), 2) );
+ }
+ write( BS("Die Freunde Deines Seherhauses duerfen "+name(WEN,1)+" jetzt "
+ +(!hauserlaubnis?"nicht mehr ":"")+"oeffnen/schliessen."));
+ return 1;
+ }
+ if(wen=="zweities")
+ {
+ if(zweitieerlaubnis!="") // Zweities erlaubt?
+ zweitieerlaubnis=""; // dann verbieten!
+ else // ansonsten:
+ {
+ if( TP->QueryProp(P_SECOND) ) // Selbst ein Zweitie?
+ zweitieerlaubnis=LOWER(TP->QueryProp(P_SECOND)); // Die Zweities vom Erstie erlauben!
+ else // sonst:
+ zweitieerlaubnis=geteuid(TP); // Eigene Ersties erlauben!
+ }
+ SetProp("cnt_zweitieerlaubnis", zweitieerlaubnis );
+ if(zweitieerlaubnis!="")
+ write( BS(CAP(zweitieerlaubnis)+"'s Zweities duerfen "+name(WEN,1)+" jetzt "
+ +(zweitieerlaubnis==""?"nicht mehr ":"")+"oeffnen/schliessen."));
+ return 1;
+ }
+ wen=CAP(wen);
+ if( file_size("//save//"+LOWER(wen[0..0])+"//"+LOWER(wen)+".o") != -1 ) // Spieler gibt es auch!
+ {
+ if( member(erlaubnis, wen) != -1 ) // Spieler hat Erlaubnis -> verbieten!
+ {
+ erlaubnis-=({wen});
+ write( BS( wen+" darf "+name(WEN,1)+" jetzt nicht mehr oeffnen/schliessen."));
+ }
+ else
+ {
+ erlaubnis+=({wen});
+ write( BS( wen+" darf "+name(WEN,1)+" jetzt oeffnen/schliessen."));
+ }
+ SetProp("cnt_erlaubnis", erlaubnis);
+ return 1;
+ }
+ else
+ write("Es gibt keinen Spieler namens "+wen+"!\n");
+ return 1;
+}
+
+varargs int skommandos(string str)
+{
+ notify_fail( "Fehler: Dieser Befehl benoetigt eine gueltige Objekt-Id als Parameter.\n"
+ +"Beispiel: skommandos "+QueryProp(P_IDS)[1]+"\n");
+ if(!str) return 0;
+ if(present(str)!=TO ) // Bin ich gemeint?
+ return 0;
+ write("=============================================================================\n");
+ write("Aktuelle Version: "+QueryProp("cnt_version_std")+QueryProp("cnt_version_obj")+"\n");
+ write( BS(Name(WER,1)+" kann nur in diesem Seherhaus verwendet werden, "
+ +"da "+QueryPronoun(WER)+" speziell dafuer gekauft wurde. "+CAP(QueryPronoun(WER))
+ +" verfuegt ueber folgende Kommandos:")
+ +"-----------------------------------------------------------------------------\n"
+ +"oeffne [Objekt-Id]\n"
+ +" oeffnet "+name(WEN,1)+"\n\n"
+ +"schliesse [Objekt-Id]\n"
+ +" schliesst "+name(WEN,1)+"\n\n"
+ +"serlaube [Objekt-Id] [Spielername|\"hausfreunde\"|\"zweities\"]\n"
+ +" Erlaubt Personen, "+name(WEN,1)+" mitzubenutzen.\n"
+ +" serlaube + Objekt-Id (ohne Spielername/hausfreunde)\n"
+ +" listet alle Personen mit Zugriff auf "+name(WEN,1)+"\n\n"
+ +"verschiebe [Objekt-Id] nach [Ausgang]\n"
+ +" Damit kannst Du "+name(WEN,1)+" innerhalb Deines Seherhauses verschieben.\n\n"
+ //Seleven 07.12.2005
+ +"sverstecke [Objekt-Id]\n"
+ +" Damit machst Du "+name(WEN,1)+" unsichtbar.\n"
+ +"shole [Objekt-Id] hervor\n"
+ +" Damit machst Du "+name(WEN,1)+" wieder sichtbar.\n"
+ // Bis hier
+ +"zertruemmer [Objekt-Id]\n"
+ +" Damit zerstoerst Du "+name(WEN,1)+".\n\n");
+
+
+ if( QueryProp("obj_cmd") )
+ write( QueryProp("obj_cmd")+"\n" );
+
+ write("[Objekt-Id] muss eine gueltige Id sein, in diesem Fall z.B. "
+ +QueryProp(P_IDS)[1]+"\n");
+ write("=============================================================================\n");
+
+
+ return 1;
+}
+
+int verschieben(string str)
+{
+ string was, wohin, zielraum,nf_str;
+ nf_str="Syntax: verschiebe [Objekt-Id] nach [Richtung]\n"
+ +"Bsp.: verschiebe "+QueryProp(P_IDS)[1]+" nach osten\n";
+ notify_fail("Fehler: Ohne Parameter klappt das nicht.\n"+nf_str);
+ if(!str) return 0;
+ if(sscanf(str,"%s nach %s", was, wohin) != 2)
+ return 0;
+ notify_fail("Fehler: Du musst eine gueltige Objekt-Id angeben!\n"+nf_str);
+ if(present(was)!=TO) // Ueberpruefe, ob auch dieses Objekt gemeint ist!
+ return 0;
+ if( QueryHausbesitzer() != QueryTP() && !QueryProp("test") )
+ {
+ write( BS("Nur "+QueryHausbesitzer()+" darf "+name(WEN,1)+" verschieben!"));
+ return 1;
+ }
+ if( member(m_indices(ETO->QueryProp(P_EXITS)), wohin) != -1 ) // Ausgang vorhanden?
+ {
+ zielraum=ETO->QueryProp(P_EXITS)[wohin];
+ if( strstr(zielraum, LOWER(QueryHausbesitzer())+"raum", 0) != -1 ||
+ QueryProp("test") ) // Gleiches Seherhaus? Oder Test?
+ {
+ TO->move(zielraum, M_PUT);
+ write("Du verschiebst "+name(WEN,1)+" nach "+CAP(wohin)+".\n");
+ TP->move(zielraum, M_GO, "nach "+CAP(wohin), "schiebt "+name(WEN),
+ "schiebt "+name(WEN)+" herein");
+ if( present("Interactive", SCHRANKMASTER) )
+ tell_room(SCHRANKMASTER, TP->Name(WER)+" verschiebt "+name(WEN)+" nach "
+ +to_string(ETO)+".\n");
+ }
+ else
+ write( BS("Du kannst "+name(WEN,1)+" nicht in einen Raum ausserhalb "
+ +"Deines Hauses schieben!"));
+ }
+ else
+ write( BS("Es gibt keinen Ausgang namens \""+wohin+"\", wohin Du "
+ +name(WEN,1)+" verschieben koenntest.",78,"Fehler: ", BS_INDENT_ONCE));
+ return 1;
+}
+
+int zertruemmern(string str)
+{
+ string nf_str;
+ nf_str="Syntax: zertruemmer [Objekt-Id]\n"
+ +"Bsp.: zertruemmer "+QueryProp(P_IDS)[1]+"\n";
+ notify_fail("Fehler: Ohne Parameter klappt das nicht.\n"+nf_str);
+ if(!str) return 0;
+ notify_fail("Fehler: Du musst eine gueltige Objekt-Id angeben!\n"+nf_str);
+ if(present(str)!=TO) // Ueberpruefe, ob auch dieses Objekt gemeint ist!
+ return 0;
+ if( QueryHausbesitzer() != QueryTP() && !QueryProp("test") )
+ {
+ write( BS("Nur "+QueryHausbesitzer()+" darf "+name(WEN,1)+" zertruemmern!"));
+ return 1;
+ }
+ write( BS("Du zertruemmerst "+name(WEN)+" mit wuchtigen Schlaegen, bis "
+ +"nicht mal mehr Kruemel von "+QueryPronoun(WEM)+" uebrig sind."));
+ tell_room(ETO, BS( TP->Name(WER)+" zertruemmert "+name(WEN)+"."), ({TP}) );
+ call_other(SCHRANKMASTER,"???",0);
+ if( present("Interactive", SCHRANKMASTER) )
+ tell_room(SCHRANKMASTER, TP->Name(WER)+" zertruemmert "+name(WEN)+".\n");
+ SCHRANKMASTER->RemoveCnt(TO, geteuid(TP) );
+ remove(1);
+ if(TO) destruct(TO);
+ return 1;
+}
+
+int props2vars() // Fuer die Update-Funktion des Schrankmasters
+{
+ zweitieerlaubnis=QueryProp("cnt_zweitieerlaubnis")||"";
+ erlaubnis=QueryProp("cnt_erlaubnis")||({});
+ if( sizeof(QueryProp("cnt_hausfreunde")) )
+ hauserlaubnis=1;
+ else
+ hauserlaubnis=0;
+ if( QueryProp(P_CNT_STATUS) == CNT_STATUS_OPEN)
+ SetProp(P_TRANSPARENT, 1);
+ else
+ SetProp(P_TRANSPARENT, 0);
+ return 1;
+}
+
+void reset()
+{
+ set_next_reset(3600); // 1 x pro Std. Reset!
+ ::reset();
+}
+
+public varargs int remove(int silent)
+{
+ // Beim Schrankmaster abmelden, dann zerstoeren.
+ string uid="";
+ if (objectp(environment()))
+ {
+ uid=environment()->QueryOwner();
+ }
+ SCHRANKMASTER->RemoveCnt(TO, uid );
+ return ::remove(silent);
+}
+
+public int UpdateMe()
+{
+ if (!objectp(environment()))
+ return 0;
+ object cnt_neu=clone_object(load_name(ME)); // Neuen Schrank clonen
+ cnt_neu->move( environment(), M_NOCHECK ); // In selben Raum wie alten schieben...
+ cnt_neu->SetProp("cnt_status", QueryProp("cnt_status") );
+ cnt_neu->SetProp("cnt_hausfreunde", QueryProp("cnt_hausfreunde") );
+ cnt_neu->SetProp("cnt_erlaubnis", QueryProp("cnt_erlaubnis") );
+ cnt_neu->SetProp("cnt_zweitieerlaubnis", QueryProp("cnt_zweitieerlaubnis") );
+ cnt_neu->props2vars(); // Schrank liest gesetzte Props aus in eigene Vars
+ // Inventar bewegen
+ foreach(object inv: all_inventory(this_object()))
+ {
+ if( inv->IsUnit() ) // Units
+ inv->move(cnt_neu, M_NOCHECK|M_MOVE_ALL);
+ else // Normale Objekte
+ inv->move(cnt_neu, M_NOCHECK);
+ }
+ remove(1);
+ return 1;
+}
+
+// Eingebaut 07.12.2005 von Seleven
+// Die Kurzbeschreibung invis machen:
+static int verstecken (string str)
+{
+ string nf_str;
+ nf_str="Syntax: sverstecke [Objekt-Id]\n"
+ +"Bsp.: sverstecke "+QueryProp(P_IDS)[1]+"\n";
+ notify_fail("Fehler: Ohne Parameter klappt das nicht.\n"+nf_str);
+ if(!str || sizeof(str) == 0 || !stringp(str)) return 0;
+
+ notify_fail("Fehler: Du musst eine gueltige Objekt-Id angeben!\n"+nf_str);
+ if(present(str)!=TO) // Ueberpruefe, ob auch dieses Objekt gemeint ist!
+ return 0;
+
+ if( QueryHausbesitzer() != QueryTP() && !QueryProp("test") )
+ {
+ write( BS("Nur "+QueryHausbesitzer()+" darf "+name(WEN,1)+" verstecken!"));
+ return 1;
+ }
+ notify_fail("Du hast "+name(WEN,1)+" doch schon versteckt!\n");
+ if(QueryProp("versteckt") == 1) return 0;
+ write("Du versteckst "+name(WEN,1)+".\n");
+ SetProp("versteckt", 1);
+ return 1;
+}
+
+static int zeigen (string str)
+{
+ string nf_str;
+ nf_str="Syntax: shole [Objekt-Id] hervor\n"
+ +"Bsp.: shole "+QueryProp(P_IDS)[1]+" hervor\n";
+ notify_fail("Fehler: Ohne Parameter klappt das nicht.\n"+nf_str);
+ if(!str || sizeof(str) == 0 || !stringp(str)) return 0;
+ if(strstr(str,"hervor") != -1)
+ sscanf(str,"%s hervor",str);
+ notify_fail("Fehler: Du musst eine gueltige Objekt-Id angeben!\n"+nf_str);
+ if(present(str)!=TO) // Ueberpruefe, ob auch dieses Objekt gemeint ist!
+ return 0;
+
+ if( QueryHausbesitzer() != QueryTP() && !QueryProp("test") )
+ {
+ write( BS("Nur "+QueryHausbesitzer()+" darf "+name(WEN,1)+
+ " wieder hervorholen!"));
+ return 1;
+ }
+ notify_fail(Name(WER,1)+" ist doch gar nicht versteckt!\n");
+ if(QueryProp("versteckt") == 0) return 0;
+ write("Du holst "+name(WEN,1)+" aus dem Versteck.\n");
+ SetProp("versteckt", 0);
+ return 1;
+}
+
+
+mixed short()
+{
+ string sh;
+
+ // Unsichtbar? Dann gibts nichts zu sehen ...
+ if (QueryProp(P_INVIS)||!(sh=QueryProp(P_SHORT)))
+ return 0;
+
+ if(QueryProp(P_CNT_STATUS)==CNT_STATUS_OPEN)
+ {sh += " (geoeffnet)";}
+
+ if(QueryProp("versteckt") == 1) {sh = "";}
+ else sh += ".";
+
+ return process_string(sh)+"\n";
+}
+
+// hier nicht genutzt, zum Ueberschreiben gedacht.
+protected void SetBesitzer(string uid, string uuid) { }
+
+// nach dem move schauen, ob man in einem Seherhaus ist. Wenn ja, wird die
+// Funktion SetBesitzer() gerufen und ihr UID und UUID des Eigentuemers
+// uebergeben. Sollten UID und/oder UUID nicht bestimmbar sein, wird die
+// Funktion nicht gerufen.
+protected void NotifyMove(object dest, object oldenv, int method)
+{
+
+ ::NotifyMove(dest, oldenv, method);
+
+ if (dest
+ && strstr(object_name(dest),"/d/seher/haeuser/") == 0)
+ {
+ // (vermutlich) in einem Seherhaus
+ string uid = dest->QueryOwner();
+ // erstmal beim Schrankmaster anmelden.
+ SCHRANKMASTER->RegisterCnt(TO, QueryProp("cnt_version_std")
+ +":"+QueryProp("cnt_version_obj"), uid, dest);
+ // UUID rausfinden
+ mixed ret = (mixed)master()->get_userinfo(uid);
+ if ( pointerp(ret) && sizeof(ret) >= 5 )
+ {
+ // Username + "_" + CreationDate
+ SetBesitzer(uid, ret[0] + "_" + ret[5]);
+ }
+ // else: User unbekannt? -> jedenfalls keine initialisierung moeglich.
+ }
+}
+
diff --git a/d/seher/haeuser/moebel/tresor.c b/d/seher/haeuser/moebel/tresor.c
new file mode 100644
index 0000000..ecad6d7
--- /dev/null
+++ b/d/seher/haeuser/moebel/tresor.c
@@ -0,0 +1,78 @@
+//--------------------------------------------------------------------------------
+// Name des Objects: Tresor
+// Letzte Aenderung: 17.03.2001
+// Magier: Swift
+//--------------------------------------------------------------------------------
+#pragma strong_types,rtt_checks
+
+#include "schrankladen.h"
+inherit LADEN("swift_std_container");
+
+#define VERSION_OBJ "3"
+
+protected void create()
+{
+ if (!clonep(TO)) return;
+ swift_std_container::create();
+ SetProp(P_SHORT, "Ein Tresor");
+ SetProp(P_LONG, BS(
+ "Ein sehr stabiler und feuersicherer Tresor, an dem sich sicher schon so "
+ +"mancher Einbrecher eine Abfuhr geholt hat. Das magische Feld, das den "
+ +"Tresor umgibt, verhindert wohl auch Attacken magischer Art. So wuchtig "
+ +"und wichtig, wie dieser Klotz aussieht, vermutest Du wohl zu Recht, "
+ +"dass sich unsagbare Reichtuemer in seinem Inneren verbergen muessen.")
+ +"@@cnt_status@@");
+ AddId(({"tresor"}));
+ SetProp("cnt_version_obj", VERSION_OBJ);
+ SetProp(P_NAME, "Tresor");
+ SetProp(P_GENDER, MALE);
+ SetProp(P_WEIGHT, 5000); // Gewicht 5 Kg
+ SetProp(P_MAX_WEIGHT, 1000000); // Es passen fuer 1000 kg Sachen rein.
+ SetProp(P_WEIGHT_PERCENT, 100); // Dafuer macht er auch nix leichter :)
+ SetProp(P_MAX_OBJECTS, 100); // Mehr sollte nicht sein, lt. Tiamak.
+ SetProp(P_VALUE, 0); // Kein materieller Wert. Ist eh nicht verkaufbar.
+ SetProp(P_NOBUY, 1); // Wird im Laden zerstoert, falls er verkauft wird.
+ SetProp(P_NOGET, "Das geht nicht. "+Name(WER,1)+" haftet wie magisch am Boden.\n");
+ SetProp(P_MATERIAL, ({MAT_STEEL, MAT_MISC_MAGIC}) );
+ SetProp(P_INFO, "Versuchs mal mit: \"skommandos "+QueryProp(P_IDS)[1]+"\" !\n");
+
+ AD(({"feld"}), BS("Ein starkes magisches Feld umgibt "+name(WEN,1)+"."));
+ AD(({"klotz"}), BS(Name(WER,1)+" ist wahrlich ein Klotz, ausgesprochen wuchtig."));
+}
+
+varargs int PreventInsert(object ob)
+{
+ // Zuerst mal: Dinge, deren Wert >= 5000 Muenzen ist, duerfen rein, solange
+ // es keine Ruestungen oder Waffen sind!
+ if( ob->QueryProp(P_VALUE) >= 5000 && !ob->QueryProp(P_ARMOUR_TYPE) &&
+ !ob->QueryProp(P_WEAPON_TYPE) )
+ return ::PreventInsert(ob);
+ if( ob->id("\ngeld") || // Geld?
+ ob->QueryMaterialGroup(MATGROUP_PRECIOUS_METAL) || // Edelmetall?
+ ob->QueryMaterialGroup(MATGROUP_JEWEL) || // Edelstein?
+ ob->QueryMaterial(MAT_CRYSTAL) || // Kristall?
+ ob->QueryMaterial(MAT_IVORY) ) // Elfenbein?
+ {
+ if(!ob->QueryProp(P_WEAPON_TYPE) ) // Auf keinen Fall Waffen!
+ {
+ if( ob->QueryProp(P_ARMOUR_TYPE ) ) // Falls Ruestungsteil...
+ {
+ if( ob->QueryProp(P_ARMOUR_TYPE)==AT_RING ||
+ ob->QueryProp(P_ARMOUR_TYPE)==AT_AMULET ||
+ ob->QueryProp(P_ARMOUR_TYPE)==AT_MISC )
+ return ::PreventInsert(ob);
+ else
+ write(BS("Nur wertvolle Ringe und Amulette kannst Du in "+name(WEN,1)
+ +" stecken, evtl. noch andere wertvolle Sachen, aber auf keinen "
+ +"Fall Ruestungen oder Waffen!"));
+ }
+ else
+ return ::PreventInsert(ob);
+ }
+ else
+ write("Waffen kannst Du nicht in "+name(WEN,1)+" tun!\n");
+ }
+ write( BS("In "+name(WEN,1)+" kannst Du nur Geld und Edelsteine legen, evtl. auch "
+ +"wertvolle Objekte, z.B. aus Edelmetallen, Kristall oder Elfenbein!"));
+ return 1;
+}
diff --git a/d/seher/haeuser/moebel/verkaeufer.c b/d/seher/haeuser/moebel/verkaeufer.c
new file mode 100644
index 0000000..5143ab2
--- /dev/null
+++ b/d/seher/haeuser/moebel/verkaeufer.c
@@ -0,0 +1,311 @@
+//--------------------------------------------------------------------------------
+// Name des Objects: Verkaeufer (August vom SCHRAENKER)
+// Letzte Aenderung: 24.08.2006
+// Magier: Seleven
+//--------------------------------------------------------------------------------
+#pragma strong_types,rtt_checks
+
+#include <properties.h>
+#include <language.h>
+#include <moving.h>
+#include <wizlevels.h>
+#include <bank.h>
+
+#include "schrankladen.h"
+inherit "/std/npc";
+
+// Wenn im Laden bzw. im Environment von August die Prop "test" auf 1 gesetzt
+// wird, kostet der Kauf nichts. Jeder der ein Seherhaus besitzt, kann kaufen.
+
+// Fuer Prop im Spieler = individuellere Begruessung
+#define LASTVISIT "schrankladen_lastvisit"
+// 10% Rabatt fuer Leute, die intensiv testeten, Ideen fuer den Laden beisteuerten,
+// oder halfen, groessere Bugs zu beheben!
+#define RABATT ({"geordi","foobar","blood","lurchi", "eldaron"})
+
+// kaufe... andere im raum sollten vor der antwort sehen wer august nach was fragt
+
+protected void create()
+{
+ if(!clonep(TO)) return;
+ ::create();
+ SetProp(P_LOG_FILE,"seleven/schraenker"); // Seleven 06.04.2006
+ SP(P_SHORT, "August");
+ SP(P_LONG, BS(
+ "Das ist August, ein kleiner Zwerg und seines Zeichens Seher-Berater. "
+ +"Er versorgt Seher mit Eigenheim mit dem Mobiliar, das man braucht, "
+ +"will man sein Haus uebersichtlich halten und etwas Ordnung in die "
+ +"Sammlungen bringen, die sich in so einem Seherhaus zwangslaeufig "
+ +"anhaeufen. Im Gegensatz zu den meisten Zwergen sieht August nicht nur "
+ +"aus wie frisch geduscht, er steckt auch in einem feinen Anzug. So "
+ +"einen gepflegten Bart wie den von August hast Du vorher noch nie "
+ +"gesehen. Und dann duftet er auch noch nach irgendeinem exotischen "
+ +"Waesserchen. Waere nicht der gierige Blick in seinen Augen, koenntest "
+ +"Du wirklich zweifeln, dass es sich hier wirklich um einen Zwerg "
+ +"handelt.",78,0,1));
+ SP(P_NAME, "August");
+ SP(P_GENDER, MALE);
+ SP(P_ARTICLE, 0);
+ SP(P_RACE, "Zwerg");
+ // Arathorn, 2015-Okt-13, Zeile vor P_XP gezogen, damit auch sicher kein
+ // EK angezeigt wird.
+ create_default_npc(20);
+ SP(P_XP, 0);
+ AddId(({"august", "inhaber", "ladeninhaber", "besitzer",
+ "firmenbesitzer", "verkaeufer", "zwerg", "seher-berater"}));
+
+ SP(P_SIZE, 130);
+ SP(P_NO_ATTACK, BS("Die beruhigende Melodie scheint nicht nur zum "
+ +"Vergnuegen der Kunden zu erklingen. Du bringst es einfach "
+ +"nicht fertig, Deine Hand gegen August zu erheben!"));
+
+ AD(({"anzug"}), BS(Name(WER)+" steckt in einem feinen rotbraunen Anzug, "
+ +"in dem vermutlich auch ein Bettler koeniglich auf Dich wirken wuerde. "
+ +"Offensichtlich ist er nicht der Aermsten einer."));
+ AD(({"bettler"}), BS("Wie ein Bettler wirkt August nicht auf Dich."));
+ AD(({"waesserchen"}), BS("Es riecht koestlich. Schnupper doch mal!"));
+ AD(({"bart"}), BS("Der vermutlich weisse Bart wurde von Kuenstlerhand "
+ +"roetlich eingefaerbt und passt farblich vorzueglich zum Anzug."));
+ AD(({"kuenstlerhand"}), BS("Bestimmt hat August das nicht selbst gemacht."));
+ AD(({"mobiliar"}), BS("Das verkauft er hier."));
+ AD(({"augen"}), BS("Obwohl "+Name(WER)+" perfekte Manieren an den Tag "
+ +"legt, seine Augen verraten ihn. Die Dollarzeichen in seinem Blick "
+ +"sind nicht zu uebersehen."));
+ AD(({"dollarzeichen"}), BS("Eine Redensart. Keine Ahnung was das sein soll."));
+ AD(({"redensart"}), BS("Irgend ein Spruch, den Du irgendwo aufgeschnappt hast."));
+ AD(({"spruch"}), BS("Im Spruecheklopfen bist Du gut, oder?"));
+ AD(({"spruecheklopfen"}), BS("OK, ich geb auf. :)"));
+ AD(({"manieren"}), "Und das bei einem Zwerg!!!\n");
+
+ AddInfo(({"laden", "schraenker"}), "Der Schraenker ist mein Laden, "
+ +"und ich denke es ist ein guter Laden. Das Geschaeft laeuft, seit "
+ +"jeder Ordnung in seinem Seherhaus haben moechte. Und Seherhaeuser "
+ +"gibt es ja mehr als genug! :)", "sagt: ");
+ AddInfo(({"haeuser", "seherhaeuser"}), "Bei mir koennen Seher "
+ +"Mobiliar fuer ihr Seherhaus kaufen. Unsere Qualitaet ist weithin "
+ +"beruehmt. Ausserdem sind wir die einzigen auf dem Markt.", "grinst: ");
+ AddInfo(({"melodie"}), "lauscht vertraeumt.\n");
+ AddInfo(({"geld"}), "Sie haben doch welches?\n", "fragt besorgt: ");
+ // Seleven 01.04.2006: frage nach (schluessel)brett eingefuegt
+ AddInfo(({"mobiliar", "schrank", "schraenke", "truhe", "truhen", "kommode",
+ "kuehlschrank", "waffenschrank", "waffentruhe", "spind", "kleiderschrank","brett","schluesselbrett",
+ "muellcontainer", "zauberkiste", "tresor", "holztruhe","vitrine","pult","lesepult"}),
+ "Lesen Sie doch bitte die Preisliste an der Wand.", "sagt: ");
+ AddInfo(({"liefern", "lieferung"}), "Wir liefern sofort.", "sagt: ");
+ AddInfo(({"bart"}), "Es ist ein schoener Bart, nicht? :)", "fragt: ");
+ AddInfo(({"augen"}), "Was haben Sie an denen auszusetzen?", "fragt: ");
+ AddInfo(({"dusche"}), "Jeden Morgen. Das ist leider Pflicht. Und 364 mal "
+ +"zu oft :(", "sagt: ");
+ AddInfo(({"pflicht", "pflichten"}), "Als Ladeninhaber hat man deren "
+ +"viele!", "sagt: ");
+ AddInfo(({"anzug"}), "Ein echter Armgani!", "verkuendet stolz: ");
+ AddInfo(({"armgani"}), "Du kennst Armgani nicht?", "fragt naseruempfend: ");
+ AddInfo(({"geordi"}), "Von ihm stammt die urspruengliche Geschaeftsidee "
+ +"fuer den SCHRAENKER. Dafuer bekommt er bei uns auch Rabatt!", "erzaehlt: ");
+ AddInfo(({"august"}), "Wollen Sie sich ueber mich lustig machen?", "fragt drohend: ");
+ AddInfo(({"rabatt"}), "Nur Stammkunden, die uns schon brauchbare Ideen "
+ +"geliefert haben, oder die uns beim Aufbau des Geschaefts geholfen haben, "
+ +"gewaehren wir Rabatt.", "sagt: ");
+ AddInfo(({"ideen"}), "Es muessen brauchbare Ideen sein.", "sagt: ");
+ AddInfo(({"stammkunde", "stammkunden"}), "Einige kommen oefter vorbei.", "sagt: ");
+ AddInfo(({"aufbau"}), "Es kommt mir noch so vor, als waers gestern gewesen.", "sagt: ");
+ AddInfo(({"kunde", "kunden"}), "Ich hoffe mal, dass SIE der Kunde sind!?", "sagt: ");
+
+ AddCmd(({"kauf", "kaufe", "bestell", "bestelle"}), "container_kaufen");
+ AddCmd(({"schnupper", "schnuppere"}), "schnuppern");
+}
+
+int schnuppern()
+{
+ write(BS("Ein betoerender Duft umgibt August, und verdeckt jeglichen Geruch, "
+ +"den Du von sonstigen Zwergen gewohnt bist."));
+ return 1;
+}
+
+static string anrede()
+{
+ switch( TP->QueryProp(P_GENDER) )
+ {
+ case MALE : return "mein Herr"; break;
+ case FEMALE : return "meine Dame"; break;
+ }
+ return "mein H... D... Wasauchimmer";
+}
+
+void begruessung(object pl, string txt)
+{
+ if( objectp(pl) && present(pl) )
+ tell_room(ETO, "\n"+txt);
+}
+
+void init()
+{
+ ::init();
+ if (!interactive(TP) || TP->QueryProp(P_INVIS))
+ return 0; // Keine Meldungen wenn invis oder kein Spieler!
+ if(TP->QueryProp(LASTVISIT) < time()-3600) // laenger als 1 Std. nicht da gewesen
+ {
+ if( member(RABATT, geteuid(TP)) != -1 )
+ call_out("begruessung", 0, TP, BS("Herzlichst Willkommen in meinem "
+ +"bescheidenen Laden, "+TP->name(WER)+". Es ist jedesmal eine Freude, "
+ +"Sie zu sehen!",78, Name(WER)+" sagt: "));
+ else
+ call_out("begruessung", 0, TP, BS("Willkommen in meinem bescheidenen Laden, "
+ +anrede()+".",78, Name(WER)+" sagt: "));
+ }
+ else // schonmal innerhalb 1 Std. da gewesen?
+ {
+ if( member(RABATT, geteuid(TP)) != -1 )
+ call_out("begruessung", 0, TP, BS("Hallo, "+TP->name(WER)+". "
+ +"Sie konnten es ja nicht lange ohne mich aushalten, aber Stammkunden "
+ +"sind mir die liebsten Kunden. Womit kann ich Ihnen diesmal "
+ +"dienen?",78, Name(WER)+" sagt: "));
+ else
+ call_out("begruessung", 0, TP, BS("Guten Tag, "+anrede()+". "
+ +"Ich freue mich, dass Sie meinen Laden so bald wieder besuchen kommen! "
+ +"Womit kann ich Ihnen diesmal dienen?",78, Name(WER)+" sagt: "));
+ }
+
+ TP->SetProp(LASTVISIT, time() );
+}
+
+int container_kaufen(string str)
+{
+ string cnt_file;
+ int preis;
+ object zielraum,cnt,ob;
+ tell_room(ETO, TP->Name(WER)+" wendet sich wegen eines Kaufs an "
+ +Name(WEN)+".\n", ({TP}) );
+ if( (query_wiz_level(TP) >= SEER_LVL && query_wiz_level(TP) < LEARNER_LVL) ||
+ ETO->QueryProp("test") ) // TP ist Seher, oder Testmodus.
+ {
+ catch(call_other("/d/seher/haeuser/"+geteuid(TP)+"raum0", "???", 0));
+ if( !zielraum=find_object("/d/seher/haeuser/"+geteuid(TP)+"raum0") )
+ {
+ tell_room(ETO, BS("Tut mir leid, "+anrede()+". Voraussetzung fuer eine "
+ +"Lieferung unserer Artikel ist ein begehbares "
+ +"Seherhaus.",78, Name(WER)+" sagt: "));
+ return 1;
+ }
+ notify_fail( BS("Tut mir leid, "+anrede()+". So einen Artikel fuehren wir nicht. "
+ +"Bitte lesen Sie die Preisliste an der Wand. Dort koennen Sie sich genau "
+ +"darueber informieren, ueber welche Artikel wir zur Zeit "
+ +"verfuegen.",78, Name(WER)+" sagt: "));
+ if(!str) return 0;
+ switch(str)
+ {
+ case "1" :
+ case "kommode" : cnt_file="kommode";
+ preis=3799;
+ break;
+ case "2" :
+ case "kleiderschrank": cnt_file="kleiderschrank";
+ preis=5899;
+ break;
+ case "3" :
+ case "spind" : cnt_file="spind";
+ preis=5299;
+ break;
+ case "4" :
+ case "kuehlschrank" : cnt_file="kuehlschrank";
+ preis=3499;
+ break;
+ case "5" :
+ case "waffenschrank" : cnt_file="waffenschrank";
+ preis=5899;
+ break;
+ case "6" :
+ case "waffentruhe" : cnt_file="waffentruhe";
+ preis=5399;
+ break;
+ case "7" :
+ case "tresor" : cnt_file="tresor";
+ preis=4499;
+ break;
+ case "8" :
+ case "zauberkiste" : cnt_file="zauberkiste";
+ preis=7999;
+ break;
+ case "9" :
+ case "muellcontainer": cnt_file="muellcontainer";
+ preis=999;
+ break;
+ // Seleven 01.04.2006
+ case "10" :
+ case "schluesselbrett": cnt_file="schluesselbrett";
+ preis=499;
+ break;
+ case "11" :
+ case "duschkabine": cnt_file="wasch";
+ preis=3499;
+ break;
+ case "12":
+ case "holztruhe":
+ cnt_file="autoloadertruhe";
+ preis=74999;
+ break;
+ case "13":
+ case "vitrine":
+ cnt_file="vitrine";
+ preis=49999;
+ break;
+ case "14":
+ case "lesepult":
+ cnt_file="lesepult";
+ preis=60000;
+ break;
+ default: return 0; break;
+ }
+ if( member(RABATT, geteuid(TP)) != -1 ) // 10% Rabatt fuer bestimmte Leute,
+ preis=preis/100*90; // die Ideen fuer den Laden beisteuerten.
+ if( !ETO->QueryProp("test") )
+ {
+ if( !TP->QueryMoney() )
+ {
+ tell_room(ETO, BS("Ohne Geld bekommen Sie bei uns nichts, "+anrede()
+ +". Wir sind kein Wohlfahrtsinstitut!",78, Name(WER)+" sagt: "));
+ return 1;
+ }
+ if( TP->QueryMoney() < preis )
+ {
+ tell_room(ETO, BS( CAP(anrede())+", Sie haben zuwenig Geld dabei. "
+ +"Der Preis fuer dieses Objekt ist "+preis
+ +" Muenzen.",78, Name(WER)+" sagt: "));
+ return 1;
+ }
+ TP->AddMoney(-preis); // Spieler Geld abziehen
+ ZENTRALBANK->PayIn(preis); // Geld auf die Bank.
+ }
+ cnt=clone_object( LADEN(cnt_file) );
+ cnt->move(zielraum, M_PUT|M_SILENT);
+ tell_room(ETO, TP->Name(WER)+" kauft "+cnt->name(WEN)+".\n", ({TP}) );
+ tell_room(ETO, BS("Es ist ein Vergnuegen, mit Ihnen Geschaefte zu machen, "
+ +anrede()+"! Wenn Sie in Ihr Haus zurueckkehren, werden Sie die Ware bereits "
+ +"vorfinden, so schnell arbeiten wir.",78, Name(WER)+" sagt: "));
+ tell_room(zielraum, BS("Mit Knall und Schwefelduft erscheint ein kleines, "
+ +"verhutzeltes Maennchen. Es traegt einen gruenen Anzug und eine gruene "
+ +"Kappe, auf der in gelbem Schriftzug \"SCHRAENKER\" steht. Das Maennchen "
+ +"stellt "+cnt->name(WEN)+" ab und verschwindet auf dem gleichen Wege, wie "
+ +"es hereingekommen ist."));
+ if( present("Interactive", SCHRANKMASTER) )
+ tell_room(SCHRANKMASTER, TP->Name(WER)+" kauft "+name(WEN)+".\n");
+ SCHRANKMASTER->RegisterCnt(cnt, cnt->QueryProp("cnt_version_std")
+ +cnt->QueryProp("cnt_version_obj"), geteuid(TP),
+ "/d/seher/haeuser/"+geteuid(TP)+"raum0");
+ return 1;
+ }
+ else if(query_wiz_level(TP) >= LEARNER_LVL ) // TP ist Magier.
+ {
+ tell_room(ETO, BS("Tut mir leid, "+anrede()+". An Magier liefern wir nichts. "
+ +"Das ist ein Prinzip des Hauses, und Prinzipien sind dazu da, dass "
+ +"sie eingehalten werden. ",78, Name(WER)+" sagt: "));
+ return 1;
+ }
+ else // TP ist Spieler, kein Seher oder Magier.
+ {
+ tell_room(ETO, BS("Tut mir leid, "+anrede()+". Wir liefern nur an Seher. "
+ +"Aber da ich Sie als strebsame und erfolgreiche Person ansehe, "
+ +"bin ich sicher, dass wir uns bald wiedersehen!",78, Name(WER)+" sagt: "));
+ return 1;
+ }
+}
diff --git a/d/seher/haeuser/moebel/vitrine.c b/d/seher/haeuser/moebel/vitrine.c
new file mode 100644
index 0000000..ae5bb96
--- /dev/null
+++ b/d/seher/haeuser/moebel/vitrine.c
@@ -0,0 +1,339 @@
+/************************************************************************************
+Vitrine fuer die Pokale
+Autor: Miril
+letzte Aenderung:
+05.09.2011
+************************************************************************************/
+
+#include <properties.h>
+#include <defines.h>
+#include <wizlevels.h>
+#include "/d/ebene/miril/fraternitas/fraternitas.h"
+#include "/d/ebene/miril/fraternitas/trophy.h"
+#pragma strong_types,rtt_checks
+#include "/d/seher/haeuser/moebel/moebel.h"
+#include "/d/seher/haeuser/haus.h"
+
+inherit LADEN("swift_std_container");
+
+string besitzer;
+int staub;
+string *trophynamen;
+
+static string my_long();
+static string staub_descr();
+void GetTrophyDetails();
+string *GetAllTrophyNames();
+void NeueDetails();
+
+protected void create()
+{
+ if (!clonep(this_object())){
+ set_next_reset(-1);
+ return;
+ }
+ set_next_reset(86400);
+ ::create();
+ besitzer="";
+ staub=0;
+ SetProp(P_NAME,"Vitrine");
+ SetProp(P_SHORT,"Eine Vitrine");
+ Set(P_LONG,#'my_long,F_QUERY_METHOD);
+ SetProp(P_GENDER,FEMALE);
+ SetProp(P_MATERIAL,([MAT_GLASS:50,MAT_EBONY:50]));
+ SetProp(P_VALUE,10000);
+ SetProp(P_WEIGHT,500000);
+ SetProp(P_MAX_OBJECTS,0);
+ SetProp(P_MAX_WEIGHT,0);
+ SetProp(H_FURNITURE,1);
+ SetProp(P_NOGET,"Die Vitrine ist viel zu schwer.\n");
+ SetProp("cnt_version_obj",2);
+ GetTrophyDetails();
+ AddId(({"\nmiril_pokal_vitrine","vitrine"}));
+
+ NeueDetails();
+
+ AddCmd(({"saeubere","saeuber","reinige","reinig","mach","mache"}),
+ "saeuber_cmd");
+
+ AddCmd(({"stelle","stell"}),"stell_cmd");
+ RemoveCmd(({"serlaube"}));
+
+}
+
+void reset(){
+ ++staub;
+ set_next_reset(86400);
+ ::reset();
+ return;
+}
+
+void SetBesitzer(string uid,string uuid){
+ besitzer=uuid;
+ GetTrophyDetails();
+ return;
+}
+
+string QueryBesitzer(){
+ return besitzer;
+}
+
+void NeueDetails(){
+ AddDetail(({"holz","ebenholz"}),BS("Die Vitrine besteht teilweise "
+ "aus Ebenholz. Tueren, Deckel und Einlegeboeden sind aus Glas."));
+ AddDetail(({"tueren","tuer","glastueren","glastuer","deckel"}),BS(
+ "Durch das Glas kannst Du ins Innere der Vitrine gucken."));
+ AddDetail(({"inneres","gegenstaende","gegenstand"}),
+ BS("Dort kann man Pokale hineinstellen, aber nicht wieder "
+ "herausnehmen."));
+ AddDetail(({"glas","scheibe","scheiben"}),
+ BS("Glas ist praktisch, solange es sauber ist: "
+ "Man kann dadurch ins Innere schauen."));
+ AddDetail(({"reihe","platz","einlegeboeden","einlegeboden","boeden",
+ "boden"}),
+ BS("Die vielen Boeden bieten Platz fuer viele Pokale!"));
+ return;
+}
+
+
+static string my_long(){
+ if(staub<21)
+ return BS(
+ "Die schlichte Vitrine aus dunklem Holz eignet sich hervorragend, um "
+ "wertvolle Gegenstaende darin auszustellen. Hinter den beiden Glastueren "
+ "siehst Du eine Reihe von Einlegeboeden, die ebenfalls aus Glas bestehen. "+
+ staub_descr());
+ else return BS(staub_descr());
+}
+
+
+static string staub_descr(){
+ string text;
+ text="";
+ switch(staub){
+ case 0..1:
+ text=
+ "Die Vitrine ist hervorragend gepflegt. Du siehst keinerlei Staub "+
+ "darin, und die Scheiben sind voellig klar.\n";
+ AddDetail(({"staub"}),BS("Keiner zu sehen."));
+ break;
+ case 2..4:
+ text=
+ "Die Vitrine ist gut gepflegt. Es liegt kaum Staub darin, und die "+
+ "Tueren sind klar.\n";
+ AddDetail(({"staub"}),BS("Man sieht nur wenig davon."));
+ break;
+ case 5..7:
+ text=
+ "Die Vitrine ist in einem ordentlichen Zustand, allerdings sammelt "+
+ "sich so langsam Staub auf den Einlegeboeden.\n";
+ AddDetail(({"staub"}),BS("So langsam koennte man die "
+ "Vitrine saeubern!"));
+ AddDetail(({"zustand"}),BS("Noch ist er ordentlich."));
+ break;
+ case 8..10:
+ text=
+ "Die Vitrine wirkt schon etwas staubig. Man erkennt auch, dass "+
+ "der ein oder andere Fingerabdruck die Tueren ziert.";
+ AddDetail(({"staub","fingerabdruck","tueren","glastueren",
+ "deckel","glastuer","tuer","zustand"}),
+ BS("Es lohnt sich jetzt schon, die Vitrine zu saeubern."));
+ break;
+ case 11..15:
+ text=
+ "Du hast den Eindruck, dass die Vitrine langsam einmal gesaeubert "+
+ "werden koennte. Die Einlegeboeden sind staubig und zahlreiche "+
+ "Fingerabdruecke sind auf den Glastueren zu sehen.";
+ break;
+ case 16..20:
+ text=
+ "Die Vitrine macht einen recht ungepflegten Eindruck. Innen ist "+
+ "sie schon sehr verstaubt und auch die Tueren sind schon recht "+
+ "dreckig geworden.";
+ AddDetail(({"staub"}),BS("Nun wird es aber wirklich Zeit, die "
+ "Vitrine zu saeubern. Sonst sieht man bald nichts mehr darin."));
+ break;
+ case 21..25:
+ text=
+ "Die Vitrine ist total zugestaubt. Ueber den Glastueren sind "+
+ "erste Spinnweben zu erkennen und die Scheiben sind schon fast "+
+ "blind von all den Fingerabdruecken unaufmerksamer Gaeste.";
+ RemoveDetail(m_indices(QueryProp(P_DETAILS)));
+ AddDetail(({"spinnweben","dreck","vitrine","glastueren","glastuer",
+ "tueren","tuer","scheibe","scheiben","deckel"}),
+ "Unter dem ganzen Dreck ist leider nichts mehr zu erkennen.\n");
+ AddDetail(({"gaeste","gast","fingerabdruck","fingerabdruecke"}),
+ "Die Gaeste sind sicher schuld an dem Dreck.\n");
+ break;
+ case 26..30:
+ text=
+ "Du kannst die Vitrine unter der dicken Staubschicht kaum noch "+
+ "erkennen und die Glastueren sind blind geworden.";
+ AddDetail(({"staubschicht","schicht"}),
+ BS("Die ist verdammt dick und undurchsichtig."));
+ break;
+ default:
+ text=
+ "Dass sich unter dieser Ansammlung von Spinnweben und Staub noch "+
+ "eine Vitrine mit Glastueren verbergen soll, kannst Du kaum glauben. "+
+ "Jedenfalls kann man durch die voellig blinden Scheiben nichts "+
+ "mehr erkennen.";
+ AddDetail(({"dreck","spinnweben","staub","ansammlung"}),"Pfui Deibel!\n");
+ }
+ return text;
+}
+
+static int saeuber_cmd(string str){
+ string text;
+ if(!str) return 0;
+ if(strstr(str,"vitrine")<0) return 0;
+ switch(staub){
+ case 0:
+ write("Das ist noch nicht noetig!\n");
+ return 1;
+ break;
+ case 1..20:
+ text="Du reinigst die Vitrine gruendlich. Das wurde auch langsam "
+ "Zeit!";
+ if(getuuid(TP)!=besitzer)
+ text+="Du fragst Dich, wieso Du fremde Moebel reinigst.";
+
+ write(BS(text));
+ say(BS(TPN+" reinigt die Vitrine gruendlich. Das wurde auch langsam "
+ "Zeit!\n"),TP);
+ staub=0; //Hier darf noch jemand helfen!
+ break;
+ case 21..30:
+ text="Du beginnst die Vitrine zu reinigen. ";
+ if(getuuid(TP)!=besitzer){
+ text+="Nach einiger Zeit fragst Du Dich, ob Du eigentlich spinnst, "+
+ "denn das ist ueberhaupt nicht Deine Vitrine. Du laesst von dem "+
+ "Vorhaben wieder ab.";
+ say(BS(TPN+" faengt kurz an, die Vitrine zu reinigen, laesst es aber "
+ "schnell wieder sein."),TP);
+ }
+ else{
+ text+="Das dauert eine ganze Weile, aber dann strahlt die Vitrine "
+ "wieder.";
+ say(BS(TPN+" beginnt die Vitrine zu reinigen. Das dauert eine ganze "
+ "Weile, aber dann strahlt sie wieder."),TP);
+ staub=0;
+ }
+ write(BS(text));
+ break;
+ default:
+ if(getuuid(TP)!=besitzer)
+ write("Das dreckige Teil fasst Du nicht an!\n");
+ else{
+ write(BS(
+ "Du schrubbst und schrubbst und es scheint kein Ende zu nehmen. "
+ "Als Du schon langsam aufgeben willst, ist so langsam ein kleiner "
+ "Erfolg zu sehen. Du nimmst Dir vor, die Vitrine in Zukunft "
+ "haeufiger zu reinigen!"));
+ say(BS(
+ TPN+" schrubbt stundenlang an der Vitrine rum, bis sie endlich "
+ "wieder richtig sauber ist."),TP);
+ staub=0;
+ }
+ }
+ if(staub==0){
+ RemoveDetail(m_indices(QueryProp(P_DETAILS)));
+ GetTrophyDetails();
+ NeueDetails();
+ }
+ return 1;
+}
+
+void GetTrophyDetails(){
+ string *trophyliste,*shorts;
+ mapping trophydetails;
+
+ shorts=({});
+
+ trophyliste=MIRIL_TROPHYMASTER->GetPlacedTrophies(besitzer);
+
+ foreach( string tr : trophyliste )
+ shorts+=({ MIRIL_TROPHYMASTER->GetTrophyShort(tr) });
+
+ shorts = sort_array(shorts, #'>);
+ if(!sizeof(shorts))
+ AddDetail(({"pokale","pokal","in vitrine"}),
+ "Bislang ist die Vitrine noch leer.\n");
+ else
+ AddDetail(({"pokale","pokal","in vitrine"}),
+ "Du siehst folgende Pokale in der Vitrine:\n"
+ +implode(shorts,".\n")+".\n");
+
+ foreach( string tr : trophyliste )
+ {
+ AddDetail( MIRIL_TROPHYMASTER->GetTrophyIds(tr),
+ BS(MIRIL_TROPHYMASTER->GetTrophyLong(tr)));
+
+ trophydetails = MIRIL_TROPHYMASTER->GetTrophyDetails(tr);
+ if ( !sizeof(trophydetails) )
+ continue;
+ foreach ( mixed det, string det_desc : trophydetails )
+ AddDetail( det, BS(det_desc) );
+ }
+ return;
+}
+
+string *GetAllTrophyNames(){
+ int i,anzahl;
+ string *trophynamen;
+
+ trophynamen=({});
+
+ foreach(string bla:MIRIL_TROPHYMASTER->GetTrophyListe())
+ trophynamen+=MIRIL_TROPHYMASTER->GetTrophyIds(bla);
+
+ return trophynamen;
+}
+
+static int stell_cmd(string str){
+ string was,identifier;
+ int resultat;
+ object ob;
+ if(!str) return 0;
+ if(strstr(str,"vitrine")<0) return 0;
+ notify_fail("Das ist nicht Deine Vitrine!\n");
+ if(getuuid(TP)!=besitzer)
+ return 0;
+ notify_fail("Die Syntax ist: stelle <gegenstand> in vitrine!\n");
+ if(sscanf(str,"%s in vitrine",was)!=1)
+ return 0;
+
+ notify_fail("Die Vitrine sollte schon offen sein.\n");
+ if(QueryProp(P_CNT_STATUS)!=CNT_STATUS_OPEN && !IS_LEARNER(TP))
+ return 0;
+ notify_fail("Du solltest die Vitrine vorher erstmal saeubern!\n");
+ if(staub>20)
+ return 0;
+ notify_fail("Das kannst Du leider nicht in die Vitrine stellen!\n");
+ if(member(GetAllTrophyNames(),lower_case(was))<0
+ && lower_case(was)!="pokal")
+ return 0;
+ notify_fail("Das hast Du nicht!\n");
+ if(!ob=present(was,TP))
+ return 0;
+ notify_fail("Das kannst Du leider nicht in die Vitrine stellen!\n");
+ if(!ob->id("\nmiril_pokal"))
+ return 0;
+
+ identifier=ob->QueryIdentifier();
+ resultat=MIRIL_TROPHYMASTER->PlaceTrophy(getuuid(TP),identifier);
+
+ notify_fail("Hier stimmt etwas nicht, sag bitte einem Erzmagier Bescheid! "
+ "Resultat="+resultat+"\n");
+ if(resultat!=1)
+ return 0;
+ write(BS("Du stellst den Pokal in die Vitrine und bewunderst ihn noch ein "
+ "wenig.\n"));
+ say(TPN+" stellt einen Pokal in die Vitrine.\n",TP);
+ GetTrophyDetails();
+ ob->remove();
+ if(ob)
+ destruct(ob);
+ return 1;
+}
+
diff --git a/d/seher/haeuser/moebel/waffenschrank.c b/d/seher/haeuser/moebel/waffenschrank.c
new file mode 100644
index 0000000..e36abc9
--- /dev/null
+++ b/d/seher/haeuser/moebel/waffenschrank.c
@@ -0,0 +1,220 @@
+//--------------------------------------------------------------------------------
+// Name des Objects: Waffenschrank
+// Letzte Aenderung: 22.03.2001
+// Magier: Swift
+//--------------------------------------------------------------------------------
+/* Changelog
+ * 21.05.2007, Zesstra
+ Kampfstaebe auf Hinweis von tassram ergaenzt.
+*/
+#pragma strong_types,rtt_checks
+
+#include "schrankladen.h"
+#include <ansi.h>
+#include <class.h>
+inherit LADEN("swift_std_container");
+
+#define VERSION_OBJ "6"
+
+string strall;
+
+protected void create()
+{
+ if (!clonep(TO)) return;
+ swift_std_container::create();
+ SetProp(P_SHORT, "Ein Waffenschrank");
+ SetProp(P_LONG, BS(
+ "Mit den Waffen, die in diesen massiven Holzschrank passen, koenntest "
+ +"Du ein ganzes Soeldnerheer ausruesten. Fuer jede Waffengattung gibt "
+ +"es einen eigenen Platz, damit man auch alles gleich findet, sollte "
+ +"man es brauchen.")+"@@cnt_status@@");
+ AddId(({"waffenschrank", "holzschrank", "schrank"}));
+ SetProp("cnt_version_obj", VERSION_OBJ);
+ SetProp(P_NAME, "Waffenschrank");
+ SetProp(P_GENDER, MALE);
+ SetProp(P_WEIGHT, 5000); // Gewicht 5 Kg
+ SetProp(P_MAX_WEIGHT, 1000000); // Es passen fuer 1000 kg Sachen rein.
+ SetProp(P_WEIGHT_PERCENT, 100); // Dafuer macht er auch nix leichter :)
+ SetProp(P_MAX_OBJECTS, 100); // Mehr sollte nicht sein, lt. Tiamak.
+ SetProp(P_VALUE, 0); // Kein materieller Wert. Ist eh nicht verkaufbar.
+ SetProp(P_NOBUY, 1); // Wird im Laden zerstoert, falls er verkauft wird.
+ SetProp(P_NOGET, "Das geht nicht. "+Name(WER,1)+" haftet wie magisch am Boden.\n");
+ SetProp(P_MATERIAL, ({MAT_MISC_WOOD, MAT_MISC_MAGIC}) );
+ SetProp(P_INFO, "Versuchs mal mit: \"skommandos "+QueryProp(P_IDS)[1]+"\" !\n");
+ SetProp("obj_cmd", "sliste [Objekt-Id] [Waffentyp|\"alles\"]\n"
+ +" Waffentypen: Schwerter, Speere, Aexte, Keulen, Kampfstaebe, Messer, Peitschen,\n"
+ +" Fernwaffen, Munition, Sonstiges, Unzuordbar\n");
+
+ AD(({"platz"}), BS("Der Schrank bietet Platz fuer jede erdenkliche "
+ +"Waffengattung."));
+
+ AddCmd(({"sliste"}), "auflistung");
+}
+
+varargs int PreventInsert(object ob)
+{
+ // Keine Waffe? Hat in diesem Container nix verloren!
+ if( !ob->QueryProp(P_WEAPON_TYPE) && !ob->QueryProp(P_WC) &&
+ !ob->id("\nBumerang") && !ob->is_class_member(CL_AMMUNITION) &&
+ !ob->id("\ngorseilpfeil") )
+ {
+ write( BS("In "+name(WEN,1)+" kannst Du nur Waffen + Munition legen!"));
+ return 1;
+ }
+ else
+ return ::PreventInsert(ob);
+}
+
+int auflistung2(string was, string nf_str1, string nf_str2, int alles)
+{
+ string obshort, suche, *strs;
+ object *obs;
+ int i;
+ mapping suchobs;
+ switch(was)
+ {
+ case "munition" : suche=WT_AMMU; break;
+ case "aexte" : suche=WT_AXE; break;
+ case "keulen" : suche=WT_CLUB; break;
+ case "messer" : suche=WT_KNIFE; break;
+ case "fernwaffen" : suche=WT_RANGED_WEAPON; break;
+ case "speere" : suche=WT_SPEAR; break;
+ case "schwerter" : suche=WT_SWORD; break;
+ case "peitschen" : suche=WT_WHIP; break;
+ case "sonstiges" : suche=WT_MISC; break;
+ case "kampfstaebe": suche=WT_STAFF; break;
+ case "unzuordbar" : suche="unzuordbar"; break;
+ default : write("Fehler: Ungueltiger Waffentyp. "
+ +"Folgende Typen gibt es:\n"+nf_str1+nf_str2);
+ return 1; break;
+ }
+ obs=all_inventory();
+ suchobs=([]);
+ for(i=0;i<sizeof(obs);i++)
+ {
+ obshort=to_string(obs[i]->QueryProp(P_SHORT));
+ if(obshort=="Ein Bumerang@@fliegt@@")
+ obshort="Ein Bumerang";
+ else if(obshort=="Nichts besonderes" || obshort=="0") // keine P_SHORT ?
+ obshort=obs[i]->Name(WER); // Hoffen wir mal dass das Obj. nen Namen hat.
+ if(obs[i]->QueryProp(P_WEAPON_TYPE)==suche || // Gesuchter WeaponType gefunden...
+ (!obs[i]->QueryProp(P_WEAPON_TYPE) && suche=="unzuordbar") )
+ {
+ if(suchobs[obshort]) // P_SHORT des Obj. schon im mapping?
+ {
+ if( obs[i]->QueryProp(P_AMOUNT) )
+ suchobs[obshort]+=obs[i]->QueryProp(P_AMOUNT); // Dann den Zaehler um Amount hoch!
+ else
+ suchobs[obshort]+=1; // Dann den Zaehler um 1 hoch!
+ }
+ else
+ {
+ if( obs[i]->QueryProp(P_AMOUNT) )
+ suchobs+=([obshort: obs[i]->QueryProp(P_AMOUNT)]);
+ else
+ suchobs+=([obshort: 1]);
+ }
+ }
+ }
+ strs=m_indices(suchobs);
+ if(sizeof(strs))
+ {
+ if(!alles)
+ {
+ if(suche=="unzuordbar")
+ strall+=Name(WER,1)+" enthaelt folgende nicht zuordbare Waffen:\n";
+ else
+ strall+=Name(WER,1)+" enthaelt folgende "+CAP(was)+":\n";
+ strall+="------------------------------------------------------------\n";
+ }
+ else
+ {
+ if(suche=="unzuordbar")
+ strall+=ANSI_BOLD+"=== Nicht zuordbare Waffen:\n"+ANSI_NORMAL;
+ else
+ strall+=ANSI_BOLD+"=== "+CAP(was)+":\n"+ANSI_NORMAL;
+ }
+ for(i=0;i<sizeof(strs);i++)
+ {
+ if(suchobs[strs[i]] > 1)
+ strall+=strs[i]+". ("+suchobs[strs[i]]+")\n";
+ else
+ strall+=strs[i]+".\n";
+ }
+ }
+ else
+ if(!alles)
+ strall+=Name(WER,1)+" enthaelt keine "+CAP(was)+"!\n";
+ return 1;
+}
+
+int auflistung(string str)
+{
+ string *strs, ob_id, was, nf_str1,nf_str2;
+ strall="";
+ nf_str1=" (Schwerter, Speere, Aexte, Keulen, Kampfstaebe, Messer, Peitschen,\n"
+ +" Fernwaffen, Munition, Sonstiges, Unzuordbar)\n";
+ nf_str2="Syntax: sliste [Objekt-Id] [Waffentyp]\n"
+ +"Bsp.: sliste "+QueryProp(P_IDS)[1]+" "+"schwerter\n"
+ +" sliste "+QueryProp(P_IDS)[1]+" alles\n";
+ notify_fail("Fehler: Ohne Parameter klappt das nicht.\n"+nf_str2);
+ if(!str) return 0;
+ if(present(str)==TO) // Ueberpruefe, ob dieses Objekt gemeint ist!
+ {
+ write("Fehler: Es fehlt ein Waffentyp. Folgende Typen gibt es:\n"
+ +nf_str1+nf_str2);
+ return 1;
+ }
+ strs=old_explode(str, " ");
+ notify_fail("Fehler: Du musst eine gueltige Objekt-Id angeben!\n"
+ +nf_str2);
+ if( sizeof(strs) < 2 ) return 0; // Nur 1 Par. und der ist nicht die Objekt-Id
+ if( sizeof(strs) == 2 ) // Anzahl Par. = 2
+ {
+ ob_id=strs[0];
+ was=strs[1];
+ if( IST_ZAHL(was) ) // Objekt-Id z.B. mit "schrank 2" angesprochen?
+ if(present(ob_id+" "+was)==TO) // Falls dieses Objekt gemeint ist und kein 3. Par!
+ {
+ write("Fehler: Es fehlt ein Waffentyp. Folgende Typen gibt es:\n"
+ +nf_str1+nf_str2);
+ return 1;
+ }
+ else
+ return 0;
+ }
+ else if( sizeof(strs) == 3 )
+ {
+ ob_id=strs[0]+" "+strs[1];
+ was=strs[2];
+ }
+ else // Anzahl erforderlicher Parameter ueberschritten!
+ return 0;
+ if(present(ob_id)!=TO) // Ueberpruefe, ob auch dieses Objekt gemeint ist!
+ return 0;
+ if(QueryProp(P_CNT_STATUS)!=CNT_STATUS_OPEN)
+ {
+ write("Dazu muesste "+name(WER,1)+" geoeffnet sein.\n");
+ return 1;
+ }
+//--- Hier ist Parameterpruefung zu Ende.
+ was=LOWER(was);
+ if(was!="alles")
+ auflistung2(was, nf_str1, nf_str2, 0);
+ else
+ {
+ auflistung2("aexte", nf_str1, nf_str2, 1);
+ auflistung2("keulen", nf_str1, nf_str2, 1);
+ auflistung2("kampfstaebe", nf_str1, nf_str2, 1);
+ auflistung2("messer", nf_str1, nf_str2, 1);
+ auflistung2("speere", nf_str1, nf_str2, 1);
+ auflistung2("schwerter", nf_str1, nf_str2, 1);
+ auflistung2("peitschen", nf_str1, nf_str2, 1);
+ auflistung2("fernwaffen", nf_str1, nf_str2, 1);
+ auflistung2("munition", nf_str1, nf_str2, 1);
+ auflistung2("sonstiges", nf_str1, nf_str2, 1);
+ auflistung2("unzuordbar", nf_str1, nf_str2, 1);
+ }
+ TP->More(strall);
+ return 1;
+}
diff --git a/d/seher/haeuser/moebel/waffentruhe.c b/d/seher/haeuser/moebel/waffentruhe.c
new file mode 100644
index 0000000..098aaa7
--- /dev/null
+++ b/d/seher/haeuser/moebel/waffentruhe.c
@@ -0,0 +1,43 @@
+//--------------------------------------------------------------------------------
+// Name des Objects: Waffentruhe
+// Letzte Aenderung: 22.03.2001
+// Magier: Swift
+//--------------------------------------------------------------------------------
+/* Changelog
+ * 21.05.2007, Zesstra
+ Da Waffenschrank und Waffentruhe sich praktisch nicht unterscheiden, bis
+ auf 10 Zeilen im Create, erbt nun die Waffentruhe den Waffenschrank und
+ ueberschreibt einfach die passenden Props.
+*/
+#pragma strong_types,rtt_checks
+
+#include "schrankladen.h"
+#include <ansi.h>
+#include <class.h>
+//inherit LADEN("swift_std_container");
+inherit LADEN("waffenschrank");
+
+#define VERSION_OBJ "7"
+
+protected void create() {
+ if (!clonep(TO)) return;
+ ::create();
+ SetProp(P_SHORT, "Eine Waffentruhe");
+ SetProp(P_LONG, BS(
+ "Diese Stahltruhe ist speziell zur Aufnahme von grossen Waffenmengen "
+ "gefertigt. Verschiedene Faecher fuer die einzelnen Waffentypen erleichtern "
+ "die Suche nach Deinem bevorzugten Waffentyp.")+"@@cnt_status@@");
+ RemoveId(({"waffenschrank", "holzschrank", "schrank"}));
+ AddId(({"waffentruhe", "stahltruhe", "truhe"}));
+ SetProp("cnt_version_obj", VERSION_OBJ);
+ SetProp(P_NAME, "Waffentruhe");
+ SetProp(P_GENDER, FEMALE);
+ SetProp(P_MATERIAL, ({MAT_MISC_METAL, MAT_MISC_MAGIC}) );
+ SetProp(P_INFO, "Versuchs mal mit: \"skommandos "+QueryProp(P_IDS)[1]+
+ "\" !\n");
+ AD(({"faecher"}), BS("Fuer jeden Waffentyp gibt es ein eigenes Fach, so dass "
+ "Du eine bessere Uebersicht hast."));
+ AD(({"platz"}), BS("Die Waffentruhe bietet Platz fuer jede erdenkliche "
+ "Waffengattung."));
+}
+
diff --git a/d/seher/haeuser/moebel/wasch.c b/d/seher/haeuser/moebel/wasch.c
new file mode 100644
index 0000000..7789350
--- /dev/null
+++ b/d/seher/haeuser/moebel/wasch.c
@@ -0,0 +1,220 @@
+// Name des Objects: Waschobjekt
+// Letzte Aenderung: 01.04.2005
+// Magier: Seleven
+// Dieses File gibt dem Spieler die Moeglichkeit, eine Waschgelegenheit in
+// seinem Seherhaus aufzustellen. Das beim Kommando wasch(e), dusch(e) laesst
+// sich die Medung ueberschreiben (Test per raum->QueryProp("h_commands"))
+// 01.07.2007 (Zesstra): GetOwner() definiert.
+//----------------------------------------------------------------------------
+#pragma strong_types,rtt_checks
+
+#include "schrankladen.h"
+inherit LADEN("swift_std_container");
+
+string *wcmd;
+string *objekte =
+ (({"\nstinkobj","\nzesstra_asche","seleve\nscheisse","\npopc",
+ "\nsspbollen","seleve\nstinkobj","\nq2p_gestank","ber\tram_skot",
+ "bambi\nschmutzigehaende"}));
+/* Wurzel(Klo/Imbiss), Zesstra(Vulkan/Illuminatos), Seleven(Klo/Nebelelfen),
+ * Seleven(Popcorn/Nebelelfen), Boing(Schleimschmeisser,SSP), STANDART
+ */
+
+static void wasch_fun();
+
+protected void create()
+{
+ if (!clonep(this_object())) return;
+ ::create();
+
+ wcmd = (({"wasche","wasch","dusche","dusch"}));
+ AddId(({"duschkabine","kabine","dusche","waschgelegenheit"}));
+ SetProp(P_NAME,"Duschkabine");
+
+ SetProp("cnt_version_obj",1);
+
+ SetProp("obj_cmd",
+ "wasch(e), dusch(e)\n"+
+ " Damit laesst sich das Stinken aus dem Imbissklo beseitigen.\n"+
+ " Wenn kein Befehl 'wasch(e)' im Raum beschrieben ist, erfolgt eine\n"+
+ " Standartmeldung, selbiges gilt fuer 'dusch(e)'.\n"+
+ "ssetz(e) waschbefehl\n"+
+ " Damit kann man die Befehlsliste erweitern, die das Waschen \n"+
+ " ausloesen\n"+
+ "sloesch(e) waschbefehl\n"+
+ " Damit kann man einen Befehl aus der Liste loeschen\n"+
+ "waschbefehlslite, wbl"+
+ " Zeigt eine Liste der Befehle an, die das Waschen ausloesen.\n");
+
+ SetProp(P_SHORT,"Eine Duschkabine");
+ SetProp(P_LONG,BS("Die Duschkabine hat einen Rahmen aus hellem Holz. "
+ "Dazwischen wurden matte Scheiben eingelassen, damit man niemanden beim "
+ "Duschen beobachten kann."));
+ AddDetail("rahmen","Der Rahmen ist aus hellem Holz.\n");
+ AddDetail(({"scheiben","scheibe"}),"Die Scheiben der Duschkabine sind "+
+ "matt und absolut undurchsichtig!\n");
+ AddDetail(({"duschen","beim duschen"}),
+ "Man kann niemanden beim Duschen beobachten.\n");
+
+ SetProp(P_GENDER, FEMALE);
+ SetProp(P_WEIGHT, 5000); // Gewicht 5 Kg
+ SetProp(P_MAX_WEIGHT, 0); // Soll nur n pseudo-Container
+ SetProp(P_WEIGHT_PERCENT, 100); // Dafuer macht er auch nix leichter :)
+ SetProp(P_MAX_OBJECTS, 0); // Kein Container :)
+ SetProp(P_VALUE, 0); // Ist eh nicht verkaufbar.
+ SetProp(P_NOBUY, 1); // Fals doch: zerstoeren!
+ SetProp(P_NOGET,
+ "Das geht nicht. "+Name(WER,1)+" haftet wie magisch am Boden.\n");
+ SetProp(P_MATERIAL, ({MAT_MISC_WOOD, MAT_MISC_MAGIC}) );
+ SetProp(P_INFO, "Versuchs mal mit: \"skommandos "+QueryProp(P_IDS)[1]+"\" !\n");
+
+ AddCmd(wcmd,"cmd_waschen");
+ RemoveCmd(({"oeffne","oeffn","schliesse","schliess"}));
+ AddCmd(({"ssetze","ssetz"}),"cmd_setzen");
+ AddCmd(({"sloesche","sloesche"}),"cmd_loeschen");
+ AddCmd(({"wbl","waschbefehlsliste"}),"liste");
+}
+
+// Zesstra, 1.7.07, fuers Hoerrohr
+string GetOwner() {return "seleven";}
+
+varargs int PreventInsert(object ob) {return 1;} //Das ist kein Container :)
+
+static void wasch_fun()
+{
+ int i;
+ object ob;
+ i = sizeof(objekte);
+ i--;
+ while(i > -1)
+ {
+
+ if(!TP) return;
+ ob = present(objekte[i],TP);
+ while(ob)
+ {
+ if(query_once_interactive(ob))
+ {
+ tell_object(TP,BS("Du scheinst jemanden in Deinem Inv zu haben!\n"
+ "Das sollte sich vielleicht ein Magier anschauen."));
+ i--;
+ return;
+ }
+ ob->remove(1);
+ if(present(objekte[i],TP));
+ ob = present(objekte[i],TP);
+ }
+ i--;
+
+ }
+}
+
+int cmd_waschen(string str)
+{
+ string verb;
+ verb = query_verb();
+ if(!environment()) return 0;
+ if( !erlaubt() )
+ {
+ write("Du solltest den Besitzer vielleicht um Erlaubnis bitten.\n");
+ return 1;
+ }
+ if(member(environment()->QueryProp("h_commands"),verb) == 0)
+ {
+ write(
+ "Du springst schnell unter die Dusche und waeschst Dich gruendlich.\n");
+ say(this_player()->Name(WER)+" springt schnell unter die Dusche.\n");
+ wasch_fun();
+ return 1;
+ }
+ wasch_fun();
+ return 1;
+}
+
+
+static int cmd_setzen(string str)
+{
+ string bef;
+ notify_fail("Moechtest Du einen Waschbefehl setzen?\n"+
+ "Syntax: ssetz(e) waschbefehl [befehl]\n");
+ if(!str || !stringp(str) || sizeof(str) == 0) return 0;
+ sscanf(str,"waschbefehl %s",bef);
+ if(!bef) return 0;
+ if(bef[sizeof(bef) .. sizeof(bef)-1] == "e")
+ bef = bef[sizeof(bef) .. sizeof(bef)-2];
+ notify_fail("Der Befehl steht schon auf der Liste.\n");
+ if(member(wcmd,bef) != -1) return 0;
+ wcmd += (({bef,bef+"e"}));
+ AddCmd(wcmd,"cmd_waschen");
+ write(BS("Du hast die Befehle "+bef+" und "+bef+"e an die Liste "
+ "angefuegt."));
+ return 1;
+}
+
+static int cmd_loeschen(string str)
+{
+ string bef;
+ notify_fail("Moechtest Du einen Waschbefehl loeschen?\n"+
+ "Syntax: sloesch(e) waschbefehl [befehl]\n");
+ if(!str || !stringp(str) || sizeof(str) == 0) return 0;
+ sscanf(str,"waschbefehl %s",bef);
+ if(!bef) return 0;
+ notify_fail("Der Befehl steht gar nicht auf der Liste.\n");
+ if(member(wcmd,bef) == -1) return 0;
+ wcmd -= (({bef}));
+ RemoveCmd(bef);
+ write(BS("Du hast die Befehle "+bef+" und "+bef+"e von der Liste "
+ "entfernt."));
+ return 1;
+}
+
+static int liste(string str)
+{
+ write("Du hast folgende Befehle auf der Waschliste stehen:\n"+
+ break_string(implode(wcmd,", "),78,3));
+ return 1;
+}
+
+
+
+// oeffnen und schliessen ausbauen.
+varargs int skommandos(string str)
+{
+ notify_fail( "Fehler: Dieser Befehl benoetigt eine gueltige Objekt-Id als Parameter.\n"
+ +"Beispiel: skommandos "+QueryProp(P_IDS)[1]+"\n");
+ if(!str) return 0;
+ if(present(str)!=TO ) // Bin ich gemeint?
+ return 0;
+ write("=============================================================================\n");
+ write("Aktuelle Version: "+QueryProp("cnt_version_std")+QueryProp("cnt_version_obj")+"\n");
+ write( BS(Name(WER,1)+" kann nur in diesem Seherhaus verwendet werden, "
+ +"da "+QueryPronoun(WER)+" speziell dafuer gekauft wurde. "+CAP(QueryPronoun(WER))
+ +" verfuegt ueber folgende Kommandos:")
+ +"-----------------------------------------------------------------------------\n"
+ +"serlaube [Objekt-Id] [Spielername|\"hausfreunde\"|\"zweities\"]\n"
+ +" Erlaubt Personen, "+name(WEN,1)+" mitzubenutzen.\n"
+ +" serlaube + Objekt-Id (ohne Spielername/hausfreunde)\n"
+ +" listet alle Personen mit Zugriff auf "+name(WEN,1)+"\n\n"
+ +"verschiebe [Objekt-Id] nach [Ausgang]\n"
+ +" Damit kannst Du "+name(WEN,1)+" innerhalb Deines Seherhauses verschieben.\n\n"
+ //Seleven 07.12.2005
+ +"sverstecke [Objekt-Id]\n"
+ +" Damit machst Du "+name(WEN,1)+" unsichtbar.\n"
+ +"shole [Objekt-Id] hervor\n"
+ +" Damit machst Du "+name(WEN,1)+" wieder sichtbar.\n"
+ // Bis hier
+ +"zertruemmer [Objekt-Id]\n"
+ +" Damit zerstoerst Du "+name(WEN,1)+".\n\n");
+
+
+ if( QueryProp("obj_cmd") )
+ write( QueryProp("obj_cmd")+"\n" );
+
+ write("[Objekt-Id] muss eine gueltige Id sein, in diesem Fall z.B. "
+ +QueryProp(P_IDS)[1]+"\n");
+ write("=============================================================================\n");
+
+
+ return 1;
+}
+
diff --git a/d/seher/haeuser/moebel/zauberkiste.c b/d/seher/haeuser/moebel/zauberkiste.c
new file mode 100644
index 0000000..ecf6f74
--- /dev/null
+++ b/d/seher/haeuser/moebel/zauberkiste.c
@@ -0,0 +1,56 @@
+//--------------------------------------------------------------------------------
+// Name des Objects: Zauberkiste
+// Letzte Aenderung: 10.05.2002
+// Magier: Vanion
+// Was: Die ID fuer die Kompos der Zauberer umgestellt.
+//--------------------------------------------------------------------------------
+#pragma strong_types,rtt_checks
+
+#include "schrankladen.h"
+
+// Fuer die IDs
+#include "/p/zauberer/zauberer.h"
+
+inherit LADEN("swift_std_container");
+
+#define VERSION_OBJ "3"
+
+protected void create()
+{
+ if (!clonep(TO)) return;
+ swift_std_container::create();
+ SetProp(P_SHORT, "Eine Zauberkiste");
+ SetProp(P_LONG, BS(
+ "Eine kleine Kiste aus Birnbaumholz. Da diesem seltenen Holz selbst "
+ +"magische Faehigkeiten nachgesagt werden, ist es wohl das ideale Material, "
+ +"um die teilweise gefaehrlichen Komponenten eines Zauberers darin "
+ +"unterzubringen.")+"@@cnt_status@@");
+ AddId(({"zauberkiste", "kiste"}));
+ SetProp("cnt_version_obj", VERSION_OBJ);
+ SetProp(P_NAME, "Zauberkiste");
+ SetProp(P_GENDER, FEMALE);
+ SetProp(P_WEIGHT, 5000); // Gewicht 5 Kg
+ SetProp(P_MAX_WEIGHT, 1000000); // Es passen fuer 1000 kg Sachen rein.
+ SetProp(P_WEIGHT_PERCENT, 100); // Dafuer macht er auch nix leichter :)
+ SetProp(P_MAX_OBJECTS, 100); // Mehr sollte nicht sein, lt. Tiamak.
+ SetProp(P_VALUE, 0); // Kein materieller Wert. Ist eh nicht verkaufbar.
+ SetProp(P_NOBUY, 1); // Wird im Laden zerstoert, falls er verkauft wird.
+ SetProp(P_NOGET, "Das geht nicht. "+Name(WER,1)+" haftet wie magisch am Boden.\n");
+ SetProp(P_MATERIAL, ({MAT_PEAR_WOOD, MAT_MISC_MAGIC}) );
+ SetProp(P_INFO, "Versuchs mal mit: \"skommandos "+QueryProp(P_IDS)[1]+"\" !\n");
+
+ AD(({"holz", "birnbaumholz"}), BS("Fast koenntest Du meinen, dass "+name(WER,1)
+ +" lebt!"));
+}
+
+varargs int PreventInsert(object ob)
+{
+ // Keine Zauberkompo? Hat in diesem Container nix verloren!
+ if( !ob->id(Z_ID_ZUTAT) )
+ {
+ write( BS("In "+name(WEN,1)+" kannst Du nur Zauberer-Komponenten legen!"));
+ return 1;
+ }
+ else
+ return ::PreventInsert(ob);
+}