ackfuss-4.3.2/area/boards/
ackfuss-4.3.2/npcs/a/
ackfuss-4.3.2/npcs/b/
ackfuss-4.3.2/npcs/c/
ackfuss-4.3.2/npcs/d/
ackfuss-4.3.2/npcs/e/
ackfuss-4.3.2/npcs/f/
ackfuss-4.3.2/npcs/h/
ackfuss-4.3.2/npcs/i/
ackfuss-4.3.2/npcs/k/
ackfuss-4.3.2/npcs/l/
ackfuss-4.3.2/npcs/n/
ackfuss-4.3.2/npcs/o/
ackfuss-4.3.2/npcs/p/
ackfuss-4.3.2/npcs/r/
ackfuss-4.3.2/npcs/s/
ackfuss-4.3.2/npcs/w/
ackfuss-4.3.2/player/c/
ackfuss-4.3.2/reports/
/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  Ack 2.2 improvements copyright (C) 1994 by Stephen Dooley              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *       _/          _/_/_/     _/    _/     _/    ACK! MUD is modified    *
 *      _/_/        _/          _/  _/       _/    Merc2.0/2.1/2.2 code    *
 *     _/  _/      _/           _/_/         _/    (c)Stephen Zepp 1998    *
 *    _/_/_/_/      _/          _/  _/             Version #: 4.3          *
 *   _/      _/      _/_/_/     _/    _/     _/                            *
 *                                                                         *
 *                        http://ackmud.nuc.net/                           *
 *                        zenithar@ackmud.nuc.net                          *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

/* Original 'magic.c' now contains the first half of the file, while the
   second half is in this 'magic2.c' file.  -S- */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "globals.h"
#ifndef DEC_MAGIC_H
#include "magic.h"
#endif

extern bool deathmatch;


bool spell_invis( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim;
   OBJ_DATA *ob;
   AFFECT_DATA af;

   if( target_name[0] == '\0' )
   {
      send_to_char( "Make who or what invisible?\n\r", ch );
      return FALSE;
   }


   if( ( victim = get_char_room( ch, target_name ) ) != NULL )
   {
      if( IS_AFFECTED( victim, AFF_INVISIBLE ) || item_has_apply( victim, ITEM_APPLY_INV ) )
         return ( ch == victim ? FALSE : TRUE );

      act( "$n fades out of existence.", victim, NULL, NULL, TO_ROOM );
      af.type = sn;
      af.duration = 4 + ( level / 5 );
      af.location = APPLY_NONE;
      af.modifier = 0;
      af.bitvector = AFF_INVISIBLE;
      affect_to_char( victim, &af );
      send_to_char( "You fade out of existence.\n\r", victim );
      return TRUE;
   }
   else if( ( ob = get_obj_carry( ch, target_name ) ) != NULL )
   {
      if( !IS_SET( ob->extra_flags, ITEM_INVIS ) )
      {
         SET_BIT( ob->extra_flags, ITEM_INVIS );
         act( "$p shimmers out of visibility.", ch, ob, NULL, TO_CHAR );
         act( "$p shimmers out of visibility.", ch, ob, NULL, TO_ROOM );
         return TRUE;
      }
      else
      {
         act( "$p is already invisible!", ch, ob, NULL, TO_CHAR );
         return FALSE;
      }
   }
   else
   {
      send_to_char( "Couldn't find that person or object.\n\r", ch );
      return FALSE;
   }
   return FALSE;
}


bool spell_know_alignment( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   char *msg;
   int ap;

   ap = victim->alignment;

   if( ap > 700 )
      msg = "$N has an aura as white as the driven snow.";
   else if( ap > 350 )
      msg = "$N is of excellent moral character.";
   else if( ap > 100 )
      msg = "$N is often kind and thoughtful.";
   else if( ap > -100 )
      msg = "$N doesn't have a firm moral commitment.";
   else if( ap > -350 )
      msg = "$N lies to $S friends.";
   else if( ap > -700 )
      msg = "$N's slash DISEMBOWELS you!";
   else
      msg = "I'd rather just not say anything at all about $N.";

   act( msg, ch, NULL, victim, TO_CHAR );
   return TRUE;
}



bool spell_lightning_bolt( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   static const sh_int dam_each[] = {
      0,
      0, 0, 0, 0, 0, 0, 0, 0, 25, 28,
      31, 34, 37, 40, 40, 41, 42, 42, 43, 44,
      44, 45, 46, 46, 47, 48, 48, 49, 50, 50,
      51, 52, 52, 53, 54, 54, 55, 56, 56, 57,
      58, 58, 59, 60, 60, 61, 62, 62, 63, 64
   };
   int dam;

   level = UMIN( level, sizeof( dam_each ) / sizeof( dam_each[0] ) - 1 );
   level = UMAX( 0, level );
   dam = number_range( dam_each[level] / 2, dam_each[level] * 2 );
   if( saves_spell( level, victim ) )
      dam /= 2;

   sp_damage( obj, ch, victim, dam, REALM_SHOCK, sn, TRUE );
   return TRUE;
}



bool spell_locate_object( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   char buf[MAX_INPUT_LENGTH];
   OBJ_DATA *ob;
   OBJ_DATA *in_obj;
   bool found;

   found = FALSE;
   for( ob = first_obj; ob != NULL; ob = ob->next )
   {
      if( !can_see_obj( ch, ob ) || !is_name( target_name, ob->name )
          || IS_SET( ob->extra_flags, ITEM_RARE )
          || ( ob->item_type == ITEM_PIECE )
          || ( IS_SET( ob->extra_flags, ITEM_UNIQUE ) ) || ( !str_prefix( target_name, "unique" ) ) )
         continue;



      for( in_obj = ob; in_obj->in_obj != NULL; in_obj = in_obj->in_obj )
         ;
      if( ( in_obj->carried_by != NULL )
          && ( IS_IMMORTAL( in_obj->carried_by )
               || ( !IS_NPC( in_obj->carried_by )
                    && IS_WOLF( in_obj->carried_by )
                    && ( IS_SHIFTED( in_obj->carried_by ) || ( IS_RAGED( in_obj->carried_by ) ) ) ) ) )
         break;

      if( in_obj->carried_by != NULL )
      {
         found = TRUE;
         sprintf( buf, "%s carried by %s.\n\r",
                  ob->short_descr, can_see( ch, in_obj->carried_by ) ? PERS( in_obj->carried_by, ch ) : "someone" );
      }
      else
      {
         found = TRUE;
         sprintf( buf, "%s in %s.\n\r", ob->short_descr, in_obj->in_room == NULL ? "somewhere" : in_obj->in_room->name );
      }

      buf[0] = UPPER( buf[0] );
      send_to_char( buf, ch );
   }

   if( !found )
      send_to_char( "Nothing like that in hell, earth, or heaven.\n\r", ch );

   return TRUE;
}



bool spell_magic_missile( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   int cnt;
   int hits;
   static const sh_int dam_each[] = {
      0,
      3, 3, 4, 4, 5, 6, 6, 6, 6, 6,
      7, 7, 7, 7, 7, 8, 8, 8, 8, 8,
      9, 9, 9, 9, 9, 10, 10, 10, 10, 10,
      11, 11, 11, 11, 11, 12, 12, 12, 12, 12,
      13, 13, 13, 13, 13, 14, 14, 14, 14, 14
   };
   int dam;

   level = UMIN( level, sizeof( dam_each ) / sizeof( dam_each[0] ) - 1 );
   level = UMAX( 0, level );
   dam = number_range( dam_each[level] / 2, dam_each[level] * 2 );
   if( saves_spell( level, victim ) )
      dam /= 2;
   cnt = 1 + ( level >= 30 ) + ( level >= 60 ) + ( level >= 80 );
   for( hits = 0; hits < cnt; hits++ )
   {
      sp_damage( obj, ch, victim, dam, REALM_IMPACT, sn, TRUE );

   }

   return TRUE;
}



bool spell_mass_invis( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   AFFECT_DATA af;
   CHAR_DATA *gch;

   for( gch = ch->in_room->first_person; gch != NULL; gch = gch->next_in_room )
   {
      if( IS_AFFECTED( gch, AFF_INVISIBLE ) || item_has_apply( gch, ITEM_APPLY_INV ) )
         continue;
      act( "$n slowly fades out of existence.", gch, NULL, NULL, TO_ROOM );
      send_to_char( "You slowly fade out of existence.\n\r", gch );
      af.type = sn;
      af.duration = 4 + ( level / 5 );
      af.location = APPLY_NONE;
      af.modifier = 0;
      af.bitvector = AFF_INVISIBLE;
      affect_to_char( gch, &af );
   }
   send_to_char( "Ok.\n\r", ch );

   return TRUE;
}



bool spell_null( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   send_to_char( "That's not a spell!\n\r", ch );
   return FALSE;
}



bool spell_pass_door( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   AFFECT_DATA af;

   if( IS_AFFECTED( victim, AFF_PASS_DOOR ) || item_has_apply( victim, ITEM_APPLY_PASS_DOOR ) )
      return FALSE;
   af.type = sn;
   af.duration = 2 + ( level / 20 );
   af.location = APPLY_NONE;
   af.modifier = 0;
   af.bitvector = AFF_PASS_DOOR;
   affect_to_char( victim, &af );
   act( "$n turns translucent.", victim, NULL, NULL, TO_ROOM );
   send_to_char( "You turn translucent.\n\r", victim );
   return TRUE;
}



