Added public files
Roughly added all public files. Probably missed some, though.
diff --git a/room/church.c b/room/church.c
new file mode 100644
index 0000000..e939b23
--- /dev/null
+++ b/room/church.c
@@ -0,0 +1,41 @@
+inherit "/std/room";
+
+#include <properties.h>
+
+create()
+{
+ ::create();
+ SetProp(P_LIGHT,1);
+ SetProp(P_INT_SHORT,"Village church");
+ SetProp(P_INT_LONG,
+ "You are in the local village church.\nThere is a huge pit in the center,\n" +
+ "and a door in the west wall. There is a button beside the door.\n"+
+ "This church has the service of reviving ghosts. Dead people come\n"+
+ "to the church and pray.\n"+
+ "There is a clock on the wall.\n"+
+ "There is an exit to south.\n");
+ AddDetail("pit","In the middle of the church is a deep pit.\n"+
+ "It was used for sacrifice in the old times, but nowadays\n" +
+ "it is only left for tourists to look at.\n");
+ AddDetail(({"elevator","door","button"}),
+ "The elevator doesn't work any more. It must be a relict from another time,\n"+
+ "a long-gone time, as this whole building.\n");
+ AddDetail("clock","The clock shows this game hasn't been rebooted for centuries. Time is\n"+
+ "standing still in this strange room.\n");
+ AddCmd("pray","pray");
+ AddCmd("open","open");
+ AddCmd("push","open");
+}
+
+open()
+{
+ notify_fail("The elevator doesn't work anymore, sorry.\n");
+ return 0;
+}
+
+pray()
+{
+ write("The gods this church was built for have died an extremly long time ago.\n");
+ return 1;
+}
+
diff --git a/room/death/death_mark.c b/room/death/death_mark.c
new file mode 100644
index 0000000..8219016
--- /dev/null
+++ b/room/death/death_mark.c
@@ -0,0 +1,67 @@
+#pragma strict_types
+
+#include <moving.h>
+#include <properties.h>
+#include <language.h>
+
+inherit "std/thing";
+
+void create()
+{
+ ::create();
+ SetProp( P_NAME, "Stempel des Todes" );
+ SetProp( P_GENDER, MALE );
+ SetProp( P_SHORT, 0 );
+ SetProp( P_INVIS, 1 );
+ SetProp( P_NEVERDROP, 1 );
+ SetProp( P_WEIGHT, 0);
+ AddId(({"death_mark","\ndeath_mark"}));
+}
+
+void reset()
+{
+ ::reset();
+ if (environment() && !query_once_interactive(environment()))
+ remove();
+}
+
+
+/*
+ * Function name: start_death
+ * Description: Start the death sequence.
+ */
+void start_death()
+{
+ if ( !environment() || !query_once_interactive(environment())
+ || !environment()->QueryProp(P_GHOST) )
+ {
+ destruct(this_object());
+ return;
+ }
+
+ say("Du siehst eine dunkle Gestalt, die etwas Dunst einsammelt ... oder vielleicht\n"+
+ "bildest du Dir das auch nur ein ...\n");
+ environment()->move("/room/death/virtual/death_room_"+getuid(environment()),
+ M_GO|M_SILENT|M_NO_SHOW|M_NOCHECK);
+ // direkt in virtuellen Todesraum moven
+}
+
+protected int PreventMove(object dest, object oldenv, int method) {
+ // wenn die marke schon ein Env hat oder der move nicht in einen Spieler
+ // geht, gehts nur mit M_NOCHECK.
+ if ( (environment(this_object()) || !query_once_interactive(dest))
+ && !(method & M_NOCHECK)) {
+ return ME_CANT_BE_DROPPED;
+ }
+
+ return ::PreventMove(dest, oldenv, method);
+}
+
+int _query_autoloadobj() { return 1; }
+
+void init()
+{
+ ::init();
+ if (this_player() == environment())
+ start_death();
+}
diff --git a/room/death/death_mark_hooked.c b/room/death/death_mark_hooked.c
new file mode 100644
index 0000000..0e09e8f
--- /dev/null
+++ b/room/death/death_mark_hooked.c
@@ -0,0 +1,66 @@
+#pragma strict_types
+
+#include <moving.h>
+#include <properties.h>
+#include <language.h>
+#include <new_skills.h>
+
+inherit "std/thing";
+
+void create()
+{
+ ::create();
+ SetProp( P_NAME, "Stempel des Todes" );
+ SetProp( P_GENDER, MALE );
+ SetProp( P_SHORT, 0 );
+ SetProp( P_INVIS, 1 );
+ SetProp( P_NEVERDROP, 1 );
+ AddId(({"death_mark","\ndeath_mark"}));
+}
+
+void reset()
+{
+ ::reset();
+ if (environment() && !query_once_interactive(environment()))
+ remove();
+}
+
+
+/*
+ * Function name: start_death
+ * Description: Start the death sequence.
+ */
+void start_death()
+{
+ if ( !environment() || !query_once_interactive(environment())
+ || !environment()->QueryProp(P_GHOST) )
+ {
+ destruct(this_object());
+ return;
+ }
+
+ say("Du siehst eine dunkle Gestalt, die etwas Dunst einsammelt ... oder vielleicht\n"+
+ "bildest du Dir das auch nur ein ...\n");
+ environment()->move("/room/death/virtual/death_room_"+getuid(environment()),
+ M_GO|M_SILENT|M_NO_SHOW|M_NOCHECK);
+ // Der folgende Code verhindert, dass ein unbedachter Magier im init
+ // oder exit einen Spieler tötet, und ihn dirket danach movet.
+ environment()->SetProp(P_TMP_MOVE_HOOK,({time()+10,this_object(),"catch_die_move"}));
+}
+
+varargs int move(mixed dest,mixed method)
+{
+ if (!method & M_NOCHECK) return ME_CANT_BE_DROPPED;
+ return ::move(dest,method);
+}
+
+int _query_autoloadobj() { return 1; }
+
+int catch_die_move() { return -1; }
+
+void init()
+{
+ ::init();
+ if (this_player() == environment())
+ start_death();
+}
diff --git a/room/death/death_room.c b/room/death/death_room.c
new file mode 100644
index 0000000..5e59f20
--- /dev/null
+++ b/room/death/death_room.c
@@ -0,0 +1,669 @@
+// MorgenGrauen MUDlib
+//
+// death_room.c -- Der Todesraum
+//
+// $Id: death_room.c 9138 2015-02-03 21:46:56Z Zesstra $
+
+
+#pragma strict_types
+
+#include <defines.h>
+#include <properties.h>
+#include <moving.h>
+#include <language.h>
+#include <wizlevels.h>
+#include <daemon.h>
+#include <new_skills.h>
+
+inherit "/std/room";
+
+mixed *players;
+mapping msgCache;
+
+
+private void flush( int unusedOnly );
+private string expand( string table, int value );
+private string parseText( string msg, object pl );
+private void do_remove();
+private varargs mixed get_sequence( string str );
+void add_player( object pl );
+static int filter_ldfied( string str );
+public int SmartLog( string creat, string myname, string str, string date );
+public mixed hier_geblieben( mixed dest, int methods, string direction,
+ string textout, string textin );
+public void init()
+{
+ this_player()->move("/room/death/virtual/death_room_"+getuid(this_player()),
+ M_NOCHECK|M_SILENT|M_NO_SHOW);
+ return;
+}
+
+public void create()
+{
+ if (IS_CLONE(this_object())) return;
+ ::create();
+
+ players = ({});
+ flush(0);
+
+ SetProp( P_NAME, "Lars" );
+ SetProp( P_GENDER, MALE );
+ SetProp( P_ARTICLE, 0 );
+ SetProp( P_LIGHT,1 );
+ SetProp( P_NO_TPORT, NO_TPORT_OUT );
+ SetProp( P_LOG_FILE, "TOD/Todesraum" );
+ SetProp( P_INT_SHORT, "Arbeitszimmer des Todes" );
+ SetProp( P_INT_LONG, break_string(
+ "Ein dunkler Raum, erleuchtet von dunklem Licht, das sich der "
+ "Dunkelheit nicht so sehr zu widersetzen scheint, indem es "
+ "leuchtet, als dass es der dunkelste Punkt in einer weniger "
+ "dunklen Umgebung ist. Im seltsamen Licht erkennst Du einen "+
+ "zentral aufgestellten Schreibtisch, der mit Diagrammen und "
+ "Buechern bedeckt ist. Die Waende verschwinden hinter Regalen, "
+ "die gefuellt sind mit in Leder gebundenen, dunklen Waelzern, "
+ "von denen geheimnisvolle Runen leuchten.\nTod.", 78, 0, 1 ) );
+}
+
+
+public void reset()
+{
+ ::reset();
+ flush(1);
+}
+
+private void flush( int unusedOnly )
+{
+ string *mi;
+ int i;
+
+ if ( unusedOnly ){
+ if ( i = sizeof(mi = m_indices(msgCache)) ){
+ for ( ; i--; )
+ if ( msgCache[mi[i], 1] )
+ msgCache[mi[i], 1] = 0;
+ else
+ msgCache = m_copy_delete( msgCache, mi[i] );
+ }
+ }
+ else
+ msgCache = ([]);
+}
+
+
+private string expand( string table, int value )
+{
+ int sz, wert, i;
+ string *texte;
+
+ sz = sizeof( texte = explode( table, "##" ) - ({""}) );
+
+ for ( i = 0; i < sz; i++ )
+ if ( i%2 ){
+ sscanf( texte[i], "%d", wert );
+
+ if ( value < wert )
+ break;
+ }
+ else
+ table = texte[i];
+
+ return table;
+}
+
+
+#define TOS(s) s[<1]
+#define STOS(s) s[<2]
+#define PUSH(x,s) (s+= ({ x }))
+#define POP(s) (s=s[0..<2])
+
+// ziemlich vom htmld abgekupfert ;)
+private string
+parseText( string msg, object pl )
+{
+ string *words, *texte, *todo, *done;
+ int endFlag;
+
+ int sz = sizeof( words = regexplode(msg, "[<][^>]*[>]") );
+ todo = ({ });
+ done = ({""});
+
+ for ( int i=1; i<sz; i+=2 ){
+ string cmd = words[i][1..<2];
+ TOS(done) += words[i-1];
+
+ if ( cmd[0] == '/' ){
+ endFlag = 1;
+ cmd = cmd[1..];
+ }
+ else
+ endFlag = 0;
+
+ switch( cmd[0] ){
+ case 'A': /*** Alignment ersetzen ***/
+ if (!endFlag){
+ PUSH( cmd, todo );
+ PUSH( "", done );
+ }
+ else
+ if ( todo[<1] == "A" ){
+ STOS(done) += expand(TOS(done), (int) pl->QueryProp(P_ALIGN));
+ done = done[0..<2];
+ todo = todo[0..<2];
+ }
+ break;
+
+ case 'D': /*** Tode ersetzen ***/
+ if ( !endFlag ){
+ PUSH( cmd, todo );
+ PUSH( "", done );
+ }
+ else
+ if ( todo[<1] == "D" ){
+ STOS(done) += expand(TOS(done), (int) pl->QueryProp(P_DEADS));
+ POP(done);
+ POP(todo);
+ }
+ break;
+
+ case 'L': /*** Level ersetzen ***/
+ if ( !endFlag ){
+ PUSH( cmd, todo );
+ PUSH( "", done );
+ }
+ else
+ if ( todo[<1] == "L" ){
+ STOS(done) += expand(TOS(done), (int) pl->QueryProp(P_LEVEL));
+ POP(done);
+ POP(todo);
+ }
+ break;
+
+ case 'Z': /*** Zufall ersetzen ***/
+ if ( !endFlag ){
+ PUSH( cmd, todo );
+ PUSH( "", done );
+ }
+ else{
+ if ( todo[<1][0] == 'Z'){
+ int cnt, rnd, wert, sz2;
+
+ if ( !sscanf(todo[<1], "Z=%d", rnd) )
+ STOS(done) += "\n###\n### Syntax Error in <Z>!\n###\n\n";
+ else {
+ rnd = random(rnd);
+ sz2 = sizeof( texte = explode(TOS(done), "##") );
+ wert=0;
+ cnt=0;
+
+ for ( int k = 1; k < sz2; k += 2 ){
+ sscanf( texte[k], "%d", wert );
+ cnt += wert;
+ if ( rnd < cnt ) {
+ STOS(done) += texte[k+1];
+ break;
+ }
+ }
+ }
+ POP(done);
+ POP(todo);
+ }
+ }
+ break;
+
+ case 'G': /*** Gender ersetzen ***/
+ if ( !endFlag ){
+ PUSH( cmd, todo );
+ PUSH( "", done );
+ }
+ else{
+ if( sizeof( texte = regexplode(TOS(done), ":") ) == 3 )
+ STOS(done) += texte[2*((int) pl->QueryProp(P_GENDER)
+ == FEMALE)];
+ POP(done);
+ POP(todo);
+ }
+ break;
+
+ case 'R': /*** Rasse ersetzen ***/
+ if ( !endFlag ){
+ PUSH( cmd, todo );
+ PUSH( "", done );
+ }
+ else{
+ int race;
+
+ texte = regexplode( TOS(done), "\\|" );
+ race = 2 * (member( ({ "Mensch", "Elf", "Zwerg", "Hobbit",
+ "Feline", "Dunkelelf" }),
+ (string) pl->QueryProp(P_RACE) ) + 1);
+
+ if ( race >= sizeof(texte) )
+ race = 0;
+
+ STOS(done) += texte[race];
+ POP(done);
+ POP(todo);
+ }
+ break;
+
+ case 'n': /*** Name, normal geschrieben ***/
+ TOS(done) += (string) (pl->name(RAW));
+ break;
+
+ case 'N': /*** Name, in Grossbuchstaben ***/
+ TOS(done) += upperstring(pl->name(RAW));
+ break;
+ }
+ }
+ PUSH( words[<1], done );
+ return implode( done, "" );
+}
+
+
+public void heart_beat()
+{
+ for ( int j = sizeof(players); j--; )
+ if ( !objectp(players[j][0]) ||
+ environment(players[j][0]) !=
+ find_object("/room/death/virtual/death_room_"+getuid(players[j][0])) )
+ players[j] = 0;
+
+ players -= ({0});
+
+ if ( !sizeof(players) ) {
+ set_heart_beat(0);
+ return;
+ }
+
+ for ( int j = sizeof(players); j--; ) {
+ int nr;
+ string msg;
+
+ nr = ++players[j][1];
+
+ if ( mappingp(players[j][2]) )
+ msg = players[j][2][nr];
+ else
+ msg = 0;
+
+ if ( !msg )
+ msg = players[j][3][1][nr];
+
+ if ( msg )
+ tell_object( players[j][0], parseText( msg, players[j][0] ) );
+ }
+
+ do_remove();
+}
+
+private void
+do_remove()
+{
+ int res;
+ string prayroom;
+ object plobj, pl;
+
+ for ( int j = sizeof(players); j--; ){
+ if ( players[j][1] >= players[j][3][0]){
+ pl = players[j][0];
+ while ( plobj = present("\ndeath_mark", pl) )
+ plobj->remove();
+
+ if ( !(prayroom = (string) pl->QueryPrayRoom()) )
+ prayroom="/room/pray_room";
+
+ pl->Set( P_TMP_MOVE_HOOK, 0 );
+ pl->Set( P_NO_ATTACK, 0, F_QUERY_METHOD );
+ pl->Set( P_LAST_KILLER, 0 );
+ pl->Set( P_KILLER, 0 );
+ pl->Set( P_ENEMY_DEATH_SEQUENCE, 0 );
+ pl->Set( P_NEXT_DEATH_SEQUENCE, 0 );
+ pl->Set( P_POISON, 0, F_QUERY_METHOD );
+
+ if ( catch( res = (int) pl->move(prayroom, M_GO|M_SILENT|M_NOCHECK) )
+ || res < 1 )
+ pl->move( "/room/pray_room", M_GO|M_NOCHECK );
+
+ players[j] = 0;
+ }
+ }
+
+ players -= ({0});
+
+ if ( !sizeof(players) )
+ set_heart_beat(0);
+}
+
+private varargs mixed
+get_sequence( string str )
+{
+ string *sequences;
+ int i, len, cacheable;
+
+ if ( !stringp(str) || catch( len = file_size(str) ) || len <= 0 ){
+ sequences = get_dir( "/room/death/sequences/*" ) - ({ ".", "..", ".svn" });
+ str = "/room/death/sequences/" + sequences[random( sizeof(sequences) )];
+ }
+
+ if ( cacheable = ((sizeof(str) > 21) &&
+ (str[0..21] == "/room/death/sequences/")) ){
+ if ( member(msgCache, str) ){
+ msgCache[str, 1] = 1; // Touch it!
+ return ({ msgCache[str], str });
+ }
+ }
+
+ sequences = explode( read_file(str), "\n" );
+ sscanf( sequences[0], "%d", len );
+ string seq = implode( sequences[1..], "\n" );
+ sequences = regexplode( seq, "[0-9][0-9]*:" );
+ mapping m = ([]);
+
+ for ( i = 1; i < sizeof(sequences)-1; i += 2 )
+ m[(int) sequences[i]] = sequences[i+1];
+
+ if ( cacheable )
+ msgCache += ([ str: ({ len, m }); 1 ]);
+
+ return ({ ({ len, m }), str });
+}
+
+// Description: Adds a player to the list
+void add_player( object pl )
+{
+ int kart, kgen;
+ int escaped;
+ object kill_liv, kill_ob;
+ mixed dseq, act_seq, killer_name, killer_msg;
+
+ set_heart_beat(1);
+ kgen = MALE;
+
+ foreach(object prev : caller_stack(1)) {
+ if ( !objectp(prev) || prev == pl )
+ continue;
+
+ string fn = object_name(prev);
+
+ if ( fn[0..12] == "/secure/login" && !kill_liv ){
+ escaped = 1;
+ break;
+ }
+
+ if ( fn[0..7] == "/secure/" && fn[0..13] != "/secure/merlin" )
+ continue;
+
+ if ( fn[0..21] == "/room/death/death_mark" )
+ continue;
+
+ if ( living(prev) ){
+ kill_liv = prev; // Killer
+ break;
+ }
+
+ kill_ob = prev; // killendes Objekt
+ }
+
+ object pre = (object) pl->QueryProp(P_KILLER);
+ if ( objectp(pre) ) {
+ dseq = (mixed) pre->QueryProp(P_ENEMY_DEATH_SEQUENCE);
+
+ if( !(killer_name = (mixed) pre->QueryProp(P_KILL_NAME)) ){
+ killer_name = (mixed) pre->QueryProp(P_NAME);
+ kart = (int) pre->QueryProp(P_ARTICLE);
+ kgen = (int) pre->QueryProp(P_GENDER);
+ }
+
+ killer_msg = (mixed)pre->QueryProp(P_KILL_MSG);
+ }
+
+ if ( !killer_name && kill_liv && function_exists( "QueryProp", kill_liv ) ){
+ dseq = (mixed) kill_liv->QueryProp(P_ENEMY_DEATH_SEQUENCE);
+
+ if( !(killer_name = (mixed) kill_liv->QueryProp(P_KILL_NAME)) ){
+ killer_name = (mixed) kill_liv->QueryProp(P_NAME);
+ kart = (int) kill_liv->QueryProp(P_ARTICLE);
+ kgen = (int) kill_liv->QueryProp(P_GENDER);
+ }
+
+ killer_msg = (mixed) kill_liv->QueryProp(P_KILL_MSG);
+ pre = kill_liv;
+ }
+
+ if ( !killer_name && kill_ob && function_exists( "QueryProp", kill_ob ) ){
+ dseq = (mixed) kill_ob->QueryProp(P_ENEMY_DEATH_SEQUENCE);
+
+ if( !(killer_name = (mixed) kill_ob->QueryProp(P_KILL_NAME)) ){
+ killer_name = (mixed) kill_ob->QueryProp(P_NAME);
+ kart = (int) kill_ob->QueryProp(P_ARTICLE);
+ kgen = (int) kill_ob->QueryProp(P_GENDER);
+ }
+
+ killer_msg = (mixed) kill_ob->QueryProp(P_KILL_MSG);
+ pre = kill_ob;
+ }
+
+ // falls keine Sequenz gesetzt, eventuelle eigene Todessequenz nehmen
+ if (!dseq)
+ dseq = (mixed)pl->QueryProp(P_NEXT_DEATH_SEQUENCE);
+
+ act_seq = 0;
+
+ if ( mappingp(dseq) )
+ act_seq = get_sequence( "/room/death/sequences/lars" );
+ else if ( pointerp(dseq) ) // ganze Todessequenz...
+ act_seq = ({ dseq, 0 });
+ else if ( stringp(dseq) )
+ act_seq = get_sequence(dseq);
+
+ if(pl->query_hc_play()>1)
+ {
+ act_seq=({({22,([1:"Du faellst und faellst...\n",
+ 5:"und faellst...\n",
+ 10:"und faellst...\n",
+ 12:"direkt in die Arme von TOD.\n",
+ 14:"Triumphierend laechelt er Dich an.\n",
+ 16:"NUN GEHOERST DU FUER IMMER MIR!\n",
+ 18:"HAHHHAHAHAAAAAAAAAAHAAAAAAAAA!\n",
+ 20:"TOD schlaegt Dir mit seiner Sense den Kopf ab.\n"])}),0});
+ }
+ if ( !act_seq )
+ act_seq = get_sequence();
+
+ if ( !mappingp(dseq) )
+ dseq = 0;
+
+ int i;
+ for ( i = sizeof(players); i--; )
+ if ( players[i][0] == pl )
+ break;
+
+ if ( i == -1 )
+ players += ({ ({ pl, 0, dseq, act_seq[0], act_seq[1], pre }) });
+ else
+ players[i][5] = pre;
+
+
+ if ( escaped ){
+ killer_name = "";
+ killer_msg = upperstring(getuid(pl)) + " VERSUCHTE, MIR ZU "
+ "ENTKOMMEN - JETZT HABE ICH WIEDER EXTRA-ARBEIT MIT "+
+ ((int) pl->QueryProp(P_GENDER) != 2 ? "IHM" : "IHR") +
+ " ...";
+ }
+ else if ( !killer_name ) {
+ if ( (string) pl->QueryProp(P_KILLER) == "gift" ){
+ killer_name = "Vergiftung";
+ kgen = FEMALE;
+ kart = 1;
+ }
+ else{
+ killer_name = "Etwas Geheimnisvolles und Unbekanntes";
+ kgen = NEUTER;
+ kart = 0;
+ }
+ }
+
+ if ( !pointerp(killer_msg) )
+ killer_msg = ({ killer_msg, 0, 0 });
+ else if ( sizeof(killer_msg) < 3 )
+ killer_msg += ({ 0, 0, 0 });
+
+ if ( stringp(killer_msg[0]) )
+ killer_msg[0] = sprintf( killer_msg[0], capitalize(getuid(pl)) );
+
+ SetProp( P_NAME, killer_name );
+ SetProp( P_ARTICLE, kart );
+ SetProp( P_GENDER, kgen );
+ string killname = Name(WER);
+ SetProp( P_NAME, "Lars" );
+ SetProp( P_ARTICLE, 0 );
+ SetProp( P_GENDER,MALE );
+
+ int magiertestie;
+ string testplayer = (string) pl->QueryProp(P_TESTPLAYER);
+ if (sizeof(testplayer))
+ {
+ if (testplayer[<5..<1]!="Gilde")
+ magiertestie = 1;
+ }
+
+ string kanal;
+ if (magiertestie || IS_LEARNING(pl))
+ kanal = "TdT";
+ else
+ kanal = "Tod";
+
+ CHMASTER->join( kanal, this_object() );
+
+ if ( (!stringp(killer_name) || killer_name != "") &&
+ (sizeof(killer_msg) < 4 || !killer_msg[3]) ){
+ if ( killer_msg[2] == PLURAL )
+ CHMASTER->send( kanal, this_object(),
+ killname + " haben gerade " +
+ capitalize(getuid(pl)) + " umgebracht." );
+ else
+ CHMASTER->send( kanal, this_object(),
+ killname + " hat gerade " +
+ capitalize(getuid(pl)) + " umgebracht." );
+ }
+
+ i = (int) pl->QueryProp(P_DEADS);
+ if ( i && (getuid(pl) == "key" || i%100 == 0 || i%250 == 0) ){
+ SetProp( P_NAME, "Tod" );
+ CHMASTER->send( kanal, this_object(),
+ sprintf( "DAS WAR SCHON DAS %dTE MAL!", i ) );
+ SetProp( P_NAME, "Lars" );
+ }
+
+ if( killer_msg[0] ){
+ if ( stringp(killer_name) && killer_name == "" ){
+ CHMASTER->send( kanal, this_object(),
+ break_string( funcall(killer_msg[0]), 78,
+ "["+kanal+":] " )[0..<2],
+ MSG_EMPTY );
+ return;
+ }
+ else {
+ if ( (killer_msg[1] < MSG_SAY) || (killer_msg[1] > MSG_GEMOTE) )
+ killer_msg[1] = MSG_SAY;
+
+ SetProp( P_NAME, killer_name );
+ SetProp( P_ARTICLE, kart );
+ SetProp( P_GENDER, kgen );
+ CHMASTER->send( kanal, this_object(), funcall(killer_msg[0]),
+ killer_msg[1] );
+ SetProp( P_NAME, "Lars" );
+ SetProp( P_ARTICLE, 0 );
+ SetProp( P_GENDER, MALE );
+ }
+ }
+
+ if ( pointerp(killer_msg = (mixed) pl->QueryProp(P_DEATH_MSG)) &&
+ sizeof(killer_msg) == 2 && stringp(killer_msg[0]) &&
+ intp(killer_msg[1]) ){
+ SetProp( P_NAME, capitalize(getuid(pl)) );
+ SetProp( P_ARTICLE, 0 );
+ SetProp( P_GENDER, pl->QueryProp(P_GENDER) );
+ CHMASTER->send( kanal, this_object(), killer_msg[0],
+ killer_msg[1] );
+ SetProp( P_NAME, "Lars" );
+ SetProp( P_ARTICLE, 0 );
+ SetProp( P_GENDER, MALE );
+ }
+
+ if (pl->query_hc_play()>1){
+ SetProp( P_NAME, "Tod" );
+ CHMASTER->send( kanal, this_object(),"NUN GEHOERST DU FUER EWIG MIR!" );
+ SetProp( P_NAME, "Lars" );
+ }
+}
+
+public int
+SmartLog( string creat, string myname, string str, string date )
+{
+ int i;
+ string fn;
+
+ for ( i = sizeof(players); i--; )
+ if ( players[i][0] == this_player() )
+ break;
+
+ // Spieler (Magier?) ist in keiner Todessequenz -> normales Repfile
+ if ( i == -1 )
+ return 0;
+
+ if ( !(fn = players[i][4]) ){
+ // Spieler hat eine unbekannte Todessequenz (kein Filename, Sequenz
+ // wurde komplett in P_ENEMY_DEATH_SEQUENCE abgelegt)
+ creat = "TOD/unbekannt.rep";
+ fn = "unbekannte Todessequenz";
+ }
+ else
+ // Jede Sequenz mit nem eigenen Repfile
+ creat = "TOD/" + explode( fn, "/" )[<1] + ".rep";
+
+ log_file( creat, myname + " von " + getuid(this_interactive())
+ + " ["+fn+"] (" + date + "):\n" + str + "\n" );
+
+ return 1;
+}
+
+public mixed hier_geblieben( mixed dest, int methods, string direction,
+ string textout, string textin )
+{
+ // Magier duerfen Spieler heraustransen
+ if ( this_interactive() && IS_LEARNER(this_interactive()) &&
+ (this_interactive() != previous_object() ||
+ IS_DEPUTY(this_interactive())) ){
+ previous_object()->Set( P_TMP_MOVE_HOOK, 0 );
+ return ({ dest, methods, direction, textout, textin });
+ }
+
+ // Spieler haengt noch in der Todessequenz
+ for ( int i = sizeof(players); i--; )
+ if ( objectp(players[i][0]) && previous_object() == players[i][0] &&
+ environment(previous_object()) == find_object(
+ "/room/death/virtual/room_death_" + getuid(previous_object()))&&
+ interactive(previous_object()) ) {
+ // Move nur erlaubt, wenn das Ziel wieder der Todesraum ist.
+ // wenn mal fuer nen bestimmten Zwecks Bewegungen raus aus dem
+ // Todesraum erforderlich sind, sollten hier entsprechende
+ // Ausnahmen eingebaut werden.
+ if ( (stringp(dest) &&
+ dest == object_name(environment(previous_object()))) ||
+ (objectp(dest) &&
+ dest == environment(previous_object())) ) {
+ previous_object()->Set( P_TMP_MOVE_HOOK, 0 );
+ return ({ dest, methods, direction, textout, textin });
+ }
+ else
+ return -1;
+ }
+
+ // Spieler ist nicht mehr im Raum oder eingeschlafen
+ if ( previous_object() )
+ previous_object()->Set( P_TMP_MOVE_HOOK, 0 );
+
+ return ({ dest, methods, direction, textout, textin });
+}
diff --git a/room/death/death_room_vc.c b/room/death/death_room_vc.c
new file mode 100644
index 0000000..71038fb
--- /dev/null
+++ b/room/death/death_room_vc.c
@@ -0,0 +1,168 @@
+// MorgenGrauen MUDlib
+//
+// death_room_vc.c -- Das Standardobjekt fuer den VC-Todesraum
+//
+// $Id: death_room_vc.c 8988 2014-12-31 13:10:19Z Zesstra $
+
+
+#pragma strict_types
+
+#include <defines.h>
+#include <properties.h>
+#include <moving.h>
+#include <language.h>
+#include <wizlevels.h>
+#include <daemon.h>
+#include <new_skills.h>
+
+inherit "/std/room";
+
+public int no_attack();
+public int no_poison(int val);
+
+public void create()
+{
+ if (IS_BLUE(this_object())) return;
+ ::create();
+
+ SetProp( P_GENDER, MALE );
+ SetProp( P_ARTICLE, 0 );
+ SetProp( P_LIGHT,1 );
+ SetProp( P_NO_TPORT, NO_TPORT_OUT );
+ SetProp( P_LOG_FILE, "TOD/Todesraum" );
+ SetProp( P_INT_SHORT, "Arbeitszimmer des Todes" );
+ SetProp( P_INT_LONG, break_string(
+ "Ein dunkler Raum, erleuchtet von dunklem Licht, das sich der "
+ "Dunkelheit nicht so sehr zu widersetzen scheint, indem es "
+ "leuchtet, als dass es der dunkelste Punkt in einer weniger "
+ "dunklen Umgebung ist. Im seltsamen Licht erkennst Du einen "+
+ "zentral aufgestellten Schreibtisch, der mit Diagrammen und "
+ "Buechern bedeckt ist. Die Waende verschwinden hinter Regalen, "
+ "die gefuellt sind mit in Leder gebundenen, dunklen Waelzern, "
+ "von denen geheimnisvolle Runen leuchten.\nTod.", 78, 0, 1 ) );
+ previous_object()->CustomizeObject();
+ call_other("/room/death/death_room","???");
+}
+
+void test_remove()
+{
+ if (!sizeof(all_inventory(this_object())&users()))
+ if (!this_object()->remove()) destruct(this_object());
+}
+
+public void reset()
+{
+ ::reset();
+ test_remove();
+ return;
+}
+
+public void exit(object liv)
+{
+ call_out("test_remove",2);
+ return;
+}
+
+
+static void deep_destruct( object ob )
+{
+ if ( objectp(ob) && environment(ob) == this_object() )
+ filter( deep_inventory(ob) + ({ ob }),
+ lambda( ({'x/*'*/}), ({#'destruct, 'x}) ) );
+}
+
+public void init()
+{
+ string prayroom;
+ int res;
+
+ ::init();
+ if ( !query_once_interactive(this_player()) ){
+ call_out( "deep_destruct", 0, this_player() );
+ return;
+ }
+
+ if ( !(prayroom = (string) this_player()->QueryPrayRoom()) )
+ prayroom = "/room/pray_room";
+
+ if ( !this_player()->QueryProp(P_GHOST) )
+ {
+ if ( IS_WIZARD(this_player()) &&
+ this_player()->QueryProp(P_WANTS_TO_LEARN) )
+ {
+ if ( !this_player()->QueryProp(P_INVIS) )
+ tell_room( this_object(),
+ "Der Tod sagt: WAS WILLST DU HIER, "+
+ upperstring((string) this_player()->name())+"?\n"+
+ "Der Tod sagt: DU BIST UNSTERBLICH, DU HAST HIER "
+ "NICHTS ZU SUCHEN!\n\n" );
+ }
+ else
+ {
+ write("Der Tod sagt: WAS TUST DU HIER? DEINE ZEIT IST NOCH "
+ "NICHT REIF!\n\n");
+
+ if ( catch(res = (int) this_player()->move( prayroom,M_GO|M_SILENT|M_NOCHECK ))
+ || res < 1 && environment(this_player()) == this_object() )
+ this_player()->move( "/room/pray_room", M_GO|M_SILENT|M_NOCHECK );
+ }
+ return;
+ }
+
+ if ( !IS_DEPUTY(this_player()) ){
+ add_action( "filter_ldfied", "", 1 );
+ this_player()->Set( P_TMP_MOVE_HOOK,
+ ({ time()+31536000,
+ find_object("/room/death/death_room"),
+ "hier_geblieben" }) );
+ }
+
+ this_player()->Set( P_NO_ATTACK, #'no_attack, F_QUERY_METHOD );
+ this_player()->Set( P_POISON, #'no_poison, F_SET_METHOD );
+
+ "/room/death/death_room"->add_player(this_player());
+}
+
+// public, da command_me() sonst buggt (Wurzels Speedy o.ae.)
+public int filter_ldfied( string str )
+{
+ // Description: Filter out relevant commands.
+ string verb;
+
+ verb=query_verb();
+
+ if ( (verb == "schlafe" || verb == "schlaf") && str == "ein" ){
+ write("DU KANNST DEM TOD NICHT ENTRINNEN!\n");
+ return 0;
+ }
+
+ if ( verb == "typo" || verb == "fehler" || verb == "bug" || verb == "idee" )
+ return 0;
+
+ write( "Dein Koerper gehorcht Dir nicht !\n" );
+ return 1;
+}
+
+public int no_attack()
+{
+ int i;
+
+ // Spieler haengt noch in der Todessequenz
+ if( present(previous_object()) )
+ return 1;
+ else
+ previous_object()->Set( P_NO_ATTACK, 0, F_QUERY_METHOD );
+
+ return 0;
+}
+
+public int no_poison(int val)
+{
+ if ( val != 0 )
+ {
+ catch( raise_error("Poisoning dead players is illegal. Calling object "
+ "was "+object_name(previous_object(1))+"\n");publish );
+ }
+ return 0;
+}
+
diff --git a/room/death/virtual/virtual_compiler.c b/room/death/virtual/virtual_compiler.c
new file mode 100644
index 0000000..90d886e
--- /dev/null
+++ b/room/death/virtual/virtual_compiler.c
@@ -0,0 +1,44 @@
+// MorgenGrauen MUDlib
+//
+// virtual_compiler.c -- Virtueller Compiler fuer die Todesraeume
+//
+// $Id.$
+
+
+#pragma strong_types
+
+inherit "/std/virtual/v_compiler";
+
+#include <defines.h>
+#include <v_compiler.h>
+
+int NoParaObjects() {return 1;}
+
+void create()
+{
+ if (IS_CLONE(this_object())) return;
+ ::create();
+ SetProp(P_STD_OBJECT, "/room/death/death_room_vc");
+ seteuid(getuid());
+ return;
+}
+
+string Validate(string file) {
+ string base, room, who;
+
+ file = ::Validate(file);
+ if(sscanf(file, "death_room_%s",who)!=1 ||
+ ((who[0..3]!="gast") &&
+ (!"/secure/master"->get_userinfo(who)))) return 0;
+ return file;
+}
+
+mixed CustomizeObject()
+{
+ string base,room,who,file,fun;
+
+ if(!(file = ::CustomizeObject()) ||
+ !Validate(file)) return 0;
+ return file;
+}
+
diff --git a/room/jail.c b/room/jail.c
new file mode 100644
index 0000000..1331223
--- /dev/null
+++ b/room/jail.c
@@ -0,0 +1,191 @@
+#pragma strong_types,rtt_checks
+
+inherit "/std/room";
+inherit "/std/hook_consumer";
+
+#define OFFICE "/d/wueste/catweazle/room/office"
+
+#include <properties.h>
+#include <wizlevels.h>
+#include <hook.h>
+
+protected void create()
+{
+ ::create();
+ SetProp(P_LIGHT, 1 );
+ SetProp(P_INT_SHORT,"Eine Gefaengniszelle");
+ SetProp(P_INT_LONG, break_string(
+ "Die Zelle ist absolut eintoenig und hat keine Fenster. Lange hier drin"
+ "zu sitzen ist bestimmt nicht angenehm. Wenn du hier heraus willst, "
+ "kannst Du wohl nur den Sheriff, seinen Stellvertreter oder einen "
+ "Erzmagier darum bitten.",78));
+ SetProp(P_INDOORS,1);
+}
+
+void init()
+{
+ ::init();
+ if (!query_once_interactive(this_player()))
+ return;
+ if ( IS_DEPUTY(this_player()) ) // EM+ sind sowieso Deputies
+ return;
+ add_action("bla","",1);
+ input_to("murks",0);
+
+ // Move-Hook anhaengen
+ int ret = this_player()->HRegisterToHook(H_HOOK_MOVE, this_object(),
+ H_HOOK_LIBPRIO(1),H_HOOK_SURVEYOR,
+ -1);
+ if ( ret <=0 )
+ raise_error("Fehler: Move-Hook konnte nicht registriert werden. "
+ "HRegisterToHook-Ergebnis: " + ret + "\n");
+}
+
+// Move-Hook austragen.
+void exit(object liv) {
+ if (objectp(liv) && !IS_DEPUTY(liv))
+ liv->HUnregisterFromHook(H_HOOK_MOVE,this_object());
+}
+
+int bla()
+{
+ string v;
+
+ v=query_verb();
+ input_to("murks",0);
+ // sagen und schlafen erlaubt.
+ if (stringp(v) && (v=="sag"||v=="sage"||v[0]=='\''
+ ||v=="schlafe"||v=="schlaf"))
+ return 0;
+ write("Nix da.\n");
+ return 1;
+}
+
+int murks(string str)
+{
+ if (!this_player() || environment(this_player())!=this_object())
+ return 0;
+
+ input_to("murks",0);
+
+ if (!str||str=="") return 1;
+ // Einschlafen erlaubt.
+ if (str == "schlafe ein") {
+ this_player()->command("schlafe ein");
+ return 1;
+ }
+ if (str[0]=='\'') str="sag "+str[1..];
+ if(str[0..3]=="sag "||str[0..4]=="sage ")
+ {
+ str=implode(old_explode(str," ")[1..]," ");
+ write(break_string(str, 78, "Du sagst: "));
+ tell_room(this_object(),break_string(str,78,
+ capitalize(this_player()->name())+" sagt: "),({this_player()}));
+ return 1;
+ }
+ write("Nix da.\n");
+ return 1;
+}
+
+public varargs int remove(int silent) {
+ // keine Zerstoerung, wenn Spieler drin sind.
+ if (sizeof(filter(all_inventory(),#'query_once_interactive)))
+ return 0;
+
+ return ::remove(1);
+}
+
+public string NotifyDestruct(object caller) {
+
+ if (previous_object() != master()
+ || caller == this_object())
+ return 0;
+
+ // wenn keiner hier ist, ists egal.
+ if (!sizeof(filter(all_inventory(),#'query_once_interactive)))
+ return 0;
+
+ // Direkter Destruct mit Anwesenden nur fuer EM+
+ if (!process_call() && this_interactive()
+ && IS_ARCH(this_interactive()))
+ return 0;
+
+ return "Direkte Zerstoerung des Jails nur fuer EM+ erlaubt.\n";
+}
+
+
+// keine anderen Move-Hooks erlaubt ausser diesem...
+status HookRegistrationCallback(object registringObject, int hookid, object
+ hookSource, int registringObjectsPriority, int registringObjectsType)
+{
+ if (hookid==H_HOOK_MOVE)
+ return 0;
+
+ return 1;
+}
+status HookCancelAllowanceCallback(object cancellingObject, int hookid, object
+ hookSource, int cancellingObjectsPriority, mixed hookData)
+{
+ if (hookid==H_HOOK_MOVE && cancellingObject != this_object()
+ && present(hookSource,this_object()))
+ return 0;
+
+ return 1;
+}
+
+status HookModificationAllowanceCallback(object modifyingObject, int hookid,
+ object hookSource, int modifyingObjectsPriority, mixed hookData)
+{
+ if (hookid==H_HOOK_MOVE && modifyingObject != this_object()
+ && present(hookSource,this_object()))
+ return 0;
+
+ return 1;
+}
+
+mixed HookCallback(object hookSource, int hookid, mixed hookData)
+{
+ // nur move hooks sind interessant hier.
+ if (hookid != H_HOOK_MOVE)
+ return ({H_NO_MOD, hookData});
+
+ // das duerfte eigentlich nicht vorkommen, da der Hook im exit() geloescht
+ // wird...
+ if (environment(hookSource) != this_object()) {
+ hookSource->HUnregisterFromHook(H_HOOK_MOVE,this_object());
+ return ({H_NO_MOD, hookData});
+ }
+
+ // Bewegungen in den Netztotenraum sind ok.
+ if (!interactive(hookSource)
+ && pointerp(hookData) && sizeof(hookData) >= 1)
+ {
+ if ((objectp(hookData[0])
+ && object_name(hookData[0]) == "/room/netztot")
+ || (stringp(hookData[0]) && hookData[0]=="/room/netztot")
+ )
+ {
+ return ({H_NO_MOD, hookData});
+ }
+ }
+
+ // Deputy (oder hoeher), kein process_call(). Sonst wird die Bewegung
+ // abgebrochen.
+ if (!this_interactive() || !IS_DEPUTY(this_interactive()))
+ {
+ return ({H_CANCELLED, hookData});
+ }
+
+ return ({H_NO_MOD, hookData});
+}
+
+// wenn hier jemand durch Zerstoerung des Objektes rauskommen will, geht das
+// schief.
+varargs void NotifyRemove(object ob) {
+ if (objectp(ob) && query_once_interactive(ob) && !IS_DEPUTY(ob))
+ {
+ ob->SetProp(P_START_HOME,"/room/jail");
+ ob->save_me(0);
+ }
+}
+
diff --git a/room/muellraum.c b/room/muellraum.c
new file mode 100644
index 0000000..21c4d22
--- /dev/null
+++ b/room/muellraum.c
@@ -0,0 +1,67 @@
+inherit "std/room";
+#include <properties.h>
+#include <wizlevels.h>
+
+void create()
+{
+ ::create();
+ SetProp(P_LIGHT, 1 );
+ SetProp(P_INT_SHORT, "Der Muellraum" );
+ SetProp(P_INDOORS, 1);
+ SetProp(P_NEVER_CLEAN, 1);
+ SetProp(P_INT_LONG,break_string(
+ "Dieser Raum ist vollkommen leer und anscheinend riiiiiiesig gross. "
+ "Du kannst seine Aussmasse nichtmals abschaetzen. Naja. Muss wohl auch "
+ "so sein, denn hier kommen alle Clones rein, die einige Sekunden "
+ "nach ihrer Erstellung noch kein Zuhause (Environment) gefunden haben. "
+ "Wenn Du das magische Kommando 'welt' gibst, wirst Du wieder in Deine Welt\n"
+ "zurueckversetzt werden."));
+ AddExit("welt", "/gilden/abenteurer");
+}
+
+// rekursiv zerstoeren
+private void rec_remove(object ob) {
+ object *inv=all_inventory(ob);
+ if (sizeof(inv)) {
+ filter(inv, #'rec_remove);
+ }
+ ob->remove(1);
+ if (objectp(ob)) destruct(ob);
+}
+
+int clean_me() {
+ object *inv=all_inventory(this_object());
+ int isize=sizeof(inv);
+ if (isize>100) {
+ //aeltestes Objekt, was kein Spieler ist, zerstoeren. Pruefung auf Spieler
+ //ist Paranoia, eigentlich sollte hier nie einer hinkommen koennen, ausser
+ //magier, und um die waers dann nicht schade. *g*
+ for (isize--; isize--; ) {
+ if (!query_once_interactive(inv[isize])) {
+ rec_remove(inv[isize]);
+ return(1);
+ }
+ }
+ }
+ return 0;
+}
+
+varargs int PreventInsert(object pl) {
+
+ if (!objectp(pl))
+ return 1;
+ clean_me();
+ return 0;
+}
+
+varargs int PreventInsertLiving(object pl) {
+
+ // keine Spieler. ;-)
+ if (!objectp(pl) ||
+ (query_once_interactive(pl) && !IS_LEARNER(pl)))
+ return 1;
+
+ clean_me();
+ return 0;
+}
+
diff --git a/room/netztot.c b/room/netztot.c
new file mode 100644
index 0000000..341c46b
--- /dev/null
+++ b/room/netztot.c
@@ -0,0 +1,92 @@
+// MorgenGrauen MUDlib
+//
+// $Id: netztot.c 8747 2014-04-26 13:08:47Z Zesstra $
+
+#include <wizlevels.h>
+#include <moving.h>
+
+create()
+{
+ call_out("invcheck",120);
+ "/obj/sperrer"->NixGibts();
+}
+
+weg(ob)
+{
+ if (!objectp(ob))
+ return;
+ ob->remove();
+ if (ob)
+ destruct(ob);
+}
+
+wegraeumen(ob)
+{
+ object *x;
+
+ if (!objectp(ob))
+ return;
+ for (x=deep_inventory(ob);sizeof(x);x=x[1..])
+ weg(x[0]);
+ ob->move("/room/void",M_NOCHECK|M_SILENT);
+ weg(ob);
+}
+
+invcheck()
+{
+ while(remove_call_out("invcheck")!=-1);
+ foreach(object ob: all_inventory(this_object()))
+ {
+ if (interactive(ob))
+ {
+ catch(this_player()->move("/room/void",M_GO));
+ set_object_heart_beat(ob,1);
+ }
+ else if (!query_once_interactive(ob) && object_name(ob)!="/obj/sperrer")
+ call_out("wegraeumen",1,ob);
+ }
+ call_out("invcheck",120);
+ "/obj/sperrer"->upd();
+}
+
+init()
+{
+ if (!this_player())
+ return;
+ catch(this_player()->StopHuntingMode());
+ if (interactive(this_player()))
+ catch(this_player()->move("/room/void",M_GO));
+ if (!query_once_interactive(this_player()))
+ {
+ this_player()->remove();
+ if(this_player())
+ destruct(this_player());
+ }
+ set_object_heart_beat(this_player(),0);
+}
+
+int_long()
+{
+ return "Dies ist der Netztotenraum. Es ist dunkel. Du siehst nichts.\n";
+}
+
+int_short()
+{
+ return "Nichts zu sehen.\n";
+}
+
+QueryProp(string str)
+{
+ switch (str) {
+ case "int_long": return int_long();
+ case "int_short": return int_short();
+ }
+}
+
+// Nicht jeder Magier darf den Netztotenraum entsorgen.
+string NotifyDestruct(object caller) {
+ if( (caller!=this_object() && !ARCH_SECURITY) || process_call() ) {
+ return "Du darfst den Netztotenraum nicht zerstoeren!\n";
+ }
+}
+
diff --git a/room/nirvana.c b/room/nirvana.c
new file mode 100644
index 0000000..ea66074
--- /dev/null
+++ b/room/nirvana.c
@@ -0,0 +1,132 @@
+#include <properties.h>
+#include <moving.h>
+
+inherit "std/room";
+
+create() {
+ ::create();
+ SetProp(P_INDOORS, 1);
+ SetProp(P_LIGHT,1);
+ SetProp(P_INT_LONG,
+"Du befindest Dich im Nirvana!\n"+
+"Es sieht anders aus als Du es Dir vorgestellt hast. Eine riesige Halle \n"+
+"mit Waenden aus Nebel, einem Boden aus Wasser und einer Decke aus Feuer\n"+
+"bildet das Heim der ewig Verstorbenen.\n"+
+"Stille herrscht hier. Grosse Stille. STILLE sozusagen.\n"+
+"Rauch durchzieht die Luft. Er entspringt einer Raeucherschale, welche auf\n"+
+"einem riesigen Altar mitten im Nirvana steht.\n"+
+"Du bist nun wohl wirklich tot.\n");
+ SetProp(P_INT_SHORT,"Im Nirvana");
+ SetProp(P_NO_TPORT,NO_TPORT);
+ SetProp(P_NO_PARA_TRANS);
+
+ AddDetail("altar",
+"Der Altar der verzweifelten Toten. Er besteht vollstaendig aus grinsenden "+
+"Totenschaedeln und bietet keinerlei Hoffnung.\nEine Raeucherschale steht auf dem Altar.\n");
+
+ AddDetail(({"tote","toten","verstorbene"}),
+"Dies hier ist das Heim der Toten.\nDu wohnst hier.\n");
+
+ AddDetail(({"hoffnung"}),
+"HAHA, KEINE HOFFNUNG!\n");
+
+ AddDetail(({"schaedel","totenschaedel"}),
+"Sie grinsen Dich haemisch an als wollten sie dich verspotten.\n"+
+"Auf einem Schadel erkennst Du eine Inschrift.\n");
+
+ AddDetail(({"inschrift"}),
+"Du kannst sie lesen.\n");
+
+ AddReadDetail(({"inschrift"}),
+"DIES IST KEIN APRILSCHERZ.\n");
+
+ AddDetail(({"schale","raeucherschale"}),
+"Aus der Schale entsteigt dunkler Rauch, der die Luft unheilvoll schwaengert.\n");
+
+
+ AddDetail(({"luft"}),
+"Luft war einmal lebensnotwendig. Du brauchst sie nicht mehr.\n");
+
+ AddDetail(({"rauch"}),
+"Der Rauch verdunkelt die Luft. Er wuerde jeden Lebenden ersticken, aber das schreckt Dich nicht mehr.\n");
+
+ AddDetail(({"stille"}),
+"Sie hoert sich irgendwie tot und endgueltig an.\n");
+
+ AddDetail(({"nirvana","raum"}),
+"Schau Dich nur um.\n");
+
+ AddDetail(({"lebende"}),
+"Zu denen gehoerst Du nicht mehr.\n");
+
+ AddDetail(({"nebel"}),
+"Der Nebel begrenzt das Nirvana seitlich. Er formt die Waende.\n");
+
+ AddDetail(({"wasser"}),
+"Der Boden des Nirvanas scheint aus Wasser zu bestehen. Du bist tot und gehst daher nicht unter.\n");
+
+ AddDetail(({"feuer"}),
+"Die Decke des Nirvanas lodert Dir feurig entgegen. Waerest Du am Leben, wuerde Dich das beunruhigen.\n");
+
+ AddDetail(({"halle"}),
+"Die Halle der Toten. Das Nirvana.\n");
+
+ AddDetail(({"heim"}),
+"Das Heim der Toten ist das Nirvana. Dein Heim.\n");
+
+
+ AddDetail(({"boden"}),
+"Der Boden wabert unter Dir. Manchmal meinst Du das Gesicht Jofs zu erkennen.\n");
+
+ AddDetail(({"gesicht"}),
+"Gesichter sind fuer Dich nicht mehr wichtig.\n");
+
+ AddDetail(({"jof"}),
+"Er schlaeft.\n");
+
+
+ AddDetail(({"decke"}),
+"Die Decke lodert Dir entgegen. Abundzu meinst Du Rumata zu erkennen.\n");
+
+ AddDetail(({"rumata"}),
+"Er ist wohl doch nicht da. Niemand wird Dir helfen. Es ist aus.\n");
+
+ AddDetail(({"wand","waende"}),
+"Der Nebel wabert auf und ab. Manchmal scheint es so, als wandere Zook durch den Nebel.\n");
+
+
+ AddDetail(({"zook"}),
+"Er grinst Dich an. Das ist wohl das Ende der Hoffnung.\nWeit hinter Zook erkennst Du eine weitere Gestalt.\n");
+
+ AddDetail(({"gestalt"}),
+"Es scheint sich um Boing zu handeln.\n");
+
+ AddDetail(({"boing"}),
+"Boing schaut Dich traurig an.\n");
+
+
+ AddDetail(({"ende"}),
+"Du hast Dein Ende erreicht. Du bist tot.\n");
+
+ AddDetail(({"leben"}),
+"Dein Leben ist zu Ende. Du bist tot.\n");
+
+ AddCmd("bete","bete");
+ AddItem("/obj/zeitungsautomat", REFRESH_REMOVE);
+}
+
+bete() {
+ write("Du haeltst eine kurze Andacht.\n");
+ if (this_player()->QueryProp(P_GHOST) && this_player()->query_hc_play()>1) {
+ write("Eine sehr starke Kraft saugt Dich auf und spuckt Dich wieder aus.\nEs scheint sich aber nichts veraendert zu haben.\n");
+ say(this_player()->name()+" erscheint nicht in koerperlicher Form.\n");
+ this_player()->SetProp(P_GHOST,0);
+ }
+ else
+ {
+ write("Fuer Dich ist dieser Altar nicht gedacht!\n");
+ }
+ return 1;
+}
+
+
diff --git a/room/noscript.c b/room/noscript.c
new file mode 100644
index 0000000..fcff28e
--- /dev/null
+++ b/room/noscript.c
@@ -0,0 +1,42 @@
+inherit "/std/room";
+#include <properties.h>
+#include <moving.h>
+
+static string x;
+static string *xx;
+
+void create() {
+ ::create();
+ x="----------";
+ xx=({
+ "/d/ebene/room/ak_str7",
+ "/d/ebene/room/dra_str3",
+ "/d/ebene/room/hp_str2c",
+ "/d/ebene/room/o_wa1d",
+ "/d/ebene/room/waldweg8"
+ });
+ SetProp(P_LIGHT,1);
+ SetProp(P_INT_LONG,
+"Dieser Raum ist fuer Leute, die TF spielen lassen.\n\
+Es gibt nur einen Weg heraus...\n");
+ AddCmd("","raus",1);
+}
+
+void init() {
+ int i;
+
+ ::init();
+ for (i=0;i<10;i++)
+ x[i]='a'+random(26);
+}
+
+varargs string GetExits(object viewer) {
+ return sprintf("Es gibt einen sichtbaren Ausgang: %s.\n",x);
+}
+
+varargs int raus(string s) {
+ if (query_verb()!=x)
+ return 0;
+ notify_fail("Etwas hat nicht funktioniert. Bitte verstaendige einen Magier.\n");
+ return ((this_player()->move(xx[random(sizeof(xx))],M_GO))>0);
+}
diff --git a/room/nowhere.c b/room/nowhere.c
new file mode 100644
index 0000000..af55f2b
--- /dev/null
+++ b/room/nowhere.c
@@ -0,0 +1,28 @@
+inherit "std/room";
+#include <properties.h>
+#include <moving.h>
+#include <wizlevels.h>
+
+void create()
+{
+ ::create();
+ SetProp(P_LIGHT, 1 );
+ SetProp(P_INT_SHORT, "Bei den inaktiven Spielern :)" );
+ SetProp(P_INT_LONG,
+ "Hier ist absolut nichts zu sehen, die, die sich hier normalerweise\n"
+ +"aufhalten, sind eh noninteractive...\n");
+ AddCmd( "", "onlywelt", 1 );
+}
+
+int onlywelt( string s ) {
+ if( query_verb()=="welt" ) {
+ this_player()->move("/gilden/abenteurer", M_TPORT);
+ return 1;
+ }
+ if( IS_LEARNER(this_player()) ) return 0;
+ write(
+ "Wenn Du das magische Kommando 'welt' gibst, wirst Du wieder in Deine Welt\n"
+ +"zurueckversetzt werden.\n"
+ );
+ return 1;
+}
diff --git a/room/orakel.c b/room/orakel.c
new file mode 100644
index 0000000..4da1508
--- /dev/null
+++ b/room/orakel.c
@@ -0,0 +1,231 @@
+// MorgenGrauen MUDlib
+//
+// orakel.c -- Der Raum, in dem man sich neue ZT-Sprueche holen kann
+//
+// $Id: orakel.c 9371 2015-10-22 19:01:48Z Zesstra $
+
+#define TIPS(x) "/secure/ARCH/ZT/"+x
+
+#define POTIONMASTER "/secure/potionmaster"
+
+inherit "/std/room";
+
+#include <properties.h>
+
+// WANNWIEVIEL zeigt an, mit wieviel Stufenpunkten man wieviele Zaubertraenke
+// haben kann, so ist zum Beispiel an fuenfter Stelle die Zahl 25 einge-
+// tragen, also kann man mit 25 Stufenpunkten 5 Zaubertraenke bekommen.
+#define WANNWIEVIEL ({ 0, 0, 0, 0,\
+ 25, 50, 75, 100, 125, 150, 175, 200, 225, 250, 275, 300, 325, 350, 375,\
+ 400, 425, 450, 475, 500, 525, 550, 575, 600, 625, 650, 675, 700, 725,\
+ 750,\
+ 790, 830, 870, 910, 950, 990, 1030, 1070, 1110, 1150, 1190, 1230, 1270,\
+ 1310, 1350, 1390, 1430, 1470, 1510, 1550, 1590, 1630, 1670, 1710, 1750,\
+ 1790,\
+ 1860, 1930, 2000, 2070, 2140, 2210, 2280, 2350, 2420, 2490,\
+ 2590, 2690, 2790, 2890, 2990, 3090, 3190, 3290, 3390, 3490 })
+#define KEINTIPTEXT "Der Nebel ueber der Kugel ruehrt sich nicht.\n"
+
+
+
+protected void create()
+{
+ ::create();
+ SetProp(P_INDOORS, 1);
+ SetProp(P_LIGHT, 1);
+ SetProp(P_INT_SHORT, "Das heilige Orakel von Tingan");
+ SetProp(P_INT_LONG,
+ "Du befindest Dich in einer mittelgrossen Hoehle, die sich halbkugel-\n"+
+ "foermig ueber Deinem Kopf erhebt. Die Hoehle wird fast komplett vom\n"+
+ "gruenlich schimmernden Quellsee des Osterbachs ausgefuellt. Ueber dem\n"+
+ "See schwebt eingehuellt in langsam ziehende Nebelschwaden eine magisch\n"+
+ "leuchtende Kugel, das heilige Orakel von Tingan. Im Osten fliesst das\n"+
+ "Wasser des Sees durch einen schmalen Gang ab, dem Du folgen koenntest.\n");
+ AddDetail("boden", "Der Boden ist groesstenteils mit Wasser bedeckt.\n");
+ AddDetail("decke", "Die Decke ist aus massivem Felsgestein, Du willst gar nicht wissen,\nwieviele Tonnen davon ueber Deinem Kopf lasten.\n");
+ AddDetail(({"fels", "gestein", "felsgestein"}), "Sowas ist im Gebirge recht haeufig.\n");
+ AddDetail(({"wand", "waende"}), "Die Waende sind feucht.\n");
+ AddDetail(({"quellsee", "see"}), "Er ist die Quelle des Osterbachs.\n");
+ AddDetail("quelle", "Das heisst, der Bach entspringt hier.\n");
+ AddDetail(({"bach", "osterbach"}), "Er fliesst nach Osten ab.\n");
+ AddDetail("wasser", "Es ist klar und frisch.\n");
+ AddDetail("gang", "Er fuehrt nach Osten.\n");
+ AddDetail("orakel", "Du fuehlst grosses Wissen in Deiner Umgebung.\n");
+ AddDetail("umgebung", "Die Umgebung ist das, was Dich umgibt.\n");
+ AddDetail("wissen", "Vielleicht nuetzt es Dir ja was.\n");
+ AddDetail(({"nebel", "schwaden", "nebelschwaden"}), "Sie ziehen langsam ueber den See.\n");
+ AddDetail("kugel", "Die Kugel leuchtet in magischem Licht und laedt Dich fast zum Meditieren ein.\n");
+ AddDetail("licht", "Magisches Licht erhellt den Raum.\n");
+ AddDetail("raum", "Schau Dich einfach mal um.\n");
+ AddDetail("hoehle", "Du befindest Dich tatsaechlich in einer Hoehle.\n");
+ AddDetail("kopf", "Das anzuschauen duerfte Dir schwer fallen.\n");
+ AddCmd(({"trink", "trinke"}), "trinken");
+ AddCmd("meditiere", "meditieren");
+ AddCmd(({"wirf", "werfe"}), "werfen");
+ AddExit("osten", "/players/boing/orakel/organg2");
+}
+
+// Es wird berechnet ob der Spieler einen neuen Tip bekommen kann.
+int NeuerTip()
+{
+ mapping platt; // Attributmapping des Spielers
+ int summe; // Summe der Attribute des Spielers + der noch zu findenen
+ // aber bekannten Zaubertrankstellen
+ int sps; // Stufenpunkte des Spielers
+
+ platt = this_player()->QueryProp(P_ATTRIBUTES);
+ summe = (int)platt["int"] + (int)platt["con"] +
+ (int)platt["dex"] + (int)platt["str"] - 4;
+ summe += sizeof(this_player()->QueryProp(P_KNOWN_POTIONROOMS));
+ sps = this_player()->QueryProp(P_LEP);
+
+// Wenn genug Stufenpunkte da sind, dann wird 1 zurueckgegeben, sonst 0
+ if (summe>79)
+ return 0;
+ if (sps > WANNWIEVIEL[summe])
+ return 1;
+ return 0;
+}
+
+// Gibt die Nummer des ausgewaehlten Zaubertranks zurueck oder 0, wenn keiner
+// mehr uebrig ist.
+int ZTAuswahl()
+{
+ int* pllist;
+ int pllsize;
+ int i;
+ mixed sorted_list; // ({ ({liste1}), ({liste2}), ..., ({liste8}) })
+
+// Initialisierung
+ sorted_list = ({ ({ }), ({ }), ({ }), ({ }), ({ }), ({ }), ({ }), ({ }) });
+ pllist = this_player()->QueryProp(P_POTIONROOMS);
+ pllsize = sizeof(pllist);
+
+// Zaubertraenke werden gemaess ihrer Liste in den neuen Array eingetragen.
+ for (i=0; i<pllsize; i++)
+ sorted_list[POTIONMASTER->GetListByNumber(pllist[i])] += ({ pllist[i] });
+
+// Alle Unterarrays werden aneinandergehaengt.
+ pllist = ({ });
+ for (i=0; i<8; i++)
+ pllist += sorted_list[i];
+ pllist -= this_player()->QueryProp(P_KNOWN_POTIONROOMS);
+
+// Jetzt sind alle Zaubertraenke wieder in der Liste, sortiert nach dem
+// Schwierigkeitsgrad, bis auf die Zaubertraenke, die der Spieler bereits
+// kennt (d.h. wo er schon den Tip bekommen hat, sie aber noch nicht
+// gefunden hat).
+
+
+// Einer der leichtesten Zaubertraenke wird ausgewaehlt und zurueckgegeben.
+ pllsize = sizeof(pllist);
+ if (!pllsize)
+ return -1;
+ if (pllsize>10)
+ return pllist[random(10)];
+ else
+ return pllist[random(pllsize)];
+}
+
+
+string Vision()
+{
+ int nr;
+ string* text;
+ int* liste;
+
+ if (!NeuerTip())
+ return KEINTIPTEXT + "Du hast wahrscheinlich zu wenig Stufenpunkte.\n";
+
+ nr = ZTAuswahl();
+ if (nr == -1)
+ return KEINTIPTEXT + "Du hast schon alle Zaubertraenke gefunden.\n";
+
+ text = POTIONMASTER->TipLesen(nr);
+// Das Folgende kann passieren, wenn entweder die Datei zu einem ZT nicht
+// existiert oder das Einlesen sonstwie fehlschlaegt. Zur Behebung des
+// Fehlers sollte man sich als erstes die Datei <nr>.zt anschauen.
+ if (intp(text) || !sizeof(text))
+ return
+ "Ploetzlich wird es totenstill im Raum, die Nebelschwaden beginnen sich\n"+
+ "um die Kugel zu drehen. Immer schneller wird der wirbelnde Tanz, bis\n"+
+ "sich das Ganze unmerklich zu einer Schrift formt:\n"+
+ " Fehler im Raum-Zeit-Gefuege, bitte wende Dich an Rikus\n"+
+ " und melde ihm die Zahl '"+nr+"'!\n"+
+ "Dann zerfliesst der Nebel und alles ist beim Alten.\n";
+
+ liste = this_player()->QueryProp(P_KNOWN_POTIONROOMS);
+ this_player()->AddKnownPotion(nr);
+
+//bis nach Reboot noetig!!! Rikus
+// "/players/boing/orakel/orakel"->AddKnownPotion(nr);
+
+ return "Der Nebel ueber der Kugel beginnt sich zu bewegen, dann hoerst Du eine\ntiefe Stimme in Deinem Kopf erklingen:\n\n"+text[random(sizeof(text))];
+}
+
+string TipListe()
+{
+ int* pll;
+ string* tip;
+ string ret;
+ int plsize, i;
+
+ ret = "";
+ pll = this_interactive()->QueryProp(P_KNOWN_POTIONROOMS);
+ plsize = sizeof(pll);
+
+ for (i=0; i<plsize; i++)
+ {
+ tip = POTIONMASTER->TipLesen(pll[i]);
+ if (sizeof(tip))
+ {
+ ret += tip[random(sizeof(tip))];
+ ret += "--------------------------------------------------------------------------\n";
+ }
+ }
+
+ if (ret=="")
+ return "Du kennst momentan keine Tips zu Zaubertraenken.\n";
+ else
+ return "--------------------------------------------------------------------------\n"+ret;
+}
+
+int trinken(string str)
+{
+ notify_fail("Was moechtest Du trinken?\n");
+ if (!str || str=="") return 0;
+ notify_fail("Das kannst Du hier nicht trinken!\n");
+ if (str!="wasser")
+ return 0;
+ write("Du trinkst einen Schluck Quellwasser und fuehlst Dich koestlich erfrischt.\n");
+ return 1;
+}
+
+meditieren()
+{
+ write(
+ "Du sammelst Deine geistigen Kraefte und verfaellst schon schnell in einen\n"+
+ "tranceartigen Zustand. Eine Vision eines Helden, der eine Muenze in den\n"+
+ "See wirft erscheint vor Deinen Augen, verschwindet aber schon schnell\n"+
+ "wieder. Als Du wieder aufwachst, ist alles wie vorher.\n");
+ return 1;
+}
+
+int werfen(string str)
+{
+ if (str=="muenze in see" || str=="muenze in wasser" ||
+ str=="muenze in quellsee")
+ {
+ if (this_player()->QueryMoney()<1)
+ {
+ write("Du hast keine Muenze.\n");
+ return 1;
+ }
+ this_player()->AddMoney(-1);
+ write("Du wirfst eine Muenze ins Wasser.\n");
+ say(capitalize(this_player()->name())+" wirft eine Muenze ins Wasser.\n");
+ write(Vision());
+ return 1;
+ }
+ return 0;
+}
diff --git a/room/post.c b/room/post.c
new file mode 100644
index 0000000..34117de
--- /dev/null
+++ b/room/post.c
@@ -0,0 +1,12 @@
+inherit "/std/post";
+#include <properties.h>
+
+create()
+{
+ ::create();
+ AddExit("osten","/gilden/abenteurer");
+ SetProp(P_INT_LONG,"Dies ist das Hauptpostamt von MorgenGrauen.\n"+
+ "Von hier aus kannst Du Briefe an Deine Mitspieler schicken und Briefe von\n"+
+ "ihnen lesen. Wenn Du das willst, tippe \"post\".\n"+
+ "Der einzige sichtbare Ausgang fuehrt nach Osten in die Gilde.\n");
+}
diff --git a/room/pray_room.c b/room/pray_room.c
new file mode 100644
index 0000000..c056d22
--- /dev/null
+++ b/room/pray_room.c
@@ -0,0 +1,37 @@
+inherit "std/room";
+
+#include <properties.h>
+
+void create()
+{
+ ::create();
+ SetProp(P_LIGHT,1);
+ SetProp(P_INT_LONG,
+ "Du befindest Dich in einer kleinen Kapelle, in der Du beten kannst, um\n"+
+ "wieder Deine natuerliche Gestalt zu erhalten. Am suedlichen Ende steht\n"+
+ "ein Altar, auf dem sich ein grosses Kreuz befindet. In den Waenden siehst\n"+
+ "Du herrliche Fenster, durch die tagsueber das Licht bunt hereinscheint.\n"+
+ "Im Norden befindet sich eine Tuer, die zur Gilde fuehrt.\n");
+ SetProp(P_INT_SHORT,"Kapelle");
+ AddDetail("altar", "Er ist aus Stein und nicht besonders schoen.\n");
+ AddDetail("kreuz", "Ein schlichtes Holzkreuz.\n");
+ AddDetail("fenster", "Die Fenster sind wunderschoen.\n");
+ AddDetail(({"wand", "waende"}), "An den Waenden siehst Du nichts besonderes.\n");
+ AddCmd("bete","bete");
+ AddExit("norden","/gilden/abenteurer");
+}
+
+static int bete() {
+ if (this_player()->QueryProp(P_GHOST))
+ {
+ write("Du haeltst eine kurze Andacht.\n");
+ write("Eine sehr starke Kraft saugt Dich auf und spuckt Dich wieder aus.\n");
+ say(this_player()->name()+" erscheint in koerperlicher Form.\n");
+ this_player()->SetProp(P_GHOST,0);
+ return 1;
+ }
+ notify_fail("Du haeltst eine kurze Andacht.\n");
+ return 0;
+}
+
+
diff --git a/room/pub2.c b/room/pub2.c
new file mode 100644
index 0000000..bf51144
--- /dev/null
+++ b/room/pub2.c
@@ -0,0 +1,44 @@
+inherit "/std/pub";
+#include <rooms.h>
+#include <properties.h>
+
+create(){
+ replace_program("std/pub.c");
+ ::create();
+
+ AddDrink("Bier nach dem Reinheitsgebot","bier",12,0,2,1,
+ ({"Der Kellner bringt Dein Bier. Du fuehlst Dich gut.",
+ "&& trinkt ein eiskaltes Bier."}));
+
+ AddDrink("Franks Spezial-Schnaps",
+ ({"schnaps","spezial","spezial-schnaps"}),
+ 50,10,8,0,
+ ({"Der Kellner bringt Deinen Schnaps.\n"+
+ "Du fuehlst ein Kribbeln im ganzen Koerper.",
+ "&& schuettet einen Spezial-Schnaps herunter."}));
+
+ AddDrink("Ein beruehmter Rachenputzer",({"putzer","rachenputzer"}),
+ 150,25,12,0,
+ ({"Du bekommst Deinen weltberuehmten Rachenputzer.\n"+
+ "Eine Schockwelle rast mit der Gewalt eines Baseball-Schlaegers durch\n"+
+ "Deinen Koerper und trifft mit voller Wucht Dein Gehirn.",
+ "&& torkelt, als &! einen Rachenputzer saeuft."}));
+
+ AddDrink("Eine Tasse Kaffee",({"kaffee","tasse","tasse kaffee"}),
+ 20,0,-2,3,
+ ({"Baeh! Schmeckt ja widerlich!",
+ "&& verzieht angewidert das Gesicht, als &! einen Kaffee schluckt."}));
+
+ AddExit("westen","room/gilde");
+
+ SetProp(P_INT_SHORT,"Franks Abenteurer-Kneipe");
+ SetProp(P_INT_LONG,"Du bist in Franks Abenteurer-Kneipe.\n"+
+ "Wie immer ist hier mal wieder die Hoelle los. Flaschen und Glaeser\n"+
+ "fliegen durch den Raum, und du musst aufpassen, dass Du nicht in\n"+
+ "die Schlaegerei zwischen einem Kerl, der aussieht wie Sylvester\n"+
+ "Stallone und einem auch nicht gerade harmlosen Zauberer hinein-\n"+
+ "gezogen wirst.\n\n"+
+ "Wenn Du wissen willst, was Du hier trinken kannst, tippe: 'menue'.\n");
+ SetProp(P_LIGHT,1);
+}
+
diff --git a/room/treff.c b/room/treff.c
new file mode 100644
index 0000000..17d0be8
--- /dev/null
+++ b/room/treff.c
@@ -0,0 +1,40 @@
+#include <properties.h>
+#include <rooms.h>
+#include <wizlevels.h>
+#include <language.h>
+inherit "/std/room";
+create(){
+ ::create();
+ SetProp(P_INT_SHORT,"Das juengste Geruecht");
+ SetProp(P_INT_LONG,
+ "Dies ist ein Raum, den die Spieler gerne und oft als \n"
+ +"'das juengste Geruecht' bezeichnen. Hier werden naem-\n"
+ +"lich wichtige Entscheidungen im Morgengrauen disku-\n"
+ +"tiert und beschlossen. Demzufolge ist dies ein reiner\n"
+ +"Magierraum. Man kann sich hier treffen, reden oder\n"
+ +"einfach herumidlen.\n");
+ AddExit("unten", "/gilden/abenteurer");
+ SetProp(P_LIGHT,100);
+ SetProp(P_INDOORS,1);
+}
+
+exit() // War schon oefter so, das Magier hier walking monsters erzeugt
+ // haben, die dann in die Gilde gehopst sind ... die exits
+ // zu sperren hat auch keinen Sinn - Sirs MNPC moved sich dann
+ // doch an seinen Startpunkt. Naja, machen wir es eben SO - Monster
+ // haben hier eh nix verloren.
+{
+ object tp;
+
+ tp=previous_object();
+ if (!query_once_interactive(tp))
+ call_out("do_destruct",1,tp);
+}
+
+do_destruct(ob)
+{
+ if (ob)
+ ob->remove();
+ if (ob)
+ destruct(ob);
+}
diff --git a/room/void.c b/room/void.c
new file mode 100644
index 0000000..061e62a
--- /dev/null
+++ b/room/void.c
@@ -0,0 +1,51 @@
+inherit "std/room";
+#include <properties.h>
+#include <moving.h>
+#include <wizlevels.h>
+
+void create()
+{
+ ::create();
+ SetProp(P_LIGHT, 1 );
+ SetProp(P_INT_SHORT, "Das Nichts" );
+ SetProp(P_INDOORS, 1);
+ SetProp(P_INT_LONG,
+ "Du schwebst im absoluten, ewigen und leeren Nichts umher. Hier kommen\n"
+ +"all die hin, deren Welt, in der sie sich befanden, zerstoert worden ist.\n"
+ +"Wenn Du das magische Kommando 'welt' gibst, wirst Du wieder in Deine Welt\n"
+ +"zurueckversetzt werden.\n"
+ );
+ AddCmd( "", "onlywelt", 1 );
+}
+
+int onlywelt( string s ) {
+ if( query_verb()=="welt" ) {
+ this_player()->move("/gilden/abenteurer", M_TPORT);
+ return 1;
+ }
+ if( IS_LEARNER(this_player()) ) return 0;
+ write(
+ "Du schwebst im absoluten, ewigen und leerem Nichts umher. Hier kommen\n"
+ +"all die hin, deren Welt, in der sie sich befanden, zerstoert worden ist.\n"
+ +"Wenn Du das magische Kommando 'welt' gibst, wirst Du wieder in Deine Welt\n"
+ +"zurueckversetzt werden.\n"
+ );
+ return 1;
+}
+
+
+// Sonst zerstoert sich das Void brav selbst - an NotifyDestruct vorbei.
+public varargs int remove()
+{
+ if (!ARCH_SECURITY || process_call())
+ return 0;
+ return ::remove();
+}
+
+// Nicht jeder Magier muss das Void entsorgen koennen.
+string NotifyDestruct(object caller) {
+ if( (caller!=this_object() && !ARCH_SECURITY) || process_call() ) {
+ return "Du darfst das Void nicht zerstoeren!\n";
+ }
+}
+
diff --git a/room/welcome/std.c b/room/welcome/std.c
new file mode 100644
index 0000000..eae3cee
--- /dev/null
+++ b/room/welcome/std.c
@@ -0,0 +1,151 @@
+#include <properties.h>
+#include <moving.h>
+#include <defines.h>
+
+inherit "/std/room";
+
+#pragma strong_types
+#pragma rtt_checks
+#pragma no_shadow
+#pragma no_inherit
+#pragma pedantic
+#pragma range_check
+
+#define BS(x) break_string(x, 78, 0, BS_LEAVE_MY_LFS|BS_SINGLE_SPACE)
+#define TUTSTART "/d/anfaenger/arathorn/minitut/room/huette_"
+
+void create() {
+ ::create();
+
+ SetProp(P_LIGHT,1);
+ SetProp(P_LIGHT_TYPE, LT_STARS|LT_MOON);
+ SetProp(P_MAP_RESTRICTIONS, MR_NOUID|MR_NOINFO);
+ SetProp(P_INDOORS,0);
+ SetProp(P_NO_TPORT, NO_TPORT);
+
+ SetProp(P_INT_SHORT, "Irgendwo im Nirgendwo");
+ SetProp(P_INT_LONG, BS(
+ "Du schwebst im Nirgendwo. Sterne umgeben Dich, und Du glaubst "
+ "zu fallen, obwohl Du Dich vollkommen schwerelos fuehlst. Ein hauch"
+ "duenner Schleier aus Staub umfaengt Dich, als Du langsam aber sicher "
+ "Deines Koerpers gewahr wirst."));
+ AddSpecialExit("welt", function int () {
+ if ( PL->QueryGuest() )
+ return PL->move("/gilden/abenteurer", M_GO);
+ else return 0;
+ });
+ Set(P_HIDE_EXITS, function mixed () {
+ return !(PL && PL->QueryGuest());
+ }, F_QUERY_METHOD);
+}
+
+void init() {
+ set_next_reset(300);
+ if ( objectp(PL) )
+ call_out("Sequenz", 0, 0);
+ return ::init();
+}
+
+// Nix resetten, aber Raum entsorgen, wenn kein Spieler drin.
+// Notfalls gibt es auch noch nen cleanup() aus dem Standardraum...
+protected void reset() {
+ if (!sizeof(filter(all_inventory(this_object()), #'query_once_interactive))
+ )
+ remove(1);
+}
+
+//TODO: Delays anpassen bzw. ausklammern, wenn immer =5 ausser am Ende.
+void Sequenz(int count) {
+ int delay;
+
+ if ( !objectp(PL) || environment(PL) != ME )
+ return;
+
+ switch(count) {
+ case 0:
+ tell_object(PL, BS(QueryProp(P_INT_LONG)));
+ delay = 4;
+ break;
+ case 1:
+ tell_object(PL, BS(
+ "\nDu schaust Dich erstaunt um. Du befindest Dich anscheinend im "
+ "Weltall, aber wie bist Du hierhergekommen? Ist das schon das "
+ "MorgenGrauen, oder bist Du wohl erst noch auf dem Weg dorthin?"));
+ delay = 8;
+ break;
+ case 2:
+ tell_object(PL, BS(
+ "\nMit einem Blick auf Deine Umgebung bemerkst Du, dass der Staub, "
+ "der Dich umgibt, sich langsam auf Dich zuzubewegen scheint. "
+ "Du willst neugierig danach greifen, aber es will Dir nicht "
+ "gelingen. Verwundert stellst Du fest, dass Du keine Haende "
+ "besitzt, und bei naeherer Betrachtung wird Dir klar, dass Du "
+ "auch sonst noch ziemlich koerperlos bist! "));
+ delay = 12;
+ break;
+ case 3:
+ tell_object(PL, BS(
+ "\nDas aendert sich aber bald, als der glitzernde Staub allmaehlich "
+ "um Dich herum eine durchscheinende Gestalt zu bilden beginnt, "
+ "die sich zuegig verdichtet."));
+ delay = 8;
+ break;
+ case 4:
+ int g = PL->QueryProp(P_GENDER);
+ string desc = PL->QueryProp(P_RACESTRING)[0];
+ string msg = (g==MALE?"ein richtiger ":"eine richtige ")+desc;
+ tell_object(PL, BS(
+ "\nSchon kurz darauf hat sich ein eleganter Koerper geformt, der "
+ "nun vollkommen Dir gehoert. Dass Du noch nackt bist, stoert Dich "
+ "nicht im geringsten, denn endlich, endlich fuehlst Du Dich "
+ "wie "+msg+"!"));
+ delay = 10;
+ break;
+ case 5:
+ tell_object(PL, BS(
+ "\nDeine Begeisterung ueber Deinen makellosen Koerper wird jaeh "
+ "unterbrochen, als ploetzlich die Sterne verblassen und sich mit "
+ "unfassbarem Tempo von Dir zu entfernen scheinen. Dann wird es "
+ "kurz schwarz um Dich herum und kurz darauf wieder hell."));
+ delay = 8;
+ break;
+ case 6:
+ tell_object(PL, "\n"+break_string(
+ "Herzlich Willkommen! Uebrigens, wenn Du auf der "
+ "Ebene Anfaenger mit anderen reden willst, folgender Tip: Probiere "
+ "mal '-anf Hallo Morgengrauen' (natuerlich ohne die ' mit "
+ "einzugeben) aus.", 78, "Merlin teilt Dir mit: "));
+ delay = 6;
+ break;
+ case 7:
+ if (PL->QueryGuest() ) {
+ PL->move("/gilden/abenteurer", M_GO);
+ return;
+ }
+ else
+ tell_object(PL, "\n"+break_string(
+ "Ich werde Dich jetzt in das Tutorial fuer Anfaenger bewegen, wo "
+ "Du Deine ersten Schritte machen kannst...",
+ 78, "Merlin teilt Dir mit: ")+"\n");
+ delay = 4;
+ break;
+ case 8:
+ PL->move(TUTSTART+getuid(PL), M_GO);
+ return; // call_out nicht wieder anwerfen.
+ }
+ ++count;
+ call_out("Sequenz", delay, count);
+}
+
+// Bei Disconnect Sequenz abbrechen, bei Re-Login wieder starten mit
+// count == 5 d.h. Spieler fliegt also quasi "im Schlaf" weiter...
+void BecomesNetDead(object pl) {
+ while(remove_call_out("Sequenz")!=-1)
+ ;
+}
+
+void BecomesNetAlive(object pl) {
+ if (interactive(pl))
+ call_out("Sequenz", 6, 5);
+}
+
diff --git a/room/welcome/virtual_compiler.c b/room/welcome/virtual_compiler.c
new file mode 100644
index 0000000..a3eea2c
--- /dev/null
+++ b/room/welcome/virtual_compiler.c
@@ -0,0 +1,27 @@
+#include <defines.h>
+#include <v_compiler.h>
+inherit "/std/virtual/v_compiler";
+
+void create() {
+ ::create();
+ SetProp(P_STD_OBJECT, "/room/welcome/std");
+}
+
+string Validate(string file) {
+
+ file=::Validate(file);
+
+ // keine Unterverzeichnisse, gueltige Charnamen
+ if (strstr(file,"/") == -1
+ && sizeof(file) <= 11 // charnamen <=11 zeichen
+ && (regmatch(file,"[a-zA-Z]+") == file // nur A-Z,a-z
+ || strstr(file,"gast") == 0 // oder Gaeste
+ )
+ )
+ {
+ // Eigentlich P_COMPILER_PATH, aber hier geht jetzt auch __DIR__
+ return __DIR__ + file;
+ }
+ return 0;
+}
+