Added public files
Roughly added all public files. Probably missed some, though.
diff --git a/std/shells/baum.c b/std/shells/baum.c
new file mode 100644
index 0000000..522f3fe
--- /dev/null
+++ b/std/shells/baum.c
@@ -0,0 +1,113 @@
+// Autor: Rumata@gmx.de
+// ... sozusagen meine private rasse ...
+//
+// MorgenGrauen MUDlib
+//
+// shells/magier.c -- magier shell
+//
+// $Id: baum.c 8675 2014-02-18 20:39:54Z Zesstra $
+
+#pragma strong_types,save_types
+
+inherit "/std/shells/magier";
+
+//#define NEED_PROTOTYPES
+
+#include <thing/properties.h>
+#include <properties.h>
+#include <wizlevels.h>
+#include <language.h>
+#include <moving.h>
+#include <attributes.h>
+#include <combat.h>
+#include <defines.h>
+#include <ansi.h>
+#include <udp.h>
+#include <new_skills.h>
+
+static int _wurzel;
+
+void create()
+{
+ if (!clonep() || object_name(this_object()) == __FILE__[0..<3]) {
+ set_next_reset(-1);
+ return;
+ }
+
+ ::create();
+ _wurzel = -1;
+}
+
+static int wurzel_an( string arg ) {
+ string num;
+ int count;
+
+ if( this_object() != this_interactive() ) return 0;
+ notify_fail( "WAS willst Du schlagen?\n" );
+ if( !arg || sscanf( arg, "wurzel%s", num ) == 0 ) return 0;
+
+ if( sscanf( num, " %d", count ) == 0 ) {
+ notify_fail( "schage wurzel <zahl>\n" );
+ return 0;
+ }
+
+ _wurzel = count;
+ say( Name(WER) + " schlaegt hier Wurzeln.\n" );
+ write( "Du schlaegst nun Wurzeln.\n" );
+ return 1;
+}
+
+static int wurzel_aus( string arg ) {
+
+ if( this_object() != this_interactive() ) return 0;
+ notify_fail( "WAS willst du loesen?\n" );
+ if( !arg ) return 0;
+ if( member( ({"wurzel","wurzeln"}), arg ) == -1 ) return 0;
+
+ _wurzel = -1;
+ say( Name(WER) + " loest " + QueryPronoun(FEMALE,WEN,PLURAL)
+ + " Wurzeln aus dem Boden.\n" );
+ write( "Du loest Deine Wurzeln aus dem Boden.\n" );
+ return 1;
+}
+
+int wurzel_info( string arg ) {
+ if( this_object() != this_interactive() ) return 0;
+ switch( _wurzel ) {
+ case -1:
+ write( "Deine Wurzeln sind lose.\n" );
+ break;
+ case 0:
+ write( "Deine Wurzeln sitzen fest.\n" );
+ break;
+ case 1:
+ write( "Noch eine Bewegung und Du sitzt fest.\n" );
+ break;
+ default:
+ printf( "Noch %d Bewegungen, und Du sitzt fest.\n", _wurzel );
+ }
+ return 1;
+}
+
+static mixed _query_localcmds() {
+ return ::_query_localcmds() + ({
+ ({ "schlag" , "wurzel_an" ,1,ARCH_LVL }),
+ ({ "loes" , "wurzel_aus" ,1,ARCH_LVL }),
+ ({ "wurzelinfo", "wurzel_info",0,ARCH_LVL })
+ });
+}
+
+varargs int move( mixed dest, int method, string dir,
+ string textout, string textin )
+{
+ if( _wurzel == 0 ) {
+ return ME_TOO_HEAVY;
+ }
+ if( _wurzel > 0 ) { _wurzel--; }
+ return ::move( dest, method, dir, textout, textin );
+}
+
+static int new_quit() {
+ _wurzel = -1;
+ return ::new_quit();
+}
diff --git a/std/shells/darkelf.c b/std/shells/darkelf.c
new file mode 100644
index 0000000..45e37fb
--- /dev/null
+++ b/std/shells/darkelf.c
@@ -0,0 +1,270 @@
+// MorgenGrauen MUDlib
+//
+// shells/darkelf.c -- Darkelf Shell
+//
+// $Id: darkelf.c 8675 2014-02-18 20:39:54Z Zesstra $
+
+#pragma strong_types,save_types
+
+inherit "/std/player/base";
+
+#include <properties.h>
+#include <attributes.h>
+#include <wizlevels.h>
+#include <health.h>
+#include <new_skills.h>
+#include <language.h>
+#include <defines.h>
+#include <combat.h>
+#include <defuel.h>
+#include <errord.h>
+
+
+protected void create()
+{
+ if (!clonep() || object_name(this_object()) == __FILE__[0..<3]) {
+ set_next_reset(-1);
+ return;
+ }
+ base::create();
+ SetDefaultHome("/gilden/dunkelelfen");
+ SetDefaultPrayRoom("/d/unterwelt/cadra/room/town/templemain");
+ SetProp(P_AVERAGE_SIZE,175);
+ SetProp(P_AVERAGE_WEIGHT,70000);
+ SetProp(P_ALIGN, -500);
+ SetProp(P_SKILL_ATTRIBUTE_OFFSETS,([SA_ENEMY_SAVE:110]));
+ SetProp(P_ATTRIBUTES_OFFSETS,([A_INT:4,A_DEX:2]));
+ SetProp(P_MATERIAL_KNOWLEDGE,([MATGROUP_UNHOLY: 100,
+ MATGROUP_MAGIC: 70,
+ MATGROUP_DEAD: 50,
+ MATGROUP_METAL: 30]) );
+ SetProp(P_RESISTANCE_STRENGTHS,
+ ([ DT_HOLY : 0.25,
+ DT_UNHOLY : -0.15,
+ DT_TERROR : -0.05 ]));
+ SetProp(P_MAX_FOOD,80);
+ SetProp(P_MAX_DRINK,150);
+ SetProp(P_MAX_ALCOHOL,70);
+
+ SetProp(P_SP_DELAY, HEAL_DELAY-2); // dafuer regeneriert man im freien
+ SetProp(P_HP_DELAY, HEAL_DELAY-1); // wirklich _nichts_
+ SetProp(P_FOOD_DELAY,FOOD_DELAY+1);
+ SetProp(P_DRINK_DELAY,DRINK_DELAY-2);
+ SetProp(P_ALCOHOL_DELAY,ALCOHOL_DELAY+1);
+
+ SetProp(P_MAGIC_RESISTANCE_OFFSET,
+ ([ MT_ILLUSION : 200,
+ MT_ANGRIFF : 500,
+ MT_BEHERRSCHUNG: 500,
+ MT_PSYCHO : 800 ]));
+
+ /* Groesse wird nur einmal gesetzt */
+ if(!QueryProp(P_SIZE)) {
+ SetProp(P_SIZE,150+random(50));
+ Set(P_SIZE,SAVE,F_MODE_AS);
+ }
+
+ /* Dito Gewicht */
+ if(!QueryProp(P_WEIGHT) || (QueryProp(P_WEIGHT) == 75000)){
+ SetProp(P_WEIGHT,60000+random(20001));
+ if(QueryProp(P_GENDER)==FEMALE)
+ SetProp(P_WEIGHT,QueryProp(P_WEIGHT)-5000);
+ Set(P_WEIGHT,SAVE,F_MODE_AS);
+ }
+ SetProp(P_DEFUEL_LIMIT_FOOD,40);
+ SetProp(P_DEFUEL_LIMIT_DRINK,30);
+ SetProp(P_DEFUEL_TIME_FOOD,400);
+ SetProp(P_DEFUEL_TIME_DRINK,250);
+ SetProp(P_DEFUEL_AMOUNT_FOOD,0.45);
+ SetProp(P_DEFUEL_AMOUNT_DRINK,0.4);
+}
+
+static void FinalSetup()
+{
+ if (!QuerySkill(SK_NIGHTVISION))
+ ModifySkill(SK_NIGHTVISION, 5000, 0, "ANY");
+}
+
+string _query_race()
+// nicht static, da sie manchmal auch so aufgerufen wird...
+{
+ return "Dunkelelf";
+}
+
+string _query_real_race()
+{
+ return "Dunkelelf";
+}
+
+static string _query_racedescr()
+{
+ return
+"\
+Das Volk der Dunkelelfen lebt in einer grossen Hoehlenstadt gut versteckt\n\
+hinter einem Wasserfall. Ueber kaum ein anderes Volk gibt es soviele\n\
+Vorurteile wie ueber die Dunkelelfen, und so werden sie von allen misstrauisch\n\
+beaeugt oder sogar bekaempft. In diesem Kampf, insbesondere gegen die Elfen,\n\
+sind sie voellig auf sich allein gestellt, und so hat sich eine mehr oder\n\
+minder autarke Gesellschaft entwickelt. Die Dunkelelfen haben eine eigene\n\
+Kultur und eine eigene Goettin, der sie huldigen. Wie auch die Elfen\n\
+verfuegen sie ueber ausserordenlich grosse magische Faehigkeiten, auch wenn\n\
+sie sich mehr auf die schwarze Seite der Magie spezialisiert haben.\n";
+}
+
+// int QueryAllowSelect() { return 0; }
+// Aktiviert am 28.07.03, Ark.
+int QueryAllowSelect() { return 1; }
+
+string *_query_racestring()
+{
+ if (QueryProp(P_GENDER)==2)
+ return ({"Dunkelelfe","Dunkelelfe","Dunkelelfe","Dunkelelfe"});
+ return ({"Dunkelelf","Dunkelelfen","Dunkelelf","Dunkelelf"});
+}
+
+static string _query_default_guild()
+{
+ return "dunkelelfen";
+}
+
+static int sun_in_room(object room)
+{
+ if (!room) return 0;
+ closure qp=symbol_function("QueryProp", room);
+ int lt=funcall(qp, P_LIGHT_TYPE);
+ // (lt & LT_SUN) ist hier zunaechst _testweise_ drin. Die Rasse wurde
+ // anders genehmigt. Sollte das im MG ueberhand nehmen und jeder Keller
+ // nun sonnendurchflutet sein, dann wird das wieder ausgebaut!
+ // 27.06.04 Padreic
+ return ( (funcall(qp, P_INT_LIGHT)>0) &&
+ ((lt & LT_SUN) || ((lt==LT_MISC) && !funcall(qp, P_INDOORS))));
+}
+
+protected void heart_beat()
+{
+ ::heart_beat();
+ if (sun_in_room(environment()) &&
+ QueryProp("Dunkelelfen:Outdoor")<random(100) && !QueryProp(P_GHOST)) {
+ int hp;
+ hp=QueryProp(P_HP)-1;
+ SetProp(P_HP, hp);
+ if (hp<0) {
+ tell_object(ME,
+ "Das war wohl zuviel fuer Dich. Das naechste mal solltest Du Dich "
+ +"wohl besser\ngegen die Sonne schuetzen.\n");
+ SetProp(P_KILL_NAME,"Zuviel Sonne");
+ do_damage(999,ME);
+ SetProp(P_KILL_NAME,0);
+ }
+ else tell_object(ME, /* die Info musste irgendwie in eine Zeile */
+ "Die Sonne scheint gnadenlos auf Dein Haupt und schwaecht Dich.\n");
+ }
+}
+
+static int _query_no_regeneration()
+{
+ if (sun_in_room(environment()))
+ return NO_REG;
+ return Query(P_NO_REGENERATION);
+}
+
+int StdSkill_Nightvision(object me, string sname, mixed sinfo)
+{
+ int last, light;
+
+ if (!sinfo || !environment()) return 0;
+ if (intp(sinfo)) sinfo=([SI_SKILLABILITY:sinfo]);
+ if (!mappingp(sinfo)) return 0;
+ light=(QueryProp(P_PLAYER_LIGHT)<=0 ? -1 : 1);
+ if (last=sinfo[SI_USR]) { // letztes Lichtlevel != 0
+ if (light==last) {
+ if (sinfo[SI_LASTLIGHT]<=time())
+ return sinfo[SI_SKILLABILITY]+1;
+ return -1;
+ }
+ else {
+ last=( MAX_ABILITY - sinfo[SI_SKILLABILITY] );
+ last=(last/1000) + (last%1000 > random(1001) ? 1 : 0);
+ if (light<0) last/=2; // an Dunkelkeit schneller gewoehnen...
+ if(!this_interactive() || this_interactive()==this_object())
+ {
+ ModifySkill(sname, ([SI_USR: light, SI_LASTLIGHT: time()+last]),
+ 0, sinfo[SI_GUILD]);
+ }
+ if (last<=0)
+ return sinfo[SI_SKILLABILITY]+1;
+ return -1;
+ }
+ }
+ else { // Startwert...
+ if(!this_interactive() || this_interactive()==this_object())
+ {
+ ModifySkill(sname, ([SI_USR: light, SI_LASTLIGHT: 0]), 0, sinfo[SI_GUILD]);
+ }
+ return sinfo[SI_SKILLABILITY]+1;
+ }
+ return 0;
+}
+
+varargs int CannotSee(int silent)
+{
+ string is_blind;
+
+ if ( is_blind = QueryProp( P_BLIND ) ) {
+ if (!silent) {
+ if (stringp(is_blind)) write(is_blind);
+ else write("Du bist blind!\n");
+ }
+ return 1;
+ }
+ if (environment() && (!IS_LEARNER(ME) || !Query(P_WANTS_TO_LEARN))) {
+ if (QueryProp(P_GHOST)) {
+ if (StdSkill_Nightvision(ME, SK_NIGHTVISION, QuerySkill(SK_NIGHTVISION))>0)
+ return 0;
+ }
+ else if (UseSkill(SK_NIGHTVISION)>0) return 0;
+ if (!silent) {
+ if (QueryProp(P_PLAYER_LIGHT)<=0)
+ write("Du kannst nichts sehen, da sich Deine Augen noch nicht an die Dunkelheit\n"
+ +"gewoehnt haben!\n");
+ else write("Du bist von dem hellen Licht total geblendet und Du musst Dich erst langsam\n"
+ +"daran gewoehnen.\n");
+ }
+ return 1;
+ }
+ return 0;
+}
+
+
+/*
+ * 2003-11-05, Zook:
+ *
+ * Temporaere Funktion, die den Delfen es ermoeglicht, einen
+ * moeglicherweise falschen Raum (Indoor/Outdoor) zu melden.
+ *
+ */
+
+static int _indoorbug(string key)
+{
+ if (!stringp(key))
+ key= "";
+
+ ERRORD->LogReportedError(
+ ([ F_PROG: "unbekannt",
+ F_LINE: 0,
+ F_MSG: "Sonnenfehler: " + key,
+ F_OBJ: environment(this_object())
+ ])
+ );
+
+ write("Du hast einen fehlerhaften Innen-/Aussen-/Sonnenlichtraum gemeldet.\n");
+
+ return 1;
+}
+
+static mixed _query_localcmds()
+{
+ return ({ ({"sonnenfehler", "_indoorbug", 0, 0 }) })
+ + base::_query_localcmds();
+}
+
diff --git a/std/shells/dwarf.c b/std/shells/dwarf.c
new file mode 100644
index 0000000..7a696dc
--- /dev/null
+++ b/std/shells/dwarf.c
@@ -0,0 +1,156 @@
+// MorgenGrauen MUDlib
+//
+// shells/dwarf.c -- Dwarven Shell
+//
+// $Id: dwarf.c,v 3.14 2004/12/13 12:54:31 Zook Exp $
+
+#pragma strong_types,save_types
+
+inherit "std/player/base";
+
+#include <properties.h>
+#include <attributes.h>
+#include <wizlevels.h>
+#include <health.h>
+#include <new_skills.h>
+#include <language.h>
+#include <combat.h>
+#include <defuel.h>
+
+
+void create(){
+ if (!clonep() || object_name(this_object()) == __FILE__[0..<3]) {
+ set_next_reset(-1);
+ return;
+ }
+
+ mixed res;
+
+ base::create();
+ SetDefaultHome("/d/gebirge/room/zkapelle");
+ SetDefaultPrayRoom("/d/gebirge/room/zkapelle");
+ SetProp(P_ATTRIBUTES_OFFSETS,([A_STR:2,A_DEX:1,A_CON:3]));
+ SetProp(P_SKILL_ATTRIBUTE_OFFSETS,([SA_DURATION:110]));
+ SetProp(P_AVERAGE_SIZE,120);
+ SetProp(P_AVERAGE_WEIGHT,75000);
+ SetProp(P_MATERIAL_KNOWLEDGE,([MATGROUP_STONE:30,
+ MATGROUP_METAL:30,
+ MATGROUP_PRECIOUS_METAL: 40,
+ MAT_GOLD:100]));
+ SetProp(P_RESISTANCE_STRENGTHS,
+ ([ DT_FIRE : -0.2,
+ DT_WATER : 0.4 ]));
+ SetProp(P_MAX_ALCOHOL,200);
+ SetProp(P_MAX_FOOD,160);
+
+ SetProp(P_SP_DELAY,HEAL_DELAY+1);
+ SetProp(P_POISON_DELAY,POISON_DELAY+1);
+ SetProp(P_FOOD_DELAY,FOOD_DELAY-1);
+ SetProp(P_ALCOHOL_DELAY,ALCOHOL_DELAY-1);
+
+ SetProp(P_MAGIC_RESISTANCE_OFFSET,
+ ([ MT_ANGRIFF : 200,
+ MT_ILLUSION : -500,
+ MT_BEHERRSCHUNG : 1000,
+ MT_VERWANDLUNG : 500 ]));
+
+ if(!IS_SEER(this_object())){
+ SetProp(P_MSGIN,"stapft herein");
+ SetProp(P_MSGOUT,"stapft");
+ }
+
+ if(!(res=QueryProp(P_HANDS)) || !pointerp(res) || (sizeof(res)<3))
+ res=({" mit blossen Haenden",35,({DT_BLUDGEON}) });
+ res[1]=35;
+ SetProp(P_HANDS,res);
+ SetProp(P_BODY,10);
+
+ /* Groesse wird nur einmal gesetzt */
+ if(!QueryProp(P_SIZE)){
+ SetProp(P_SIZE,110+random(21));
+ Set(P_SIZE,SAVE,F_MODE_AS);
+ }
+
+ /* Dito Gewicht */
+ if(!QueryProp(P_WEIGHT) || (QueryProp(P_WEIGHT) == 75000)){
+ SetProp(P_WEIGHT,65000+random(20001));
+ if(QueryProp(P_GENDER)==FEMALE)
+ SetProp(P_WEIGHT,QueryProp(P_WEIGHT)-5000);
+ Set(P_WEIGHT,SAVE,F_MODE_AS);
+ }
+
+ SetProp(P_DEFUEL_LIMIT_FOOD,70);
+ SetProp(P_DEFUEL_LIMIT_DRINK,50);
+ SetProp(P_DEFUEL_TIME_FOOD,535);
+ SetProp(P_DEFUEL_TIME_DRINK,500);
+ SetProp(P_DEFUEL_AMOUNT_FOOD,0.8);
+ SetProp(P_DEFUEL_AMOUNT_DRINK,0.6);
+
+}
+
+string _query_race()
+{
+ return "Zwerg";
+}
+
+string _query_real_race()
+{
+ return "Zwerg";
+}
+
+string _query_racedescr()
+{
+ return
+ "Zwerge sind kleine aber kraeftige Gebirgsbewohner, nicht sehr gespraechig,\n"
+ +"leicht erzuernt, aber eine schlagkraeftige Unterstuetzung fuer ihre Freunde."
+ +"\n"
+ +"Ihr Mut und ihre Standfestigkeit ist weit und breit beruehmt, auch ihr\n"
+ +"Geschick im Umgang mit Zwergenwaffen verleiht ihnen zusaetzliche Kraft.\n"
+ +"Leider sind Zwerge nicht allzu schlau, sie verlassen sich lieber auf\n"
+ +"ihre Kraft als auf ihr Gehirn.\n";
+}
+
+int QueryAllowSelect() { return 1; }
+
+string *_query_racestring()
+{
+ if (QueryProp(P_GENDER)==2)
+ return ({"Zwergin","Zwergin","Zwergin","Zwergin"});
+ return ({"Zwerg","Zwerges","Zwerg","Zwerg"});
+}
+int _query_hp_delay(){
+ int re;
+ re = Query(P_HP_DELAY);
+ if (environment() && environment()->QueryProp(P_INDOORS))
+ re--;
+ else
+ re++;
+ return re;
+}
+int _query_sp_delay(){
+ int re;
+ re = Query(P_SP_DELAY);
+ if (environment() && environment()->QueryProp(P_INDOORS))
+ re--;
+ else
+ re++;
+ return re;
+}
+
+string _query_default_guild(){
+ return "abenteurer";
+}
+
+mixed RaceDefault(string arg)
+{
+ if (!arg)
+ return 0;
+ switch(arg)
+ {
+ case P_HANDS :
+ return ({" mit blossen Haenden",35,({DT_BLUDGEON}) });
+ case P_BODY :
+ return 10;
+ }
+ return 0;
+}
diff --git a/std/shells/elf.c b/std/shells/elf.c
new file mode 100644
index 0000000..dec4118
--- /dev/null
+++ b/std/shells/elf.c
@@ -0,0 +1,154 @@
+// MorgenGrauen MUDlib
+//
+// shells/elf.c -- Elven Shell
+//
+// $Id: elf.c 8928 2014-09-08 16:18:41Z Zesstra $
+
+#pragma strong_types,save_types
+
+inherit "std/player/base";
+
+#include <properties.h>
+#include <attributes.h>
+#include <wizlevels.h>
+#include <health.h>
+#include <new_skills.h>
+#include <language.h>
+#include <combat.h>
+#include <defuel.h>
+
+
+
+void create()
+{
+ if (!clonep() || object_name(this_object()) == __FILE__[0..<3]) {
+ set_next_reset(-1);
+ return;
+ }
+
+ base::create();
+ SetDefaultHome("/d/wald/room/es_mitte");
+ SetDefaultPrayRoom("/d/wald/room/es_mitte");
+ SetProp(P_AVERAGE_SIZE,195);
+ SetProp(P_AVERAGE_WEIGHT,70000);
+ SetProp(P_SKILL_ATTRIBUTE_OFFSETS,([SA_ENEMY_SAVE:110]));
+ SetProp(P_ATTRIBUTES_OFFSETS,([A_INT:3,A_DEX:2,A_CON:1]));
+ SetProp(P_MATERIAL_KNOWLEDGE,([MATGROUP_WOOD:30,
+ MATGROUP_HERBAL:30,
+ MATGROUP_LIVING:20]));
+
+ SetProp(P_MAX_FOOD,80);
+ SetProp(P_MAX_DRINK,150);
+ SetProp(P_MAX_ALCOHOL,70);
+
+ SetProp(P_SP_DELAY,HEAL_DELAY-1);
+ SetProp(P_FOOD_DELAY,FOOD_DELAY+1);
+ SetProp(P_DRINK_DELAY,DRINK_DELAY-2);
+ SetProp(P_ALCOHOL_DELAY,ALCOHOL_DELAY+1);
+
+ SetProp(P_MAGIC_RESISTANCE_OFFSET,
+ ([ MT_ILLUSION : 800,
+ MT_ANGRIFF : 200,
+ MT_VERWANDLUNG : 400,
+ MT_PSYCHO : 500 ]));
+
+ // Elfen kriegen die Ebene der Wipfellaeufer per default. (Zu diesem
+ // Zeitpunkt stehen in P_CHANNELS nur die default channel drin, wird dann
+ // ueber das Einlesen des Savefiles ggf. ueberschrieben.)
+ SetProp(P_CHANNELS, QueryProp(P_CHANNELS) + ({"wipfellaeufer"}));
+
+ if(!IS_SEER(this_object())){
+ SetProp(P_MSGIN,"wandelt herein");
+ SetProp(P_MSGOUT,"wandelt");
+ }
+
+ /* Groesse wird nur einmal gesetzt */
+ if(!QueryProp(P_SIZE)){
+ SetProp(P_SIZE,185+random(21));
+ Set(P_SIZE,SAVE,F_MODE_AS);
+ }
+
+ /* Dito Gewicht */
+ if(!QueryProp(P_WEIGHT) || (QueryProp(P_WEIGHT) == 75000)){
+ SetProp(P_WEIGHT,60000+random(20001));
+ if(QueryProp(P_GENDER)==FEMALE)
+ SetProp(P_WEIGHT,QueryProp(P_WEIGHT)-5000);
+ Set(P_WEIGHT,SAVE,F_MODE_AS);
+ }
+ SetProp(P_DEFUEL_LIMIT_FOOD,40);
+ SetProp(P_DEFUEL_LIMIT_DRINK,20);
+ SetProp(P_DEFUEL_TIME_FOOD,400);
+ SetProp(P_DEFUEL_TIME_DRINK,200);
+ SetProp(P_DEFUEL_AMOUNT_FOOD,0.4);
+ SetProp(P_DEFUEL_AMOUNT_DRINK,0.35);
+
+}
+
+string _query_race()
+{
+ return "Elf";
+}
+
+string _query_real_race()
+{
+ return "Elf";
+}
+
+string _query_racedescr()
+{
+ return
+"\
+Als Elfen bezeichnet man in der Regel jene hageren Hinterwaeldler, deren\n\
+demonstratives Naturgehabe in der Regel nur durch ihre Liebe zu kitschigen\n\
+Gedichten und ausschweifendem Geschlechtsleben in den Schatten gestellt wird.\n\
+Einen Elf kann man im allgemeinen nicht nur an aeusseren Missbildungen\n\
+(spitze Ohren, spindelduerre Gestalt, blonde Haare) erkennen, sondern auch\n\
+an seiner aufdringlichen Art, ueber jeden und alles hemmungslos ins Gruene\n\
+loszuphilosophieren.\n";
+
+}
+
+int QueryAllowSelect() { return 1; }
+
+string *_query_racestring()
+{
+ if (QueryProp(P_GENDER)==2)
+ return ({"Elfe","Elfe","Elfe","Elfe"});
+ return ({"Elf","Elfen","Elf","Elf"});
+}
+int _query_hp_delay(){
+ int re;
+ re = Query(P_HP_DELAY);
+ if (environment() && environment()->QueryProp(P_INDOORS))
+ re++;
+ else
+ re--;
+ return re;
+}
+int _query_sp_delay(){
+ int re;
+ re = Query(P_SP_DELAY);
+ if (environment() && environment()->QueryProp(P_INDOORS))
+ re++;
+ else
+ re--;
+ return re;
+}
+
+string _query_default_guild(){
+ return "wipfellaeufer";
+}
+
+static void FinalSetup()
+{
+ if(QueryProp(P_GUILD) != "chaos")
+ SetProp(P_RESISTANCE_STRENGTHS,
+ ([ DT_MAGIC : -0.2,
+ DT_HOLY : 0.1,
+ DT_UNHOLY : 0.3 ]));
+ else
+ SetProp(P_RESISTANCE_STRENGTHS,
+ ([ DT_MAGIC : -0.2,
+ DT_UNHOLY : 0.1,
+ DT_HOLY : 0.3 ]));
+}
diff --git a/std/shells/feline.c b/std/shells/feline.c
new file mode 100644
index 0000000..f590fab
--- /dev/null
+++ b/std/shells/feline.c
@@ -0,0 +1,259 @@
+// MorgenGrauen MUDlib
+//
+// shells/feline.c -- Feline Shell
+//
+// $Id: feline.c 8487 2013-05-21 19:15:52Z Zesstra $
+
+#pragma strong_types,save_types
+
+inherit "/std/player/base";
+
+#include <attributes.h>
+#include <combat.h>
+#include <health.h>
+#include <new_skills.h>
+#include <properties.h>
+#include <language.h>
+#include <wizlevels.h>
+#include <defuel.h>
+
+
+void create()
+{
+ if (!clonep() || object_name(this_object()) == __FILE__[0..<3]) {
+ set_next_reset(-1);
+ return;
+ }
+
+ int i,g;
+ mixed h;
+
+ base::create();
+
+// Startraum/Kapelle setzen
+ SetDefaultHome("/d/dschungel/paracelsus/room/fkapelle");
+ SetDefaultPrayRoom("/d/dschungel/paracelsus/room/fkapelle");
+
+// Besondere rassenspezifische Properties (bei denen es nichts macht, wenn
+// sie nach jedem Einloggen neu gesetzt werden):
+
+ SetProp(P_ATTRIBUTES_OFFSETS, // Summe 4 statt 6 wg. SA_SPEED
+ ([
+ A_STR : 1,
+ A_INT : 2,
+ A_DEX : 2,
+ A_CON : -1
+ ]) );
+ SetProp(P_AVERAGE_SIZE,200);
+ SetProp(P_AVERAGE_WEIGHT,85000);
+ SetProp(P_BODY,15);
+ SetProp(P_SKILL_ATTRIBUTE_OFFSETS,([SA_SPEED:120]));
+ SetProp(P_MATERIAL_KNOWLEDGE,
+ ([
+ MATGROUP_WOOD : 60,
+ MATGROUP_JEWEL : 100,
+ MATGROUP_EATABLE : 30
+ ]) );
+
+ SetProp(P_MAGIC_RESISTANCE_OFFSET,
+ ([
+ MT_ANGRIFF : 200,
+ MT_ILLUSION : -500,
+ MT_VERWANDLUNG : 500,
+ MT_PSYCHO : 1000
+ ]) );
+
+ SetProp(P_RESISTANCE_STRENGTHS,
+ ([
+ DT_WATER : -0.1,
+ DT_ACID : 0.1,
+ DT_COLD : 0.1
+ ]) );
+
+// Lebenspunkte werden langsamer als normal regeneriert
+ SetProp(P_HP_DELAY,HEAL_DELAY+1);
+
+// Magiepunkte werden schneller als normal regeneriert
+ SetProp(P_SP_DELAY,HEAL_DELAY-1);
+
+// Gift wirkt etwas langsamer als normal
+ SetProp(P_POISON_DELAY,POISON_DELAY+1);
+
+// Getraenke werden etwas schneller als normal abgebaut
+ SetProp(P_DRINK_DELAY,DRINK_DELAY-1);
+
+// Essen wird etwas schneller als normal abgebaut ...
+ SetProp(P_FOOD_DELAY,FOOD_DELAY-1);
+ SetProp(P_MAX_FOOD,140);
+
+// Es gibt einige Sachen, die sollen nur beim ersten Einloggen gesetzt werden.
+// Andere muessen nachtraeglich - aber nur einmal - gemacht werden, weil sich
+// etwas geaendert hat.
+ switch( QueryProp(P_SHELL_VERSION) )
+ {
+ case 0 :
+
+ g=QueryProp(P_GENDER);
+
+ if ( !(i=QueryProp(P_SIZE)) || (i<(g==FEMALE?165:170))
+ || (i>(g==FEMALE?225:230)) )
+ {
+ SetProp(P_SIZE, (g==FEMALE?195:200)
+ + random(16) - random(16) + random(16) - random(16) );
+ }
+
+ if( !(i=QueryProp(P_WEIGHT)) || (i<(g==FEMALE?70000:77000))
+ || (i>(g==FEMALE?88000:95000)) || (i==75000) )
+ {
+ SetProp(P_WEIGHT, (g==FEMALE?70000:77000)
+ + random(4501) + random(4501) + random(4501) + random(4501) );
+ }
+
+
+ SetProp(P_MATERIAL,([
+ MAT_MISC_LIVING : 90,
+ MAT_PELT : 8,
+ MAT_HORN : 2
+ ]) );
+
+ if ( !IS_SEER(this_object()) )
+ {
+ SetProp(P_MSGIN,"schleicht herein");
+ SetProp(P_MSGOUT,"schleicht");
+ SetProp(P_MMSGIN,"erscheint mit einem grellen Blitz");
+ SetProp(P_MMSGOUT,"verschwindet mit einem grellen Blitz");
+ SetProp(P_HANDS,({" mit scharfen Krallen",40, ({DT_RIP}) }));
+ }
+ else
+ {
+ if ( !pointerp(h=QueryProp(P_HANDS)) || (sizeof(h)<1) )
+ h = ({" mit scharfen Krallen",40, ({DT_RIP}) });
+ else
+ h = ({h[0],40, ({DT_RIP}) });
+ SetProp(P_HANDS, h);
+ }
+
+ if ( !pointerp(h=QueryProp(P_CHANNELS)) )
+ SetProp(P_CHANNELS,({"katzenkrieger"}));
+ else if ( member(h,"katzenkrieger")==-1 )
+ SetProp(P_CHANNELS, h + ({"katzenkrieger"}) );
+
+ Set(P_SIZE,SAVE,F_MODE_AS);
+ Set(P_MATERIAL,SAVE,F_MODE_AS);
+ Set(P_WEIGHT,SAVE,F_MODE_AS);
+
+ default :
+
+ SetProp(P_SHELL_VERSION,1);
+ }
+ SetProp(P_DEFUEL_LIMIT_FOOD,70);
+ SetProp(P_DEFUEL_LIMIT_DRINK,40);
+ SetProp(P_DEFUEL_TIME_FOOD,400);
+ SetProp(P_DEFUEL_TIME_DRINK,300);
+ SetProp(P_DEFUEL_AMOUNT_FOOD,0.55);
+ SetProp(P_DEFUEL_AMOUNT_DRINK,0.4);
+
+}
+
+// Diese Rasse kann derzeit gewaehlt werden:
+int QueryAllowSelect() { return 1; }
+
+// Rassenbezeichnung
+string _query_race()
+{
+ return "Feline";
+}
+
+string _query_real_race()
+{
+ return "Feline";
+}
+
+// Die Rassenbeschreibung, die man beim ersten Einloggen abrufen kann.
+string _query_racedescr()
+{
+ return break_string(
+ "Felinen sind aufrecht gehende Katzenwesen.\n"+
+ "Ihre Heimat ist der Dschungel. Kaum jemand duerfte sich dort "+
+ "besser zurechtfinden als sie. Bedingt durch diese Umgebung "+
+ "haben sie im Laufe der Zeit eine Vorliebe fuer elegante Hoelzer "+
+ "und funkelnde Edelsteine entwickelt. Sie sind zwar nicht so "+
+ "'raffgierig' wie Zwerge, aber dennoch sollte man besser nicht "+
+ "versuchen, einem Felinen einen Edelstein wegzunehmen. Sie "+
+ "benutzen die Edelsteine sehr gerne, um sich damit zu schmuecken. "+
+ "Felinen betreiben sogar einen regelrechten Koerperkult, "+
+ "insbesondere wenn es darum geht, das Fell oder die Krallen zu "+
+ "faerben. Edelsteine kommen da als Accessoires gerade recht.\n"+
+ "Auch im Kampf gegen einen Felinen sollte man sehr vorsichtig "+
+ "sein, da Felinen ihre geringe Ausdauer durch eine hohe "+
+ "Geschwindigkeit sowie Geschick und Intelligenz wettmachen. "+
+ "Auch die Spitzen Krallen sind da nicht zu verachten und so "+
+ "mancher Gegner musste schon als Ersatz fuer einen Kratzbaum "+
+ "herhalten.",78,0,1);
+}
+
+// Geschlechtsabhaengiges Rassenbezeichnungs-Array
+string *_query_racestring()
+{
+ if (QueryProp(P_GENDER)==2)
+ return ({"Felinin","Felinin","Felinin","Felinin"});
+ return ({"Feline","Felinen","Felinen","Felinen"});
+}
+
+// Regeneration der Lebenspunkte ist von der Umgebung abhaengig
+// Im Wald und Dschungel geht es schneller, in der Wueste und im
+// Polargebiet dagegen langsamer.
+int _query_hp_delay()
+{
+ int re;
+ string fn;
+
+ re = Query(P_HP_DELAY);
+ if (environment() && !(environment()->QueryProp(P_INDOORS)) &&
+ fn=object_name(environment()))
+ {
+ if (fn[0..12]=="/d/dschungel/" || fn[0..7]=="/d/wald/")
+ re--;
+ else if (fn[0..9]=="/d/wueste/" || fn[0..8]=="/d/polar/")
+ re++;
+ }
+ return re;
+}
+
+// Regeneration der Magiepunkte ist von der Umgebung abhaengig
+// Im Wald und Dschungel geht es schneller, in der Wueste und im
+// Polargebiet dagegen langsamer.
+int _query_sp_delay()
+{
+ int re;
+ string fn;
+
+ re = Query(P_SP_DELAY);
+ if (environment() && !(environment()->QueryProp(P_INDOORS)) &&
+ fn=object_name(environment()))
+ {
+ if (fn[0..12]=="/d/dschungel/" || fn[0..7]=="/d/wald/")
+ re--;
+ else if (fn[0..9]=="/d/wueste/" || fn[0..8]=="/d/polar/")
+ re++;
+ }
+ return re;
+}
+
+string _query_default_guild(){
+ return "katzenkrieger";
+}
+
+mixed RaceDefault(string arg)
+{
+ if (!arg)
+ return 0;
+ switch(arg)
+ {
+ case P_HANDS :
+ return ({" mit scharfen Krallen",40, ({DT_RIP}) });
+ case P_BODY :
+ return 15;
+ }
+ return base::RaceDefault(arg);
+}
diff --git a/std/shells/goblin.c b/std/shells/goblin.c
new file mode 100644
index 0000000..ed694b3
--- /dev/null
+++ b/std/shells/goblin.c
@@ -0,0 +1,213 @@
+/*
+ * Goblin-Rassenshell
+ * [/std/shells/goblin.c]
+ * (c) 2007 nibel@mg.mud.de
+ *
+ * Werte von Ark abgesegnet am 11.12.2007
+ */
+
+#pragma strong_types,save_types
+
+#include <attributes.h>
+#include <health.h>
+#include <new_skills.h>
+#include <properties.h>
+#include <wizlevels.h>
+#include <defuel.h>
+#include <moving.h>
+
+inherit "/std/player/base.c";
+
+static varargs int GoblinCmdWaaagh(string arg);
+
+public void create() {
+ mixed res;
+ base::create();
+
+ SetDefaultHome("/d/wald/kessa/waaagh/room/starthut/hut[" +
+ getuid(this_object()) +"]");
+ SetDefaultPrayRoom("/d/wald/nibel/lichtung/room/lichtung_45");
+
+ SetProp(P_AVERAGE_SIZE, 80);
+ SetProp(P_AVERAGE_WEIGHT, 32000);
+ SetProp(P_MATERIAL_KNOWLEDGE, ([MATGROUP_EATABLE:20, MATGROUP_DRUG:40,
+ MATGROUP_PRECIOUS_METAL:25, MATGROUP_JEWEL:25]));
+
+ SetProp(P_BODY, 15);
+ SetProp(P_ATTRIBUTES_OFFSETS, ([A_STR:0, A_INT:1, A_DEX:2, A_CON:2]));
+ SetProp(P_RESISTANCE_STRENGTHS, ([DT_FIRE:-0.15, DT_LIGHTNING:-0.15,
+ DT_SOUND:0.1, DT_HOLY:0.1, DT_AIR:0.1, DT_ACID:0.1]));
+ SetProp(P_MAGIC_RESISTANCE_OFFSET, ([MT_ANGRIFF:600, MT_ILLUSION:500,
+ MT_VERWANDLUNG:-300, MT_HELLSICHT:-750, MT_BEHERRSCHUNG:250]));
+ SetProp(P_SKILL_ATTRIBUTE_OFFSETS, ([SA_ENEMY_SAVE:103, SA_DAMAGE:107]));
+
+ SetProp(P_SP_DELAY, HEAL_DELAY + 2);
+ SetProp(P_HP_DELAY, HEAL_DELAY - 1);
+ SetProp(P_ALCOHOL_DELAY, ALCOHOL_DELAY - 1);
+
+ switch(QueryProp(P_SHELL_VERSION)) {
+ case 0:
+ if(!QueryProp(P_SIZE)) // Maennlein und Weiblein sind gleich "gross"
+ SetProp(P_SIZE, 75 + random(11));
+ if(QueryProp(P_WEIGHT) == 75000) // Dito Gewicht
+ SetProp(P_WEIGHT, (QueryProp(P_SIZE) * 390) +
+ random(QueryProp(P_SIZE) * 10));
+ SetProp(P_MATERIAL,([MAT_MISC_LIVING:100]));
+
+ Set(P_SIZE, SAVE, F_MODE_AS);
+ Set(P_WEIGHT, SAVE, F_MODE_AS);
+ Set(P_MATERIAL, SAVE, F_MODE_AS);
+
+ if(!pointerp(res = QueryProp(P_HANDS)) || sizeof(res) < 3)
+ res = ({" mit kleinen Faeustchen", 30, ({ DT_BLUDGEON })});
+ SetProp(P_HANDS, res);
+
+ if(!IS_SEER(this_object())) {
+ SetProp(P_MSGIN, "flitzt herein");
+ SetProp(P_MSGOUT, "flitzt");
+ }
+ SetProp(P_SHELL_VERSION, 1);
+ case 1:
+ // /std/player/base setzt ja schon P_WEIGHT...
+ if(QueryProp(P_WEIGHT) == 75000) {
+ SetProp(P_WEIGHT, (QueryProp(P_SIZE) * 390) +
+ random(QueryProp(P_SIZE) * 10));
+ }
+ SetProp(P_SHELL_VERSION, 2);
+ default: break;
+ }
+
+ SetProp(P_MAX_FOOD, 110);
+ SetProp(P_MAX_DRINK, 80);
+ SetProp(P_MAX_ALCOHOL, 125);
+ SetProp(P_DEFUEL_LIMIT_FOOD, 60);
+ SetProp(P_DEFUEL_LIMIT_DRINK, 60);
+ SetProp(P_DEFUEL_TIME_FOOD, 400);
+ SetProp(P_DEFUEL_TIME_DRINK, 360);
+ SetProp(P_DEFUEL_AMOUNT_FOOD, 0.5);
+ SetProp(P_DEFUEL_AMOUNT_DRINK, 0.4);
+}
+
+static void FinalSetup() {
+ object o;
+ if(QueryProp(P_LEVEL) > 5 || present("\nibel:waldlichtungskarte",
+ this_object())) return;
+ if(!catch(o = clone_object("/d/wald/nibel/lichtung/obj/karte")))
+ o->move(this_object(), M_NOCHECK);
+}
+
+public int QueryAllowSelect() { return 1; }
+
+public string _query_race() { return "Goblin"; }
+public string _query_real_race() { return "Goblin"; }
+
+public string _query_racedescr() {
+ return break_string("Goblins sind winzige, gruenhaeutige Wesen, sogar "
+ "noch kleiner als Hobbits. An ihren zu dick geratenen Koepfchen "
+ "befinden sich lange, selten reglose, Ohren und eine grosse, krumme "
+ "Nase. Ihre kleine Statur sollte jedoch nicht taeuschen, denn ihre "
+ "fehlende Kraft machen sie mit Geschwindigkeit, Praezision und nicht "
+ "zuletzt ihrer unbestrittenen Ruchlosigkeit alleweil wett. Obwohl "
+ "fuer sie Pluendern, lautes Herumbruellen und die gemeinsten Streiche "
+ "spielen zum Alltag gehoert, wuerde sie niemand als boesartig "
+ "bezeichnen. Denn Goblins sind vieles, aber sicherlich nicht die "
+ "intelligentesten Kreaturen. Durch ihren zaehen Willen und die dicke, "
+ "lederne Haut sind sie aussergewoehnlich widerstandsfaehig, und, "
+ "sofern funkelnde Beute winkt, fuer jedes Abenteuer zu haben.", 78);
+}
+
+public string *_query_racestring() {
+ if(QueryProp(P_GENDER) == FEMALE)
+ return ({"Goblinfrau", "Goblinfrau", "Goblinfrau", "Goblinfrau"});
+ return ({"Goblin", "Goblins", "Goblin", "Goblin"});
+}
+
+public string _query_default_guild() {return "abenteurer";}
+
+public string _query_visible_guild() {
+ switch(lower_case(QueryProp(P_GUILD))) {
+ case "abenteurer": return "abentoira";
+ case "wipfellaeufer": return "wiffelloifa";
+ case "chaos": return "kaos";
+ case "zauberer": return "zaubara";
+ case "bierschuettler": return "biaschuettla";
+ case "katzenkrieger": return "kaznkriega";
+ case "tanjian": return "tanschan";
+ case "klerus": return "klerikae";
+ case "dunkelelfen": return "dunklelfn";
+ case "kaempfer": return "kaempfa";
+ case "karate": return "karatae";
+ case "werwoelfe": return "weawoelf";
+ case "magus": return "magia";
+ case "urukhai": return "urugai";
+ }
+ return QueryProp(P_GUILD);
+}
+
+public mixed RaceDefault(string arg) {
+ if(!arg) return 0;
+ switch(arg) {
+ case P_HANDS:
+ return ({" mit kleinen Faeustchen", 30, ({ DT_BLUDGEON })});
+ case P_BODY:
+ return 15;
+ }
+ return base::RaceDefault(arg);
+}
+
+static mixed _query_localcmds() {
+ return ({({"waaagh", "GoblinCmdWaaagh", 0, 0})}) +
+ base::_query_localcmds();
+}
+
+// "knuddel alle" ist deutlich teurer also who cares :-)
+static varargs int GoblinCmdWaaagh(string arg) {
+ object *obs;
+ string s, w;
+
+ if(!objectp(environment())) return 0;
+ obs = filter(all_inventory(environment()) - ({this_object()}), #'living);
+ obs = obs - filter_objects(obs, "QueryProp", P_INVIS);
+ // levelabhaengige Anzahl aaaaaaa's
+ w = "W"+ sprintf("%'a'"+ (QueryProp(P_LEVEL) / 10 + 3) +"s", "aaa") +"gh!";
+
+ foreach(object o : obs)
+ {
+ string str=(break_string(Name(WER) +" ballt die Faeustchen und "
+ "kreischt laut: "+ w +"\n"
+ + capitalize(o->QueryDu(WER)) + " zuckst erschrocken zusammen.",
+ 78, 0, BS_LEAVE_MY_LFS));
+
+ int res=o->ReceiveMsg(str,MT_LISTEN,MA_EMOTE,0,this_object());
+ if (res<0)
+ {
+ obs-=({o}); // unten nicht mehr mit anzeigen.
+ if (res==MSG_SENSE_BLOCK)
+ ReceiveMsg(o->Name(WER) +" kann Dich nicht hoeren.",
+ MT_NOTIFICATION|MSG_DONT_IGNORE|MSG_DONT_STORE,
+ MA_EMOTE,0,this_object());
+ else
+ ReceiveMsg(o->Name(WER) +" ignoriert Dich oder diesen Befehl.",
+ MT_NOTIFICATION|MSG_DONT_IGNORE|MSG_DONT_STORE,
+ MA_EMOTE,0,this_object());
+ }
+ }
+ int anzahl=sizeof(obs);
+ if(!anzahl)
+ {
+ ReceiveMsg("Du ballst die Faeustchen und kreischst laut: "
+ + w, MT_NOTIFICATION|MSG_DONT_IGNORE,MA_EMOTE,0,this_object());
+ }
+ else
+ {
+ s = CountUp(map_objects(obs, "name", WER));
+ ReceiveMsg(break_string("Du ballst die Faeustchen und kreischst laut: "
+ + w +"\n"+ capitalize(s) +" zuck"
+ +(anzahl > 1 ? "en" : "t") +" erschrocken zusammen.",
+ 78, 0, BS_LEAVE_MY_LFS),
+ MT_NOTIFICATION|MSG_DONT_STORE|MSG_DONT_IGNORE,
+ MA_EMOTE,0,this_object());
+ }
+ return 1;
+}
+
diff --git a/std/shells/hobbit.c b/std/shells/hobbit.c
new file mode 100644
index 0000000..b626b06
--- /dev/null
+++ b/std/shells/hobbit.c
@@ -0,0 +1,139 @@
+// MorgenGrauen MUDlib
+//
+// shells/hobbit.c -- Hobbit Shell
+//
+// 9.April 1995 V1.0 Gundur
+//
+// 15.Juni prayroom und defHome auf Hobbitdorf gesetzt von Gundur
+//
+// $Id: hobbit.c 8920 2014-09-02 20:18:38Z Zesstra $
+
+#pragma strong_types,save_types
+
+inherit "std/player/base";
+
+#include <properties.h>
+#include <attributes.h>
+#include <wizlevels.h>
+#include <health.h>
+#include <new_skills.h>
+#include <language.h>
+#include <combat.h>
+#include <moving.h>
+#include <defuel.h>
+
+
+
+void create(){
+ if (!clonep() || object_name(this_object()) == __FILE__[0..<3]) {
+ set_next_reset(-1);
+ return;
+ }
+
+ mixed res;
+
+ base::create();
+ SetDefaultHome("/d/wald/gundur/hobbitdorf/schrein");
+ SetDefaultPrayRoom("/d/wald/gundur/hobbitdorf/schrein");
+ SetProp(P_ATTRIBUTES_OFFSETS,([A_DEX:4,A_CON:2]));
+ SetProp(P_AVERAGE_SIZE, 105);
+ SetProp(P_AVERAGE_WEIGHT, 60000);
+ SetProp(P_MATERIAL_KNOWLEDGE,([MATGROUP_EATABLE:30,
+ MATGROUP_DRUG:30,
+ MATGROUP_POISONOUS:10]));
+ SetProp(P_RESISTANCE_STRENGTHS,
+ ([ DT_TERROR : -0.1,
+ DT_MAGIC : -0.1,
+ DT_SOUND : 0.2,
+ DT_LIGHTNING : 0.1,
+ DT_POISON : 0.1 ]));
+ SetProp(P_MAX_FOOD,250);
+ SetProp(P_MAX_DRINK,100);
+ SetProp(P_MAX_ALCOHOL,150);
+
+ SetProp(P_SP_DELAY,HEAL_DELAY+1);
+ SetProp(P_POISON_DELAY,POISON_DELAY-1);
+ SetProp(P_FOOD_DELAY,FOOD_DELAY-2);
+ SetProp(P_ALCOHOL_DELAY,ALCOHOL_DELAY+1);
+
+ SetProp(P_MAGIC_RESISTANCE_OFFSET,
+ ([ MT_ANGRIFF : 500,
+ MT_HELLSICHT : -500,
+ MT_PSYCHO : -500 ]));
+
+ if(!(res=QueryProp(P_HANDS)) || !pointerp(res) || (sizeof(res)<3))
+ res=({" mit pelzigen Haenden",25,({DT_BLUDGEON})});
+ res[1]=25;
+ SetProp(P_HANDS,res);
+ SetProp(P_BODY,15);
+
+ /* Groesse wird nur einmal gesetzt */
+ if(!QueryProp(P_SIZE)){
+ SetProp(P_SIZE,95+random(21));
+ Set(P_SIZE,SAVE,F_MODE_AS);
+ }
+
+ /* Dito Gewicht */
+ if(!QueryProp(P_WEIGHT) || (QueryProp(P_WEIGHT) == 75000)){
+ SetProp(P_WEIGHT,50000+random(20001));
+ if(QueryProp(P_GENDER)==FEMALE)
+ SetProp(P_WEIGHT,QueryProp(P_WEIGHT)-5000);
+ Set(P_WEIGHT,SAVE,F_MODE_AS);
+ }
+ SetProp(P_DEFUEL_LIMIT_FOOD,140);
+ SetProp(P_DEFUEL_LIMIT_DRINK,50);
+ SetProp(P_DEFUEL_TIME_FOOD,850);
+ SetProp(P_DEFUEL_TIME_DRINK,450);
+ SetProp(P_DEFUEL_AMOUNT_FOOD,0.8);
+ SetProp(P_DEFUEL_AMOUNT_DRINK,0.6);
+
+}
+
+string _query_race()
+{
+ return "Hobbit";
+}
+
+string _query_real_race()
+{
+ return "Hobbit";
+}
+
+string _query_racedescr()
+{
+ return "Hobbits sind kleine Wesen, die am ehesten den Menschen aehneln.\n"+
+ "Sie zeichnen sich trotz Ihrer Groesse durch ihren Mut und Standfestigkeit "+
+ "aus.\nObwohl sie viel lieber zuhause vorm warmen Kamin sitzen, sind sie "+
+ "immer\nfuer ein Abenteuer zu haben.\n";
+}
+
+int QueryAllowSelect() { return 1; }
+
+string *_query_racestring(){
+ if (QueryProp(P_GENDER) == FEMALE)
+ return ({"Hobbitfrau","Hobbitfrau","Hobbitfrau","Hobbitfrau"});
+ return ({"Hobbit","Hobbits","Hobbit","Hobbit"});
+}
+
+string _query_default_guild(){
+ return "abenteurer";
+}
+
+void FinalSetup() {
+ if(!present("pfeifchen",this_object()))
+ clone_object("/items/pfeifchen")->move(this_object(),M_NOCHECK);
+}
+
+mixed RaceDefault(string arg)
+{
+ if (!arg)
+ return 0;
+ switch(arg)
+ {
+ case P_HANDS :
+ return ({" mit pelzigen Haenden",25,({DT_BLUDGEON}) });
+ case P_BODY :
+ return 15;
+ }
+ return base::RaceDefault(arg);
+}
diff --git a/std/shells/human.c b/std/shells/human.c
new file mode 100644
index 0000000..c18df2d
--- /dev/null
+++ b/std/shells/human.c
@@ -0,0 +1,113 @@
+// MorgenGrauen MUDlib
+//
+// shells/human.c -- Human Shell
+//
+// $Id: human.c 9022 2015-01-10 21:50:50Z Zesstra $
+
+#pragma strong_types,save_types
+
+inherit "/std/player/base";
+
+#include <properties.h>
+#include <attributes.h>
+#include <moving.h>
+#include <wizlevels.h>
+#include <health.h>
+#include <new_skills.h>
+#include <language.h>
+#include <defuel.h>
+
+
+
+void create() {
+ if (!clonep() || object_name(this_object()) == __FILE__[0..<3]) {
+ set_next_reset(-1);
+ return;
+ }
+
+ base::create();
+ SetDefaultHome("/gilden/abenteurer");
+ SetDefaultPrayRoom("/d/ebene/room/PortVain/pray_room");
+ SetProp(P_ATTRIBUTES_OFFSETS,([A_INT:1,A_STR:1,A_CON:1,A_DEX:3]));
+ SetProp(P_AVERAGE_SIZE,170);
+ SetProp(P_AVERAGE_WEIGHT,75000);
+ SetProp(P_MATERIAL_KNOWLEDGE,([MATGROUP_WOOD:20,
+ MATGROUP_METAL:20,
+ MATGROUP_ELEMENTAL:20,
+ MATGROUP_CLOTH:20]));
+
+ SetProp(P_MAX_FOOD,120);
+ SetProp(P_MAX_DRINK,120);
+ SetProp(P_MAX_ALCOHOL,120);
+
+ SetProp(P_MAGIC_RESISTANCE_OFFSET,
+ ([ MT_ANGRIFF : 500,
+ MT_ILLUSION : 700,
+ MT_BEHERRSCHUNG : 500,
+ MT_HELLSICHT : 1000,
+ MT_VERWANDLUNG : -500,
+ MT_PSYCHO : -500 ]));
+
+ // Zukuenftig 0, nicht mehr -5. Ark, 04.01.08.
+ SetProp(P_BODY,0);
+
+ /* Groesse wird nur einmal gesetzt */
+ if(!QueryProp(P_SIZE)){
+ SetProp(P_SIZE,160+random(21));
+ Set(P_SIZE,SAVE,F_MODE_AS);
+ }
+
+ /* Dito Gewicht */
+ if(!QueryProp(P_WEIGHT) || (QueryProp(P_WEIGHT) == 75000)){
+ SetProp(P_WEIGHT,65000+random(20001));
+ if(QueryProp(P_GENDER)==FEMALE)
+ SetProp(P_WEIGHT,QueryProp(P_WEIGHT)-5000);
+ Set(P_WEIGHT,SAVE,F_MODE_AS);
+ }
+ SetProp(P_DEFUEL_LIMIT_FOOD,60);
+ SetProp(P_DEFUEL_LIMIT_DRINK,50);
+ SetProp(P_DEFUEL_TIME_FOOD,500);
+ SetProp(P_DEFUEL_TIME_DRINK,245);
+ SetProp(P_DEFUEL_AMOUNT_FOOD,0.75);
+ SetProp(P_DEFUEL_AMOUNT_DRINK,0.5);
+
+}
+
+string _query_race()
+{
+ return "Mensch";
+}
+
+string _query_real_race()
+{
+ return "Mensch";
+}
+
+string *_query_racestring()
+{
+ if (QueryProp(P_GENDER)==2)
+ return ({"Menschenfrau","Menschenfrau","Menschenfrau","Menschenfrau"});
+ return ({"Mensch","Menschen","Mensch","Menschen"});
+}
+
+string _query_racedescr()
+{
+ return "Die Staerke des Menschen ist seine Vielseitigkeit.\n"+
+ "Der Mensch kann zwar nichts besonders gut - dafuer aber eigentlich alles.\n";
+}
+
+int QueryAllowSelect() { return 1; }
+
+void FinalSetup()
+{
+ // Im MG gibt fuer kleine Spieler eine Karte von Port Vain. Die gibt es
+ // woanders meist nicht.
+#if MUDNAME == "MorgenGrauen"
+ if (QueryProp(P_LEVEL)<=3 && !present("portvainkarte",this_object()))
+ clone_object("/d/ebene/obj/pv")->move(this_object(),M_NOCHECK);
+#endif
+}
+
+string _query_default_guild(){
+ return "abenteurer";
+}
diff --git a/std/shells/magier.c b/std/shells/magier.c
new file mode 100644
index 0000000..dc2a150
--- /dev/null
+++ b/std/shells/magier.c
@@ -0,0 +1,326 @@
+// MorgenGrauen MUDlib
+//
+// shells/magier.c -- magier shell
+//
+// $Id: magier.c 9231 2015-05-27 21:53:32Z Zesstra $
+
+//
+// Magiershell Basisfile
+//
+// Ueberarbeitung abgeschlossen am 18.12.2002
+//
+// Dank an Zwirch@PK, Rikus@MG, Zoran@PK, Vanion@MG
+// und viele andere, die ich vergessen habe.
+//
+// Fragen und Bughinweise an Mandragon@MG oder einen
+// Erzmagier Deiner Wahl.
+//
+// Zur Shell gehoeren ausser dieser Datei:
+// admin.c: Administrative Befehle
+// comm.c: Kommunikationsbefehle
+// fileedit.c: Befehle zum Veraendern von Dateien
+// fileview.c: Befehle zum Lesen von Dateien
+// magier_ext.c: Generelle Magierbefehle
+// moving.c: Bewegungsbefehle
+// objects.c: Erzeugen und zerstoeren von Objekten
+// parsing.c Auswertung von Pfadangaben und Wildcards
+// players.c: Befehle zur Beeinflussung von Spielern
+// todo.c: Implementation der Todoliste
+// upd.c: Der Befehl upd
+// magier.h Generelle Header-Datei
+//
+
+#pragma strict_types,save_types
+
+inherit "/std/player/base";
+inherit "/std/shells/magier/magier_ext";
+
+#include <wizlevels.h>
+#include <moving.h>
+#include <properties.h>
+#include <new_skills.h>
+#include <config.h>
+
+protected void create()
+{
+ if (!clonep() || object_name(this_object()) == __FILE__[0..<3]) {
+ set_next_reset(-1);
+ return;
+ }
+
+ base::create();
+
+ Set(P_RACE, SAVE, F_MODE);
+ Set(P_ZAP_MSG, SAVE, F_MODE);
+ Set(P_TRANK_FINDEN, SAVE, F_MODE);
+ Set(P_HANDS, SAVE, F_MODE);
+ Set(P_RACESTRING, SAVE, F_MODE);
+ SetDefaultHome("/gilden/abenteurer");
+ SetProp(P_ENEMY_DEATH_SEQUENCE,
+ ([17:"Der Tod schuettelt verstaendnislos den Kopf.\n\n",
+ 18:"Der Tod sagt: WIESO MUSSTEST DU DICH AUCH UNBEDINGT "
+ "MIT EINEM MAGIER ANLEGEN?\n\n"]));
+ SetProp(P_ATTRIBUTES_OFFSETS,([]));
+ SetProp(P_AVERAGE_SIZE,185);
+ if(!QueryProp(P_DEFAULT_GUILD)) SetProp(P_DEFAULT_GUILD,"abenteurer");
+}
+
+protected void create_super() {
+ set_next_reset(-1);
+}
+
+
+protected void heart_beat()
+{
+ mixed *en;
+
+ if (!QueryProp(P_WANTS_TO_LEARN)||((en=QueryEnemies())&&sizeof(en[0])))
+ base::heart_beat();
+ else if (!CheckTelnetKeepAlive()) {
+ // Wenn der Magier kein Telnet Keep-Alive wuenscht, kann der HB ganz
+ // abgeschaltet werden. Sonst muss er aber weiterlaufen, damit
+ // CheckTelnetKeepAlive() regelmaessig gerufen wird.
+ set_heart_beat(0);
+ }
+}
+
+
+public varargs int remove(int silent)
+{
+ string workroom;
+
+ if (IS_WIZARD(this_object()))
+ workroom = "/players/"+getuid()+"/workroom";
+ else
+ workroom = "/secure/merlin";
+ if( !environment() || object_name(environment()) != workroom )
+ catch(move(workroom, M_GO, "nach Hause"));
+ return base::remove(silent);
+}
+
+public string NotifyDestruct(object caller) {
+
+ if (previous_object() != master()
+ || object_name(this_object()) == __FILE__[..<3])
+ return 0;
+
+ // Nicht-EMs sollen keine EMs zerstoeren koennen, woraufhin auch evtl.
+ // EM-Tools rumliegen koennten.
+ if ( IS_ARCH(this_object()) && caller != this_object()
+ && getuid(caller) != ROOTID
+ && (process_call() || !ARCH_SECURITY) )
+ return "Das Zerstoeren von EMs ist ein Fehler. ;-)\n";
+
+ return ::NotifyDestruct(caller);
+}
+
+void reset()
+{
+ if (!interactive(this_object()))
+ {
+ quit();
+ if (this_object())
+ remove();
+ if (this_object())
+ destruct(this_object());
+ return;
+ }
+}
+
+// ####################
+//################# Query-Funktionen ##################
+// ####################
+
+varargs int id (string str) {
+ if (QueryProp(P_INVIS) &&
+ (!this_interactive() ||!IS_LEARNER(this_interactive())))
+ return 0;
+ return ::id(str);
+}
+
+
+static string *_query_racestring()
+{
+ if (pointerp(Query(P_RACESTRING)))
+ return Query(P_RACESTRING);
+ else
+ return
+ ({QueryProp(P_RACE),QueryProp(P_RACE),
+ QueryProp(P_RACE),QueryProp(P_RACE)});
+}
+
+
+static string _query_default_guild()
+{
+ return (Query(P_DEFAULT_GUILD)||"abenteurer");
+}
+
+
+static string _query_racedescr()
+{
+ return "Magier koennen einfach alles. Aber manche Magier koennen mehr.\n";
+}
+
+
+static string _query_race()
+{
+ if (previous_object() && previous_object()->query_login_object())
+ return 0;
+
+ return Query(P_RACE) ? Query(P_RACE) : Set(P_RACE, "Magier");
+}
+
+
+static mixed _query_localcmds()
+{
+ return
+ base::_query_localcmds()
+ +magier_ext::_query_localcmds();
+}
+
+
+static void upd_my_age()
+{
+ age=_age+absolute_hb_count()-_hbstop;
+ _age=age;
+ _hbstop=absolute_hb_count();
+ return;
+}
+
+
+static int _query_age()
+{
+ upd_my_age();
+ return age;
+}
+
+static int _set_earmuffs(int level)
+{
+ int maxl=1+query_wiz_level(this_object());
+ maxl = max(maxl,99);
+ return Set(P_EARMUFFS,min(maxl,level));
+}
+
+
+// ############################
+//#################### Interne Shell-Funktionen ####################
+// ############################
+
+int MayAddWeight(int w) { return 0;}
+int MayAddObject(object ob) { return 1; }
+
+
+static void initialize()
+{
+ magier_ext::initialize();
+ return;
+}
+
+
+static void FinalSetup()
+{
+ SetProp(P_CURRENTDIR,"/players/"+getuid());
+ initialize();
+ if (IS_LEARNER(this_player())) cat("/etc/WIZNEWS");
+ _age=age;
+ _hbstop=absolute_hb_count();
+ return;
+}
+
+
+void save_me(int i)
+{
+ upd_my_age();
+ base::save_me(i);
+ return;
+}
+
+
+varargs void Reconnect(int silent,string my_ip)
+{
+ base::Reconnect(silent,my_ip);
+ magier_ext::reconnect();
+ return;
+}
+
+
+void notify_player_change(string who, int rein, int invis)
+{
+ string *list,name;
+ mixed mlist;
+ int vis_change;
+
+ if (invis) name="("+who+")";
+ else name=who;
+
+ if(query_verb() && (query_verb()=="vis" || query_verb()=="invis"))
+ vis_change=1;
+
+ if (Query(P_INFORMME) && !vis_change)
+ {
+ if (rein)
+ tell_object(this_object(),
+ sprintf("%s ist gerade ins "MUDNAME" gekommen.\n",name));
+ else
+ tell_object(this_object(),
+ sprintf("%s hat gerade das "MUDNAME" verlassen.\n",name));
+ }
+
+ if(Query(P_WAITFOR_FLAGS) & (0x01))return ;
+
+ if (pointerp(list=Query(P_WAITFOR))&&sizeof(list))
+ if (member(list,who)!=-1)
+ delayed_write(
+ ({
+ ({sprintf("%s%s I S T J E T Z T %s !!!\n",
+ (QueryProp(P_VISUALBELL) ? "" : sprintf("%c",7)),
+ name,
+ (vis_change?
+ (rein?"S I C H T B A R":"U N S I C H T B A R"):
+ (rein?"D A":"N I C H T M E H R D A"))),
+ 0})
+ }));
+
+ if (rein && (sizeof(mlist=QueryProp(P_WAITFOR_REASON))) &&
+ (mappingp(mlist)) && (mlist[who]))
+ Show_WaitFor_Reason(who,invis);
+ return;
+}
+
+mixed modify_command(string str) {
+ if (previous_object() &&
+ (previous_object()!=this_object() || process_call()) )
+ {
+ if (IS_ARCH(this_object()))
+ tell_object(this_object(),
+ sprintf("Illegal modify_command(%s) from %O\n",
+ str, previous_object()));
+ return 0;
+ }
+ //////////////////////////////////////////////////////////////////////
+ // Magier-Escape-Kommandos werden behandelt
+ if (str=="\\ESCAPE" && IS_LORD(this_object()))
+ {
+ __set_environment(this_object(),"/room/void");
+ environment()->init();
+ printf("You escaped.\n");
+ return "";
+ }
+ if (str[0..2]=="\\\\\\" && IS_LORD(this_object()))
+ {
+ str = _return_args(str);
+ string* input = explode(str[3..]," ");
+ string verb = input[0];
+ if (verb && verb!="")
+ {
+ string cmd = implode(input[1..]," ");
+ if (!__auswerten(cmd,verb))
+ SoulComm(cmd,verb);
+ }
+ return 1;
+ }
+ //////////////////////////////////////////////////////////////////////
+
+ return ::modify_command(str);
+}
+
diff --git a/std/shells/magier/admin.c b/std/shells/magier/admin.c
new file mode 100644
index 0000000..a41d1b7
--- /dev/null
+++ b/std/shells/magier/admin.c
@@ -0,0 +1,428 @@
+// MorgenGrauen MUDlib
+//
+// admin.c
+//
+// $Id: admin.c 8755 2014-04-26 13:13:40Z Zesstra $
+#pragma strict_types
+#pragma save_types
+#pragma range_check
+#pragma no_clone
+#pragma pedantic
+
+#include <udp.h>
+#include <wizlevels.h>
+#include <input_to.h>
+
+#define NEED_PROTOTYPES
+#include <magier.h>
+#include <player.h>
+
+inherit "/std/util/cidr";
+
+mixed _query_localcmds()
+{
+ return ({({"udpq","_udpq",0,LEARNER_LVL}),
+ ({"shutdown","shut_down_game",0,ARCH_LVL}),
+ ({"addmaster","_addmaster",0,GOD_LVL}),
+ ({"removemaster","_removemaster",0,GOD_LVL}),
+ ({"addguildmaster", "_addguildmaster", 0, GOD_LVL}),
+ ({"removeguildmaster", "_removeguildmaster", 0, GOD_LVL}),
+ ({"suender","sinners",0,WIZARD_LVL}),
+ ({"banish","banish", 0, WIZARD_LVL}),
+ ({"mbanish","mbanish", 0, WIZARD_LVL}),
+ ({"tbanish","tbanish", 0, WIZARD_LVL}),
+ ({"sbanish","sbanish", 0, WIZARD_LVL})});
+}
+
+static int _udpq(string str)
+{
+ string ret, mud, type;
+
+ if (!(str=_unparsed_args()) || str=="" || sscanf(str,"%s %s",mud,type)<2)
+ {
+ write("Syntax: udpq mud type\n");
+ return 1;
+ }
+ if (member(({"commands","email","hosts","inetd","list","mud_port","time",
+ "version"}),type)==-1)
+ write("TYPEs: commands, email, hosts, inetd, list, mud_port, time, version\n");
+ if (ret=(string)INETD->_send_udp(mud,([SENDER:getuid(), REQUEST:QUERY, DATA:type]),1))
+ write(ret);
+ else
+ write("Anfrage abgeschickt.\n");
+ return 1;
+}
+
+static int shut_down_game(string str)
+{
+ if (!IS_ARCH(this_object()) || this_object()!=this_interactive())
+ return 0;
+ _notify_fail("Du musst einen Grund dafuer angeben.\n");
+ if (!str) return 0;
+ write( "Direkter shutdown mit Grund \""+str+"\"?\n" );
+ input_to("shut_down_game_2",INPUT_PROMPT, "(ja/nein) :", str);
+ return 1;
+}
+
+static int shut_down_game_2(string arg,string str)
+{
+ if (!IS_ARCH(this_object()) || this_object()!=this_interactive())
+ return 0;
+ if( arg!="ja" ) {
+ write( "Shutdown abgebrochen.\n" );
+ } else {
+ shutdown(str);
+ }
+ return 1;
+}
+
+
+static int _addmaster(string str)
+{
+ string master, domain;
+
+ if (!GOD_SECURITY)
+ {
+ write("Das darfst Du nicht!\n");
+ return 1;
+ }
+ _notify_fail("Syntax: addmaster <user> <domain>\n");
+ if (!str) return 0;
+ if (sscanf(str,"%s %s",master,domain)!=2) return 0;
+ if (!master || !domain) return 0;
+ if (!"/secure/master"->add_domain_master(master,domain))
+ write("Hat nicht funktioniert.\n");
+ else
+ write("Ok.\n");
+ return 1;
+}
+
+static int _removemaster(string str)
+{
+ string master, domain;
+
+ if (!GOD_SECURITY)
+ {
+ write("Das darfst Du nicht!\n");
+ return 1;
+ }
+ _notify_fail("Syntax: removemaster <user> <domain>\n");
+ if (!str) return 0;
+ if (sscanf(str,"%s %s",master,domain)!=2) return 0;
+ if (!master || !domain) return 0;
+ if (!"/secure/master"->remove_domain_master(master,domain))
+ write("Hat nicht funktioniert.\n");
+ else
+ write("Ok.\n");
+ return 1;
+}
+
+static int _addguildmaster(string str)
+{
+ string master, guild;
+
+ if (!GOD_SECURITY)
+ {
+ write ("Das darfst Du nicht!\n");
+ return 1;
+ }
+
+ _notify_fail("Synatx: addguildmaster <user> <guild>\n");
+ if (!str) return 0;
+ if (sscanf(str, "%s %s", master, guild)!=2) return 0;
+ if (!master || !guild) return 0;
+ if (!"/secure/master"->add_guild_master(master,guild))
+ write("Hat nicht funktioniert.\n");
+ else
+ write ("Ok.\n");
+ return 1;
+}
+
+static int _removeguildmaster(string str)
+{
+ string master, guild;
+
+ if (!GOD_SECURITY)
+ {
+ write ("Das darfst Du nicht!\n");
+ return 1;
+ }
+ _notify_fail("Syntax: removeguildmaster <user> <guild>\n");
+ if (!str) return 0;
+ if (sscanf(str, "%s %s", master, guild)!=2) return 0;
+ if (!master || !guild) return 0;
+ if (!"/secure/master"->remove_guild_master(master,guild))
+ write("Hat nicht funktioniert.\n");
+ else
+ write("Ok.\n");
+ return 1;
+}
+
+static int sinners(string arg)
+{ string *parts;
+ int i;
+
+ if ( !IS_DEPUTY(this_object()) )
+ return 0;
+
+ arg=_unparsed_args()||arg;
+
+ notify_fail(
+ "Syntax: suender ? => Liste aller Eingetragenen\n"+
+ " suender <name> => Eintraege lesen\n"+
+ " suender +<name> <text> => Eintrag hinzufuegen\n"+
+ " suender -<name> <nr> => Eintrag loeschen\n"+
+ " suender ! => Alle Eintraege dumpen\n"+
+ " suender * => Alle Eintraege anzeigen\n");
+
+ if ( !stringp(arg) || (sizeof(arg)<1) )
+ return 0;
+
+ if ( arg=="?" )
+ {
+ write(call_other("/secure/sinmaster","ListSinners"));
+ return 1;
+ }
+ if ( arg=="!" )
+ {
+ write(call_other("/secure/sinmaster","Dump"));
+ return 1;
+ }
+ if ( arg=="*" )
+ {
+ More((string)call_other("/secure/sinmaster","Dump",1));
+ return 1;
+ }
+
+ if ( (i=sizeof(parts=explode(arg," ")))<1 )
+ return 0;
+
+ if ( parts[0][0..0]=="-" )
+ {
+ if ( i<2 )
+ return 0;
+ write(call_other("/secure/sinmaster","RemoveSin",
+ lowerstring(parts[0][1..]),
+ to_int(parts[1])));
+ }
+ else if ( parts[0][0..0]=="+" )
+ {
+ if ( i<2 )
+ return 0;
+ write(call_other("/secure/sinmaster","AddSin",
+ lowerstring(parts[0][1..]),
+ implode(parts[1..]," ")));
+ }
+ else
+ {
+ if ( i>1 )
+ return 0;
+ write(call_other("/secure/sinmaster","ListSins",
+ lowerstring(parts[0])));
+ }
+ return 1;
+}
+
+static int banish(string str)
+{
+ string grund, name;
+ int force;
+
+ if ( !LORD_SECURITY && !IS_DEPUTY(secure_euid()) )
+ return 0;
+
+ if ( !str || !stringp(str) || !sizeof(str) ) {
+ write("Syntax: banish [-f] <name> [<grund>]\n");
+ return 1;
+ }
+
+ str = _unparsed_args();
+
+ if ( explode(str, " ")[0] == "-f" ){
+ str = implode( explode(str, " ")[1..], " " );
+ force = 1;
+ }
+
+ if ( sscanf( str, "%s %s", name, grund ) != 2 )
+ name=str;
+
+ if ( !name || !sizeof(name) ){
+ write("Syntax: banish [-f] <name> [<grund>]\n");
+ return 1;
+ }
+
+ name=lower_case(name);
+ "/secure/master"->BanishName( name, grund, force );
+ return 1;
+}
+
+static int mbanish(string str)
+{
+ string grund, name, *namen, txt, *dummy;
+ mapping list;
+ int i;
+
+ if ( !IS_DEPUTY(secure_euid()) )
+ return 0;
+
+ _notify_fail( "Syntax: mbanish <name> [<grund>]\n" );
+
+ if ( !str || !stringp(str) || !sizeof(str) ){
+ if ( !mappingp(list = (mapping)"/secure/merlin"->MBanishList()) ||
+ !(i = sizeof(list)) ){
+ write( "Momentan ist kein Spieler auf der mbanish-Liste.\n" );
+ return 1;
+ }
+
+ txt = " Name | gebanisht von | Grund\n" +
+ "=============================================================" +
+ "==================\n";
+
+ namen = sort_array( m_indices(list), #'</*'*/ );
+
+ for ( ; i--; ){
+ dummy = explode( break_string( list[namen[i],0] ||
+ "-- keine Begruendung --", 45 ),
+ "\n" ) - ({""});
+
+ txt += sprintf( " %-11s | %-11s | %s\n",
+ capitalize( namen[i] ),
+ capitalize( list[namen[i],1] || "" ),
+ capitalize( implode( dummy, "\n |"
+ " | " ) ) );
+ }
+
+ More(txt);
+
+ return 1;
+ }
+
+ if ( sscanf( str, "%s %s", name, grund ) !=2 )
+ name = str;
+
+ if ( !name || !sizeof(name) )
+ return 0;
+
+ name = lower_case(name);
+
+ if ( !grund || !stringp(grund) || lower_case(grund) != "loeschen" ){
+ "/secure/merlin"->MBanishInsert( name, grund, this_interactive() );
+ write( "Du setzt "+capitalize(name)+" auf die MBanish-Liste.\n" );
+ }
+ else{
+ if ( !ARCH_SECURITY ){
+ write( "Das duerfen nur Erzmagier.\n" );
+ return 1;
+ }
+ "/secure/merlin"->MBanishDelete( name );
+ write( "Du loescht "+capitalize(name)+" von der MBanish-Liste.\n" );
+ }
+
+ return 1;
+}
+
+
+static int tbanish( string str )
+{
+ string name;
+ int days;
+
+ if ( !IS_DEPUTY(secure_euid()) )
+ return 0;
+
+ _notify_fail("Syntax: tbanish <name> <tage>\n");
+
+ if ( !str || !stringp(str) || !sizeof(str) )
+ return 0;
+
+ if ( sscanf(str,"%s %d",name,days) != 2 )
+ return 0;
+
+ if ( !name || !sizeof(name) )
+ return 0;
+
+ name = lower_case(name);
+
+ if ( !"/secure/master"->TBanishName( name, days ) )
+ return 1;
+
+ if ( !days )
+ write( "Okay, keine Spielpause fuer "+capitalize(name)+" mehr.\n" );
+ else
+ write( "Du verpasst "+capitalize(name)+" eine Spielpause fuer "+
+ (days>0 ? days+" Tage" : "laaaange Zeit")+".\n" );
+ return 1;
+}
+
+static int sbanish( string str )
+{
+ string ip;
+ int days;
+ mapping sites;
+
+ // Mindestens L26 fuer diesen Befehl
+ if ( secure_level() <= DOMAINMEMBER_LVL )
+ return 0;
+
+ if ( !str || !stringp(str) || !sizeof(str) ){
+ if ( !sizeof(sites = (mapping)MASTER->SiteBanish( 0, 0 )) ){
+ write( "Es sind zur Zeit keine Adressen gesperrt!\n" );
+ return 1;
+ }
+
+ ip = " Adresse | gesperrt bis | gesperrt "
+ + "durch\n========================================================"
+ + "==============\n";
+
+ int *keys = sort_array( m_indices(sites), #'</*'*/ );
+
+ foreach(int key : keys) {
+ ip += sprintf( " %:15-s | %:27-s | %-s\n",
+ IPv4_int2addr(key),
+ sites[key] > 0 ? dtime(sites[key]) :
+ "St. Nimmerleinstag",
+ capitalize(sites[key, 1]) );
+ }
+ write( ip + "\n" );
+ return 1;
+ }
+
+ _notify_fail("Syntax: sbanish <numerische ip> <tage>\n");
+
+ if ( sscanf( this_player()->_unparsed_args(), "%s %d", ip, days ) != 2 )
+ return 0;
+
+ if ( !ip || !sizeof(ip) )
+ return 0;
+
+// _notify_fail( "Ungueltiges Adress-Format!\n" );
+
+ if ( !days ){
+ int res=(int)MASTER->SiteBanish(ip, 0);
+ if ( res == 1 )
+ printf( "Die Adresse '%s' ist jetzt nicht mehr gesperrt.\n",
+ ip );
+ else if ( res == 0 )
+ printf( "Die Adresse '%s' war gar nicht gesperrt!\n",
+ ip );
+ else
+ printf( "Du darfst nur eigene Sperrungen wieder aufheben!\n" );
+ }
+ else {
+ int res;
+ if ( days != 1 && !IS_DEPUTY(secure_euid()) )
+ write( "Du darfst Adressen nur fuer einen Tag sperren!\n" );
+ else if ( (res = (int)MASTER->SiteBanish(ip, days)) == 1 )
+ printf( "Die Adresse '%s' ist jetzt fuer %s gesperrt.\n",
+ ip, (days > 1 ? sprintf( "%d Tage", days ) :
+ (days > 0 ? "einen Tag" : "immer")) );
+ else if ( res == -1 )
+ write( "Du darfst " + (LORD_SECURITY ? "255 IP-Adressen"
+ : "nur einzelne IP-Adressen") + " sperren!\n" );
+ else if ( res == -2 )
+ write( "Du hast schon genug Adressen gesperrt!\n" );
+ }
+
+ return 1;
+}
+
diff --git a/std/shells/magier/comm.c b/std/shells/magier/comm.c
new file mode 100644
index 0000000..0cbd266
--- /dev/null
+++ b/std/shells/magier/comm.c
@@ -0,0 +1,149 @@
+// MorgenGrauen MUDlib
+//
+// comm.c
+//
+// $Id: comm.c 8755 2014-04-26 13:13:40Z Zesstra $
+#pragma strict_types
+#pragma save_types
+#pragma range_check
+#pragma no_clone
+#pragma pedantic
+
+#include <wizlevels.h>
+#include <magier.h>
+#define NEED_PROTOTYPES
+#include <thing/properties.h>
+#include <thing/description.h>
+#include <player.h>
+#include <properties.h>
+
+
+// ###########
+//############################ ECHOALL ################################
+// ###########
+
+static int _echoall(string str)
+{
+ if (!(str=_unparsed_args()))
+ return USAGE("echoall <text>\n");
+ str=break_string(str);
+ shout(str);
+ printf(str);
+ return 1;
+}
+
+// ##########
+//############################ ECHOTO #################################
+// ##########
+
+static int _echoto(string str)
+{
+ object ob;
+ string who;
+ string msg;
+
+ if (!(str=_unparsed_args())||sscanf(str, "%s %s", who, msg) != 2)
+ return USAGE("echoto <spieler> <text>\n");
+ ob = find_player(lower_case(who));
+ if (!ob)
+ {
+ printf("echoto: Es ist kein Spieler '%s' eingeloggt.\n",who);
+ return 1;
+ }
+ msg=break_string(msg,78);
+ tell_object(ob,msg);
+ printf("%s->%s",ob->Name(WEN),msg);
+ return 1;
+}
+
+// #########
+//############################ MECHO ##################################
+// #########
+
+static int _mecho(string str) {
+ object *who;
+ int i;
+
+ if (!sizeof(str=_unparsed_args()))
+ return USAGE("mecho <text>\n");
+ who=users();
+ i=sizeof(who);
+ while(i--)if (IS_LEARNER(who[i]))
+ tell_object(who[i], break_string(str,78));
+ return 1;
+}
+
+// ########
+//############################# PING ##################################
+// ########
+
+static int _ping(string str)
+{
+ object pl;
+
+ if (!sizeof(str))
+ return USAGE("ping <spielername>\n");
+ if (!(pl=find_player(lower_case(str))))
+ return
+ _notify_fail(sprintf("ping: Spieler %s nicht gefunden.\n",
+ capitalize(str))),0;
+ tell_object(pl,sprintf("%s pingt Dich an.\a\n",capitalize(getuid())));
+ return printf("PINGGGGGGG! DAS sollte %s auf Dich aufmerksam "
+ "gemacht haben.\n",capitalize(getuid(pl))),1;
+}
+
+// ##########
+//############################ OROPAX #################################
+// ##########
+
+int _oropax(string cmdline)
+{
+ int level,old,new;
+
+ cmdline=_unparsed_args();
+ old=QueryProp(P_EARMUFFS);
+ if (!sizeof(cmdline)||cmdline=="0")
+ {
+ if (old)
+ {
+ printf("Du nimmst das Oropax aus Deinen Ohren und hoerst "
+ "wieder allen anderen zu.\n");
+ SetProp(P_EARMUFFS, 0);
+ }
+ else
+ printf("Du hast doch gar kein Oropax in den Ohren.\n");
+ return 1;
+ }
+ if (sscanf(cmdline, "%d", level) == 0 || level < 1)
+ return USAGE("oropax [<magierlevel>]\n");
+ if ((new=SetProp(P_EARMUFFS, level))==level)
+ {
+ if (new==old)
+ return printf("Du hattest Deine Oropaxmenge schon auf Magierlevel "
+ "%d angepasst.\n",level),1;
+ if (new>old)
+ return printf("Du stopfst Dir soviel Oropax in die Ohren, dass "
+ "Du nur noch %s ab\nLevel %d hoerst.\n",
+ level>=LEARNER_LVL?"Magier":"Seher",level),1;
+ return printf("Du nimmst soviel Oropax aus den Ohren, dass Du ab "
+ "sofort wieder %s ab\nLevel %d verstehst.\n",
+ level>=LEARNER_LVL?"Magier":"Seher",level),1;
+ }
+ return printf("Du stopfst und stopfst, bis Dir das Oropax wieder zur "
+ "Nase herauskommt.\nLeider musst Du damit Magier ab Level "
+ "%d weiterhin hoeren.\n",new),1;
+}
+
+// ###################
+//########################## INITIALISIERUNG #############################
+// ###################
+
+static mixed _query_localcmds()
+{
+ return
+ ({({"oropax","_oropax",0,LEARNER_LVL}),
+ ({"echoto","_echoto",0,LEARNER_LVL}),
+ ({"echoall","_echoall",0,LEARNER_LVL}),
+ ({"mecho","_mecho",0,LEARNER_LVL}),
+ ({"ping","_ping",0,LEARNER_LVL})});
+}
diff --git a/std/shells/magier/fileedit.c b/std/shells/magier/fileedit.c
new file mode 100644
index 0000000..f4df0a5
--- /dev/null
+++ b/std/shells/magier/fileedit.c
@@ -0,0 +1,718 @@
+// MorgenGrauen MUDlib
+//
+//fileedit.c
+//
+// $Id: fileedit.c 9142 2015-02-04 22:17:29Z Zesstra $
+#pragma strict_types
+#pragma save_types
+//#pragma range_check
+#pragma no_clone
+#pragma pedantic
+
+#include <wizlevels.h>
+#include <input_to.h>
+
+#define NEED_PROTOTYPES
+#include <magier.h>
+#include <player.h>
+#include <files.h>
+
+// ###################
+//######################### INITIALISIERUNG #############################
+// ###################
+
+mixed _query_localcmds()
+{
+ return ({ ({"cp","_cp",0,WIZARD_LVL}),
+ ({"mv","_cp",0,WIZARD_LVL}),
+ ({"rm","_rm",0,WIZARD_LVL}),
+ ({"rmdir","_rmdir",0,WIZARD_LVL}),
+ ({"mkdir","_mkdir",0,WIZARD_LVL}),
+ ({"ed","_ed",0,WIZARD_LVL})});
+}
+
+// ######
+//################################ ED ###################################
+// ######
+
+
+//
+// _ed_file: Mehrere Files hintereinander editieren
+//
+
+private nosave string *_ed_cache;
+
+private void _ed_file()
+{
+ if (!sizeof(_ed_cache)) return;
+ printf("ed: Naechste Datei: %s\n",_ed_cache[0]);
+ ed(_ed_cache[0],"_ed_file");
+ _ed_cache=_ed_cache[1..];
+ return;
+}
+
+#if __VERSION__ < "3.2.9"
+private mixed _ed_size_filter(mixed *arg)
+{
+ if (arg[FILESIZE]>=-1) return arg[FULLNAME];
+ printf("%s ist ein Verzeichnis.\n",arg[FULLNAME]);
+ return 0;
+}
+#endif
+
+//
+// _more: Dateien anzeigen
+// cmdline: Kommandozeile
+//
+
+static int _ed(string cmdline)
+{
+ mixed *args,*args2;
+ int flags,i,arg_size;
+ cmdline=_unparsed_args();
+ args=parseargs(cmdline,&flags,"",1);
+ if (flags==-1||!(arg_size=sizeof(args)))
+ return USAGE("ed <datei> [<datei2>..]");
+ while(arg_size--)
+ {
+ if (sizeof(args2=file_list(args[arg_size..arg_size],MODE_ED,0,"/")))
+ args[arg_size..arg_size]=args2;
+ else
+ args[arg_size]=({ "" , -1, 0 , (string)
+ call_other(master(),"_get_path",args[arg_size],
+ getuid())});
+ }
+#if __VERSION__ < "3.2.9"
+ args=map(args,#'_ed_size_filter)-({0});
+#else
+ args=map(args,(:
+ if ($1[FILESIZE]>=-1) return $1[FULLNAME];
+ printf("%s ist ein Verzeichnis.\n",$1[FULLNAME]);
+ return 0; :))-({0});
+#endif
+ if (flags==-1||!sizeof(args)) return USAGE("ed <datei> [<datei2>..]");
+ _ed_cache=args;
+ _ed_file();
+ return 1;
+}
+
+
+// ###########
+//############################## CP & MV ################################
+// ###########
+
+static void _cp_ask_copy(mixed *filedata,int dummy, int flags);
+static void _cp_ask_overwrite(mixed *filedata, int mode, int flags);
+static void _mv_ask_overwrite(mixed *filedata, int mode, int flags);
+
+static mixed cp_file(mixed filedata,int move,int flags, mixed *do_delete)
+{
+ string source,dest;
+ source=(string)filedata[FULLNAME];
+ dest=(string)filedata[DESTNAME];
+ if (source==dest) return ERROR(SAME_FILE,source,RET_FAIL);
+ if (!MAY_READ(source)) return ERROR(NO_READ,source,RET_JUMP);
+ if (!MAY_WRITE(dest)) return ERROR(NO_WRITE,dest,RET_JUMP);
+ if (filedata[FILESIZE]==-1) return ERROR(DOESNT_EXIST,source,RET_JUMP);
+ if (filedata[FILESIZE]==-2) // Quelle ist Verzeichnis
+ {
+ switch(file_size(dest))
+ {
+ case -1:
+ if (move)
+ {
+ if (rename(source,dest)) return ERROR(NO_CREATE_DIR,dest,RET_JUMP);
+ if (flags&CP_V) printf(FILE_MOVED,source);
+ return RET_JUMP;
+ }
+ if (!mkdir(dest)) return ERROR(NO_CREATE_DIR,dest,RET_JUMP);
+ if (flags&CP_V) printf(DIR_CREATED,dest);
+ case -2:
+ if (!move) return RET_OK;
+ if (filedata[SUBDIRSIZE]>0) return RET_DELETE;
+ if (!rmdir(source)) return ERROR(NO_DELETE,source,RET_FAIL);
+ if (flags&MV_V) printf("mv: %s: Quellverzeichnis wurde "
+ "geloescht.\n",source);
+ return RET_OK;
+ default: return ERROR(NO_DIRS,dest,RET_JUMP);
+ }
+ }
+ switch(file_size(dest))
+ {
+ case -2: return ERROR(DEST_IS_DIR,dest,RET_FAIL);
+ default:
+ if (flags&CP_F)
+ {
+ if (!rm(dest)) return ERROR(DEST_NO_DELETE,dest,RET_FAIL);
+ if (flags&CP_V) printf(FILE_DELETED,dest);
+ }
+ else
+ {
+ if (move) return #'_mv_ask_overwrite;
+ else return #'_cp_ask_overwrite;
+ }
+ case -1:
+ if (move)
+ {
+ if (rename(source,dest)) return ERROR(NO_MOVE,source,RET_FAIL);
+ if (flags&CP_V) printf(FILE_MOVED,source);
+ return RET_OK;
+ }
+ if (copy_file(source,dest)) return ERROR(NO_COPY,source,RET_FAIL);
+ if (flags&CP_V) printf(FILE_COPIED,source);
+ return RET_OK;
+ }
+ return 0; // not-reached
+}
+
+static void _cp_ask_overwrite2(string input, mixed *filedata,
+ int interactive,int flags,int move)
+{
+ if (!sizeof(input)) input=" ";
+ input=lower_case(input);
+ switch(input[0])
+ {
+ case 'q':
+ printf("%s abgebrochen!\n",move?"Bewegen":"Kopieren");
+ return;
+ case 'a':
+ flags|=CP_F;
+ if (!(flags&CP_I))
+ {
+ asynchron(filedata,#'cp_file,move,flags,0);
+ return;
+ }
+ case 'y':
+ case 'j':
+ if (!rm(filedata[0][DESTNAME]))
+ printf(DEST_NO_DELETE "Uebergehe Datei...\n",filedata[0][DESTNAME]);
+ else
+ {
+ if (flags&CP_V) printf(FILE_DELETED,filedata[0][DESTNAME]);
+ if (move)
+ {
+ if (rename(filedata[0][FULLNAME],filedata[0][DESTNAME]))
+ printf(NO_MOVE "Uebergehe Datei...\n",filedata[0][FULLNAME]);
+ }
+ else
+ {
+ if (copy_file(filedata[0][FULLNAME],filedata[0][DESTNAME]))
+ printf(NO_COPY "Uebergehe Datei...\n",filedata[0][FULLNAME]);
+ }
+ }
+ case 'n':
+ if (flags&CP_I)
+ _cp_ask_copy(filedata[1+filedata[0][SUBDIRSIZE]..],move,flags);
+ else
+ asynchron(filedata[1+filedata[0][SUBDIRSIZE]..],
+ #'cp_file,move,flags,0);
+ return;
+ default:
+ printf("Kommando nicht verstanden.\n");
+ _cp_ask_overwrite(filedata,interactive,flags);
+ return;
+ }
+
+}
+
+static void _cp_ask_overwrite(mixed *filedata, int interactive, int flags)
+{
+ printf("Die Datei '%s' existiert schon.\n",
+ filedata[0][DESTNAME]);
+ input_to("_cp_ask_overwrite2",INPUT_PROMPT,"Ueberschreiben? (j,n,a,q): ",
+ filedata,interactive,flags,0);
+ return;
+}
+
+static void _mv_ask_overwrite(mixed *filedata, int interactive, int flags)
+{
+ printf("Die Datei '%s' existiert schon.",
+ filedata[0][DESTNAME]);
+ input_to("_cp_ask_overwrite2",INPUT_PROMPT,"Ueberschreiben? (j,n,a,q): ",
+ filedata,interactive,flags,1);
+ return;
+}
+
+static void _cp_ask_copy2(string input,mixed *filedata,int mode,
+ int flags,int move)
+{
+ if (!sizeof(input)) input=" ";
+ input=lower_case(input);
+ switch(input[0])
+ {
+ case 'y':
+ case 'j':
+ if (mode==1)
+ {
+ if (!(flags&CP_F))
+ {
+ if (move) _mv_ask_overwrite(filedata,1,flags);
+ else _cp_ask_overwrite(filedata,1,flags);
+ return;
+ }
+ if (!rm(filedata[0][DESTNAME]))
+ {
+ printf(DEST_NO_DELETE "Uebergehe Datei...\n",
+ filedata[0][DESTNAME]);
+ _cp_ask_copy(filedata[1..],move,flags);
+ return;
+ }
+ if (flags&CP_V) printf(FILE_DELETED,filedata[0][DESTNAME]);
+ }
+ if (mode<2)
+ {
+ if (move) rename(filedata[0][FULLNAME],filedata[0][DESTNAME]);
+ else copy_file(filedata[0][FULLNAME],filedata[0][DESTNAME]);
+ _cp_ask_copy(filedata[1..],move,flags);
+ return;
+ }
+ if (mode==2)
+ {
+ if (move)
+ {
+ if (rename(filedata[0][FULLNAME],filedata[0][DESTNAME]))
+ printf(NO_MOVE "Uebergehe Verzeichnis...\n",
+ filedata[0][FULLNAME]);
+ _cp_ask_copy(filedata[1+filedata[0][SUBDIRSIZE]..],move,flags);
+ return;
+ }
+ if (mkdir(filedata[0][DESTNAME]))
+ {
+ _cp_ask_copy(filedata[1..],0,flags);
+ return;
+ }
+ printf(NO_CREATE_DIR "Uebergehe Verzeichnis...\n",
+ filedata[0][DESTNAME]);
+ }
+ case 'n':
+ _cp_ask_copy(filedata[(1+filedata[0][SUBDIRSIZE])..],0,flags);
+ return;
+ case 'q':
+ printf("Kopieren abgebrochen!\n");
+ return;
+ case 'a':
+ flags&=~CP_I;
+ asynchron(filedata,#'cp_file,move,flags,0);
+ return;
+ default:
+ printf("Kommando nicht verstanden.\n");
+ _cp_ask_copy(filedata,0,flags);
+ return;
+ }
+}
+
+static void _cp_ask_copy(mixed *filedata,int move, int flags)
+{
+ mixed data;
+ string dest,source;
+ int delete_subs,jump;
+
+ if(!sizeof(filedata))
+ {
+ printf("%s: abgeschlossen.\n",move?"mv":"cp");
+ return;
+ }
+ dest=filedata[0][DESTNAME];
+ source=filedata[0][FULLNAME];
+ switch(0) // break wirkt damit wie ein goto end_of_switch
+ {
+ default:
+ case 0: // Sinnlos, aber er compiliert sonst nicht :(
+ jump=filedata[0][SUBDIRSIZE];
+ if (source==dest)
+ {
+ printf(SAME_FILE,source);
+ break;
+ }
+ if (!MAY_READ(source))
+ {
+ printf(NO_READ,source);
+ break;
+ }
+ if (!MAY_WRITE(dest))
+ {
+ printf(NO_WRITE,dest);
+ jump=0;
+ break;
+ }
+ if (filedata[0][FILESIZE]==-1)
+ {
+ printf(DOESNT_EXIST,source);
+ break;
+ }
+ if (filedata[0][FILESIZE]==-2) // Quelle ist Verzeichnis
+ {
+ if (file_size(dest)>-1)
+ {
+ printf(NO_DIRS,dest);
+ break;
+ }
+ if (file_size(dest)==-2)
+ {
+ jump=0;
+ break;
+ }
+ printf("Verzeichnis '%s' %s?\n",source,
+ move?"bewegen":"kopieren");
+ input_to("_cp_ask_copy2",INPUT_PROMPT, "(j,n,a,q) ",
+ filedata,2,flags,move);
+ return;
+ }
+ if (file_size(dest)==-2)
+ {
+ printf(DEST_IS_DIR,dest);
+ break;
+ }
+ printf("'%s' %s?\n",source,move?"bewegen":"kopieren");
+ input_to("_cp_ask_copy2",INPUT_PROMPT, "(j,n,a,q) ",
+ filedata,(file_size(dest)!=-1),flags,move);
+ return;
+ }
+ _cp_ask_copy(filedata[1+jump..],move,flags);
+ return;
+}
+
+
+static int _cp(string cmdline)
+{
+ mixed *args;
+ int flags;
+ string mask;
+ string dest,*dest2;
+ cmdline=_unparsed_args();
+ args=parseargs(cmdline,&flags,CP_OPTS,0);
+ if (flags==-1||!sizeof(args))
+ return USAGE(query_verb()+" [-" CP_OPTS
+ "] <datei/verz> [<datei2/verz2> ... ] <ziel> [<maske>]");
+ if (flags&CP_M)
+ {
+ mask=args[<1];
+ args=args[0..<2];
+ }
+ if (!dest=to_filename(args[<1]))
+ return USAGE(query_verb()+" [-" CP_OPTS
+ "] <datei/verz> [<datei2/verz2> ... ] <ziel> [<maske>]");
+ if (file_size(dest)==-1)
+ {
+ dest2=explode(dest,"/");
+ if (file_size(implode(dest2[0..<2],"/"))==-2)
+ {
+ if (dest2[<1]=="*")
+ dest=implode(dest2[0..<2],"/");
+ else
+ if (member(dest2[<1],'*')>-1||
+ member(dest2[<1],'?')>-1)
+ return notify_fail(
+ sprintf("%s: Keine * und ? im Zielnamen erlaubt.\n",query_verb())),0;
+ }
+ else
+ return notify_fail(
+ sprintf("%s: Der angegebene Zielpfad existiert nicht.\n",
+ query_verb())),0;
+ }
+ args=args[0..<2];
+ if (file_size(dest)!=-2&&sizeof(args)>1)
+ return notify_fail(
+ sprintf("%s: Bei mehreren Quellen muss das Ziel ein Verzeichnis "
+ "sein.\n",query_verb())),0;
+ if (!sizeof(args=map(args,#'to_filename)-({0})))
+ return USAGE(query_verb()+" [-" CP_OPTS
+ "] <datei/verz> [<datei2/verz2> ... ] <ziel> [<maske>]");
+ // DEBUG("DEST: " + dest + " : FLAGS: " + flags);
+ args=file_list(args,MODE_CP,(flags&CP_R),dest+"/",mask);
+ if (!sizeof(args))
+ return notify_fail(sprintf("%s: Keine passenden Dateien gefunden.\n",
+ query_verb())),0;
+
+ if (sizeof(args)>1&&(args[0][FILESIZE]>=0)&&file_size(dest)!=-2)
+ return notify_fail(
+ sprintf("%s: Bei mehreren Quellen muss das Ziel ein Verzeichnis "
+ "sein.\n",query_verb())),0;
+ if (sizeof(args)==1&&file_size(dest)!=-2)
+ args[0][DESTNAME]=dest;
+ if (!(flags&CP_I))
+ {
+ asynchron(args,#'cp_file,(query_verb()=="mv"),flags,0);
+ return 1;
+ }
+ if (query_verb()=="cp")
+ _cp_ask_copy(args,0,flags);
+ else
+ _cp_ask_copy(args,1,flags);
+ return 1;
+}
+
+// #########
+//############################### RMDIR #################################
+// #########
+
+
+//
+// _rmdir: Verzeichnis loeschen
+// cmdline: Kommandozeilenargumente
+//
+
+
+#if __VERSION__ < "3.2.9"
+
+private int _dir_filter(mixed arg)
+{
+ return (arg[FILESIZE]==-2);
+}
+
+#endif
+
+static int _rmdir(string cmdline)
+{
+ string dest,tmp;
+ int flags;
+ mixed *args;
+
+ cmdline=_unparsed_args();
+ args=parseargs(cmdline,&flags,RMDIR_OPTS,1);
+ if (flags==-1||!sizeof(args))
+ return USAGE("rmdir [-" RMDIR_OPTS "] <Verzeichnis>");
+ if (sizeof(args)>1)
+ return
+ notify_fail("Mit 'rmdir' kann nur jeweils EIN Verzeichnis geloescht "
+ "werden.\nDer Befehl 'rm' bietet erweiterte Moeglichkeiten.\n"),0;
+ dest=args[0];
+ if (dest!="/")
+ {
+ args=file_list(({dest}),MODE_RMDIR,0,"/");
+#if __VERSION__ < "3.2.9"
+ args=filter(args,#'_dir_filter);
+#else
+ args=filter(args,(: ($1[FILESIZE]==-2) :));
+#endif
+ if (!sizeof(args))
+ return notify_fail(
+ sprintf("rmdir: %s: Kein solches Verzeichnis gefunden.\n",dest)),0;
+ if (sizeof(args)>1)
+ return notify_fail(
+ sprintf("rmdir: %s: Maske ist nicht eindeutig.\n",dest)),0;
+ dest=args[0][FULLNAME];
+ if (!MAY_WRITE(dest)) return ERROR(NO_WRITE,dest,1);
+ if (!rmdir(dest))
+ {
+ if (sizeof((get_dir(dest+"/*")||({}))-({".",".."})))
+ printf("rmdir: %s: Verzeichnis ist nicht leer.\n",dest);
+ }
+ else
+ {
+ if (flags&&RMDIR_V) printf(FILE_DELETED,dest);
+ }
+ return 1;
+ }
+ return ERROR(NO_DELETE,dest,1);
+}
+
+// #########
+//############################### MKDIR #################################
+// #########
+
+
+//
+// _mkdir: Verzeichnis erstellen
+// cmdline: Kommandozeilenargumente
+//
+
+static int _mkdir(string cmdline)
+{
+ string dest,tmp;
+ int flags,i;
+ string *args;
+
+ cmdline=_unparsed_args();
+ args=parseargs(cmdline,&flags,MKDIR_OPTS,1);
+ if (flags==-1) return 0;
+ if (!sizeof(args))
+ return USAGE("mkdir [-" MKDIR_OPTS "] <Verzeichnis>");
+ if (sizeof(args)>1)
+ return notify_fail("Mit 'mkdir' kann nur jeweils EIN Verzeichnis "
+ "erstellt werden.\n"),0;
+ dest=args[0];
+
+ if ((i=file_size(implode((args=explode(dest,"/"))[0..<2],"/")))==FSIZE_DIR)
+ {
+ if (!mkdir(dest)) return ERROR(NO_CREATE_DIR,dest,1);
+ if (flags&MKDIR_V) printf(DIR_CREATED,dest,1);
+ printf("mkdir: abgeschlossen.\n");
+ return 1;
+ }
+
+ if (i==FSIZE_NOFILE)
+ {
+ if (flags&MKDIR_R)
+ {
+ if (mkdirp(dest) != 1)
+ return ERROR(NO_CREATE_DIR,dest,1);
+ if (flags&MKDIR_V)
+ printf(DIR_CREATED,implode(args[0..i],"/"));
+ printf("mkdir: abgeschlossen.\n");
+ return 1;
+ }
+ return ERROR(DOESNT_EXIST,implode(args[0..<2],"/"),1);
+ }
+ return ERROR(ALREADY_EXISTS,dest,1);
+}
+
+// ######
+//################################ RM ###################################
+// ######
+
+private void _rm_ask_delete(mixed *filedata, int flags);
+
+static void _rm_ask_delete2(string input,mixed *filedata,int flags)
+{
+ int i;
+ if (!sizeof(input)) input=" ";
+ input=lower_case(input);
+ switch(input[0])
+ {
+ case 'q':
+ printf("Loeschen abgebrochen!\n");
+ return;
+ case 'y':
+ case 'j':
+ if (filedata[0][FILESIZE]==-2)
+ {
+ if (i=filedata[0][SUBDIRSIZE]) // Dir-Eintrag nach hinten schieben
+ {
+ mixed temp;
+ int j;
+ temp=filedata[0];
+ temp[SUBDIRSIZE]=0;
+ for(j=0;j<i;j++) filedata[j]=filedata[j+1];
+ filedata[j]=temp;
+ _rm_ask_delete(filedata,flags);
+ return;
+ }
+ if (!rmdir(filedata[0][FULLNAME]))
+ printf(NO_DELETE,filedata[0][FULLNAME]);
+ else if (flags&RM_V) printf(FILE_DELETED,filedata[0][FULLNAME]);
+ }
+ else // Datei existiert
+ {
+ if (!rm(filedata[0][FULLNAME]))
+ printf(DEST_NO_DELETE "Uebergehe Datei...\n",
+ filedata[0][FULLNAME]);
+ else if (flags&RM_V) printf(FILE_DELETED,filedata[0][FULLNAME]);
+
+ }
+ case 'n':
+ _rm_ask_delete(filedata[1+filedata[0][SUBDIRSIZE]..],flags);
+ return;
+ default:
+ printf("Kommando nicht verstanden.\n");
+ _rm_ask_delete(filedata,flags);
+ return;
+ }
+ return;
+}
+
+private void _rm_ask_delete(mixed *filedata, int flags)
+{
+ int i;
+ mixed temp;
+ if (!sizeof(filedata))
+ {
+ printf("rm: abgeschlossen.\n");
+ return;
+ }
+ switch(filedata[0][FILESIZE])
+ {
+ case -1:
+ if (flags&RM_V) printf(DOESNT_EXIST,filedata[0][FULLNAME]);
+ _rm_ask_delete(filedata[1..],flags);
+ return;
+ case -2:
+ if (i=filedata[0][SUBDIRSIZE])
+ printf("Ins Verzeichnis '%s' hinabsteigen?\n",
+ filedata[0][FULLNAME]);
+ else
+ printf("Verzeichnis '%s' loeschen?\n",
+ filedata[0][FULLNAME]);
+ input_to("_rm_ask_delete2",INPUT_PROMPT, "(j,n,q) ",
+ filedata,flags);
+ return;
+ default:
+ printf("'%s' loeschen? (j,n,q)\n",
+ filedata[0][FULLNAME]);
+ input_to("_rm_ask_delete2",INPUT_PROMPT, "(j,n,q) ",
+ filedata,flags);
+ return;
+ }
+}
+
+
+private void rm_file(mixed filedata, mixed notused, int flags)
+{
+ string dest;
+ dest=filedata[FULLNAME];
+ if (!MAY_WRITE(dest))
+ {
+ printf(NO_WRITE,dest);
+ return;
+ }
+ switch(filedata[FILESIZE])
+ {
+ case -1:
+ if (flags&RM_V) printf(DOESNT_EXIST,dest);
+ return;
+ case -2:
+ if (!rmdir(dest)) printf(DEST_NO_DELETE,dest);
+ else
+ {
+ if (flags&RM_V) printf(FILE_DELETED,dest);
+ }
+ return;
+ default:
+ if (!rm(dest)) printf(DEST_NO_DELETE,dest);
+ else
+ {
+ if (flags&RM_V) printf(FILE_DELETED,dest);
+ }
+ return;
+ }
+}
+
+static int _rm(string cmdline)
+{
+ mixed *args,*args2;
+ int flags,i;
+ string mask;
+
+ cmdline=_unparsed_args();
+ args=parseargs(cmdline,&flags,RM_OPTS,0);
+ if (flags==-1||!sizeof(args))
+ return USAGE("rm [-" RM_OPTS
+ "] <datei/verz> [<datei2/verz2> ... ] [<maske>]");
+ if (flags&RM_M)
+ {
+ mask=args[<1];
+ args=args[0..<2];
+ }
+ args=map(args,#'to_filename)-({0});
+ args=file_list(args,MODE_RM,(flags&RM_R),"/",mask);
+ if (!(i=sizeof(args)))
+ return printf("Keine passende Datei gefunden.\n"),1;
+ if (!(flags&RM_I))
+ {
+ if (i>1) // Umdrehen
+ {
+ mixed temp;
+ i>>=1;
+ while(i)
+ {
+ temp=args[<(i--)];
+ args[<(i+1)]=args[i];
+ args[i]=temp;
+ }
+ }
+ asynchron(args,#'rm_file,args,flags,0);
+ return 1;
+ }
+ _rm_ask_delete(args,flags);
+ return 1;
+}
diff --git a/std/shells/magier/fileview.c b/std/shells/magier/fileview.c
new file mode 100644
index 0000000..731de5a
--- /dev/null
+++ b/std/shells/magier/fileview.c
@@ -0,0 +1,728 @@
+// MorgenGrauen MUDlib
+//
+// fileview.c
+//
+// $Id: fileview.c 9142 2015-02-04 22:17:29Z Zesstra $
+#pragma strict_types
+#pragma save_types
+//#pragma range_check
+#pragma no_clone
+#pragma pedantic
+
+#include <ansi.h>
+#include <player/base.h>
+#include <wizlevels.h>
+#include <shells.h>
+#include <daemon/mand.h>
+#include <udp.h>
+#define NEED_PROTOTYPES
+#include <magier.h>
+#include <thing/properties.h>
+#include <player.h>
+
+private nosave mapping colorstrings;
+private nosave mapping oldman_result;
+
+// ###################
+//######################### INITIALISIERUNG #############################
+// ###################
+
+mixed _query_localcmds()
+{
+ return ({({"ls","_ls",0,LEARNER_LVL}),
+ ({"more","_more",0,LEARNER_LVL}),
+ ({"cat","_cat",0,LEARNER_LVL}),
+ ({"head","_cat",0,LEARNER_LVL}),
+ ({"tail","_cat",0,LEARNER_LVL}),
+ ({"man","_man",0,LEARNER_LVL}),
+ ({"rman","_rman",0,LEARNER_LVL}),
+ ({"showprops","_showprops",0,WIZARD_LVL}),
+ ({"grep","_grep",0,LEARNER_LVL})});
+}
+
+
+// ######
+//################################ LS ###################################
+// ######
+
+//
+// _ls: Der ls-Befehl: Verzeichnisse und Dateien anzeigen
+// cmdline: Kommandozeile
+//
+
+//
+// Funktionen zum Sortieren und fuer filter_ldfied/map_ldfied
+//
+
+
+private string _get_color(string color)
+{
+ return COLORS[lower_case(color)];
+}
+
+
+private void SetColorstrings()
+{
+ string tmp,term;
+ mapping vars;
+ vars=QueryProp(P_VARIABLES);
+ colorstrings=m_allocate(0,2);
+ switch(term=QueryProp(P_TTY))
+ {
+ case "vt100":
+ case "ansi":
+ if(stringp(vars["LS_DIR"]))
+ tmp=implode(map(explode(vars["LS_DIR"],"+"),#'_get_color),
+ "");
+ else
+ tmp = (term == "ansi") ? ANSI_BLUE+ANSI_BOLD: ANSI_BOLD;
+ colorstrings[DIR] = tmp+"%s"+(term == "vt100"?"/":"")+ANSI_NORMAL;
+ if(term == "vt100") colorstrings[DIR, 1] = 1;
+ if(stringp(vars["LS_OBJ"]))
+ tmp=implode(map(explode(vars["LS_OBJ"],"+"),#'_get_color),
+ "");
+ else
+ tmp = (term == "ansi") ? ANSI_RED : ANSI_INVERS;
+ colorstrings[OBJ] = tmp+"%s"+ANSI_NORMAL;
+ if(stringp(vars["LS_VC"]))
+ tmp=implode(map(explode(vars["LS_VC"],"+"),#'_get_color),
+ "");
+ else
+ tmp = (term == "ansi") ? ANSI_PURPLE : ANSI_INVERS;
+ colorstrings[VC] = tmp+"%s"+ANSI_NORMAL;
+ break;
+ case "dumb":
+ colorstrings[DIR] = "%s/"; colorstrings[DIR, 1] = 1;
+ colorstrings[OBJ] = "%s*"; colorstrings[OBJ, 1] = 1;
+ colorstrings[VC] = "%s*"; colorstrings[VC , 1] = 1;
+ break;
+ default:
+ colorstrings[DIR] = "%s";
+ colorstrings[OBJ] = "%s";
+ colorstrings[VC] = "%s";
+ }
+ return;
+}
+
+
+private string _ls_output_short(mixed filedata,
+ int maxlen,int counter,int maxcount)
+{
+ string tmp;
+ tmp=filedata[BASENAME];
+ maxlen-=sizeof(tmp);
+ switch(filedata[FILESIZE])
+ {
+ case -2: tmp=sprintf(colorstrings[DIR],tmp);
+ maxlen-=colorstrings[DIR,1]; break;
+ case -1: tmp=sprintf(colorstrings[VC],tmp);
+ maxlen-=colorstrings[VC,1]; break;
+ default: if (find_object(filedata[FULLNAME]))
+ {
+ maxlen-=colorstrings[OBJ,1];
+ tmp=sprintf(colorstrings[OBJ],tmp); break;
+ }
+ }
+ if (!maxcount) return tmp+"\n";
+ return sprintf("%-*s%s",(maxlen+sizeof(tmp)),tmp,
+ ((counter++)==maxcount?(counter=0,"\n"):" "));
+}
+
+private int _ls_maxlen(mixed filedata,int flags,int maxlen)
+{
+ string base;
+ int size;
+ base=filedata[BASENAME];
+ if (!(flags&LS_A)&&(base[0]=='.')) return 0;
+#if __VERSION__ < "3.2.9"
+ if (sizeof(base)>maxlen) maxlen=sizeof(base);
+#else
+ maxlen=max(maxlen,sizeof(base));
+#endif
+ return 1;
+}
+
+private string _ls_output_long(mixed filedata, int flags,closure valid_read,
+ closure valid_write,closure creator_file)
+{
+ string *tmp,full,base,path,date,creator,group;
+ int size,dir,ftime;
+ object ob;
+
+ base=filedata[BASENAME];
+ if (!(sizeof(base))||((!(flags&LS_A))&&(base[0]=='.')))
+ return 0;
+ size=filedata[FILESIZE];
+ path=filedata[PATHNAME];
+ tmp=(string *)call_other(master(),"full_path_array",
+ filedata[FULLNAME],getuid());
+ full=sprintf("/%s",implode(tmp,"/"));
+ dir=(size==-2);
+ ob=find_object(full);
+ ftime=filedata[FILEDATE];
+ date=dtime(ftime);
+ date=sprintf("%s %s %s",date[9..11],date[5..6],
+ ((time()-ftime)<31536000?date[19..23]:(" "+date[13..16])));
+ creator="";
+ group="";
+ if (flags&LS_U)
+ {
+ creator=(string)call_other(master(),"creator_file",full);
+ switch(creator)
+ {
+ case ROOTID: creator="root"; break;
+ case BACKBONEID: creator="daemon"; break;
+ default: if(!creator) creator="none"; break;
+ }
+ }
+ if (flags&LS_G)
+ {
+ if (sizeof(tmp))
+ {
+ switch(tmp[0])
+ {
+ case WIZARDDIR: group="magier"; break;
+ case "news": group="news"; break;
+ case "mail": group="mail"; break;
+ case "open": group="public"; break;
+ case "p": group="project"; break;
+ case DOMAINDIR: if (sizeof(tmp)>1) { group=tmp[1]; break; }
+ default: group="mud"; break;
+ }
+ }
+ else group="mud";
+ }
+ if (dir) base=sprintf(colorstrings[DIR],base);
+ else
+ {
+ if (ob)
+ {
+ if (size==-1)
+ base=sprintf(colorstrings[VC],base);
+ else
+ base=sprintf(colorstrings[OBJ],base);
+ }
+ }
+ return sprintf(("%c%c%c%c %3d"+((flags&LS_U)?" %-24.24s":"%-0.1s")+
+ ((flags&LS_G)?" %-8.8s":"%0.1s")+" %8s %s %s\n"),
+ (dir?'d':'-'),
+ (!funcall(valid_read,full,getuid(),
+ "read_file",this_object())?'-':'r'),
+ (!funcall(valid_write,full,getuid(),
+ "write_file",this_object())?'-':'w'),
+ (ob?'x':'-'),
+ (dir?(sizeof((get_dir(full+"/*")||({}))-({".",".."}))):0),
+ creator,group,(dir?"-":size==-1?"<vc>":to_string(size)),
+ date,base);
+}
+
+
+static int _ls(string cmdline)
+{
+ int flags,cmp,i,arg_size,size;
+ int maxlen,counter,maxcount;
+ string *args,output;
+ mixed *tmp;
+ closure output_fun,v_read,v_write,creator,sort_fun;
+
+ cmdline=_unparsed_args()||"";
+ args=parseargs(cmdline,&flags,LS_OPTS,1);
+ if (flags==-1)
+ return USAGE("ls [-" LS_OPTS "] [<Verzeichnis>] [<Verzeichnis2> ..]");
+ SetColorstrings();
+ output="";
+ if (!sizeof(args)) args=({ QueryProp(P_CURRENTDIR) });
+ if (!sizeof(args=file_list(args,MODE_LSA,0,"/")))
+ return notify_fail("ls: Keine passenden Verzeichnisse gefunden.\n"), 0;
+// Files sortieren die erste
+ if (flags&LS_T) cmp=FILEDATE;
+ else if (flags&LS_S) cmp=FILESIZE;
+ else cmp=BASENAME; // =0 :-)
+ sort_fun=lambda(({ 'a,'b }),({
+ ((!cmp&&!(flags&LS_R))||(cmp&&(flags&LS_R))?#'>:#'<),
+ ({#'[,'a,cmp}),({#'[,'b,cmp})}));
+ args=sort_array(args,sort_fun);
+// Ausgabeformat bestimmen
+ if (flags&LS_L)
+ {
+ v_read=VALID_READ_CL;
+ v_write=VALID_WRITE_CL;
+ creator=CREATOR_CL;
+ }
+ arg_size=sizeof(args);
+ if (arg_size>1||(arg_size&&args[0][FILESIZE]>=0))
+ {
+ if (flags&LS_L)
+ tmp=map(args,#'_ls_output_long,flags,v_read,
+ v_write,creator)-({0});
+ else
+ {
+ counter=0;maxlen=0;
+ tmp=filter(args,#'_ls_maxlen,flags,&maxlen);
+ if (maxlen>76) maxlen=76;
+ maxcount=(78/(maxlen+2))-1;
+ tmp=map(tmp,#'_ls_output_short,maxlen,&counter,maxcount);
+ }
+ output=sprintf("\n%d Dateien/Unterverzeichnisse:\n%s\n",
+ sizeof(tmp),implode(tmp,""));
+ }
+ for(i=0;i<arg_size;i++)
+ {
+ tmp=({});
+ size=args[i][FILESIZE];
+ if (size==-2)
+ {
+ tmp=file_list(({args[i][FULLNAME]+"/*"}),MODE_LSB,0,"/");
+ tmp=sort_array(tmp,sort_fun);
+ if (flags&LS_L)
+ tmp=map(tmp,#'_ls_output_long,flags,v_read,
+ v_write,creator)-({0});
+ else
+ {
+ counter=0;maxlen=0;
+ tmp=filter(tmp,#'_ls_maxlen,flags,&maxlen);
+ maxcount=(78/(maxlen+2));
+ if (maxcount) maxcount--;
+ tmp=map(tmp,#'_ls_output_short,maxlen,&counter,maxcount);
+ }
+ if (sizeof(tmp))
+ {
+ output+=sprintf("\n%s: Verzeichnis, %d Dateien/Unterverzeichnisse:\n",
+ args[i][FULLNAME],sizeof(tmp));
+ output+=(implode(tmp,"")+((string)(tmp[<1][<1..<1])=="\n"?"":"\n"));
+ }
+ else
+ {
+ output+=sprintf("\n%s: Leeres Verzeichnis.\n",args[i][FULLNAME]);
+ }
+ }
+ }
+ More(output);
+ return 1;
+}
+
+// ########
+//############################### MORE ###################################
+// ########
+//
+// _more_file: Mehrere Files hintereinander ausgeben
+//
+
+private void _more_file(string *arg)
+{
+ if (!sizeof(arg)) return;
+ printf("more: Naechste Datei: %s\n",arg[0]);
+ More(arg[0],1,#'_more_file,({ arg[1..]}));
+ return;
+}
+
+
+private mixed _size_filter(mixed *arg)
+{
+ if (arg[FILESIZE]>0) return arg[FULLNAME];
+ if (arg[FILESIZE]==0)
+ {
+ printf("%s: %s: Leere Datei.\n",query_verb()||"more",arg[FULLNAME]);
+ return 0;
+ }
+ if (arg[FILESIZE]==-2)
+ printf("%s: %s ist ein Verzeichnis.\n",query_verb()||"more",arg[FULLNAME]);
+ else
+ printf("%s: %s: Datei existiert nicht.\n", query_verb()||"more",
+ arg[FULLNAME]);
+ return 0;
+}
+
+
+//
+// _more: Dateien anzeigen
+// cmdline: Kommandozeile
+//
+
+static int _more(string cmdline)
+{
+ mixed *args;
+ int flags;
+ cmdline=_unparsed_args();
+ args=parseargs(cmdline,&flags,"",1);
+ if (flags==-1||!sizeof(args)) return USAGE("more <datei> [<datei2>..]");
+ args=file_list(args,MODE_MORE,0,"/");
+ if (!sizeof(args))
+ return printf("more: %s: Keine passende Datei gefunden.\n",cmdline),1;
+ args=map(args,#'_size_filter)-({0});
+ if (sizeof(args)) _more_file(args);
+ return 1;
+}
+
+// ###################
+//########################## HEAD, TAIL, CAT #############################
+// ###################
+
+static int _cat(string cmdline)
+{
+ mixed *args;
+ int flags;
+ cmdline=_unparsed_args();
+ args=parseargs(cmdline,&flags,"",1);
+ if(flags==-1||!sizeof(args))
+ return USAGE(query_verb()+" <dateiname> [<datei2>..]");
+ args=file_list(args,MODE_CAT,0,"/");
+ if (!sizeof(args))
+ return printf("%s: %s: Keine passende Datei gefunden.\n",query_verb(),
+ cmdline),1;
+ args=map(args,#'_size_filter)-({0});
+ if (!sizeof(args)) return 1;
+ while(sizeof(args))
+ {
+ switch(query_verb())
+ {
+ case "cat":
+ if (!cat(args[0]))
+ printf("cat: %s konnte nicht angezeigt werden.\n",args[0]);
+ break;
+ case "head":
+ if (!cat(args[0],0,10))
+ printf("head: %s konnte nicht angezeigt werden.\n",args[0]);
+ break;
+ case "tail": tail(args[0]); break;
+ }
+ args=args[1..];
+ }
+ return 1;
+}
+
+// #######
+//############################### MAN ###################################
+// #######
+
+static int _man(string cmdline)
+{
+ mixed *args;
+ int i, flags;
+ string *tmp, *tmp2;
+
+ cmdline=_unparsed_args();
+ args=parseargs(cmdline,&flags,MAN_OPTS,0);
+
+ if (flags==-1 ||
+ (sizeof(args)!=1 &&
+ (sizeof(args)<2 || sizeof(args[1])>1 || !(i=to_int(args[1])))))
+ return USAGE("man [-" MAN_OPTS "] <hilfeseite>");
+ tmp=explode(args[0],"/");
+
+ if (oldman_result && sizeof(tmp)==1 && sizeof(args)==1 &&
+ sizeof(tmp[0])==1 && (i=to_int(tmp[0])) && member(oldman_result,i)) {
+ tmp=({oldman_result[i,0],oldman_result[i,1]});
+ i=0;
+ }
+ else if (!(flags&(MAN_M|MAN_R))&&sizeof(tmp)>1)
+ {
+ if (file_size(MAND_DOCDIR+args[0])>=0)
+ tmp=({tmp[<1],args[0]});
+ else
+ tmp=({});
+ }
+ else
+ {
+ if (flags&MAN_R)
+ {
+ flags&=(~MAN_M);
+ if (catch(regexp(({""}),args[0]))||
+ !regexp(({""}),args[0]))
+ return printf("man: Ungueltiger Ausdruck in Maske.\n"),1;
+ }
+ tmp=(string *)call_other(MAND,"locate",args[0],flags&(MAN_M|MAN_R));
+ }
+
+ oldman_result=(mapping)0;
+ if(i && sizeof(tmp)>2 && sizeof(tmp)>=(i<<1))
+ tmp=tmp[((i<<1)-2)..((i<<1)-1)];
+ switch(sizeof(tmp))
+ {
+ case 0:
+ printf("Keine Hilfeseite gefunden fuer '%s'.\n",args[0]);
+ break;
+ case 2:
+ /*
+ if (flags&MAN_I)
+ {
+ // BRANCH TO MANUALD
+ return 1;
+ }
+ */
+ printf("Folgende Hilfeseite wurde gefunden: %s\n",tmp[1]);
+ More(MAND_DOCDIR+tmp[1],1);
+ return 1;
+ default:
+ i=sizeof(tmp)>>1;
+ tmp2=allocate(i);
+ oldman_result=m_allocate(i,2);
+ while(i)
+ {
+ tmp2[(i-1)]=sprintf("%d: ",i)+tmp[(i<<1)-2];
+ oldman_result[i,0]=tmp[(i<<1)-2];
+ oldman_result[i,1]=tmp[(i<<1)-1];
+ i--;
+ }
+ printf("Es wurden folgende potentiell passenden Seiten gefunden:\n"
+ "%'-'78.78s\n%s%'-'78.78s\n","",
+ break_string(implode(tmp2," "),78),"");
+ break;
+ }
+ return 1;
+}
+
+// ########
+//############################### RMAN ##################################
+// ########
+
+static int _rman(string str)
+{
+ int flags;
+ string *args;
+
+ str=_unparsed_args();
+ args=parseargs(str,&flags,"",0);
+ if (flags==-1||sizeof(args)!=2)
+ return USAGE("rman <hilfeseite> <mudname>");
+ write("man: " +
+ (string)call_other(UDP_CMD_DIR+"man","send_request",args[1],args[0]));
+ return 1;
+}
+
+
+// #############
+//############################# SHOWPROPS ###############################
+// #############
+
+//
+// _showprops: Zeigt Properties zu einem Objekt an
+//
+
+static int _showprops(string str)
+{
+ int i;
+ string *list, ausgabe;
+
+ if (str) {
+ if (str[0]!='/') str="/"+str;
+ if (str[0..4]!="/std/")
+ {
+ printf("showprops: Es koennen nur Properties von Objekten "
+ "aus /std/ angezeigt werden.\n");
+ return 1;
+ }
+ if (str[<1]=='.') str+="c";
+ if (str[<2..<1]!=".c") str+=".c";
+ if (file_size(str)<0)
+ {
+ printf("showprops: %s: Es gibt kein Objekt diesen Namens.\n",str[0..<3]);
+ return 1;
+ }
+ if (catch(call_other(str[0..<3], "???")))
+ {
+ printf("showprops: %s: Datei konnte nicht geladen werden.\n",str);
+ return 1;
+ }
+ }
+ if (!str || !find_object(str)) {
+ notify_fail("Welche Properties moechtest Du sehen?"
+ " Bsp.: <showprops /std/npc>\n");
+ return 0;
+ }
+ list=inherit_list(find_object(str));
+#if __VERSION__ < "3.2.9"
+ list=map(list,lambda(({'x}),({#'extract,'x,4,-2})));
+ list+=map(list,lambda(({'x}),({#'[<,({#'old_explode,'x,"/"}),1})));
+ list=map(m_indices(mkmapping(list)),lambda(({'x}),({#'+,({#'+,"/sys/",'x}),"h"})));
+ list=filter(list,lambda(({'x}),({#'>,({#'file_size,'x}),0})) );
+#else
+ list=map(list,(: return $1[5..<2]+"h"; :));
+ list+=map(list,(: return explode($1,"/")[<1]; :));
+ list=map(m_indices(mkmapping(list)),(: return "/sys/"+$1; :));
+ list=filter(list,(: return file_size($1)>0; :));
+#endif
+ list=sort_array(list, #'<);
+ ausgabe="";
+ for (i=sizeof(list);i--;)
+ {
+#if __VERSION__ < "3.2.9"
+ str=implode(filter(old_explode(read_file(list[i]), "\n"),
+ lambda( ({ 'x }), ({#'==, ({#'extract, 'x, 0, 9}), "#define P_"}) ))
+ , "\n");
+#else
+ str=implode(filter(explode(read_file(list[i]),"\n"),
+ (: return $1[0..9]=="#define P_";:)),"\n");
+#endif
+ if (str!="") ausgabe+=sprintf("%s\n%s\n\n", list[i], str);
+ }
+ if (ausgabe!="")
+ More(ausgabe);
+ else
+ printf("Keine Property-Definitionen zu diesem Objekt gefunden!\n");
+ return 1;
+}
+
+// ########
+//############################### GREP ###################################
+// ########
+
+#if __VERSION__ < "3.2.9"
+
+private int _grep_filter(string filename)
+{
+ return (call_other("valid_write",filename,getuid(this_object()),
+ "write_file",this_object())!=0);
+}
+
+#endif
+
+//
+// grep_file: Datei greppen
+// rexpr: Regular Expression
+// flags: Flags
+//
+
+private int grep_file(mixed filedata, string rexpr, int flags)
+{
+ string fullname,data,carry,*lines,*lines_orig,*tmp,*result;
+ int ptr,count,i,nol,match,index;
+ fullname=filedata[FULLNAME];
+ if ((flags&GREP_F)&&fullname=="/players/"+getuid()+"/grep.out")
+ {
+ write_file("/players/"+getuid()+"/grep.out",
+ "Uebergehe grep.out ...\n");
+ return RET_FAIL;
+ }
+ switch(filedata[FILESIZE])
+ {
+ case -2: return RET_FAIL;
+ case -1: return ERROR(DOESNT_EXIST,fullname,RET_FAIL);
+ case 0: return RET_FAIL;
+ default: break;
+ }
+ if (!MAY_READ(fullname)) return ERROR(NO_READ,fullname,RET_FAIL);
+ carry=""; result=({});
+ if (flags&GREP_I)
+ rexpr=lower_case(rexpr);
+ do
+ {
+ data=read_bytes(fullname,ptr,MAXLEN)||"";
+ ptr+=MAXLEN;
+ lines=explode(carry+data,"\n");
+ switch(sizeof(lines))
+ {
+ case 0: continue;
+ case 1:
+ carry="";
+ break;
+ default:
+ carry=lines[<1];
+ lines=lines[0..<2];
+ break;
+ }
+ lines_orig=lines;
+ if (flags&GREP_I)
+ lines=map(lines,#'lower_case);
+ nol=sizeof(lines);
+ for (i=0;i<nol;i++)
+ {
+ match=sizeof(regexp(lines[i..i],rexpr));
+ if (flags&GREP_V) match=!match;
+ if (match)
+ {
+ if (!(flags&GREP_C))
+ {
+ if (flags&GREP_N)
+ result+=({ sprintf("%4d %s",index+i+1,lines_orig[i])});
+ else
+ result+=lines_orig[i..i];
+ }
+ count++;
+ }
+ }
+ index+=nol;
+ }
+ while(sizeof(data)==MAXLEN);
+ if (carry!="")
+ {
+ if (flags&GREP_I) carry=lower_case(carry);
+ match=sizeof(regexp(({ carry }),rexpr));
+ if (flags&GREP_V) match=!match;
+ if (match)
+ {
+ if(!(flags&GREP_C))
+ {
+ if(flags&GREP_N)
+ result+=({ sprintf("%4d %s",index+1,carry) });
+ else
+ result+=({carry});
+ }
+ count++;
+ }
+ }
+ carry="";
+ if (count)
+ {
+ if (flags&GREP_L) carry=sprintf("%s\n",fullname);
+ else if (flags&GREP_H) data="";
+ else data=sprintf(" %s:",fullname);
+ if (flags&GREP_C) carry=sprintf("%s %d passende Zeile%s.\n",data,count,
+ (count==1?"":"n"));
+ else
+ carry=(data+"\n"+implode(result,"\n")+"\n");
+ }
+ if (flags&GREP_F)
+ return write_file("/players/"+getuid()+"/grep.out",carry);
+ write(carry);
+ return RET_OK;
+}
+
+static int _grep(string cmdline)
+{
+ string rexpr,mask;
+ mixed *args;
+ int flags;
+ cmdline=_unparsed_args();
+ args=parseargs(cmdline,&flags,GREP_OPTS,0);
+ if ((flags==-1)||!sizeof(args))
+ return USAGE("grep [-" GREP_OPTS
+ "] <regexp> <datei/verz> [<datei2> ... ] [<maske>]");
+ rexpr=args[0];
+ if (catch(regexp(({""}),rexpr))||!regexp(({""}),rexpr))
+ return printf("grep: Ungueltiger Suchausdruck: %s\n",rexpr) ,1;
+ args=args[1..];
+ if (flags&GREP_M)
+ {
+ mask=args[<1];
+ args=args[0..<2];
+ }
+ if (!sizeof(args))
+ return USAGE("grep [-" GREP_OPTS
+ "] <regexp> <datei/verz> [<datei2> ... ] [<maske>]");
+ args=map(args,#'to_filename)-({0});
+ /*
+#if __VERSION__ < "3.2.9"
+ args=filter(args,#'_grep_filter);
+#else
+ args=filter(args,(: return (valid_write($1,
+ getuid(this_object()),"write_file",this_object())!=0):));
+#endif
+ */
+ args=file_list(args,MODE_GREP,(flags&GREP_R?1:0),"/",mask);
+ if (!sizeof(args))
+ return printf("Keine passenden Dateien gefunden.\n"),1;
+ if (flags&GREP_I) rexpr=lower_case(rexpr);
+ if (flags&GREP_F)
+ {
+ if (file_size("/players/"+getuid()+"/grep.out")==-2||
+ !MAY_WRITE("/players/"+getuid()+"/grep.out"))
+ return printf("grep: Datei /players/%s/grep.out kann nicht "
+ "geschrieben werden.\n",getuid()),1;
+ else
+ write_file("/players/"+getuid()+"/grep.out",
+ "Ausgabe von \"grep " + _unparsed_args() + "\":\n");
+ }
+ asynchron(args,#'grep_file,rexpr,flags,0);
+ return 1;
+}
diff --git a/std/shells/magier/magier_ext.c b/std/shells/magier/magier_ext.c
new file mode 100644
index 0000000..a5d30b2
--- /dev/null
+++ b/std/shells/magier/magier_ext.c
@@ -0,0 +1,733 @@
+// $Id: magier_ext.c 9555 2016-05-03 20:42:46Z Zesstra $
+#pragma strict_types
+#pragma save_types
+//#pragma range_check
+#pragma no_clone
+#pragma pedantic
+
+#include <wizlevels.h>
+#include <logging.h>
+#include <magier.h>
+#include <snooping.h>
+#include <driver_info.h>
+#define NEED_PROTOTYPES
+#include <player/telnetneg.h>
+#include <player/base.h>
+#undef NEED_PROTOTYPES
+#include <properties.h>
+#include <files.h>
+#include <events.h>
+#include <player/comm.h>
+
+inherit "/std/shells/magier/parsing";
+inherit "/std/shells/magier/upd";
+inherit "/std/shells/magier/fileview";
+inherit "/std/shells/magier/objects";
+inherit "/std/shells/magier/fileedit";
+//inherit "/std/shells/magier/todo";
+inherit "/std/shells/magier/players";
+inherit "/std/shells/magier/admin";
+inherit "/std/shells/magier/moving";
+inherit "/std/shells/magier/comm";
+
+
+// #######
+//############################### SET #################################
+// #######
+
+
+//
+// _set(): Shell-Befehl 'set'
+// args: Kommandozeilenargumente
+//
+
+static int _set(mixed args)
+{
+ int pos;
+ string var;
+ mixed val;
+ mapping vars;
+
+ if(!args=_unparsed_args())
+ {
+ if(!sizeof(vars=QueryProp(P_VARIABLES)))
+ printf("Du hast noch keine Variablen definiert!\n");
+ else
+ {
+ printf("Du hast die folgenden Variablen definiert:\n");
+ walk_mapping(vars,((: printf(" %-20s = %s\n",$1,
+ pointerp($2)?implode($2,":"):$2) :)));
+
+ }
+ return 1;
+ }
+ pos = member(args,' ');
+ if(pos == -1)
+ if(sizeof(args))
+ {
+ m_delete(QueryProp(P_VARIABLES), args);
+ printf("Variable %s wurde geloescht.\n",args);
+ return 1;
+ }
+ else return USAGE("set <variable> <wert>");
+ var = args[0..pos-1];
+ val = (member(args[pos+1..],':')>-1?
+ explode(args[pos+1..], ":") :
+ args[pos+1..]);
+ vars=QueryProp(P_VARIABLES);
+ vars+= ([var : val]);
+ printf("Variable gesetzt: %s = %s\n",var,args[pos+1..]);
+ return 1;
+}
+
+// ############
+//############################# CD + PWD ###################################
+// ############
+
+static int _pwd()
+{
+ printf("Aktuelles Verzeichnis: %s\n",QueryProp(P_CURRENTDIR));
+ return 1;
+}
+
+static int _cd2(string cmdline)
+{
+ string dest,tmp;
+ int flags;
+ mixed *args;
+
+ args=parseargs(cmdline,&flags,CD_OPTS,1);
+ if (flags==-1) return 0;
+ if(flags&CD_B)
+ {
+ dest=QueryProp(P_LASTDIR);
+ }
+ if (sizeof(args)>1)
+ return notify_fail("Man kann sich (leider) nur in einem "
+ "Verzeichnis gleichzeitig befinden.\n"),0;
+ if(!dest)
+ {
+ if (!sizeof(args))
+ {
+ if (IS_WIZARD(this_object()))
+ dest="/players/"+getuid(this_object());
+ else
+ dest="/doc";
+ }
+ else
+ {
+ dest=args[0];
+ }
+ }
+
+ if (dest!="/")
+ {
+ args=file_list(({dest}),MODE_CD,0,"/");
+ args = filter(args, function int (mixed arr)
+ { return arr[FILESIZE] == FSIZE_DIR; } );
+
+ if (!sizeof(args))
+ return notify_fail("cd: "+dest+
+ ": Kein solches Verzeichnis gefunden.\n"),0;
+ if (sizeof(args)>1)
+ return notify_fail("cd: "+dest+": Maske ist nicht eindeutig.\n"),0;
+ dest=args[0][FULLNAME];
+ }
+ if (!IS_WIZARD(this_object())&&dest[0..3]!="/doc") dest="/doc";
+ SetProp(P_LASTDIR,QueryProp(P_CURRENTDIR));
+ printf("Aktuelles Verzeichnis ist jetzt: %s\n",SetProp(P_CURRENTDIR,dest));
+ tmp="";
+ if (((flags&CD_L)||
+ ((!m_contains(&tmp,QueryProp(P_VARIABLES),"CD_SHORT")||
+ tmp!="1")&&(!(flags&CD_S)))))
+ tell_object(this_object(),
+ read_file(dest+(dest[<1]=='/'?".readme":"/.readme"))||"");
+ return 1;
+}
+
+static int _cd(string cmdline)
+{
+ return _cd2(_unparsed_args());
+}
+
+static string _set_currentdir(string path)
+{
+ Set(P_CURRENTDIR, path);
+ this_object()->modify_prompt(); // Prompt mit neuem Pfad setzen, telnetneg
+ return path;
+}
+
+private string _query_currentdir()
+{
+ string c;
+ if(!c=Query(P_CURRENTDIR))
+ return Set(P_CURRENTDIR, "/players/"+getuid(this_object()),F_VALUE);
+ return c;
+}
+
+// ##########
+//############################ PROMPT #################################
+// ##########
+
+//
+// _prompt_subst: Mudnamen, Usernamen, Zeilenvorschub in Eingabeauf-
+// forderung einbauen
+// str: Uebergebener Kommandozeilenabschnitt
+//
+
+private string _prompt_subst(string str)
+{
+ switch(str)
+ {
+ case "\\h": return sizeof(MUDNAME)?MUDNAME:"Mud ohne Namen";
+ case "\\u": return capitalize(getuid(this_object()));
+ case "\\n": return "\n";
+ case "\\t": return "\t";
+ case "\\w": return "\w";
+ }
+ return str;
+}
+
+
+//
+// _prompt: Eingabeaufforderung setzen
+// arg: Kommandozeile
+//
+
+static int _prompt(string args)
+{
+ string *pargs;
+
+ args=(extern_call()?_unparsed_args():args);
+ if (!sizeof(args)) args="> ";
+ if (args[0]=='"') args=args[1..<2]; //");
+ if(!sizeof(pargs = regexplode(args, "\\\\[thuwn]")))
+ return USAGE("prompt \"<Eingabeaufforderungsdefinition>\"");
+ pargs=map(pargs,#'_prompt_subst);
+
+ SetProp(P_PROMPT,implode(pargs,""));
+ return 1;
+}
+
+static string _set_prompt(string prompt) {
+ Set(P_PROMPT, prompt, F_VALUE);
+ this_object()->modify_prompt(); // neuen Prompt setzen (telnetneg.c)
+ return prompt;
+}
+
+
+// ##############
+//############################ SHOWPRESAY ###############################
+// ##############
+
+static int _showpresay(string cmdline)
+{
+ int presay;
+ presay=QueryProp(P_CAN_FLAGS)&CAN_PRESAY;
+ cmdline=_unparsed_args(0);
+ if (!sizeof(cmdline))
+ {
+ printf("Dein Presay wird im Moment %sangezeigt.\n"
+ "%sschalten mit \'showpresay %s\'.\n",
+ presay?"":"nicht ",presay?"Aus":"Ein",
+ presay?"aus":"ein");
+ return 1;
+ }
+ if (cmdline=="ein"||cmdline=="an")
+ {
+ printf("Dein Presay wird jetzt angezeigt.\n");
+ SetProp(P_CAN_FLAGS,QueryProp(P_CAN_FLAGS)|CAN_PRESAY);
+ return 1;
+ }
+ if (cmdline=="aus")
+ {
+ printf("Dein Presay wird jetzt nicht mehr angezeigt.\n");
+ SetProp(P_CAN_FLAGS,QueryProp(P_CAN_FLAGS)&~CAN_PRESAY);
+ return 1;
+ }
+ return USAGE("showpresay [ein|an|aus]");
+}
+
+// ########
+//############################### EXEC ###############################
+// ########
+
+static int _exec(string filename)
+{
+ object ob;
+ if (!IS_LORD(this_object())) return 0;
+ if (this_player()!=this_interactive()) return 0;
+ if (this_player()!=this_object()) return 0;
+ if (!(filename=_unparsed_args())) return USAGE("exec <objektname>");
+ filename=(string)"secure/master"->_get_path(filename,getuid());
+ if (file_size(filename)<0&&(!to_filename(filename+".c"))||
+ file_size(to_filename(filename+".c"))<0)
+ {
+ printf("exec: %s: Datei nicht vorhanden oder ein Verzeichnis.\n",filename);
+ return 1;
+ }
+ if (catch(call_other(filename,"????")))
+ {
+ printf("exec: Fehler beim Laden von %s.\n",filename);
+ return 1;
+ }
+ if (!(ob=clone_object(filename))) return 0;
+ if (getuid(ob) != getuid(this_object()))
+ {
+ printf("exec: UID-Konflikt: %s <-> %s.\n",getuid(ob),
+ getuid(this_object()));
+ destruct(ob);
+ return 1;
+ }
+ log_file(SHELLLOG("EXEC"),
+ sprintf("%12.12s %40.40s %25.25s\n",
+ capitalize(getuid(this_object())),filename,dtime(time())[4..]));
+ disable_commands();
+ exec(ob,this_object());
+ if (interactive(this_object())||!interactive(ob))
+ {
+ enable_commands();
+ printf("Fehler bei EXEC: Uebertragung der Shell "
+ "nicht moeglich.\n");
+ return 1;
+ }
+ ob->start_player(capitalize(getuid(this_object())));
+ remove();
+ return 1;
+}
+// ############
+//############################# SNOOPING ###############################
+// ############
+
+private nosave string snoop_allowed;
+private nosave object snoopee;
+
+nomask int QueryAllowSnoop(object who)
+{
+ return (getuid(who) == snoop_allowed);
+}
+
+static int _sallow(string str)
+{
+ object ob;
+
+ if (!sizeof(str))
+ {
+ if (!snoop_allowed) return USAGE("sallow [<name>]\n");
+ str=snoop_allowed;
+ snoop_allowed=0;
+ printf("Du entziehst %s die Erlaubnis zum Snoopen.\n",capitalize(str));
+ ob=query_snoop(this_player());
+ if (!ob||(getuid(ob)!=str)) return 1;
+ tell_object(ob,break_string(sprintf("%s entzieht Dir die "
+ "Erlaubnis zum snoopen und zwingt Dich so dazu, mit "
+ "dem Snoopen aufzuhoeren.\n",capitalize(getuid()))));
+ snoop(ob);
+ return 1;
+ }
+ if (snoop_allowed) _sallow(""); // Erstmal abschalten
+ ob=find_player(lower_case(str));
+ str=capitalize(str);
+ if (!ob) return
+ printf("sallow: Spieler %s konnte nicht gefunden werden.\n",str),1;
+ if (query_wiz_grp(ob)>query_wiz_grp(this_player()))
+ return printf("sallow: %s hat einen hoeheren Rang als Du und kann "
+ "Dich daher ohnehin snoopen.\n",str),1;
+ snoop_allowed=getuid(ob);
+ return printf("sallow: Du erlaubst %s, Dich zu snoopen.\n",str),1;
+}
+
+static int _snoop(string cmdline)
+{
+ object ob;
+ int flags;
+ string *args;
+
+ if (!sizeof(cmdline=_unparsed_args())||
+ sizeof(args=parseargs(cmdline,&flags,SNOOP_OPTS,0))!=1||flags==-1)
+ {
+ if (!snoop(this_object())) return USAGE("snoop [-" SNOOP_OPTS
+ "] [<spieler>]\n");
+ if (snoopee)
+ printf("Du snoopst %s jetzt nicht mehr.\n",capitalize(getuid(snoopee)));
+ else
+ {
+ printf("Du hoerst auf zu snoopen.\n");
+ // evtl. irgendetwas loggen ... sollte eigentlich nicht passieren.
+ }
+ snoopee=(object)0;
+ return 1;
+ }
+ SetProp(P_SNOOPFLAGS,flags); // FUNKTIONIERT NUR, WENN magier.h und
+ // snooping.h abgeglichen sind
+ if (!(ob = find_player(args[0])))
+ return printf("snoop: Konnte keinen Spieler '%s' finden.\n",
+ capitalize(args[0])),1;
+ if (!snoop(this_player(),ob))
+ return printf("snoop: Der Versuch, %s zu snoopen, ist "
+ "fehlgeschlagen.\n%s",capitalize(args[0]),
+ ((~flags)&SNOOP_F)?"Eventuell funktioniert es mit dem "
+ "Flag '-f'.\n":""),1;
+ snoopee=ob;
+ return printf("Du snoopst jetzt %s.\n",capitalize(getuid(ob))),1;
+}
+
+
+// ##########
+//############################ MSCHAU #################################
+// ##########
+
+static int _mschau(string str)
+{
+ if (this_interactive()!=this_object()) return 0;
+ if (str=="ja"||str=="an"||str=="ein")
+ {
+ if ( QueryProp(P_WANTS_TO_LEARN) )
+ printf("Du hast den Magier-Modus doch schon eingeschaltet!\n");
+ else
+ {
+ printf("Du hast jetzt den Magier-Modus eingeschaltet.\n" );
+ SetProp(P_WANTS_TO_LEARN, 1);
+ }
+ return 1;
+ }
+ if (str=="nein"||str=="aus")
+ {
+ if (QueryProp(P_WANTS_TO_LEARN))
+ {
+ printf( "Du schaltest den Magier-Modus aus.\n");
+ set_heart_beat(1);
+ SetProp(P_WANTS_TO_LEARN,0);
+ }
+ else
+ printf("Du hast den Magier-Modus doch schon ausgeschaltet.\n");
+ return 1;
+ }
+ if (str=="+debug")
+ {
+ printf("Du nimmst jetzt Debugausgaben wahr.\n");
+ SetProp(P_WIZ_DEBUG,1);
+ return 1;
+ }
+ if (str=="-debug")
+ {
+ printf("Du nimmst jetzt keine Debugausgaben mehr wahr.\n");
+ SetProp(P_WIZ_DEBUG,0);
+ return 1;
+ }
+ return USAGE("mschau [an|ein|ja|aus|nein|+debug|-debug]\n");
+}
+
+// ###########
+//############################ PROTECT ################################
+// ###########
+
+static int _protect(string str)
+{
+
+ if (this_object()!=this_interactive()) return 0;
+ if (!sizeof(str))
+ return USAGE("protect <propertyname>\n");
+ Set(str, PROTECTED, F_MODE);
+ return printf("Deine Property %s ist jetzt %sgeschuetzt.\n",
+ str,(Query(str,F_MODE) & PROTECTED?"":"nicht mehr ")),1;
+}
+
+
+// ###############
+//########################## VIS + INVIS ##############################
+// ###############
+
+static int _hbstop;
+static int _age;
+
+static int _invis(string inform)
+{
+
+ if (QueryProp(P_INVIS))
+ return printf("Du bist doch schon unsichtbar!\n"),1;
+ tell_room(environment(),sprintf("%s %s.\n",capitalize(Name()),
+ QueryProp(P_MMSGOUT)),({ this_object() }));
+ if (inform=="e") {
+ // Logout-event ausloesen
+ EVENTD->TriggerEvent(EVT_LIB_LOGOUT, ([
+ E_OBJECT: this_object(),
+ E_PLNAME: getuid(this_object()),
+ E_ENVIRONMENT: environment() ]) );
+
+ call_notify_player_change(0);
+ }
+
+ SetProp(P_INVIS, QueryProp(P_AGE));
+ printf("Du bist jetzt unsichtbar.\n");
+ return 1;
+}
+
+static int _vis(string inform)
+{
+ if (!QueryProp(P_INVIS))
+ return printf("Du bist doch schon sichtbar.\n"),1;
+ tell_room(environment(),sprintf("%s %s.\n",capitalize(Name()),
+ QueryProp(P_MMSGIN)),({ this_object() }));
+ SetProp(P_INVIS, 0);
+ if (inform=="e") {
+ // Login-event ausloesen
+ EVENTD->TriggerEvent(EVT_LIB_LOGIN, ([
+ E_OBJECT: this_object(),
+ E_PLNAME: getuid(this_object()),
+ E_ENVIRONMENT: environment() ]) );
+
+ call_notify_player_change(1);
+ }
+ printf("Du bist jetzt sichtbar.\n");
+ return 1;
+}
+
+// ############
+//########################### LOCALCMD ###############################
+// ############
+
+
+static int _localcmd()
+{
+ int size,more;
+ string *verbs,result;
+
+ // Per Umweg ueber Mapping doppelte Werte einstampfen
+ size=sizeof(verbs=m_indices(mkmapping(query_actions(this_object()))));
+ verbs-=({""});
+ more=(size>sizeof(verbs));
+ if (!sizeof(verbs))
+ {
+ if (more)
+ printf("Die vorhandenen Befehle koennen nicht angezeigt werden, "
+ "da sie per 'add_action(\"funktion\",\"\",1)' definiert "
+ "wurden.\n");
+ else
+ printf("Dir stehen keine Befehle zur Verfuegung ... eigenartig!\n");
+ return 1;
+ }
+ verbs=sort_array(verbs,#'>);
+ result=break_string(sprintf("\'%s\'",implode(verbs,"' '")),78);
+ return printf("\n%'-'78.78s\nDie fuer Dich aktuell verfuegbaren "
+ "Befehle sind:\n\n%s\n%s%'-'78.78s\n","",result,
+ more?"Zudem wurden Befehle per 'add_action("
+ "\"funktion\",\"\",1)' definiert.\n":"",""),1;
+}
+
+// ###########
+//############################ TRAENKE ################################
+// ###########
+
+static int _traenke(string str)
+{
+ if(SetProp(P_TRANK_FINDEN, !QueryProp(P_TRANK_FINDEN)))
+ write("Du kannst jetzt Zaubertraenke finden.\n");
+ else
+ write("Du findest jetzt keine Zaubertraenke mehr.\n");
+ return 1;
+}
+
+static int norm_rusage() {
+ mixed* r;
+ r = rusage();
+ return r[0]/100 + r[1]/100;
+}
+
+// #############
+//############################ ASYNCHRON #################################
+// #############
+
+//
+// asynchron(): Asynchrone Abarbeitung eines Arrays
+// array: Zu bearbeitendes Array
+// cmd: Auszufuehrende Closure
+// data: Extraargumente
+// flags: Zusatzdaten (normalerweise Flags)
+// c: schon asynchron?
+//
+
+static varargs void asynchron(mixed* array, closure cmd, mixed data, mixed flags,int c)
+{
+ int i, j, k;
+ mixed ret_val;
+ string cmd_string;
+
+ k = norm_rusage()+5;
+ j = sizeof(array);
+ i=0;
+
+ switch (cmd_string=explode(sprintf("%O",cmd),"->")[1])
+ {
+ case "_make": cmd_string=(data&UPD_LOAD?"load":"upd");break;
+ case "cp_file": cmd_string =(data?"mv":"cp"); break;
+ case "grep_file": cmd_string = "grep"; break;
+ case "rm_file": cmd_string = "rm"; break;
+ default: break;
+ }
+
+ while(i < j && get_eval_cost() > 200000 && norm_rusage()<k)
+ // Sowohl Too-Long-Eval als auch Lag verhindern
+ {
+ ret_val=apply(cmd,array[i],data, flags);
+ if (closurep(ret_val))
+ {
+ if(c) tell_object(this_object(),
+ sprintf("%s: Verlasse Asynchronen Modus.\n",cmd_string));
+ funcall(ret_val,array[i..],data,flags);
+ return;
+ }
+ if (ret_val==RET_DELETE)
+ {
+ array[i+array[i][SUBDIRSIZE]+1..i+array[i][SUBDIRSIZE]]=
+ ({ (array[i][0..5]+({0})) });
+ }
+ if (ret_val==RET_JUMP) i+=array[i][SUBDIRSIZE];
+ i++;
+ }
+ if(sizeof(array = array[i..]))
+ {
+ if(!c) tell_object(this_object(),
+ sprintf("%s: Asynchroner Modus aktiviert!\n", cmd_string));
+ call_out(#'asynchron, 1, array, cmd, data,flags, 1);
+ }
+ else
+ {
+ if(c) tell_object(this_object(),
+ sprintf("%s: abgeschlossen.\n",cmd_string));
+ else if (query_verb()) tell_object(this_object(),
+ sprintf("%s: abgeschlossen.\n",query_verb()));
+ }
+ return;
+}
+
+//
+// ######################## Driver Status Infos ##########################
+//
+static int _driver_malloc(string str)
+{
+ if(!sizeof(str))
+ {
+ write(efun::driver_info(DI_STATUS_TEXT_MALLOC));
+ return 1;
+ }
+ if(str == "extstats")
+ {
+ write(efun::driver_info(DI_STATUS_TEXT_MALLOC_EXTENDED));
+ return 1;
+ }
+ return 0;
+}
+
+static int _driver_dumpallobj(string str)
+{
+ write("Dumping to /OBJ_DUMP ... ");
+ efun::dump_driver_info(DDI_OBJECTS);
+ efun::dump_driver_info(DDI_OBJECTS_DESTRUCTED);
+ write("done\n");
+ return 1;
+}
+
+static int _driver_opcdump(string str)
+{
+ efun::dump_driver_info(DDI_OPCODES);
+ return 1;
+}
+
+static int _driver_status(string str)
+{
+ int opt;
+
+ switch(str || "")
+ {
+ case "":
+ opt = DI_STATUS_TEXT_MEMORY;
+ break;
+
+ case "tables":
+ case " tables":
+ opt = DI_STATUS_TEXT_TABLES;
+ break;
+
+ case "swap":
+ case " swap":
+ opt = DI_STATUS_TEXT_SWAP;
+ break;
+
+ case "malloc":
+ case " malloc":
+ opt = DI_STATUS_TEXT_MALLOC;
+ break;
+
+ case "malloc extstats":
+ case " malloc extstats":
+ opt = DI_STATUS_TEXT_MALLOC_EXTENDED;
+ break;
+
+ default:
+ return 0;
+ }
+ write(efun::driver_info(opt));
+ return 1;
+}
+
+// ###################
+//########################## INITIALISIERUNG #############################
+// ###################
+
+//
+// _query_localcmds: Welche Kommandos werden in dieser Datei implementiert?
+//
+
+static mixed _query_localcmds()
+{
+ return ({
+ ({"set","_set",0,LEARNER_LVL}),
+ ({"pwd","_pwd",0,LEARNER_LVL}),
+ ({"cd","_cd",0,LEARNER_LVL}),
+ ({"prompt","_prompt",0,LEARNER_LVL}),
+ ({"showpresay","_showpresay",0,LEARNER_LVL}),
+ ({"exec","_exec",0,ARCH_LVL}),
+ ({"sallow","_sallow",0,LEARNER_LVL}),
+ ({"snoop","_snoop",0,WIZARD_LVL}),
+ ({"mschau","_mschau",0,LEARNER_LVL}),
+ ({"protect","_protect",0,WIZARD_LVL}),
+ ({"invis","_invis",0,LEARNER_LVL}),
+ ({"vis","_vis",0,LEARNER_LVL}),
+ ({"localcmd","_localcmd",0,LEARNER_LVL}),
+ ({"traenke","_traenke",0,DOMAINMEMBER_LVL}),
+ ({"malloc","_driver_malloc",0,LEARNER_LVL}),
+ ({"dumpallobj","_driver_dumpallobj",0,ARCH_LVL}),
+ ({"opcdump","_driver_opcdump",0,ARCH_LVL}),
+ ({"status","_driver_status",0,LEARNER_LVL}),
+ })
+ +fileview::_query_localcmds()
+ +upd::_query_localcmds()
+ +objects::_query_localcmds()
+ +fileedit::_query_localcmds()
+// +todo::_query_localcmds()
+ +players::_query_localcmds()
+ +admin::_query_localcmds()
+ +moving::_query_localcmds()
+ +comm::_query_localcmds();
+}
+
+//
+// initialize: Initialisierung der Shell
+//
+
+static void initialize()
+{
+ Set(P_PROMPT, SAVE, F_MODE_AS);
+ Set(P_VARIABLES,SAVE,F_MODE_AS);
+ Set("filesys",SAVE,F_MODE_AD); // P_FILESYS ist obsolet
+ Set("short_cwd",SAVE,F_MODE_AD); // P_SHORT_CWD auch
+ if(!mappingp(QueryProp(P_VARIABLES)))
+ SetProp(P_VARIABLES, ([]));
+ _prompt(QueryProp(P_PROMPT));
+// todo::initialize();
+ _cd2("");
+ return;
+}
+
+static void reconnect() { _cd(QueryProp(P_CURRENTDIR)); }
diff --git a/std/shells/magier/moving.c b/std/shells/magier/moving.c
new file mode 100644
index 0000000..3095a3f
--- /dev/null
+++ b/std/shells/magier/moving.c
@@ -0,0 +1,232 @@
+// MorgenGrauen MUDlib
+//
+// moving.c
+//
+// $Id: moving.c 9142 2015-02-04 22:17:29Z Zesstra $
+#pragma strict_types
+#pragma save_types
+#pragma range_check
+#pragma no_clone
+#pragma pedantic
+
+#define NEED_PROTOTYPES
+#include <magier.h>
+#include <thing/properties.h>
+#include <living/moving.h>
+#include <player.h>
+#undef NEED_PROTOTYPES
+#include <wizlevels.h>
+#include <moving.h>
+#include <properties.h>
+
+private mixed verfolger()
+{
+ mixed *pur;
+
+ if (!pointerp(pur=QueryProp(P_PURSUERS))) return 0;
+ else return pur[0];
+}
+
+// #########
+//########################## IN+AT ############################
+// #########
+
+static int _move_base(object target, object old_room, string cmd)
+{
+ if (environment()!=target)
+ if (IS_ARCH(this_object()))
+ {
+ __set_environment(this_object(),target);
+ printf("%s: Bewegung hat nicht geklappt. Versuche es mit "
+ "set_environment... %s.\n.",query_verb(),
+ environment()==target?"hat geklappt":"erfolglos");
+ }
+ else
+ printf("%s: Bewegung hat nicht geklappt.\n",query_verb());
+ if (environment()!=target) return 1;
+ command(cmd);
+ if (old_room) move_object(old_room);
+ else
+ return printf("%s: Ursprungsraum wurde zerstoert.\n",query_verb()),1;
+ if (environment()!=old_room)
+ {
+ if (IS_ARCH(this_object()))
+ {
+ __set_environment(this_object(),old_room);
+ printf("%s: Zurueckbewegen hat nicht geklappt. Versuche es mit "
+ "set_environment ... %s.\n",query_verb(),
+ environment()==old_room?"hat geklappt":"erfolglos");
+ }
+ else
+ printf("at: Zurueckbewegen hat nicht geklappt.\n");
+ }
+ return 1;
+}
+
+static int _in_room(string str)
+{
+ string room;int size;
+ object old_room;
+ string cmd,err;
+
+ if (!sizeof(str=_unparsed_args()) ||
+ !sizeof(str=regreplace(str,"^ *","",1)) ||
+ sscanf(str, "%s %s", room, cmd) != 2)
+ return USAGE("in <raum> <befehl>\n");
+ old_room = environment();
+ room=(string)call_other(master(),"_get_path",room,getuid());
+ if (err=catch(move_object(room)))
+ {
+ if (catch(size=file_size(room+".c"))||size<1)
+ printf("%s: %s.c: Datei nicht vorhanden.\n",query_verb(),room);
+ else
+ printf("%s: Bewegung nach %s hat nicht funktioniert: %s\n",
+ query_verb(),room,err);
+ return 1;
+ }
+ return _move_base(find_object(room),old_room,cmd);
+}
+
+static int _at_player(string dest)
+{
+ object ob,old_room;
+ mixed tmp;
+ string cmd;
+
+ if (!sizeof(dest=_unparsed_args()) ||
+ !sizeof(dest=regreplace(dest,"^ *","",1)) ||
+ sscanf(dest, "%s %s", dest, cmd) != 2)
+ return USAGE("at <lebewesen> <befehl>\n");
+ if (!(ob=find_living(dest)))
+ {
+ tmp=match_living(dest,1);
+ if (stringp(tmp)) ob = find_living(tmp);
+ }
+ if (!ob||!(ob=environment(ob)))
+ return _notify_fail(sprintf("at: Lebewesen \'%s\' nicht gefunden.\n",
+ dest)),0;
+ old_room=environment();
+ move_object(ob);
+ return _move_base(ob,old_room,cmd);
+}
+
+// ########
+//############################ GOTO ############################
+// ########
+
+static object find_living_nr(string str)
+{ string name,check;
+ int nr;
+ object*livings;
+ if(sscanf(str,"%s %d%s",name,nr,check)<2||sizeof(check))
+ return find_living(str);
+ if(!sizeof(livings=filter((find_livings(name)||({})),#'environment))
+ ||nr<1||sizeof(livings)<nr)
+ return 0;
+ return livings[nr-1];
+}
+
+static int _goto(string dest){
+ mixed target;
+ string target2,err;
+
+ if (!sizeof(dest=_unparsed_args()))
+ return USAGE("goto [lebewesen|filename]\n");
+ if (!((target=find_living_nr(dest)) && (target=environment(target))))
+ {
+ target2=target=(mixed)call_other(master(),"_get_path",dest,getuid());
+ if (!find_object(target))
+ {
+ if (target2[<1]=='.') target2+="c";
+ if (target2[<2..<1]!=".c") target2+=".c";
+ notify_fail(sprintf("goto: Datei %O nicht vorhanden.\n",target));
+ if (!(file_size(target2)>-1||
+ file_size(implode(explode(target,"/")[0..<2],"/")+
+ "/virtual_compiler.c")>-1)||(err=catch(call_other(target,"?"))))
+ {
+ if (err)
+ notify_fail(sprintf("goto: Fehler beim Teleport nach %O:\n%s\n",
+ dest,implode(explode(err,"\n")," ")));
+ target=match_living(dest,1);
+ if (!(stringp(target)&&(target=find_living(target))&&
+ (target=environment(target))))
+ return 0;
+ }
+ }
+ }
+ if (verfolger()) _verfolge("");
+ if (move(target,M_TPORT|M_NOCHECK)<0)
+ printf("Bewegung fehlgeschlagen!\n");
+ return 1;
+}
+
+// ########
+//############################ HOME ############################
+// ########
+
+static int _home()
+{
+ string dest;
+ if (verfolger()) _verfolge("");
+ dest="/players/" + getuid() + "/workroom";
+ if (file_size(dest+".c")<1||catch(call_other(dest,"???")))
+ {
+ printf("Fehler beim Laden Deines Workrooms.\n"
+ "Gehe zum Magiertreff.\n");
+ dest="/secure/merlin";
+ }
+
+ if (move(dest,M_TPORT|M_NOCHECK)<0)
+ printf("Bewegung fehlgeschlagen!\n");
+ return 1;
+}
+
+// ###############
+//######################### +MAGIERNAME ##########################
+// ###############
+
+static int _go_wiz_home(string str)
+{
+ _notify_fail("Syntax: '+magiername'\n");
+ if(sizeof(query_verb())>1) str=query_verb()[1..];
+ if(!sizeof(str)) return 0;
+ if(query_verb()[0]!='+') return 0;
+ str=(old_explode(str," ")-({0}))[0];
+ if(!sizeof(str)) return 0;
+ str=lower_case(str);
+ if (str=="merlin")
+ {
+ move("/secure/merlin",M_TPORT|M_NOCHECK);
+ return 1;
+ }
+ if ((!call_other(master(),"get_userinfo",str))||
+ !IS_LEARNER(str))
+ {
+ printf("Es gibt keinen Magier namens %s.\n",
+ capitalize(str));
+ return 1;
+ }
+ if (file_size("/players/"+str+"/workroom.c")<1)
+ {
+ printf("%s hat keinen Workroom.\n",capitalize(str));
+ return 1;
+ }
+ if (catch(call_other("/players/"+str+"/workroom","???")))
+ {
+ printf("Der Workroom von %s hat Fehler.\n",capitalize(str));
+ return 1;
+ }
+ move("/players/"+str+"/workroom",M_TPORT|M_NOCHECK);
+ return 1;
+}
+
+
+static mixed _query_localcmds()
+{
+ return
+ ({({"goto","_goto",0,LEARNER_LVL}),
+ ({"in","_in_room",0,LEARNER_LVL}),
+ ({"at","_at_player",0,LEARNER_LVL}),
+ ({"home","_home",0,WIZARD_LVL}),
+ ({"+","_go_wiz_home",1,LEARNER_LVL})});
+}
diff --git a/std/shells/magier/objects.c b/std/shells/magier/objects.c
new file mode 100644
index 0000000..ed74f56
--- /dev/null
+++ b/std/shells/magier/objects.c
@@ -0,0 +1,168 @@
+// $Id: objects.c 8848 2014-06-11 22:05:04Z Zesstra $
+#pragma strict_types
+#pragma save_types
+#pragma range_check
+#pragma no_clone
+#pragma pedantic
+
+#include <wizlevels.h>
+#include <moving.h>
+#define NEED_PROTOTYPES
+#include <thing/language.h>
+#include <thing/properties.h>
+#include <thing/description.h>
+#include <living/put_and_get.h>
+#include <player.h>
+#include <magier.h>
+
+// ###################
+//######################### INITIALISIERUNG #############################
+// ###################
+
+
+static mixed _query_localcmds()
+{
+ return ({({"clone","_clone",0,WIZARD_LVL}),
+ ({"setcmsg","_setcmsg",0,WIZARD_LVL}),
+ ({"setdmsg","_setdmsg",0,WIZARD_LVL}),
+ ({"destruct","_destruct",0,WIZARD_LVL}),
+ });
+}
+
+// #########
+//############################### CLONE ##############################
+// #########
+
+static int _clone(string cmdline)
+{
+ mixed *tmp;
+ int flags;
+ object ob;
+ string *args,*args2,err;
+
+ cmdline=_unparsed_args();
+ args=parseargs(cmdline,&flags,CLONE_OPTS,1);
+ if (flags==-1||sizeof(args)!=1)
+ return USAGE("clone [-" CLONE_OPTS "] <objektname>");
+ if (flags&CLONE_F)
+ cmdline=args[0];
+ else
+ {
+ // etwas umstaendlich, aber so kann man auch Dateien clonen,
+ // wenn man keine Leserechte hat. Man muss aber im Verzeichnis
+ // lesen koennen
+ args2=explode(args[0],"/");
+ if (args2[<1][<1]=='.') args2[<1]+="c";
+ else if (args2[<1][<2..<1]!=".c") args2[<1]+=".c";
+ tmp=file_list(({implode(args2[0..<2],"/")+"/*"}),MODE_CLONE,0,"",
+ args2[<1]);
+ if (!sizeof(tmp)||tmp[0][FILESIZE]<0)
+ return printf("clone: %s: Datei existiert nicht.\n",args[0]),1;
+ cmdline=tmp[0][FULLNAME];
+ }
+
+ if (err=catch(ob=clone_object(cmdline))||!ob)
+ return printf("clone: %s: Objekt konnte nicht erzeugt werden.\n"
+ "Grund: %O",
+ args[0],err||"unbekannt"),1;
+ if (!objectp(ob))
+ return printf("clone: %s: Objekt beim Erzeugen zerstoert.\n",
+ args[0]),1;
+ if ((ob->move(this_object(),M_GET)>0) ||
+ (!objectp(ob)||ob->move(environment(),M_NOCHECK)>0)||!objectp(ob))
+ {
+ if (!objectp(ob))
+ return printf("clone: %s: Objekt beim Erzeugen zerstoert.\n",
+ args[0]),1;
+ printf("Clone: %s erzeugt.\n",object_name(ob));
+ tell_room(environment(this_object()),
+ sprintf("%s %s.\n",Name(WER,1),QueryProp(P_CLONE_MSG)),
+ ({ this_object()}));
+ return 1;
+ }
+ tell_room(environment(this_object()),
+ sprintf("%s malt wilde Zeichen in die Luft und "
+ "murmelt vor sich hin, aber nichts "
+ "passiert...\n",Name(WER,1)),
+ ({ this_object()}));
+ destruct(ob);
+ printf("Clone: %s: Objekt konnte nicht bewegt werden.",args[0]);
+ return 1;
+}
+
+
+// ############
+//############################# DESTRUCT ##############################
+// ############
+
+//
+// _destruct: Objekte zerstoeren
+//
+
+static int _destruct(string cmdline)
+{
+ int flags;
+ mixed *args;
+ object ob;
+
+ if (!sizeof(cmdline=_unparsed_args()))
+ return USAGE(query_verb()+" <objektname>");
+ args=find_obs(lower_case(cmdline),PUT_GET_NONE);
+ if (!args||!sizeof(args))
+ {
+ if (!(ob=find_object(cmdline)))
+ {
+ notify_fail(query_verb()+": Objekt \"" +cmdline+
+ "\" nicht gefunden.\n");
+ return 0;
+ }
+ }
+ else
+ ob=args[0];
+ cmdline=capitalize(to_string(ob->name(WER)));
+ flags=(int)ob->QueryProp(P_PLURAL); // Missbrauch von flags :o)
+ if (query_verb()=="destruct")
+ {
+ if (!ob->remove())
+ {
+ notify_fail(cmdline+" will nicht zerstoert werden!\n");
+ return 0;
+ }
+ }
+ else destruct(ob);
+ if (!ob)
+ {
+ if (!QueryProp(P_INVIS))
+ {
+ tell_room(environment(this_object()),
+ sprintf("%s %s.\n",cmdline,QueryProp(P_DESTRUCT_MSG)),
+ ({ this_object() }));
+ }
+ printf("%s w%s von Dir zerstaeubt.\n",cmdline,(flags?"erden":"ird"));
+ }
+ else
+ printf("%s kann nicht zerstoert werden.\n",cmdline);
+ return 1;
+}
+
+// ####################
+//######################### SetCMsg, SetDMsg ############################
+// ####################
+
+static int _setcmsg(string str)
+{
+ printf("Beim Clonen von Objekten sehen die Anderen nun:\n"
+ "<Dein Name> %s.\n",
+ (SetProp(P_CLONE_MSG, _unparsed_args()||"zaubert etwas aus "
+ + QueryPossPronoun(MALE,WEM) + " Aermel hervor")));
+ return 1;
+}
+
+static int _setdmsg(string str)
+{
+ printf("Beim Zerstoeren von Objekten sehen die Anderen nun:\n"
+ "<Objekt> %s.\n",
+ SetProp(P_DESTRUCT_MSG, _unparsed_args()||"wird von " + name(WER,1)
+ + " zerstaeubt"));
+ return 1;
+}
diff --git a/std/shells/magier/parsing.c b/std/shells/magier/parsing.c
new file mode 100644
index 0000000..555332d
--- /dev/null
+++ b/std/shells/magier/parsing.c
@@ -0,0 +1,370 @@
+// $Id: parsing.c 9142 2015-02-04 22:17:29Z Zesstra $
+#pragma strict_types
+#pragma save_types
+//#pragma range_check
+#pragma no_clone
+#pragma pedantic
+
+#include <files.h>
+#include <wizlevels.h>
+#include <logging.h>
+#include <regexp.h>
+#define NEED_PROTOTYPES
+#include <magier.h>
+#include <thing/properties.h>
+#include <player.h>
+
+//
+// glob2regexp: Argument von glob in Regexp umwandeln
+// str: Argument (als Referenz)
+//
+
+static string glob2regexp(string str)
+{
+ str=regreplace(str,"([\\.\\^\\$\\[\\]\\(\\)])","\\\\\\1",RE_TRADITIONAL|1);
+ str=regreplace(str,"\\*",".*",RE_TRADITIONAL|1);
+ return sprintf("^%s$",regreplace(str,"?",".",RE_TRADITIONAL|1));
+}
+
+//
+// to_filename: Argument in Dateinamen umwandeln
+// str: Argument
+// Rueckgabe: Dateiname
+//
+
+static mixed to_filename(string str)
+{
+ string *tmp,p,newfn;
+ int i;
+// Testen ob .. in einem Filenamenabschnitt, falls Version <3.2.5
+ tmp=explode(str,"/");
+// Testen auf Pfadvariable
+ if (sizeof(tmp[0]) && tmp[0][0]=='$'
+ && m_contains(&p,QueryProp(P_VARIABLES),tmp[0][1..]))
+ tmp[0]=p;
+// Pfad absolut machen (Hat danach noch Wildcards drinnen) oder auch nicht
+ return master()->make_path_absolute(implode(tmp,"/"));
+}
+
+
+//
+// _parseargs(): Kommandozeilenabschnitt parsen
+// str: Kommandozeilenabschnitt
+// line: Array von geparsten Kommandozeilenabschnitten (Referenz)
+// flags: Als Referenz uebergebener Flag-Wert
+// opts: Erlaubte Flags
+// build_fn: Filenamen aendern
+//
+
+private void _parseargs(string str, string *line,int flags,string opts,
+ int build_fn )
+{
+
+// Strings in "" erhalten
+ if(str[0] == "\""[0])
+ {
+ line += ({ str[1..<2] });
+ return;
+ }
+// Flags parsen
+ if(str[0] == '-')
+ {
+ int i,j;
+ i=sizeof(str);
+ while(i--)
+ if (str[i]!='-')
+ {
+ if((j = member(opts, str[i])) != -1)
+ flags |= (1 << j);
+ else
+ {
+ flags=-1;
+ printf("Das Flag '-%c' wird von dem Befehl '%s' nicht "
+ "unterstuetzt.\n",str[i],query_verb()||"");
+ }
+ }
+ return;
+ }
+ if (build_fn)
+ {
+ if (str=(string)to_filename(str)) line+=({ str });
+ }
+ else
+ line+= ({ str });
+}
+
+
+//
+// parseargs() - zerlegt Kommandozeile in ein Array:
+// cmdline: Kommandozeile
+// flags: Als Referenz uebergebener leerer Integerwert. Enthaelt danach
+// die Flags
+// opts: String mit erlaubten Optionen
+// build_fn: Filenamen umbauen?
+// Rueckgabe: Array der Kommandozeilenargumente (ausser Flags)
+//
+
+static string *parseargs(string cmdline,int flags, string opts,int build_fn)
+{
+ int i;
+ string *line;
+ line=({});
+ if (!sizeof(cmdline)) return ({});
+ map(regexplode(cmdline,"[\"][^\"]*[\"]| ", RE_TRADITIONAL)-({" ", ""}),
+ #'_parseargs, &line, &flags,opts, build_fn);
+ return line - ({""});
+}
+
+//
+// _vc_map: VC-Objektnamen zu Arrays umwandeln ({ name, -1, program_time() })
+//
+
+private int *_vc_map(object ob,mixed *list)
+{
+ list+=({ explode(object_name(ob),"/")[<1],-1,program_time(ob) });
+ return 0;
+}
+
+
+//
+// _get_files: Filedaten beim Rekursiven kopieren erstellen
+// dirname: Bearbeitetes Verzeichnis
+// mask: Maske, der Dateinamen genuegen muessen
+// mode: Welche Daten werden benoetigt? (siehe magier.h)
+// dest: In welches Verzeichnis soll kopiert werden?
+// Rueckgabe: Alist mit den Dateiinformationen
+//
+
+private varargs mixed *_get_files(string dirname,string mask,int mode,string dest)
+{
+ mixed *files,*tmp,*data;
+ string fullname,base;
+
+ //DEBUG("_GF: DIRNAME " + dirname);
+ data=get_dir(dirname+"*",7);
+ if(!sizeof(data)) return ({});
+ files=({});
+
+ while(sizeof(data))
+ {
+ tmp=({});
+ base=data[BASENAME];
+ fullname=dirname+base;
+ if (base!="."&&base!=".."&&(!(mode==MODE_GREP&&base=="RCS"))&&
+ ((data[FILESIZE]==-2&&
+ sizeof(tmp=_get_files(fullname+"/",mask,mode,
+ dest+base+"/"))&&mode!=MODE_RM)||!mask||sizeof(regexp(({ base }),mask, RE_TRADITIONAL))))
+ {
+ //DEBUG("_GF: ADDING FILE " + fullname);
+ files+= ({ data[0..2]+({ fullname,dirname,dest+base,
+ sizeof(tmp) }) });
+ }
+ if (sizeof(files)+sizeof(tmp)>MAX_ARRAY_SIZE)
+ raise_error("Zu viele Files (>3000)!! Abgebrochen!\n");
+ files+=tmp;
+ data=data[3..];
+ }
+
+ if(sizeof(files)>300&&!IS_ARCH(this_object()))
+ // Tod allen Laggern :o)
+ raise_error("Zu viele Files (>300)!! Abgebrochen!\n");
+ return files;
+}
+
+
+//
+// _get_matching: Rekursive Funktion zum ermitteln der Files, wenn mit Maske
+// gearbeitet wird (z.B. cp -m /bla/*/* /ziel *.c)
+// pathmask: Array, das die einzelnen Elemente der Maske (Arg1) enthaelt
+// (per efun:old_explode(arg1,"/"))
+// depth: Aktuelles Element von pathmask
+// path: implode(pathmask[0..depth],"/");
+// mode: Welche Daten werden benoetigt? (siehe magier.h)
+// flags: Welche Flags wurden gesetzt?
+// dest: Zielverzeichnis (beim kopieren/moven)
+// filemask: Maske, der die Files genuegen muessen
+// Rueckgabe: Alist mit den Dateiinformationen
+//
+
+private mixed *_get_matching(string *pathmask, int depth, string path,
+ int mode, int recursive, string dest,string filemask)
+{
+ mixed *data,*tmp,*files;
+ string base,full;
+
+ //DEBUG("_GM: PM: " + pathmask[depth]);
+ //DEBUG("_GM: FM: " + filemask);
+ data=get_dir(path+pathmask[depth++],GETDIR_NAMES|GETDIR_SIZES|GETDIR_DATES)||({});
+ if (!sizeof(data)) return ({});
+ files=({});
+ while(sizeof(data))
+ {
+ if ((base=data[BASENAME])=="."||base=="..")
+ {
+ data=data[3..];
+ continue;
+ }
+ full=path+base;
+ //DEBUG("_GM: FULL: " + full);
+ if ((data[FILESIZE]==-2)&&(sizeof(pathmask)>depth)&&
+ (!(mode==MODE_GREP&&base=="RCS")))
+ {
+ //DEBUG("DESCEND INTO " + full);
+ tmp=_get_matching(pathmask,depth,full+"/",mode,recursive,
+ (recursive?dest+base+"/":dest),filemask);
+ }
+ else tmp=({});
+ //DEBUG("DEPTH: " + depth + " : " + sizeof(pathmask));
+ if((!filemask&&(depth==sizeof(pathmask)))||
+ (filemask&&(depth+2>sizeof(pathmask))&&
+ sizeof(regexp(({ base }),filemask,RE_TRADITIONAL)))||
+ ((mode==MODE_CP||mode==MODE_MV||(filemask&&
+ (mode==MODE_RM)&&sizeof(regexp(({ base}),filemask,RE_TRADITIONAL))))&&
+ sizeof(tmp)))
+ {
+ //DEBUG("ADDING: " + base+ " : "+ full );
+ files+=({ data[0..2]+({ full, path, dest+base,sizeof(tmp)}) });
+ }
+ if (sizeof(files)+sizeof(tmp)>MAX_ARRAY_SIZE)
+ raise_error("Zu viele Files (>3000)!! Abgebrochen!\n");
+ files+=tmp;
+ data=data[3..];
+ }
+ if(sizeof(files)>300&&!IS_ARCH(this_object()))
+ // Tod allen Laggern!
+ raise_error("Zu viele Files (>300)!! Abgebrochen!\n");
+ return files;
+}
+
+
+//
+// get_files: Basisroutine zum Ermitteln der zu bearbeitenden Dateien
+// filename: Pfadmaske, Verzeichnisname, Dateiname, der bearbeitet werden
+// soll
+// mode: Welche Daten werden benoetigt? (siehe magier.h)
+// recursive: Auch Unterverzeichnisse bearbeiten?
+// dest: Wenn kopiert werden soll: wohin?
+// filemask: Maske, der die Dateinamen genuegen muessen
+// Rueckgabe: Alist mit den Dateiinformationen
+//
+
+static varargs mixed *get_files(string filename, int mode, int recursive, string dest, string filemask)
+{
+ string full,path,base,*patharray,*vrooms,dest2;
+ object vcompiler;
+ mixed *files,*data;
+
+ // DEBUG("GF: " + filename);
+ // DEBUG("REC: " + recursive + " MODE: " + mode);
+ // if (dest[<1..<1]!="/") DEBUG("DEST: " + dest);
+ if (filename=="/")
+ {
+ switch (mode)
+ {
+ case MODE_LSA: return ({({ "", -2, 0,"","","",0 })});
+ default: if (!recursive) return ({});
+ break;
+ }
+ }
+ patharray=explode(filename,"/");
+ if(!sizeof(data=get_dir(filename,7)||({}))&&
+ (mode==MODE_UPD||mode==MODE_MORE||mode==MODE_ED))
+ data=get_dir(filename+".c",7)||({});
+ if ((mode==MODE_LSA||mode==MODE_LSB)&&
+ (vcompiler = find_object(implode(patharray[0..<2],"/")+"/virtual_compiler")) &&
+ pointerp(vrooms=(mixed *)vcompiler->QueryObjects()))
+ map(vrooms,#'_vc_map,&data);
+ files=({});
+ if (sizeof(data)) // passende files
+ {
+ mixed *subfiles;
+ subfiles=({});
+ path=implode(patharray[0..<2],"/")+"/";
+ while (sizeof(data))
+ {
+ subfiles=({});
+ base=data[BASENAME];
+ if (mode==MODE_LSB||(base!="."&&base!=".."))
+ {
+ //DEBUG("PATH: " + path+" BASE: " + base + " MODE: " + mode);
+ full=path+base;
+ dest2=((dest=="/"||file_size(dest[0..<2])==-2)?
+ (dest+base):(dest=="/"?"/":dest[0..<2]));
+ //DEBUG("DEST: " + dest);
+ if (recursive&&data[FILESIZE]==-2) // Verzeichnis, Rekursiv
+ subfiles=_get_files(full+"/",filemask,mode,dest2+"/");
+ if (!(filemask&&!sizeof(subfiles)&&!sizeof(regexp(({ base }),filemask,RE_TRADITIONAL))))
+ {
+ if (!filemask||mode!=MODE_RM)
+ files+=({ data[0..2]+({ full, path, dest2,sizeof(subfiles)}) });
+ if (sizeof(files)+sizeof(subfiles)>MAX_ARRAY_SIZE)
+ raise_error("Zu viele Files (>3000)!! Abgebrochen!\n");
+ files+=subfiles;
+ }
+ }
+ data=data[3..];
+ }
+ return files;
+ }
+// File existiert nicht -> Wildcard oder tatsaechlich nicht existent
+// Behandeln je nach mode
+ switch(mode)
+ {
+ case MODE_CP:
+ case MODE_MV:
+ case MODE_CD:
+ case MODE_LSA:
+ files=_get_matching(patharray+(filemask?({ "*" }):({})),1,"/",mode,
+ recursive,dest,filemask);
+ break;
+ default: break;
+ }
+ return files;
+}
+
+
+//
+// file_list(): Liste der Fileinformationen
+// files: Array der Filenamen MIT Wildcards
+// mode: Welche Daten werden benoetigt
+// recursive: Rekursiv listen?
+// dest: Zielverzeichnis
+// mask: Maske (regexp, wenn definiert)
+// Rueckgabe: Liste der betroffenen Files
+//
+
+static varargs mixed *file_list(string *files, int mode, int recursive, string dest, string mask)
+{
+ string *list,err,*result;
+ int i,j;
+ list=({});
+ if (mask) mask=glob2regexp(mask);
+ j=sizeof(files);
+ for(i=0;i<j;i++)
+ {
+ // Abschliessenden / von Pfadnamen abschneiden, weil in diesem Fall
+ // die Inhalte der ersten Unterverzeichnisebene mit ausgegeben
+ // wurden. Ursache hierfuer ist ein Fix an full_path_array() im
+ // Masterobjekt, der dazu fuehrte, dass get_dir() den abschliessenden /
+ // des uebergebenen Pfades jetzt korrekt behandelt. \o/
+ if ( sizeof(files[i]) > 1 && files[i][<1] == '/' )
+ {
+ files[i] = files[i][0..<2];
+ if ( !sizeof(files[i]) )
+ continue;
+ }
+ if (err=catch(list+=get_files(files[i],mode,recursive,dest,mask)))
+ {
+ printf("Fehler aufgetreten: %s\n",err);
+ log_file(SHELLLOG("FILE_LIST"),
+ sprintf("%s fuehrte folgendes Kommando aus: (Zeit: %s)\n"
+ " >>%s %s<<\n"
+ " Folgender Fehler trat dabei auf:\n"
+ " %s\n\n",
+ capitalize(getuid())||"<Unbekannt>",dtime(time()),
+ query_verb()||"*",_unparsed_args()||"*",err||"*"));
+ return ({});
+ }
+ }
+ return list;
+}
diff --git a/std/shells/magier/players.c b/std/shells/magier/players.c
new file mode 100644
index 0000000..c563d9d
--- /dev/null
+++ b/std/shells/magier/players.c
@@ -0,0 +1,529 @@
+// MorgenGrauen MUDlib
+//
+// players.c
+//
+// $Id: players.c 9551 2016-04-20 22:54:58Z Arathorn $
+#pragma strict_types
+#pragma save_types
+#pragma range_check
+#pragma no_clone
+#pragma pedantic
+
+#include <wizlevels.h>
+#include <ansi.h>
+#include <logging.h>
+#define NEED_PROTOTYPES
+#include <magier.h>
+#include <thing/properties.h>
+#include <thing/description.h>
+#include <living/comm.h>
+#include <player.h>
+#undef NEED_PROTOTYPES
+#include <properties.h>
+#include <moving.h>
+
+static mixed _query_localcmds()
+{
+ return ({({"zap","_zap",0,WIZARD_LVL}),
+ ({"verfolge","_verfolge",0,LEARNER_LVL}),
+ ({"trans","_trans",0,LEARNER_LVL}),
+ ({"peace","_frieden",0,LEARNER_LVL}),
+ ({"frieden","_frieden",0,LEARNER_LVL}),
+ ({"pwho","_pwho",0,WIZARD_LVL}),
+ ({"zwinge","_zwinge",0,WIZARD_LVL}),
+ ({"heal","_heile",0,WIZARD_LVL}),
+ ({"heil","_heile",1,WIZARD_LVL}),
+ ({"people","_people",0,LEARNER_LVL}),
+ ({"spieler","_spieler",0,WIZARD_LVL})});
+}
+
+// #######
+//################################ ZAP ##################################
+// #######
+
+private string _zap_message(string str, object obj)
+{
+ str=regreplace(str,"@@wer@@",(string)obj->name(WER,2),1);
+ str=regreplace(str,"@@wessen@@",(string)obj->name(WESSEN,2),1);
+ str=regreplace(str,"@@wem@@",(string)obj->name(WEM,2),1);
+ str=regreplace(str,"@@wen@@",(string)obj->name(WEN,2),1);
+ str=regreplace(str,"@@ich@@",name(WER,2),1);
+ return capitalize(str);
+}
+
+static int _zap(string str)
+{
+ object opfer;
+ string *message, dummy;
+ int spieler;
+
+ if (!str) return USAGE("zap <name>");
+ if (sscanf( str, "spieler %s", dummy ))
+ {
+ str = dummy;
+ spieler = 1;
+ }
+ if (opfer=present(str,environment()))
+ {
+ if ( !living(opfer) )
+ {
+ printf("%s ist doch gar kein Lebewesen!\n",capitalize(str) );
+ return 1;
+ }
+ if (query_once_interactive(opfer)&&!spieler )
+ {
+ printf( "Spieler kannst Du nur mit der Syntax 'zap spieler <name>' "
+ "toeten!\n" );
+ return 1;
+ }
+ else
+ if ( !query_once_interactive(opfer) && spieler )
+ {
+ printf( "Aber %s ist doch gar kein Spieler!\n",capitalize(str));
+ return 1;
+ }
+
+ message = QueryProp(P_ZAP_MSG);
+
+ if ( !pointerp(message) || sizeof(message) != 3 ){
+ tell_room(environment(),sprintf("%s beschwoert einen Blitz "
+ "vom Himmel.\n",capitalize(getuid())),({ this_object() }));
+ printf("Du toetest %s.\n",opfer->name( WEN,2));
+ }
+ else
+ {
+ printf(_zap_message(message[0],opfer));
+ tell_room(environment(),_zap_message(message[1],opfer),
+ ({this_player(),opfer}));
+ tell_object(opfer,_zap_message(message[2],opfer));
+ }
+
+ opfer->die();
+ return 1;
+ }
+ else{
+ printf("Sowas siehst Du hier nicht.\n");
+ return 1;
+ }
+}
+
+
+// ############
+//############################## VERFOLGE ################################
+// ############
+
+static int _verfolge(string str)
+{
+ // Wenn nichts eingegeben wurde, wird ver Verfolgungsmodus beendet, sofern
+ // er zuvor eingeschaltet war. Ansonsten wird eine Fehlermeldung
+ // ausgegeben.
+ if (!sizeof(str))
+ {
+ mixed *pur = Query(P_PURSUERS);
+ if ( pointerp(pur) && sizeof(pur) && objectp(pur[0]) )
+ {
+ pur[0]->RemovePursuer(this_object());
+ ReceiveMsg("Verfolgungsmodus abgeschaltet.", MT_NOTIFICATION);
+ }
+ else
+ {
+ ReceiveMsg("Du verfolgst doch ueberhaupt niemanden.", MT_NOTIFICATION);
+ }
+ return 1;
+ }
+ str=lower_case(str);
+
+ // match_living() erlaubt die Pruefung, ob die Angabe eindeutig war.
+ int|string lv = match_living(str);
+ if ( intp(lv) )
+ {
+ if ( lv == -2 )
+ ReceiveMsg("Kein solches Wesen gefunden.", MT_NOTIFICATION);
+ else
+ ReceiveMsg(sprintf("verfolge: '%s' ist nicht eindeutig.\n", str),
+ MT_NOTIFICATION);
+ return 1;
+ }
+
+ // Spieler zuerst auswaehlen, danach im Raum anwesende Lebewesen.
+ object ziel = find_player(lv) || present(lv, environment(this_player()));
+
+ // Wurde kein Lebewesen gefunden, wird das erste Element aus der Liste der
+ // Lebewesen dieses Namens gewaehlt, falls vorhanden. Nur Lebewesen mit
+ // Environment kommen in Frage, denn sonst gibt es keinen Raum, in den der
+ // neue Verfolger bewegt werden koennte.
+ if ( !objectp(ziel) ) {
+ object* eligible_livings = filter(find_livings(lv), #'environment);
+ if (sizeof(eligible_livings))
+ ziel = eligible_livings[0];
+ }
+
+ // Endlich etwas gefunden? Dann Verfolger eintragen und zum Ziel bewegen.
+ if ( objectp(ziel) )
+ {
+ if ( ziel == this_player() )
+ {
+ ReceiveMsg("Du kannst Dich nicht selbst verfolgen.", MT_NOTIFICATION);
+ }
+ else
+ {
+ ReceiveMsg(sprintf(
+ "Du verfolgst jetzt %s. [%s]", ziel->name(WEN), object_name(ziel)),
+ MT_NOTIFICATION, MA_MOVE);
+ ziel->AddPursuer(this_object());
+ ziel->TakeFollowers();
+ }
+ }
+ else
+ {
+ ReceiveMsg("Kein Wesen mit dem Namen '"+lv+"' gefunden, oder nur "
+ "solche ohne Environment.", MT_NOTIFICATION, 0, "verfolge: ");
+ }
+ return 1;
+}
+
+
+// #########
+//############################### TRANS #################################
+// #########
+
+static int _trans(string str)
+{
+ object living;
+
+ if (!sizeof(str))
+ return _notify_fail("Syntax: trans <spielername>\n"),0;
+ str=match_living(str,0);
+ if (intp(str))
+ switch (str)
+ {
+ case -1: write("Das war nicht eindeutig.\n"); return 1;
+ case -2: write("So ein Wesen gibt es nicht.\n"); return 1;
+ }
+ if(living=find_living(str))
+ {
+ if (living->move(object_name(environment()),
+ M_TPORT|M_NOCHECK)<=0)
+ {
+ printf("Teleportieren von %s fehlgeschlagen.\n",living->Name(WEM));
+ if (IS_LEARNER(living))
+ tell_object(living,sprintf("%s wollte Dich teleportieren, "
+ "hat aber versagt!\n",capitalize(getuid())));
+ return 1;
+ }
+ tell_object(living,sprintf(
+ "Ein seltsames Gefuehl ueberkommt Dich ...\n"
+ "Du verlierst die Orientierung ...\n"
+ +(QueryProp(P_INVIS)?"":"%s holt Dich zu sich.\n"),
+ capitalize(getuid())));
+ printf("%s wurde herbeizitiert.\n",living->Name(WER));
+ return 1;
+ }
+ printf("Das Lebewesen '%s' konnte nicht gefunden werden.\n",
+ capitalize(str));
+ return 1;
+}
+
+// ###########
+//############################## FRIEDEN #################################
+// ###########
+
+static int _frieden(string sname)
+{
+ object *enem,obj;
+ int i;
+ string him;
+
+ if (!sname)
+ {
+ enem=all_inventory(environment());
+ map_objects(enem,"StopHuntingMode");
+ tell_room(environment(),sprintf("%s stiftet Frieden.\n",capitalize(getuid())),
+ ({ this_object()}));
+ printf("Du stiftest Frieden.\n");
+ return 1;
+ }
+ else
+ {
+ if (!obj=find_living(sname))
+ return printf("Kein solches Lebewesen im Spiel.\n"),1;
+ him=(string)obj->name(WEM);
+ i=sizeof(enem=(object *)(((mixed *)obj->StopHuntingMode())[0]));
+ // Mistdriver ... object** waere richtig gewesen ... *seufz*
+ while(i--)
+ {
+ enem[i]->StopHuntFor(obj);
+ tell_object(obj,sprintf("%s beendet Deinen Kampf mit %s.\n",
+ capitalize(getuid()),enem[i]->Name(WEM)));
+ tell_object(enem[0],sprintf("%s beendet Deinen Kampf mit %s.\n",
+ capitalize(getuid()),him));
+ }
+ }
+ printf("%s und alle Gegner wurden befriedet.\n",obj->Name(WER));
+ return 1;
+}
+
+// ########
+//############################### PWHO ##################################
+// ########
+
+#if __VERSION__ < "3.2.9"
+private int _pwho_learner_test(object ob)
+{
+ return !IS_LEARNER(ob);
+}
+#endif
+
+static int _pwho()
+{
+ mixed* spieler, res, *hands;
+ int i;
+#if __VERSION__ < "3.2.9"
+ spieler = filter(users(),#'_pwho_learner_test);
+#else
+ spieler = filter(users(),(: return !IS_LEARNER($1); :));
+#endif
+ spieler = sort_array(spieler, function int (object a, object b)
+ { return a->QueryProp(P_LEVEL) > b->QueryProp(P_LEVEL); } );
+
+ res = "Lvl Name Erfahrung QP Int Str Dex Con WC "
+ "AC HANDS HP (max)\n"
+ "--------------------------------------------------------------"
+ "-----------------\n";
+ for (i=sizeof(spieler)-1; i>=0; i--)
+ res += sprintf("%3d %-12s %9d %5d %3d %3d %3d %3d %4d %4d %5d "
+ "%4d (%4d)\n",
+ spieler[i]->QueryProp(P_LEVEL),
+ capitalize(getuid(spieler[i])),
+ spieler[i]->QueryProp(P_XP),
+ spieler[i]->QueryProp(P_QP),
+ spieler[i]->QueryAttribute(A_INT),
+ spieler[i]->QueryAttribute(A_STR),
+ spieler[i]->QueryAttribute(A_DEX),
+ spieler[i]->QueryAttribute(A_CON),
+ spieler[i]->QueryProp(P_TOTAL_WC),
+ spieler[i]->QueryProp(P_TOTAL_AC),
+ (sizeof(hands=((int *)spieler[i]->QueryProp(P_HANDS)))?hands[1]:0),
+ spieler[i]->QueryProp(P_HP),
+ spieler[i]->QueryProp(P_MAX_HP));
+ More(res);
+ return 1;
+}
+
+// ##########
+//############################## ZWINGE #################################
+// ##########
+
+static int _zwinge(string str)
+{
+ object living;
+ string what, rest;
+ string living_name;
+
+ str = _unparsed_args();
+ if(!str|| sscanf( str, "%s %s", living_name, what ) != 2 )
+ return _notify_fail("Zwinge WEN zu WAS?\n"),0;
+ if( sscanf( what, "zu %s", rest ) == 1 ) what = rest;
+ if (!(living = find_living(living_name)))
+ return printf ("Ein Lebewesen namens '%s' konnte nicht gefunden werden!\n",
+ capitalize(living_name)),1;
+ if (living->command_me(what))
+ {
+ printf("Du zwingst %s zu \"%s\".\n",capitalize(living_name),what);
+ if (!IS_ARCH(this_object())&&getuid()!=(string)living->QueryProp(P_TESTPLAYER))
+ log_file(SHELLLOG("ZWINGE"),
+ sprintf("%s zwingt %s (%s) zu %s [%s]\n",
+ capitalize(getuid()),living->Name(),capitalize(getuid(living)),
+ what,dtime(time())));
+ }
+ else
+ write("Hat leider nicht geklappt!\n");
+ return 1;
+}
+
+// #########
+//############################### HEILE #################################
+// #########
+
+static int _heile(string name)
+{
+ object ob;
+ int lpv, mpv;
+
+ if (!name) return USAGE("heile <name>");
+ name = lower_case(name);
+ if ((!(ob = present(name,environment())))
+ ||!living(ob))
+ ob = find_living(name);
+ if (!ob)
+ {
+ printf("'%s' ist momentan nicht da.\n",capitalize(name));
+ return 1;
+ }
+ lpv = (int)ob->QueryProp(P_HP);
+ mpv = (int)ob->QueryProp(P_SP);
+ ob->heal_self(1000000);
+ if (!IS_LEARNER(ob) && (!ob->QueryProp(P_TESTPLAYER)||
+ (((string)ob->QueryProp(P_TESTPLAYER))[<5..<1]=="Gilde")))
+ log_file(SHELLLOG("HEAL"),
+ sprintf("%s heilt %s (%s) %s (LP: %d -> %d, MP: %d -> %d)\n",
+ capitalize(geteuid(this_player())),
+ call_other(ob,"name"), capitalize(geteuid(ob)),
+ dtime(time()), lpv, (int)ob->QueryProp(P_HP),
+ mpv,(int)ob->QueryProp(P_SP)));
+ tell_object(ob, QueryProp(P_NAME) + " heilt Dich.\n");
+ printf("Du heilst %s.\n",capitalize(name));
+ return 1;
+}
+
+// ##########
+//############################## PEOPLE #################################
+// ##########
+
+private string _people_filename(object obj)
+{
+ string str;
+ str=object_name(environment(obj));
+ if (!str) return 0;
+ if (str[0..2] == "/d/") return sprintf("+%s",str[3..<1]);
+ if (str[0..8] == "/players/") return sprintf("~%s",str[9..<1]);
+ return str;
+}
+
+static int _people()
+{
+ mixed *list, res;
+ int i,j, a;
+ string a_age,a_ipnum,a_name,a_level,a_idle,a_room,a_end, a_title;
+
+ switch(QueryProp("tty"))
+ {
+ case "vt100":
+ a_ipnum = ""; a_name = ANSI_BOLD;
+ a_level = ANSI_NORMAL; a_idle = ANSI_BLINK;
+ a_room = ANSI_NORMAL; a_end = ANSI_NORMAL;
+ a_title = ANSI_INVERS; a_age = ANSI_NORMAL;
+ break;
+ case "ansi":
+ a_ipnum = ANSI_BLUE; a_name = ANSI_BOLD;
+ a_level = ANSI_RED; a_idle = ANSI_BLACK+ANSI_BOLD;
+ a_room = ANSI_BOLD+ANSI_BLUE; a_end = ANSI_NORMAL;
+ a_title = ANSI_INVERS; a_age = ANSI_PURPLE;
+ break;
+ default:
+ a_title = a_ipnum = a_name = a_level = a_idle = a_room = a_end = "";
+ a_age = "";
+ }
+ list = sort_array(users(), function int (object a, object b) {
+ return query_ip_number(a)>query_ip_number(b);} );
+
+ j=sizeof(list);
+ a=0;res="";
+ for(i=0; i<sizeof(list); i++) {
+ string name_;
+ name_ = capitalize(list[i]->query_real_name()||"<logon>");
+ res += sprintf( "%s%-15s%s %s%-13s%s %s%3d%s %s %s %s%s%s%s %s%s\n",
+ a_ipnum, query_ip_number(list[i]),a_end,a_name,
+ (list[i]->QueryProp(P_INVIS)?"("+name_+")":name_),
+ a_end,a_level, MASTER->get_wiz_level(getuid(list[i])),
+ a_end,a_age,
+ time2string("%4x %0X",((int)list[i]->QueryProp(P_AGE))*2),
+ query_idle(list[i])>=300?(a++,(a_idle+"I")):" ",
+ a_end,
+ query_editing(list[i])?a_idle+"E"+a_end:" ",
+ query_input_pending(list[i])?a_idle+"M"+a_end:" ",
+ environment(list[i])?a_room+_people_filename(list[i]):"",
+ a_end);
+ }
+ if (a)
+ res = sprintf("%s%d Spieler anwesend (%d aktiv). %s%s\n",a_title,j,
+ (j-a),query_load_average(),a_end)+res;
+ else
+ res = sprintf("%s%d Spieler anwesend. %s%s\n",a_title,j,
+ query_load_average(),a_end)+res;
+ More(res);
+
+ return 1;
+}
+
+
+// ###########
+//############################## SPIELER #################################
+// ###########
+
+private string _spieler_time2string(int time)
+{
+ string ret;
+
+ ret="";
+ if (time>=86400)
+ {
+ ret+=time/86400+"d ";
+ time%=86400;
+ }
+ if(time<36000) ret+="0";
+ ret+=time/3600+":";
+ time%=3600;
+ if(time<600) ret+="0";
+ ret+=time/60+":";
+ time%=60;
+ if(time<10) ret+="0";
+ ret+=time+"";
+ return ret;
+}
+
+
+static int _spieler(string arg)
+{
+ string dummy,ip;
+ object *spieler,pl;
+ int i;
+
+ arg=_unparsed_args();
+ if(!sizeof(arg) || sscanf(arg,"aus ip %s",dummy)!=1)
+ return USAGE("spieler aus ip [von <spieler>|<ip>]");
+ arg=dummy;
+ if (sscanf(arg,"von %s",dummy)==1)
+ {
+ dummy=lower_case(dummy);
+ if (!(pl=find_player(dummy)))
+ return notify_fail(sprintf("Spieler '%s' konnte nicht gefunden "
+ "werden.\n",capitalize(dummy))),0;
+ ip=query_ip_number(pl);
+ }
+ else ip=arg;
+ ip=implode((explode(ip,".")-({""})+({"*","*","*","*"}))[0..3],".");
+if (catch(
+ spieler=filter(users(),
+ (: return sizeof(regexp(({query_ip_number($1)}),$2)); :),"^"+glob2regexp(ip)+"$")
+
+ ))
+ return printf("In der IP duerfen nur Zahlen(0-255), Punkte (.) und "
+ "Sterne (*) vorkommen.\n"),1;
+ if (!sizeof(spieler))
+ return printf("Es konnte kein Spieler mit der IP '%s' gefunden "
+ "werden.\n",ip),1;
+ arg=sprintf("\nFolgende Spieler haben die IP %s:\n"
+ "================================================================"
+ "===========\n"
+ "Name: Zweitie von: Eingeloggt: "
+ "Idle seit:\n"
+ "----------------------------------------------------------------"
+ "-----------\n",ip);
+ i=sizeof(spieler);
+ while(i--)
+ {
+ arg+=sprintf("%-11s %-17s %26s %-15s\n",
+ capitalize(getuid(spieler[i])),
+ ((dummy=(string)spieler[i]->QueryProp(P_SECOND))?
+ (sizeof((mixed *)call_other(master(),
+ "get_userinfo",dummy))?
+ capitalize(dummy):"*ungueltig*"):""),
+ dtime(spieler[i]->QueryProp(P_LAST_LOGIN)),
+ _spieler_time2string(query_idle(spieler[i])));
+ }
+ arg+="==============================================================="
+ "============\n\n";
+ More(arg);
+ return 1;
+}
diff --git a/std/shells/magier/todo.c b/std/shells/magier/todo.c
new file mode 100644
index 0000000..f4120e7
--- /dev/null
+++ b/std/shells/magier/todo.c
@@ -0,0 +1,222 @@
+// $Id: todo.c 9142 2015-02-04 22:17:29Z Zesstra $
+#pragma strict_types
+#pragma save_types
+#pragma range_check
+#pragma no_clone
+#pragma pedantic
+
+#include <wizlevels.h>
+#include <defines.h>
+#define NEED_PROTOTYPES
+#include <magier.h>
+#include <player.h>
+
+#define SAVEFILENAME sprintf("/players/%s/.todoliste",getuid())
+
+private nosave status todo_initialized;
+private nosave mixed *todo_data;
+mixed *todo_data_public;
+static mixed _query_localcmds()
+{
+ return ({
+ ({"todo","_todo",0,WIZARD_LVL})});
+}
+
+private void todo_save()
+{
+
+ int i,j;
+ string a,b;
+ a=SAVEFILENAME+".o";
+ rm(a);
+ if (j=sizeof(todo_data))
+ {
+#if !__EFUN_DEFINED__(save_value)
+ write_file(a,"#0:0\ntodo_data_public ({");
+ for (i=0;i<j;i++)
+ {
+ b=regreplace(todo_data[i][1],"\"","\\\"",1);
+ b=regreplace(b,"\n","\\n",1);
+ write_file(a,sprintf("({%d,\"%s\",}),",
+ todo_data[i][0],b));
+ }
+ write_file(a,"})\n");
+#else
+ todo_data_public=todo_data;
+ write_file(a,save_value(todo_data_public));
+ todo_data_public=0;
+#endif
+ }
+ return;
+
+}
+
+static void initialize()
+{
+ if(!IS_WIZARD(this_object())) return;
+ if (!restore_object(SAVEFILENAME)) todo_data=({});
+ else
+ {
+ todo_data=todo_data_public;
+ todo_data_public=0;
+ }
+ return;
+}
+
+static void _todo_neu2(string input,string carry)
+{
+ if (input=="q"||(input=="."&&!sizeof(carry)))
+ {
+ printf("Abbruch!");
+ return;
+ }
+ if (input!=".")
+ {
+ printf("]");
+ input_to("_todo_neu2",0,carry+input+"\n");
+ return;
+ }
+ todo_data+=({ ({ time(), carry }) });
+ todo_save();
+ printf("Eintrag angelegt. Laufende Nummer ist %d.\n",sizeof(todo_data));
+ return;
+}
+
+private int _todo_neu(string cmdline)
+{
+ if (cmdline!="neu") return 0;
+ printf("Was musst Du noch machen? (Abbruch mit 'q', "
+ "Ende mit '.')\n]");
+ input_to("_todo_neu2",0,"");
+ return 1;
+}
+
+private int _todo_loeschen(string cmdline)
+{
+ int nr;
+ if (!sscanf(cmdline,"loeschen %d",nr))
+ return notify_fail("Welchen Eintrag moechtest Du loeschen?\n"),0;
+ if (!sizeof(todo_data))
+ return notify_fail("Deine Todo-Liste hat ja ueberhaupt keinen "
+ "Eintrag!\n"),0;
+ if (nr>sizeof(todo_data))
+ {
+ printf("Deine Todo-Liste hat nur %d Eintra%s.\n",sizeof(todo_data),
+ (sizeof(todo_data)==1?"g":"ege"));
+ return 1;
+ }
+ todo_data[nr-1]=0;
+ todo_data-=({0});
+ todo_save();
+ printf("Eintrag Nummer %d wurde geloescht. Da hast Du ja ordentlich "
+ "was geschafft...\noder geschickt delegiert ;-)\n",nr);
+ return 1;
+}
+
+private int _todo_anzeigen(string cmdline)
+{
+ int nr1,nr2;
+ string output;
+ if (!sizeof(todo_data))
+ return notify_fail("Deine Todo-Liste hat keine Eintraege.\n"),0;
+ switch(sscanf(cmdline,"anzeigen %d bis %d",nr1,nr2))
+ {
+ case 0: nr1=1; nr2=sizeof(todo_data); break;
+ case 1: nr2=nr1; break;
+ case 2: break;
+ }
+ if (nr1<0) nr1=sizeof(todo_data)+nr1+1;
+ if (nr2<0) nr2=sizeof(todo_data)+nr2+1;
+ if (nr1<1||nr2<1||nr1>sizeof(todo_data)||nr2>sizeof(todo_data))
+ return notify_fail(sprintf("Deine Todo-Liste hat (gluecklicherweise) "
+ "nur %d Eintra%s.\n",sizeof(todo_data),
+ (sizeof(todo_data)>1?"ege":"g"))),0;
+ output="\n-----------------------------------------------------------------------------\n";
+ if (nr1>nr2) // Rueckwaerts
+ {
+ while(nr1>=nr2)
+ output+=sprintf("Eintrag Nr. %d von %s:\n%s\n\n",nr1--,
+ dtime(todo_data[nr1][0]),break_string(todo_data[nr1][1],78,5,
+ BS_LEAVE_MY_LFS));
+ }
+ else
+ {
+ nr1--;
+ while (nr1<nr2)
+ output+=sprintf("\nEintrag Nr. %d von %s:\n%s\n",(nr1+1),
+ dtime(todo_data[nr1][0]),break_string(todo_data[nr1++][1],78,5,
+ BS_LEAVE_MY_LFS));
+ }
+ More(output+"-----------------------------------------------------------------------------\n");
+ return 1;
+}
+
+private int _todo_verschieben(string cmdline)
+{
+ int from;
+ mixed to,dummy;
+ if (!(sscanf(cmdline,"verschieben %d nach %d",from,to)==2||
+ sscanf(cmdline,"verschieben %d nach %s",from,to)==2))
+ return 0;
+ from--;
+ if (stringp(to))
+ {
+ switch(to)
+ {
+ case "oben": to=from-1; break;
+ case "unten": to=from+1; break;
+ default: return 0;
+ }
+ }
+ else to--;
+ if (to==from) return notify_fail("Da ist der Eintrag ja schon!\n"),0;
+ if (from<0||from>=sizeof(todo_data)) return notify_fail(
+ "Wie willst Du einen nicht existenten Eintrag verschieben?\n"),0;
+ if (to<0||to>=sizeof(todo_data)) return notify_fail(
+ "Dahin kannst Du den Eintrag nicht verschieben.\n"),0;
+ dummy=todo_data[from];
+ if (to>from)
+ while (from++<to) todo_data[from-1]=todo_data[from];
+ else
+ while(from-->to) todo_data[from+1]=todo_data[from];
+ todo_data[to]=dummy;
+ printf("Eintrag wurde verschoben.\n");
+ return 1;
+}
+
+private int _todo_hilfe()
+{
+ printf(
+ "-------------------------------------------------------------------------------\n\n"
+ " Die Todo-Liste laesst sich mit den folgenden Befehlen steuern:\n\n"
+ " todo neu - Legt einen neuen Eintrag an.\n"
+ " todo loeschen <nummer> - Loescht einen Eintrag.\n"
+ " todo anzeigen [<nummer> [bis <nummer>]] - Zeigt die Todo-Liste an.\n"
+ " todo verschieben <nummer> nach <ziel> - Verschiebt einen Eintrag.\n\n"
+ " <ziel> kann eine Zahl oder die Worte 'oben' oder 'unten' sein.\n"
+ "-------------------------------------------------------------------------------\n");
+ return 1;
+}
+
+
+static int _todo(string cmdline)
+{
+ string *args;
+
+ cmdline=_unparsed_args(1);
+ notify_fail("Falsche Syntax. 'todo hilfe' zeigt eine Hilfe an.\n");
+ if (sizeof(cmdline))
+ {
+ args=explode(cmdline," ");
+ switch(args[0])
+ {
+ case "neu": return _todo_neu(cmdline);
+ case "loeschen": return _todo_loeschen(cmdline);
+ case "anzeigen": return _todo_anzeigen(cmdline);
+ case "verschieben": return _todo_verschieben(cmdline);
+ case "hilfe": return _todo_hilfe();
+ default: return 0;
+ }
+ }
+ return 0;
+}
diff --git a/std/shells/magier/upd.c b/std/shells/magier/upd.c
new file mode 100644
index 0000000..f09ea9a
--- /dev/null
+++ b/std/shells/magier/upd.c
@@ -0,0 +1,563 @@
+// MorgenGrauen MUDlib
+//
+// upd.c
+//
+// $Id: upd.c 8850 2014-06-13 21:34:44Z Zesstra $
+#pragma strict_types
+#pragma save_types
+#pragma range_check
+#pragma no_clone
+#pragma pedantic
+
+#define NEED_PROTOTYPES
+#include <magier.h>
+#include <player.h>
+#undef NEED_PROTOTYPES
+#include <debug_info.h>
+#include <wizlevels.h>
+#include <moving.h>
+#include <properties.h>
+#include <logging.h>
+#include <thing/properties.h>
+
+varargs static int _make(string file, int flags, int recursive);
+
+static mixed _query_localcmds()
+{
+ return ({({"upd","_upd",0,LEARNER_LVL}),
+ ({"load","_load",0,LEARNER_LVL})});
+}
+
+//
+// _save(): Spieler in Rettungsraum retten
+// obj: Spielerobjekt(?)
+// inv_save: Rettungsraumname
+// Rueckgabe: 0 wenn kein Spielerobjekt
+// Spielerobjekt, falls doch
+//
+
+static mixed _save( object obj, object inv_saver )
+{
+ if ( query_once_interactive(obj) )
+ {
+ obj->move( inv_saver, NO_CHECK );
+ return obj;
+ }
+ return 0;
+}
+
+
+//
+// _reload(): Objekt laden
+// file: Filename. Muss in der Form /xx/xx/xx.c vorliegen
+// clone: > 0 -> Es soll geclont werden, enthaelt Objektnummer des
+// Vorgaengerobjektes
+// flags: Kommandozeilenoptionen
+// err: Leerstring als Referenz uebergeben. Enthaelt nach dem
+// Aufruf vom _reload() die Fehlermeldungen als String.
+// Rueckgabe: Das neu erzeugte Objekt bzw. das schon vorhandene Objekt
+// bzw. 0, wenn Fehler auftrat.
+//
+
+private object _reload(string file, int clone, int flags, string err)
+{
+ object obj;
+
+ if (!obj=find_object(file[0..<3]+(clone?("#"+clone):"")))
+ {
+ int pos,pos2;
+ string bt;
+
+ if(file_size(file)<0)
+ {
+ if (file_size(file)==-1)
+ err = sprintf("upd: %s: Datei existiert nicht.\n", file);
+ else // directory
+ err = sprintf("upd: %s: Verzeichnisse koennen nicht geladen "
+ "werden.\n",file);
+ return obj; // 0
+ }
+ pos = max(file_size(__DEBUG_LOG__),0);
+
+ if ((err = (clone?catch(obj = clone_object(file)):
+ catch(load_object(file)) )) && (flags & UPD_B))
+ {
+ if (( pos2=file_size(__DEBUG_LOG__)) > pos )
+ err+=sprintf("\nBacktrace:\n%s",
+ read_bytes(__DEBUG_LOG__,pos, pos2-pos ));
+ else
+ err+=sprintf("\nKEIN BACKTRACE VERFUEGBAR!\n");
+ }
+ if (!err&&!obj&&(!obj = find_object(file[0..<3])))
+ err += sprintf( "upd: %s: Blueprint nach dem Laden zerstoert.\n",file );
+ }
+ else
+ err=sprintf("upd: Objekt existiert schon: %O\n",obj);
+ return obj;
+}
+
+
+//
+// _update(): File updaten -> Blueprint destructen
+// file: Filename
+// dummy: simulieren? (1->wird nicht aktualisiert)
+// flags: Kommandozeilenoptionen
+// Rueckgabe: -1: Keine Vollzugriff
+// 0: Objekt ist nicht geladen
+// 1: Operation wird durchgefuehrt
+//
+
+private varargs int _update(string file, int dummy, int flags)
+{
+ object obj;
+ string err;
+ if (!dummy && !objectp(obj = find_object(file))) return 0;
+ if (!IS_ARCH(this_object()))
+ {
+ // Schreibrechte nur pruefen, wenn echt aktualisiert werden soll.
+ if(!dummy && !MAY_WRITE(file))
+ return (printf("upd: %s: Keine Schreibrechte!\n",file), -1);
+ if(!MAY_READ(file))
+ return (printf("upd: %s: Keine Leserechte!\n", file), -1);
+ }
+ if (dummy) return 1;
+
+ if ( flags & UPD_D )
+ {
+ object *inv;
+ if (sizeof(inv = deep_inventory(obj)))
+ {
+ printf("upd: %s: Entferne Objekte im Inventar\n", file );
+ if (!(flags&UPD_H))
+ {
+ if(err=catch(filter_objects( inv, "remove", 1 )))
+ printf("upd: %s: Fehlgeschlagen. Grund:\n%s\n",
+ file,err);
+ }
+ if (sizeof(inv = deep_inventory(obj)))
+ filter(inv, function void (object ob)
+ {destruct(ob);});
+ }
+ }
+ if (!(flags&UPD_H))
+ {
+ if(err = catch(obj->remove()))
+ printf("upd: %s: remove() fehlgeschlagen. Aufruf von " +
+ "destruct().\n",file);
+ }
+ if(objectp(obj)) destruct(obj);
+ return 1;
+}
+
+
+//
+// _instance_upd(): Alle Objekte nach Clones des Objekts durchsuchen
+// file: Filename des Objektes
+// flags: Kommandozeilenargumente
+// obj: Aktuelles Objekt
+// instances: Zahl der gefundenen Instanzen
+//
+
+private void _instance_upd(string file, int flags, mixed obj, int instances,
+ int firstcall)
+{
+ int i;
+ if (firstcall)
+ printf("upd: %s: %s Instanzen.\n",file,flags&UPD_A?"Aktualisiere":"Suche");
+
+ while (get_eval_cost()>220000 && i < sizeof(obj))
+ {
+ if (!objectp(obj[i]))
+ instances--;
+ else
+ {
+ if (flags&UPD_F&&!(flags&UPD_S))
+ printf( "upd: %O gefunden in %s\n", obj[i],
+ environment(obj[i])?object_name(environment(obj[i]))
+ : "keiner Umgebung" );
+ if (flags&UPD_A) _make(object_name(obj[i]), flags & ~(UPD_A|UPD_F),1 );
+ }
+ i++;
+ }
+ if (i < sizeof(obj))
+ call_out( #'_instance_upd/*'*/,2,file,flags,obj[i..],instances,0);
+ else
+ printf( "upd: %s: %d Instanzen %s\n", file, instances,
+ (flags & UPD_A) ? "aktualisiert" : "gefunden" );
+ return;
+}
+
+
+//
+// _do_make(): Alle geerbten Objekte bearbeiten (fuer -m/-v)
+// file: Name des Files
+// clone: 0, wenn blueprint, ansonsten Clonenummer
+// flags: Kommandozeilenparameter
+// dep: geschachteltes Array mit Meldungen (wg. Rekursion)
+// ready: Array der schon bearbeiteten Objekte (wg. Rekursion)
+// Rueckgabe: Array der Objektnamen, die bearbeitet wurden
+// (Array in Array in ...)
+//
+
+varargs private int _do_make( string file,int clone,int flags,mixed dep,
+ string *ready )
+{
+ object obj;
+ string err;
+ string *ilist;
+ mixed downdeps;
+ int ret;
+
+ if (!pointerp(ready)) ready = ({});
+ ready += ({ file });
+
+ if ( !(obj = _reload(file,clone,flags,&err)))
+ {
+ dep += ({ err });
+ return 0;
+ }
+
+ ilist = inherit_list(obj)-ready;
+
+ downdeps = ({});
+
+ while (sizeof(ilist))
+ {
+ ret = _do_make( ilist[0],0,flags, &downdeps, &ready )||ret;
+ ilist[0..0] = ({});
+ ilist -= ready;
+ }
+
+ if ( ret||file_time(file)>program_time(obj)||(flags &UPD_I))
+ if ( _make( file, flags & ~(UPD_M|UPD_I) ,1) < 0 )
+ dep = ({ "{" + explode(file,"/")[<1] + "}", downdeps });
+ else{
+ dep = ({ "[" + explode(file,"/")[<1] + "]", downdeps });
+ ret = 1;
+ }
+ else if (flags&UPD_V) dep += ({ explode(file,"/")[<1], downdeps });
+ return ret;
+}
+
+
+//
+// _make_dep(): Ausgabe des Ererbungsbaumes
+// Objekte im Array dep
+// prefix enthaelt Zeilenanfang (fuer Rekursion)
+// Rueckgabe: String mit dem Vererbungsbaum des Objektes
+//
+
+private string _make_dep( mixed dep, string prefix )
+{
+ string ret;
+ int i, size;
+
+ ret="";
+ size=sizeof(dep);
+ for (i=0; i<size;i++)
+ if (pointerp(dep[i]))
+ ret += _make_dep(dep[i],prefix + (i < (size-1) ? "| ":" "));
+ else
+ ret += prefix + "+-" + dep[i] + "\n";
+ return ret;
+}
+
+
+//
+// _illegal_closure(): ist closure in arg an objekt gebunden?
+// arg: closure(-array/mapping)
+// Rueckgabe: 0 wenn alles okay
+// 1 wenn closure geloescht werden muss
+//
+
+private int _illegal_closure( mixed arg )
+{
+ int i, j;
+ string *indices;
+
+ if ( closurep(arg) && !objectp(query_closure_object(arg)) )
+ return 1;
+
+ if ( pointerp(arg) ){
+ for ( i = sizeof(arg); i--; )
+ if ( _illegal_closure(arg[i]) )
+ return 1;
+ }
+ else if ( mappingp(arg) ){
+ indices = m_indices(arg);
+ for ( i = sizeof(indices); i--; )
+ for ( j = get_type_info( arg, 1 ); j--; )
+ if ( _illegal_closure(arg[indices[i], j]) )
+ return 1;
+ }
+ return 0;
+}
+
+//
+// _make(): Update file
+// file: Filename
+// flags: Kommandozeilenargumente
+//
+
+varargs static int _make(string file, int flags,int recursive)
+{
+ string msg, err, blue;
+ int inst;
+ object obj, inv_saver;
+ mixed tmp;
+
+ msg = "";
+
+ if (!file) return printf( "upd: Kein Filename uebergeben!\n" ), RET_FAIL;
+
+// Filename in Blue, Objektname in blue, Instanznummer in inst
+
+ if (sscanf(file,"%s#%d",blue,inst)==2) blue += ".c";
+ else blue = file + (file[<2..]==".c" ? "" : ".c");
+
+// Alle Instanzen durchsuchen im Falle von -a oder -f
+
+ if ((flags & UPD_LOAD)&&find_object(file))
+ return printf("load: %s: Objekt ist schon geladen.\n",file),RET_OK;
+
+ if ( flags & (UPD_F|UPD_A))
+ {
+ if (inst) return printf( "upd: %s: Eine Instanz kann keine " +
+ "Clones haben.\n",file ), RET_FAIL;
+ if ((tmp=_update(file, 1,flags))==-1)
+ return printf( "upd: %s: Kein Vollzugriff auf die " +
+ "Datei erlaubt.\n",file), RET_FAIL;
+ if (tmp==0) return RET_FAIL;
+
+ tmp=clones(blue[0..<3],2);
+ if (sizeof(tmp))
+ call_out( #'_instance_upd/*'*/, 0, file,flags,tmp,sizeof(tmp),1);
+ else
+ printf( "upd: %s: Keine Clones vorhanden!\n", blue[0..<3]);
+
+ if ( (flags & UPD_F) && !(flags &(UPD_R|UPD_L|UPD_LOAD))) return RET_OK;
+ // Nichts laden -> Auch kein Backup
+ }
+
+// Backupraum festlegen
+
+ if( blue==INV_SAVE ) {
+ printf("upd: Achtung: Raum zum Zwischenspeichern soll geladen werden?!\n");
+ }
+ if ( !(inv_saver=load_object(INV_SAVE)) )
+ {
+ printf("upd: %s: Raum zum Zwischenspeichern des " +
+ "Rauminhalts ist nicht ladbar.\n" +
+ " %s\n",file,INV_SAVE);
+ return RET_FAIL;
+ }
+
+// Wenn das Objekt existiert bzw. Deep aktualisiert werden soll
+
+ if ( (!(flags&UPD_LOAD))&&
+ ((obj = find_object(file)) || (flags & (UPD_M|UPD_I))))
+ {
+ object *inv, env, *pl_inv;
+ mapping pro;
+ int i;
+ mixed configdata;
+ int restore_config;
+
+ // Wenn Objekt existiert, dann Inhalt und ggf. Daten aus Configure() oder
+ // Props sichern:
+ if (obj)
+ {
+ // im Fall UPD_C erfolgt _kein_ Auslesen und _keine_ Restauration
+ // mittels Configure()
+ if ( ! (flags & UPD_C ) )
+ {
+ catch(restore_config=(mixed)call_resolved(&configdata,obj,
+ "Configure",0);
+ publish);
+ // Wenn UPD_CONF gesetzt wird, _muss_ das Objekt ein oeffentliches
+ // Configure() definieren, sonst erfolgt Abbruch.
+ if ((flags & UPD_CONF) && !restore_config)
+ {
+ printf("upd: %s: hat kein Configure(), Zerstoerung abgebrochen.\n",file);
+ return RET_FAIL;
+ }
+ }
+ if (!(flags&UPD_D)&&(flags&(UPD_L|UPD_R)))
+ {
+ if (i=sizeof(inv=(all_inventory(obj)-({0}))))
+ {
+ mixed items;
+ // Herausbekommen, ob hier Items existieren, die per AddItem
+ // erzeugt werden. Die duerfen nicht gesichert werden.
+ items=(mixed)obj->QueryProp(P_ITEMS); // mixed, da array of arrays
+ if (pointerp(items)&&sizeof(items))
+ {
+ items=transpose_array(items)[0];
+ while (i--)
+ if (member(items, inv[i])==-1)
+ inv[i]->move(inv_saver,NO_CHECK);
+ }
+ else // In diesem Objekt sind keine Items gesetzt.
+ while (i--) inv[i]->move(inv_saver,NO_CHECK);
+ }
+ }
+ else
+ {
+ inv=map( deep_inventory(obj), #'_save/*'*/, inv_saver )-({0});
+ }
+ env = environment(obj);
+ if ( flags & UPD_C )
+ {
+ pro = (mapping)(obj->QueryProperties());
+ }
+ }
+ else inv = ({});
+
+// Ererbte Objekte durchsuchen.
+ if ( flags & (UPD_M|UPD_I) )
+ {
+ mixed dep;
+ dep = ({});
+ _do_make( blue, inst, flags & ~(UPD_M|UPD_L|UPD_R|UPD_F|UPD_A), &dep );
+ printf( _make_dep( dep, "" ) + "\n" );
+ }
+
+// Tatsaechlichen Update durchfuehren
+
+ if ( _update(file, 0, flags)< 0) return RET_FAIL;
+ msg += (inst ? "zerstoert" : "aktualisiert");
+
+// Neu laden ??
+ if ( flags & (UPD_R|UPD_L) )
+ {
+ if ( obj = _reload( blue,inst,flags, &err ) )
+ msg += ", " + (inst ? "neu geclont" : "neu geladen");
+
+// Neu geladen: Properties wiederherstellen, Closures filtern
+ if (!err)
+ {
+ if (!obj) obj = find_object(file);
+ // Wenn gewuenscht, Props zurueckschreiben (hat Prioritaet vor
+ // Configure(), weil explizit vom Magier angefordert).
+ if ( pro && (flags & UPD_C) )
+ {
+ string *names;
+
+ names = m_indices(pro);
+
+ // Closures in (mittlerweile) zerstoerten Objekten
+ // rausfiltern, damit die (hoffentlich korrekten) Closures
+ // im neu geclonten Objekt erhalten bleiben
+ for ( i = sizeof(names); i--; )
+ if ( _illegal_closure(pro[names[i], F_VALUE]) ||
+ _illegal_closure(pro[names[i], F_QUERY_METHOD]) ||
+ _illegal_closure(pro[names[i], F_SET_METHOD]) )
+ m_delete( pro, names[i] );
+
+ obj->SetProperties(pro);
+ msg += ", Properties gesetzt";
+ }
+ // Wenn kein UPD_C, wird ggf. das Ergebnis von Configure() wieder
+ // uebergeben.
+ else if (restore_config)
+ {
+ int conf_res;
+ if (!catch(conf_res=(int)obj->Configure(configdata); publish)
+ && conf_res == 1)
+ {
+ msg += ", (re-)konfiguriert";
+ }
+ else
+ {
+ msg += ", (Re-)Konfiguration fehlgeschlagen";
+ if (flags & UPD_CONF)
+ printf("upd: Daten von %s konnten nicht rekonfiguriert werden: "
+ "%O\n", file, configdata);
+ }
+ }
+ if (env)
+ {
+ if ( obj->move( env, NO_CHECK ) <= 0 )
+ printf( "upd: /%O konnte nicht in /%O zurueckbewegt werden\n",
+ obj, env );
+ else
+ msg += ", bewegt";
+ }
+ if (i=sizeof(inv))
+ {
+ while(i--) if (inv[i]) inv[i]->move(obj, NO_CHECK );
+ msg += ", Inhalt zurueckbewegt";
+ }
+ }
+ else
+ return printf( "upd: %s: %s", file, err ), RET_FAIL;
+ }
+ }
+ else
+ if ( !_update(file, 0, flags) && (flags & (UPD_L|UPD_LOAD)) )
+ if ( !_reload( blue, inst, flags, &err ) )
+ return printf( "%s: %s: %s", (flags&UPD_LOAD?"load":"upd"),file, err ),
+ RET_FAIL;
+ else
+ msg += "geladen";
+
+ if ( sizeof(msg)&&!(flags&UPD_S&&recursive) )
+ printf("%s: %s: %s.\n",(flags&UPD_LOAD?"load":"upd"),file,msg);
+ return RET_OK;
+}
+
+//
+// _upd: Objekte laden, zerstoeren und aktualisieren
+//
+
+static int _upd(string cmdline)
+{
+ int flags;
+ mixed *args;
+
+ cmdline=_unparsed_args();
+ args=parseargs(cmdline,&flags,UPD_OPTS,1);
+ if(flags==-1||!sizeof(args))
+ return USAGE("upd [-"+UPD_OPTS+"] <datei> [<datei> ..]");
+ if ((flags & UPD_C) && (flags & UPD_CONF))
+ {
+ printf("upd: -c und -C gleichzeitig werden nicht unterstuetzt.\n");
+ return 1;
+ }
+ args=file_list(args,MODE_UPD,0,"/");
+ if(!sizeof(args)) return printf("upd: Keine passende Datei gefunden!\n"),1;
+
+ args=map(args,(: $1[FULLNAME] :))-({0});
+
+ if(!sizeof(args))
+ {
+ printf("upd: Verzeichnisse koennen nicht aktualisiert werden!\n");
+ return 1;
+ }
+ asynchron(args,#'_make,flags,0,0);
+ return 1;
+}
+
+//
+// _load: Objekte laden
+//
+
+static int _load(string cmdline)
+{
+ int flags;
+ mixed *args;
+
+ cmdline=_unparsed_args();
+ args=parseargs(cmdline,&flags,"",1);
+ if(flags==-1||!sizeof(args))
+ return USAGE("load <datei> [<datei> ..]");
+ args=file_list(args,MODE_UPD,0,"/");
+ if(!sizeof(args)) return printf("load: Keine passende Datei gefunden!\n"),1;
+ args=map(args,(: (($1[FILESIZE]!=-2||find_object($1[FULLNAME]))?
+ $1[FULLNAME]:0) :))-({0});
+
+ if(!sizeof(args))
+ return printf("load: Verzeichnisse koennen nicht geladen werden!\n"),1;
+ asynchron(args,#'_make,UPD_LOAD,0,0);
+ return 1;
+}
diff --git a/std/shells/orc.c b/std/shells/orc.c
new file mode 100644
index 0000000..95c73f6
--- /dev/null
+++ b/std/shells/orc.c
@@ -0,0 +1,203 @@
+#pragma strong_types,save_types
+
+inherit "std/player/base";
+
+#include <properties.h>
+#include <attributes.h>
+#include <wizlevels.h>
+#include <health.h>
+#include <new_skills.h>
+#include <language.h>
+#include <combat.h>
+#include <defines.h>
+#include <defuel.h>
+
+/*
+ * Orks:
+ * Orks sind eigentlich boese und blutruenstig, was auch oft genug zum
+ * Vorschein tritt :) Wenn ein Ork zu heftig forscht, quengelt er rum
+ * und weigert sich, bis er nicht wieder ein bisschen Blut verspritzt
+ * hat,
+*/
+#define F_MAX 500
+#define F_DEG 3
+#define NO_EXAMINE ({ \
+ "Du knurrst: Ich will Blut, keine Bluemchen.", \
+ "Du grummelst: Bin ich ein Forscher, oder was?" \
+ })
+
+static int f_cnt, f_deg;
+
+int
+QueryFCnt() {
+ return f_cnt;
+}
+
+int
+SetFCnt(int fc) {
+ if(fc > -1 && fc < F_MAX)
+ f_cnt = fc;
+ return f_cnt;
+}
+
+int
+QueryFDeg() {
+ return f_deg;
+}
+
+void
+create() {
+ if (!clonep() || object_name(this_object()) == __FILE__[0..<3]) {
+ set_next_reset(-1);
+ return;
+ }
+
+ mixed res;
+
+ base::create();
+
+ f_cnt=0;
+ f_deg=F_DEG;
+
+ SetDefaultHome("/d/vland/morgoth/room/city/rathalle");
+ SetDefaultPrayRoom("/d/vland/morgoth/room/city/c0606");
+ SetProp(P_ATTRIBUTES_OFFSETS,([A_STR:3,A_INT:-1,A_CON:2]));
+ /* Kleine aeh grosse Muskelpakete */
+ SetProp(P_SKILL_ATTRIBUTE_OFFSETS,([SA_DAMAGE:110]));
+ SetProp(P_AVERAGE_SIZE,195);
+ SetProp(P_AVERAGE_WEIGHT,125000); // ziemlich schwer, viele Muskeln
+ SetProp(P_MATERIAL_KNOWLEDGE,([MATGROUP_DEAD:60,
+ MATGROUP_BIO:40,
+ MATGROUP_ELEMENTAL: 20,
+ MAT_BLOOD:100]));
+ SetProp(P_CHANNELS, QueryProp(P_CHANNELS) + ({"Uruk-Hai"}));
+ SetProp(P_RESISTANCE_STRENGTHS,
+ ([
+ DT_FIRE : -0.2,
+ DT_HOLY :0.3,
+ DT_UNHOLY : -0.2,
+ DT_ACID : 0.2 ]));
+
+ SetProp(P_MAX_FOOD,110);
+ SetProp(P_MAX_DRINK,110);
+ SetProp(P_MAX_ALCOHOL,150);
+ SetProp(P_DEFUEL_LIMIT_FOOD,50);
+ SetProp(P_DEFUEL_LIMIT_DRINK,70);
+ SetProp(P_DEFUEL_TIME_FOOD,300);
+ SetProp(P_DEFUEL_TIME_DRINK,400);
+ SetProp(P_DEFUEL_AMOUNT_FOOD,0.4);
+ SetProp(P_DEFUEL_AMOUNT_DRINK,0.35);
+
+ /* SP regenerieren sie nich ganz so schnell, dafuer sind sie
+ * ein bischen schneller bei Gift und Futter */
+ SetProp(P_SP_DELAY,HEAL_DELAY+1);
+ SetProp(P_POISON_DELAY,POISON_DELAY-1);
+ SetProp(P_FOOD_DELAY,FOOD_DELAY-1);
+
+ SetProp(P_MAGIC_RESISTANCE_OFFSET,
+ ([ MT_ANGRIFF : 500,
+ MT_ILLUSION : -250,
+ MT_BEHERRSCHUNG : -250,
+ MT_VERWANDLUNG : 500 ]));
+
+
+ if(!(res=QueryProp(P_HANDS)) || !pointerp(res) || (sizeof(res)<3))
+ res=({" mit starken Haenden",35,({DT_BLUDGEON, DT_RIP}) });
+ SetProp(P_HANDS,res);
+ /* Orks haben dicke Haut */
+ SetProp(P_BODY,20);
+
+ /* Groesse wird nur einmal gesetzt */
+ if(!QueryProp(P_SIZE)){
+ SetProp(P_SIZE,180+random(31));
+ Set(P_SIZE,SAVE,F_MODE_AS);
+ }
+
+ /* Dito Gewicht */
+ if(!QueryProp(P_WEIGHT) || (QueryProp(P_WEIGHT) == 75000)){
+ SetProp(P_WEIGHT,100000+random(25001)+random(25001));
+ Set(P_WEIGHT,SAVE,F_MODE_AS);
+ }
+}
+
+string
+_query_race() {
+ return "Ork";
+}
+
+string
+_query_real_race() {
+ return "Ork";
+}
+
+string
+_query_racedescr() {
+ return break_string("Ein Ork. Die brutale Macht des Boesen. Ein "
+ "erbitterter Kaempfer, ohne Furcht vor dem Tod. So stellst Du "
+ "Dir einen Ork vor.\nDiese Orks sehen vielleicht ausserlich so "
+ "aus: Eine dicke und dunkle, lederartige Haut, die sicher "
+ "einiges an Schlaegen abhaelt. Lange Eckzaehne, die sicher boese "
+ "Wunden reissen koennen.\nDu spuerst, dass diese Orks hier ein "
+ "wenig anders sind. Ihren Drang nach dem Blut ihrer Feinde scheinen "
+ "sie recht gut unter Kontrolle zu haben, die meiste Zeit zumindest. "
+ "Sie sind in der Lage, friedlich zwischen den anderen Rassen zu "
+ "wandeln. Dennoch sind vor allem die Uruk-Hai Orks als Gegner nicht "
+ "zu unterschaetzen, sollte es doch einmal zu einem Kampf kommen.",
+ 78,0,BS_LEAVE_MY_LFS);
+}
+
+int
+QueryAllowSelect() {
+ return 1;
+}
+
+string
+*_query_racestring() {
+ if (QueryProp(P_GENDER)==FEMALE)
+ return ({"Orkin","Orkin","Orkin","Orkin"});
+ return ({"Ork","Orkes","Ork","Ork"});
+}
+
+string
+_query_default_guild(){
+ return "urukhai";
+}
+
+mixed
+RaceDefault(string arg) {
+ if (!arg)
+ return 0;
+ switch(arg) {
+ case P_HANDS :
+ return ({" mit starken Haenden",35,({DT_BLUDGEON,DT_RIP}) });
+ case P_BODY :
+ return 25;
+ }
+ return base::RaceDefault(arg);
+}
+
+protected void heart_beat() {
+ ::heart_beat();
+
+ if(f_cnt > 0 && !--f_deg) {
+ f_cnt--;
+ f_deg=F_DEG;
+ }
+}
+
+void
+Attack(object enemy) {
+ if(f_cnt > 0)
+ f_cnt--;
+ return ::Attack(enemy);
+}
+
+varargs int
+_examine(string str, int mode) {
+
+ if(++f_cnt > F_MAX) {
+ tell_object(this_object(),break_string(NO_EXAMINE[random(sizeof(NO_EXAMINE))],78));
+ return 1;
+ }
+ return ::_examine(str,mode);
+}
diff --git a/std/shells/testie.c b/std/shells/testie.c
new file mode 100644
index 0000000..18c42af
--- /dev/null
+++ b/std/shells/testie.c
@@ -0,0 +1,6 @@
+#pragma strong_types,save_types
+
+inherit "/std/shells/human";
+
+int QueryAllowSelect() { return 0; }
+