bool spell_poison( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   AFFECT_DATA af;

   if( saves_spell( level, victim ) )
      return TRUE;
   af.type = sn;
   af.duration = 12 + ( level / 10 );
   af.location = APPLY_STR;
   af.modifier = -2;
   af.bitvector = AFF_POISON;
   affect_join( victim, &af );
   send_to_char( "You feel very sick.\n\r", victim );
   act( "$n looks very sick.", victim, NULL, NULL, TO_ROOM );
   return TRUE;
}



bool spell_protection( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   AFFECT_DATA af;

   if( IS_AFFECTED( victim, AFF_PROTECT ) || item_has_apply( victim, ITEM_APPLY_PROT ) )
      return ( ch == victim ? FALSE : TRUE );
   af.type = sn;
   af.duration = 8 + ( level / 5 );
   af.location = APPLY_NONE;
   af.modifier = 0;
   af.bitvector = AFF_PROTECT;
   affect_to_char( victim, &af );
   send_to_char( "You feel protected.\n\r", victim );
   act( "$n looks better protected.", victim, NULL, NULL, TO_ROOM );
   return TRUE;
}



bool spell_refresh( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   if( ch->carry_weight >= can_carry_w( ch ) )
   {
      send_to_char( "That's not gonna help, you are carrying too much wieght!\n\r", ch );
      return FALSE;
   }
   victim->move = UMIN( victim->move + level, victim->max_move );
   send_to_char( "You feel less tired.\n\r", victim );
   act( "$n looks less tired.", victim, NULL, NULL, TO_ROOM );
   return TRUE;
}



bool spell_remove_curse( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   if( is_affected( victim, gsn_curse ) )
   {
      affect_strip( victim, gsn_curse );
      send_to_char( "You feel better.\n\r", victim );
      act( "$n looks more Holy.", victim, NULL, NULL, TO_ROOM );
   }

   return TRUE;
}



bool spell_sanctuary( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   AFFECT_DATA af;

   if( IS_AFFECTED( victim, AFF_SANCTUARY ) || item_has_apply( victim, ITEM_APPLY_SANC ) )
      return ( ch == victim ? FALSE : TRUE );
   af.type = sn;
   af.duration = 5 + ( level / 20 );
   af.location = APPLY_NONE;
   af.modifier = 0;
   af.bitvector = AFF_SANCTUARY;
   affect_to_char( victim, &af );
   act( "$n is surrounded by a white aura.", victim, NULL, NULL, TO_ROOM );
   send_to_char( "You are surrounded by a white aura.\n\r", victim );
   return TRUE;
}



bool spell_sense_evil( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   AFFECT_DATA af;

   if( IS_AFFECTED( victim, AFF_DETECT_EVIL ) )
      return FALSE;
   af.type = sn;
   af.duration = 5 + ( level / 10 );
   af.modifier = 0;
   af.location = APPLY_NONE;
   af.bitvector = AFF_DETECT_EVIL;
   affect_to_char( victim, &af );
   send_to_char( "Your eyes tingle.\n\r", victim );
   act( "$n's eyes glow briefly.", victim, NULL, NULL, TO_ROOM );
   return TRUE;
}



bool spell_shield( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   AFFECT_DATA af;

   if( is_affected( victim, sn ) )
      return FALSE;
   af.type = sn;
   af.duration = 4 + ( level / 5 );
   af.location = APPLY_AC;
   af.modifier = -20 - get_psuedo_level( ch ) / 5;
   af.bitvector = 0;
   affect_to_char( victim, &af );
   act( "$n is surrounded by a force shield.", victim, NULL, NULL, TO_ROOM );
   send_to_char( "You are surrounded by a force shield.\n\r", victim );
   return TRUE;
}



bool spell_shocking_grasp( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   static const int dam_each[] = {
      0,
      0, 0, 0, 0, 0, 0, 20, 25, 29, 33,
      36, 39, 39, 39, 40, 40, 41, 41, 42, 42,
      43, 43, 44, 44, 45, 45, 46, 46, 47, 47,
      48, 48, 49, 49, 50, 50, 51, 51, 52, 52,
      53, 53, 54, 54, 55, 55, 56, 56, 57, 57
   };
   int dam;

   level = UMIN( level, sizeof( dam_each ) / sizeof( dam_each[0] ) - 1 );
   level = UMAX( 0, level );
   dam = number_range( dam_each[level] / 2, dam_each[level] * 2 );
   if( saves_spell( level, victim ) )
      dam /= 2;
   sp_damage( obj, ch, victim, dam, REALM_SHOCK, sn, TRUE );
   return TRUE;
}



bool spell_sleep( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   AFFECT_DATA af;

   if( IS_AFFECTED( victim, AFF_SLEEP ) || level < victim->level || saves_spell( level, victim ) )
      return TRUE;

   af.type = sn;
   af.duration = 4 + ( level / 15 );
   af.location = APPLY_NONE;
   af.modifier = 0;
   af.bitvector = AFF_SLEEP;
   affect_join( victim, &af );

   if( IS_AWAKE( victim ) )
   {
      send_to_char( "You feel very sleepy ..... zzzzzz.\n\r", victim );

      /*
       * will stop the char from attackin' right away (4-24-96)
       * -Damane- 
       */
      if( victim->position == POS_FIGHTING )
         stop_fighting( victim, TRUE );
      do_sleep( victim, "" );
   }

   return TRUE;
}



bool spell_stone_skin( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   AFFECT_DATA af;

   if( is_affected( ch, sn ) || is_affected( ch, skill_lookup( "stone skin" ) ) )
      return FALSE;
   af.type = sn;
   af.duration = 5 + ( level / 12 );
   af.location = APPLY_AC;
   af.modifier = -40 - get_psuedo_level( ch ) / 10;
   af.bitvector = 0;
   affect_to_char( victim, &af );
   act( "$n's skin turns to stone.", victim, NULL, NULL, TO_ROOM );
   send_to_char( "Your skin turns to stone.\n\r", victim );
   return TRUE;
}



bool spell_summon( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim;
   char buf[MAX_STRING_LENGTH];

   if( ( victim = get_char_world( ch, target_name ) ) == NULL
       || victim == ch
       || victim->in_room == NULL
       || IS_SET( victim->in_room->room_flags, ROOM_SAFE )
       || IS_SET( victim->in_room->room_flags, ROOM_NO_RECALL )
       || !( IS_SET( victim->in_room->area->flags, AREA_TELEPORT ) )
       || victim->level >= level + 10
       || victim->fighting != NULL
       || ( IS_NPC( victim ) && saves_spell( level, victim ) )
       || room_is_private( ch->in_room ) || ( ch->in_room->area->max_level < ( victim->level - 15 ) ) )
   {
      send_to_char( "You failed.\n\r", ch );
      return TRUE;
   }
   if( ( IS_SET( victim->act, PLR_NOSUMMON ) ) || ( IS_NPC( victim ) && ( victim->level > ( level - 21 ) ) ) )
   {
      send_to_char( "You seemed unable to snatch your victim!\n\r", ch );
      send_to_char( "You feel a slight tugging sensation.\n\r", victim );
      return TRUE;
   }

   act( "$n disappears suddenly.", victim, NULL, NULL, TO_ROOM );
   char_from_room( victim );
   char_to_room( victim, ch->in_room );
   act( "$n arrives suddenly.", victim, NULL, NULL, TO_ROOM );
   sprintf( buf, "%s has summoned you!!", ch->name );
   send_to_char( buf, victim );
   do_look( victim, "auto" );
   return TRUE;
}



bool spell_teleport( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   ROOM_INDEX_DATA *pRoomIndex;

   if( deathmatch )
   {
      send_to_char( "Not during a @@eDeath Match@@N!!\n\r", ch );
      return FALSE;
   }
   if( victim->in_room == NULL
       || IS_SET( victim->in_room->room_flags, ROOM_NO_RECALL )
       || ( !IS_NPC( ch ) && victim->fighting != NULL )
       || ( victim != ch && ( saves_spell( level, victim ) || saves_spell( level, victim ) ) ) )
   {
      send_to_char( "You failed.\n\r", ch );
      return TRUE;
   }

   for( ;; )
   {
      pRoomIndex = get_room_index( number_range( 0, 32767 ) );
      if( pRoomIndex == NULL )
         continue;
      if( !IS_SET( pRoomIndex->room_flags, ROOM_PRIVATE )
          && !IS_SET( pRoomIndex->room_flags, ROOM_SOLITARY ) && IS_SET( pRoomIndex->area->flags, AREA_TELEPORT ) )
         break;
   }

   act( "$n slowly fades out of existence.", victim, NULL, NULL, TO_ROOM );
   char_from_room( victim );
   char_to_room( victim, pRoomIndex );
   act( "$n slowly fades into existence.", victim, NULL, NULL, TO_ROOM );
   do_look( victim, "auto" );
   return TRUE;

}



