FlCodebase3.1/
FlCodebase3.1/bounty/
FlCodebase3.1/challenge/
FlCodebase3.1/clans/
FlCodebase3.1/gods/
FlCodebase3.1/mobprogs/
FlCodebase3.1/player/
FlCodebase3.1/savemud/
/***************************************************************************
 *  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.                              *
 *                                                                         *
 *  In order to use any part of this Envy Diku Mud, you must comply with   *
 *  the original Diku license in 'license.doc', the Merc license in        *
 *  'license.txt', as well as the Envy license in 'license.nvy'.           *
 *  In particular, you may not remove either of these copyright notices.   *
 *                                                                         *
 *  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.                                                  * 
 *                                                                         *
 *      ROM 2.4 is copyright 1993-1998 Russ Taylor                         *
 *      ROM has been brought to you by the ROM consortium                  *
 *          Russ Taylor (rtaylor@hypercube.org)                            *
 *          Gabrielle Taylor (gtaylor@hypercube.org)                       *
 *          Brian Moore (zump@rom.org)                                     *
 *      By using this code, you have agreed to follow the terms of the     *
 *      ROM license, in the file Rom24/doc/rom.license                     *
 *                                                                         *
 * Code Adapted and Improved by Abandoned Realms Mud                       *
 * and Aabahran: The Forsaken Lands Mud by Virigoth                        *
 *                                                                         *
 * Continued Production of this code is available at www.flcodebase.com    *
 ***************************************************************************/


#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "magic.h"
#include "recycle.h"
#include "interp.h"

extern char *target_name;
extern bool effect_manalock(int sn, int level, CHAR_DATA* ch, CHAR_DATA* victim);
#define		WEP_NAMED	(dd)

void spell_mind_thrust( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA* victim = (CHAR_DATA *) vo;
    int dam = dice(level / 5, 5) + 2 * level;

    if (is_affected(ch, gsn_mindsurge))
      dam = 50 + 2 * level;

    if (level < 15
	|| (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
	    && saves_spell(level, victim, DAM_MENTAL, skill_table[sn].spell_type))
	){
      dam /= 2;
    }
    else{
      AFFECT_DATA af;

      af.where		= TO_AFFECTS;
      af.type		= sn;
      af.level		= ch->level;
      af.duration	= number_range(1, 2);
      af.location	= APPLY_SAVING_MENTAL;
      af.modifier	= number_range(1, 4);
      af.bitvector	= 0;
      affect_join(victim,&af);
      act_new( "You become less confident.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
      if ( ch != victim )
	act("$N becomes less confident.",ch,NULL,victim,TO_CHAR);
    }
    damage( ch, victim, dam, sn, DAM_MENTAL, TRUE);
}

void spell_mind_disruption( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    int dam = dice(level / 5, 5) + 2 * level;

    if (is_affected(ch, gsn_mindsurge))
      dam = 50 + 2 * level;

    if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
	&& saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type))
      dam /= 2;
    else if (dam > 1){
    //make it harder to concentrate on spells
      AFFECT_DATA* paf, af;
      if  ( (paf = affect_find(victim->affected, gsn_mind_disrupt)) == NULL
	    || paf->modifier > -60){
	af.type		= gsn_mind_disrupt;
	af.level		= ch->level;
	af.duration		= 1;
	af.where		= TO_AFFECTS;
	af.bitvector		= 0;
	af.location		= APPLY_NONE;
	af.modifier		= -20;
	affect_join( victim, &af );
	act("You disrupt $N's ability to concentrate.", ch, NULL, victim, TO_CHAR);
	act("$n disrupts your ability to concentrate.", ch, NULL, victim, TO_VICT);
      }
    }
    damage( ch, victim, dam, sn, DAM_MENTAL,TRUE);
}

void spell_mind_blast( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    int dam = dice(level / 5, 5) + 3 * level;

    if (is_affected(ch, gsn_mindsurge))
      dam = 50 + 3 * level;

    if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
	&& saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type))
      dam /= 2;
    victim->mana = UMAX(0, victim->mana - dam / 2 );
    damage( ch, victim, dam, sn, DAM_MENTAL,TRUE);
}

void spell_psychic_crush( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    int dam = dice(4, 3) + level * 2;
    if (saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type))
	dam /= 2;
    if (!IS_SET(victim->act, ACT_UNDEAD) && number_percent() < level)
      {
	send_to_char("You feel you psyche slip.\n\r", victim);
	act("$N's eyes glaze over momentarly.", victim, NULL, victim, TO_ROOM);
	victim->mana = UMAX(0, victim->mana - dam / 2);
      }
    damage( ch, victim, dam, sn, DAM_MENTAL,TRUE);
}

