blob: 93bace6fabd20ea5900571c460c371f7dff69df6 [file] [log] [blame]
MG Mud User88f12472016-06-24 23:31:02 +02001//---------------------------------------------------------------------------
2// Name des Objects: Schluesselbrett
3// Letzte Aenderung: 02.06.2001
4// Original: Swift
5// Neue Version: Seleven
6// Übernommen: 23.01.2006
7//---------------------------------------------------------------------------
8/* Changelog
9 * 21.06.2007, Zesstra
10 im inherit abs. Pfad durch LADEN(x) ersetzt.
11 * 01.07.2007, Zesstra
12 GetOwner() definiert.
13 * 11.05.2015, Arathorn
14 weitraeumig ueberarbeitet zur Behebung von Fehlfunktionen
15*/
16#pragma strong_types, rtt_checks
17
18#include "/d/seher/haeuser/moebel/schrankladen.h"
19#include <ansi.h>
20inherit LADEN("swift_std_container");
21
22#define VERSION_OBJ "3"
23// Zur Indizierung des Mappings <haken>
24#define HOOK_OB 0
25#define HOOK_LABEL 1
26
27private varargs string KeyDescription(int keynum);
28private int IsValidKey(object ob);
29private int GetNextFreeSlot();
30private object GetKeyForLabel(string label);
31private int GetHookNumberForKey(object ob);
32private void ConsolidateInventory();
33
34// Struktur: ([ haken_nr : objekt; beschriftung ])
35private mapping haken=([:2]);
36private int hooklist_long = 0;
37
38protected void create() {
39 if (!clonep(TO)) {
40 set_next_reset(-1);
41 return;
42 }
43 ::create();
44
45 foreach(int i: 1..16) {
46 m_add(haken, i);
47 }
48
49 // DEBUG! Sonst funktioniert's ausserhalb von Seherhaeusern nicht.
50 SetProp("test",1);
51 SetProp(P_SHORT, "Ein Schluesselbrett");
52 Set(P_LONG, function string () {
53 string text = BS(
54 "Ein kleines Brett aus Holz, an dem in 2 Reihen je 8 Haken befestigt "
55 "sind, an die man insgesamt 16 Schluessel haengen kann. Um die "
56 "Uebersicht nicht zu verlieren, befindet sich ueber jedem der Haken "
57 "ein kleines Schildchen aus Schiefer, das sich beschriften laesst. "
58 "Auf diese Weise geht der Sinn und Zweck des Schluessels, der an "
59 "diesem Haken ruht, nicht verloren. Praktischerweise haengt an einer "
60 "Schnur ein Stueck Kreide von dem Brett herab, mit dem Du die "
61 "Schildchen beschriften kannst.");
62 text += KeyDescription(0);
63 return text;
64 }, F_QUERY_METHOD);
65
66 AddId(({"schluesselbrett","brett"}));
67 SetProp("cnt_version_obj", VERSION_OBJ);
68 SetProp(P_CNT_STATUS, 0);
69 SetProp(P_NAME, "Schluesselbrett");
70 SetProp(P_GENDER, NEUTER);
71 SetProp(P_WEIGHT, 1000); // Gewicht 1 Kg
72 SetProp(P_MAX_WEIGHT, 1000000); // Es passen fuer 1000 kg Sachen rein.
73 SetProp(P_WEIGHT_PERCENT, 100); // Dafuer macht er auch nix leichter :)
74 SetProp(P_MAX_OBJECTS, 16);
75 // Man soll nichts ueber den normalen Mechanismus reinstecken oder
76 // rausnehmen koennen. Wird von put_and_get.c geprueft.
77 SetProp(P_CONTAINER, 0);
78 SetProp(P_NOINSERT_MSG, BS("An das Schluesselbrett kannst Du nur "
79 "Schluessel haengen.\nSyntax: 'haenge <schluessel> an brett'."));
80 SetProp(P_NOGET, "Das geht nicht. "+Name(WER,1)+
81 " laesst sich nicht bewegen.\n");
82 SetProp(P_MATERIAL, ({MAT_OAK, MAT_MISC_MAGIC}) );
83 SetProp(P_INFO, "Versuch's mal mit: \"skommandos schluesselbrett\".\n");
84
85 AD(({"holz"}), BS("Echte, robuste Eiche."));
86
87 RemoveCmd(({"schliesse","schliess","oeffne"}));
88
89 AddCmd(({"unt", "untersuche", "betrachte", "betracht", "betr",
90 "schaue", "schau"}), "unt_haken");
91 AddCmd(({"haeng", "haenge"}), "schluessel_an_haken_haengen");
92 AddCmd(({"nimm"}), "schluessel_von_haken_nehmen");
93 AddCmd("sbeschrifte", "cmd_beschriften");
94 AddCmd("sliste", "cmd_sliste");
95}
96
97/***** KOMMANDOFUNKTIONEN *****/
98
99// Konfiguration der Schluesselliste, entweder "alle" anzeigen oder nur die
100// belegten Haken.
101static int cmd_sliste(string str) {
102 notify_fail("Syntax: 'sliste alle|belegte'.\n");
103 if ( !stringp(str) || !sizeof(str) )
104 return 0;
105
106 if ( str == "alle" ) {
107 if ( !hooklist_long ) {
108 tell_object(TP, BS("Ok, es werden jetzt immer alle Haken "
109 "aufgelistet."));
110 hooklist_long = 1;
111 }
112 else
113 tell_object(TP, BS("Die Einstellung war schon 'alle'."));
114 }
115 else if ( str == "belegte" ) {
116 if ( hooklist_long ) {
117 tell_object(TP, BS("Ok, es werden jetzt nur die belegten Haken "
118 "aufgelistet."));
119 hooklist_long =0;
120 }
121 else
122 tell_object(TP, BS("Die Einstellung war schon 'belegte'."));
123 }
124 else
125 return 0;
126 return 1;
127}
128
129// Haken untersuchen. Ohne Angabe der Nummer werden alle ausgegeben,
130// ansonsten der gewuenschte, sofern es diesen gibt.
131static int unt_haken(string str) {
132 if ( !stringp(str) || !sizeof(str) || strstr(str, "haken") == -1 )
133 return 0;
134
135 int hakennr;
136 if ( sscanf(str, "haken %d", hakennr) != 1 ) {
137 string det = KeyDescription(hakennr);
138 tell_object(TP, sizeof(det) ? det : "Die Haken sind alle leer.\n");
139 return 1;
140 }
141
142 notify_fail("Welchen Haken moechtest Du untersuchen? Es gibt nur die "
143 "Haken 1 bis 16.\n");
144 if( hakennr<1 || hakennr > 16 )
145 return 0;
146
147// ausgabe_haken(hakennr);
148 tell_object(TP, KeyDescription(hakennr));
149 return 1;
150}
151
152// Schluessel aufhaengen.
153static int schluessel_an_haken_haengen(string str) {
154 notify_fail("Was willst Du woran haengen?\n");
155 if(!stringp(str) || !sizeof(str))
156 return 0;
157
158 notify_fail("Das darfst Du nicht.\n");
159 if(!erlaubt())
160 return 0;
161
162 string was, woran;
163 notify_fail("Folgende Syntax versteht Dein Schluesselbrett:\n"
164 " \"haenge <schluesselname> an haken [nr]\" oder\n"
165 " \"haenge <schluesselname> an [schluessel]brett\".\n");
166 if ( sscanf(str, "%s an %s", was, woran) != 2 )
167 return 0;
168
169 notify_fail("Was moechtest Du an das Schluesselbrett haengen?\n");
170 if ( !stringp(was) )
171 return 0;
172
173 notify_fail("Woran willst Du das denn haengen?\n");
174 if ( strstr(woran, "haken", 0)==-1 && !id(woran) )
175 return 0;
176
177 // Test, ob es Objekte dieses Namens gibt.
178 object *obs = TP->find_obs(was, PUT_GET_NONE);
179 // Aus der Liste der gefundenen Objekte alle rausfiltern, die keine
180 // Schluessel sind. Als Schluessel gelten hier alle Objekte, die die
181 // ID "schluessel" haben oder die mittels QueryDoorKey() einer bestimmten
182 // Tuer zugeordnet sind.
183 obs = filter(obs, #'IsValidKey);
184 notify_fail("Keine(n) Schluessel mit dem Namen gefunden.\n");
185 if ( !sizeof(obs) )
186 return 0;
187
188 int nr = GetNextFreeSlot();
189 notify_fail("Am Schluesselbrett ist kein Haken mehr frei.\n");
190 if ( !nr )
191 return 0;
192
193 // Wenn nur ein Schluessel gefunden wurde, wird genauer geschaut, ob
194 // der Spieler gesagt hat, wo der hinsoll.
195 if ( sizeof(obs) == 1 ) {
196 if ( woran != "haken" || !id(woran) )
197 sscanf(woran, "haken %d", nr);
198 }
199
200 notify_fail("Es gibt nur die Haken 1 bis 16.\n");
201 if ( nr < 1 || nr > 16 )
202 return 0;
203
204 notify_fail("Der Haken ist nicht mehr frei.\n");
205 if ( objectp(haken[nr,HOOK_OB]) )
206 return 0;
207
208 // Alle gefundenen Schluesselobjekte ans Brett haengen.
209 foreach( object key : obs ) {
210 switch (key->move(ME, M_PUT)) {
211 // Die Kapazitaet ist ueber P_MAX_OBJECTS begrenzt. Alle
212 // Schleifendurchlaeufe, die die Kapazitaetsgrenze erreichen, landen
213 // in default und beenden damit die Schleife. Daher muessen sie
214 // nicht gesondert behandelt werden.
215 case MOVE_OK :
216 // Falls das Brett voll sein sollte, aber faelschlicherweise
217 // dennoch ein weiterer Schluessel hineinbewegt wurde, ist nr==0,
218 // und es wird ein Fehler ausgeloest, damit nicht hinterher ein
219 // Schluessel an Haken 0 haengt.
220 if ( !nr ) {
221 raise_error("Fehler: Haken 0 darf nicht belegt werden.");
222 break;
223 }
224 tell_object(TP, BS("Du haengst "+obs[0]->name(WEN,1)+" an Haken "+
225 nr+"."));
226 // Nur wenn ein Schluessel erfolgreich drangehaengt wurde, wird er
227 // in die Liste eingetragen. Etwaige Beschriftungen bleiben bestehen,
228 haken[nr, HOOK_OB] = key;
229 // und nur dann wird der naechste Slot probiert. Wenn nur ein
230 // Schluessel verarbeitet wird, ist das hier unschaedlich, weil es
231 // nicht nochmal ausgewertet wird.
232 nr = GetNextFreeSlot();
233 // Schluessel wurde verarbeitet und Meldung ausgegeben
234 obs -= ({key});
235 break;
236 case ME_CANT_LEAVE_ENV :
237 case ME_CANT_BE_INSERTED :
238 case ME_CANT_BE_DROPPED :
239 // Schluessel wurde nicht erfolgreich drangehaengt.
240 tell_object(TP, BS(key->Name(WER,1)+" weigert sich, ans "
241 "Schluesselbrett gehaengt zu werden."));
242 // Meldung wurde ausgegeben, nichts weiter zu tun.
243 obs -= ({key});
244 break;
245 // TOO_MANY_OBJECTS wird nicht hier behandelt, sondern weiter unten,
246 // um eine Auflistung der Schluesselnamen ausgeben zu koennen, statt
247 // eine Zeile pro Schluessel. Die anderen Rueckgabewerte von move()
248 // sind bei dieser Art der Bewegung nicht zu erwarten.
249 default: break;
250 }
251 }
252 // Fuer alle uebrigen war wohl TOO_MANY_OBJECTS der Rueckgabewert, denn
253 // das Schluesselbrett erlaubt nur P_MAX_OBJECTS = 16.
254 if ( sizeof(obs) ) {
255 tell_object(TP, BS("Fuer "+CountUp(obs->name(WEN))+" ist leider kein "
256 "Haken mehr am Schluesselbrett frei."));
257 }
258 return 1;
259}
260
261// Schluessel abnehmen
262static int schluessel_von_haken_nehmen(string str) {
263 if( !stringp(str) || !sizeof(str) )
264 return 0;
265
266 string was, woraus;
267 if ( sscanf(str, "%s aus %s", was, woraus) != 2 &&
268 sscanf(str, "%s von %s", was, woraus) != 2 )
269 return 0;
270
271 notify_fail("Das darfst Du nicht!\n");
272 if(!erlaubt())
273 return 0;
274
275 notify_fail("Woraus willst Du das denn nehmen?\n");
276 if ( !id(woraus) && strstr(woraus, "haken", 0) == -1 )
277 return 0;
278
279 notify_fail("Was willst Du denn vom Schluesselbrett nehmen?\n");
280 if( !stringp(was) )
281 return 0;
282
283 notify_fail("Das Schluesselbrett ist doch aber leer.\n");
284 if ( !sizeof(all_inventory(ME)) )
285 return 0;
286
287 int hakennr;
288 object *keys = ({});
289 // Es muessen auch Schluessel von bestimmten Haken abgenommen
290 // werden koennen, nicht nur jeweils der erste mit der angegebenen ID.
291 // Dies hat auch Prio gegenueber der allgemeinen Begriffssuche mit
292 // find_obs().
293 if ( sscanf(woraus, "haken %d", hakennr) == 1 ) {
294 notify_fail("Es gibt nur die Haken 1 bis 16.\n");
295 if ( hakennr < 1 || hakennr > 16 )
296 return 0;
297 notify_fail("An diesem Haken haengt aber doch kein Schluessel.\n");
298 if ( !objectp(haken[hakennr,HOOK_OB]) )
299 return 0;
300
301 keys += ({ haken[hakennr,HOOK_OB] });
302 }
303
304 // Keiner gefunden? Vielleicht ist ja einer mit einer bestimmten
305 // Beschriftung gemeint?
306 if ( !sizeof(keys) ) {
307 // Schluessel mit dem angegebenen Namen suchen
308 keys = TP->find_obs(was+" in brett in raum");
309 // Hakennummer ermitteln, wenn eine Beschriftung angegeben wurde.
310 string wanted_desc;
311 sscanf(was, "schluessel fuer %s", wanted_desc);
312 object wanted_key = GetKeyForLabel(wanted_desc);
313 if ( objectp(wanted_key) )
314 keys += ({wanted_key});
315 }
316 // Immer noch nix gefunden? Dann muss sich der Spieler was anderes
317 // einfallen lassen.
318 notify_fail("Am Schluesselbrett haengt kein solcher Schluessel.\n");
319 if ( !sizeof(keys) )
320 return 0;
321
322 // Alle gefundenen Schluessel verarbeiten. Alle, die nicht bewegt werden
323 // koennen, verbleiben in der Liste.
324 foreach( object key : keys ) {
325 int current_hook = GetHookNumberForKey(key);
326 if ( key->move(TP,M_GET) == MOVE_OK ) {
327 keys -= ({ key });
328 tell_object(TP, BS("Du nimmst "+key->name(WEN,1)+" von Haken "+
329 current_hook+" ab."));
330 // Schluessel austragen; bestehende Beschriftungen bleiben erhalten
331 haken[current_hook, HOOK_OB] = 0;
332 }
333 }
334 // Von allen nicht vom Haken genommenen Schluesseln die Namen ermitteln
335 // und auflisten.
336 if ( sizeof(keys) ) {
337 tell_object(TP, BS(capitalize(CountUp(keys->name(WER,1)))+" "+
338 (sizeof(keys)==1?"konnte":"konnten")+" nicht vom Schluesselbrett "
339 "abgenommen werden."));
340 }
341 return 1;
342}
343
344// Verfuegbare Kommandos auflisten.
345varargs int skommandos(string str) {
346 notify_fail( "Fehler: Dieser Befehl benoetigt eine gueltige Objekt-Id als "
347 +"Parameter.\nBeispiel: skommandos [schluessel]brett\n");
348
349 if( !id(str) ) return 0;
350
351 write(
352 "==================================================================="
353 "==========\n"
354 "Aktuelle Version: "+QueryProp("cnt_version_std")+
355 QueryProp("cnt_version_obj")+"\n"+
356 BS(Name(WER,1)+" kann nur in diesem Seherhaus verwendet werden, "
357 "da "+QueryPronoun(WER)+" speziell dafuer gekauft wurde. "+
358 CAP(QueryPronoun(WER))+" verfuegt ueber folgende Kommandos:")+
359 "----------------------------------------------------------------------"
360 "-------\n"
361 "serlaube [schluessel]brett [spielername|\"hausfreunde\"|\"zweities\"]\n"
362 " Erlaubt Personen, "+name(WEN,1)+" mitzubenutzen.\n"
363 " serlaube ohne Angabe eines Arguments listet alle Personen mit Zugriff "
364 "auf\n "+name(WEN,1)+" auf.\n\n"
365 "verschiebe [schluessel]brett nach [ausgang]\n"
366 " Damit kannst Du "+name(WEN,1)+" innerhalb Deines Seherhauses "
367 "verschieben.\n\n"
368 "sverstecke [schluessel]brett\n"
369 " Damit machst Du "+name(WEN,1)+" unsichtbar.\n"
370 "shole [schluessel]brett hervor\n"
371 " Damit machst Du "+name(WEN,1)+" wieder sichtbar.\n"
372 "zertruemmer [schluessel]brett\n"
373 " Damit zerstoerst Du das Schluesselbrett.\n"
374 "sbeschrifte haken <nr> mit <text>|nichts\n"
375 " Eine Beschriftung an einem Haken anbringen oder loeschen.\n"
376 "sliste lang|kurz\n"
377 " Schluesselanzeige konfigurieren: alle oder nur belegte auflisten.\n"
378 "haenge <schluesselname> an haken [nr]\n"
379 "haenge <schluesselname> an [schluessel]brett\n"
380 " Damit haengst Du einen Schluessel an das Brett.\n"
381 "nimm schluessel von haken <nr>\n"
382 "nimm <schluesselname> von [schluessel]brett\n"
383 "nimm schluessel fuer <beschriftung> von [schluessel]brett.\n"
384 " Damit nimmst Du einen Schluessel vom Schluesselbrett.\n"
385 "==================================================================="
386 "==========\n");
387 return 1;
388}
389
390static int erlaubnis_liste()
391{
392 if( QueryHausbesitzer() != QueryTP() && !QueryProp("test") )
393 {
394 tell_object(TP, BS("Nur "+QueryHausbesitzer()+" darf Berechtigungen "
395 +name(WESSEN,1)+" abfragen!"));
396 return 1;
397 }
398
399 string *strs;
400 string str =
401 "==================================================================="
402 "==========\n";
403 if ( hauserlaubnis ) {
404 strs = SHVERWALTER->HausProp(LOWER(QueryHausbesitzer()), 2);
405 str += "Folgende Freunde Deines Hauses duerfen "+name(WEN,1)+
406 " mitbenutzen:\n";
407 if(sizeof(strs)) {
408 str += BS(CountUp(strs));
409 }
410 else {
411 str += BS("Du hast keiner Person Zugriff auf Dein Haus gewaehrt...");
412 }
413 }
414 else {
415 str+= BS("Die Freunde Deines Hauses duerfen "+name(WEN,1)+
416 " nicht mitbenutzen.");
417 }
418
419 str +=
420 "-------------------------------------------------------------------"
421 "----------\n";
422
423 if( zweitieerlaubnis!="" ) {
424 if( zweitieerlaubnis==geteuid(TP) )
425 str += BS("Alle Deine Zweities duerfen "+name(WEN,1)+" mitbenutzen.");
426 else
427 str += BS("Alle Zweities von "+CAP(zweitieerlaubnis)+" duerfen "
428 +name(WEN,1)+" mitbenutzen.");
429 str +=
430 "-------------------------------------------------------------------"
431 "----------\n";
432 }
433
434 strs=QueryProp("cnt_erlaubnis");
435
436 if(sizeof(strs)) {
437 str += BS("Folgende sonstige Personen duerfen "+name(WEN,1)+
438 " mitbenutzen:");
439 str += CountUp(strs);
440 }
441 else {
442 str += BS("Es gibt keine sonstigen Personen, die "+name(WEN,1)+
443 " mitbenutzen duerfen.");
444 }
445 str +=
446 "==================================================================="
447 "==========\n";
448
449 return 1;
450}
451
452// Haken beschriften.
453static int cmd_beschriften(string str) {
454 string nfm = "Syntax: sbeschrifte haken <hakennummer> mit "
455 "<text>|nichts\n"
456 "Fuer <text> kannst Du einen beliebigen Text mit bis zu 30 Zeichen "
457 "angeben,\n"
458 "'nichts' loescht die Beschriftung eines Schildes.\n";
459
460 notify_fail("Das darfst Du nicht!\n");
461 if(!erlaubt())
462 return 0;
463
464 string text;
465 int hnr;
466 str = TP->_unparsed_args(0);
467 notify_fail(nfm);
468 if ( !stringp(str) || !sizeof(str) )
469 return 0;
470 if ( sscanf(str,"haken %d mit %s", hnr, text)!=2 )
471 return 0;
472
473 notify_fail("Welchen Haken moechtest Du beschriften?\n"+nfm);
474 if(!hnr)
475 return 0;
476
477 notify_fail("Es gibt nur die Haken 1 bis 16.\n");
478 if ( hnr < 1 || hnr > 16 )
479 return 0;
480
481 notify_fail("Womit moechtest Du den Haken beschriften?\n"+nfm);
482 if( !stringp(text) || !sizeof(text) )
483 return 0;
484
485 notify_fail("Der Text sollte nicht laenger als 30 Zeichen sein.\n");
486 if(sizeof(text) > 30)
487 return 0;
488
489 if ( lower_case(text) == "nichts" ) {
490 if ( stringp(haken[hnr,HOOK_LABEL]) ) {
491 tell_object(TP, BS("Sorgfaeltig wischst Du die Beschriftung des "
492 "Hakens "+hnr+" weg."));
493 haken[hnr,HOOK_LABEL]=0;
494 }
495 else {
496 tell_object(TP, BS("Du musst Dich geirrt haben. Haken "+hnr+" ist "
497 "gar nicht beschriftet."));
498 }
499 }
500 else if ( lower_case(text) == "schluessel" ) {
501 tell_object(TP, BS(
502 "Du solltest Dir etwas Aussagekraeftigeres einfallen lassen."));
503 }
504 else {
505 tell_object(TP, BS("Du beschriftest das Schildchen ueber Haken "+hnr+
506 " mit "+text+"."));
507 tell_room(environment(), BS(
508 TP->Name(WER)+" schreibt etwas ans Schluesselbrett."), ({TP}));
509 haken[hnr,HOOK_LABEL] = text;
510 }
511 return 1;
512}
513
514/***** HILFSFUNKTIONEN *****/
515
516// Beschreibung eines Hakens erzeugen. Wenn <keynum> angegeben wird,
517// wird nur der gesuchte Haken angezeigt, egal ob leer oder nicht.
518// Ansonsten werden die belegten Haken angezeigt, ausser wenn
519// <hooklist_long> gesetzt ist. Dann werden alle Haken aufgelistet.
520private varargs string KeyDescription(int keynum) {
521 string desc="";
522 mapping keylist=([:2]);
523
524 // Liste derHaken auf den/die gesuchten einschraenken.
525 // Nur ein Haken soll angeschaut werden. Dies hat immer Prioritaet,
526 // d.h. auch bei <sliste alle> wird nur ein Haken gelistet.
527 if ( keynum ) {
528 m_add(keylist, keynum, m_entry(haken, keynum)...);
529 }
530 // Wenn <sliste alle> gesetzt ist, alle ausgeben.
531 else if ( hooklist_long ) {
532 keylist = haken;
533 }
534 // Ansonster nur die belegten.
535 else {
536 keylist = filter(haken,
537 function int (int num, <string|object>* values) {
538 return objectp(values[0]);
539 });
540 }
541
542 // Ueber das Mapping mit den selektierten Haken laufen und Ausgaben
543 // erzeugen.
544 foreach(int num : 1..16) {
545 // Hier wird der aktuelle Wert uebersprungen, wenn er nicht enthalten
546 // ist, da die Zuweisung in <key> und <keydesc> auch dann eine 0 ergeben
547 // wuerde, und somit Keys mit leeren Values nicht von nicht existierenden
548 // Keys zu unterscheiden waeren.
549 if ( member(m_indices(keylist), num) == -1 )
550 continue;
551 string keydesc = keylist[num, HOOK_LABEL];
552 object key = keylist[num, HOOK_OB];
553 desc += "Haken " + num + (stringp(keydesc)?" ["+keydesc+"]: " : ": ");
554 desc += (objectp(key) ? key->short() : "leer\n");
555 }
556 return desc;
557}
558
559// Rueckgabewert: 1, wenn es sich um ein Schluesselobjekt handelt, sonst 0.
560// Schluessel werden anhand der ID "schluessel" erkannt oder daran, dass
561// QueryDoorKey() einen Wert zurueckgibt, d.h. dass dieses Objekt eine
562// Standard-Doormaster-Tuer oeffnet.
563private int IsValidKey(object ob) {
564 return (objectp(ob) && (ob->id("schluessel") || ob->QueryDoorKey()!=0));
565}
566
567// Gibt die Nummer des naechsten freien Hakens zurueck oder 0, wenn
568// keiner frei ist. Da Mappings nicht sortiert sind, muss von 1-16 numerisch
569// iteriert werden, damit immer der erste freie Haken gefunden wird und nicht
570// irgendeiner.
571// Rueckgabewert: Hakennummer von 1-16 oder 0, wenn kein Haken frei ist.
572private int GetNextFreeSlot() {
573 int slot;
574 foreach(int i : 1..16) {
575 if ( !objectp(haken[i,HOOK_OB]) ) {
576 slot = i;
577 break;
578 }
579 }
580 return slot;
581}
582
583// Gibt zu einer Schild-Beschriftung die zugehoerige Hakenposition aus.
584// Es wird die kleingeschriebene Variante gesucht, so dass Spieler zwar
585// Grossschreibung in den Beschriftungen verwenden koennen, diese aber
586// nicht beruecksichtigt wird. Ansonsten koennte es zu Schwierigkeiten mit
587// Dopplungen wie "Vesray" und "vesray" kommen.
588// Rueckgabewert: Hakennummer von 1-16 oder 0, wenn der Text nicht gefunden
589// wurde.
590private object GetKeyForLabel(string label) {
591 if ( label )
592 label = lower_case(label);
593 foreach(int i: 1..16) {
594 if ( haken[i, HOOK_LABEL] && label &&
595 lower_case(haken[i,HOOK_LABEL]) == label )
596 return haken[i,HOOK_OB];
597 }
598 return 0;
599}
600
601// Gibt zu dem uebergebenen Objekt die Nummer des Hakens zurueck, an dem
602// es haengt.
603private int GetHookNumberForKey(object ob) {
604 foreach(int num, object key : haken) {
605 if ( key == ob )
606 return num;
607 }
608 return 0;
609}
610
611// Bereinigt Datenstruktur in <haken> und das Inventar des Brettes, indem
612// a) geprueft wird, ob alle in <haken> eingetragenen Objekte sich auch im
613// Brett befinden und
614// b) geprueft wird, ob alle im Inventar befindlichen Objekte auch korrekt in
615// <haken> eingetragen sind.
616// Ueberzaehlige Objekte werden rausgeworfen.
617private void ConsolidateInventory() {
618 foreach(int i, object ob : haken) {
619 // Objekt existiert, ist aber nicht im Schluesselbrett? Dann austragen.
620 if (objectp(ob) && environment(ob) != ME) {
621 m_delete(haken, i);
622 // Wird auch vom reset() aus gerufen, dann ist TP == 0.
623 if ( objectp(TP) )
624 tell_object(TP, BS("Hoppla! "+ob->Name(WER,1)+" scheint vom "
625 "Schluesselbrett verschwunden zu sein!"));
626 }
627 }
628 object *resterampe = all_inventory(ME) - m_values(haken, HOOK_OB);
629 if (sizeof(resterampe)) {
630 resterampe->move(environment(),M_PUT);
631 tell_room(environment(), BS("Ploetzlich faellt etwas vom "
632 "Schluesselbrett zu Boden, das Du zuvor gar nicht gesehen hattest."));
633 }
634}
635
636string short() {
637 string sh=QueryProp(P_SHORT);
638
639 // Unsichtbar? Dann gibts nichts zu sehen ...
640 if ( QueryProp(P_INVIS) || !sh )
641 return 0;
642 if ( QueryProp("versteckt") == 1 )
643 sh = "";
644 else
645 sh += ".";
646
647 return process_string(sh)+"\n";
648}
649
650// Im Reset vorsichtshalber auch mal aufraeumen.
651void reset() {
652 ConsolidateInventory();
653 return ::reset();
654}
655
656varargs int PreventInsert(object ob) {
657 // Kein Schluessel? Hat in diesem Container nix verloren!
658 if( !IsValidKey(ob )) {
659 return 1;
660 }
661 ConsolidateInventory();
662 return ::PreventInsert(ob);
663}
664
665// Wenn ein Schluessel sich aufloest, muss die Liste abgeglichen werden.
666void NotifyRemove(object ob) {
667 tell_room(environment(ME), BS("Hoppla! "+ob->Name(WER,1)+" hat sich "
668 "gerade in Wohlgefallen aufgeloest."));
669 // Das Objekt <ob> zerstoert sich erst nach dem Aufruf dieser Funktion,
670 // daher per call_out() aufraeumen.
671 call_out(#'ConsolidateInventory, 1);
672}
673
674// Zesstra, 1.7.07, fuers Hoerrohr
675// Darf ich da Arathorn eintragen? ;-)
676string GetOwner() {
677 return "seleven";
678}
679