bool spell_ventriloquate( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   char buf1[MAX_STRING_LENGTH];
   char buf2[MAX_STRING_LENGTH];
   char speaker[MAX_INPUT_LENGTH];
   CHAR_DATA *vch;

   target_name = one_argument( target_name, speaker );

   sprintf( buf1, "%s says '%s'.\n\r", speaker, target_name );
   sprintf( buf2, "Someone makes %s say '%s'.\n\r", speaker, target_name );
   buf1[0] = UPPER( buf1[0] );

   for( vch = ch->in_room->first_person; vch != NULL; vch = vch->next_in_room )
   {
      if( !is_name( speaker, vch->name ) )
         send_to_char( saves_spell( level, vch ) ? buf2 : buf1, vch );
   }

   return TRUE;
}

bool spell_warcry( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
/* --Stephen 
 * FIXME: make this a warrior skill, check for bless.
 */
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   AFFECT_DATA af;

   if( victim->position == POS_FIGHTING || is_affected( victim, sn ) )
      return FALSE;
   af.type = sn;
   af.duration = 4 + level;
   af.location = APPLY_HITROLL;
   af.modifier = level / 16;
   af.bitvector = 0;
   affect_to_char( victim, &af );

   af.location = APPLY_SAVING_SPELL;
   af.modifier = 0 - level / 16;
   affect_to_char( victim, &af );
   send_to_char( "You feel righteous.\n\r", victim );
   if( ch != victim )
      send_to_char( "Ok.\n\r", ch );
   return TRUE;
}


bool spell_weaken( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   AFFECT_DATA af;

   if( is_affected( victim, sn ) || saves_spell( level, victim ) )
      return TRUE;
   af.type = sn;
   af.duration = 1 + ( level / 16 );
   af.location = APPLY_STR;
   af.modifier = -2;
   af.bitvector = 0;
   affect_to_char( victim, &af );
   send_to_char( "You feel weaker.\n\r", victim );
   if( ch != victim )
      send_to_char( "Ok.\n\r", ch );
   return TRUE;
}



/*
 * For Ack! : Level 66 Priest spell - allow 100% recall.
 */
bool spell_word_of_recall( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   ROOM_INDEX_DATA *location;

   act( "$n requests Holy transport!", victim, NULL, NULL, TO_ROOM );
   if( IS_AFFECTED( victim, AFF_CURSE ) )
   {
      send_to_char( "The Gods do not transport cursed players!\n\r", ch );
      return FALSE;
   }

   if( IS_NPC( victim ) || victim->level < 6 )
      location = get_room_index( ROOM_VNUM_TEMPLE );
   else
      location = get_room_index( race_table[victim->race].recall );

   if( location == NULL )
   {
      send_to_char( "You are completely lost.\n\r", victim );
      return FALSE;
   }

   if( victim->in_room == location )
      return FALSE;

   if( IS_SET( victim->in_room->room_flags, ROOM_NO_RECALL ) )
   {
      send_to_char( "Some strange force prevents your transport.\n\r", victim );
      return TRUE;
   }

   if( victim->fighting != NULL )
      stop_fighting( victim, TRUE );

   act( "$n is engulfed by a stream of blue light!", victim, NULL, NULL, TO_ROOM );
   char_from_room( victim );
   char_to_room( victim, location );
   act( "$n arrives, carried by a blue stream of light!", victim, NULL, NULL, TO_ROOM );
   do_look( victim, "auto" );
   return TRUE;
}



/*
 * NPC spells.
 */
bool spell_acid_breath( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   /*
    * Fixed the nice bug that referenced the _caster's_ equipment,
    * * so that it checks the victim's instead *laugh* -S-
    */

   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   OBJ_DATA *obj_lose;
   OBJ_DATA *obj_next;
   int dam;
   int hpch;

   if( number_percent(  ) < 2 * level && !saves_spell( level, victim ) )
   {
      OREF( obj_next, OBJ_NEXTCONTENT );
      for( obj_lose = victim->first_carry; obj_lose != NULL; obj_lose = obj_next )
      {
         int iWear;

         obj_next = obj_lose->next_in_carry_list;

         if( number_bits( 2 ) != 0 )
            continue;

         switch ( obj_lose->item_type )
         {
            case ITEM_ARMOR:
               if( obj_lose->value[0] > 0 )
               {
                  act( "$p is pitted and etched!", victim, obj_lose, NULL, TO_CHAR );
                  if( ( iWear = obj_lose->wear_loc ) != WEAR_NONE )
                     victim->armor -= apply_ac( obj_lose, iWear );
                  obj_lose->value[0] -= 1;
                  obj_lose->cost = 0;
                  if( iWear != WEAR_NONE )
                     victim->armor += apply_ac( obj_lose, iWear );
               }
               break;

            case ITEM_CONTAINER:

            {
               OBJ_DATA *content;
               OBJ_DATA *content_next;
               act( "$p fumes and dissolves!", victim, obj_lose, NULL, TO_CHAR );
               for( content = obj_lose->first_in_carry_list; content; content = content_next )
               {
                  content_next = content->next_in_carry_list;
                  obj_from_obj( content );
                  obj_to_room( content, victim->in_room != NULL ? victim->in_room : get_room_index( ROOM_VNUM_LIMBO ) );
               }
               extract_obj( obj_lose );
               break;
            }
         }
      }
      OUREF( obj_next );

   }

   hpch = UMAX( 10, ch->hit );
   dam = number_range( hpch / 16 + 1, hpch / 8 );
   if( saves_spell( level, victim ) )
      dam /= 2;
   sp_damage( obj, ch, victim, dam, REALM_ACID | NO_REFLECT | NO_ABSORB, sn, TRUE );
   return TRUE;
}



bool spell_fire_breath( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   OBJ_DATA *obj_lose;
   OBJ_DATA *obj_next;
   int dam;
   int hpch;


   if( !IS_NPC( ch ) )
   {
      dam = number_range( get_psuedo_level( ch ) * 1.2, get_psuedo_level( ch ) * 1.6 );
      if( saves_spell( level, victim ) )
         dam /= 2;
      damage( ch, victim, dam, sn );
      return TRUE;
   }

   if( number_percent(  ) < 2 * level && !saves_spell( level, victim ) )
   {
      OREF( obj_next, OBJ_NEXTCONTENT );
      for( obj_lose = victim->first_carry; obj_lose != NULL; obj_lose = obj_next )
      {
         char *msg;

         obj_next = obj_lose->next_in_carry_list;
         if( number_bits( 2 ) != 0 )
            continue;

         switch ( obj_lose->item_type )
         {
            default:
               continue;
            case ITEM_CONTAINER:
               msg = "$p ignites and burns!";
               break;
            case ITEM_POTION:
               msg = "$p bubbles and boils!";
               break;
            case ITEM_SCROLL:
               msg = "$p crackles and burns!";
               break;
            case ITEM_STAFF:
               msg = "$p smokes and chars!";
               break;
            case ITEM_WAND:
               msg = "$p sparks and sputters!";
               break;
            case ITEM_FOOD:
               msg = "$p blackens and crisps!";
               break;
            case ITEM_PILL:
               msg = "$p melts and drips!";
               break;
         }

         act( msg, victim, obj_lose, NULL, TO_CHAR );
         if( obj_lose->item_type == ITEM_CONTAINER )
         {
            OBJ_DATA *content;
            OBJ_DATA *content_next;
            OREF( content_next, OBJ_NEXTCONTENT );
            for( content = obj_lose->first_in_carry_list; content; content = content_next )
            {
               content_next = content->next_in_carry_list;
               obj_from_obj( content );
               obj_to_room( content, victim->in_room != NULL ? victim->in_room : get_room_index( ROOM_VNUM_LIMBO ) );
            }
            OUREF( content_next );
            extract_obj( obj_lose );
         }
      }
      OUREF( obj_next );
   }

   hpch = UMAX( 10, ch->hit );
   dam = number_range( hpch / 16 + 1, hpch / 8 );
   if( saves_spell( level, victim ) )
      dam /= 2;
   sp_damage( obj, ch, victim, dam, REALM_FIRE | NO_REFLECT | NO_ABSORB, sn, TRUE );
   return TRUE;
}



bool spell_frost_breath( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   OBJ_DATA *obj_lose;
   OBJ_DATA *obj_next;
   int dam;
   int hpch;

   if( number_percent(  ) < 2 * level && !saves_spell( level, victim ) )
   {
      OREF( obj_next, OBJ_NEXTCONTENT );
      for( obj_lose = victim->first_carry; obj_lose != NULL; obj_lose = obj_next )
      {
         char *msg;

         obj_next = obj_lose->next_in_carry_list;
         if( number_bits( 2 ) != 0 )
            continue;

         switch ( obj_lose->item_type )
         {
            default:
               continue;
            case ITEM_CONTAINER:
            case ITEM_DRINK_CON:
            case ITEM_POTION:
               msg = "$p freezes and shatters!";
               break;
         }

         act( msg, victim, obj_lose, NULL, TO_CHAR );
         if( obj_lose->item_type == ITEM_CONTAINER )
         {
            OBJ_DATA *content;
            OBJ_DATA *content_next;
            OREF( content_next, OBJ_NEXTCONTENT );
            for( content = obj_lose->first_in_carry_list; content; content = content_next )
            {
               content_next = content->next_in_carry_list;
               obj_from_obj( content );
               obj_to_room( content, victim->in_room != NULL ? victim->in_room : get_room_index( ROOM_VNUM_LIMBO ) );
            }
            OUREF( content_next );
         }
      }
      OUREF( obj_next );
   }

   hpch = UMAX( 10, ch->hit );
   dam = number_range( hpch / 16 + 1, hpch / 8 );
   if( saves_spell( level, victim ) )
      dam /= 2;
   sp_damage( obj, ch, victim, dam, REALM_COLD | NO_REFLECT | NO_ABSORB, sn, TRUE );
   return TRUE;
}



