| //--------------------------------------------------------------------------- |
| // 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"; |
| } |
| |