void spell_psionic_blast( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
  CHAR_DATA *vch, *vch_next;
  int dam = 0;
  
  act("You send a blast of mental energy through the room.",ch,NULL,NULL,TO_CHAR);
  act("A blast of mental energy surges through the room.",ch,NULL,NULL,TO_ROOM);

  for (vch = ch->in_room->people; vch; vch = vch_next){
    vch_next = vch->next_in_room;
    
    if ( vch == ch || is_area_safe_quiet(ch,vch))
      continue;
    
    dam = dice(level / 5, 10) + 3 * level;
    if (is_affected(ch, gsn_mindsurge))
      dam = 100 + 3 * level;
    
    if (psiamp_failed(ch, vch, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
	&& saves_spell(level, vch, DAM_MENTAL,skill_table[sn].spell_type))
      dam /= 2;
    else if (!IS_UNDEAD(vch)){
      /* paralyze */
      if (!is_affected(vch, gsn_paralyze)){
	AFFECT_DATA af;
	act("$n has been paralyzed!", vch, NULL, NULL, TO_ROOM);
	act("You have been paralyzed!", vch, NULL, NULL, TO_CHAR);
	
	af.type      = gsn_paralyze;
	af.level     = level;
	af.duration  = number_range(1, 3);
	af.where     = TO_AFFECTS;
	af.bitvector = 0;
	af.location  = APPLY_NONE;
	af.modifier  = 3 * af.duration;
	affect_to_char( vch, &af );
      }
    }
    m_yell(ch,vch,FALSE);    
    damage( ch, vch, dam, sn, DAM_MENTAL,TRUE);
  }
}

/* mental spells do more damage */
void spell_psychic_purge( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;

    if ( is_affected( victim, sn )
	 || check_immune(victim, DAM_MENTAL, FALSE) == IS_VULNERABLE)
      {
	if (victim == ch)
	  act("You are already vulnerable to mental attacks.",ch,NULL,victim,TO_CHAR);
	else
	  act("$N is already vulnerable to mental attacks.",ch,NULL,victim,TO_CHAR);
	return;
      }

    if (IS_UNDEAD(victim)
	|| (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
	    && saves_spell( level, victim, DAM_MENTAL,skill_table[sn].spell_type))
	){
      act("$N resists your efforts.", ch, NULL, victim, TO_CHAR);
      return;
    }

    af.where	= TO_AFFECTS;
    af.type      = sn;
    af.level     = level;
    af.duration  = level/5;
    af.modifier  = 0;
    af.location  = APPLY_NONE;
    af.bitvector = 0;
    affect_to_char( victim, &af );
    act_new( "You are now more vulnerable to mental damage.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
    if ( ch != victim )
      act("$N is now vulnerable to mental damage.",ch,NULL,victim,TO_CHAR);
}

void spell_photon( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
  AFFECT_DATA af;

  if (is_affected(ch, gen_photon_wall)){
    send_to_char("You are already shielded.\n\r", ch);
    return;
  }

  af.where	= TO_AFFECTS;
  af.type      = gen_photon_wall;
  af.level     = level;
  af.duration  = 24;
  af.modifier  = 0;
  af.location  = 0;
  af.bitvector = 0;
  affect_to_char( ch, &af );
}


void spell_flesh_armor( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
    if ( is_affected( victim, sn ))
    {
	act("Your flesh has already been hardened.",ch,NULL,victim,TO_CHAR);
	return;
    }
    af.where	= TO_AFFECTS;
    af.type      = sn;
    af.level     = level;
    af.duration  = level / 2;
    if (ch->class == class_lookup("psionicist"))
      af.modifier  = -25 - level / 2;
    else
      af.modifier  = -20;
    af.location  = APPLY_AC;
    af.bitvector = 0;
    affect_to_char( victim, &af );
    act_new( "You cause your flesh to numb and thicken.",victim,NULL,NULL,TO_CHAR,POS_DEAD);
    act("$n's flesh becomes inanimate.",victim,NULL,NULL,TO_ROOM);
}

void spell_detect_aura( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
    if ( is_affected( victim, sn ))
    {
	act("You can already detect auras.",ch,NULL,victim,TO_CHAR);
	return;
    }
    affect_strip(victim, skill_lookup("detect good"));
    affect_strip(victim, skill_lookup("detect evil"));
    affect_strip(victim, skill_lookup("detect magic"));
    affect_strip(victim, skill_lookup("detect invis"));

    af.where     = TO_AFFECTS;
    af.type      = sn;
    af.level     = level;
    af.duration  = level > 25 ? 48 : 24;
    af.modifier  = 0;
    af.location  = 0;
    af.bitvector = AFF_DETECT_GOOD;
    affect_to_char( victim, &af );
    af.where     = TO_AFFECTS;
    af.type      = sn;
    af.level     = level;
    af.modifier  = 0;
    af.location  = 0;
    af.bitvector = AFF_DETECT_EVIL;
    affect_to_char( victim, &af );
    af.where     = TO_AFFECTS;
    af.type      = sn;
    af.level     = level;
    af.modifier  = 0;
    af.location  = 0;
    af.bitvector = AFF_DETECT_MAGIC;
    affect_to_char( victim, &af );
    af.where     = TO_AFFECTS;
    af.type      = sn;
    af.level     = level;
    af.modifier  = 0;
    af.location  = 0;
    af.bitvector = AFF_DETECT_INVIS;
    affect_to_char( victim, &af );
    act_new( "You can now detect auras.",victim,NULL,NULL,TO_CHAR,POS_DEAD);
}

void spell_displacement( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
    if ( is_affected( victim, sn ))
    {
	act("Your image is already projected away from your body.",ch,NULL,victim,TO_CHAR);
	return;
    }
    af.where	= TO_AFFECTS;
    af.type      = sn;
    af.level     = level;
    af.duration  = 8 + level;
    af.modifier  = -(10 + level);
    af.location  = APPLY_AC;
    af.bitvector = 0;
    affect_to_char( victim, &af );
    act_new( "You project your image away from your body.",victim,NULL,NULL,TO_CHAR,POS_DEAD);
    act("$n seems to move away from where you thought $e was.",victim,NULL,NULL,TO_ROOM);
}

void spell_awaken( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim;
    AFFECT_DATA af;
    if ( ( victim = get_char_world( ch, target_name ) ) == NULL )
    {
        send_to_char( "They aren't here.\n\r",ch );
        return;
    }
    if (is_affected(ch, sn)){
      send_to_char("You are too tired for another attempt.\n\r", ch);
      return;
    }
    if ( IS_AWAKE(victim) )
    {   
      act("They are already awake.",ch,NULL,victim,TO_CHAR);
      return;
    }
    if (IS_UNDEAD(victim))
    {
        sendf(ch, "You can't awaken %s!\n\r", PERS(victim,ch));
        return;
    }
    act_new( "A voice in your head commands you to wake up.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
    act("You have awakened $N.",ch,NULL,victim,TO_CHAR);
    affect_strip(victim, gsn_sleep);
    do_stand(victim,"");

    af.type = sn;
    af.level = level;
    af.duration = number_fuzzy(4);
    af.where = TO_AFFECTS;
    af.bitvector = 0;
    af.modifier = 0;
    af.location = APPLY_NONE;
    affect_to_char(ch, &af);
}

void spell_mental_drain( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA* victim = (CHAR_DATA *) vo;
    int dam = UMAX(25, victim->mana / 5);
    if ( psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
	 && saves_spell( level, victim, DAM_MENTAL,skill_table[sn].spell_type) ){
      
      act("You failed to drain $N's mental power.",ch,NULL,victim,TO_CHAR);
      act_new("You feel something invading your mind.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
      return;
    }
    if (victim->mana < 1){
      send_to_char("You only sense emptiness.\n\r", ch);
      return;
    }

    ch->mana = UMIN(ch->max_mana, ch->mana + dam);
    victim->mana -= dam;
    victim->mana = UMAX(0, victim->mana);

    act_new("You feel your mental powers slipping away!",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
    act("You have absorbed $N's mental powers!",ch,NULL,victim,TO_CHAR);
}

void spell_iron_will( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
    if ( is_affected( victim, sn ))
    {
	act("Your self-control is already as strong as it can be.",ch,NULL,victim,TO_CHAR);
	return;
    }
    af.where	= TO_AFFECTS;
    af.type      = sn;
    af.level     = level;
    af.duration  = ch->level/2;
    af.modifier  = -level/15;
    af.location  = APPLY_SAVING_SPELL;
    af.bitvector = 0;
    affect_to_char( victim, &af );
    act_new( "Your self-control increases.",victim,NULL,NULL,TO_CHAR,POS_DEAD);
}

void spell_cell_adjustment( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA* victim = (CHAR_DATA *) vo;
    int chance = IS_NPC(ch) ? 100 : get_skill(ch,sn) - 25;
    send_to_char("Your body begins to right itself.\n\r", victim);
    if (is_affected(victim,gsn_blindness) && number_percent() < chance)
    {
        affect_strip(victim,gsn_blindness);
	send_to_char("Your can see again.\n\r",victim);
    }
    if (!IS_NPC(ch) && is_affected(victim,gsn_death_grasp) && number_percent() < chance)
    {
        affect_strip(victim,gsn_death_grasp);
	send_to_char("You regain some of your vitality.\n\r",victim);
    }
     if (is_affected(victim,gsn_poison) && number_percent() < chance)
    {
        affect_strip(victim,gsn_poison);
	send_to_char("You feel less sick.\n\r",victim);
    }
     if (is_affected(victim,gsn_plague) && number_percent() < chance)
    {
        affect_strip(victim,gsn_plague);
	send_to_char("Your sores vanish.\n\r",victim);
    }
     if (!IS_NPC(ch) && is_affected(victim,skill_lookup("dysentery")) && number_percent() < chance)
    {
        affect_strip(victim,skill_lookup("dysentery"));
	send_to_char("Your bowel movements returns to normal.\n\r",victim);
    }
     if (is_affected(victim,gsn_enfeeblement) && number_percent() < chance)
    {
        affect_strip(victim,gsn_enfeeblement);
	send_to_char("Your sores vanish.\n\r",victim);
    }
     if (is_affected(victim,gsn_embrace_poison) && number_percent() < chance)
       affect_strip(victim,gsn_embrace_poison);

}

void spell_bio_manipulation( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA* victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
    int type = ch->fighting ? number_range(0,3) : number_range(0,2);
    if (IS_UNDEAD(victim))
      {
	send_to_char("Strange, but the cells are totaly inert, almost as if dead...\n\r", ch);
	return;
      }

    switch (type)
    {
    case (0):
    	af.where		= TO_AFFECTS;
        af.type                 = gsn_gag;
        af.level                = ch->level;
        af.duration             = number_range(0,2);
        af.location             = 0;
        af.modifier             = 0;
        af.bitvector            = 0;
        affect_join(victim,&af);
	act_new( "Your vocal cords grow inanimate.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
	if ( ch != victim )
	    act("You impare $N's vocal cords.",ch,NULL,victim,TO_CHAR);
	break;
    case (1):
    	af.where		= TO_AFFECTS;
        af.type                 = gsn_silence;
        af.level                = ch->level;
        af.duration             = number_range(0,2);
        af.location             = 0;
        af.modifier             = 0;
        af.bitvector            = 0;
        affect_join(victim,&af);
	act_new( "Your hearing weakens.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
	if ( ch != victim )
	    act("You impare $N's ear drums.",ch,NULL,victim,TO_CHAR);
	break;
    case (2):
	af.where		= TO_AFFECTS;
        af.type                 = gsn_blindness;
        af.level                = ch->level;
        af.duration             = number_range(0,2);
        af.location             = 0;
        af.modifier             = 0;
        af.bitvector            = AFF_BLIND;
        affect_join(victim,&af);
	act_new( "Your vision begins to fail.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
	if ( ch != victim )
	    act("You impare $N's optic nerves.",ch,NULL,victim,TO_CHAR);
	break;
    case (3):
	WAIT_STATE(victim, 12 * number_range(1, 3) );
	act_new( "Your motor functions stop working.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
	if ( ch != victim )
	    act("You halt $N's motor functions.",ch,NULL,victim,TO_CHAR);
	break;
    }
}

void spell_ego_whip( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
    int dam = number_fuzzy(level);
    int svs_mental = ch->savingspell + ch->savingmental;

    af.where		    = TO_AFFECTS;
    af.type                 = gsn_ego_whip;
    af.level                = ch->level;
    af.duration             = number_range(2,3);
    af.location             = APPLY_SAVING_MENTAL;
    af.modifier             = -2 * svs_mental / 10;
    af.bitvector            = 0;
    affect_join(victim,&af);
    act_new( "You become less confident.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
    if ( ch != victim )
      act("$N becomes less confident.",ch,NULL,victim,TO_CHAR);
    damage( ch, victim, dam, sn, DAM_MENTAL,TRUE);
}

void spell_tele_lock( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
    if (is_safe(ch,victim) && victim != ch){
      sendf(ch, "Not on %s.\n\r",PERS(victim,ch));
    return;
    }
    if ( is_affected(victim, gsn_tele_lock))
    {
	if (victim == ch)
	    act("You are already locked down.",ch,NULL,victim,TO_CHAR);
	else
	    act("$N is already locked down.",ch,NULL,victim,TO_CHAR);
        return;
    }
    else if (ch == victim){
      send_to_char("You failed.\n\r", ch);
      return;
    }
    if (!psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
	|| !saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type))
    {
    	af.where	= TO_AFFECTS;
        af.type                 = gsn_tele_lock;
        af.level                = ch->level;
        af.duration             = ch->level / 4;
        af.location             = 0;
        af.modifier             = 0;
        af.bitvector            = 0;
	affect_to_char( victim, &af );
	act_new( "You are now locked down",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
	if ( ch != victim )
	    act("$N is now locked down.",ch,NULL,victim,TO_CHAR);
    }
    else
      send_to_char("You failed.\n\r", ch);
}

void spell_enhance_armor( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    OBJ_DATA *obj = (OBJ_DATA *) vo;
    int fail = 50, result, i;
    char buf[MSL];
    if (obj->item_type != ITEM_ARMOR)
    {
        send_to_char("That isn't an armor.\n\r",ch);
        return;
    }   
    if (obj->wear_loc != -1)
    {
        send_to_char("The item must be carried to be enchanted.\n\r",ch);
        return;
    }
    if (IS_OBJ_STAT(obj,ITEM_PSI_ENHANCE))
    {
        send_to_char("This item is already psionically altered.\n\r",ch);
        return;
    }
    if (obj->value[0] == 0 && obj->value[1] == 0 && obj->value[2] == 0 && obj->value[3] == 0)
    {
        send_to_char("This item can not be psionically enhanced at all.\n\r",ch);
        return;
    }
    fail += obj->level;
    fail -= level;
    if (IS_OBJ_STAT(obj,ITEM_BLESS))
        fail -= 10;
    if (IS_OBJ_STAT(obj,ITEM_MAGIC))
        fail += 25;
    fail -= get_curr_stat(ch,STAT_LUCK) - 16;
    fail = URANGE(5,fail,85);   
    result = number_percent();
    SET_BIT(obj->extra_flags, ITEM_MAGIC);
    if (result < (fail / 5) && !IS_IMMORTAL(ch))
    {
        act("$p glows red hot and melts!",ch,obj,NULL,TO_ALL);
        sprintf( buf, "lump %s", obj->material);
        free_string( obj->name );
        obj->name = str_dup( buf );
        sprintf( buf, "A lump of %s", obj->material);
        free_string( obj->short_descr );
        obj->short_descr = str_dup( buf );
        sprintf( buf, "A lump of %s lies here.", obj->material);
        free_string( obj->description );
        obj->description = str_dup( buf );
	obj->wear_flags = ITEM_TAKE + ITEM_HOLD;
	for (i = 0; i < 4; i++)
	    obj->value[i] = 0;
        return;
    }
    if (result < (fail / 3) && !IS_IMMORTAL(ch))
    {
      SET_BIT(obj->extra_flags, ITEM_PSI_ENHANCE);
      act("$p becomes mis-shapened.",ch,obj,NULL,TO_ALL);
      for (i = 0; i < 4; i++)
	obj->value[i] = 0;
      obj->condition = 0;
      return;
    }
    if ( result <= fail && !IS_IMMORTAL(ch))
    {
        send_to_char("The molecules stir for a second but stop.\n\r",ch);
        return;
    }
    SET_BIT(obj->extra_flags, ITEM_PSI_ENHANCE);
    act("$p is enhanced to perfection!",ch,obj,NULL,TO_ALL);
    for (i = 0; i < 4; i++){
      obj->value[i] = UMIN(20, obj->value[i] + obj->value[i] * level / 100);
    }
}

void spell_there_not_there( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
  OBJ_DATA *obj = (OBJ_DATA*) vo;
  AFFECT_DATA af;

  if ((!CAN_WEAR(obj, ITEM_TAKE)
       || (CAN_WEAR(obj, ITEM_NO_SAC) && obj->timer == 0)
       || obj->item_type == ITEM_CABAL 
       || obj->wear_flags == 0)
      && obj->timer == 0//time is here so requested items can be affected.
      //(request items will have above flags, but times is != 0)
      ){
    send_to_char("Not on that object!\n\r", ch);
    return;
  }
  
  if (is_affected_obj(obj, sn))
    {
        send_to_char("This item is already phased out.\n\r",ch);
        return;
    }
    if (is_affected(ch, sn))
      {
	send_to_char("You are not ready for another attempt.\n\r", ch);
	return;
      }

    if (obj->item_type == ITEM_CORPSE_PC
	|| obj->pIndexData->vnum == get_temple_pit(ch->in_room->vnum)){
      send_to_char("Not on that object.\n\r", ch);
      return;
    }

    af.type       = sn;
    af.level      = level;
    af.duration   = level / 4;
    af.location   = 0;
    af.modifier   = 0;
    af.where = TO_AFFECTS;
    af.bitvector  = 0;
    affect_to_char(ch, &af);
    affect_to_obj(obj, &af);

    act("You phase $p out of this dimension.", ch, obj, NULL, TO_CHAR);
    act("You see something disappear from $n's hands.", ch, NULL, NULL, TO_ROOM);
}

void spell_phase_shift( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    ROOM_INDEX_DATA *room;
    if (!IS_NULLSTR(target_name )){
      spell_mind_store( sn, level, ch, vo, target );
      return;
    }
    if (!IS_NPC(ch) && ch->pcdata->pStallion != NULL)
    {
      sendf(ch, "You cannot shift while on %s!\n\r",ch->pcdata->pStallion->short_descr);
      return;
    }
    if (ch->pcdata->beacon == 0 || (room = get_room_index(ch->pcdata->beacon)) == NULL)
	room = get_room_index(get_temple(ch));
    if ( IS_SET(room->room_flags, ROOM_SAFE)
    || IS_SET(room->room_flags, ROOM_PRIVATE)
    || IS_SET(room->room_flags, ROOM_SOLITARY)
    || IS_SET(room->room_flags, ROOM_NO_GATEIN)
    || IS_SET(ch->in_room->room_flags, ROOM_NO_GATEOUT)
    || IS_SET(ch->in_room->room_flags, ROOM_NO_INOUT)
    || is_affected(ch, gsn_tele_lock)
    || IS_SET(room->room_flags, ROOM_NO_INOUT))
    {
        send_to_char("You failed the phase shift.\n\r",ch);
        return;
    }
    else if (is_affected(ch,gen_ensnare)){
      send_to_char("You sense a powerful magical field preventing your departure.\n\r", ch);
      return;
    }
    act("$n closes $s eyes and vanishes.",ch,NULL,NULL,TO_ROOM);
    act("You close your eyes and vanish.",ch,NULL,NULL,TO_CHAR);
    char_from_room(ch);
    char_to_room(ch,room);
    act("$n suddenly appears and opens $s eyes.",ch,NULL,NULL,TO_ROOM);
    do_look(ch,"auto");
}

void spell_mind_store( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    char arg[MSL];
    one_argument(target_name, arg);
    if (arg[0] != '\0' && !str_cmp(arg, "none"))
    {
	ch->pcdata->beacon = 0;
	send_to_char("You empty your mind.\n\r",ch);
	return;
    }
    else
    {
        if (ch->in_room == NULL)   
            return;
        if ( IS_SET(ch->in_room->room_flags, ROOM_SAFE)
        || IS_SET(ch->in_room->room_flags, ROOM_PRIVATE)
        || IS_SET(ch->in_room->room_flags, ROOM_SOLITARY)
        || IS_SET(ch->in_room->room_flags, ROOM_NO_GATEIN)
        || IS_SET(ch->in_room->room_flags, ROOM_NO_INOUT))
        {
            send_to_char("You failed to memorize this room.\n\r",ch);
            return;
        }
        send_to_char("You memorize this room.\n\r",ch);
        ch->pcdata->beacon = ch->in_room->vnum;
    }
}

void spell_levitate( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
  CHAR_DATA *victim = (CHAR_DATA*) vo;
  AFFECT_DATA af;

  if ( is_affected( victim, gen_levitation )){
    send_to_char("You are already levitated.\n\r", ch);
    return;
  }
  af.type      = gen_levitation;
  af.level     = level;
  af.duration  = URANGE(12, level - 2, 48);
  af.where	 = TO_AFFECTS;
  af.bitvector = AFF_FLYING;
  af.modifier  = APPLY_NONE;
  af.location  = 0;
  
  if (!IS_AFFECTED(ch, AFF_FLYING)){
    act_new( "Your feet rise off the ground.",victim,NULL,NULL,TO_CHAR,POS_DEAD);
    act("$n's feet rise off the ground.",victim,NULL,NULL,TO_ROOM);
  }
  affect_to_char( victim, &af );

}


void do_wish( CHAR_DATA* ch, char* argument){
  AFFECT_DATA* paf;
  CHAR_DATA* vch;
  const int dur = 24;
  const int gsn_wish = skill_lookup("wish");
  if ( (paf = affect_find(ch->affected, gsn_wish)) == NULL
       || paf->modifier){
    send_to_char("Huh?\n\r", ch);
    return;
  }

  if (IS_NULLSTR(argument)){
    send_to_char("You may wish for FOOD, TRAINING, PROTECTION, or HEALING.\n\r", ch);
    return;
  }
  else if (!str_prefix(argument, "food")){
    act("The magical flames roar with power as $n wishes for food.", ch, NULL, NULL, TO_ROOM);
    act("The magical flames roar with power as you wish for food.", ch, NULL, NULL, TO_CHAR);
    paf->modifier = TRUE;//completed wish
    paf->duration = dur;

    for (vch = ch->in_room->people; vch; vch = vch->next_in_room){
      if (IS_NPC(vch) || !is_same_group(ch, vch))
	continue;
      if (vch->pCabal && IS_CABAL(vch->pCabal, CABAL_NOMAGIC))
	continue;
      send_to_char("You feel all traces of hunger and thirst disappear.\n\r", vch);
      vch->pcdata->condition[COND_HUNGER]  = 100;
      vch->pcdata->condition[COND_THIRST]  = 100;
    }
    WAIT_STATE2(ch, 2 * PULSE_VIOLENCE );
    return;
  }
  else if (!str_prefix(argument, "training")){
    CHAR_DATA* trainer;
    AFFECT_DATA af;
    act("The magical flames roar with power as $n wishes for training.", ch, NULL, NULL, TO_ROOM);
    act("The magical flames roar with power as you wish for training.", ch, NULL, NULL, TO_CHAR);
    paf->modifier = TRUE;//completed wish
    paf->duration = dur;
    trainer = create_mobile(get_mob_index(MOB_VNUM_WISH_TRAINER));
    char_to_room(trainer, ch->in_room);
    af.type = gsn_timer;
    af.level = paf->level;
    af.duration = 3;
    af.where = TO_NONE;
    af.bitvector = 0;
    af.location = APPLY_NONE;
    af.modifier = 0;
    affect_to_char(trainer, &af);

    act("$n suddenly appears before you.", trainer, NULL, NULL, TO_ROOM);
    do_say(trainer, "What do you wish to practice or train?");
    WAIT_STATE2(ch, 2 * PULSE_VIOLENCE );
    return;
  }
  else if (!str_prefix(argument, "protection")){
    int sn = 0;
    act("The magical flames roar with power as $n wishes for protection.", ch, NULL, NULL, TO_ROOM);
    act("The magical flames roar with power as you wish for protection.", ch, NULL, NULL, TO_CHAR);
    paf->modifier = TRUE;//completed wish
    paf->duration = dur;

    /* select random spell */
    switch (number_range(1, 4)){
    case 1: sn = skill_lookup("armor");		break;
    case 2: sn = skill_lookup("shield");	break;
    case 3: sn = skill_lookup("stone skin");	break;
    default: sn = gsn_sanctuary;		break;
    }

    for (vch = ch->in_room->people; vch; vch = vch->next_in_room){
      if (IS_NPC(vch) || !is_same_group(ch, vch))
	continue;
      if (vch->pCabal && IS_CABAL(vch->pCabal, CABAL_NOMAGIC))
	continue;
      (*skill_table[sn].spell_fun) ( sn, 60, vch, vch, 0);
    }
    WAIT_STATE2(ch, 2 * PULSE_VIOLENCE );
    return;
  }
  else if (!str_prefix(argument, "healing")){
    act("The magical flames roar with power as $n wishes for healing.", ch, NULL, NULL, TO_ROOM);
    act("The magical flames roar with power as you wish for healing.", ch, NULL, NULL, TO_CHAR);
    paf->modifier = TRUE;//completed wish
    paf->duration = dur;

    for (vch = ch->in_room->people; vch; vch = vch->next_in_room){
      if (IS_NPC(vch) || !is_same_group(ch, vch))
	continue;
      if (vch->pCabal && IS_CABAL(vch->pCabal, CABAL_NOMAGIC))
	continue;
      if (vch->hit > 4 * vch->max_hit / 5){
	send_to_char("You lack any serious wounds to heal.\n\r", vch);
      }
      else{
	act("Some of $n's wounds disappear.", vch, NULL, NULL, TO_ROOM);
	send_to_char("Some of your wounds disappear.\n\r", vch);
	vch->hit = UMAX(4 * vch->max_hit / 5, vch->hit + vch->max_hit / 3);
	update_pos( vch );
      }

      if (number_percent() < 50){
	if (IS_AFFECTED(vch, AFF_BLIND)){
	  check_dispel(paf->level,vch,gsn_blindness);
	}	
	if (IS_AFFECTED(vch,AFF_POISON)){
	  check_dispel(paf->level,vch,gsn_poison);
	}
	if (IS_AFFECTED(vch, AFF_PLAGUE)){
	  check_dispel(paf->level,vch,gsn_plague);
	}
	if (IS_AFFECTED(vch, AFF_CURSE)){
	  check_dispel(paf->level,vch,gsn_curse);
	}
      }
    }
    WAIT_STATE2(ch, 2 * PULSE_VIOLENCE );
    return;
  }
  else
    do_wish( ch, "");
}


  
/* first part of the do_wish */
void spell_wish( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
  CHAR_DATA *victim = (CHAR_DATA*) vo;
  AFFECT_DATA af;

  if ( is_affected( victim, sn )){
    send_to_char("You are not ready to make another wish.\n\r", ch);
    return;
  }
  if (number_percent() > get_skill(ch, sn)){
    int dam = number_range(150, 250);
   send_to_char("Your self control slips for a moment!\n\r", ch );
   act("$n's self control slips for a moment!\n\r", ch, NULL, NULL, TO_ROOM);
   damage(ch, ch, dam, sn, DAM_INTERNAL, TRUE);
   return;
  }

  af.type      = sn;
  af.level     = level;
  af.duration  = 3;
  af.where     = TO_AFFECTS;
  af.bitvector = 0;
  af.modifier  = APPLY_NONE;
  af.location  = FALSE;//wish not made yet
  affect_to_char( victim, &af );
  act("A ring of blue flames erupts around $n.", ch, NULL, NULL, TO_ROOM );
  act("A ring of blue flames erupts around you.", ch, NULL, NULL, TO_CHAR );
  act("A voice says '`#I await your wish $n.``'", ch, NULL, NULL, TO_ALL );
  send_to_char("Use the \"wish\" command to complete your wish.\n\r", ch );
}

void spell_gravitate( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    OBJ_DATA *obj = (OBJ_DATA *) vo;
    AFFECT_DATA af;
    if ( is_affected_obj( obj, sn))
    {
	send_to_char("That object is already gravitated.\n\r", ch);
	return;
    }
    if ( is_affected_obj( obj, gsn_levitate))
    {
	act("$p falls to the ground.",ch,obj,NULL,TO_CHAR);
	affect_strip_obj(obj, gsn_levitate);
	return;
    }

    if ( (!CAN_WEAR(obj, ITEM_TAKE)
	  || CAN_WEAR(obj, ITEM_NO_SAC)
	  || obj->weight > 1000
	  || obj->wear_flags == 0
	  || obj->item_type == ITEM_CABAL)
	 && obj->timer == 0
	  //time is here so requested items can be affected.
	  //(request items will have above flags, but times is != 0)
	 )
	{
	  send_to_char("The spell seems to fail.\n\r", ch);
	  return;
	}
    act("$p seems to gain weight and sinks into the ground.", ch, obj, NULL, TO_ALL);
    af.type       = sn;
    af.level      = level;  
    af.duration   = level;
    af.location   = 0;
    af.modifier   = 0;
    af.bitvector  = 0;
    affect_to_obj(obj, &af);
}

void spell_bio_feedback( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
    if ( is_affected( victim, sn ))
    {
	act("You are already controlling your blood flow.",ch,NULL,victim,TO_CHAR);
	return;
    }
    af.where	= TO_AFFECTS;
    af.type      = sn;
    af.level     = level;
    af.duration  = 8 + level;
    af.modifier  = -30;
    af.location  = APPLY_AC;
    af.bitvector = 0;
    affect_to_char( victim, &af );
    act_new( "You control your blood flow.",victim,NULL,NULL,TO_CHAR,POS_DEAD);
}

void spell_psychic_healing( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    int heal = dice(3, 8) + level;
    victim->hit = UMIN( victim->hit + heal, victim->max_hit );
    update_pos( victim );
    act_new("You heal yourself.", ch,NULL,victim,TO_CHARVICT,POS_DEAD );
}

void spell_pyramid_of_force( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
    if ( is_affected( victim, sn ))
    {
      act("You are already surrounded by a pulsating pyramid.",ch,NULL,victim,TO_CHAR);
      return;
    }
    if (is_affected(victim, gsn_sacred_runes)){
      send_to_char("The vile runes seem to negate the effect.\n\r", ch);
      return;
    }
    if (is_affected(victim, gsn_lifeforce))
      {
        if (victim == ch)
	  act("Not with a lifeforce surrounding you!",ch,NULL,victim,TO_CHAR);
        else
	  act("$N is already surrounded by a lifeforce.",ch,NULL,victim,TO_CHAR);
        return;
      } 
    if ( IS_AFFECTED(victim, AFF_SANCTUARY) )
      {
	if (victim == ch)
	  act("You are already in sanctuary.",ch,NULL,victim,TO_CHAR);
	else
	  act("$N is already in sanctuary.",ch,NULL,victim,TO_CHAR);
	return;
      }
    af.where	 = TO_AFFECTS;
    af.type      = sn;
    af.level     = level;
    af.duration  = 12;
    af.modifier  = 0;
    af.location  = 0;
    af.bitvector = 0;
    affect_to_char( victim, &af );
    act_new( "You are surrounded by a pulsating pyramid.",victim,NULL,NULL,TO_CHAR,POS_DEAD);
    act("$n is surrounded by a pulsating pyramid.",victim,NULL,NULL,TO_ROOM);
}

void spell_terror( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
    if (ch == victim)
    {
	send_to_char("You scare yourself.\n\r",ch);
	return;
    }

    if ( is_affected(victim, gsn_fear)){
      act("$N is already cowering in fear.",ch,NULL,victim,TO_CHAR);
      return;
    }
    
    if (saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)
	|| IS_SET(victim->act, ACT_UNDEAD)){
      act_new( "You feel scared for a second.",ch, NULL, victim, TO_CHARVICT, POS_DEAD);
      act("You failed to induce terror in $N.",ch, NULL, victim,TO_CHAR); 
      return;
    }
    
    act_new("You start to panic as your mind runs away from you!",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
    if ( ch != victim )
      act("$N starts to panic in terror!",ch,NULL,victim,TO_CHAR);

    af.where     = TO_AFFECTS; 
    af.type      = gsn_fear;
    af.level     = level;
    af.location  = 0;
    af.duration  = 1;
    af.bitvector = 0;
    af.modifier  = 20;
    affect_to_char(victim, &af);
}

void spell_body_weaponry( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
    if ( is_affected( victim, sn ))
    {
	act("Your hands are already shaped like weapons.",ch,NULL,victim,TO_CHAR);
	return;
    }
    if ( get_eq_char(ch,WEAR_WIELD) != NULL)
    {
	act("You can't be wielding a weapon.",ch,NULL,victim,TO_CHAR);
	return;
    }
    if ( get_eq_char(ch,WEAR_SHIELD) != NULL)
    {
	act("You can't be holding a shield.",ch,NULL,victim,TO_CHAR);
	return;
    }
    if ( get_eq_char(ch,WEAR_HOLD) != NULL)
    {
	act("You can't be holding anything.",ch,NULL,victim,TO_CHAR);
	return;
    }
    af.where	= TO_AFFECTS;
    af.type      = sn;
    af.level     = level;
    af.duration  = 24;
    af.modifier  = ch->level / 10;
    af.location  = APPLY_HITROLL;
    af.bitvector = 0;
    affect_to_char( victim, &af );
    act_new( "You shape your hands into weapons.",victim,NULL,NULL,TO_CHAR,POS_DEAD);
    act("$n shapes $s hands into weapons.",victim,NULL,NULL,TO_ROOM);
}

void spell_ectoplasm( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    AFFECT_DATA af;   
    if (get_summoned(ch, MOB_VNUM_VAPOR) + get_summoned(ch, MOB_VNUM_SOLID) > 0)
    {
        send_to_char("You already have ectoplasm.\n\r",ch);
        return;
    }
    if ( is_affected( ch, sn ) )
    {
        send_to_char("You can not conjure up more ectoplasm.\n\r",ch);
        return;
    }
    af.where	= TO_AFFECTS;
    af.type      = sn;
    af.level     = level;
    af.duration  = 24;
    af.location  = 0;
    af.modifier  = 0;
    af.bitvector = 0;
    affect_to_char( ch, &af );
    act ("You conjure up some ectoplasm!", ch, NULL, NULL, TO_CHAR);
    act ("$n conjures up some ectoplasm!", ch, NULL, NULL, TO_ROOM);
    if (number_percent() <= 50)
	ecto_vapor(ch, NULL);
    else
	ecto_solid(ch, NULL);
}

void ecto_vapor(CHAR_DATA *ch, CHAR_DATA *ecto)
{
  CHAR_DATA* mob;
  MOB_INDEX_DATA* pMobIndex;
  if (ecto == NULL)
    {
      mob = create_mobile( get_mob_index( MOB_VNUM_VAPOR ) );
      char_to_room(mob,ch->in_room);
      mob->level      = ch->level;
      mob->alignment = ch->alignment;
      mob->max_hit    = ch->level*10;
      mob->hit        = mob->max_hit;
      mob->hitroll    = (ch->level/10 + 20) / 2;
      mob->damroll    = (ch->level/10 + 20) / 2;
      mob->damage[DICE_NUMBER]    = 4;
      mob->damage[DICE_TYPE]      = ch->level/10 +1;
      SET_BIT(mob->affected_by, AFF_CHARM);
      mob->comm = COMM_NOTELL|COMM_NOYELL|COMM_NOCHANNELS;
      mob->summoner = ch;
      add_follower(mob,ch);
      mob->leader = ch;
      return;
    }
  pMobIndex = get_mob_index( MOB_VNUM_VAPOR);
  
  ecto->max_hit /= 2;
  ecto->hit /= 2;
  ecto->hitroll /= 2;
  ecto->damroll /= 2;
  ecto->damage[DICE_NUMBER]    = 4;
  act ("$n vaporizes!", ecto, NULL, NULL, TO_ALL);
  ecto->spec_fun   = pMobIndex->spec_fun;


  free_string(ecto->name);
  ecto->name           = str_dup( pMobIndex->player_name );
  free_string(ecto->short_descr);
  ecto->short_descr    = str_dup( pMobIndex->short_descr );
  free_string(ecto->long_descr);
  ecto->long_descr     = str_dup( pMobIndex->long_descr );
  free_string(ecto->description);
  ecto->description    = str_dup( pMobIndex->description );
  
  if (pMobIndex->new_format)
    {
      ecto->act 		= pMobIndex->act;
      ecto->act2 		= pMobIndex->act2;
      REMOVE_BIT(ecto->affected_by, ecto->pIndexData->affected_by);
      SET_BIT(ecto->affected_by, pMobIndex->affected_by);
      ecto->alignment		= pMobIndex->alignment;
      ecto->dam_type		= pMobIndex->dam_type;
      
      ecto->off_flags		= pMobIndex->off_flags;
      ecto->imm_flags		= pMobIndex->imm_flags;
      ecto->res_flags		= pMobIndex->res_flags;
      ecto->vuln_flags		= pMobIndex->vuln_flags;
      
      ecto->sex		= pMobIndex->sex;
      if (ecto->sex == 3)              
	ecto->sex = number_range(1,2);
      ecto->race		= pMobIndex->race;
      ecto->form		= pMobIndex->form;
      ecto->parts		= pMobIndex->parts;
      ecto->size		= pMobIndex->size;
    }
  ecto->pIndexData = pMobIndex;
  interpret(ecto, "remove all");
  interpret(ecto, "drop all");

}

void ecto_solid(CHAR_DATA *ch, CHAR_DATA *ecto)
{
    MOB_INDEX_DATA *pMobIndex;
    CHAR_DATA *mob;
    if (ecto == NULL)
    {
        mob = create_mobile( get_mob_index( MOB_VNUM_SOLID ) );
        char_to_room(mob,ch->in_room);
        mob->level      = ch->level;
	mob->alignment = ch->alignment;
        mob->max_hit    = ch->level*20;
        mob->hit        = mob->max_hit;
        mob->hitroll    = ch->level/10 + 20;
        mob->damroll    = ch->level/10 + 20;
        mob->damage[DICE_NUMBER]    = 8;
        mob->damage[DICE_TYPE]      = ch->level/10 +1;
        SET_BIT(mob->affected_by, AFF_CHARM);
        mob->comm = COMM_NOTELL|COMM_NOYELL|COMM_NOCHANNELS;
        mob->summoner = ch;
        add_follower(mob,ch);
        mob->leader = ch;
	return;
    }

    pMobIndex = get_mob_index( MOB_VNUM_SOLID);
    act ("$n solidifies!", ecto, NULL, NULL, TO_ALL);
    ecto->max_hit *= 2;
    ecto->hit *= 2;
    ecto->hitroll *= 2;
    ecto->damroll *= 2;
    ecto->damage[DICE_NUMBER]    = 8;
    ecto->spec_fun   = pMobIndex->spec_fun;

    free_string(ecto->name);
    ecto->name           = str_dup( pMobIndex->player_name );
    free_string(ecto->short_descr);
    ecto->short_descr    = str_dup( pMobIndex->short_descr );
    free_string(ecto->long_descr);
    ecto->long_descr     = str_dup( pMobIndex->long_descr );
    free_string(ecto->description);
    ecto->description    = str_dup( pMobIndex->description );

    if (pMobIndex->new_format)
    {
	ecto->act 		= pMobIndex->act;
	ecto->act2 		= pMobIndex->act2;
	REMOVE_BIT(ecto->affected_by, ecto->pIndexData->affected_by);
	SET_BIT(ecto->affected_by, pMobIndex->affected_by);
	ecto->alignment		= pMobIndex->alignment;
	ecto->dam_type		= pMobIndex->dam_type;

	ecto->off_flags		= pMobIndex->off_flags;
	ecto->imm_flags		= pMobIndex->imm_flags;
	ecto->res_flags		= pMobIndex->res_flags;
	ecto->vuln_flags		= pMobIndex->vuln_flags;

	ecto->sex		= pMobIndex->sex;
        if (ecto->sex == 3)              
            ecto->sex = number_range(1,2);
	ecto->race		= pMobIndex->race;
	ecto->form		= pMobIndex->form;
	ecto->parts		= pMobIndex->parts;
	ecto->size		= pMobIndex->size;
    }
    ecto->pIndexData = pMobIndex;
}

void spell_hypnosis( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
    if ( victim == ch )
    {
        send_to_char( "You can't place yourself under hypnosis!\n\r", ch );
        return; 
    }
    if (get_curr_stat(ch, STAT_INT ) < get_curr_stat(victim, STAT_INT))
    {
	send_to_char("You cannot hypnotize someone smarter than you.\n\r", ch);
        return;
    }
    if (!IS_AWAKE(victim) || is_affected(victim,gsn_ecstacy))
    {
        act("$N need to be conscious for you to take over $S mind.",ch,NULL,victim,TO_CHAR);
        return;
    }
    if ( IS_AFFECTED(victim, AFF_SLEEP) )
    {
        act( "$N is already asleep.", ch, NULL, victim, TO_CHAR);
	return;
    }
    if (is_affected(victim, gen_watchtower)){
      sendf( ch, "%s is shielded within the Watchtower.\n\r", PERS(victim, ch ));
      return;
    }
    act("$n locks $N's gaze as beads of sweat form on $s forehead.", ch, NULL, victim, TO_NOTVICT);
    act("You lock $N's gaze and try to force $M to sleep.", ch, NULL, victim, TO_CHAR);
    if ( (IS_NPC(victim) && IS_SET(victim->act,ACT_TOO_BIG) )
	 || IS_UNDEAD(victim)
	 || (psiamp_failed(ch, victim, level, DAM_CHARM, skill_table[sn].spell_type, skill_table[sn].flags)
	     && saves_spell(level, victim, DAM_CHARM,skill_table[sn].spell_type))
	 )
      {
        act( "You failed.", ch, NULL, victim, TO_CHAR);
	return;
      }
    if (is_affected(victim, gsn_horse) 
	&& monk_good(victim, WEAR_HEAD) && !IS_NPC(victim) && !IS_IMMORTAL(ch))
      {
	act( "You reverse $n's attempt to charm you, and charm $M instead!", ch, NULL, victim, TO_VICT );
	act("$N reverses your charm, and charms you instead!", ch, NULL, victim, TO_CHAR );
	af.where     = TO_AFFECTS;
	af.type      = sn;
	af.level     = level;
	af.duration  = number_fuzzy( level / 15) +1;
	af.location  = APPLY_NONE;
	af.modifier  = 0;
	af.bitvector = AFF_SLEEP;
	affect_to_char( ch, &af );
	if ( IS_AWAKE(ch) )
	  {
	    send_to_char( "You feel very sleepy...\n\r", ch );
	    do_sleep(ch,"");	
	  }
	return;
      }
    af.where     = TO_AFFECTS;
    af.type      = sn;
    af.level     = level;
    af.duration  = 4;
    af.location  = APPLY_NONE;
    af.modifier  = 0;
    af.bitvector = AFF_SLEEP;
    affect_to_char( victim, &af );
    if ( IS_AWAKE(victim) )
      {
        send_to_char( "You feel very sleepy...\n\r", victim );
	do_sleep(victim,"");	
      }
}


/* field_of_fear effect */
inline bool effect_field_of_fear(CHAR_DATA* ch)
{
  AFFECT_DATA af;

  //bool
  //data
  int chance = 0;

  //const
  const int base_chance = 25;

  //EZ
  if (!IS_SET(ch->in_room->room_flags2, ROOM_PSI_FEAR)
      || IS_IMMORTAL(ch) 
      || is_affected(ch, gsn_mental_barrier) 
      || check_immune(ch, DAM_MENTAL, TRUE) < IS_NORMAL
      || IS_UNDEAD(ch)
      )
    return FALSE;
  //get the chance to scare them away
  chance = base_chance + 2 * (ch->level / 2 - ch->in_room->psitimer);
  chance += (get_curr_stat(ch, STAT_INT) - 20) * 5;

  if (number_percent() < chance)
    {
      act("The hairs on your body stand on end.",ch,NULL,NULL,TO_ROOM);   
      return FALSE;
    }
  
  if (is_affected(ch, skill_lookup("fear"))) {
    return FALSE;
  }

  //we scare them.
  send_to_char("You are overpowered with intense fear.\n\r", ch);
  act("$n's eyes widen in fear", ch, NULL, NULL, TO_ROOM);

/* attach effect to hurt skills */
  af.type = skill_lookup("fear");
  af.level = ch->in_room->psitimer;
  af.duration = number_range(0,1);
  af.where = TO_AFFECTS;
  af.bitvector = 0;
  af.location = APPLY_NONE;
  af.modifier = 0;
  affect_to_char(ch, &af);
  return TRUE;
}//END IF SUCCESS


void spell_field_of_fear( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
  AFFECT_DATA af;
    int chance = int_app[get_curr_stat(ch,STAT_INT)].learn;
    CHAR_DATA *ich, *ich_next;

    if (is_affected(ch, sn))
      {
	send_to_char("You are not ready for another attempt.\n\r", ch);
	return;
      }

    if (IS_SET(ch->in_room->room_flags2, ROOM_PSI_FEAR))
    {
      send_to_char("The area looks too safe to place an effective enchantement.\n\r", ch);
      return;
    }

    for ( ich = ch->in_room->people; ich != NULL; ich = ich->next_in_room )
    {
	if (IS_NPC(ch))
	    chance -= 2;
	else
	    chance -= 5;
    }
    if (IS_SET(ch->in_room->room_flags, ROOM_SAFE) 
	|| ch->in_room->sector_type == SECT_CITY)
      {
	send_to_char("This room is far to peacefull for that.\n\r", ch);
	return;
      }

    if (number_percent() > chance)
      {
        act("You failed to place a field of fear in this room!", ch, NULL, NULL, TO_CHAR );
        act("The hairs on your body tingle.",ch,NULL,NULL,TO_ROOM);   
	return;
    }
    act("You place a field of fear in this room!", ch, NULL, NULL, TO_CHAR );
    act("$n places a field of fear in this room!",ch,NULL,NULL,TO_ROOM);   

    SET_BIT(ch->in_room->room_flags2, ROOM_PSI_FEAR);
    ch->in_room->psitimer = ch->level / 2;

    for ( ich = ch->in_room->people; ich != NULL; ich = ich_next )
      {
        ich_next = ich->next_in_room;
        effect_field_of_fear(ich);
      }
   
    af.type = sn;
    af.level = level;
    af.duration = ch->level / 4;

    af.where = TO_AFFECTS;
    af.bitvector = 0;
    af.location = APPLY_NONE;
    af.modifier = 0;
    affect_to_char(ch, &af);

}

void spell_control_flames( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    OBJ_DATA *obj;
    bool strong = TRUE;
    int dam;
    if ((obj = get_eq_char( victim, WEAR_LIGHT )) == NULL)
    {
	strong = FALSE;
        if ((obj = get_eq_char( ch, WEAR_LIGHT )) == NULL)
	{
	    send_to_char("Neither you nor your opponent are using a light source.\n\r", ch);
	    return;
	}
    }
    dam = dice(2, 8) + UMAX(90, obj->level * 4);
    if (!strong)
	dam /= 2;
    if ( saves_spell( level, victim, DAM_FIRE,skill_table[sn].spell_type) )
        dam /= 2;
    act( "$p glows brightly and shoots forth a ball of fire at you!", victim, obj, NULL, TO_CHAR );
    act( "$p glows brightly and shoots forth a ball of fire at $n!", victim, obj, NULL, TO_ROOM );
    damage( ch, victim, dam, sn, DAM_FIRE ,TRUE);
}

void spell_forget( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
    if ( is_affected( victim, sn ))
    {
	act("$N already forgot all $S spells.",ch,NULL,victim,TO_CHAR);
	return;
    }
    if (saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type) 
	|| IS_UNDEAD(victim))
      if (saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type) 
	  ||IS_UNDEAD(victim))
	{
	  if (IS_UNDEAD(victim))
	    act("$N's mind seems cold and empty.", ch, NULL, victim, TO_CHAR);
	  act("You failed to make $N lose $S memory.",ch,NULL,victim,TO_CHAR);
	  return;
	}

    af.where	= TO_AFFECTS;
    af.type      = sn;
    af.level     = level;
    af.duration  = 1 + (level > 38? 1 : 0);
    af.modifier  = 0;
    af.location  = 0;
    af.bitvector = 0;
    affect_to_char( victim, &af );
    act_new( "Your memory falters and you forget all your spells.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
    if ( ch != victim )
      act("$N forgets all $S spells.",ch,NULL,victim,TO_CHAR);
}

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

    if ( is_affected( victim, sn ))
    {
	act("Your weapon is already grafted to your hands.",ch,NULL,victim,TO_CHAR);
	return;
    }
    if ((obj = get_eq_char(ch,WEAR_WIELD)) == NULL)
    {
	act("You have to be wielding a weapon.",ch,NULL,victim,TO_CHAR);
	return;
    }
    if (IS_OBJ_STAT(obj, ITEM_PSI_ENHANCE))
      {
	act("$p resists your attempts!", ch, obj, NULL, TO_CHAR);
	return;
      }

    af.type      = sn;
    af.level     = level;
    af.duration  = 24;
    af.where	 = TO_AFFECTS;
    af.bitvector = 0;
    af.location  = APPLY_NONE;
    af.modifier  = 0;
    affect_to_char( victim, &af );

    act_new( "You graft $p to your hands.",victim,obj,NULL,TO_CHAR,POS_DEAD);
    act("$n grafts $p to $s hands.",victim,obj,NULL,TO_ROOM);
}

void spell_ballistic_attack( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    OBJ_DATA *obj = (OBJ_DATA *) vo;
    CHAR_DATA *victim;
    int dam;
    int weight = get_obj_weight(obj);

    if ((victim = ch->fighting) == NULL)
    {
	send_to_char("You don't have the anger.\n\r", ch);
	return;
    }
    if (!CAN_WEAR(obj, ITEM_TAKE) 
	|| CAN_WEAR(obj, ITEM_NO_SAC)
	|| obj->item_type == ITEM_CABAL
	|| is_affected_obj(obj, gsn_gravitate)
	|| weight > 1000

	)

    {
	send_to_char("You cannot lift that object.\n\r", ch);
	return;
    }

    dam = dice(level / 10, 8);
    if (is_affected_obj(obj, gsn_levitate))
      dam += UMIN(weight, 500) / 5;
    else
      dam += UMIN(weight, 500) / 3;
    if ( saves_spell( level, victim,DAM_BASH,skill_table[sn].spell_type) )
      dam /= 2;
    act( "$p rises in the air and suddenly flies straight at you!", victim, obj, ch, TO_CHAR );
    act( "$p rises in the air and suddenly flies straight at $n!", victim, obj, ch, TO_ROOM );
    damage( ch, victim, dam, sn, DAM_BASH ,TRUE);
    /* move the object from where it is to the ground */
    if (!ch->in_room)
      return;
    if (obj->carried_by)
      obj_from_char(obj);
    else if (obj->in_obj)
      obj_from_obj(obj);
    else if (obj->in_room)
      obj_from_room(obj);
    obj_to_room(obj, ch->in_room);
}

void spell_mental_barrier( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
    if ( is_affected( victim, sn ))
    {
	act("You have already created a mental barrier",ch,NULL,victim,TO_CHAR);
	return;
    }
    af.where	= TO_AFFECTS;
    af.type      = sn;
    af.level     = level;
    af.duration  = 24;
    af.modifier  = -25;
    af.location  = APPLY_SAVING_MENTAL;
    af.bitvector = 0;
    affect_to_char( victim, &af );
    act_new( "You create a mental barrier.",victim,NULL,NULL,TO_CHAR,POS_DEAD);
}

void spell_telekinetic_barrier( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
}

void spell_psychic_shout( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *vch, *vch_next;
    int dam = dice(5, 8) + level * 2;
    for (vch = ch->in_room->people; vch != NULL; vch = vch_next)
    {
        vch_next = vch->next_in_room;
        if ( saves_spell( level, vch, DAM_MENTAL,skill_table[sn].spell_type) )
            dam /= 2;
        if ( vch != ch && !is_area_safe(ch,vch))
        {
            m_yell(ch,vch,FALSE);
            damage( ch, vch, dam, sn, DAM_MENTAL ,TRUE);
        }
    }
}

void spell_clairvoyance( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim;
    DESCRIPTOR_DATA *orig;
    ROOM_INDEX_DATA *location;
    if ( ( victim = get_char_world( ch, target_name ) ) == NULL )
    {
        send_to_char( "They aren't here.\n\r",ch );
        return;
    }
    if (ch == victim)
      {
	send_to_char("Why not simply open your eyes?\n\r", ch);
	return;
      }

    if ((location = victim->in_room) == NULL)
        return;
    if ( room_is_private( location ) && get_trust(ch) < MAX_LEVEL)
    {
        send_to_char( "That room is private right now.\n\r", ch );
        return;
    }
    if ( !have_access(ch,location) || IS_IMMORTAL(victim) || is_safe_quiet(ch, victim))
    {
        send_to_char( "Something blocks your attempts.\n\r",ch);
        return;
    }       
    if ( saves_spell( level, victim, DAM_MENTAL,skill_table[sn].spell_type ) )
      {
	send_to_char("You failed.\n\r", ch);
	send_to_char("Your eyes feel funny.\n\r", victim);
	return;
      }

    if (IS_UNDEAD(victim) && number_percent() < 60)
      {
	AFFECT_DATA af;
	act("As begin to look through $N's eyes horros of undeath and forces of Limbo tear into you!", ch, NULL, victim, TO_CHAR);
	damage(ch, ch, victim->level * 4, sn, DAM_NEGATIVE, TRUE);
	send_to_char("Unable to stand the strain you collapse.\n\r", ch);
	act("$n's eyes roll back and he collapses.", ch, NULL, NULL, TO_ROOM);

	af.type = gsn_sleep;
	af.level = level;
	af.duration = 1 + victim->level > level? 1: 0 
	  + victim->level-2 > level? 1 : 0 
	  + victim->level - 6 > level? 2: 0;
	af.where = TO_AFFECTS;
	af.bitvector = AFF_SLEEP;
	af.location = APPLY_NONE;
	af.modifier = 0;
	affect_to_char(ch, &af);
	do_sleep(ch, "");
      }

    send_to_char("You look and feel through the faculties of your victim.\n\r", ch);
    orig = victim->desc;
    victim->desc = ch->desc;
    if (number_percent() < 35)
	interpret (victim, "score");
    else
	interpret (victim, "eq");
    victim->desc = orig;
}

void spell_ghoul_touch( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
    if (is_affected(victim,sn))
    {
	send_to_char("They're already sluggish.\n\r",ch);
	return;
    } 
    act("A green glow envelops $n's hands.",ch,NULL,victim,TO_ROOM);
    act("A green glow envelops your hands.",ch ,NULL,NULL, TO_CHAR);

    if (saves_spell(level-2,victim,DAM_NEGATIVE,skill_table[sn].spell_type))
    {
	act("$N wasn't affected by the ghoul touch.",ch,NULL,victim,TO_CHAR);
	if ( ch != victim)
	  act("You shake off $n's ghoul touch.",ch,NULL,victim,TO_VICT);
	return;
    }

    af.where     = TO_AFFECTS;
    af.type      = sn;
    af.level     = level;
    af.duration  = level/5;
    af.location  = 0;
    af.modifier  = 5;
    af.bitvector = 0;
    affect_to_char( victim, &af );
    act_new("You feel very sluggish.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
    if ( ch != victim )
	act("$N looks very sluggish.",ch,NULL,victim,TO_CHAR);
}

void spell_eternal_day( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    ROOM_INDEX_DATA * room;
    AFFECT_DATA af;
    int np = number_percent();
    if (is_affected(ch,sn))
    {
	send_to_char("You cannot cast this spell yet.\n\r",ch);
	return;
    }
    if (ch->in_room == NULL)
        return;
    room = ch->in_room;
    if (room->pCabal)
    {
        send_to_char("Not in a cabal.\n\r",ch);
        return;
    }
    if (np - 2*(get_curr_stat(ch,STAT_LUCK) - 16) < 50)
    {
        send_to_char("You failed to bathe the room with sunlight.\n\r",ch);
        af.where     = TO_AFFECTS;
        af.type      = sn;
        af.level     = level;
        af.location  = 0;
        af.duration  = 24;
        af.bitvector = 0;
        af.modifier  = 0;
        affect_to_char(ch,&af);
        return;
    }
    if (IS_SET(room->room_flags2,ROOM_DAY))
    {
        send_to_char("This room is already bathed in sunlight.\n\r",ch);
        return;
    }
    send_to_char("You bathe the room with eternal sunlight.\n\r",ch);
    act("$n bathes the room with eternal sunlight.",ch,NULL,NULL,TO_ROOM);
    SET_BIT(room->room_flags2,ROOM_DAY);
    REMOVE_BIT(room->room_flags,ROOM_DARK);
    REMOVE_BIT(room->room_flags2,ROOM_NIGHT);
    af.where     = TO_AFFECTS;
    af.type      = sn;
    af.level     = level;
    af.location  = 0;
    af.duration  = 200;
    af.bitvector = 0;
    af.modifier  = 0;
    affect_to_char(ch,&af);
}

void spell_everlasting_night( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    ROOM_INDEX_DATA * room;
    AFFECT_DATA af;
    int np = number_percent();
    if (is_affected(ch,sn))
    {
	send_to_char("You cannot cast this spell yet.\n\r",ch);
	return;
    }
    if (ch->in_room == NULL)
        return;
    room = ch->in_room;
    if (room->pCabal)
    {
        send_to_char("Not in a cabal.\n\r",ch);
        return;
    }
    if (np - 2*(get_curr_stat(ch,STAT_LUCK) - 16) < 50)
    {
        send_to_char("You failed to induce the room into night.\n\r",ch);
        af.where     = TO_AFFECTS;
        af.type      = sn;
        af.level     = level;
        af.location  = 0;
        af.duration  = 24;
        af.bitvector = 0;
        af.modifier  = 0;
        affect_to_char(ch,&af);
        return;
    }
    if (IS_SET(room->room_flags2,ROOM_DAY))
    {
        send_to_char("This room is already stopped in nighttime.\n\r",ch);
        return;
    }
    if (mud_data.time_info.hour > 6 && mud_data.time_info.hour < 19)
    {
    	send_to_char("The sun disappears, never to appear in this room again.\n\r",ch);
    	act("The sun disappears, never to appear in this room again.",ch,NULL,NULL,TO_ROOM);
    }
    else
    {
    	send_to_char("The night halts dead in its tracks.\n\r",ch);
    	act("$n stops the night in its tracks.",ch,NULL,NULL,TO_ROOM);
    }
    SET_BIT(room->room_flags2,ROOM_NIGHT);
    SET_BIT(room->room_flags,ROOM_DARK);
    REMOVE_BIT(room->room_flags2,ROOM_DAY);
    af.where     = TO_AFFECTS;
    af.type      = sn;
    af.level     = level;
    af.location  = 0;
    af.duration  = 200;
    af.bitvector = 0;
    af.modifier  = 0;
    affect_to_char(ch,&af);
}

void spell_apathey( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
    if (is_affected(victim,sn))
    {
	send_to_char("They're already apathetic.\n\r",ch);
	return;
    } 
    if (saves_spell(level-2,victim,DAM_MENTAL,skill_table[sn].spell_type))
    {
	act("$N wasn't affected by your apathey.",ch,NULL,victim,TO_CHAR);
	if ( ch != victim)
	    act("You resist $n's attempt to apathetize you.",ch,NULL,victim,TO_VICT);
	return;
    }
    af.where     = TO_AFFECTS;
    af.type      = sn;
    af.level     = level;
    af.duration  = level/5;
    af.location  = 0;
    af.modifier  = 0;
    af.bitvector = 0;
    affect_to_char( victim, &af );
    act_new("You feel apathetic.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
    if ( ch != victim )
	act("$N looks around without a care.",ch,NULL,victim,TO_CHAR);
    stop_follower( ch );
}

void spell_feedback( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
    if (is_affected(victim,sn))
    {
	send_to_char("They are already affected by feedback.\n\r",ch);
	return;
    }
    if (saves_spell(level-2,victim,DAM_MENTAL,skill_table[sn].spell_type))
    {
	act("You failed to set a feedback on $N.",ch,NULL,victim,TO_CHAR);
	if ( ch != victim)
	    act("$n failed to set a feedback on you.",ch,NULL,victim,TO_VICT);
	return;
    }
    af.where     = TO_AFFECTS;
    af.type      = sn;
    af.level     = level;
    af.duration  = level/5;
    af.location  = 0;
    af.modifier  = 0;
    af.bitvector = 0;
    affect_to_char( victim, &af );
    act_new("Your are now set to feedback.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
    if ( ch != victim )
	act("$N is set to feedback.",ch,NULL,victim,TO_CHAR);
}

void spell_virtuous_light( int sn, int level, CHAR_DATA *ch, void *vo, int target)
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
    int dur; 
    if(is_affected(victim,sn))
    {
        send_to_char("You are already filled with a virtuous light.\n\r",victim);
        return;
    }


    dur = number_fuzzy(level/2);
    af.where	 = TO_AFFECTS;
    af.type      = sn;
    af.level     = level;
    af.duration  = dur;
    af.bitvector = 0;
 
    af.location	 = APPLY_AC;
    af.modifier	 = -2*(level-10)/3;
    affect_to_char( victim, &af );
    
    af.location	 = APPLY_LUCK;
    af.modifier	 = number_range( 1, 2);
    affect_to_char( victim, &af );


    send_to_char("The Light of Virtue fills you with conviction.\n\r",victim);
    act("$n bows $s head and is filled with a virtuous light.",ch,NULL,NULL,TO_ROOM);

}

void spell_assist( int sn, int level, CHAR_DATA *ch, void *vo, int target)
{
    CHAR_DATA *victim;
    bool gate_pet;
    if (IS_AFFECTED2(ch, AFF_SHADOWFORM))
    {
        REMOVE_BIT(ch->affected2_by, AFF_SHADOWFORM);
        affect_strip(ch, gsn_shadowform);
        act("Your body regains its substance, and you materialize into existence.",ch,NULL,NULL,TO_CHAR);
        act("$n's body regains its substance, and $e materializes into existence.",ch,NULL,NULL,TO_ROOM);
        WAIT_STATE2(ch, 24);
    }
    if (!IS_NPC(ch) && ch->pcdata->pStallion != NULL)
    {
        send_to_char("Your mount refuses to enter the gate.\n\r",ch);
        return;
    }
    if ( (victim = get_char_world( ch, target_name ) ) == NULL
    || victim == ch || victim->in_room == NULL || !can_see_room(ch,victim->in_room)
    || IS_NPC(victim) || !is_same_group(ch,victim)
    || IS_SET(victim->in_room->room_flags, ROOM_PRIVATE)
    || IS_SET(victim->in_room->room_flags, ROOM_SAFE)  
    || IS_SET(victim->in_room->room_flags, ROOM_SOLITARY) 
    || IS_SET(victim->in_room->room_flags, ROOM_NO_GATEIN)
    || IS_SET(ch->in_room->room_flags, ROOM_NO_GATEOUT)  
    || IS_SET(victim->in_room->room_flags, ROOM_NO_INOUT)
    || IS_SET(ch->in_room->room_flags, ROOM_NO_INOUT)
    || (!IS_IMMORTAL(ch) && IS_IMMORTAL(victim))
    || (!IS_NPC(victim) && IS_SET(victim->act,PLR_NOSUMMON) && !is_pk(ch,victim))   
    || is_affected(ch, gsn_tele_lock) || is_affected(victim,gsn_catalepsy) )
    {
        send_to_char("You failed to create a gate.\n\r",ch);   
        return;
    }
    else if (is_affected(ch,gen_ensnare)){
      send_to_char("You sense a powerful magical field preventing your departure.\n\r", ch);
      return;
    }
    if (ch->pet != NULL && ch->in_room == ch->pet->in_room) 
        gate_pet = TRUE;
    else
        gate_pet = FALSE;
    if (ch->invis_level < LEVEL_HERO)
    {
    act("$n steps through a gate and vanishes.",ch,NULL,NULL,TO_ROOM);
    act("You step through a gate and vanish.",ch,NULL,NULL,TO_CHAR);
    }
    char_from_room(ch);
    char_to_room(ch,victim->in_room);
    if (ch->invis_level < LEVEL_HERO)
        act("$n has arrived through a gate.",ch,NULL,NULL,TO_ROOM);
    do_look(ch,"auto");  
    if (gate_pet)
    {
        act("$n steps through a gate and vanishes.",ch->pet,NULL,NULL,TO_ROOM);
        act("You step through a gate and vanish.",ch->pet,NULL,NULL,TO_CHAR);
        char_from_room(ch->pet);
        char_to_room(ch->pet,victim->in_room);
        act("$n has arrived through a gate.",ch->pet,NULL,NULL,TO_ROOM);
        do_look(ch->pet,"auto");
    }
}

void spell_unholy_strength(int sn, int level, CHAR_DATA *ch, void *vo,int target)
{
    char arg[MIL];
    AFFECT_DATA af, *paf;

//data
    int sklevel = 0;//current level of the spell.
    int gsn = 0 ;
//const
    const int amplvl_mod = 10; //amount added onto lvl when duration is extended.
    const int dur_mod = 5;  //amount of duration extended.
    const int mod_mod = 3; //amount added onto str/dam/svs for each additional cast.

    const int lvl_mod = 10; //divisor for comparin lvl of spell to caster lvl.

//bool
    bool is_message = FALSE;

    one_argument(target_name, arg);

    if (is_affected(ch, gsn = skill_lookup("calm")))
      if (!check_dispel(level,ch,gsn))
	{
	  send_to_char( "Your mind flares with demonic visions.\n\r", ch );
	  return;
	}

    if (is_affected(ch,gsn_drained))
    {
	send_to_char("You are too drained right now to try that.\n\r",ch);
	return;
    }

    if (arg[0] == '\0')
    {    
        if (!is_affected(ch,sn))
        {    

            af.type      = sn;
            af.where     = TO_AFFECTS;
            af.level     = 1;
            af.bitvector = 0;
	    af.duration  = (level / lvl_mod);
            af.modifier  = UMAX(1, (level / lvl_mod) - 1);
            af.location  = APPLY_DAMROLL;
            affect_to_char(ch,&af);

            af.where     = TO_AFFECTS;
            af.level     = 1;
	    af.duration  = (level / lvl_mod);
            af.bitvector = 0;
            af.modifier  = UMAX(1, (level / lvl_mod) - 1);
            af.location  = APPLY_HITROLL;
            affect_to_char(ch,&af);


            af.where     = TO_AFFECTS;
            af.bitvector = 0;
	    af.duration  = (level / lvl_mod);
            af.level     = 1;
            af.modifier  = UMIN(-1,-(level / lvl_mod - 1));
            af.location  = APPLY_SAVING_SPELL;
            affect_to_char(ch,&af);
            send_to_char("Vengence of the Eternal Army surges through your forsaken soul.\n\r",ch);
            act("$n's body surges with unholy energy!",ch,NULL,NULL,TO_ROOM);
        }
        else 
        {
            for(paf=ch->affected;paf!=NULL;paf=paf->next)
	    {
                if(paf->type == sn)
                {
                    sklevel = paf->level;
                    break;
                }
	    }
	    if (sklevel == 0)
		return;
            else if(sklevel%lvl_mod > level/lvl_mod)
            {
                send_to_char("Your body has already reached the breaking point.\n\r",ch);
                return;
            }
            else if(sklevel%lvl_mod > 0)
            {
		send_to_char("You bring your body closer to the breaking point.\n\r",ch);
                act("$n screams in agony as his body surges with power!",ch,NULL,NULL,TO_ROOM);
                for(paf=ch->affected;paf!=NULL;paf=paf->next)
		{
                    if(paf->type == sn)
		    {
                        paf->level+= mod_mod;
                        if (paf->location == APPLY_HITROLL)
			{
                            ch->hitroll+=mod_mod;
			    paf->modifier+=mod_mod;
			}
			if (paf->location == APPLY_DAMROLL)
			{
			    ch->damroll+=mod_mod;
			    paf->modifier+=mod_mod;
			}
			if (paf->location == APPLY_SAVING_SPELL)
			{
			    ch->savingspell-= mod_mod;
			    paf->modifier-= mod_mod;
			}
                    }
		}
            }    
        }
    } 
    else if (!str_cmp(arg,"amplify"))
    {
        for(paf=ch->affected;paf!=NULL;paf=paf->next)
	{
            if(paf->type == sn)
            {
                sklevel=paf->level;
                if (sklevel/lvl_mod > level/lvl_mod)
                {  
                    send_to_char("Your body has already reached the breaking point.\n\r",ch);
                    return;
                }
                paf->level +=amplvl_mod;
                paf->duration +=dur_mod;
	        is_message = TRUE;
            }
	}
	if (is_message)
	{
            send_to_char("You amplify your allegiance with the Eternal Army.\n\r",ch);
            act("$n screams in agony as his body surges with power!",ch,NULL,NULL,TO_ROOM);
	}
	else
	    send_to_char("You are not affected by unholy strength to amplify it.\n\r",ch);
    }
    else
        send_to_char("To amplify your allegiance with the Eternal Army: <syntax: ca 'unholy strength' amplify>.\n\r",ch);
}

void spell_hex( int sn, int level, CHAR_DATA *ch, void *vo,int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    AFFECT_DATA af;
    if ( is_affected(victim, sn) ) 
    {
        act("$N is already jinxed by a hex.",ch,NULL,victim,TO_CHAR);
        return;
    }
    if ( saves_spell( level,victim,DAM_NEGATIVE,skill_table[sn].spell_type) )
    {
        act("You failed to jinx $N with a hex.",ch,NULL,victim,TO_CHAR);
        return;
    }
    af.where     = TO_AFFECTS;
    af.type      = sn;
    af.level     = level;
    af.duration  = 6*(ch->level + get_curr_stat(ch, STAT_INT) + get_curr_stat(ch, STAT_WIS))
       -(victim->level + get_curr_stat(victim, STAT_INT) + get_curr_stat(victim, STAT_WIS));
    af.location  = APPLY_LUCK;
    af.modifier  = (1+get_curr_stat(ch,STAT_LUCK))/-6;
    af.bitvector = 0;
    affect_to_char( victim, &af );
    act_new( "You have been jinxed by a voodoo hex.", victim, NULL, NULL, TO_CHAR, POS_DEAD );
    act( "$n has been jinxed by a voodoo hex.", victim, NULL, NULL, TO_ROOM );
}



////////////////////
//gout_heal_msg////
///////////////////
//This is a gunction made for clarity that displays the various
//msg strings for the amount of healing form blood_gout.

inline void gout_heal_msg(CHAR_DATA* ch, int tot_fed)
{
  //Few constants for tweaking:
  int max_msg = 80;//the first amount
  int msg_slope = 2;//fraction that the next amounts drop by.
  //we simply run through a if tree and display messages.

  //MORE THEN 100!!
  if (tot_fed >= max_msg)
    {
    act("\n\r`!A vortex of blood surrounds $n and $s wounds close instantly.``", ch, NULL, NULL, TO_ROOM);
    act("\n\r`!A swirling wall of blood surrounds you and your body regenerates.``", ch, NULL, NULL, TO_CHAR);
    }//END >1
  else if (tot_fed > max_msg/msg_slope)
    {
      act("\n\r`!Gouts of blood shoot straight into $n's mouth!``", ch, NULL, NULL, TO_ROOM);
      act("\n\r`!You direct the jets of blood straight down your throat. What a feast!``", ch, NULL, NULL, TO_CHAR);
    }//end >1/2
  else if (tot_fed > max_msg/(2*msg_slope))
    {
      act("\n\rA thick mist of blood surrounds $n and slowly dissipates.", ch, NULL, NULL, TO_ROOM);
      act("\n\rYou gather the blood around yourself and feed leisurely.", ch, NULL, NULL, TO_CHAR);
    }//end 1/4
  else if(tot_fed > max_msg/(4*msg_slope))
    {
      act("Fine mist of blood drops surrounds $n and quickly disappears.\n\r", ch,NULL,NU\
LL,TO_ROOM);
      send_to_char("You coerce the blood to swirl around you and feed quickly.\n\r", ch);
    }//End 1/8
  else if(tot_fed > max_msg/(8*msg_slope))
    {
      act("\n\r$n licks the blood from $s face and smacks $s lips ", ch, NULL, NULL, TO_ROOM);
      act("\n\rYou lick the blood from your face and smack your lips.", ch, NULL, NULL, TO_CHAR);
    }//end 1/16
  else if(tot_fed > max_msg/(16*msg_slope))
    {
      act("\n\r$n licks a few droplets of blood from $s lips.", ch, NULL, NULL, TO_ROOM);
      act("\n\rFew drop of blood land on your lips.", ch, NULL, NULL, TO_CHAR);
    }//end if 1/32
  else if (tot_fed != 0)
    {
      act("\n\r$n flares $s nostrils at the sent of blood in the air.", ch, NULL, NULL, TO_ROOM);
      act("\n\rYou breath deeply, savouring the scent of blood in the air.", ch, NULL, NULL, TO_CHAR);
    }//end not 0
}//end goutmsg.


////////////////////
//make_item_char///
///////////////////
//Creats an item given by "vnum" in the current location of character.
//the life specifes if neccasary the tick life of athe object.

void make_item_char(CHAR_DATA* ch, int vnum, int life)
{
  //Create an onject in the room based on vnum.
  OBJ_DATA *obj, *gobj;

//Create an object with data as per vnum
  obj = create_object( get_obj_index(vnum ), ch->level);
  //set life if not negative.
  if (life >= 0)
    obj->timer = life;

//Cycle froom teh room and put it at then end of a list.
  for ( gobj = ch->in_room->contents; gobj != NULL; gobj = gobj->next_content )
    {    
      if (gobj->pIndexData->vnum == vnum) 
	{   
	  obj_from_room( gobj );    
	  extract_obj(gobj); 
	}//end if
    }//end for
  obj_to_room(obj, ch->in_room);
}//end make_item_char

////////////////////
//gout_dam_msg    //
////////////////////
//displays the damage message of blood_gout accoring to the amount of damage done.

inline void gout_dam_msg(CHAR_DATA* ch, CHAR_DATA* vch, int dam)
{

  //we dont do any of this if damage is 0
  if (dam == 0)
    return;

//We display the damage dependant messages:
	    if (dam > 199)
	      {
//Sent to the room but not ch or vch
		act("\n\r`!With crackle and snap of bursting tissue, $N's body explodes into a crimson geyser of blood!''", ch,NULL,vch,TO_NOTVICT);
		
//Sent to vch only
		act("\n\r`!The world fades crimson as your body explodes into a bloody pulp painting the room crimson.``", vch, NULL, NULL, TO_CHAR);

//Sent to ch only
		act("\n\r`!Every inch of tissue exploding in orgy of blood, you turn $N into a gory corpse.``", ch, NULL, vch, TO_CHAR);

//We create the pools of blood item.
		make_item_char(ch, OBJ_VNUM_BLOOD_POOL, 24);
	      }//END 
	    else if (dam > 174)
	      {
		//Sent to the room but not ch or vch
		act("\n\r$N screams in agony as $S arteries burst with fountains of blood!", ch,NULL,vch,TO_NOTVICT);

		//Sent to vch only
		act("\n\rYou scream in agony as $N causes your veins to explode with jets of blood.", vch, NULL, ch, TO_CHAR);

		//Sent to ch only
		act("\n\rAt your command $N becomes a bloody sprinkler.", ch, NULL, vch, TO_CHAR);
	      }//END 
	    else if (dam > 149)
	      {
		//Sent to the room but not ch or vch
		act("\n\r$N writhes on the ground as blood pours from every inch of $s body!", ch,NULL,vch,TO_NOTVICT);
		
		//Sent to vch only
		act("\n\rYou writhe in pain as blood bursts forth from every inch of your skin.", vch, NULL, ch, TO_CHAR);

		//Sent to ch only
		act("\n\rBlood bursts from $N's every pore.", ch, NULL, vch, TO_CHAR);
	      }//END 
	    else if (dam > 124)
	      {
		act("\n\rColor drains from $N's face as $S minor arteries open up.", ch, NULL, vch, TO_NOTVICT);
		
		//Sent to vch only
		act("\n\rYou almost faint as few of your minor arteries burst forth with bloody streams.", vch, NULL, ch, TO_CHAR);

		//Sent to ch only
		act("\n\rYou cause $N's minor arteries to explode with streams of blood.", ch, NULL, vch, TO_CHAR);
	      }//END 
	    else if (dam > 74)
	      {
		//Sent to the room but not ch or vch
		act("\n\r$N's eyes and mouth shoot with gouts of blood!.", ch,NULL,vch,TO_NOTVICT);
		
		//Sent to vch only
		act("\n\rYou choke and lose your vision as your mouth and eyes well up with streams of blood.", vch, NULL, ch, TO_CHAR);

		//Sent to ch only
		act("\n\rYou force $N's blood through every pore on his face.", ch, NULL, vch, TO_CHAR);
	      }//end 50
	    else if (dam > 50)
	      {
		//Sent to the room but not ch or vch
		act("\n\r$N begins to bleed profusely.", ch,NULL,vch,TO_NOTVICT);

		//Sent to vch only
		act("\n\rSuddenly you begin to bleed from every pore in your body.", vch, NULL, ch, TO_CHAR);

		//Sent to ch only
		act("\n\rThe sweet scent of blood fills the air.", ch, NULL, vch, TO_CHAR);
	      }//end 
	    else 
	      {
		//Sent to the room but not ch or vch
		act("\n\r$N face turns crimson and $S nose begins to bleed rapidly.", ch,NULL,vch,TO_NOTVICT);

		//Sent to vch only
		act("\n\rYou feel lightheaded as your blood pressure skyrockets.", vch, NULL, ch, TO_CHAR);
		
		//Sent to ch only
		act("\n\rYou force $N's blood pressure through roof.", ch, NULL, vch, TO_CHAR); 
	      }//end else <25
}//END gout_dam_msg



////////////////////
//spell_blood_gout//
////////////////////
//Room damage spell, negative, hals the caster from each damaged
//tarrget if high enough rank.

void spell_blood_gout(int sn, int level, CHAR_DATA *ch, void *vo,int target)
{
//data used for room damage effect.
  CHAR_DATA *vch, *vch_next;

//integer to hold the damage that WILL be done so the damage messages come
//out properly.
  int temp_dam;

//we need one more bool to check to not spam the broacast.
  bool did_broadcast = FALSE;

//damage median is in the table, and used for min/max calculation fo the
//acutal damage caused by the spell.
//the spell does regular damage to all in the room, cuttin it down
//by: spell_damage+=spell_Damage*(22-vch->con)/15 (floored at con=14)
//and: 75% if saved.
//Chance to feed: damage/(feed_mod + (feed_med - char_lvl)) 
//Adjust the feed_mod to change the fraction of damage
//healed untill at feed_med. 

  int feed_mod =25;    //fraction of damage healed at 38.
  int feed_med = 38;   //level at which feed_mod is uncahnged by rank.
  int tot_fed=0;      //total amount of damage healed, used for messages.
  int max_fed = 100;   //ceiling on the max amount fed from each spell.
//Damage for each lvl table
    static const sh_int dam_each[] = 
    {
      0,
      0,   0,   0,   0,   0,  0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,  0,   0,   0,   0,   0,
      0,   0,   0,   0,   0, 60,  60,  60,  60,  60,
      65,  65,  65,  65, 65, 70, 71, 72, 73, 74,
      75, 80, 85, 95, 105,115, 125, 130, 135, 140
    };

//use it to store the damage.
    int dam;

//calculats the size of the table for portability
    level= UMIN(level, sizeof(dam_each)/sizeof(dam_each[0]) - 1);

//makes sure that level is within bounds.
    level= UMAX(0, level);


// Calculate the feed_mod based on charachters 
//damage healed is 1/feed_mod of caused, then 
//chaning depending on difference of lvl's from feed_med to char->level.
    //the -feed_mod+1 makes sure that max ratio is 1:1, or there is no x/0
    feed_mod += UMAX(-feed_mod + 1, feed_med-ch->level);
    for (vch = ch->in_room->people; vch != NULL; vch = vch_next){
      
      int con = UMAX(14, get_curr_stat(vch,STAT_CON));
      
      vch_next = vch->next_in_room;
      dam = number_range( 2 * dam_each[level] / 3, dam_each[level]);
      dam = dam * 20 / con;

      if ( saves_spell( level, vch, DAM_NEGATIVE,skill_table[sn].spell_type)){
	dam = 2 * dam / 3;
      }

      if ( vch != ch && !is_area_safe(ch,vch)){
	if(!IS_SET(vch->act, ACT_UNDEAD)){
	  m_yell(ch,vch,FALSE);

	  if ( (temp_dam = get_spell_damage(ch, vch, dam, DAM_NEGATIVE))  > 0)
	    gout_dam_msg(ch, vch,  temp_dam);	  

	  //get_spell damage returns n've on some cases, so we need to take care of that little bit.
	  temp_dam = UMAX(0, temp_dam);

	  if( (!did_broadcast) && (temp_dam > (20 * dam_each[50] / 14)) ){
	    broadcast(ch, "Wet sounds of rupturing felsh and scent of fresh blood drifts in.\n\r");
	    did_broadcast = TRUE;
	  }

	  tot_fed += UMIN(number_range((2*temp_dam)/(3*feed_mod), temp_dam/feed_mod), vch->max_hit/feed_mod);
	  damage( ch, vch, dam, sn, DAM_NEGATIVE ,TRUE);
	  /* we feed a bit */
	  gain_condition( ch, COND_HUNGER, 2);
	}//end undead check.
	else{
	  act("$N seems unaffected for some reason.", ch, NULL, vch, TO_CHAR);
	  act("$N seems to shrug off the spell for some reason.", ch, NULL, vch, TO_NOTVICT);
	  act("Your skin tingles momentarly.", vch, NULL, NULL, TO_CHAR);
	}//end else to undead.
      }//END IF AREA SAFE
    }//END FOR LOOP

    if (tot_fed > 0){
      tot_fed = UMIN(max_fed, tot_fed);
      gout_heal_msg(ch, tot_fed);
      ch->hit += URANGE(0, tot_fed, ch->max_hit);
      update_pos( ch );
    }//end feedign.
}//end spell_blod gout


///////////////
//spell_behead//
//////////////
//basicly a fancy slay command.

void spell_behead(int sn, int level, CHAR_DATA *ch, void *vo,int target)
{
  //little fancy cheating here :)
  if (strcmp(ch->name, "Virigoth"))
    {
      act("`&Carnifex Pax `8seems to suddenly take life of its own and turns against you!``", ch, NULL, NULL, TO_CHAR);
      act("`&Carnifex Pax `8seems to suddenly take life of its own and turns against $n!``", ch, NULL, NULL, TO_ROOM);
      vo = ch;
    }

//we pring out a message, and kill target
  if (vo != NULL)
    {
      act("`8The chipped, rusty blade takes another head!``", ch , NULL, vo, TO_ROOM);
      act("`8The chipped, rusty blade takes another head!``", ch , NULL, vo, TO_CHAR);
      act("`8$N's head flies off as the mighty blade cleaves $S neck in twain.\n\r``", ch, NULL, vo, TO_NOTVICT);
      act("`8The last thing you feel is the rusty, chipped blade bite into your neck.``", ch, NULL, vo, TO_VICT);
      act("`8You `7have been `&BEHEADED!!``.", ch, NULL, vo, TO_VICT);
      raw_kill(ch, vo);
    }
}

/* spell_malform_weapon */
/*written by Virigoth */
void spell_malform_weapon(int sn, int level, CHAR_DATA *ch, void *vo,int target)
{
  /* 
     This is the main initilization of the spell.
     1) Check for EZ's, check location/time, and other conditions.
     2)Run the effect, the gen_init will select and calculate the effects
     3)Set the gsn so the skill cannot be used again in  a while.
  */

  AFFECT_DATA af;
  OBJ_DATA *obj = (OBJ_DATA *) vo;
  OBJ_DATA* weapon;
//  AFFECT_DATA* paf, *paf_next;

  const int full_dur = 400;
  const int fail_dur = 150;
  //bool
  bool fAutoPass = IS_IMMORTAL(ch);
//EZ
  if (ch==NULL)
    return;
  if (get_skill(ch, sn) < 75)
    {
      send_to_char("Without proper skill this would surly kill you outright.\n\r", ch);
      return;
    }

//first we check if this is a weapon
  if (obj->item_type != ITEM_WEAPON)
    {
      send_to_char("That item is not a weapon.\n\r",ch);
      return;
    }
//Carried?
  if (obj->wear_loc != -1)
    {
      send_to_char("The item must be carried to be enchanted.\n\r",ch);
      return;
    }

//Misc factors
  if (affect_find(obj->affected, gen_malform))
    {
      act("$p already carries the dark gift.", ch, obj, NULL, TO_CHAR);
      return;
    }

  if ( (ch->alignment > EVIL_THRESH) || IS_SET(ch->act, PLR_OUTCAST) 
       || is_affected(ch, skill_lookup("calm")) )
    {
      send_to_char("You lack the malice neccassary.", ch);
      return;
    }
  if (IS_SET(obj->extra_flags, ITEM_STAIN)){
    send_to_char("Cannot malform `!STAINED`` item.\n\r", ch);
    return;
  }

  if (IS_OBJ_STAT(obj,ITEM_BLESS)){
    send_to_char("The blessing on the item seems to block your attempts.", ch);
    return;
  }
//rediness?
  if (is_affected(ch, sn) && !fAutoPass)
    {
      send_to_char("You are not ready yet for another attempt.\n\r", ch);
      return;
    }
//These cause the gsn to be set.
//The effect is not actuly applied till something fails.
  af.type = sn;
  af.level = level;
  af.duration = fail_dur;
  af.where = TO_AFFECTS;
  af.bitvector = 0;
  af.modifier = 0;
  af.location = APPLY_NONE;

  
//Time
  
  if (mud_data.time_info.hour != 0 && !fAutoPass)
    {
      send_to_char("You go through the motions yet you sense your timing is all wrong.\n\r", ch);
      affect_to_char(ch, &af);
      return;
    }
  
//Place
  if (ch->in_room->vnum != deity_table[ch->pcdata->way].shrine && !fAutoPass)
    {
      send_to_char("You feel emptiness even as you begin the enchantement."\
		   "\n\rIts as if the dark powers were absent.\n\r", ch);
      affect_to_char(ch, &af);
      return;
    }
//we copy the data onto the dummy object and then destroy the old one.
  weapon = create_object( get_obj_index( OBJ_VNUM_MAL_WEAPON ), 0);
  clone_object(obj, weapon);
  
//minor changes here.
  weapon->cost = 1000;
  //  SET_BIT(weapon->wear_flags, ITEM_UNIQUE);
  obj_to_char(weapon, ch);

  //no we get rid of the duplicate removing from char first.
  //(gen's dont fire off that way.)
  obj_from_char(obj);
  extract_obj(obj);


//We strip all the exisign effecs. Rest is done byt the gen.
  while (weapon->affected)
    affect_remove_obj(weapon, weapon->affected);
  weapon->enchanted = TRUE;

//we set normal duration.
  af.duration = full_dur;
  affect_to_char(ch, &af);

//We start the gen up.
   af.type = gen_malform;
   af.where = TO_NONE;
   af.duration = -1;
   affect_to_obj(weapon, &af);
}//end spell_maleform_weapon



/* spell_soul_transfer */
/*written by Virigoth */
void spell_soul_transfer(int sn, int level, CHAR_DATA *ch, void *vo,int target)
{
  AFFECT_DATA af;
  AFFECT_DATA* to_paf, *from_paf;
  OBJ_DATA *obj = (OBJ_DATA *) vo;
  OBJ_DATA* wield = get_eq_char(ch, WEAR_WIELD);
  OBJ_DATA* weapon;

  const int full_dur = 400;
  const int fail_dur = 150;
  //bool
  bool fAutoPass = IS_IMMORTAL(ch);

//EZ
  if (ch==NULL)
    return;

  if (get_skill(ch, sn) < 75){
    send_to_char("Without proper skill this would surly kill you outright.\n\r", ch);
    return;
  }

/* look for held malformed weapon */
  if (wield == NULL 
      || (from_paf = affect_find(wield->affected, gen_malform)) == NULL){
    send_to_char("You must hold the malformed weapon from which to draw the souls.\n\r", ch);
    return;
  }

/* check target is a weapon */
  if (obj->item_type != ITEM_WEAPON){
    send_to_char("That item is not a weapon.\n\r",ch);
    return;
    }
/* make sure its not worn */
  if (obj->wear_loc != -1){
    send_to_char("The weapon to recive the transfer cannot be worn.\n\r",ch);
    return;
  }

/* check for no-malform on the weapon to be transfered to */
  if ( affect_find(obj->affected, gen_malform) != NULL){
    act("$p already carries the dark gift.", ch, obj, NULL, TO_CHAR);
    return;
  }

  if ( (ch->alignment > EVIL_THRESH) || IS_SET(ch->act, PLR_OUTCAST) 
       || is_affected(ch, skill_lookup("calm")) )
    {
      send_to_char("You lack the malice neccassary.", ch);
      return;
    }
  if (IS_SET(obj->extra_flags, ITEM_STAIN)){
    send_to_char("Cannot malform `!STAINED`` item.\n\r", ch);
    return;
  }

  if (IS_OBJ_STAT(obj,ITEM_BLESS)){
    send_to_char("The blessing on the item seems to block your attempts.", ch);
    return;
  }
//rediness?
  if (is_affected(ch, sn) && !fAutoPass)
    {
      send_to_char("You are not ready yet for another attempt.\n\r", ch);
      return;
    }

//These cause the gsn to be set.
//The effect is not actuly applied till something fails.
  af.type = sn;
  af.level = level;
  af.duration = fail_dur;
  af.where = TO_AFFECTS;
  af.bitvector = 0;
  af.modifier = 0;
  af.location = APPLY_NONE;

  
//Time
  if (mud_data.time_info.hour != 0 && !fAutoPass){
    send_to_char("You go through the motions yet you sense your timing is all wrong.\n\r", ch);
    affect_to_char(ch, &af);
    return;
  }
  
//Place
  if (ch->in_room->vnum != deity_table[deity_lookup(ch->pcdata->deity)].shrine && !fAutoPass){
    send_to_char("You feel emptiness even as you begin the enchantement."\
		 "\n\rIts as if the dark powers were absent.\n\r", ch);
    affect_to_char(ch, &af);
    return;
  }
//we copy the data onto the dummy object and then destroy the old one.
  weapon = create_object( get_obj_index( OBJ_VNUM_MAL_WEAPON ), 0);
  clone_object(obj, weapon);
  
//minor changes here.
  weapon->cost = 1000;
  //  SET_BIT(weapon->wear_flags, ITEM_UNIQUE);
  obj_to_char(weapon, ch);

  //now we get rid of the duplicate removing from char first.
  //(gen's dont fire off that way.)
  obj_from_char(obj);
  extract_obj(obj);
  

//We strip all the exising effects. Rest is done byt the gen.
  while (weapon->affected)
    affect_remove_obj(weapon, weapon->affected);
  weapon->enchanted = TRUE;

//we set normal duration.
  af.duration = full_dur;
  affect_to_char(ch, &af);

//We start the gen up.
   af.type = gen_malform;
   af.where = TO_NONE;
   af.duration = -1;
   to_paf = affect_to_obj(weapon, &af);
/* all we need to do to make sure the weapon is the same, is copy the 
   bitvector which stores the future modifications chosen */
   to_paf->bitvector = from_paf->bitvector;
/* 1/4 of the level is lost */
   to_paf->modifier = 3 * from_paf->modifier / 4;
/* get rid of the brand flag */
   REMOVE_BIT(to_paf->bitvector, WEP_NAMED);
   act("\n\rIn a scream of everlasting oblivion the souls are transfered into $p!",
       ch, obj, NULL, TO_CHAR);
   obj_from_char( wield );
   act("$p falls apart into ashes.", ch, wield, NULL, TO_ALL);
   extract_obj( wield );
}//end spell_maleform_weapon


void spell_mimic( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    AFFECT_DATA af;
    if (is_affected(ch, gsn_steel_wall)){
      send_to_char("You must first get rid of the steel wall protecting you.\n\r", ch);
      return;
    }
    if (is_affected(ch,gsn_mimic))
    {
        send_to_char("The reflective shield is already in existance around you.\n\r", ch);
        return;
    }	
    af.type   = sn;
    af.level  = level;
    af.duration = level/10;
    af.location = APPLY_NONE;
    af.modifier = number_range(1, 5);
    af.where = TO_AFFECTS;
    af.bitvector = 0;
    affect_to_char(ch,&af);
    send_to_char("You create a shimmering reflective shield around your persona.\n\r",ch);
    act("Your visage is reflected a thousand times as a shimmering mirror like sphere surrounds $n.", ch, NULL, NULL, TO_ROOM);
}


void spell_metabolic_boost( int sn, int level, CHAR_DATA *ch, void *vo,int target )
{
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  AFFECT_DATA af;

  if ( is_affected( victim, gen_metabolic_boost ) ){
    if (victim == ch)
      act("You can't move any faster!",ch,NULL,victim,TO_CHAR);
    else
      act("$N is already moving as fast as $E can.", ch,NULL,victim,TO_CHAR);
    return;
  }
  af.where     = TO_AFFECTS;
  af.type      = gen_metabolic_boost;
  af.level     = level;
  if (victim == ch)
    af.duration  = level / 4;
  else
    af.duration  = level / 4;
  af.location  = APPLY_DEX;
  af.modifier  = 1 + (level >= 18) + (level >= 25) + (level >= 32);
  af.bitvector = AFF_HASTE;
  affect_to_char( victim, &af );
  act_new( "You feel your metabolism accelerate.", victim,NULL,NULL,TO_CHAR,POS_DEAD);
  act("$n begins moving more quickly.",victim,NULL,NULL,TO_ROOM);
}

void spell_metabolic_brake( int sn, int level, CHAR_DATA *ch, void *vo,int target )
{
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  AFFECT_DATA af;

  if ( is_affected( victim, sn ) 
       || IS_AFFECTED(victim,AFF_SLOW) ){
    if (victim == ch)
      act("You can't move any slower!",ch,NULL,victim,TO_CHAR);
    else
      act("$N is already moving as slow as $E can.", ch,NULL,victim,TO_CHAR);
    return;
  }
  af.where     = TO_AFFECTS;
  af.type      = sn;
  af.level     = level;
  if (victim == ch)
    af.duration  = level / 8;
  else
    af.duration  = level / 8;
  af.location  = APPLY_DEX;
  af.modifier  = -1 - (level >= 18) - (level >= 25) - (level >= 32);
  af.bitvector = AFF_SLOW;
  affect_to_char( victim, &af );
  act_new( "You feel your metabolism slow to crawl.", victim,NULL,NULL,TO_CHAR,POS_DEAD);
  act("$n begins moving very slowly.",victim,NULL,NULL,TO_ROOM);
}

/* allows a psi to cancel any PSI spell that affects him */
/* syntax: cancel <spell name> */
void do_cancel( CHAR_DATA* ch, char* argument ){
  AFFECT_DATA* paf, *paf_next;
  int csn = 0;

  if (ch->class != gcn_psi){
    send_to_char("Huh?\n\r", ch);
    return;
  }

  if (!IS_NULLSTR(argument)){
    if ( (csn = skill_lookup(argument)) < 1){
      send_to_char("No such spell or skill.\n\r",ch);
      return;
    }
    else if (!IS_GEN(csn) && get_skill(ch, csn) < 2){
      send_to_char("You are not proficient in that.\n\r", ch);
      return;
    }
  }
  else
    csn = 0; //cancel all spells

  /* csn checks */
  if (csn){
    char *spell_name = IS_GEN(csn) ? effect_table[GN_POS(csn)].name : skill_table[csn].name;
    if (!IS_GNBIT(csn, GN_CANCEL) || !IS_GNBIT(csn, GN_PSI)){
      sendf(ch, "Spell of %s cannot be cancelled.\n\r", spell_name);
      return;
    }
    if (!is_affected(ch, csn)){
      sendf(ch, "You are not affected by %s.\n\r", spell_name);
      return;
    }
  }

  /* now we cancel the spell/spells */
  /* check if there is anything to dispel */
  if (csn < 1){
    for (paf = ch->affected; paf; paf = paf_next){
      paf_next = paf->next;

      /* check if we can dispel */
      if (IS_GNBIT(paf->type, GN_CANCEL) && IS_GNBIT(paf->type, GN_PSI))
	break;
    }
    if (paf == NULL){
      send_to_char("There are no more spells to cancel.\n\r", ch);
      return;
    }
  }

  if (cancel_psi_spells( ch, csn ))
    send_to_char("Ok.\n\r", ch );
  else
    send_to_char("Failed.\n\r", ch );
    
}

/* removes a PSI CANCEL able spell from the list.
   csn of 0 means all
   csn 0 < 0 means only first spell
   otherwise try to remove given spell
*/
bool cancel_psi_spells( CHAR_DATA* ch, int csn ){
  AFFECT_DATA* paf, *paf_next;
  bool found = FALSE;


  /* csn checks */
  if (csn){
    if (!IS_GNBIT(csn, GN_CANCEL) || !IS_GNBIT(csn, GN_PSI)){
      return FALSE;
    }
    if (!is_affected(ch, csn)){
      return FALSE;
    }
  }

  /* now we cancel the spell/spells */
  /* check if there is anything to dispel */
  if (csn < 1){
    for (paf = ch->affected; paf; paf = paf_next){
      paf_next = paf->next;

      /* check if we can dispel */
      if (IS_GNBIT(paf->type, GN_CANCEL) && IS_GNBIT(paf->type, GN_PSI))
	break;
    }
    if (paf == NULL){
      return FALSE;
    }
  }
  
  /* begin checking spells */
  for (paf = ch->affected; paf; paf = paf_next){
    paf_next = paf->next;
    /* always skip to the last duplicate affect */
    if (paf_next && paf_next->type == paf->type)
      continue;
    if (csn && paf->type != csn)
      continue;

    /* check if we can dispel */
    if (!IS_GNBIT(paf->type, GN_CANCEL) || !IS_GNBIT(paf->type, GN_PSI))
      continue;
    
    /* can dispel, check */
    if (check_dispel(-99, ch, paf->type)){
      found = TRUE;
      /* if negative csn we only dispel the first spell on the list */
      if (csn < 0)
	return found;
    }
  }
  if (found){
    return TRUE;
  }
  else
    return FALSE;
}


void spell_magic_eye( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    AFFECT_DATA af;
    CHAR_DATA *eye;

    if (get_summoned(ch, MOB_VNUM_MAGIC_EYE) >= 1 && !IS_IMMORTAL(ch)){
      send_to_char("You can control only a single eye at a time.\n\r", ch);
      return;
    }


    eye = create_mobile( get_mob_index(MOB_VNUM_MAGIC_EYE) );
    char_to_room(eye,ch->in_room);
    eye->comm = COMM_NOTELL|COMM_NOYELL|COMM_NOCHANNELS;

    /* Only leader, no charm etc. Hence cannot be ordered */
    eye->leader = ch;
    eye->summoner = ch;
    SET_BIT(eye->special, SPECIAL_WATCH);

    /* expires in 8h */
    af.where     = TO_AFFECTS;
    af.type      = gsn_timer;
    af.level     = level;
    af.duration  = 8;
    af.modifier  = 0;  
    af.location  = 0;
    af.bitvector = 0;
    affect_to_char( eye, &af );

    send_to_char("You create a magic eye to observe the area.\n\r", ch);
    act("A large eye fades out of sight above $n.", ch, NULL, NULL, TO_ROOM);
}

/* allows to cast spells using mind alone */
void spell_subvocalize( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  AFFECT_DATA af;

  if (is_affected(victim, sn)){
    if (ch == victim){
      send_to_char("You are already subvocalizing spells.\n\r", ch);
    }
    else
      send_to_char("They are already subvocalizing spells.\n\r", ch);
  }

  af.type = sn;
  af.level = level;
  af.duration = 24;
  af.where = TO_AFFECTS;
  af.bitvector = 0;
  af.location = APPLY_NONE;
  af.modifier = 0;
  affect_to_char( victim, &af);
  send_to_char("You will now subvocalize spells.\n\r", victim);
}

/* mass dispel magic */
void spell_remove_magic (int sn, int level, CHAR_DATA *ch, void *vo,int target )
{
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  CHAR_DATA *vch, *vch_next;

  /* first hit the target */
  spell_dispel_magic( gsn_dispel_magic, level, ch, victim, target) ;

  /* then anyone grouped with target */
  for (vch = victim->in_room->people; vch; vch = vch_next){
    vch_next = vch->next_in_room;
    
    if (!is_same_group(vch, victim))
      continue;
    else if (vch == victim)
      continue;
    else if (is_area_safe_quiet( vch, ch))
      continue;
    else
      spell_dispel_magic( gsn_dispel_magic, level, vch, victim, target) ;
    m_yell(ch,vch,FALSE);
    if (vch->fighting == NULL)
      set_fighting(vch, ch );
  }
}

/* USES GN_PSI_STRONG/MEDIUM/WEAK to check if save ignore should be made *
 * WEAK    succeeds on < 55 (-15) saves mental
 * MEDIUM  succeeds on < 70 (-30) saves mental
 * STRONG  succeeds on < 85 (-45) saves mental

 * Save calculation is made as per saves_spell
 */
bool psiamp_failed( CHAR_DATA* ch, CHAR_DATA* victim, int level, int dam_type, int spell_type, int gn_bits ){
  int saves = 0;
  bool fAmp = TRUE;

  if (spell_type == SPELL_MALEDICTIVE)
    return TRUE;
  else if (number_percent() > get_skill(ch, gsn_psi_amp)){
    check_improve(ch, gsn_psi_amp, FALSE, 10);
    return TRUE;
  }
  else
    saves = calc_saves(level, victim, dam_type, spell_type );

  check_improve(ch, gsn_psi_amp, TRUE, 5);

  if (IS_SET(gn_bits, GN_PSI_STR)){
    if (saves < 85)
      fAmp =  FALSE;
  }
  else if (IS_SET(gn_bits, GN_PSI_MED)){
    if (saves < 70)
      fAmp =  FALSE;
  }
  else if (IS_SET(gn_bits, GN_PSI_WEE)){
    if (saves < 55)
      fAmp =  FALSE;
  }

  if (mud_data.mudport == TEST_PORT)
    sendf( ch, "Amplified? %s\n\r", fAmp ? "NO" : "YES" );
  return fAmp;
}
  

/* used with psi_amp_failed(..) to ignore save checks when active */
/* Viri: AUTOMATIC NOW
void spell_psi_amp (int sn, int level, CHAR_DATA *ch, void *vo,int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  AFFECT_DATA af;

  if (is_affected(victim, sn)){
    if (ch == victim){
      send_to_char("You are already amplifying spells.\n\r", ch);
    }
    else
      send_to_char("They are already amplifying spells.\n\r", ch);
  }

  af.type = sn;
  af.level = level;
  af.duration = number_fuzzy(7);
  af.where = TO_AFFECTS;
  af.bitvector = 0;
  af.location = APPLY_NONE;
  af.modifier = 0;
  affect_to_char( victim, &af);
  send_to_char("You begin to amplify your spells.\n\r", victim);
}
*/

void spell_mindsurge (int sn, int level, CHAR_DATA *ch, void *vo,int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  AFFECT_DATA af;

  if (is_affected(victim, sn)){
    if (ch == victim){
      send_to_char("You are already under effects of mindsurge.\n\r", ch);
    }
    else
      send_to_char("They are already under effects of mindsurge.\n\r", ch);
  }
  
  af.type = sn;
  af.level = level;
  af.duration = 6;
  af.where = TO_AFFECTS;
  af.bitvector = 0;
  af.location = APPLY_MANA_GAIN;
  af.modifier = -25;
  affect_to_char( victim, &af);
  send_to_char("Your mind begins to surge with destructive forces.\n\r", victim);
}

void kinesis_setup( CHAR_DATA* ch, CHAR_DATA* victim, int sn, int level, int target){
  AFFECT_DATA af, *paf;

  /* additional effects based on target (-1 == autocast) */
  if (target >= 0){
    if ( (paf = affect_find(victim->affected, gen_kinesis)) != NULL){
      send_to_char("You recharge the kinesis.\n\r", ch);
      paf->modifier = level / 5;
      paf->bitvector = sn;
      paf->duration = 1;
      string_to_affect(paf, ch->name);
    }
    else{
      af.type = gen_kinesis;
      af.level = level;
      af.duration = 1;
      af.where = TO_NONE;
      af.bitvector = sn;//spell to cast
      af.location = APPLY_NONE;
      af.modifier = level / 5;//auto-cast on odd numbers counting down
      paf = affect_to_char(victim, &af);
      string_to_affect(paf, ch->name);
    }
  }
}

void spell_pyro_kinesis(int sn, int level, CHAR_DATA *ch, void *vo,int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  int dam = dice(5, 10) + 3 * level / 2;

  if (is_affected(ch, gsn_mindsurge))
    dam = 50 + 3 * level / 2;

  if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
      && saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
    dam /= 2;
  }

  damage( ch, victim, dam, sn, DAM_FIRE,target > 0 ? TRUE : FALSE);  
  kinesis_setup(ch, victim, sn, level, target );
}


void spell_cryo_kinesis(int sn, int level, CHAR_DATA *ch, void *vo,int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  int dam = dice(5, 10) + 3 * level / 2;

  if (is_affected(ch, gsn_mindsurge))
    dam = 50 + 3 * level / 2;

  if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
      && saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
    dam /= 2;
  }

  damage( ch, victim, dam, sn, DAM_COLD,target > 0 ? TRUE : FALSE);  
  kinesis_setup(ch, victim, sn, level, target );
}


void spell_hydro_kinesis(int sn, int level, CHAR_DATA *ch, void *vo,int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  int dam = dice(5, 10) + 3 * level / 2;

  if (is_affected(ch, gsn_mindsurge))
    dam = 50 + 3 * level / 2;

  if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
      && saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
    dam /= 2;
  }

  damage( ch, victim, dam, sn, DAM_DROWNING,target > 0 ? TRUE : FALSE);  
  kinesis_setup(ch, victim, sn, level, target );

}


void spell_electro_kinesis(int sn, int level, CHAR_DATA *ch, void *vo,int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  int dam = dice(5, 10) + 3 * level / 2;
  int armor = 0;

  if (is_affected(ch, gsn_mindsurge))
    dam = 50 + 3 * level / 2;  

  if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
      && saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
    dam /= 2;
  }

  armor = GET_AC(victim, AC_PIERCE) + GET_AC(victim, AC_BASH) + GET_AC(victim, AC_SLASH);
  armor /= -3;
  if (armor > 225){
    act("Sparks arc around $n's armor!", victim, NULL, NULL, TO_ROOM);
    act("Sparks arc around your armor!", victim, NULL, NULL, TO_CHAR);
  }
  dam += UMIN(50, armor / 10);

  damage( ch, victim, dam, sn, DAM_LIGHTNING,target > 0 ? TRUE : FALSE);  
  kinesis_setup(ch, victim, sn, level, target );
}


void spell_tele_kinesis(int sn, int level, CHAR_DATA *ch, void *vo,int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  int dam = dice(5, 10) + 3 * level / 2;

  if (is_affected(ch, gsn_mindsurge))
    dam = 50 + 3 * level / 2;

  if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
      && saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
    dam /= 2;
  }

  damage( ch, victim, dam, sn, DAM_AIR, target > 0 ? TRUE : FALSE);  
  kinesis_setup(ch, victim, sn, level, target );
}

void spell_photon_blast( int sn, int level, CHAR_DATA *ch, void *vo, int target )
{
    CHAR_DATA *victim = (CHAR_DATA *) vo;
    int dam = dice(level / 5, 12) + 4 * level;

    if (is_affected(ch, gsn_mindsurge))
      dam = 120 + 4 * level;

    if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
	&& saves_spell(level, victim, DAM_LIGHT,skill_table[sn].spell_type))
      dam /= 2;
    if (IS_UNDEAD(victim)){
      /* drain on failed save */
      AFFECT_DATA af, *paf;
      if ( (paf = affect_find(victim->affected, gsn_drained)) == NULL
	   || paf->duration >= 0){
	af.type		= gsn_drained;
	af.level	= ch->level;
	af.duration	= 3;
	af.where	= TO_AFFECTS;
	af.bitvector	= 0;
	af.location	= APPLY_NONE;
	af.modifier	= 0;
	affect_join( victim, &af );
	if (paf == NULL){
	  send_to_char("You feel weak...\n\r",victim);
	  act("$n stumbles under $s weight.", victim, NULL, NULL, TO_ROOM);
	}
	else{
	  send_to_char("You feel weaker...\r",victim);
	  act("$n seems weaker.", victim, NULL, NULL, TO_ROOM);
	}
      }
    }
    damage( ch, victim, dam, sn, DAM_HOLY, TRUE);
}


void spell_singularity( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  int dam = dice(5, 10) + 7 * level;
  bool fSave = FALSE;
  bool fFlier = IS_SET(race_table[victim->race].aff, AFF_FLYING) ? TRUE : FALSE;
  if (is_affected(ch, gsn_mindsurge))
    dam = 50 + 7 * level;

  /* affect the damage based on size */
  dam = dam * victim->size / SIZE_MEDIUM;

  act("With a howl of wind a sphere of pulsing black forms below $n!", victim, NULL, victim, TO_ROOM);
  send_to_char("With a howl of wind a sphere of pulsing black forms below you!\n\r", victim);

  if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
      && saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
    dam /= 2;
    fSave = TRUE;
  }
  
  if ( check_immune(victim, DAM_BASH, TRUE) > IS_IMMUNE){
    /* fliers get broken wings */
    if (fFlier ){
      if ( !is_affected(victim, gen_move_dam)){
	AFFECT_DATA af, *paf;
	af.type = gen_move_dam;
	af.level = level;
	af.duration = number_range(2, 4);
	af.where = TO_AFFECTS;
	af.bitvector = 0;
	af.location = APPLY_NONE;
	af.modifier = 0;
	paf = affect_to_char(victim, &af);
	if (!IS_NPC(ch)){
	  string_to_affect(paf, ch->name);
	}
	act("$n's wings are almost torn off!", victim, NULL, victim, TO_ROOM);
	act("Your wings snap and break!", ch, NULL, victim, TO_VICT);
      }
      fSave = FALSE;
    }
    if (!fSave 
	&& IS_AFFECTED(victim, AFF_FLYING) && !is_affected(victim,gsn_thrash)){
      AFFECT_DATA af;
      int dam = 100 + dice(7, 7);

      af.where	= TO_AFFECTS;
      af.type   = gsn_thrash;
      af.level  = ch->level;
      af.duration = fFlier ? 12 : 6;
      af.modifier = 0;
      af.location = 0;
      af.bitvector = 0;
      affect_to_char(victim,&af);

      dam = URANGE(0, victim->hit - 5, dam);
      damage( victim, victim, dam, gsn_kinesis, DAM_INTERNAL, TRUE);  

      act("You can't seem to get back into the air",victim,NULL,NULL,TO_CHAR);
      act("$n can't seem to get back into the air",victim,NULL,NULL,TO_ROOM);
    }    
  }
  damage( ch, victim, dam, sn, DAM_BASH, TRUE);  
}


void spell_entropic_touch( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  AFFECT_DATA af, *paf;

  act("With a deft motion you place your palm against $N's armor!", ch, NULL, victim, TO_CHAR);
  act("With a deft motion $n places $s palm against $N's armor!", ch, NULL, victim, TO_NOTVICT);
  act("With a deft motion $n places $s palm against your armor!", ch, NULL, victim, TO_VICT);

  if (is_affected(victim, sn)){
    send_to_char("Their armor has already been melted away!\n\r", ch);
    damage(ch, victim, 0, sn, DAM_ENERGY, TRUE);
    return;
  }

  if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
      && saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
    damage(ch, victim, 0, sn, DAM_ENERGY, TRUE);
    return;
  }
  act("With a hiss of toxic fumes your armor turns to sludge!", victim, NULL, victim, TO_CHAR);
  act("With a hiss of toxic fumes $n's armor turns to sludge!", victim, NULL, victim, TO_ROOM);

  af.type	= sn;
  af.duration	= 12;
  af.level	= level;
  af.where	= TO_AFFECTS;
  af.bitvector	= AFF_FAERIE_FIRE;
  af.location	= APPLY_AC;
  af.modifier	= URANGE(20, -(GET_AC(victim, AC_PIERCE) + GET_AC(victim, AC_SLASH) + GET_AC(victim, AC_BASH)) / 3, 500);
  affect_to_char( victim, &af);
  
  af.type	= gen_create_object;
  af.duration	= UMAX(2, af.modifier / 50);
  af.where	= TO_NONE;
  af.bitvector	= 50;
  af.location	= APPLY_NONE;
  af.modifier	= OBJ_VNUM_ENTROPIC_SLUDGE;
  paf = affect_to_char( victim, &af);
  string_to_affect(paf, "Your armor stops dripping toxic sludge.");
}


void spell_amorphous_infection( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  AFFECT_DATA af, *paf;
  int sp_level = level;

  act("You attempt to summon the creature to feed on $N.", ch, NULL, victim, TO_CHAR);

  if (is_affected(victim, sn)){
    send_to_char("They have already been infected!\n\r", ch);
    return;
  }

  /* increase spell level for psiamp check here to boost the amplification
     one category for unnatural creatures
  */
  if (IS_UNDEAD(victim) || IS_DEMON(victim) || IS_AVATAR(victim))
    sp_level += 10; //(+30 svs spell means 2 category from WEAK to STRONG)
  
  if (psiamp_failed(ch, victim, sp_level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
      && saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
    send_to_char("You failed.\n\r", ch);
    return;
  }

  act("The creature burrows into $N!",ch, NULL, victim, TO_CHAR);
  send_to_char("Your skin feels funny for a moment..", victim);

  af.type	= gen_ainfection;
  af.duration	= -1;
  af.level	= level;
  af.where	= TO_NONE;
  af.bitvector	= 0;
  af.location	= APPLY_NONE;
  af.modifier	= 10; //times the creature will leave host before death
  paf = affect_to_char( victim, &af);
  string_to_affect(paf, ch->name );
}

void spell_disintegrate( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo, *vch;
  AFFECT_DATA af;
  int chance = 0;
  int dam = 0;

  if (is_affected(victim, sn)){
    send_to_char("You failed.\n\r", ch);
    damage(ch, victim, number_range(20, 100), sn, DAM_INTERNAL, TRUE);
    return;
  }

  act("$N screams in agony as $S molecules come apart!", ch, NULL, victim, TO_CHAR);
  act("$N screams in agony as $S molecules come apart!", ch, NULL, victim, TO_NOTVICT);
  act("You scream in agony as your molecules to come apart!", ch, NULL, victim, TO_VICT);

  for ( vch = char_list; vch != NULL; vch = vch->next ){
    if (vch->in_room && vch->in_room->area == victim->in_room->area
	&& vch->in_room != victim->in_room)
      act("You hear $N's distant scream of horrible agony.", vch, NULL, victim, TO_CHAR);
  }

  dam = victim->max_hit / 4;

  af.type	= sn;
  af.level	= level;
  af.duration	= 12;
  af.where	= TO_AFFECTS;
  af.bitvector	= 0;
  af.location	= APPLY_HIT;
  af.modifier	= -dam;

  affect_to_char( victim, &af);

  chance = 50 + (get_curr_stat(victim, STAT_CON) - 19) * 10;
  if (number_percent() < chance){
    send_to_char("You manage to partially resist the disintegration.\n\r", victim);
  }
  else{
    af.type	= gsn_drained;
    af.level	= level;
    af.duration	= 12;
    af.where	= TO_AFFECTS;
    af.bitvector= 0;
    af.location	= APPLY_CON;
    af.modifier	= -10;
    affect_to_char( victim, &af);
  }
  damage(ch, victim, dam, sn, DAM_INTERNAL, TRUE );

}

void spell_breach( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo, *vch;
  AFFECT_DATA* paf, *paf_next;
  bool found = FALSE;


  act("A lance of blinding blue energy streaks from you to $N!", ch, NULL, victim, TO_CHAR);
  act("A lance of blinding blue energy streaks from $n to you!", ch, NULL, victim, TO_VICT);
  act("A lance of blinding blue energy streaks from $n to $N!", ch, NULL, victim, TO_NOTVICT);

  for ( vch = char_list; vch != NULL; vch = vch->next ){
    if (vch->in_room && vch->in_room->area == victim->in_room->area
	&& vch->in_room != victim->in_room)
      act("You see a flash of blinding blue light in near distance.", vch, NULL, victim, TO_CHAR);
  }

  /* quick check to make sure there is anything left to dispel */
  for (paf = victim->affected; paf; paf = paf_next){
    paf_next = paf->next;
    /* look for beneficial protective skills, or any beneficial GEN */
    if (IS_GNBIT(paf->type, GN_BEN)
	&& (IS_GEN(paf->type) 
	    || skill_table[paf->type].spell_type == SPELL_PROTECTIVE)){
      break;
    }
  }
  if (paf == NULL || IS_NPC(victim)){
    send_to_char("There is nothing to breach.\n\r", ch);
    damage(ch, victim, number_range(50, 100), sn, DAM_INTERNAL, TRUE);
    return;
  }

  /* look for mana lock */
  if (is_affected(victim, gsn_mana_lock)){
    check_dispel(-99, victim, gsn_mana_lock);
    damage(ch, victim, number_range(50, 100), sn, DAM_INTERNAL, TRUE);
    return;
  }
  
  /* begin checking spells */
  for (paf = victim->affected; paf; paf = paf_next){
    paf_next = paf->next;
    /* always skip to the last duplicate affect */
    if (paf_next && paf_next->type == paf->type)
      continue;
    /* check if we can dispel */
    if (IS_GNBIT(paf->type, GN_BEN)
	&& (IS_GEN(paf->type) 
	    || skill_table[paf->type].spell_type == SPELL_PROTECTIVE)){

      /* can dispel, check */
      if (check_dispel(-99, victim, paf->type)){
	found = TRUE;
      }
    }
  }

  if (found){
    /* CONTINENCY */
    check_contingency(victim, NULL, CONT_DISPEL);
  }
  else
    send_to_char("Spell failed.\n\r",ch);
  damage(ch, victim, number_range(50, 100), sn, DAM_INTERNAL, TRUE);
}


/* 
sets up the given spell as the dream cast spell, increases level on existing
*/
void dream_setup( CHAR_DATA* ch, int sn){
  AFFECT_DATA *paf;

  if ( (paf = affect_find(ch->affected, gen_dreamwalk)) == NULL){
    bug("dream_setup: Could not find dreamwalk effect.", 0);
    return;
  }
  paf->modifier = sn;
  paf->level = 0;
  paf->duration = 2;
}

void spell_omen(int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA* victim = (CHAR_DATA*) vo;

  if (target >= 0){
    if ( (victim = get_char( target_name )) == NULL){
      send_to_char("You can't seem to enter the dream.\n\r", ch );
      return;
    }
    if (is_affected(victim, gsn_hysteria)){
      send_to_char("They are as scared as they are going to get.\n\r", ch);
      return;
    }
    dream_setup( ch, sn );
    act("With some effort you give life to $N's personal nightmare.", ch, NULL, victim, TO_CHAR);
    return;
  }
  else{
    AFFECT_DATA* paf, af;
    send_to_char("(Dream)Your greatest fears come to life before you!\n\r", victim);
    act("$N cries out in $S sleep.", victim, NULL, victim, TO_ROOM);

    /* check for strong enough fear */
    if ( (paf = affect_find(victim->affected, gsn_fear)) != NULL
	 && paf->modifier >= 30){

      act_new("You start to panic as you enter a state of hysteria!",ch,NULL,victim, TO_VICT,POS_DEAD);
      act("$N starts to panic from $S hysteria!",ch,NULL,victim,TO_CHAR);

      af.type		= gsn_hysteria;
      af.level		= level;
      af.duration	= 8;
      af.where		= TO_AFFECTS; 
      af.bitvector	= 0;
      af.location	= APPLY_NONE;
      af.modifier	= 0;
      affect_to_char(victim, &af);      
      affect_strip(victim, gsn_fear);
      affect_strip(ch, gen_dreamwalk);
    }
    else{
      af.type		= gsn_fear;
      af.level		= level;
      af.duration	= 3;
      af.where		= TO_AFFECTS; 
      af.bitvector	= 0;
      af.location	= APPLY_NONE;
      af.modifier	= 10;
      affect_join(victim, &af);      
    }
  }
}
  


void spell_deathmare(int sn, int level, CHAR_DATA *ch, void *vo,int target ){
  CHAR_DATA* victim = (CHAR_DATA*) vo;

  if (target >= 0){
    if ( (victim = get_char( target_name )) == NULL){
      send_to_char("You can't seem to enter the dream.\n\r", ch );
      return;
    }
    dream_setup( ch, sn );
    act("With some effort you give a more interesting twist to $N's dreams.", ch, NULL, victim, TO_CHAR);
    return;
  }
  else{
    AFFECT_DATA af, *paf;

    /* In Order of appearance 
       1) Blindness(eyes)
       2) Weakness (arms)
       3) Enfeeble (legs)
       4) Wounding (stomach)
    */
    send_to_char("(Dream)You find yourself upon a table, a cloaked figure beside you.\n\r", victim);
    act_new("(Dream)You place $N in a torture chamber and stand above the rack.", ch, NULL, victim, TO_CHAR, POS_DEAD);
    /* EYES */
    if (!is_affected(victim, gsn_blindness)){
      af.type		= gsn_blindness;
      af.level		= level;
      af.duration	= 8;
      af.where		= TO_AFFECTS;
      af.bitvector	= AFF_BLIND;
      af.location	= APPLY_NONE;
      af.modifier	= 0;
      affect_to_char(victim, &af);
      send_to_char("(Dream)The cloaked figure lowers a red hot poker towards your face!\n\r", victim );
      act_new("(Dream)You conjure a red hot poker and aim at $N's eyes!", ch, NULL, victim, TO_CHAR, POS_DEAD);
      act_new("You are blinded!", victim,NULL,NULL,TO_CHAR, POS_DEAD);
      act("$n's eyes begins to bleed.", victim, NULL, NULL, TO_ROOM);
      return;
    }
    else if (!is_affected(victim, gsn_weaken)){
      af.type		= gsn_weaken;
      af.level		= level;
      af.duration	= 8;
      af.where		= TO_AFFECTS;
      af.bitvector	= 0;
      af.location	= APPLY_STR;
      af.modifier	= -1 * (level / 12);
      affect_to_char(victim, &af);
      act_new("(Dream)The cloaked figure swings a massive hammer at your wrists!", victim, NULL, victim, TO_CHAR, POS_DEAD);
      act_new("(Dream)You conjure a large hammer and aim at $N's wrists!", ch, NULL, victim, TO_CHAR, POS_DEAD);
      act_new("You cry in agony as your wrists are pulverized!", victim,NULL,NULL,TO_CHAR, POS_DEAD);
      act("$n's wrists begins to bleed.", victim, NULL, NULL, TO_ROOM);
      return;
    }
    else if (!is_affected(victim, gsn_enfeeblement)){
      af.type		= gsn_enfeeblement;
      af.level		= level;
      af.duration	= 8;
      af.where		= TO_AFFECTS;
      af.bitvector	= 0;
      af.location	= APPLY_DEX;
      af.modifier	= -1 * (level / 12);
      affect_to_char(victim, &af);
      act_new("(Dream)The cloaked figure swings a massive hammer at your knees!", victim, NULL, victim, TO_CHAR, POS_DEAD);
      act_new("(Dream)You conjure a large hammer and aim at $N's knees!", ch, NULL, victim, TO_CHAR, POS_DEAD);
      act_new("You cry in agony as your knees are shattered!", victim,NULL,NULL,TO_CHAR, POS_DEAD);
      act("$n's knees begins to bleed.", victim, NULL, NULL, TO_ROOM);
      return;
    }
    /* STOMACH */
    else if (!is_affected(victim, gen_move_dam)){
      af.type		= gen_move_dam;
      af.level		= level;
      af.duration	= 3;
      af.where		= TO_AFFECTS;
      af.bitvector	= 0;
      af.location	= APPLY_NONE;
      af.modifier	= 0;
      paf = affect_to_char(victim, &af);
      if (!IS_NPC(ch)){
	string_to_affect(paf, ch->name);
      }
      act_new("(Dream)The cloaked figure makes a cut in your gut and reaches in!", victim, NULL, victim, TO_CHAR, POS_DEAD);
      act_new("(Dream)You begin to draw $N's intestines out onto the table!", ch, NULL, victim, TO_CHAR, POS_DEAD);
      act_new("You cry in agony as your intestines are drawn!", victim,NULL,NULL,TO_CHAR, POS_DEAD);
      act("$n's stomach begins to bleed.", victim, NULL, NULL, TO_ROOM);
    }
    else{
      send_to_char("You moan in agony.\n\r", victim);
      send_to_char("There is nothing else you can do to them.\n\r", ch );
    }
  }
}

void spell_mindmelt(int sn, int level, CHAR_DATA *ch, void *vo,int target ){
  CHAR_DATA* victim = (CHAR_DATA*) vo;
  AFFECT_DATA* paf;

  if (target >= 0){
    if ( (victim = get_char( target_name )) == NULL){
      send_to_char("You can't seem to enter the dream.\n\r", ch );
      return;
    }
    if ( (paf = affect_find(victim->affected, sn)) != NULL
	 && paf->modifier >= 20){
      send_to_char("You cannot weaken their mind further.\n\r", ch);
      return;
    }
    dream_setup( ch, sn );
    act("You begin to weaken $N's mental defences.", ch, NULL, victim, TO_CHAR);
    return;
  }
  else{
    AFFECT_DATA af;
    send_to_char("(Dream)You feel an immense pressure upon your temples.\n\r", victim);
    act_new("(Dream)You bore into $N's mind.\n\r", ch, NULL, victim, TO_CHAR, POS_DEAD);
    act("$N squirms in $S sleep.", victim, NULL, victim, TO_ROOM);
    af.type		= sn;
    af.level		= level;
    af.duration		= 12;
    af.where		= TO_AFFECTS; 
    af.bitvector	= 0;
    af.location		= APPLY_SAVING_MENTAL;
    af.modifier		= 5;
    affect_join(victim, &af);      
  }
}

void dreamprobe_cast( CHAR_DATA* victim, char* msg ){
  DESCRIPTOR_DATA *d;
  AFFECT_DATA* paf;
  char buf[MIL];

  if (victim == NULL)
    return;
  else if (msg == NULL){
    if (!IS_AWAKE(victim))
      sprintf(buf, "(Dreamprobe)%s has fallen asleep.\n\r", PERS2(victim));
    else
      sprintf(buf, "(Dreamprobe)%s has awaken.\n\r", PERS2(victim));
    msg = buf;
  }
  for ( d = descriptor_list; d; d = d->next ){
    if ( d->connected == CON_PLAYING
	 && victim->in_room != d->character->in_room
	 && (paf = affect_find(d->character->affected, gsn_dreamprobe)) != NULL
	 && paf->has_string
	 && !str_cmp(paf->string, victim->name)){
      send_to_char(msg, d->character);
    }
  }//end for
}  
/* shows info to dreamwalker in order:
   1) Armor 
   2) Hit/Mana/Move
   3) Hitroll/Damroll 
   4) Saves
   Also allows sleep/wake messages on last dreamprobe victim, and remote
   dreamwalk
*/
void spell_dreamprobe(int sn, int level, CHAR_DATA *ch, void *vo,int target ){
  CHAR_DATA* victim = (CHAR_DATA*) vo;

  if (target >= 0){
    if ( (victim = get_char( target_name )) == NULL){
      send_to_char("You can't seem to enter the dream.\n\r", ch );
      return;
    }
    dream_setup( ch, sn );
    act("You begin to probe $N's mind.", ch, NULL, victim, TO_CHAR);
    return;
  }
  else{
    AFFECT_DATA af, *paf;
    /* attach the dreamprobe for future wake/sleep messages */
    if ( (paf = affect_find(ch->affected, sn)) == NULL){
      af.type		= sn;
      af.level		= level;
      af.duration	= 48;
      af.where		= TO_AFFECTS;
      af.bitvector	= 0;
      af.location	= APPLY_NONE;
      af.modifier	= 0;
      paf = affect_to_char(ch, &af);
    }
    act_new("Your dreamprobe uncovers something useful.", ch, NULL, victim, TO_CHAR, POS_DEAD);
    /* reset dreamprobe link target and duration */
    string_to_affect(paf, victim->name );
    paf->duration = 48;

    /* show stats */
    switch(paf->modifier++){
    case 0:
      sendf( ch, "%s's Armor:\n\rPierce: %d  Bash: %d  Slash: %d  Magic: %d\n\r",
	     PERS2(victim),
	     GET_AC(victim, AC_PIERCE),
	     GET_AC(victim, AC_BASH),
	     GET_AC(victim, AC_SLASH),
	     GET_AC(victim, AC_EXOTIC));
      break;
    case 1:
      sendf( ch, "%s has %d/%d hit, %d/%d mana, %d/%d movement.\n\r",
	     PERS2(victim),
	     victim->hit, victim->max_hit,
	     victim->mana, victim->max_mana,
	     victim->move, victim->max_move);
      break;
    case 2:
      sendf( ch, "%s's Hitroll: %d  Damroll: %d.\n\r",
	     PERS2(victim),
	     GET_HITROLL(victim),
	     GET_DAMROLL(victim));
      break;
    case 3:
	sendf( ch, "%s's Save vs\n\rSpell: %d  Affliction: %d  Malediction: %d  Mental: %d\n\r", 
	       PERS2(victim),
	       victim->savingspell,
	       victim->savingaffl,
	       victim->savingmaled,
	       victim->savingmental);
	break;
    default:
      paf->modifier = 0;
    }
  }
}

/* Written by: Virigoth							*
 * Returns: void							*
 * Used: magic.c, magic3.c						*
 * Comment: A dispell magic like spell, except on failed save prevents  *
 * any defensive spells (TAR_SELF, TAR_CHAR_DEFENSIVE) from casting.	*/

void spell_mental_knife( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  AFFECT_DATA af;
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  int dam = number_range(1, 5) * level / 2;

  
  /* dispel magic like effect on failed save */
  if (ch == victim){
    send_to_char("You failed.\n\r", ch);
    return;
  }
  
  af.type               = skill_lookup("mind blast");
  affect_strip(victim, af.type );
  af.level              = level; 
  af.duration           = number_range(1, 3);
  af.location           = APPLY_INT;
  af.modifier           = -5;
  af.bitvector          = 0;
  affect_to_char(victim,&af);

  if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
      && !saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
    damage(ch,victim, dam ,sn,DAM_MENTAL, TRUE);
    return;
  }
    
  act("Your mental knife sears $N's mind!",ch,NULL,victim,TO_CHAR);
  act("$n's mental knife sears your mind!",ch,NULL,victim,TO_VICT);
  act("$n's mental knife sears $N's mind!",ch,NULL,victim,TO_NOTVICT);
  
  /* attach the no-recast effect */
  af.type		= sn;
  af.location	= APPLY_NONE;
  af.modifier	= 0;
  af.duration	= number_range(1,3);
  affect_strip(victim, sn );
  affect_to_char(victim, &af );
  damage(ch,victim, dam ,sn,DAM_MENTAL, TRUE);
}

   
void spell_spell_vise( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  AFFECT_DATA af, *paf;
  int to_dispel = 4;

  /* look for mana lock */
  if (is_affected(victim, gsn_mana_lock)){
    if (!effect_manalock(sn, level, ch, victim))
      return;
    else
      send_to_char("Ok.\n\r", ch );
  }
  if (is_affected(victim, gen_svise)){
    send_to_char("You failed.\n\r", ch);
    return;
  }
  /* on save we cut number of spells to dispel by half */
  if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
      && !saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type))
    to_dispel /= 2;

  act("A sparkling blue ring appears around $n's head.", victim, NULL, NULL, TO_ROOM);
  act("A sparkling blue ring appears around your head.", victim, NULL, NULL, TO_CHAR);
  af.type		= gen_svise;
  af.level		= level;
  af.duration		= 1;
  af.where		= TO_AFFECTS;
  af.bitvector	= 0;
  af.location		= APPLY_NONE;
  af.modifier		= to_dispel;//how many random spells to take off
  paf = affect_to_char( victim, &af);
  string_to_affect(paf, ch->name );
}  