bool spell_gas_breath( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *vch;
   CHAR_DATA *vch_next;
   int dam;
   int hpch;
   CREF( vch_next, CHAR_NEXTROOM );

   for( vch = ch->in_room->first_person; vch != NULL; vch = vch_next )
   {
      vch_next = vch->next_in_room;
      if( IS_NPC( ch ) ? !IS_NPC( vch ) : IS_NPC( vch ) )
      {
         hpch = UMAX( 10, ch->hit );
         dam = number_range( hpch / 16 + 1, hpch / 8 );
         if( saves_spell( level, vch ) )
            dam /= 2;
         sp_damage( obj, ch, vch, dam, REALM_GAS | NO_REFLECT | NO_ABSORB, sn, TRUE );
      }
   }
   CUREF( vch_next );
   return TRUE;
}



bool spell_lightning_breath( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   int dam;
   int hpch;

   hpch = UMAX( 10, ch->hit );
   dam = number_range( hpch / 16 + 1, hpch / 8 );
   if( saves_spell( level, victim ) )
      dam /= 2;
   sp_damage( obj, ch, victim, dam, REALM_SHOCK | NO_REFLECT | NO_ABSORB, sn, TRUE );
   return TRUE;
}


bool spell_hellspawn( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   /*
    * High level mag / psi spell. -S- 
    */
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   int dam;

   dam = number_range( level / 2, level * 5 / 2 );
   if( saves_spell( level, victim ) )
      dam /= 2;

   sp_damage( obj, ch, victim, dam, REALM_DRAIN, sn, TRUE );
   return TRUE;
}


