// 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>
#include <player/telnetneg.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(QueryProp(P_TELNET_KEEPALIVE_DELAY)))
  {
    // 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 {
    string rstring = (QueryProp(P_GENDER)==FEMALE ? "Magierin" : "Magier");
    return allocate(4, rstring);
  }
}


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);
}