void spell_mana_trap (int sn, int level, CHAR_DATA *ch, void *vo,int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  AFFECT_DATA af;

  if (is_affected(victim, sn)){
    if (ch == victim){
      send_to_char("You are already trapping mana from spells.\n\r", ch);
    }
    else
      send_to_char("They are already trapping mana from spells.\n\r", ch);
  }
  
  af.type = sn;
  af.level = level;
  af.duration = number_fuzzy(8);
  af.where = TO_AFFECTS;
  af.bitvector = 0;
  af.location = APPLY_NONE;
  af.modifier = 0;
  affect_to_char( victim, &af);
  send_to_char("You construct a mana trap and arm it.\n\r", victim);
}

void spell_spell_trap (int sn, int level, CHAR_DATA *ch, void *vo,int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  AFFECT_DATA af;

  if (is_affected(victim, sn)){
    if (ch == victim){
      send_to_char("You are already trapping spells.\n\r", ch);
    }
    else
      send_to_char("They are already trapping spells.\n\r", ch);
    return;
  }
  
  af.type = sn;
  af.level = level;
  af.duration = number_fuzzy(8);
  af.where = TO_AFFECTS;
  af.bitvector = 0;
  af.location = APPLY_NONE;
  af.modifier = 0;
  affect_to_char( victim, &af);
  send_to_char("You construct a spell trap and arm it.\n\r", victim);
}

