| #pragma strong_types, save_types, rtt_checks |
| #pragma no_inherit, no_shadow |
| |
| inherit "/std/container"; |
| |
| #include <properties.h> |
| #include <defines.h> |
| #include <items/kraeuter/kraeuter.h> |
| |
| #define BS(x) break_string(x, 78, 0, BS_LEAVE_MY_LFS) |
| |
| // Enthaelt die raumabhaengig variable Kurzbeschreibung, die der Trockner |
| // annimmt, wenn gerade ein Kraut getrocknet wird. |
| private string short_desc; |
| |
| // Globale Variable fuer die Qualitaet, damit man den Wert nicht im |
| // call_out() mitgeben muss, und sie somit auch nicht mit call_out_info() |
| // abfragbar ist. |
| private int drying_quality; |
| |
| private void dry_plant(object kraut, string *msgs); |
| private void destroy_herb(object kraut); |
| private string my_short(); |
| private int|string my_noget(); |
| private string my_long(); |
| private string* my_ids(); |
| private string|string* my_name(); |
| private mixed my_mat(); |
| |
| protected void create() { |
| if ( !clonep(ME) ) { |
| set_next_reset(-1); |
| return; |
| } |
| ::create(); |
| |
| Set(P_SHORT, #'my_short, F_QUERY_METHOD); |
| Set(P_LONG, #'my_long, F_QUERY_METHOD); |
| Set(P_NOGET, #'my_noget, F_QUERY_METHOD); |
| Set(P_IDS, #'my_ids, F_QUERY_METHOD); |
| Set(P_NAME, #'my_name, F_QUERY_METHOD); |
| Set(P_MATERIAL, #'my_mat, F_QUERY_METHOD); |
| // Properties zu securen ist vielleicht etwas sehr paranoid. |
| Set(P_SHORT, SECURED|NOSETMETHOD, F_MODE_AS); |
| Set(P_LONG, SECURED|NOSETMETHOD, F_MODE_AS); |
| Set(P_NOGET, SECURED|NOSETMETHOD, F_MODE_AS); |
| Set(P_IDS, SECURED|NOSETMETHOD, F_MODE_AS); |
| Set(P_NAME, SECURED|NOSETMETHOD, F_MODE_AS); |
| SetProp(P_MAX_OBJECTS,1); |
| SetProp(P_MAX_WEIGHT,100000); |
| SetProp(P_TRANSPARENT,0); |
| |
| AddCmd("trockne&@PRESENT", "cmd_trocknen", "Was willst Du trocknen?"); |
| } |
| |
| private string my_short() { |
| if ( first_inventory(ME) ) |
| return short_desc; |
| return 0; |
| } |
| |
| // Querymethoden, die Langbeschreibung und weitere Properties des im |
| // Trockner enthaltenen Krautobjektes nach draussen weiterreichen, um die |
| // Illusion zu erzeugen, dass wirklich das echte Kraut im Raum zu sehen sei. |
| // Alle Funktionen gehen davon aus, dass das zu trocknende Kraut das erste |
| // (und einzige) Objekt im Inventar des Trockners ist und geben dessen |
| // Properties zurueck. |
| private string my_long() { |
| object inv = first_inventory(ME); |
| if ( objectp(inv) ) |
| return inv->QueryProp(P_LONG)+inv->Name(WER,1)+ |
| " wird gerade getrocknet.\n"; |
| return 0; |
| } |
| |
| private string|string* my_name() { |
| object inv = first_inventory(ME); |
| if ( objectp(inv) ) |
| return inv->QueryProp(P_NAME); |
| return Query(P_NAME,F_VALUE); |
| } |
| |
| private mixed my_mat() { |
| object inv = first_inventory(ME); |
| if ( objectp(inv) ) |
| return inv->QueryProp(P_MATERIAL); |
| return ([]); |
| } |
| |
| private int|string my_noget() { |
| object inv = first_inventory(ME); |
| if ( objectp(inv) ) |
| return inv->Name(WER,1)+" wird gerade getrocknet, Du solltest "+ |
| inv->QueryPronoun(WEN)+" liegenlassen, bis "+ |
| inv->QueryPronoun(WER)+" fertig ist."; |
| return 1; |
| } |
| |
| private string* my_ids() { |
| object inv = first_inventory(ME); |
| if ( objectp(inv) ) |
| return inv->QueryProp(P_IDS); |
| return Query(P_IDS,F_VALUE); |
| } |
| |
| // Kommandofunktion zum Starten des Tocknungsvorganges. Holt sich die |
| // relevanten Daten aus dem Krautmaster ab, setzt Meldungen und Texte und |
| // wirft den Trocknungs-Callout an. |
| static int cmd_trocknen(string str, mixed *param) { |
| // Master liefert leeres Array oder eins mit 2 Elementen ({delay, quality}) |
| // environment(ME) liest er selbstaendig aus |
| int *drying_data = PLANTMASTER->QueryDryingData(); |
| object kraut = param[0]; |
| |
| // Der Trockner taeuscht vor, selbst das Kraut zu sein, das zum Trocknen |
| // im Raum liegt. Daher wird hier noch geprueft, ob der Spieler vielleicht |
| // den Trockner selbst zu trocknen versucht. |
| if ( kraut == ME ) { |
| tell_object(PL, BS(kraut->Name(WER,1)+" wird bereits getrocknet, Du " |
| "solltest "+kraut->QueryPronoun(WEN)+" besser liegenlassen.")); |
| } |
| // Es muss sich auch um ein Kraut handeln und nicht irgendwas anderes. |
| else if ( load_name(kraut) != PLANTITEM ) { |
| return 0; |
| } |
| // Spieler muss das Kraut im Inventar haben. |
| else if ( environment(kraut) != PL ) { |
| tell_object(PL, BS( |
| "Du musst "+kraut->name(WEN,1)+" schon in die Hand nehmen, um "+ |
| kraut->QueryPronoun(WEN)+" sorgfaeltig trocknen zu koennen.")); |
| } |
| // Das Kraut darf nicht unwirksam sein, was durch eine Plant-ID von -1 |
| // gekennzeichet ist. |
| else if ( param[0]->QueryPlantId() == -1 ) { |
| tell_object(PL, BS( |
| kraut->Name(WER,1)+" haette ohnehin keine Wirkung, da kannst Du Dir " |
| "die Muehe sparen, "+kraut->QueryPronoun(WEN)+" noch aufwendig zu " |
| "trocknen.")); |
| } |
| // Master hat keine Daten geliefert, also befindet sich der Trockner |
| // offenbar in einem unzulaessigen Raum. |
| else if ( sizeof(drying_data) != 2 ) { |
| tell_object(PL, BS( |
| "Dieser Ort ist nicht geeignet, um "+kraut->name(WEN,1)+" hier zu " |
| "trocknen.")); |
| } |
| // Kraut ist schon getrocknet? Dann waere eine weitere Trocknung unsinnig. |
| else if ( kraut->QueryDried() ) { |
| tell_object(PL, BS(kraut->Name(WER,1)+" ist schon getrocknet, eine " |
| "weitere Behandlung wuerde "+kraut->QueryPronoun(WEM)+" zu stark " |
| "zusetzen, "+kraut->QueryPronoun(WEN)+" gar zerstoeren.")); |
| } |
| // Es ist schon eine Pflanze im Trockner? Dann nicht noch eine reintun. |
| else if ( first_inventory(ME) ) { |
| tell_object(PL, BS("Hier wird gerade schon etwas getrocknet.")); |
| } |
| // Aus irgendeinem Grund schlaegt die Bewegung des Krautes in den Trockner |
| // fehl? Dann muss sich das ein Magier anschauen, denn das geht nicht mit |
| // rechten Dingen zu. |
| else if ( kraut->move(ME, M_PUT) != MOVE_OK ) { |
| tell_object(PL, BS("Aus einem Dir unerfindlichen Grund schaffst Du es " |
| "nicht, die Trocknung "+kraut->name(WESSEN,1)+" zufriedenstellend " |
| "durchzufuehren und brichst den Versuch wieder ab. Du solltest einem " |
| "Magier Bescheid sagen, dass hier etwas nicht stimmt.")); |
| } |
| // Alles geklappt, alle Bedingungen erfuellt? Dann koennen wir jetzt |
| // tatsaechlich endlich das Kraut trocknen. |
| else { |
| int drying_delay = drying_data[0]; // nur lokal benoetigt |
| drying_quality = drying_data[1]; // globale Variable |
| string where = load_name(environment(ME)); |
| string msg_self, msg_other; |
| string kr = kraut->name(WEN,1); |
| string* callout_msgs = ({ |
| kraut->Name(WER,1)+" ist jetzt in einem zufriedenstellenden " |
| "Zustand. Besser wirst Du es an diesem Ort vermutlich nicht " |
| "hinbekommen, daher beendest Du die Trocknung und nimmst "+ |
| kraut->QueryPronoun(WEN)+" wieder an Dich.", |
| PL->Name(WER)+" schaut "+kr+" pruefend an und " |
| "beendet dann die Trocknung, offenbar zufrieden mit dem Resultat."}); |
| int blocker; // auf 1 setzen, falls das Trocknen verhindert werden soll |
| // Hier koennen jetzt abhaengig vom Raum passende Meldungen gesetzt |
| // werden. Die zulaessigen Standorte hier noch weiter zu obfuscaten |
| // waere zwar moeglich, aber zu unuebersichtlich geworden. |
| switch(where) { |
| /* |
| * GEBIRGE |
| */ |
| case "/d/gebirge/silvana/cronoertal/room/th7u": |
| msg_self = "Du legst "+kr+" vorsichtig und in gebuehrendem Abstand " |
| "zu den Flammen neben die Feuerstelle und wartest gespannt, ob " |
| "die Trocknung wohl gelingen wird."; |
| msg_other = PL->Name(WER)+" legt etwas neben die Feuerstelle, " |
| "vermutlich, um es zu trocknen."; |
| short_desc = kraut->Name(WER)+" liegt zum Trocknen am Feuer"; |
| break; |
| /* |
| * EBENE |
| */ |
| case "/d/ebene/zardoz/burg/kueche": |
| msg_self = "Du legst "+kr+" vorsichtig an eine der kuehleren " |
| "Stellen des Bleches im Ofen, es soll ja trocknen, und nicht " |
| "backen."; |
| msg_other = PL->Name(WER)+" legt etwas Gruenzeug auf das Blech im " |
| "Ofen."; |
| short_desc = kraut->Name(WER)+" liegt zum Trocknen im Ofen"; |
| break; |
| case "/d/ebene/esme/masinya/rooms/kueche": |
| msg_self = "Du haengst "+kr+" ueber den Herd, um "+ |
| kraut->QueryPronoun(WEN)+" in der Abwaerme trocknen zu lassen."; |
| msg_other = PL->Name(WER)+" haengt ein Kraut zum Trocknen ueber " |
| "den Herd."; |
| short_desc = kraut->Name(WER)+" haengt zum Trocknen ueber dem Herd"; |
| break; |
| case "/d/ebene/throin/brauerei/room/darre06": |
| msg_self = "Du legst "+kr+" zu dem Malz in den " |
| "Keimkasten in der Hoffnung, dass "+kraut->QueryPronoun(WER)+ |
| " auf diese Weise getrocknet werden kann."; |
| msg_other = PL->Name(WER)+" legt etwas eigenes Gruenzeug zu dem " |
| "Malz in den Keimkasten."; |
| short_desc = kraut->Name(WER)+" liegt zum Trocknen im Keimkasten"; |
| break; |
| case "/d/ebene/arathorn/orakel/room/zelt": |
| msg_self = "Du legst "+kr+" vorsichtig ans " |
| "Lagerfeuer. Du schaust unsicher zu Chinkuwaila, doch der " |
| "alte Schamane nickt zustimmend, Du hast wohl alles richtig " |
| "gemacht."; |
| msg_other = PL->Name(WER)+" legt eine Pflanze ans Lagerfeuer, wohl " |
| "um sie zu trocknen."; |
| short_desc = kraut->Name(WER)+" wird gerade am Lagerfeuer getrocknet"; |
| break; |
| /* |
| * WUESTE |
| */ |
| case "/d/wueste/tsunami/schule/rooms/kraeuter": |
| blocker = objectp(present_clone("/d/wueste/tsunami/schule/mon/hexe", |
| environment(ME))); |
| if ( !blocker ) { |
| msg_self = "Du steckst "+kr+" in Muetterchen " |
| "Isewinds Trockenofen, der wohlig zu knistern beginnt."; |
| msg_other = PL->Name(WER)+" legt vorsichtig ein Kraut "; |
| short_desc = kraut->Name(WER)+" wird gerade im Ofen getrocknet"; |
| } |
| else { |
| msg_self = "Muetterchen Isewind haelt Dich auf, sie scheint " |
| "niemanden an ihren Trockenofen heranlassen zu wollen."; |
| msg_other = PL->Name(WER)+" wird von Muetterchen Isewind an der " |
| "Benutzung des Ofens gehindert."; |
| } |
| break; |
| /* |
| * WALD |
| */ |
| case "/d/wald/feigling/quest/room/huette3": |
| msg_self = "Du legst "+kr+" so nah ans Feuer, " |
| "wie Du glaubst, dass es der Trocknung nicht schadet."; |
| msg_other = PL->Name()+" legt eine Pflanze an die Kochstelle."; |
| short_desc = kraut->Name(WER)+" liegt zum Trocknen an der " |
| "Feuerstelle"; |
| break; |
| case "/d/wald/leusel/quest/rooms/laborsuedosten": |
| msg_self = "Du legst "+kr+" in eins der " |
| "Tonschiffchen und schiebst es in den mittelheissen Ofen hinein. " |
| "Hoffentlich geht das gut, es kommt Dir da drinnen schon fast zu " |
| "warm fuer eine ordnungsgemaesse Trocknung vor."; |
| msg_other = PL->Name(WER)+" schiebt ein Kraut in einem " |
| "Tonschiffchen in einen der Oefen hinein, um es zu trocknen."; |
| short_desc = kraut->Name(WER)+" dampft in einem Tonschiffchen im " |
| "ersten Ofen vor sich hin"; |
| break; |
| /* |
| * INSELN |
| */ |
| case "/d/inseln/zesstra/vulkanweg/room/r8": |
| msg_self = "Du legst "+kr+" vorsichtig auf die " |
| "heissen Felsen in der Naehe des Lavasees, auf dass die " |
| "heissen Winde "+kraut->QueryPronoun(WEN)+" trocknen moegen."; |
| msg_other = PL->Name(WER)+" legt ein Kraut auf den Felsen ab, um es " |
| "von der heissen Luft trocknen zu lassen."; |
| short_desc = kraut->Name(WER)+" liegt zum Trocknen auf dem Felsen"; |
| break; |
| case "/d/inseln/miril/zyklopen/room/palast/insel1p6": |
| // QueryOven() liefert 2 fuer "Feuer", 1 fuer "Glut", 0 fuer "aus". |
| switch (environment(ME)->QueryOven()) { |
| case 2: |
| msg_self = "Du legst "+kr+" vorsichtig an das Feuer, das in " |
| "der Feuerstelle brennt, sorgsam bemueht, dass "+ |
| kraut->QueryPronoun(WER)+" nicht zuviel Hitze abbekommt."; |
| msg_other = PL->Name(WER)+" legt sorgsam ein Kraut in die Naehe " |
| "des Feuers, das in der Feuerstelle brennt."; |
| break; |
| case 1: |
| msg_self = "Du legst "+kr+" an die Feuerstelle, pruefst die " |
| "Hitze und rueckst "+kraut->QueryPronoun(WEN)+" noch etwas " |
| "naeher an die Glut, dann trittst Du zufrieden einen Schritt " |
| "zurueck."; |
| msg_other = PL->Name(WER)+" legt "+kraut->name(WEN)+" an die " |
| "Feuerstelle, schubst noch ein wenig daran herum und tritt " |
| "dann von der Glut zurueck, "+PL->QueryPronoun(WER)+" scheint " |
| "recht zufrieden zu sein."; |
| break; |
| default: |
| blocker=1; |
| msg_self = "In dem Kamin findest Du nicht einmal etwas Glut, " |
| "geschweige denn offenes Feuer. So wird das mit dem Trocknen " |
| "nichts, und auf dem Herd ist Dir das Risiko zu gross, dass " |
| "Fett aus der Pfanne auf "+kr+" spritzt."; |
| break; |
| } |
| short_desc = kraut->Name(WER)+" liegt zum Trocknen an der " |
| "Feuerstelle"; |
| break; |
| /* |
| * POLAR |
| */ |
| case "/d/polar/tilly/llp/rentner/kueche": |
| msg_self = "Der Herd gibt eine infernalische Hitze ab. Zum Kochen " |
| "ist das toll, aber Du brauchst doch einen Moment, um ein " |
| "geeignetes Plaetzchen fuer "+kr+" zu finden."; |
| msg_other = PL->Name(WER)+" legt ein Kraut auf den heissen Herd " |
| "und schiebt es unruhig noch ein wenig hin und her, als waere "+ |
| PL->QueryPronoun(WEM)+" die Hitze beinahe ein wenig zu gross."; |
| short_desc = kraut->Name(WER)+" liegt auf dem schmiedeeisernen " |
| "Herd"; |
| break; |
| /* |
| * VLAND |
| */ |
| case "/d/vland/morgoth/room/kata/ukat13": |
| object c = present_clone("/d/vland/morgoth/obj/kata/rfdcorpse", |
| environment(ME)); |
| // Bequemer, das auf 0 zu setzen, wenn's klappt, bei sovielen |
| // Hinderungsgruenden. ;-) |
| blocker = 1; |
| // Leiche liegt da. |
| if ( objectp(c) ) |
| { |
| // Feuerdaemon anwesend: der blockt den Versuch |
| if ( present_clone("/d/vland/morgoth/npc/kata/firedemon3", |
| environment(ME)) ) |
| { |
| msg_self = "Der Feuerdaemon droht Dir mit sengender Hoellenpein. " |
| "Beschwichtigend trittst Du einen Schritt zurueck."; |
| msg_other = PL->Name(WER)+" tritt auf den Aschehaufen zu, wird " |
| "aber von dem Feuerdaemon bedroht und weicht wieder zurueck."; |
| } |
| // Aschehaufen nicht mehr heiss genug? |
| else if ( c->QueryDecay()<2 ) { |
| msg_self = c->Name(WER,1)+" ist schon zu sehr abgekuehlt und " |
| "wuerde nicht mehr genug Hitze spenden, um "+kr+" zu trocknen."; |
| } |
| else |
| { |
| blocker = 0; |
| msg_self = "Dich vorsichtig umschauend, legst Du "+kr+" in die " |
| "Naehe "+c->name(WESSEN,1)+". Hoffentlich gelingt das in " |
| "dieser unwirtlichen Umgebung!"; |
| msg_other = PL->Name(WER)+" beugt sich zum Boden hinuntern und " |
| "legt vorsichtig ein Kraut in die Naehe "+c->name(WESSEN,1)+"."; |
| } |
| short_desc = kraut->Name(WER)+" liegt neben "+c->name(WEM,1)+ |
| ", offenbar soll "+kraut->QueryPronoun(WER)+" getrocknet werden"; |
| } |
| // Keine Leiche da? Dann geht's nicht. |
| else { |
| msg_self = "Genausowenig, wie Dir die Flammen in diesem Inferno " |
| "etwas anhaben koennen, so wenig kannst Du sie nutzen, um "+ |
| kr+" zu trocknen."; |
| } |
| break; |
| case "/d/vland/morgoth/room/kata/kata5": |
| object ob = present_clone("/d/vland/morgoth/npc/kata/ghost", |
| environment(ME)); |
| blocker = 1; |
| // Geist anwesend? Keine Chance. |
| if ( objectp(ob) ) { |
| msg_self = ob->Name(WER,1)+" stoert Dich in Deiner Konzentration, " |
| "Du kannst so nicht arbeiten!"; |
| } |
| // Umgebung noch neblig? Dann nicht trocknen. |
| else if ( environment(ME)->QueryFog() ) { |
| msg_self = "In diesem verdammten Nebel ist absolut nichts zu " |
| "sehen. Ausserdem ist es hier viel zu feucht, "+kr+" wuerde " |
| "ohnehin nur vor Deiner Nase wegschimmeln."; |
| } |
| // Feuer brennt nur noch 90 Sekunden? Dann lohnt sich das nicht. |
| else if ( query_next_reset(environment()) < time()+90 ) { |
| msg_self = "Ein pruefender Blick auf das Feuer zeigt Dir, dass " |
| "es wohl nicht mehr lange genug brennen wird, um "+kr+" noch " |
| "erfolgreich trocknen zu koennen."; |
| } |
| else { |
| blocker = 0; |
| msg_self = "Du legst "+kr+" in angemessenem Abstand zum Feuer " |
| "auf den Boden und wartest gespannt, ob Dir hier wohl eine " |
| "brauchbare Trocknung gelingen wird."; |
| msg_other = PL->Name(WER)+" bueckt sich zum Boden und legt etwas " |
| "ans Feuer, anscheinend ein Kraut, das "+PL->QueryPronoun(WER)+ |
| " trocknen will."; |
| short_desc = kraut->Name(WER)+" liegt zum Trocknen am Feuer"; |
| } |
| break; |
| case "/d/vland/alle/koomi_v/wschenke/room/waldschenke": |
| msg_self = "Dieser Kachelofen ist ungemein praktisch. Du legst "+ |
| kr+" einfach oben drauf, und die kuschelige Waerme trocknet "+ |
| kraut->QueryPronoun(WEN)+" beinahe von selbst."; |
| msg_other = PL->Name(WER)+" legt ein Kraut zum Trocknen oben auf " |
| "den Kachelofen, offenbar recht angetan von dessen kuscheliger " |
| "Waerme."; |
| short_desc = kraut->Name(WER)+" liegt zum Trocknen auf dem " |
| "Kachelofen"; |
| break; |
| /* |
| * DEBUGZWECKE |
| */ |
| case "/players/arathorn/workroom": |
| msg_self = "Du haeltst das Kraut vors Feuer und beginnst die " |
| "Trocknung."; |
| msg_other = PL->Name(WER)+" schickt sich an, ein Kraut am Feuer zu " |
| "trocknen."; |
| short_desc = kraut->Name(WER)+" liegt zum Trocknen am Feuer"; |
| break; |
| } |
| // Raummeldungen entsprechend der eingestellten Texte ausgeben. |
| tell_object(PL, BS(msg_self)); |
| if ( msg_other ) |
| tell_room(environment(ME), BS(msg_other), ({PL})); |
| // Callout starten, wenn niemand das Trocknen verhindert. |
| if ( !blocker ) |
| call_out(#'dry_plant, drying_delay, kraut, callout_msgs); |
| // Ansonsten das Kraut in den Spieler zurueck, das ja oben schon |
| // in den Trockner bewegt wurde. |
| else { |
| kraut->move(PL, M_GET); |
| } |
| } |
| return 1; |
| } |
| |
| // Kraut wird getrocknet, sofern der Spieler noch im Raum ist, ... |
| private void dry_plant(object kraut, string *msgs) { |
| if ( objectp(PL) && environment(PL) == environment(ME) ) { |
| tell_object(PL, BS(msgs[0])); |
| tell_room(environment(ME), BS(msgs[1]), ({PL})); |
| kraut->move(PL, M_GET); |
| kraut->DryPlant(drying_quality); |
| } |
| // ... ansonsten laeuft die Trocknung weiter, und das Kraut verbrennt. |
| else { |
| tell_room(ME, BS(kraut->Name(WER,1)+" wird extrem dunkel, bald wird "+ |
| kraut->QueryPronoun(WER)+" zu nichts mehr zu gebrauchen sein!")); |
| // Das Delay fuer diesen zweiten Callout ist immer fix. Kommt hoffentlich |
| // selten genug vor und braucht daher eher nicht extra aus dem Master |
| // geholt zu werden. |
| call_out(#'destroy_herb, 20, kraut); |
| } |
| } |
| |
| // Zerstoerung des Krautes. Da die Krautobjekte selbst eine Meldung |
| // ausgeben, wenn DryPlant(0) gerufen wird, wird erst das Kraut ins |
| // Environment bewegt und erst danach die Funktion gerufen. |
| private void destroy_herb(object kraut) { |
| kraut->move(environment(ME),M_PUT); |
| kraut->DryPlant(0); |
| } |
| |
| // Nur die korrekten Krautobjekte koennen in den Trockner bewegt werden. |
| // Schuetzt natuerlich nicht vor M_NOCHECK, aber wenn das vorkommen sollte, |
| // muss vielleicht noch weiter abgesichert werden, oder der verursachende |
| // Magier ausgeschimpft. ;-) |
| varargs int PreventInsert(object ob) { |
| if (load_name(ob) == PLANTITEM && clonep(ob)) |
| return ::PreventInsert(ob); |
| return 1; |
| } |