MG Mud User | 88f1247 | 2016-06-24 23:31:02 +0200 | [diff] [blame^] | 1 | //--------------------------------------------------------------------------- |
| 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> |
| 20 | inherit 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 | |
| 27 | private varargs string KeyDescription(int keynum); |
| 28 | private int IsValidKey(object ob); |
| 29 | private int GetNextFreeSlot(); |
| 30 | private object GetKeyForLabel(string label); |
| 31 | private int GetHookNumberForKey(object ob); |
| 32 | private void ConsolidateInventory(); |
| 33 | |
| 34 | // Struktur: ([ haken_nr : objekt; beschriftung ]) |
| 35 | private mapping haken=([:2]); |
| 36 | private int hooklist_long = 0; |
| 37 | |
| 38 | protected 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. |
| 101 | static 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. |
| 131 | static 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. |
| 153 | static 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 |
| 262 | static 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. |
| 345 | varargs 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 | |
| 390 | static 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. |
| 453 | static 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. |
| 520 | private 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. |
| 563 | private 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. |
| 572 | private 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. |
| 590 | private 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. |
| 603 | private 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. |
| 617 | private 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 | |
| 636 | string 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. |
| 651 | void reset() { |
| 652 | ConsolidateInventory(); |
| 653 | return ::reset(); |
| 654 | } |
| 655 | |
| 656 | varargs 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. |
| 666 | void 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? ;-) |
| 676 | string GetOwner() { |
| 677 | return "seleven"; |
| 678 | } |
| 679 | |