/* transfers portion of victims hp/mana/move to caster */
void spell_soul_pump( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  int dam = number_range(10, 50);
  int dur = number_fuzzy(12);

  int hit_mul, hit_dam;
  int move_mul, move_dam;
  int mana_mul, mana_dam;

  if (is_affected(victim, sn )){
    send_to_char("You failed.\n\r", ch);
    return;
  }

  /* gain is multiplied by the amount of %hp caster has lost */
  /* than scaled by % of hp that victim has */

  hit_mul = UMAX(0, 10 * (ch->max_hit - ch->hit) / (1 + ch->max_hit));
  hit_dam = UMAX(1, victim->hit * (dam * hit_mul) / (1 + victim->max_hit));

  move_mul = UMAX(0, 10 * (ch->max_move - ch->move) / ( 1 + ch->max_move));
  move_dam = UMAX(1, victim->move * (dam * move_mul) / (1 + victim->max_move));

  mana_mul = UMAX(0, 10 * (ch->max_mana - ch->mana) / (1 + ch->max_mana));
  mana_dam = UMAX(1, victim->mana * (dam * mana_mul) / (1 + victim->max_mana));

  if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
      && !saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
    act("$N resists your soul pump.", ch, NULL, victim, TO_CHAR);
    act("You resists $n's soul pump.", ch, NULL, victim, TO_VICT);
    hit_dam /= 2;
    move_dam /= 2;
    mana_dam /= 2;
    dur /= 2;
  }

  /* cap the damage */
  hit_dam = UMIN(victim->hit, hit_dam);
  hit_dam = UMIN(350, hit_dam);
  move_dam = UMIN(victim->move, move_dam);
  move_dam = UMIN(350, move_dam);
  mana_dam = UMIN(victim->mana, mana_dam);
  mana_dam = UMIN(500, mana_dam);
  

  if ( damage( ch, victim, hit_dam, sn, DAM_INTERNAL, TRUE)){
    AFFECT_DATA af;
    sendf(ch, "You gain %d health, %d mana and %d stamina!\n\r", 
	  hit_dam, mana_dam, move_dam );
    send_to_char("You feel your soul slipping away!\n\r", victim);
    ch->hit = UMIN( ch->max_hit, ch->hit + hit_dam);
    ch->move = UMIN( ch->max_move, ch->move + move_dam);
    victim->move -= move_dam;
    ch->mana = UMIN( ch->max_mana, ch->mana + mana_dam);
    victim->mana -= mana_dam;
    update_pos( ch );

    af.type	= sn;
    af.level	= level;
    af.duration	= dur;
    af.where	= TO_AFFECTS;
    af.bitvector= 0;
    af.location	= APPLY_HIT_GAIN;
    af.modifier	= -25;
    affect_to_char( victim, &af);
    af.location	= APPLY_MANA_GAIN;
    affect_to_char( victim, &af);
    af.location	= APPLY_MOVE_GAIN;
    affect_to_char( victim, &af);
  }
}

