/
lib/banish/
lib/d/
lib/doc/
lib/doc/domains/
lib/doc/efun/
lib/doc/examples/
lib/doc/examples/armour/
lib/doc/examples/contain/
lib/doc/examples/food/
lib/doc/examples/magic/
lib/doc/examples/monster/
lib/doc/examples/room/
lib/doc/examples/weapons/
lib/function/
lib/include/
lib/include/fn_specs/
lib/include/skills/
lib/info/
lib/inherit/base/
lib/log/
lib/manuals/312/
lib/news/
lib/obj/party/
lib/objects/components/
lib/open/
lib/open/library/
lib/open/party/
lib/players/
lib/players/zilanthius/
lib/room/
lib/room/city/arena/
lib/room/city/creator/
lib/room/city/garden/monst/
lib/room/city/obj/
lib/room/city/shop/
lib/room/death/
lib/room/registry/
lib/secure/
lib/secure/UDP_CMD_DIR/
lib/skills/
lib/skills/fighter/
lib/skills/thief/
lib/usr/
lib/usr/creators/
lib/usr/players/
#include <mudlib.h>
inherit BASE;

#include <rnd_name.h>

#define GET_LOADED_SPELL(XX,YY,ZZ) \
  (mixed *)clone_object("obj/shadows/get_spell")->get_loaded_spell(XX,YY,ZZ,1)

#define BINS   ({ "/skills/mage/", "/skills/cleric/", })
#define WAND_ACTIVATION_TIME  3   /* Time to cast any spell      */
#define WAND_USAGE_TIME       5   /* Time between casting spells */

string *spells, *class, casting_msg;
int charges, max_charges, cast_level;

#ifdef WAND_USAGE_TIME
int last_time;
#endif

/********************************************************************/
/* query */

/* These are necessary hooks to work as a wand in spell system */

int query_charges()   { return charges;                        }
int query_cast_level(){ return cast_level;                     }



int query_value() { return ((100 * cast_level) + charges); }

int query_max_charges(){ return max_charges;  }

string *query_spells() { return spells;                 }
string *query_class()  { return (class) ? class : ({}); }
string query_casting_msg() { return casting_msg;        }

/********************************************************************/
/* sets */

int set_charges(int i) {
  if(!max_charges) max_charges = i;
  return charges = i;
}

int set_max_charges(int i)     { return max_charges = i; }
int set_cast_level(int i)      { return cast_level = i;  }

string *set_spells(string *arr) { return spells = (arr) ? arr : ({}); }
string *set_class(string *arr)  { return class = (arr) ? arr : ({});  }
string set_casting_msg(string s){ return casting_msg = s;             }


void add_spell(mixed arg) {
  int i;

  if(!pointerp(arg)) arg = ({ arg, });
  if(!spells) spells =({});  
  for(i = 0; i < sizeof(arg); i++) {
    if(member_array(arg[i], spells) == -1) {
      spells += ({ make_name(arg[i]), arg[i], });
    }
  }
}
 
/********************************************************************/
/* adj */

int adj_charges(int i) {  
  charges += i; 
  if(charges > max_charges) charges = max_charges;
  if(charges < 0) charges = 0;
  return charges;
}  


init() {
  int i, j;

  ::init();
  if(!spells) return;
  if(!class) class = ({ "fighter", "thief", "mage", "cleric", });
  if(!casting_msg) {
    casting_msg = "The @@query_name:$this_object()$@@ begins to feel warm.\n";
  }
  for(j = 0; j < sizeof(class); j++) {
    if(this_player()->query_class(class[j])) {
      for(i = 0; i < sizeof(spells); i += 2) {
        add_action("load_spell", spells[i]);
      }
      break;
    }
  }
}

void activate_wand(string *spell) {
  if(!this_player()) return; /* player logged out */
  if(sizeof((mixed *)this_player()->query_loaded_spell())) { /* wait state */
    call_out("activate_wand", 2, spell);
    return;
  }
  call_other(spell[0], spell[1], spell[2], this_object()); /* invoke spell  */
  this_player()->cast_spell_at_target();                   /* force casting */
}

status load_spell(string str) {   /* start cast spell */
  string verb, spell, spell2;
  int i;

  verb = query_verb();

#ifdef WAND_USAGE_TIME
  if(last_time + WAND_USAGE_TIME + WAND_ACTIVATION_TIME > time()) {
    write("Nothing Happens.\n");
    return 1;
  }
#endif

  if(find_call_out("activate_wand") != -1) {
    write("Nothing Happens.\n");
    return 1;
  }
  if((i = member_array(verb, spells)) == -1) return 0;

  spell = spells[i+1];
  if(sscanf(spell,"%s %s", spell, spell2) == 2) {
    if(str) 
      str = spell2 +" "+ str;
    else
      str = spell2;
  }
  for(i = 0; i < sizeof(BINS); i++) {
    if(file_size(BINS[i] + spell +".c") > 0) {
      write(process_msg(casting_msg));
      say(this_player()->query_name() +"'s "+ query_name() 
         +" begins to glow...\n");

      /* This is Ugly..but it solves some notify fail problems */
      
      if(!sizeof(GET_LOADED_SPELL(spell,str,this_object()))) return 0;

#if (WAND_ACTIVATION_TIME > 0)
      call_out("activate_wand", WAND_ACTIVATION_TIME,
#else
      activate_wand(
#endif
               ({ BINS[i] + spell, spell, str, }));

#ifdef WAND_USAGE_TIME
      last_time = time();
#endif
      return 1;
    }
  }
  return 0;
}


status get() { return 1; }

void end_spell() {     /* this is called when the spell finishes */
  write("The "+ query_name() +" starts to cools down.\n");
}

/* for enchant an item spell info */

string query_charges_string() {
  if(spells && sizeof(spells)) {
    return "The "+ query_name() +" has "+ charges +" charges.\n";
  }
}

string query_classes_string() {
  if(class && sizeof(class)) {
    return "The "+ query_name() +" can only be used by "+
           implode(class, ", ") +".\n";
  }
}

string query_level_string() {
  if(cast_level) {
    return "The "+ query_name() +" casts spells at a skill level of "+
         cast_level +".\n";
  }
}

string query_spell_triggers() {
  int i;
  string str;

  if(spells) {
    for(i = 0; i < sizeof(spells); i += 2) {
      if(!str) str = "";
      str += "The word '"+ spells[i] +"' triggers the spell '"
          + spells[i+1] +"'.\n";
    }
  }
  return str;
}

string query_wand_info() {
  return "@@query_charges_string:$this_object()$@@"+
         "@@query_classes_string:$this_object()$@@"+
         "@@query_level_string:$this_object()$@@"+
         "@@query_spell_triggers:$this_object()$@@";
}