bool spell_planergy( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{

   /*
    * Psi spell.  Work out which energy to summon, according to
    * * ch's level.  Each 9 levels, the Psi gets the use of a different
    * * spell, and more damage! ;)  (planergy = planar energy)
    * * --Stephen
    */


   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   int dam;
   int lvl;
   int plane;

   if( level <= 8 )
   {
      lvl = 4;
      plane = REALM_IMPACT;
   }
   else if( level <= 17 )
   {
      lvl = 13;
      plane = REALM_GAS;
   }
   else if( level <= 26 )
   {
      lvl = 22;
      plane = REALM_FIRE;
   }
   else if( level <= 35 )
   {
      lvl = 31;
      plane = REALM_LIGHT;
   }
   else if( level <= 44 )
   {
      lvl = 40;
      plane = REALM_SHOCK;
   }
   else if( level <= 53 )
   {
      lvl = 49;
      plane = REALM_SOUND;
   }
   else if( level <= 62 )
   {
      lvl = 58;
      plane = REALM_MIND;
   }
   else if( level <= 71 )
   {
      lvl = 67;
      plane = REALM_ACID;
   }
   else
   {
      lvl = 80;
      plane = REALM_POISON;
   }

   dam = dice( 6, lvl / 2 );

   if( saves_spell( level, victim ) )
      dam /= 2;
   SET_BIT( plane, NO_REFLECT );
   SET_BIT( plane, NO_ABSORB );

   sp_damage( obj, ch, victim, dam, plane, sn, TRUE );

   return TRUE;
}


bool spell_visit( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{

   /*
    * Psi spell.  Kinda like summon, but almost done in reverse.
    * * allows the Psi to try and transfer themself to the 'victim'
    * * --Stephen
    */

   CHAR_DATA *victim = ( CHAR_DATA * ) vo;

   if( deathmatch )
   {
      send_to_char( "Not during a @@eDeath Match@@N!!\n\r", ch );
      return FALSE;
   }
   if( ( victim = get_char_world( ch, target_name ) ) == NULL
       || victim == ch
       || IS_NPC( victim )
       || victim->in_room == NULL
       || IS_SET( victim->in_room->room_flags, ROOM_PRIVATE )
       || IS_SET( victim->in_room->room_flags, ROOM_SOLITARY )
       || IS_SET( victim->in_room->room_flags, ROOM_SAFE )
       || IS_SET( ch->in_room->room_flags, ROOM_NO_RECALL ) || !IS_SET( victim->in_room->area->flags, AREA_TELEPORT ) )
   {
      send_to_char( "You failed.\n\r", ch );
      return TRUE;
   }

   if( IS_SET( victim->act, PLR_NOVISIT ) )
   {
      send_to_char( "You seem unable to visit your target!\n\r", ch );
      return TRUE;
   }

   /*
    * Check is ch screws up, and ends up in limbo... <grin> 
    */

   if( number_percent(  ) < 25 ) /* 25% chance */
   {
      send_to_char( "You get distracted, and appear in the middle of nowhere!\n\r", ch );
      act( "$n disappears suddenly.", ch, NULL, NULL, TO_ROOM );
      char_from_room( ch );
      char_to_room( ch, get_room_index( ROOM_VNUM_LIMBO ) );
      act( "$n arrives suddenly.", ch, NULL, NULL, TO_ROOM );
      do_look( ch, "auto" );
      return TRUE;
   }

   act( "$n disappears suddenly.", ch, NULL, NULL, TO_ROOM );
   char_from_room( ch );
   char_to_room( ch, victim->in_room );
   act( "$n arrives suddenly.", ch, NULL, NULL, TO_ROOM );
   send_to_char( "You change locations!\n\r", ch );
   do_look( ch, "auto" );
   return TRUE;
}


bool spell_barrier( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{

   /*
    * Psi spell, like shield, but slightly better.  Good idea to make
    * * sure Psi's don't have access to shield as well as this... ;)
    * * -- Stephen
    */

   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   AFFECT_DATA af;

   if( is_affected( victim, sn ) )
      return FALSE;

   af.type = sn;
   af.duration = 4 + ( level / 20 );
   af.location = APPLY_AC;
   af.modifier = -20 - get_psuedo_level( ch ) / 10;
   af.bitvector = 0;
   affect_to_char( victim, &af );

   act( "$n is surrounded by a telekinetic barrier.", victim, NULL, NULL, TO_ROOM );
   send_to_char( "You are surrounded by a telekinetic barrier.\n\r", victim );
   return TRUE;
}


bool spell_static( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   /*
    * Psi Spell.
    * * Uses ch's movement, which is transfered to static electricity    
    * * which is then chanelled at the poor victim <laugh>
    * * --Stephen
    */

   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   int dam;
   int loss;

   send_to_char( "You transfer kinetic to static energy!\n\r", ch );

   loss = dice( 2, level ) + dice( 2, level );

   dam = number_range( 6, 8 ) * ( level / 3 );
   if( ( ch->move - loss ) <= 0 )
   {
      send_to_char( "You have no kinetic energy left!!\n\r", ch );
      return FALSE;
   }

   ch->move = UMAX( 1, ch->move - loss );

   if( saves_spell( level, victim ) )
      dam /= 2;

   act( "$n transfers kinetic to static energy.", ch, NULL, NULL, TO_ROOM );
   sp_damage( obj, ch, victim, dam, REALM_SHOCK | NO_REFLECT | NO_ABSORB, sn, TRUE );

   return TRUE;
}

bool spell_phobia( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   /*
    * Psi Spell.
    * * Conjures victims's phobia in their mind, does dam (small) or
    * * causes them to flee.
    * * --Stephen
    */

   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   int dam;

   if( ( victim->level ) > ( level + 8 ) )
   {
      send_to_char( "Your spell fails to take affect!\n\r", ch );
      return TRUE;
   }

   /*
    * figure out dam.... not too much as spell is meant to make vo flee 
    */

   dam = dice( 2, level / 8 );
   if( obj == NULL )
   {
      act( "$n projects nightmare images into $N's mind!", ch, NULL, victim, TO_NOTVICT );
      act( "You project nightmare images into $N's mind!", ch, NULL, victim, TO_CHAR );
      act( "$N projects nightmare images into your mind!", victim, NULL, ch, TO_CHAR );
   }
   else
   {
      act( "$p projects nightmare images into $n's mind!", victim, obj, NULL, TO_ROOM );
      act( "$p projects nightmare images into your mind!", victim, obj, NULL, TO_CHAR );
   }
   send_to_char( "Your worst phobia springs to life in your mind. Arrrggghhh!\n\r", victim );
   act( "$N suffers a mental phobia attack!", ch, NULL, victim, TO_NOTVICT );

   if( sp_damage( obj, ch, victim, dam, REALM_MIND, sn, TRUE ) )
   {
      if( !IS_NPC( victim ) && ( IS_WOLF( victim ) || IS_VAMP( victim ) ) )
         return TRUE;

      if( number_percent(  ) < 70 ) /* 70% chance */
      {
         act( "$N screams at $n in horror!!", ch, NULL, victim, TO_ROOM );
         act( "$N screams at you in horror!!", ch, NULL, victim, TO_CHAR );
         send_to_char( "You flip, and look for escape!!\n\r", victim );
         do_flee( victim, "" );
      }
   }

   return TRUE;
}

bool spell_mindflame( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   /*
    * Psi Multiple Attack - screws up all those affected 
    */



   CHAR_DATA *vch;
   CHAR_DATA *vch_next;

   if( obj == NULL )
   {
      send_to_char( "You initiate a mindflame attack!!\n\r", ch );
      act( "$n concentrates, and initiates a mindlame attack!", ch, NULL, NULL, TO_ROOM );
   }
   else
   {
      act( "$p glows, and initiates a mindflame attack!", ch, obj, NULL, TO_ROOM );
      act( "$p glows, and initiates a mindflame attack!", ch, obj, NULL, TO_CHAR );
   }
   CREF( vch_next, CHAR_NEXT );
   for( vch = first_char; vch != NULL; vch = vch_next )
   {
      vch_next = vch->next;
      if( vch->in_room == NULL )
         continue;
      if( vch->in_room == ch->in_room )
      {
         if( vch != ch && ( IS_NPC( ch ) ? !IS_NPC( vch ) : IS_NPC( vch ) ) )
         {
            act( "$n rolls on the floor, clutching $s head in pain!", vch, NULL, NULL, TO_ROOM );
            send_to_char( "You roll on the floor, clutching your head in pain!\n\r", vch );
            sp_damage( obj, ch, vch, ( get_psuedo_level( ch ) / 2 ) + dice( 6, 12 ),
                       REALM_MIND | NO_REFLECT | NO_ABSORB, sn, TRUE );
         }
         continue;
      }

      if( vch->in_room->area == ch->in_room->area )
         send_to_char( "You notice a slight burning feeling in your mind.\n\r", vch );
   }
   CUREF( vch_next );
   return TRUE;
}

bool spell_chain_lightning( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   /*
    * affects all in a room, can also hit caster <grin> 
    */


   CHAR_DATA *vch;
   CHAR_DATA *vch_next;
   int dam;

   /*
    * Work out starting damage. 
    */
   dam = dice( 10, ( get_psuedo_level( ch ) / 2 ) );

   if( obj == NULL )
   {
      send_to_char( "Lightning flashes from your fingers!\n\r", ch );
      act( "$n unleashes lightning from $s fingers!", ch, NULL, NULL, TO_ROOM );
   }
   else
   {
      act( "A lightning bolt flashes from $p!", ch, obj, NULL, TO_ROOM );
      act( "A lightning bolt flashes from $p!", ch, obj, NULL, TO_CHAR );
   }
   CREF( vch_next, CHAR_NEXTROOM );

   for( vch = ch->in_room->first_person; vch != NULL; vch = vch_next )
   {
      vch_next = vch->next_in_room;

      if( vch != ch && IS_NPC( ch ) ? !IS_NPC( vch ) : IS_NPC( vch ) )
      {
         send_to_char( "The lightning bolt strikes you!\n\r", vch );
         act( "The lightning bolt strikes $n!", vch, NULL, NULL, TO_ROOM );
         sp_damage( obj, ch, vch, dam, REALM_SHOCK | NO_REFLECT, sn, TRUE );
         dam = ( 4 * dam / 5 );
      }
   }
   CUREF( vch_next );



   /*
    * Now see if caster gets hit. 
    */

   if( saves_spell( level, ch ) )
   {
      act( "The lightning bolt hits the ground, and is GONE!", ch, NULL, NULL, TO_ROOM );
      send_to_char( "Your lightning bolts hits the ground and is GONE!\n\r", ch );
   }
   else
   {
      act( "The lightning bolt strikes $n and vanishes!", ch, NULL, NULL, TO_ROOM );
      send_to_char( "Your lightning returns, and hits you!\n\r", ch );
      dam = UMIN( level / 2, dam );
      sp_damage( obj, ch, ch, dam, REALM_SHOCK | NO_REFLECT | NO_ABSORB, sn, TRUE );
   }
   return TRUE;
}


bool spell_suffocate( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   int dam;

   dam = dice( level / 3, 2 );

   if( ( level + 5 ) > victim->level )
      dam += ( ( ( level + 5 ) - victim->level ) * 2 );
   else
      dam -= ( ( victim->level - level ) * 2 );

   act( "$n chokes and gags!", victim, NULL, NULL, TO_ROOM );
   send_to_char( "You feel your throat squeezed by an invisible force!\n\r", victim );

   sp_damage( obj, ch, victim, dam, REALM_IMPACT, sn, TRUE );  /* -1 = no dam message */
   return TRUE;
}

bool spell_enhance_weapon( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   OBJ_DATA *ob = ( OBJ_DATA * ) vo;
   AFFECT_DATA *paf;

   /*
    * Quick way to stop imms (Bash?) enchanting weapons for players 
    */
   if( IS_IMMORTAL( ch ) && ch->level != 85 )
   {
      send_to_char( "Nothing Happens.\n\r", ch );
      return FALSE;
   }

   if( ob->item_type != ITEM_WEAPON || IS_OBJ_STAT( ob, ITEM_MAGIC ) || ob->first_apply != NULL )
      return TRUE;

   GET_FREE( paf, affect_free );
   paf->type = sn;
   paf->duration = 3 + ( level / 4 );
   paf->location = APPLY_HITROLL;
   paf->modifier = 3;
   paf->bitvector = 0;
   LINK( paf, ob->first_apply, ob->last_apply, next, prev );

   GET_FREE( paf, affect_free );
   paf->type = -1;
   paf->duration = 3 + ( level / 4 );
   paf->location = APPLY_DAMROLL;
   paf->modifier = 2;
   paf->bitvector = 0;
   LINK( paf, ob->first_apply, ob->last_apply, next, prev );

   act( "$p shines brightly.", ch, ob, NULL, TO_CHAR );
   act( "$p belonging to $n shines brightly.", ch, ob, NULL, TO_ROOM );

   return TRUE;
}

bool spell_bloody_tears( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;

   if( IS_AFFECTED( victim, AFF_BLIND ) || saves_spell( level, victim ) )
      return TRUE;

   act( "$n's eyes start bleeding!", victim, NULL, NULL, TO_ROOM );
   send_to_char( "Your eyes start bleeding!\n\r", victim );
   spell_blindness( skill_lookup( "blindness" ), level, ch, vo, obj );

   sp_damage( obj, ch, victim, ( level / 2 ), REALM_MIND | NO_REFLECT | NO_ABSORB, sn, FALSE ); /* -1 = no dam message */

   return TRUE;
}

bool spell_mind_bolt( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   int cnt;
   int foo;
   int dam;


   cnt = ( level >= 12 ) + ( level >= 30 ) + ( level >= 60 ) + ( ch->level >= 75 );
   for( foo = 0; foo < cnt; foo++ )
   {
      if( number_range( 0, 99 ) < 30 )
         continue;
      dam = number_range( level / 4, level * 2 / 3 );
      if( saves_spell( level, victim ) )
         dam /= 2;

      sp_damage( obj, ch, victim, dam, REALM_MIND | NO_REFLECT | NO_ABSORB, sn, TRUE );   /* -1 = no dam message */

   }
   return TRUE;
}

bool spell_nerve_fire( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *vch;
   CHAR_DATA *vch_next;

   if( obj == NULL )
   {
      send_to_char( "You initiate a Nerve Fire attack!!\n\r", ch );
      act( "$n concentrates, and initiates a Nerve Fire attack!", ch, NULL, NULL, TO_ROOM );
   }
   else
   {
      act( "$p glows with the power of Nerve Fire!", ch, obj, NULL, TO_ROOM );
      act( "$p glows with the power of Nerve Fire!", ch, obj, NULL, TO_CHAR );
   }
   CREF( vch_next, CHAR_NEXT );
   for( vch = first_char; vch != NULL; vch = vch_next )
   {
      vch_next = vch->next;
      if( vch->in_room == NULL )
         continue;
      if( vch->in_room == ch->in_room )
      {
         if( vch != ch && ( IS_NPC( ch ) ? !IS_NPC( vch ) : IS_NPC( vch ) ) )
         {
            sp_damage( obj, ch, vch, ( level ) + dice( 5, 20 ), REALM_MIND | NO_REFLECT | NO_ABSORB, sn, TRUE );
         }
         continue;
      }

      if( vch->in_room->area == ch->in_room->area )
         send_to_char( "You notice a slight burning feeling in your body.\n\r", vch );
   }
   CUREF( vch_next );
   return TRUE;
}

bool spell_fighting_trance( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   AFFECT_DATA af;

   if( is_affected( victim, sn ) )
      return FALSE;

   af.type = sn;
   af.duration = 6 + ( level / 20 );
   af.location = APPLY_HITROLL;
   af.modifier = get_psuedo_level( ch ) / 10;
   af.bitvector = 0;
   affect_to_char( victim, &af );

   af.location = APPLY_SAVING_SPELL;
   af.modifier = 0 - level / 8;
   affect_to_char( victim, &af );

   af.location = APPLY_DAMROLL;
   af.modifier = get_psuedo_level( ch ) / 10;
   affect_to_char( victim, &af );

   af.location = APPLY_AC;
   af.modifier = -10 - get_psuedo_level( ch ) / 10;
   affect_to_char( victim, &af );
   send_to_char( "You feel much stronger.\n\r", victim );
   act( "$n looks much stronger.", victim, NULL, NULL, TO_ROOM );
   if( ch != victim )
      send_to_char( "Ok.\n\r", ch );
   return TRUE;
}

bool spell_phase( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   AFFECT_DATA af;

   if( IS_AFFECTED( victim, AFF_PASS_DOOR ) || item_has_apply( victim, ITEM_APPLY_PASS_DOOR ) )
      return FALSE;

   af.type = sn;
   af.duration = 3 + ( level / 20 );
   af.location = APPLY_AC;
   af.modifier = -10 - get_psuedo_level( ch ) / 10;
   af.bitvector = AFF_PASS_DOOR;
   affect_to_char( victim, &af );
   send_to_char( "Your body switches phase.\n\r", victim );
   act( "$n's body switches phase.", victim, NULL, NULL, TO_ROOM );
   return TRUE;
}

bool spell_dimension_blade( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   OBJ_DATA *ob = ( OBJ_DATA * ) vo;
   AFFECT_DATA *paf;

   /*
    * Quick way to stop imms (Bash?) enchanting weapons for players 
    */
   if( IS_IMMORTAL( ch ) && ch->level != 85 )
   {
      send_to_char( "Nothing Happens.\n\r", ch );
      return FALSE;
   }

   if( dice( 4, 5 ) == 20 )
   {
      act( "$p shatters into pieces!", ch, ob, NULL, TO_CHAR );
      act( "$p carried by $n shatters!", ch, ob, NULL, TO_ROOM );
      extract_obj( ob );
      return TRUE;
   }

   if( ob->item_type != ITEM_WEAPON || IS_OBJ_STAT( ob, ITEM_MAGIC ) || ob->first_apply != NULL )
      return TRUE;

   GET_FREE( paf, affect_free );
   paf->type = sn;
   paf->duration = -1;
   paf->location = APPLY_HITROLL;
   paf->modifier = 1 + ( level >= 50 ) + ( level >= 60 ) + ( level >= 70 );
   paf->bitvector = 0;
   LINK( paf, ob->first_apply, ob->last_apply, next, prev );

   GET_FREE( paf, affect_free );
   paf->type = -1;
   paf->duration = -1;
   paf->location = APPLY_DAMROLL;
   paf->modifier = 1 + ( level >= 55 ) + ( level >= 70 );
   paf->bitvector = 0;
   LINK( paf, ob->first_apply, ob->last_apply, next, prev );

   act( "Part of $p switches into a different plane.", ch, ob, NULL, TO_CHAR );
   act( "$n makes $p into a dimension blade.", ch, ob, NULL, TO_ROOM );
   return TRUE;
}

bool spell_produce_food( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{

   OBJ_DATA *mushroom;

   mushroom = create_object( get_obj_index( OBJ_VNUM_FOOD ), 0 );
   mushroom->value[0] = 5 + level;
   obj_to_room( mushroom, ch->in_room );
   act( "$p suddenly appears.", ch, mushroom, NULL, TO_ROOM );
   act( "$p suddenly appears.", ch, mushroom, NULL, TO_CHAR );
   return TRUE;
}

bool spell_animate( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   OBJ_DATA *ob;
   OBJ_DATA *bits;
   CHAR_DATA *corpse;

   if( IS_NPC( ch ) )
      return FALSE;

   ob = get_obj_here( ch, target_name );

   if( ob == NULL )
   {
      send_to_char( "Couldn't find it.\n\r", ch );
      return FALSE;
   }

   if( ch->lvl2[3] < 70 )
   {
      send_to_char( " @@eDUE TO A ROLEPLAYING CHANGE, THIS SPELL IS NO LONGER AVAILABLE TO ANY CLASS\n\r", ch );
      send_to_char( " BUT a high level @@dNECRMOANCER@@N.  THE SKILL HAS BEEN REMOVED FROM YOU CHARACTER, \n\r", ch );
      send_to_char( " SORRY FOR THE INCONVIENENCE.  @@mTHANK YOU@@N :)\n\r", ch );
      ch->pcdata->learned[sn] = 0;
      return FALSE;
   }

   if( ob->item_type != ITEM_CORPSE_NPC )
   {
      send_to_char( "You can't animate that!\n\r", ch );
      return FALSE;
   }

   act( "$n lays $s hands onto the $p!", ch, ob, NULL, TO_ROOM );
   act( "You lay your hands upon the $p.", ch, ob, NULL, TO_CHAR );

   act( "Bright bolts of lightning fly out from $p!!", ch, ob, NULL, TO_ROOM );
   act( "Bright bolts of lightning fly out from $p!!", ch, ob, NULL, TO_CHAR );

   corpse = create_mobile( get_mob_index( MOB_VNUM_ZOMBIE ) );
   char_to_room( corpse, ch->in_room );
   act( "$n stands up, and stretches slowly.", corpse, NULL, NULL, TO_ROOM );

   if( ob->item_type == ITEM_CORPSE_NPC )
   {
      SET_BIT( corpse->act, ACT_UNDEAD );
      act( "$n's eyes glow black!", corpse, NULL, NULL, TO_ROOM );
   }

   corpse->level = ob->level; /* Level of (N)PC before death */
   corpse->max_hit = dice( 5, level );
   corpse->hit = corpse->max_hit;
   corpse->max_move = dice( 10, level );
   corpse->move = corpse->max_move; /* Set Zombie's stats */

   for( ;; )
   {
      if( ob->first_in_carry_list == NULL )
         break;
      bits = ob->first_in_carry_list;
      obj_from_obj( bits );
      obj_to_char( bits, corpse );

   }

   extract_obj( ob );
   do_wear( corpse, "all" );  /* FIXME: better to check items, then wear... */
   SET_BIT( corpse->act, ACT_PET );
   SET_BIT( corpse->affected_by, AFF_CHARM );
   corpse->extract_timer = get_psuedo_level( ch ) / 3;

   add_follower( corpse, ch );
   return TRUE;
}

bool spell_see_magic( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   AFFECT_DATA af;

   if( IS_AFFECTED( victim, AFF_DETECT_MAGIC ) || item_has_apply( victim, ITEM_APPLY_HIDE ) )
      return FALSE;
   af.type = sn;
   af.duration = 6 + ( level / 4 );
   af.modifier = 0;
   af.location = APPLY_NONE;
   af.bitvector = AFF_DETECT_MAGIC;
   affect_to_char( victim, &af );
   send_to_char( "Your eyes tingle.\n\r", victim );
   act( "$n's eyes glow briefly.", victim, NULL, NULL, TO_ROOM );
   return TRUE;
}

bool spell_detection( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   char buf[MAX_INPUT_LENGTH];
   OBJ_DATA *ob;
   OBJ_DATA *in_obj;
   bool found;

   found = FALSE;
   for( ob = first_obj; ob != NULL; ob = ob->next )
   {


      if( !can_see_obj( ch, ob ) || !is_name( target_name, ob->name )
          || IS_SET( ob->extra_flags, ITEM_RARE )
          || ( ob->item_type == ITEM_PIECE )
          || ( IS_SET( ob->extra_flags, ITEM_UNIQUE ) ) || ( !str_prefix( target_name, "unique" ) ) )
         continue;





      for( in_obj = ob; in_obj->in_obj != NULL; in_obj = in_obj->in_obj )
         ;
      if( ( in_obj->carried_by != NULL )
          && ( IS_IMMORTAL( in_obj->carried_by )
               || ( !IS_NPC( in_obj->carried_by )
                    && IS_WOLF( in_obj->carried_by )
                    && ( IS_SHIFTED( in_obj->carried_by ) || ( IS_RAGED( in_obj->carried_by ) ) ) ) ) )
         break;


      if( in_obj->carried_by != NULL )
      {
         found = TRUE;
         sprintf( buf, "%s carried by %s.\n\r",
                  ob->short_descr, can_see( ch, in_obj->carried_by ) ? PERS( in_obj->carried_by, ch ) : "someone" );
      }
      else
      {
         found = TRUE;
         sprintf( buf, "%s in %s.\n\r", ob->short_descr, in_obj->in_room == NULL ? "somewhere" : in_obj->in_room->name );
      }

      buf[0] = UPPER( buf[0] );
      send_to_char( buf, ch );
   }

   if( !found )
      send_to_char( "You fail to detect any such object.\n\r", ch );

   return TRUE;
}


bool spell_fire_blade( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   OBJ_DATA *blade;

   if( get_obj_wear( ch, "fireblade" ) != NULL )
      return FALSE;  /* Only have one at a time.. */

   if( remove_obj( ch, WEAR_HOLD_HAND_L, TRUE ) )
   {
      blade = create_object( get_obj_index( OBJ_VNUM_FIREBLADE ), level );
      obj_to_char( blade, ch );
      equip_char( ch, blade, WEAR_HOLD_HAND_L );
      blade->timer = 2 + ( level / 20 );
      act( "A blazing FireBlade appears in $n's hand!", ch, NULL, NULL, TO_ROOM );
      send_to_char( "A blazing FireBlade appears in your hand!", ch );
   }
   return TRUE;
}


bool spell_know_weakness( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   AFFECT_DATA af;

   if( is_affected( ch, sn ) )
      return FALSE;

   af.type = sn;
   af.duration = 2 + ( level >= 20 ) + ( level >= 40 ) + ( level >= 60 ) + ( level >= 80 );
   af.location = APPLY_HITROLL;
   af.modifier = 3;
   af.bitvector = 0;
   affect_to_char( ch, &af );
   send_to_char( "You are more aware of your enemy's weaknesses.\n\r", ch );
   return TRUE;
}

bool spell_know_critical( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   AFFECT_DATA af;

   if( is_affected( ch, sn ) )
      return FALSE;

   af.type = sn;
   af.duration = 2 + ( level >= 20 ) + ( level >= 40 ) + ( level >= 60 ) + ( level >= 80 );
   af.location = APPLY_DAMROLL;
   af.modifier = 3;
   af.bitvector = 0;
   affect_to_char( ch, &af );
   send_to_char( "You are more aware of critical damage points.\n\r", ch );
   return TRUE;
}

bool spell_calm( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *ppl;
   int chance;

   for( ppl = ch->in_room->first_person; ppl != NULL; ppl = ppl->next_in_room )
      if( IS_NPC( ppl ) && ppl != ch )
      {
         chance = ( ( IS_NPC( ch ) ? 50 : ch->pcdata->learned[sn] / 2 ) + ( 5 * ( level - ppl->level ) ) );
         if( number_percent(  ) < chance )
            stop_fighting( ppl, TRUE );
      }
   if( obj == NULL )
   {
      act( "$n emits a great feeling of calm around you.", ch, NULL, NULL, TO_ROOM );
      send_to_char( "You emit a great feeling of calm around you.\n\r", ch );
   }
   else
   {
      act( "$p glows with a clam light.", ch, obj, NULL, TO_ROOM );
      act( "$p glows with a clam light.", ch, obj, NULL, TO_CHAR );
   }
   return TRUE;
}


bool spell_hypnosis( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   AFFECT_DATA af;

   if( victim == ch )
   {
      send_to_char( "You like yourself even better!\n\r", ch );
      return FALSE;
   }

   if( !IS_NPC( victim ) )
   {
      send_to_char( "You're not that powerful.\n\r", ch );
      return FALSE;
   }

   if( IS_AFFECTED( victim, AFF_CHARM )
       || IS_AFFECTED( ch, AFF_CHARM ) || level - 5 < victim->level || saves_spell( level, victim ) )
      return TRUE;
   if( IS_VAMP( victim ) && ( IS_NPC( victim ) ) )
   {
      send_to_char( "Wow, it seems to be immune--imagine that!\n\r", ch );
      return TRUE;
   }


   if( victim->master )
      stop_follower( victim );
   add_follower( victim, ch );
   af.type = sn;
   af.duration = 3 + ( level / 8 );
   af.location = 0;
   af.modifier = 0;
   af.bitvector = AFF_CHARM;
   affect_to_char( victim, &af );
   act( "Isn't $n just so nice?", ch, NULL, victim, TO_VICT );
   if( ch != victim )
      send_to_char( "Ok.\n\r", ch );
   victim->extract_timer = get_psuedo_level( ch ) / 3;
   return TRUE;
}

bool spell_mind_flail( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   int dam;
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;

   if( victim == ch )
      return FALSE;

   if( IS_NPC( victim ) && IS_SET( victim->act, ACT_NOMIND ) )
      return TRUE;


   dam = 5 + ( 10 * ( ( level > 20 ) + ( level >= 40 ) + ( level >= 60 ) + ( level >= 75 ) ) );

   if( saves_spell( level, victim ) )
      dam /= 2;


   sp_damage( obj, ch, victim, dam, REALM_MIND | NO_REFLECT | NO_ABSORB, sn, TRUE );
   return TRUE;
}


bool spell_know_item( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   OBJ_DATA *ob = ( OBJ_DATA * ) vo;
   char buf[MAX_STRING_LENGTH];
   AFFECT_DATA *paf;

   sprintf( buf,
            "Object '%s' is type %s, extra flags %s.\n\rWeight is %d.\n\r",
            ob->name, item_type_name( ob ), extra_bit_name( ob->extra_flags ), ob->weight );
   send_to_char( buf, ch );

   switch ( ob->item_type )
   {
      case ITEM_SCROLL:
      case ITEM_POTION:
         sprintf( buf, "Level %d spells of:", ob->value[0] );
         send_to_char( buf, ch );

         if( ob->value[1] >= 0 && ob->value[1] < MAX_SKILL )
         {
            send_to_char( " '", ch );
            send_to_char( skill_table[ob->value[1]].name, ch );
            send_to_char( "'", ch );
         }

         if( ob->value[2] >= 0 && ob->value[2] < MAX_SKILL )
         {
            send_to_char( " '", ch );
            send_to_char( skill_table[ob->value[2]].name, ch );
            send_to_char( "'", ch );
         }

         if( ob->value[3] >= 0 && ob->value[3] < MAX_SKILL )
         {
            send_to_char( " '", ch );
            send_to_char( skill_table[ob->value[3]].name, ch );
            send_to_char( "'", ch );
         }

         send_to_char( ".\n\r", ch );
         break;

      case ITEM_WAND:
      case ITEM_STAFF:
         sprintf( buf, "Has %d(%d) charges of level %d", ob->value[1], ob->value[2], ob->value[0] );
         send_to_char( buf, ch );

         if( ob->value[3] >= 0 && ob->value[3] < MAX_SKILL )
         {
            send_to_char( " '", ch );
            send_to_char( skill_table[ob->value[3]].name, ch );
            send_to_char( "'", ch );
         }

         send_to_char( ".\n\r", ch );
         break;

      case ITEM_WEAPON:
         sprintf( buf, " Average damage is %d.\n\r", ( ob->value[1] + ob->value[2] ) / 2 );
         send_to_char( buf, ch );
         break;

      case ITEM_ARMOR:
         sprintf( buf, "Armor class is %d.\n\r", ob->value[0] );
         send_to_char( buf, ch );
         break;
   }

   for( paf = ob->first_apply; paf != NULL; paf = paf->next )
   {
      if( paf->location != APPLY_NONE && paf->modifier != 0 )
      {
         sprintf( buf, "Affects %s by %d.\n\r", affect_loc_name( paf->location ), paf->modifier );
         send_to_char( buf, ch );
      }
   }


   return TRUE;
}


bool spell_physic_thrust( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   int dam;
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;

   if( victim == ch )
      return FALSE;


   if( IS_NPC( victim ) && IS_SET( victim->act, ACT_NOMIND ) )
      return TRUE;


   dam = 5 + ( 20 * ( level > 20 ) + ( level >= 40 ) + ( level >= 60 ) + ( level >= 75 ) );

   if( saves_spell( level, victim ) )
      dam /= 2;

   sp_damage( obj, ch, victim, dam, REALM_MIND | NO_REFLECT | NO_ABSORB, sn, TRUE );
   return TRUE;
}


bool spell_physic_crush( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   int dam;
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;

   if( victim == ch )
      return FALSE;

   if( IS_NPC( victim ) && IS_SET( victim->act, ACT_NOMIND ) )
      return TRUE;


   dam = get_psuedo_level( ch ) / 2 + ( 30 * ( level > 20 ) + ( level >= 40 ) + ( level >= 60 ) + ( level >= 75 ) );

   if( saves_spell( level, victim ) )
      dam /= 2;

   sp_damage( obj, ch, victim, dam, REALM_MIND | NO_REFLECT | NO_ABSORB, sn, TRUE );
   return TRUE;
}

bool spell_ego_whip( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   int dam;
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;

   if( victim == ch )
      return FALSE;

   if( IS_NPC( victim ) && IS_SET( victim->act, ACT_NOMIND ) )
      return TRUE;


   dam = 50 + ( 40 * ( level > 20 ) + ( level >= 40 ) + ( level >= 60 ) + ( level >= 75 ) );

   if( saves_spell( level, victim ) )
      dam /= 2;

   sp_damage( obj, ch, victim, dam, REALM_MIND | NO_REFLECT | NO_ABSORB, sn, TRUE );
   return TRUE;
}


bool spell_night_vision( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   AFFECT_DATA af;

   if( IS_AFFECTED( victim, AFF_INFRARED ) || item_has_apply( victim, ITEM_APPLY_INFRA ) )
      return ( ch == victim ? FALSE : TRUE );
   act( "$n's eyes glow red.\n\r", ch, NULL, NULL, TO_ROOM );
   af.type = sn;
   af.duration = 4 + ( level / 3 );
   af.location = APPLY_NONE;
   af.modifier = 0;
   af.bitvector = AFF_INFRARED;
   affect_to_char( victim, &af );
   send_to_char( "Your eyes glow red.\n\r", victim );
   if( ch != victim )
      send_to_char( "Ok.\n\r", ch );
   return TRUE;
}

bool spell_stalker( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   /*
    * Fixed problem of stalker not finding victim, and attacking caster,
    * * thus giving an easy source of xp -S-
    */

   CHAR_DATA *victim;
   CHAR_DATA *stalker;

   if( target_name[0] == '\0' )
   {
      send_to_char( "Summon a stalker to hunt who?\n\r", ch );
      return FALSE;
   }


   victim = get_char_world( ch, target_name );

   if( victim == NULL )
   {
      send_to_char( "Target can't be found!\n\r", ch );
      return FALSE;
   }

   if( ch == victim )
   {
      send_to_char( "That WOULDN'T be wise!\n\r", ch );
      return FALSE;
   }
   act( "$n calls upon the dark powers to summon forth a Stalker!", ch, NULL, NULL, TO_ROOM );
   send_to_char( "You call upon the dark powers to summon forth a Stalker!\n\r", ch );

   stalker = create_mobile( get_mob_index( MOB_VNUM_STALKER ) );

   char_to_room( stalker, ch->in_room );
   act( "$n appears before you suddenly.", stalker, NULL, NULL, TO_ROOM );

   stalker->level = victim->level;
   stalker->max_hit = victim->max_hit;
   stalker->hit = stalker->max_hit;
   stalker->exp = victim->level * 10;  /* not much exp :P */

   if( set_hunt( stalker, ch, victim, NULL, HUNT_MERC, HUNT_CR ) )
      act( "$n sniffs the air in search of $s prey.", stalker, NULL, NULL, TO_ROOM );
   else
   {
      int sn;

      sn = skill_lookup( "hellspawn" );
      if( sn != 0 )  /* Check to be sure... should never == 0 */
         ( *skill_table[sn].spell_fun ) ( sn, stalker->level, stalker, ch, NULL );

      do_say( stalker, "How dare you waste my time!!" );
      act( "$n returns to the dark planes, vanishing suddenly!", stalker, NULL, NULL, TO_ROOM );
      /*
       * char_from_room( stalker );   
       */
      extract_char( stalker, TRUE );
   }
   return TRUE;
}

bool spell_mystic_armor( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   AFFECT_DATA af;

   if( ch == victim )
   {
      send_to_char( "You are mystically armoured, but it suddenly fades away!\n\r", ch );
      return FALSE;
   }

   if( is_affected( victim, sn ) )
      return TRUE;

   af.type = sn;
   af.duration = 4 + ( level / 3 );
   af.location = APPLY_AC;
   af.modifier = -10 - get_psuedo_level( ch ) / 8;
   af.bitvector = 0;
   affect_to_char( victim, &af );

   act( "$n is surrounded by $N's mystic armour.", victim, NULL, ch, TO_ROOM );
   act( "$N is surrounded by your mystic armour.", ch, NULL, victim, TO_CHAR );
   act( "You are surrounded by $N's mystic armour.", victim, NULL, ch, TO_CHAR );
   return TRUE;
}


bool spell_flare( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   CHAR_DATA *victim = ( CHAR_DATA * ) vo;
   AFFECT_DATA af;

   if( IS_AFFECTED( victim, AFF_BLIND ) || saves_spell( level, victim ) )
      return TRUE;

   if( victim == ch )
      return FALSE;

   af.type = sn;
   af.location = APPLY_HITROLL;
   af.modifier = level / 4;
   af.duration = 1 + ( level / 4 );
   af.bitvector = AFF_BLIND;
   affect_to_char( victim, &af );
   act( "$n invokes the power of Ra to produce a solar flare which blinds $N!", ch, NULL, victim, TO_NOTVICT );
   act( "$N invokes the power of Ra to produce a solar flare.  You are BLINDED!", victim, NULL, ch, TO_CHAR );
   act( "You invoke the power of Ra to produce a solar flare, which blinds $N!", ch, NULL, victim, TO_CHAR );


   return TRUE;
}

bool spell_travel( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   /*
    * Transfer the player to Midgaard recall 
    */

   ROOM_INDEX_DATA *room;

   if( ch->fighting != NULL )
   {
      send_to_char( "You can't travel when fighting!\n\r", ch );
      return FALSE;
   }

   if( ( room = get_room_index( 3001 ) ) == NULL )
   {
      send_to_char( "It seems the Midgaard Temple has vanished!\n\r", ch );
      return FALSE;
   }

   act( "$n is engulfed by a stream of green light!", ch, NULL, NULL, TO_ROOM );
   char_from_room( ch );
   char_to_room( ch, room );
   act( "$n arrives, carried by a stream of green light!", ch, NULL, NULL, TO_ROOM );
   do_look( ch, "auto" );
   return TRUE;
}

bool spell_window( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   /*
    * Create a magic window to look into another room 
    */
   OBJ_DATA *beacon;
   OBJ_DATA *ob;

   if( target_name[0] == '\0' )
   {
      send_to_char( "Form a window to whom?\n\r", ch );
      return FALSE;
   }

   beacon = get_obj_world( ch, target_name );

   if( beacon == NULL || beacon->item_type != ITEM_BEACON )
   {
      send_to_char( "Couldn't find target.  Sorry.\n\r", ch );
      return FALSE;
   }

   if( beacon->in_room == NULL )
   {
      send_to_char( "It seems that someone is carrying it.\n\r", ch );
      return FALSE;
   }

   if( str_cmp( beacon->owner, ch->name ) )
   {
      send_to_char( "That's not one of YOUR beacons!\n\r", ch );
      return FALSE;
   }

   act( "$n creates a magic window with a wave of $s hand.", ch, NULL, NULL, TO_ROOM );
   send_to_char( "You create a magic window with a wave of your hand.\n\r", ch );

   ob = create_object( get_obj_index( OBJ_VNUM_WINDOW ), level );
   obj_to_room( ob, ch->in_room );
   ob->timer = 1 + ( level / 30 );
   ob->value[0] = beacon->in_room->vnum;
   ob->value[1] = 1;
   send_to_room( "The beacon suddenly vanishes!\n\r", beacon->in_room );
   extract_obj( beacon );
   return TRUE;
}

bool spell_portal( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   /*
    * Create a magic portal to another room 
    */
   OBJ_DATA *beacon;
   OBJ_DATA *ob;

   if( deathmatch )
   {
      send_to_char( "Not during a @@eDeath Match@@N!!!\n\r", ch );
      return FALSE;
   }
   if( target_name[0] == '\0' )
   {
      send_to_char( "Form a portal to what?\n\r", ch );
      return FALSE;
   }

   beacon = get_obj_world( ch, target_name );

   if( beacon == NULL || beacon->item_type != ITEM_BEACON )
   {
      send_to_char( "Couldn't find target.  Sorry.\n\r", ch );
      return FALSE;
   }

   if( beacon->in_room == NULL )
   {
      send_to_char( "It seems that someone is carrying it.\n\r", ch );
      return FALSE;
   }

   if( str_cmp( beacon->owner, ch->name ) )
   {
      send_to_char( "That's not one of YOUR beacons!\n\r", ch );
      return FALSE;
   }

   ob = create_object( get_obj_index( OBJ_VNUM_PORTAL ), level );
   obj_to_room( ob, ch->in_room );
   ob->timer = 1 + ( level / 30 );
   ob->value[0] = ( beacon->carried_by == NULL ? beacon->in_room->vnum : beacon->carried_by->in_room->vnum );
   ob->value[1] = 1;
   ob->value[2] = 1;

   act( "$n creates $p with a wave of $s hand.", ch, ob, NULL, TO_ROOM );
   act( "You create $p with a wave of your hand.", ch, ob, NULL, TO_CHAR );

   ob = create_object( get_obj_index( OBJ_VNUM_PORTAL ), level );
   obj_to_room( ob, beacon->in_room );
   ob->timer = 1 + ( level / 30 );
   ob->value[0] = ch->in_room->vnum;
   ob->value[1] = 1;
   ob->value[2] = 1;
   send_to_room( "The beacon suddenly vanishes!\n\r", beacon->in_room );
   send_to_room( "A glowing portal suddenly forms before you!\n\r", ob->in_room );
   extract_obj( beacon );
   return TRUE;
}

bool spell_beacon( int sn, int level, CHAR_DATA * ch, void *vo, OBJ_DATA * obj )
{
   /*
    * Create a beacon, ready for a portal to 'goto'.
    * * I owe someone thanks for this, but forgot the name... D'oh.
    * * How this works: (+ for portals, etc )
    * * a) Caster makes beacon: ownership set, obj->name = target_name
    * * b) Someone goes off with beacon, drops it
    * * c) Owner can then cast portal spell to it, beacon extracted
    * * -S- 
    */

   char buf[MAX_STRING_LENGTH];
   char arg[MAX_STRING_LENGTH];
   OBJ_DATA *ob;

   one_argument( target_name, arg );

   ob = get_obj_world( ch, arg );
   if( ob != NULL )
   {
      send_to_char( "There is already an object with that keyword.\n\r", ch );
      return FALSE;
   }

   ob = create_object( get_obj_index( OBJ_VNUM_BEACON ), level );
   sprintf( buf, "%s", arg );
   free_string( ob->name );
   ob->name = str_dup( arg );
   sprintf( buf, "%s", ch->name );
   free_string( ob->owner );
   ob->owner = str_dup( buf );
   ob->timer = number_range( 30, 45 );
   obj_to_room( ob, ch->in_room );
   act( "$n magically produces $p!", ch, ob, NULL, TO_ROOM );
   act( "You magically produce $p!", ch, ob, NULL, TO_CHAR );
   return TRUE;
}