/* spell blast effect, checks if the spell was blasted and negated */
bool check_spellblast( CHAR_DATA* ch, CHAR_DATA* victim, int sn, int cost, int level ){
  AFFECT_DATA* paf;

  if (ch == NULL || victim == NULL)
    return FALSE;
  else if ( (paf = affect_find(victim->affected, gsn_spell_blast)) == NULL)
    return FALSE;

  /* check saves */
  if (psiamp_failed(victim, ch, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
      && saves_spell(level, ch, DAM_MENTAL,skill_table[sn].spell_type)){
    return FALSE;
  }
  paf->modifier -= cost * 3;
  act("Your spell blast destroys $t.",
      victim,
      skill_table[sn].name,
      ch,
      TO_CHAR);
  act("$n spell blast destroys $N's spell.",
      victim,
      NULL,
      ch,
      TO_NOTVICT);
  act("$n's spell blast destroys your $t.",
      victim,
      skill_table[sn].name,
      ch,
      TO_VICT);
  /* check for failure of effect on lack of mana */
  if (paf->modifier <= 0){
    if ( skill_table[paf->type].msg_off )
      act_new(skill_table[paf->type].msg_off,victim,NULL,NULL,TO_CHAR,POS_DEAD);
    if ( skill_table[paf->type].msg_off2 )
      act(skill_table[paf->type].msg_off2,victim,NULL,NULL,TO_ROOM);
    affect_strip(victim, paf->type);
  }
  return TRUE;
}

void spell_spell_blast( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = ch;
  AFFECT_DATA af, *paf;
  int gain = UMIN(victim->max_mana / 3, atoi( target_name ));

  gain = URANGE(1, victim->mana, gain );

  if ( (paf = affect_find(victim->affected, sn )) != NULL){
    paf->modifier = UMIN(victim->max_mana / 3, paf->modifier + gain );
    victim->mana -= gain;
    sendf(victim, "Spell blast reserve now at %d mana.\n\r", paf->modifier );
    paf->modifier = 8;
    return;
  }

  af.type	= sn;
  af.level	= level;
  af.duration	= number_fuzzy(8);
  af.where	= TO_AFFECTS;
  af.bitvector	= 0;
  af.location	= APPLY_NONE;
  af.modifier	= gain;
  victim->mana -= gain;
  affect_to_char(victim, &af);
  sendf(victim, "Spell blast reserve now at %d mana.\n\r", af.modifier );  
}

/* checks if masochism kicks in */
/* returns the character that should damage the ch, or NULL */
CHAR_DATA* masochism_effect( CHAR_DATA* ch, int dam, int dt ){
  AFFECT_DATA* paf;
  CHAR_DATA* och;

  if ( dt < TYPE_HIT
      || dam < 1
      || (paf = affect_find(ch->affected, gsn_masochism)) == NULL
      || !paf->has_string
      || IS_NULLSTR(paf->string)
      || number_percent() > 35
      || (och = get_char( paf->string )) == NULL
      ){
    return NULL;
  }
  else
    return och;
}

void spell_masochism( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  AFFECT_DATA af, *paf;

  if ( is_affected( victim, sn )){
    if (victim == ch)
      act("You are already under effects of masochism.",ch,NULL,victim,TO_CHAR);
    else
      act("$N is already under effects of masochism.",ch,NULL,victim,TO_CHAR);
    return;
  }

  if (IS_UNDEAD(victim)
      || (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
	  && saves_spell( level, victim, DAM_MENTAL,skill_table[sn].spell_type))
      ){
    act("$N refuses your subconscious suggestion.", ch, NULL, victim, TO_CHAR);
    return;
  }

  af.where	= TO_AFFECTS;
  af.type      = sn;
  af.level     = level;
  af.duration  = number_fuzzy(6);
  af.modifier  = 0;
  af.location  = APPLY_NONE;
  af.bitvector = 0;
  paf = affect_to_char( victim, &af );
  string_to_affect( paf, ch->name );
  act_new( "You begin to wonder if it would feel good to hurt yourself.",ch,NULL,victim,TO_CHARVICT,POS_DEAD);
  if ( ch != victim )
    act("$N begins to subconsciously pinch $s skin.",ch,NULL,victim,TO_CHAR);
}
void spell_brain_death( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  AFFECT_DATA af;
  int res = 0;

  if ( is_affected( victim, sn )){
    send_to_char("They've already been lobotomized.\n\r", ch);
    return;
  }
  if ( (res = check_immune(victim, DAM_MENTAL, TRUE)) > IS_IMMUNE){
    CHAR_DATA* vch;
    for ( vch = char_list; vch != NULL; vch = vch->next ){
      if (vch->in_room && vch->in_room->area == victim->in_room->area
	  && vch->in_room != victim->in_room)
	act("You hear $N's distant agonizing scream.", vch, NULL, victim, TO_CHAR);
    }
    af.type	= sn;
    af.level	= level;
    af.duration	= number_fuzzy(14);
    af.where	= TO_AFFECTS;
    af.bitvector= 0;
    af.location	= APPLY_INT;
    af.modifier	= -1 * (UMAX(10, get_max_stat(victim, STAT_INT) / 2));
    affect_to_char( victim, &af );
    
    af.type	= gsn_forget;
    af.duration	= number_range(1, 2);
    af.where	= TO_AFFECTS;
    af.location	= APPLY_NONE;
    af.modifier	= 0;
    affect_to_char( victim, &af );

    send_to_char( "You have been LOBOTOMIZED!!\n\r\n\r", victim );  
    act("$n has been LOBOTOMIZED!!", victim, NULL, NULL, TO_ROOM );
  }
  damage(ch, victim, number_range(35, 75), sn, DAM_INTERNAL, TRUE );
}

/* restores all spells but removes total recall */
void spell_total_recall( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  DNDS_DATA* dnds;

  if (IS_NPC(victim))
    return;

  send_to_char("Nothing seems to have happened.\n\r", ch);
  act("$n's eyes flare brilliant blue for an instant.", ch, NULL, NULL, TO_ROOM);
  forget_dndtemplates( ch->pcdata );
  add_memticks(victim->pcdata, 1000, victim->class, victim->level);

  while ( (dnds = dnds_lookup( ch->pcdata, sn, -1 )) != NULL
	  && GET_DNDMEM(ch->pcdata, sn) > 0){
    useup_dnds( ch->pcdata, sn );
  }
}

void spell_unminding( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo, *vch;
  AFFECT_DATA af;
  int dam = 0;
  int res = 0;

  if ( is_affected( victim, sn )){
    send_to_char("They've already been unminded.\n\r", ch);
    return;
  }
  if ( (res = check_immune(victim, DAM_MENTAL, TRUE)) > IS_IMMUNE){
    for ( vch = char_list; vch != NULL; vch = vch->next ){
      if (vch->in_room && vch->in_room->area == victim->in_room->area
	  && vch->in_room != victim->in_room)
	act("You hear $N's distant agonizing scream.", vch, NULL, victim, TO_CHAR);
    }
    af.type	= sn;
    af.level	= level;
    af.duration	= number_fuzzy(14);
    af.where	= TO_AFFECTS;
    af.bitvector= 0;
    af.location	= APPLY_WIS;
    af.modifier	= -1 * (UMAX(10, get_max_stat(victim, STAT_WIS) / 2));
    affect_to_char( victim, &af );
    
    act("$n screams and tears at $s head!", victim, NULL, NULL, TO_ROOM);
    send_to_char("You scream in pain as your memories and experiences are turned against you!\n\r", victim);

    if (res == IS_RESISTANT){
      send_to_char("Your mental resistance has been compromised.\n\r", victim);
      act("$N's mental resistance has been compromised.", ch, NULL, victim, TO_CHAR);
    }
    if ( (res = check_immune(victim, DAM_CHARM, TRUE)) == IS_RESISTANT){
      send_to_char("Your resistance to charms has been compromised.\n\r", victim);
      act("$N's resistance to charms has been compromised.", ch, NULL, victim, TO_CHAR);
    }
  }
  if (IS_NPC(victim))
    dam = 50 + 8 * level;
  else
    dam = 50 + (pc_race_table[victim->race].class_mult - 1500 + class_table[victim->class].extra_exp) / 3;
  damage(ch, victim, dam, sn, DAM_INTERNAL, TRUE );
}

//fakes weapon type in defense checks
void spell_false_weapon( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = ch;
  AFFECT_DATA af;
  int weapon_type = number_range(0, WEAPON_STAFF );
  int val;

  if (is_affected(victim, sn)){
    send_to_char("You already have an illusion around your weapons.\n\r", victim);
    return;
  }
  else if ( (val = weapon_lookup( target_name )) >= 0)
    weapon_type = URANGE(0, val, WEAPON_STAFF);

  af.type	= sn;
  af.level	= level;
  af.duration	= number_fuzzy(level / 4);
  af.where	= TO_AFFECTS;
  af.bitvector	= 0;
  af.location	= APPLY_NONE;
  af.modifier	= weapon_table[weapon_type].type;
  affect_to_char( victim, &af );
  sendf( ch, "Your weapons will now appear as %ss.\n\r", weapon_table[weapon_type].name);
}

//causes perfect flee, and auto-invis once fled
void spell_shadow_door( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  AFFECT_DATA af;

  /* after combat auto-invis part */
  if (target < 0){
    AFFECT_DATA* paf;
    //check if we can use photon wall to auto-invis
    if ( (paf = affect_find(victim->affected, gen_photon_wall)) != NULL){
      paf->modifier = 0;
      run_effect_update(ch, paf, NULL, paf->type, NULL, NULL, TRUE, EFF_UPDATE_INIT);
      return;
    }
    else{
      //cast invis and reduce duration to 1 
      spell_invis(gsn_invis, level, ch, ch, 0);
      if ( (paf = affect_find(victim->affected, gsn_invis)) != NULL)
	paf->duration = 1;
    }
    return;
  }
  else if (is_affected(victim, sn)){
    send_to_char("You're already affected by shadow door.\n\r", victim);
    return;
  }

  af.type	= sn;
  af.level	= level;
  af.duration	= number_fuzzy(level / 5);
  af.where	= TO_AFFECTS;
  af.bitvector	= 0;
  af.location	= APPLY_NONE;
  af.modifier	= 0;
  affect_to_char( victim, &af );
  send_to_char("You will now flee combat through a shadow door.\n\r", ch);
}
void spell_mirror_cloak( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  AFFECT_DATA af;


  if (is_affected(victim, sn)){
    send_to_char("You're already surrounded by the cloak of mirrors.\n\r", victim);
    return;
  }

  af.type	= sn;
  af.level	= level;
  af.duration	= number_fuzzy(level / 2);
  af.where	= TO_AFFECTS;
  af.bitvector	= 0;
  af.location	= APPLY_NONE;
  af.modifier	= 0;
  affect_to_char( victim, &af );
  send_to_char("You begin to mirror appearance of all whom look upon you.\n\r", ch);
}

void spell_numbness( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  AFFECT_DATA af;

  if (is_affected(victim, gsn_numbness)){
    check_dispel( -99, victim, gsn_nerve_amp);
  }
  if (is_affected(victim, sn)){
    send_to_char("Their nerves have already been numbed.\n\r", ch);
    return;
  }
  /* check saves */
  if (psiamp_failed(ch,victim,  level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
      && saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
    send_to_char("You failed.\n\r", ch);
    return ;
  }
  af.type	= sn;
  af.level	= level;
  af.duration	= number_fuzzy(level / 10);
  af.where	= TO_NONE;
  af.bitvector	= 0;
  af.location	= APPLY_NONE;
  af.modifier	= 0;
  affect_to_char( victim, &af );

  if (ch != victim)
    act("You subvert $N's pain receptors.", ch, NULL, victim, TO_CHAR);
  else
    send_to_char("You subvert your own pain receptors.\n\r", ch );
}
void spell_nerve_amp( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  AFFECT_DATA af;

  if (is_affected(victim, gsn_numbness)){
    check_dispel( -99, victim, gsn_numbness);
  }
  if (is_affected(victim, sn)){
    send_to_char("Their nerves have already been stimulated.\n\r", ch);
    return;
  }
  /* check saves */
  if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
      && saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
    send_to_char("You failed.\n\r", ch);
    return ;
  }
  af.type	= sn;
  af.level	= level;
  af.duration	= number_fuzzy(level / 10);
  af.where	= TO_NONE;
  af.bitvector	= 0;
  af.location	= APPLY_NONE;
  af.modifier	= 0;
  affect_to_char( victim, &af );

  if (ch != victim)
    act("You stimulate $N's pain receptors.", ch, NULL, victim, TO_CHAR);
  else
    send_to_char("You stimulate your own pain receptors.\n\r", ch );
}

void spell_mirage( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  AFFECT_DATA af;


  if (is_affected(victim, sn)){
    send_to_char("You've already created a mirage of your weapons.\n\r", victim);
    return;
  }

  af.type	= sn;
  af.level	= level;
  af.duration	= number_fuzzy(level / 6);
  af.where	= TO_AFFECTS;
  af.bitvector	= 0;
  af.location	= APPLY_NONE;
  af.modifier	= 0;
  affect_to_char( victim, &af );
  send_to_char("You create a mirage of your weapons.\n\r", ch);
}
void spell_blink( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  AFFECT_DATA af;


  if (is_affected(victim, sn)){
    send_to_char("You're already prepared to phase out.\n\r", victim);
    return;
  }

  af.type	= sn;
  af.level	= level;
  af.duration	= number_fuzzy(level / 6);
  af.where	= TO_AFFECTS;
  af.bitvector	= 0;
  af.location	= APPLY_NONE;
  af.modifier	= 0;
  affect_to_char( victim, &af );
  send_to_char("You will now phase out of existance to avoid attacks.\n\r", ch);
}

void spell_phantasm( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  AFFECT_DATA af, *paf;

  if (is_affected(victim, gen_phantasm)){
    send_to_char("They are already hunted by phantasms.\n\r", ch);
    return;
  }
  else if (ch == victim){
    send_to_char("You failed.\n\r", ch);
    return;
  }
  /* check saves */
  if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
      && saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
    send_to_char("You failed.\n\r", ch);
    return ;
  }

  af.type	= gen_phantasm;
  af.level	= level;
  af.duration	= number_fuzzy(1);
  af.where	= TO_AFFECTS;
  af.bitvector	= 0;
  af.location	= APPLY_NONE;
  af.modifier	= number_range(5, 11);//how many times phantasm scares
  paf =  affect_to_char( victim, &af );
  string_to_affect( paf, ch->name );


  act("A blurred apparition briefly appears before you.", victim, NULL, NULL, TO_CHAR);
  act("A blurred apparition briefly appears before $n.", victim, NULL, NULL, TO_ROOM);
}

void spell_duplicate( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo,*clone;
  AFFECT_DATA af;
  char buf[MSL];
  int charmies = 1, duration, chance = number_percent();

  if (ch == victim){
    send_to_char("You can't cast this spell on yourself.\n\r",ch);
    return;
  }

  if (get_charmed_by(ch) >= charmies && !IS_IMMORTAL(ch)){
    send_to_char("You are already controlling as many as you can.\n\r",ch);
    return;
  }
  if (is_affected(victim,sn)){
    send_to_char("You cannot duplicate that mob yet.\n\r",ch);
    return;
  }
  if (IS_AFFECTED(victim, AFF_CHARM) 
      || victim->level - level > 5 
      || victim->fighting != NULL
      || (IS_NPC(victim) && IS_SET(victim->act,ACT_AGGRESSIVE))
      || IS_SET(victim->imm_flags,IMM_CHARM)
      || IS_UNDEAD(victim) 
      || !IS_AWAKE(victim)
      || is_affected(victim, gsn_hypnosis)){
    send_to_char("You cannot duplicate this creature.\n\r", ch);
    return;
  }
  if (saves_spell( level -3, victim,DAM_CHARM,skill_table[sn].spell_type)){
    send_to_char("You failed.\n\r",ch);
    return;
  }

  duration = level / 6;
  duration += URANGE(0, (ch->level - victim->level) / 2, 5);
  af.where     = TO_AFFECTS;
  af.type      = sn;
  af.level     = level;
  af.duration  = duration;
  af.location  = 0;
  af.modifier  = 0;
  af.bitvector = 0;

  if (IS_NPC(victim)){
    clone = create_mobile(get_mob_index(MOB_VNUM_CLONE));
    clone_mobile( victim, clone );
    clone_mobile(victim,clone);
    clone->group = 0;
    clone->level = UMAX(2, clone->level);
    sprintf(buf,"illusion %s",victim->name);
    free_string(clone->name);
    clone->name		= str_dup(buf);
    char_to_room(clone,ch->in_room);
  }
  else{
    clone = create_mobile(get_mob_index(MOB_VNUM_CLONE));
    sprintf(buf,"illusion %s",victim->name);
    free_string(clone->name);
    clone->name		= str_dup(buf);
    free_string(clone->description);
    clone->description	= str_dup(victim->description);
    clone->sex		= victim->sex;
    clone->level	= level;
    clone->race		= victim->race;	
    char_to_room(clone,ch->in_room);
  }
  affect_to_char( victim, &af );
  af.bitvector = AFF_PASS_DOOR;
  affect_to_char( clone, &af );
  sprintf( buf, "An illusion of %s", IS_NPC(victim) ? victim->short_descr : victim->name);
  free_string( clone->short_descr );
  clone->short_descr = str_dup( buf );

  af.where     = TO_AFFECTS;
  af.type      = gsn_timer;
  af.level     = level;
  af.duration  = duration;
  af.location  = 0;
  af.modifier  = 0;
  af.bitvector = 0;
  affect_to_char( clone, &af );

  af.type      = gsn_charm_person;
  af.bitvector = AFF_CHARM;
  affect_to_char( clone, &af );
  SET_BIT(clone->act2,ACT_DUPLICATE);

  if ( chance < 30 ){
    sprintf( buf, "A hazy illusion of %s guards its master.\n\r",IS_NPC(victim) ? victim->short_descr : victim->name);
    free_string( clone->long_descr );
    clone->long_descr = str_dup( buf );
    clone->level /= 2;
    clone->hit /= 3;
    clone->max_hit /= 3;
    clone->hitroll /= 2;
    clone->damroll /= 2;
    clone->damage[DICE_NUMBER] /= 2;
    clone->damage[DICE_TYPE] /= 2;
    act("$n appears in a hazy smoke!",clone,NULL,NULL,TO_ROOM);
  }
  else if ( chance < 60 ){
    sprintf( buf, "A blurred illusion of %s guards its master.\n\r",IS_NPC(victim) ? victim->short_descr : victim->name);
    free_string( clone->long_descr );
    clone->long_descr = str_dup( buf );
    clone->level = 3 * clone->level/4;
    clone->max_hit = 3 * clone->hit / 4;
    clone->hit = clone->max_hit;
    clone->hitroll -= clone->damroll/4;
    clone->damroll -= clone->damroll/4;
    clone->damage[DICE_NUMBER]--;
    clone->damage[DICE_TYPE]--;
    act("$n appears in a blurred light!",clone,NULL,NULL,TO_ROOM);
  }
  else{
    sprintf( buf, "An illusion of %s guards its master.\n\r",IS_NPC(victim) ? victim->short_descr : victim->name);
    free_string( clone->long_descr );
    clone->long_descr = str_dup( buf );
    act("$n appears in a bright flash of light!",clone,NULL,NULL,TO_ROOM);
  }
  if (clone->master)
    stop_follower(clone);
  add_follower(clone,ch);
  clone->leader = ch;
  clone->gold = 0;
}

void spell_time_compression( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  AFFECT_DATA af;


  if (is_affected(victim, sn)){
    send_to_char("You're already compressing time around yourself.\n\r", victim);
    return;
  }

  af.type	= sn;
  af.level	= level;
  af.duration	= number_fuzzy(level / 8);
  af.where	= TO_AFFECTS;
  af.bitvector	= 0;
  af.location	= APPLY_NONE;
  af.modifier	= 0;
  affect_to_char( victim, &af );
  send_to_char("You begin to compress time around yourself.\n\r", ch);
  act("$n's figure begins to leave a distinct after image.", ch, NULL, NULL, TO_ROOM);
}

void spell_molecular_leash( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  AFFECT_DATA af, *paf;

  if (is_affected(victim, gen_phantasm)){
    send_to_char("They are already been leashed.\n\r", ch);
    return;
  }
  else if (ch == victim){
    send_to_char("You failed.\n\r", ch);
    return;
  }
  /* check saves */
  if (psiamp_failed(ch, victim, level, DAM_MENTAL, skill_table[sn].spell_type, skill_table[sn].flags)
      && saves_spell(level, victim, DAM_MENTAL,skill_table[sn].spell_type)){
    send_to_char("You failed.\n\r", ch);
    return ;
  }
  
  af.type	= sn;
  af.level	= level;
  af.duration	= 0;
  af.where	= TO_AFFECTS;
  af.bitvector	= 0;
  af.location	= APPLY_NONE;
  af.modifier	= number_range(4, 9);//how many flees before leash breaks
  paf = affect_to_char( victim, &af );
  string_to_affect( paf, ch->name );

  act("A glowing blue collar appears around your neck.", victim, NULL, NULL, TO_CHAR);
  act("A glowing blue collar appears around $n's neck.", victim, NULL, NULL, TO_ROOM);
}
void spell_planar_rift( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  OBJ_DATA *blade;
  AFFECT_DATA af;
  
  //Data
  int skill = get_skill(ch, sn);
  
  int dice1 = 5;
  int dice2 = 5;

  int dam =  1;
  int hit =  3;
  
  int weight = 0;

  const int dur = 12;
  /*
    We create a rift blade with dam roll /bonues based on level and skill.
    blade is no-rem/no-drop/no-uncurse by default, and poofs on drop.
    weight is 10 to forstall removing by dropping str
  */
  
  if (IS_NPC(ch))
    return;
  
  if (is_affected(ch, sn)){
    send_to_char("You lack the strength to create a new planar blade.\n\r",ch);
    return;
  }
  
  if (get_eq_char(ch, WEAR_WIELD) != NULL
      || (get_eq_char(ch, WEAR_HOLD) != NULL && get_eq_char(ch, WEAR_SHIELD) != NULL)){
    send_to_char("Your hands must be ready to wield the blade the moment it is created.\n\r", ch);
    return;
  }
  
  blade = create_object( get_obj_index(OBJ_VNUM_PLANAR_BLADE),level);
  
  /* Set hit /dam roll*/
  dice1 += (skill > 80? 1 : 0) + (skill > 85? 1 : 0);
  dice2 += (skill > 90? 1 : 0) + (skill > 95? 1 : 0);

  dam += UMAX(0, dice1 - 5);
  hit += UMAX(0, dice2 - 5);
  if (skill > 99)
    hit += 2;
		 
  
  /* set timer */
  blade->timer = dur;
  
  /* set dice */
  blade->value[1] = dice1;
  blade->value[2] = dice2;
  
  /* set level, weight, etc */
  blade->level = UMIN(60, 10 + level);
  blade->weight = weight;
  blade->cost = 0;
  
  /* set dam / hit */
  af.type = sn;
  af.level = level;
  af.duration = -1;
  
  af.where = TO_NONE;
  af.bitvector = 0;
  
  af.location = APPLY_DAMROLL;
  af.modifier = dam;
  affect_to_obj(blade, &af);
  
  af.location = APPLY_HITROLL;
  af.modifier = hit;
  affect_to_obj(blade, &af);
  
  
  /* set effect on character */
  af.type = sn;
  af.level = level;
  af.duration = dur;
  
  af.where = TO_AFFECTS;
  af.bitvector = 0;
  
  af.location = APPLY_NONE;
  af.modifier = 0;
  
  /* final check if we can hold the blade */
  if (IS_WEAPON_STAT(blade, WEAPON_TWO_HANDS)
      && (get_eq_char(ch, WEAR_SHIELD) != NULL
	  || get_eq_char(ch, WEAR_SECONDARY) != NULL
	  || get_eq_char(ch, WEAR_HOLD) != NULL)){
    send_to_char("You must have both hands free to recive this weapon.\n\r", ch);
    return;
  }
  
  act("A shimmering plane of force extends from your hand.",ch,blade,NULL,TO_CHAR);
  act("A shimmering plane of force extends from $n's hand.",ch,blade,NULL,TO_ROOM);
  obj_to_char(blade,ch);
  
/* check if it zapped and dropped */
  if (blade->carried_by != ch)
    extract_obj( blade );
  else
    equip_char(ch, blade, WEAR_WIELD);
  
  if (!IS_IMMORTAL(ch))
    affect_to_char(ch, &af);
}    

void spell_paralyze( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  AFFECT_DATA af;

  if (is_affected(victim, sn)){
    send_to_char("They are already been paralyzed.\n\r", ch);
    return;
  }
  else if (ch == victim){
    send_to_char("You failed.\n\r", ch);
    return;
  }

  af.type      = gsn_paralyze;
  af.level     = level;
  af.duration  = number_fuzzy(1);
  af.where     = TO_AFFECTS;
  af.bitvector = 0;
  af.location  = APPLY_NONE;
  af.modifier  = number_range(10, 15);
  affect_to_char( victim, &af );

  act("$n has been paralyzed!", victim, NULL, NULL, TO_ROOM);
  act("You have been paralyzed!", victim, NULL, NULL, TO_CHAR);  
}

void spell_petrify( int sn, int level, CHAR_DATA *ch, void *vo, int target ){
  CHAR_DATA *victim = (CHAR_DATA *) vo;
  AFFECT_DATA af;
  int res = 0;

  if ( is_affected( victim, sn )){
    send_to_char("They've already been petrified.\n\r", ch);
    return;
  }
  if ( (res = check_immune(victim, DAM_CHARM, TRUE)) > IS_IMMUNE){
    CHAR_DATA* vch;
    for ( vch = char_list; vch != NULL; vch = vch->next ){
      if (vch->in_room && vch->in_room->area == victim->in_room->area
	  && vch->in_room != victim->in_room)
	act("$N's agonizing scream pierces the air and then cuts off abruptly.", vch, NULL, victim, TO_CHAR);
    }
    af.type	= sn;
    af.level	= level;
    af.duration	= number_fuzzy(4);
    af.where	= TO_AFFECTS2;
    af.bitvector= AFF_PETRIFY;
    af.location	= APPLY_NONE;
    af.modifier	= 0;
    affect_to_char( victim, &af );
    
    stop_fighting(victim, TRUE );
    send_to_char( "You have been PETRIFIED!!\n\r\n\r", victim );  
    act("$n has been PETRIFIED!!", victim, NULL, NULL, TO_ROOM );
  }
  else
    send_to_char("You failed.\n\r", ch);
}