/
mudtem/
mudtem/area/scripts/
mudtem/bin/
mudtem/log/
mudtem/player/
mudtem/slang/autoconf/
mudtem/slang/doc/
mudtem/slang/doc/OLD/help/
mudtem/slang/doc/internal/
mudtem/slang/doc/text/
mudtem/slang/doc/tm/tools/
mudtem/slang/examples/
mudtem/slang/modules/
mudtem/slang/slsh/
mudtem/slang/slsh/lib/
mudtem/slang/slsh/scripts/
mudtem/slang/src/mkfiles/
mudtem/slang/src/util/
mudtem/src/CVS/
mudtem/src/include/
mudtem/src/include/CVS/
mudtem/src/var/CVS/
/***************************************************************************
 *  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 Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  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-1996 Russ Taylor			   *
*	ROM has been brought to you by the ROM consortium		   *
*	    Russ Taylor (rtaylor@efn.org)				   *
*	    Gabrielle Taylor						   *
*	    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			   *
***************************************************************************/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "merc.h"
#include "magic.h"
#include "tables.h"

#define CHECKENT()	if ( !entidadEsCh(ent) )		\
				return fERROR;			\
			else					\
				victim = entidadGetCh(ent);

#define CHECKOBJENT()	if ( !entidadEsObj(ent) )		\
				return fERROR;			\
			else					\
				obj = entidadGetObj(ent);

#define CHECKCH()	if ( !entidadEsCh(caster) )		\
				return fERROR;			\
			else					\
				ch = entidadGetCh(caster);

DECLARE_DO_FUN(do_scan);
DECLARE_DO_FUN(do_flee);
DECLARE_DO_FUN(do_say);

extern char *target_name;

int evaluate( char *, CHAR_DATA *, CHAR_DATA *, double * );

SPELL_FUN_DEC(spell_farsight)
{
    CHAR_DATA *ch;

    CHECKCH()

    do_scan(ch,target_name);

    return fOK;
}

SPELL_FUN_DEC(spell_portal)
{
    CHAR_DATA *victim;
    OBJ_DATA *portal, *stone;
    CHAR_DATA *ch;

    CHECKCH()

        if ( ( victim = get_char_world( ch, target_name ) ) == NULL
    ||   entComparar(ent, caster)
    ||   victim->in_room == NULL
    ||   !can_see_room(ch,victim->in_room)
    ||   IS_SET(victim->in_room->room_flags, ROOM_SAFE)
    ||   IS_SET(victim->in_room->room_flags, ROOM_PRIVATE)
    ||   IS_SET(victim->in_room->room_flags, ROOM_SOLITARY)
    ||   IS_SET(victim->in_room->room_flags, ROOM_NO_RECALL)
    ||   (IS_NPC(victim) && IS_SET(victim->act, ACT_PROTOTIPO))
    ||   IS_SET(entWhereIs(caster)->room_flags, ROOM_NO_RECALL)
    ||   entGetNivel(ent) >= level + 3
    ||   (!ent_is_npc(ent) && entGetNivel(ent) >= LEVEL_HERO)  /* NOT trust */
    ||   (ent_is_npc(ent) && IS_SET(victim->imm_flags,IMM_SUMMON))
    ||   (ent_is_npc(ent) && ent_saves_spell( level, ent, DAM_NONE) ) 
    ||	(is_clan(victim) && !is_same_clan(ch,victim)))
    {
        send_to_char( "Fallaste.\n\r", ch );
        return fFAIL;
    }   

    stone = get_eq_char(ch,WEAR_HOLD);
    if (!IS_IMMORTAL(ch) 
    &&  (stone == NULL || stone->item_type != ITEM_WARP_STONE))
    {
	send_to_char("You lack the proper component for this spell.\n\r",ch);
	return fERROR;
    }

    if (stone != NULL && stone->item_type == ITEM_WARP_STONE)
    {
     	act("You draw upon the power of $p.",ch,objToEnt(stone),NULL,TO_CHAR);
     	act("It flares brightly and vanishes!",ch,objToEnt(stone),NULL,TO_CHAR);
     	extract_obj(stone, TRUE);
    }

    portal = create_object(get_obj_index(OBJ_VNUM_PORTAL),0);
    portal->timer = 2 + level / 25; 
    portal->value[3] = victim->in_room->vnum;

    obj_to_room(portal,entWhereIs(caster));

    act("$p rises up from the ground.",ch,objToEnt(portal),NULL,TO_ROOM);
    act("$p rises up before you.",ch,objToEnt(portal),NULL,TO_CHAR);

    return fOK;
}

SPELL_FUN_DEC(spell_nexus)
{
    CHAR_DATA *victim;
    OBJ_DATA *portal, *stone;
    ROOM_INDEX_DATA *to_room, *from_room;
    CHAR_DATA *ch;

    CHECKCH()

    from_room = entWhereIs(caster);
 
        if ( ( victim = get_char_world( ch, target_name ) ) == NULL
    ||   entComparar(ent, caster)
    ||   (to_room = victim->in_room) == NULL
    ||   !can_see_room(ch,to_room) || !can_see_room(ch,from_room)
    ||   IS_SET(to_room->room_flags, ROOM_SAFE)
    ||	 IS_SET(from_room->room_flags,ROOM_SAFE)
    ||   IS_SET(to_room->room_flags, ROOM_PRIVATE)
    ||   IS_SET(to_room->room_flags, ROOM_SOLITARY)
    ||   IS_SET(to_room->room_flags, ROOM_NO_RECALL)
    ||   IS_SET(from_room->room_flags,ROOM_NO_RECALL)
    ||   entGetNivel(ent) >= level + 3
    ||   (!ent_is_npc(ent) && entGetNivel(ent) >= LEVEL_HERO)  /* NOT trust */
    ||   (ent_is_npc(ent) && IS_SET(victim->imm_flags,IMM_SUMMON))
    ||   (ent_is_npc(ent) && ent_saves_spell( level, ent, DAM_NONE) ) 
    ||	 (is_clan(victim) && !is_same_clan(ch,victim)))
    {
        send_to_char( "Fallaste.\n\r", ch );
        return fFAIL;
    }   
 
    stone = get_eq_char(ch,WEAR_HOLD);
    if (!IS_IMMORTAL(ch)
    &&  (stone == NULL || stone->item_type != ITEM_WARP_STONE))
    {
        send_to_char("You lack the proper component for this spell.\n\r",ch);
        return fERROR;
    }
 
    if (stone != NULL && stone->item_type == ITEM_WARP_STONE)
    {
        act("You draw upon the power of $p.",ch,objToEnt(stone),NULL,TO_CHAR);
        act("It flares brightly and vanishes!",ch,objToEnt(stone),NULL,TO_CHAR);
        extract_obj(stone, TRUE);
    }

    /* portal one */ 
    portal = create_object(get_obj_index(OBJ_VNUM_PORTAL),0);
    portal->timer = 1 + level / 10;
    portal->value[3] = to_room->vnum;
 
    obj_to_room(portal,from_room);
 
    act("$p rises up from the ground.",ch,objToEnt(portal),NULL,TO_ROOM);
    act("$p rises up before you.",ch,objToEnt(portal),NULL,TO_CHAR);

    /* no second portal if rooms are the same */
    if (to_room == from_room)
	return fOK;

    /* portal two */
    portal = create_object(get_obj_index(OBJ_VNUM_PORTAL),0);
    portal->timer = 1 + level/10;
    portal->value[3] = from_room->vnum;

    obj_to_room(portal,to_room);

    if (to_room->people != NULL)
    {
	act("$p rises up from the ground.",to_room->people,objToEnt(portal),NULL,TO_ROOM);
	act("$p rises up from the ground.",to_room->people,objToEnt(portal),NULL,TO_CHAR);
    }

    return fOK;
}

SPELL_FUN_DEC(spell_combat_mind)
{
    AFFECT_DATA af;

    if ( ent_is_affected( ent, sn ) )
    {
	if ( entComparar(ent, caster) )
		send_to_ent( "Ya entiendes tacticas de batalla.\n\r", caster );
	else
		nact( "$N ya entiende tacticas de batalla.", caster, NULL, ent, TO_CHAR );
	return fERROR;
    }

    af.type	 = sn;
    af.duration	 = level + 3;
    af.location	 = APPLY_HITROLL;
    af.modifier	 = level / 6;
    af.level	 = level;
    af.bitvector = 0;
    affect_to_ent( ent, &af );

    af.location	 = APPLY_AC;
    af.modifier	 = - level/2 - 5;
    affect_to_ent( ent, &af );

    send_to_ent( "Aprendes un nuevo conjunto de tacticas de batalla.\n\r", ent );
    nact( "$n aprende un nuevo conjunto de tacticas de batalla.", ent, NULL, NULL, TO_ROOM );

    return fOK;
}

/*
 * Code for Psionicist spells/skills by Thelonius
 */
SPELL_FUN_DEC(spell_adrenaline_control)
{
    CHAR_DATA  *victim;
    AFFECT_DATA af;
    CHAR_DATA *ch;

    CHECKCH()

    CHECKENT()

    if ( ent_is_affected( ent, sn ) )
        return fERROR;

    af.where	 = TO_AFFECTS;
    af.type	 = sn;
    af.duration	 = level - 5;
    af.location	 = APPLY_DEX;
    af.level	 = level;
    af.modifier	 = 2;
    af.bitvector = 0;
    affect_to_ent( ent, &af );

    af.location	= APPLY_CON;
    affect_to_ent( ent, &af );

    send_to_char( "You have given yourself an adrenaline rush!\n\r", ch );
    act( "$n has given $mself an adrenaline rush!", ch, NULL, NULL,
	TO_ROOM );
   
    return fOK;
}

SPELL_FUN_DEC(spell_agitation )
{
    CHAR_DATA *victim;
    static const int        dam_each [ ] =
    {
	0,
	 0,  0,  0,  0,  0,      12, 15, 18, 21, 24,
	24, 24, 25, 25, 26,      26, 26, 27, 27, 27,
	28, 28, 28, 29, 29,      29, 30, 30, 30, 31,
	31, 31, 32, 32, 32,      33, 33, 33, 34, 34,
	34, 35, 35, 35, 36,      36, 36, 37, 37, 37
    };
		 int        dam;

    CHECKENT()

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

    return newdamage(caster,victim,dam,sn,DAM_MENTAL,TRUE );
}

SPELL_FUN_DEC(spell_aura_sight)
{
    sn = skill_lookup( "know alignment" );

    return (*skill_table[sn].spell_fun) ( sn, level, caster, ent, TAR_CHAR_SELF );
}

SPELL_FUN_DEC(spell_awe)
{
    CHAR_DATA *victim;
    CHAR_DATA *ch;

    CHECKCH()

    CHECKENT()

    if ( victim->fighting == ch && !ent_saves_spell( level, ent, DAM_MENTAL ) )
    {
	stop_fighting ( victim, TRUE);
	act( "$N is in AWE of you!", ch, NULL, ent, TO_CHAR    );
	act( "You are in AWE of $n!",ch, NULL, ent, TO_VICT    );
	act( "$N is in AWE of $n!",  ch, NULL, ent, TO_NOTVICT );
    }
    return fOK;
}

SPELL_FUN_DEC(spell_ballistic_attack )
{
                 CHAR_DATA *victim;
    static const int        dam_each [ ] =
    {
	 0,
	 3,  4,  4,  5,  6,       6,  6,  7,  7,  7,
	 7,  7,  8,  8,  8,       9,  9,  9, 10, 10,
	10, 11, 11, 11, 12,      12, 12, 13, 13, 13,
	14, 14, 14, 15, 15,      15, 16, 16, 16, 17,
	17, 17, 18, 18, 18,      19, 19, 19, 20, 20
    };
		 int        dam;
	
    CHECKENT()

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

    nact( "You chuckle as a stone strikes $N.", caster, NULL, ent,
	TO_CHAR );

    return newdamage( caster, victim, dam, sn, DAM_MENTAL, TRUE );
}

SPELL_FUN_DEC(spell_biofeedback )
{
    return (*skill_table[gsn_sanctuary].spell_fun) ( gsn_sanctuary, level, caster, ent, TAR_CHAR_SELF );
}

SPELL_FUN_DEC(spell_cell_adjustment )
{
    CHAR_DATA *victim;
   
    CHECKENT()

    if ( ent_is_affected( ent, gsn_poison ) )
    {
	affect_strip( victim, gsn_poison );
	send_to_char( "A warm feeling runs through your body.\n\r", victim );
	nact( "$N looks better.", caster, NULL, ent, TO_NOTVICT );
    }
    if ( ent_is_affected( ent, gsn_curse  ) )
    {
	affect_strip( victim, gsn_curse  );
	send_to_char( "You feel better.\n\r", victim );
    }	
    send_to_ent( "Ok.\n\r", caster );
    return fOK;
}

SPELL_FUN_DEC(spell_complete_healing )
{
    CHAR_DATA *victim;

    CHECKENT()

    change_health( caster, ent, entGetMaxHit(ent) - entGetHit(ent) );
    update_pos( victim );
    if ( !entComparar(caster, ent) )
        send_to_ent( "Ok.\n\r", caster );
    send_to_char( "Ahhhhhh...You are completely healed!\n\r", victim );
    return fOK;
}

SPELL_FUN_DEC(spell_control_flames )
{
    CHAR_DATA *victim;
    static const int        dam_each [ ] = 
    {
	 0,
	 0,  0,  0,  0,  0,       0,  0, 16, 20, 24,
	28, 32, 35, 38, 40,      42, 44, 45, 45, 45,
	46, 46, 46, 47, 47,      47, 48, 48, 48, 49,
	49, 49, 50, 50, 50,      51, 51, 51, 52, 52,
	52, 53, 53, 53, 54,      54, 54, 55, 55, 55
    };
		 int        dam;

    CHECKENT()

    if ( !ent_get_eq_char( caster, WEAR_LIGHT ) )
    {
	send_to_ent( "You must be carrying a light source.\n\r", caster );
	return fERROR;
    }

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

    newdamage( caster, victim, dam, sn, DAM_MENTAL, TRUE );

    if ( !char_died(victim) )
    	fire_effect( victim, level, dam, TARGET_CHAR );

    return fOK;
}

SPELL_FUN_DEC(spell_create_sound )
{
    CHAR_DATA *vch;
    char       buf1    [ MAX_STRING_LENGTH ];
    char       buf2    [ MAX_STRING_LENGTH ];
    char       speaker [ MAX_INPUT_LENGTH  ];

    target_name = one_argument( target_name, speaker );

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

    for ( vch = entGetPeopleRoom(caster); vch; vch = vch->next_in_room )
    {
	if ( !is_exact_name( speaker, vch->name ) && IS_AWAKE(vch) )
	    send_to_char( saves_spell( level, vch, DAM_MENTAL ) ? buf2 : buf1, vch);
    }
    return fOK;
}

SPELL_FUN_DEC(spell_death_field )
{
    CHAR_DATA *vch;
    CHAR_DATA *vch_next;
    int        dam;
    int        hpch;

    if ( !ent_is_evil( caster ) )
    {
	send_to_ent( "You are not evil enough to do that!\n\r", caster);
	return fERROR;
    }

    send_to_ent( "A black haze emanates from you!\n\r", caster );
    nact ( "A black haze emanates from $n!", caster, NULL, NULL, TO_ROOM );

    for ( vch = entGetPeopleRoom(caster); vch; vch = vch_next )
    {
        vch_next = vch->next_in_room;

	if ( !ent_is_safe_spell( caster, chToEnt(vch), TRUE) )
	{
	    hpch = URANGE( 10, entGetHit(caster), 999 );

	    dam = number_range( hpch / 8 + 1, hpch / 4);

	    if ( !saves_spell( level, vch, DAM_MENTAL ) && (entGetNivel(caster) - getNivelPr(vch) > 5) )
	    {
		send_to_char( "The haze envelops you!\n\r", vch );
		act( "The haze envelops $n!", vch, NULL, NULL, TO_ROOM );
		dam *= 2 + CHANCE(level);
	    }

	    dam = UMIN( dam, 1200 );
	    newdamage( caster, vch, dam, sn, DAM_MENTAL, TRUE );
        }
    }

    return fOK;
}

SPELL_FUN_DEC(spell_detonate )
{
    CHAR_DATA *victim;
    static const int        dam_each [ ] =
    {
	  0,
	  0,   0,   0,   0,   0,        0,   0,   0,   0,   0,
	  0,   0,   0,   0,   0,        0,   0,   0,   0,  75,
	 80,  85,  90,  95, 100,      102, 104, 106, 108, 110,
	112, 114, 116, 118, 120,      122, 124, 126, 128, 130,
	132, 134, 136, 138, 140,      142, 144, 146, 148, 150
    };
    int        dam;

    CHECKENT()

    level    = UMIN( level, sizeof( dam_each ) / sizeof( dam_each[0] ) - 1 );
    level    = UMAX( 0, level );
    dam	     = number_range( dam_each[level] / 2, dam_each[level] * 2 );
    if ( ent_saves_spell( level, ent, DAM_MENTAL ) )
        dam /= 2;
    return newdamage( caster, victim, dam, sn, DAM_MENTAL, TRUE );
}

SPELL_FUN_DEC(spell_disintegrate )
{
    CHAR_DATA *victim;
    OBJ_DATA  *obj_lose;
    OBJ_DATA  *obj_next;

    CHECKENT()

    if ( !ent_is_npc(ent) )
    	return fERROR;

    if ( number_percent( ) < 2 * level && !ent_saves_spell( level, ent, DAM_MENTAL ) )
      for ( obj_lose = victim->carrying; obj_lose; obj_lose = obj_next )
      {
	  obj_next = obj_lose->next_content;

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

	  act( "$p disintegrates!", victim, objToEnt(obj_lose), NULL, TO_CHAR );
	  act( "$p disintegrates!", victim, objToEnt(obj_lose), NULL, TO_ROOM );
	  extract_obj( obj_lose, TRUE ) ;
      }

    if ( !ent_saves_spell( level, ent, DAM_MENTAL ) )
    /*
     * Disintegrate char, do not generate a corpse, do not
     * give experience for kill.  Extract_char will take care
     * of items carried/wielded by victim.  Needless to say,
     * it would be bad to be a target of this spell!
     * --- Thelonius (Monk)
     */
    {
	nact( "Tu #B*** #FDESINTEGRASTE#f ***#b a $N!", caster, NULL, ent, TO_CHAR );
	nact( "Fuiste #B*** #FDESINTEGRADO#f ***#b por $n!", caster, NULL, ent, TO_VICT );
	nact( "El spell de $n #B*** #FDESINTEGRA#f ***#b a $N!", caster, NULL, ent, TO_NOTVICT );

	extract_char( victim, TRUE );
	return victdead;
    }

    return fOK;
}

SPELL_FUN_DEC(spell_displacement )
{
    CHAR_DATA  *victim;
    AFFECT_DATA af;

    CHECKENT()

    if ( ent_is_affected( ent, sn ) )
	return fERROR;

    af.where	 = TO_AFFECTS;
    af.type	 = sn;
    af.duration	 = level - 4;
    af.location	 = APPLY_AC;
    af.level	 = level;
    af.modifier	 = 4 - level;
    af.bitvector = 0;
    affect_to_ent( ent, &af );

    send_to_char( "Your form shimmers, and you appear displaced.\n\r",
		 victim );
    nact( "$N shimmers and appears in a different location.",
	caster, NULL, ent, TO_NOTVICT );
    return fOK;
}

SPELL_FUN_DEC(spell_domination )
{
    CHAR_DATA  *victim;
    CHAR_DATA *ch;
    AFFECT_DATA af;

    CHECKCH()
    CHECKENT()

    if ( entComparar(ent, caster) )
    {
	send_to_ent( "Dominate yourself?  You're weird.\n\r", caster );
	return fERROR;
    }

    if ( IS_AFFECTED(victim, AFF_CHARM)
    ||   ent_IS_AFFECTED(caster, AFF_CHARM)
    ||   level < entGetNivel(ent)
    ||   IS_SET(victim->imm_flags,IMM_CHARM)
    ||   ent_saves_spell( level, ent, DAM_CHARM) )
	return fFAIL;

    if (IS_SET(victim->in_room->room_flags,ROOM_LAW))
    {
	send_to_ent(
	    "The mayor does not allow charming in the city limits.\n\r",caster);
	return fERROR;
    }

    if ( victim->master )
        stop_follower( victim );
    add_follower( victim, ch );
    victim->leader = ch;
    af.where	 = TO_AFFECTS;
    af.type	 = sn;
    af.duration	 = number_fuzzy( level / 4 );
    af.location	 = APPLY_NONE;
    af.level	 = level;
    af.modifier	 = 0;
    af.bitvector = AFF_CHARM;
    affect_to_ent( ent, &af );

    nact( "Your will dominates $N!", caster, NULL, ent, TO_CHAR );
    nact( "Your will is dominated by $n!", caster, NULL, ent, TO_VICT );
    return fOK;
}

SPELL_FUN_DEC(spell_ectoplasmic_form )
{
    CHAR_DATA  *victim;
    AFFECT_DATA af;

    CHECKENT()

    if ( IS_AFFECTED( victim, AFF_PASS_DOOR ) )
        return fERROR;

    af.where	 = TO_AFFECTS;
    af.type	 = sn;
    af.duration	 = number_fuzzy( level / 4 );
    af.location	 = APPLY_NONE;
    af.modifier	 = 0;
    af.level	 = level;
    af.bitvector = AFF_PASS_DOOR;
    affect_to_ent( ent, &af );

    send_to_char( "You turn translucent.\n\r", victim );
    act( "$n turns translucent.", victim, NULL, NULL, TO_ROOM );
    return fOK;
}

SPELL_FUN_DEC(spell_ego_whip )
{
    CHAR_DATA  *victim;
    AFFECT_DATA af;

    CHECKENT()

    if ( ent_is_affected( ent, sn ) || ent_saves_spell( level, ent, DAM_MENTAL ) )
        return fFAIL;

    af.where	 = TO_AFFECTS;
    af.type	 = sn;
    af.duration	 = level;
    af.location	 = APPLY_HITROLL;
    af.modifier	 = -2;
    af.bitvector = 0;
    af.level	 = level;
    affect_to_ent( ent, &af );

    af.location	 = APPLY_SAVING_SPELL;
    af.modifier	 = 2;
    affect_to_ent( ent, &af );

    af.location	 = APPLY_AC;
    af.modifier	 = level / 2;
    affect_to_ent( ent, &af );

    nact( "You ridicule $N about $S childhood.", caster, NULL, ent, TO_CHAR    );
    send_to_char( "Your ego takes a beating.\n\r", victim );
    nact( "$N's ego is crushed by $n!",          caster, NULL, ent, TO_NOTVICT );

    return fOK;
}

SPELL_FUN_DEC(spell_energy_containment )
{
    CHAR_DATA  *victim;
    AFFECT_DATA af;

    CHECKENT()

    if ( ent_is_affected( ent, sn ) )
        return fERROR;

    af.where	 = TO_AFFECTS;
    af.type	 = sn;
    af.duration	 = level / 2 + 7;
    af.modifier	 = -level / 5;
    af.location  = APPLY_SAVING_SPELL;
    af.level	 = level;
    af.bitvector = 0;
    affect_to_ent( ent, &af );

    send_to_ent( "You can now absorb some forms of energy.\n\r", caster );
    return fOK;
}

SPELL_FUN_DEC(spell_enhance_armor)
{
    OBJ_DATA    *obj;
    AFFECT_DATA af;

    CHECKOBJENT()

    if ( obj->item_type != ITEM_ARMOR
      || IS_OBJ_STAT( obj, ITEM_MAGIC )
      || obj->affected )
    {
	send_to_ent( "Ese objeto no puede ser encantado.\n\r", caster );
	return fERROR;
    }

    af.where		= TO_OBJECT;
    af.type		= sn;
    af.duration		= -1;
    af.location		= APPLY_AC;
    af.level		= level;
    af.bitvector	= 0;

    if ( number_percent() < ent_get_skill(caster, sn)/2
	+ 3 * ( entGetNivel(caster) - obj->level ) )

    /* Good enhancement */
    {
	af.modifier   = -level / 8;

	if ( ent_is_good( caster ) )
	{
		SET_BIT( obj->extra_flags, ITEM_ANTI_EVIL );
		nact( "$p empieza a brillar con un tono azul.",   caster, objToEnt(obj), NULL, TO_CHAR );
	}
	else if ( ent_is_evil( caster ) )
	{
		SET_BIT( obj->extra_flags, ITEM_ANTI_GOOD );
		nact( "$p empieza a brillar con un tono rojizo.", caster, objToEnt(obj), NULL, TO_CHAR );
	}
	else
	{
		SET_BIT( obj->extra_flags, ITEM_ANTI_EVIL );
		SET_BIT( obj->extra_flags, ITEM_ANTI_GOOD );
		nact( "$p empieza a brillar con un tono dorado.", caster, objToEnt(obj), NULL, TO_CHAR );
	}

	SET_BIT(obj->extra_flags, ITEM_GLOW);
	send_to_ent( "Ok.\n\r", caster );
    }
    else
    /* Bad Enhancement ... opps! :) */
    {
	af.modifier	= level / 8;
	obj->cost	= 0;

	SET_BIT( obj->extra_flags, ITEM_NODROP );
	SET_BIT( obj->extra_flags, ITEM_DARK );
	nact( "$p cambia a un color oscuro.", caster, objToEnt(obj), NULL, TO_CHAR );
    }

    affect_to_obj( obj, &af );

    return fOK;
}

SPELL_FUN_DEC(spell_enhanced_strength )
{
    CHAR_DATA  *victim;
    AFFECT_DATA af;

    CHECKENT()

    if ( ent_is_affected( ent, sn )
    ||   ent_is_affected( ent, skill_lookup( "giant strength" ) ) )
    {
	if (entComparar(ent, caster))
	  send_to_ent("You are already as strong as you can get!\n\r",caster);
	else
	  nact("$N can't get any stronger.",caster,NULL,ent,TO_CHAR);
	return fERROR;
    }

    af.where	 = TO_AFFECTS;
    af.type	 = sn;
    af.duration	 = level;
    af.level	 = level;
    af.location	 = APPLY_STR;
    af.modifier	 = 1 + ( level >= 15 ) + ( level >= 25 );
    af.bitvector = 0;
    affect_to_ent( ent, &af );

    send_to_char( "You are HUGE!\n\r", victim );
    return fOK;
}

SPELL_FUN_DEC(spell_flesh_armor )
{
    CHAR_DATA  *victim;
    AFFECT_DATA af;

    CHECKENT()

    if ( ent_is_affected( ent, sn )
    ||   ent_is_affected( ent, skill_lookup("stone skin") ) )
    {
	if (entComparar(ent, caster))
	  send_to_ent("Your skin is already as hard as a rock.\n\r",caster); 
	else
	  nact("$N is already as hard as can be.",caster,NULL,ent,TO_CHAR);
	return fERROR;
    }

    af.where	 = TO_AFFECTS;
    af.type	 = sn;
    af.duration	 = level;
    af.location	 = APPLY_AC;
    af.level	 = level;
    af.modifier	 = -40;
    af.bitvector = 0;
    affect_to_ent( ent, &af );

    send_to_char( "Your flesh turns to steel.\n\r", victim );
    nact( "$N's flesh turns to steel.", caster, NULL, ent, TO_NOTVICT);
    return fOK;
}

SPELL_FUN_DEC(spell_inertial_barrier )
{
    CHAR_DATA  *gch;
    AFFECT_DATA af;

    for ( gch = entGetPeopleRoom(caster); gch; gch = gch->next_in_room )
    {
	if ( !ent_is_same_group( chToEnt(gch), caster )
	   || IS_AFFECTED( gch, AFF_PROTECT_EVIL )
	   || IS_AFFECTED( gch, AFF_PROTECT_GOOD) )
	    continue;

	act( "An inertial barrier forms around $n.", gch, NULL, NULL,
	    TO_ROOM );
	send_to_char( "An inertial barrier forms around you.\n\r", gch );

	af.where     = TO_AFFECTS;
	af.type	     = sn;
	af.duration  = 24;
        af.level     = level;
	af.modifier  = 0;
	af.location  = APPLY_NONE;
	af.bitvector = AFF_PROTECT_EVIL;
	af.caster_id = entGetId(caster);
	affect_to_char( gch, &af );
    }
    return fOK;
}

SPELL_FUN_DEC(spell_inflict_pain )
{
    CHAR_DATA *victim;

    CHECKENT()

    return newdamage( caster, victim, dice( 2, 10 ) + level / 2, sn, DAM_MENTAL, TRUE );
}

SPELL_FUN_DEC(spell_intellect_fortress )
{
    CHAR_DATA  *gch;
    AFFECT_DATA af;

    for ( gch = entGetPeopleRoom(caster); gch; gch = gch->next_in_room )
    {
	if ( !ent_is_same_group( chToEnt(gch), caster ) || is_affected( gch, sn ) )
	    continue;

	send_to_char( "A virtual fortress forms around you.\n\r", gch );
	act( "A virtual fortress forms around $n.", gch, NULL, NULL, TO_ROOM );

        af.where     = TO_AFFECTS;
	af.type	     = sn;
	af.duration  = 24;
        af.level     = level;
	af.location  = APPLY_AC;
	af.modifier  = -40;
	af.bitvector = 0;
	af.caster_id = entGetId(caster);
	affect_to_char( gch, &af );
    }
    return fOK;
}

SPELL_FUN_DEC(spell_lend_health )
{
    CHAR_DATA *victim;
    int        hpch;

    CHECKENT()

    if ( entComparar(caster, ent) )
    {
	send_to_ent( "Lend health to yourself?  What a weirdo.\n\r", caster );
	return fERROR;
    }
    hpch = UMIN( 50, entGetMaxHit(ent) - entGetHit(ent) );
    if ( hpch == 0 )
    {
	nact( "Nice thought, but $N doesn't need healing.", caster, NULL,
	    ent, TO_CHAR );
	return fERROR;
    }
    if ( entGetHit(caster)-hpch < 50 )
    {
	send_to_ent( "You aren't healthy enough yourself!\n\r", caster );
	return fERROR;
    }
    change_health(caster, ent, hpch);
    change_health(caster, caster, -hpch);
    update_pos( victim );
    ent_update_pos( caster );

    nact( "You lend some of your health to $N.", caster, NULL, ent, TO_CHAR );
    nact( "$n lends you some of $s health.",     caster, NULL, ent, TO_VICT );

    return fOK;
}

SPELL_FUN_DEC(spell_levitation )
{
    CHAR_DATA *victim;
    AFFECT_DATA af;

    CHECKENT()

    if ( IS_AFFECTED( victim, AFF_FLYING ) )
        return fERROR;

    af.where	 = TO_AFFECTS;
    af.type	 = sn;
    af.duration	 = level + 3;
    af.location	 = APPLY_NONE;
    af.level     = level;
    af.modifier	 = 0;
    af.bitvector = AFF_FLYING;
    affect_to_ent( ent, &af );

    send_to_char( "Tus pies empiezan a elevarse.\n\r", victim );
    act( "$n empieza a levitar.", victim, NULL, NULL, TO_ROOM );
    return fOK;
}

SPELL_FUN_DEC(spell_mental_barrier )
{
    CHAR_DATA  *victim;
    AFFECT_DATA af;

    CHECKENT()

    if ( ent_is_affected( ent, sn ) )
        return fERROR;

    af.where	 = TO_AFFECTS;
    af.type	 = sn;
    af.duration	 = 24;
    af.location	 = APPLY_AC;
    af.modifier	 = -20;
    af.level     = level;
    af.bitvector = 0;
    affect_to_ent( ent, &af );

    send_to_char( "Levantas una barrera mental a tu alrededor.\n\r",
		 victim );
    return fOK;
}

SPELL_FUN_DEC(spell_mind_thrust )
{
    CHAR_DATA *victim;

    CHECKENT()

    return newdamage( caster, victim, dice( 1, 10 ) + level / 2, sn, DAM_MENTAL, TRUE );
}

SPELL_FUN_DEC(spell_project_force )
{
    CHAR_DATA *victim;

    CHECKENT()

    return newdamage( caster, victim, dice( 4, 6 ) + level, sn, DAM_MENTAL, TRUE );
}

SPELL_FUN_DEC(spell_psionic_blast )
{
                 CHAR_DATA *victim;
    static const int        dam_each [ ] =
    {
	  0,
	  0,   0,   0,   0,   0,        0,   0,   0,   0,   0,
	  0,   0,   0,   0,   0,        0,  45,  50,  55,  60,
	 64,  68,  72,  76,  80,       82,  84,  86,  88,  90,
	 92,  94,  96,  98, 100,      102, 104, 106, 108, 100,
	112, 114, 116, 118, 120,      122, 124, 126, 128, 130
    };
		 int        dam;

    CHECKENT()

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

    return newdamage( caster, victim, dam, sn, DAM_MENTAL, TRUE );
}

SPELL_FUN_DEC(spell_psychic_crush )
{
    CHAR_DATA *victim;

    CHECKENT()

    return newdamage( caster, victim, dice( 3, 5 ) + level, sn, DAM_MENTAL, TRUE );
}

SPELL_FUN_DEC(spell_psychic_drain )
{
    CHAR_DATA  *victim;
    AFFECT_DATA af;

    CHECKENT()

    if ( ent_is_affected( ent, sn ) || ent_saves_spell( level, ent, DAM_MENTAL ) )
        return fFAIL;

    af.where	 = TO_AFFECTS;
    af.type	 = sn;
    af.duration	 = level / 2;
    af.level     = level;
    af.location	 = APPLY_STR;
    af.modifier	 = -1 - ( level >= 10 ) - ( level >= 20 ) - ( level >= 30 );
    af.bitvector = 0;
    affect_to_ent( ent, &af );

    send_to_char( "You feel drained.\n\r", victim );
    act( "$n appears drained of strength.", victim, NULL, NULL, TO_ROOM );
    return fOK;
}

SPELL_FUN_DEC(spell_psychic_healing )
{
    CHAR_DATA *victim;
    int heal;

    CHECKENT()

    heal = dice( 3, 6 ) + 2 * level / 3 ;
    change_health(caster, ent, heal);
    update_pos( victim );

    if ( !entComparar(caster, ent) )
    	send_to_ent( "Ok.\n\r", caster );

    send_to_char( "Te sientes mejor!\n\r", victim );
    return fOK;
}

SPELL_FUN_DEC(spell_share_strength )
{
    CHAR_DATA  *victim;
    AFFECT_DATA af;

    CHECKENT()

    if ( entComparar(ent, caster) )
    {
	send_to_ent( "No puedes compartir fuerza contigo mismo.\n\r", caster );
	return fERROR;
    }
    if ( ent_is_affected( ent, sn ) )
    {
	nact( "$N ya esta compartiendo fuerza con alguien.", caster, NULL, ent,
	    TO_CHAR );
	return fERROR;
    }
    if ( ent_get_curr_stat( caster, STAT_STR ) <= 5 )
    {
	send_to_ent( "Estas demasiado debil como para compartir tu fuerza.\n\r", caster );
	return fERROR;
    }

    af.where	 = TO_AFFECTS;
    af.type	 = sn;
    af.level     = level;
    af.duration	 = level;
    af.location	 = APPLY_STR;
    af.modifier	 =  1 + ( level >= 20 ) + ( level >= 30 );
    af.bitvector = 0;
    affect_to_ent( ent, &af );
    
    af.modifier	 = -1 - ( level >= 20 ) - ( level >= 30 );
    affect_to_ent( caster,     &af );

    nact( "Compartes tu fuerza con $N.", caster, NULL, ent, TO_CHAR );
    nact( "$n comparte su fuerza contigo.",  caster, NULL, ent, TO_VICT );
    return fOK;
}

SPELL_FUN_DEC(spell_thought_shield )
{
    CHAR_DATA  *victim;
    AFFECT_DATA af;

    CHECKENT()

    if ( ent_is_affected( ent, sn ) )
        return fERROR;

    af.where	 = TO_AFFECTS;
    af.type	 = sn;
    af.duration	 = level;
    af.level     = level;
    af.location	 = APPLY_AC;
    af.modifier	 = -20;
    af.bitvector = 0;
    affect_to_ent( ent, &af );

    send_to_ent( "Has creado un escudo a tu alrededor.\n\r", caster );
    return fOK;
}

SPELL_FUN_DEC(spell_ultrablast )
{
    CHAR_DATA *vch;
    CHAR_DATA *vch_next;
    int        dam;
    int        hpch;

    for ( vch = entGetPeopleRoom(caster); vch; vch = vch_next )
    {
        vch_next = vch->next_in_room;

	if ( ent_is_npc( caster ) ? !IS_NPC( vch ) : IS_NPC( vch ) )
	{
	    hpch = UMAX( 10, entGetHit(caster) );
	    dam  = number_range( hpch / 8+1, hpch / 4 );
	    if ( saves_spell( level, vch, DAM_MENTAL ) )
	        dam /= 2;
	    newdamage( caster, vch, dam, sn, DAM_MENTAL, TRUE );
	}
    }
    return fOK;
}

SPELL_FUN_DEC(spell_vampiric_bite)
{
    CHAR_DATA  *victim;
    OBJ_DATA   *obj;
    AFFECT_DATA af;
    int         dam;

    CHECKENT()

    dam = dice( 5, level );
    newdamage( caster, victim, dam, sn, DAM_POISON, TRUE );

    change_health( caster, caster, dam );

    if ( entGetNivel(ent) < 11 || get_age( victim ) < 21 )
        return fERROR;

    if ( IS_AFFECTED( victim, AFF_POLYMORPH ) )
        return fERROR;

    if ( ent_saves_spell( level, ent, DAM_POISON )
	|| number_bits( 1 ) == 0 )
	return fFAIL;

    if ( ( obj = get_eq_char( victim, ITEM_HOLD ) ) )
    {
        if ( IS_OBJ_STAT( obj, ITEM_VAMPIRE_BANE )
	    && entGetNivel(caster) < 21 )
	    return fERROR;
	else
	{
	    if ( IS_OBJ_STAT( obj, ITEM_ANTI_EVIL ) )
	    {
	        if ( entGetNivel(caster) < 32 )
		{
		    return fERROR;
		}
		else
		{
		    if ( entGetNivel(ent) > entGetNivel(caster) )
		        return fERROR;
		}
	    }
	}
    }
		  
    af.where	 = TO_AFFECTS2;
    af.type      = sn;
    af.duration  = UMAX( 5, 30 - level );
    af.location  = APPLY_NONE;
    af.level     = level;
    af.modifier  = 0;
    af.bitvector = AFF_VAMP_BITE;
    affect_join( victim, &af );

    if ( !entComparar(caster, ent) )
	send_to_ent( "Ahh!  Taste the power!\n\r", caster );
    send_to_char( "Your blood begins to burn!\n\r", victim );
    return fOK;
}

SPELL_FUN_DEC(spell_turn_undead)
{
    CHAR_DATA  *victim;

    CHECKENT()

    if (   entGetNivel(ent) >= level
	|| ent_saves_spell( level, ent, DAM_OTHER ) )
    {
        send_to_ent( "You have failed.\n\r", caster );
	return fFAIL;
    }

    if ( (victim->race == RACE_VAMPIRE) || IS_SET(victim->form, FORM_UNDEAD) )
    	do_flee( victim, "" );

    return fOK;
}

SPELL_FUN_DEC(spell_exorcise)
{
    CHAR_DATA *victim;

    CHECKENT()

    if ( !ent_is_affected( ent, gsn_vampiric_bite )
    &&  (!IS_IMMORTAL(victim) || !ent_is_affected( ent, gsn_stake )) )
    {
    	nact( "$N no necesita un exorcismo.", caster, NULL, ent, TO_CHAR );
        return fERROR;
    }

    /*
     * We actually give the vampiric curse a chance to save
     * at the victim's level
     */
    if ( ent_saves_spell( level, ent, DAM_POISON ) )
    {
    	send_to_ent( "No pasa nada.\n\r", caster );
	return fFAIL;
    }

    affect_strip( victim, gsn_vampiric_bite );

    if ( IS_IMMORTAL(victim) )
    	affect_strip( victim, gsn_stake );

    send_to_ent( "Ok.\n\r",                                    caster     );
    send_to_char( "A warm feeling runs through your body.\n\r", victim );
    nact( "$N looks better.", caster, NULL, ent, TO_NOTVICT );

    strip_mem_char( victim, MEM_VAMPIRE );

    return fOK;
}

SPELL_FUN_DEC(spell_mute)
{
    CHAR_DATA  *victim;
    AFFECT_DATA af;

    CHECKENT()

    if ( IS_AFFECTED2( victim, AFF_MUTE )
	|| ent_saves_spell( level - 4, ent, DAM_OTHER ) )
    {
	send_to_ent( "Pronunciaste mal una silaba.\n\r", caster );
	return fFAIL;
    }

    af.where	 = TO_AFFECTS2;
    af.level	 = level - 2;
    af.type      = sn;
    af.duration  = level / 8;
    af.location  = 0;
    af.modifier  = 0;
    af.bitvector = AFF_MUTE;
    affect_to_ent( ent, &af );
    
    nact( "You have silenced $N!", caster, NULL, ent, TO_CHAR    );
    nact( "$n has silenced you!",  caster, NULL, ent, TO_VICT    );
    nact( "$n has silenced $N!",   caster, NULL, ent, TO_NOTVICT );

    if ( ent_is_npc(ent) && IS_MOB_MAGIC(victim) )
    	SET_BIT(victim->act, ACT_WIMPY);

    return fOK;
}

SPELL_FUN_DEC(spell_amnesia)
{
   CHAR_DATA *victim;
   AFFECT_DATA af;

   CHECKENT()

   if ( IS_AFFECTED2( victim, AFF_AMNESIA)
     || ent_saves_spell( level, ent, DAM_MENTAL ) )
     return fFAIL;
   
   af.where	= TO_AFFECTS2;
   af.level	= level;
   af.type	= sn;
   af.duration	= level / 4;
   af.location	= 0;
   af.modifier	= 0;
   af.bitvector	= AFF_AMNESIA;
   affect_to_ent( ent, &af );

   nact( "No recuerdas nada!", caster, NULL, ent, TO_VICT );
   nact( "$N parece estar muy confundido.", caster, NULL, ent, TO_CHAR );
   nact( "$N parece estar muy confundido.", caster, NULL, ent, TO_NOTVICT );

   return fOK;
}

SPELL_FUN_DEC(spell_levantar_muertos)
{
    OBJ_DATA *obj;
    CHAR_DATA *mob;
    int i;
    char buf[MAX_STRING_LENGTH];
    AFFECT_DATA af;
    CHAR_DATA *ch;

    CHECKCH()

    obj = ent_get_obj_here( caster, target_name );

    if ( obj == NULL )
    {
        send_to_ent( "Resucitar que?\n\r", caster );
        return fERROR;
    }

    /* Nothing but NPC corpses. */
    if( obj->item_type != ITEM_CORPSE_NPC )
    {
        if( obj->item_type == ITEM_CORPSE_PC )
            send_to_ent( "No puedes resucitar jugadores.\n\r", caster );
        else
            send_to_ent( "No serviria para nada...\n\r", caster );
        return fERROR;
    }

    if( obj->value[3] == MOB_VNUM_ZOMBIE )
    {
    	send_to_ent( "No puedes resucitar un zombie!\n\r", caster );
    	return fERROR;
    }

    if( obj->level > (entGetNivel(caster) + 2) )
    {
        send_to_ent( "No puedes traer de vuelta a un espiritu tan poderoso.\n\r", caster );
        return fERROR;
    }

    if ( obj->level < 5 )
    {
    	send_to_ent( "Ese espiritu es demasiado debil.\n\r", caster );
    	return fERROR;
    }

    if( entGetPet(caster) != NULL )
    {
        send_to_ent( "Ya tienes una mascota.\n\r", caster );
        return fERROR;
    }

    /* Chew on the zombie a little bit, recalculate level-dependant stats */

    mob = create_mobile( get_mob_index( MOB_VNUM_ZOMBIE ) );

    sprintf( buf, "zombie %s", obj->name );
    free_string(mob->name);
    mob->name = str_dup(buf);

    sprintf(buf,"Un zombie de %s esta aqui, esperando a su maestro.\n\r",obj->short_descr);
    free_string(mob->long_descr);
    mob->long_descr = str_dup(buf);

    sprintf(buf,"un zombie de %s",obj->short_descr);
    free_string(mob->short_descr);
    mob->short_descr = str_dup(buf);

    setClasePr(mob, CHANCE(80) ? CLASS_WARRIOR : CLASS_CLERIC, obj->level - 2);

    mob->max_hit                = getNivelPr(mob) * 8 + number_range(
                                        getNivelPr(mob) * getNivelPr(mob)/4,
                                        getNivelPr(mob) * getNivelPr(mob));
    mob->max_hit				= (int) (mob->max_hit * .9);
    mob->hit                    = mob->max_hit;
    mob->max_mana               = 100 + dice(getNivelPr(mob),10);
    mob->mana                   = mob->max_mana;
    for (i = 0; i < 3; i++)
        mob->armor[i]           = interpolate(getNivelPr(mob),100,-100);
    mob->armor[3]               = interpolate(getNivelPr(mob),100,0);

    for (i = 0; i < MAX_STATS; i++)
        mob->perm_stat[i] = 11 + getNivelPr(mob)/4;

    mob->damage[DICE_NUMBER]	= recval_table[getNivelPr(mob)].numdam;
    mob->damage[DICE_TYPE]	= recval_table[getNivelPr(mob)].typdam;

    /* You rang? */
    char_to_room( mob, entWhereIs(caster) );
    nact( "$p vuelve a la vida como un zombie!", caster, objToEnt(obj), NULL, TO_ROOM );
    nact( "$p vuelve a la vida como un zombie!", caster, objToEnt(obj), NULL, TO_CHAR );

    extract_obj(obj, TRUE);

    /* Yessssss, massssssster... */
    af.where		= TO_AFFECTS;
    af.level		= level;
    af.type		= sn;
    af.duration		= level;
    af.location		= 0;
    af.modifier		= 0;
    af.bitvector	= AFF_CHARM;
    af.caster_id	= entGetId(caster);
    affect_to_char( mob, &af );

    SET_BIT(mob->act, ACT_PET);
    mob->timer	= level;
    add_follower( mob, ch );
    mob->leader	= ch;
    ch->pet = mob;
    /* For a little flavor... */
    REMOVE_BIT(mob->comm, COMM_NOCHANNELS);
    do_say( mob, "Como puedo servirte, maestro?" );
    mob->comm	= COMM_NOTELL|COMM_NOSHOUT|COMM_NOCHANNELS;
    return fOK;
}

SPELL_FUN_DEC(spell_creature_bond)
{
	CHAR_DATA *victim;
	CHAR_DATA *master;

	CHECKENT()

	if ( !IS_NPC( victim ) || !IS_AFFECTED( victim, AFF_CHARM ) )
	{
		send_to_ent( "Esa criatura no esta encantada!\n\r", caster );
		return fERROR;
	}

	master = victim->master ? victim->master : victim;

	if ( master && entGetNivel(caster) < getNivelPr(master) - 20 )
	{
		send_to_ent( "The current bond is too strong for you to overcome.\n\r", caster );
		return fERROR;
	}

	if ( number_range( 0, 105 ) < ( level + entGetNivel(caster) - getNivelPr(master) ) )
	{
		if ( ent_saves_spell( level, ent, DAM_CHARM ) )
		{
			do_say( victim, "Como te atreves!, yo ADORO a mi maestro!" );
			ent_multi_hit( ent, caster, TYPE_UNDEFINED );
			return fFAIL;
		}
		stop_follower( victim );
		SET_BIT( victim->act, ACT_PET );
		SET_BIT( victim->affected_by, AFF_CHARM );
		victim->timer = level / 3;
		ent_add_follower( ent, caster );
	}
	else
	{
		do_say( victim, "Como te atreves!, yo ADORO a mi maestro!" );
		ent_multi_hit( ent, caster, TYPE_UNDEFINED );
		return fFAIL;
	}

	return fOK;
}

SPELL_FUN_DEC(spell_corrupt_bond)
{
	CHAR_DATA *victim;
	CHAR_DATA *master = NULL;

	CHECKENT()

	if ( !IS_NPC( victim ) || !IS_AFFECTED( victim, AFF_CHARM ) )
	{
		send_to_ent( "Esa criatura no esta encantada!\n\r", caster );
		return fERROR;
	}

	master = victim->master ? victim->master : victim;

	if ( entGetNivel(caster) < getNivelPr(master) - 20 )
	{
		send_to_ent( "The current bond is too strong for you to corrupt.\n\r", caster );
		return fERROR;
	}

	if ( number_percent() < level + entGetNivel(caster) - getNivelPr(master) )
	{
		if ( ent_saves_spell( level, ent, DAM_CHARM ) )
		{
			do_say( victim, "Como te atreves!, yo ADORO a mi maestro!" );
			ent_multi_hit( ent, caster, TYPE_UNDEFINED );
			return fFAIL;
		}

		stop_follower( victim );
		if ( victim->in_room == master->in_room )
		{
			do_say( victim, "Ahora podre vengarme por el encantamiento!!!" );
			multi_hit( victim, master, TYPE_UNDEFINED );
			return fOK;
		}
		else
		{
			do_say( victim, "AARRGH!  ODIO estar encantado! Ahora tendre mi #BVENGANZA#b!" );
			set_hunt( victim, master, FALSE );
			return fOK;
		}
	}
	else
	{
		do_say( victim, "Como te atreves!, yo ADORO a mi maestro!" );
		ent_multi_hit( ent, caster, TYPE_UNDEFINED );
		return fFAIL;
	}

	return fOK;
}

SPELL_FUN_DEC(spell_mystic_armor)
{
   CHAR_DATA *victim;
   AFFECT_DATA af;

   CHECKENT()

   if ( entComparar(caster, ent) )
   {
       send_to_ent( "You are mystically armoured, but it suddenly fades away!\n\r", caster );
       return fERROR;
   }

    if ( ent_is_affected( ent, sn ) )
         return fERROR;

    af.where		= TO_AFFECTS;
    af.type		= sn;
    af.duration		= 4 + (level/3);
    af.location		= APPLY_AC;
    af.modifier		= -10;
    af.bitvector	= 0;
    af.level		= level;
    affect_to_ent( ent, &af );

    nact( "$N is surrounded by your mystic armour.", caster, NULL, ent, TO_CHAR );
    nact( "You are surrounded by $n's mystic armour.", caster, NULL, ent, TO_VICT );
    nact( "$N is surrounded by $n's mystic armour.", caster, NULL, ent, TO_NOTVICT );

    return fOK;
}

SPELL_FUN_DEC(spell_stalker)
{
   /* Fixed problem of stalker not finding victim, and attacking caster,
    * thus giving an easy source of xp -S-
    */

   CHAR_DATA *victim;
   CHAR_DATA *stalker;

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

   victim = ent_get_char_world( caster, target_name );

   if ( victim == NULL )
   {
      send_to_ent( "Target can't be found!\n\r", caster );
      return fERROR;
   }

   if ( entComparar(caster, chToEnt(victim)) )
   {
      send_to_ent( "That WOULDN'T be wise!\n\r", caster );
      return fERROR;
   }

   nact( "$n calls upon the dark powers to summon forth a Stalker!", caster, NULL, NULL, TO_ROOM );
   send_to_ent( "You call upon the dark powers to summon forth a Stalker!\n\r", caster );

   stalker = create_mobile( get_mob_index( MOB_VNUM_STALKER ) );

   char_to_room( stalker, entWhereIs(caster) );
   act( "$n appears before you suddenly.", stalker, NULL, NULL, TO_ROOM );

   setNivelPr(stalker,getNivelPr(victim));
   stalker->max_hit	= victim->max_hit;
   stalker->hit		= victim->max_hit;
   stalker->exp		= getNivelPr(victim)*10;
   stalker->timer	= 10;

   if ( can_hunt( stalker, victim, TRUE ) )
   {
	act( "$n sniffs the air in search of $s prey.", stalker, NULL, NULL, TO_ROOM );
	set_hunt( stalker, victim, TRUE );
   }
   else
   {
	(*skill_table[sn].spell_fun) (sn, getNivelPr(stalker), chToEnt(stalker), caster, TARGET_CHAR );

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

   return fOK;
}

SPELL_FUN_DEC(spell_hellspawn)
{
   /* High level mag / psi spell. -S- */
   CHAR_DATA *victim;
   int dam;

   CHECKENT()

   dam = number_range( level * 2, level * 6 );

   if (ent_saves_spell( level, ent, DAM_NEGATIVE ) )
      dam /= 2;

   act( "The Dark Powers of the HellSpawn strike $n!!", victim, NULL, NULL, TO_ROOM );
   send_to_char( "The Dark Powers of the HellSpawn strike you!!\n\r", victim );
   return newdamage( caster, victim, dam, sn, DAM_NEGATIVE, TRUE );
}

void room_fire_effect( EVENT *ev )
{
	ROOM_INDEX_DATA *room = ev->item.room;
	CHAR_DATA *ch, *ch_next;
	int dam;

	if (!IS_SET(room->room_flags, ROOM_FLAMING)
	||   IS_SET(room->room_flags, ROOM_PROTOTIPO))
		return;

	for ( ch = room->people; ch; ch = ch_next )
	{
		ch_next = ch->next_in_room;
		if ( !ES_IMMUNE(ch, IMM_FIRE) && !is_affected(ch,skill_lookup("fireproof")) )
		{
			send_to_char( "Las llamas te rodean...tu piel arde!\n\r", ch );
			fire_effect( ch, getNivelPr(ch), (dam = dice(5,6)), TARGET_CHAR );
			damage( ch, ch, dam, 0, DAM_FIRE, FALSE );
		}
		if ( !char_died(ch) && IS_NPC(ch) )
		{
			int blah = mob_best_door(ch);

			if (blah != -1)
				move_char( ch, blah, FALSE );
		}
	}

	if ( IS_SET(room->room_flags, ROOM_FLAMING) )
		room_event_add( room, 4*PULSE_PER_SECOND, 0, room_fire_effect );
}

void raise_affect( EVENT *ev )
{
	ROOM_INDEX_DATA *room = ev->item.room;
	AFFECT_DATA af;
	int level = (int) ev->param;

	if ( IS_SET(room->room_flags, ROOM_FLAMING) )
		return;

	af.where	= TO_ROOM_AFF;
	af.type		= skill_lookup( "raise fire" );
	af.level	= level;
	af.duration	= level / 10;
	af.modifier	= 0;
	af.location	= APPLY_NONE;
	af.bitvector	= ROOM_FLAMING;
	affect_to_room( room, &af );

	send_to_room( "El cuarto arde en llamas.", room );
	room_event_add( room, 4*PULSE_PER_SECOND, 0, room_fire_effect );
}

SPELL_FUN_DEC(spell_raise_fire)
{
	if ( IS_SET(entWhereIs(caster)->room_flags, ROOM_SAFE)
	|| IS_SET(entWhereIs(caster)->room_flags, ROOM_LAW) )
	{
		send_to_ent( "No puedes hacer eso aqui.\n\r", caster );
		return fERROR;
	}

	nact( "Alzas tus manos e invocas las llamas del averno.", caster, NULL, NULL,  TO_CHAR );
	nact( "$n alza sus manos e invoca las llamas del averno.", caster, NULL, NULL, TO_ROOM );

	room_event_add( entWhereIs(caster), skill_table[sn].beats, (void *) level, raise_affect );
	return fOK;
}

void cone_msg( EVENT *ev )
{
	ROOM_INDEX_DATA *room = ev->item.room;
	AFFECT_DATA af;
	int level = (int) ev->param;

	if ( IS_SET(room->room_flags, ROOM_CONE_OF_SILENCE) )
		return;

	af.where	= TO_ROOM_AFF;
	af.type		= skill_lookup( "cone of silence" );
	af.level	= level;
	af.duration	= level / 10;
	af.modifier	= 0;
	af.location	= APPLY_NONE;
	af.bitvector	= ROOM_CONE_OF_SILENCE;
	affect_to_room( room, &af );

	if ( room->people )
		act( "Un cono de silencio cae sobre el cuarto.", room->people, 0, 0, TO_ALL );
}

SPELL_FUN_DEC(spell_cone_of_silence)
{
	if ( IS_SET(entWhereIs(caster)->room_flags, ROOM_SAFE)
	  || IS_SET(entWhereIs(caster)->room_flags, ROOM_LAW) )
	{
		send_to_ent( "No puedes hacer eso aqui.\n\r", caster );
		return fERROR;
	}

	nact( "$n recita unas palabras en un idioma incomprensible.", caster, NULL, NULL, TO_ROOM );
	nact( "Recitas las palabras ocultas.", caster, NULL, NULL, TO_CHAR );

	room_event_add( entWhereIs(caster), skill_table[sn].beats, (void *) level, cone_msg );
	if ( entEsCh(caster) )
	{
		char_event_add( entGetCh(caster), skill_table[sn].beats, (void *) "Terminas de recitar.\n\r", stc_event );
		char_event_add( entGetCh(caster), skill_table[sn].beats, (void *) "$n termina de recitar.", to_room_act_event );
	}
	return fOK;
}

SPELL_FUN_DEC(spell_acid_arrow)
{
	CHAR_DATA *victim;
	int dam;

	CHECKENT()

	dam = dice(2,4) + level;

	if ( ent_saves_spell( level, ent, DAM_ACID ) )
		dam /= 2;

	nact( "$n te lanza una flecha acida!", caster, NULL, ent, TO_VICT );
	nact( "$n lanza una flecha acida hacia $N.", caster, NULL, ent, TO_NOTVICT );
	nact( "Lanzas una flecha acida hacia $N!", caster, NULL, ent, TO_CHAR );
	
	acid_effect( victim, level, DAM_ACID, TARGET_CHAR );
	return newdamage( caster, victim, dam, sn, DAM_ACID, TRUE );
}

void ehealth_event( EVENT *ev )
{
	CHAR_DATA *victim = ev->item.ch;
	CHAR_DATA *ch = (long) (ev->param > 0) ? get_char_from_id( (long) ev->param ) : victim;
	AFFECT_DATA af;

	if ( (ch == NULL) || (ch->in_room != victim->in_room) )
		return;

	if (is_affected(victim, gsn_enhance_health))
	{
		if ( ch != victim )
			act( "$N ya se siente #BPODEROS$t#b.", ch, strToEnt(USTRSEX(victim),ch->in_room), chToEnt(victim), TO_CHAR );
		else
			send_to_char( "Ya te sientes #BPODEROSO#b.\n\r", ch );
		return;
	}

	af.where	= TO_AFFECTS;
	af.type		= gsn_enhance_health;
	af.level	= getNivelPr(ch);
	af.duration	= getNivelPr(ch) / 2;
	af.modifier	= getNivelPr(ch) + getNivelPr(victim);
	af.location	= APPLY_HIT;
	af.bitvector	= 0;
	af.caster_id	= ch->id;
	affect_to_char( victim, &af );

	act( "Te sientes mas #BPODEROS$t#b.", victim, strToEnt(USTRSEX(victim),victim->in_room), NULL, TO_CHAR );
	act( "$n se siente mas #BPODEROS$t#b.", victim, strToEnt(USTRSEX(victim),victim->in_room), NULL, TO_ROOM );

	return;
}

SPELL_FUN_DEC(spell_enhance_health)
{
	CHAR_DATA *victim;
	Entity * blah;

	CHECKENT()

	if ( !entComparar(caster, ent) )
	{
		nact( "$n mira a $N y empieza a hacer movimientos extranos con las manos.", caster, NULL, ent, TO_NOTVICT );
		nact( "$n te mira y empieza a hacer movimientos extranos con las manos.", caster, NULL, ent, TO_VICT );
		nact( "Miras a $N y empiezas a hacer movimientos extranos con las manos.", caster, NULL, ent, TO_CHAR );
	}
	else
	{
		nact( "$n empieza a hacer movimientos extranos con las manos.", caster, NULL, NULL, TO_ROOM );
		nact( "Empiezas a hacer movimientos extranos con las manos.", caster, 0, 0, TO_CHAR );
	}

	blah = entCopiar( caster );

	ent_event_add( blah, skill_table[sn].beats, (void *) "Tus movimientos terminan.\n\r", ent_stc_event );
	ent_event_add( blah, skill_table[sn].beats + 1, NULL, ent_free_event );

	char_event_add( victim, skill_table[sn].beats, (void *) entGetId(caster), ehealth_event );

	return fOK;
}

void emana_event( EVENT *ev )
{
	CHAR_DATA *ch = ev->item.ch;
	AFFECT_DATA af;

	if (is_affected(ch, gsn_concentracion))
	{
		send_to_char( "Ya estas concentrado.\n\r", ch );
		return;
	}

	af.where	= TO_AFFECTS;
	af.type		= gsn_concentracion;
	af.level	= getNivelPr(ch);
	af.duration	= getNivelPr(ch);
	af.modifier	= 10 + getNivelPr(ch) * 2;
	af.location	= APPLY_MANA;
	af.bitvector	= 0;
	af.caster_id	= ch->id;
	affect_to_char( ch, &af );
	send_to_char( "Te concentras al maximo.\n\r", ch );
	act( "$n se concentra al maximo.", ch, 0, 0, TO_ROOM );
	return;
}

SPELL_FUN_DEC(spell_concentracion)
{
	nact( "$n empieza a concentrarse.", ent ? ent : caster, NULL, NULL, TO_ROOM );
	nact( "Empiezas a concentrarte.", ent ? ent : caster, 0, 0, TO_CHAR );

	if ( entEsCh(caster) )
		char_event_add( entGetCh(caster), skill_table[sn].beats, 0, emana_event );
	else
	if ( entEsCh(ent) )
		char_event_add( entGetCh(ent), skill_table[sn].beats, 0, emana_event );

	return fOK;
}

SPELL_FUN_DEC(spell_estupidez)
{
	CHAR_DATA *victim;
	AFFECT_DATA af;
	int mod1, mod2, modx;

	CHECKENT()

	if ( IS_AFFECTED2( victim, AFF_ESTUPIDEZ ) )
	{
		if ( !entComparar(caster, ent) )
			nact( "$N ya es un estupido.", caster, NULL, ent, TO_CHAR );
		else
			send_to_ent( "Ya eres un estupido.\n\r", caster );
		return fERROR;
	}

	if ( ent_saves_spell( level, ent, DAM_MENTAL ) )
	{
		send_to_char( "Te sientes un poco mas tonto, pero te recuperas.\n\r", victim );
		act( "$n se pone un poco mas tonto, pero se recupera.", victim, 0, 0, TO_ROOM );
		return fFAIL;
	}

	mod1 = 10 - get_curr_stat( victim, STAT_INT );
	mod2 = - (level / 3);

	modx = mod1 < mod2 ? mod2 : mod1;

	if ( modx >= 0 )
		modx = -1;

	af.type		= sn;
	af.where	= TO_AFFECTS2;
	af.level	= level;
	af.duration	= level;
	af.modifier	= modx;
	af.location	= APPLY_INT;
	af.bitvector	= AFF_ESTUPIDEZ;
	affect_to_ent( ent, &af );

	nact( "$N empieza a babear.", caster, NULL, ent, TO_NOTVICT );
	if (!entComparar(caster, ent))
		nact( "$N empieza a babear.", caster, NULL, ent, TO_CHAR );
	nact( "Ahhhh....peleeeaa....cerveza....", caster, NULL, ent, TO_VICT );

	return fOK;
}

/* Flame shield spell from Malice of EnvyMud */
SPELL_FUN_DEC(spell_flaming_shield)
{
    AFFECT_DATA af;

    if ( ent_IS_AFFECTED2( ent, AFF_FLAMING_SHIELD ) )
    {
    	if ( entComparar(ent, caster) )
		send_to_ent( "El fuego ya te rodea.\n\r", caster );
	else
		nact( "El fuego ya rodea a $N.", caster, NULL, ent, TO_CHAR );
        return fERROR;
    }

    af.type      = sn;
    af.level	 = level;
    af.where	 = TO_AFFECTS2;
    af.duration  = number_fuzzy( level / 8 );
    af.location  = APPLY_NONE;
    af.modifier  = 0;
    af.bitvector = AFF_FLAMING_SHIELD;
    affect_to_ent( ent, &af );

    send_to_ent( "Un escudo de fuego te rodea.\n\r", ent );
    nact( "$n es rodeado por un escudo de fuego.",
	ent, NULL, NULL, TO_ROOM );

    return fOK;
}

SPELL_FUN_DEC(spell_random_bueno)
{
	int uno = 0, temp = -1, num;
	char *spell = NULL;

	while( CHANCE(100 - uno*25) )
	{
		num = number_range(0,10);

		switch(num)
		{
			case 0:	spell = "cure light";		break;
			case 1: spell = "cure serious";		break;
			case 2: spell = "cure critical";	break;
			case 3: spell = "cure blindness";	break;
			case 4: spell = "cure disease";		break;
			case 5: spell = "cure poison";		break;
			case 6: spell = "heal";			break;
			case 7: spell = "sanctuary";		break;
			case 8: spell = "haste";		break;
			case 9: spell = "giant strength";	break;
			case 10: spell = "armor";		break;
		}

		temp = skill_lookup( spell );

		if ( temp > 0 )
			return (*skill_table[temp].spell_fun) (temp,level,caster,caster,TARGET_CHAR);

		uno++;
	}

	return fFAIL;
}

SPELL_FUN_DEC(spell_alucinar)
{
	CHAR_DATA *victim;

	CHECKENT()

	if ( ent_saves_spell( level, ent, DAM_MENTAL ) )
		return fFAIL;

	send_to_char( "Uhhh...sientes que empiezas a flotar!\n\r", victim );
	act( "$n pone cara de volado.", victim, NULL, NULL, TO_ROOM );

	return fOK;
}

SPELL_FUN_DEC(spell_power_word_of_kill)
{
	CHAR_DATA *victim;

	CHECKENT()

	if ( entComparar(caster, ent) )
	{
		send_to_ent( "No seas ridiculo!\n\r", caster );
		return fERROR;
	}

	nact( "Invocas el poder de $t para destruir a $N!", caster, strToEnt(entGetClanGod(caster),entWhereIs(caster)), ent, TO_CHAR );
	nact( "$n invoca el poder de $t para destruirte!", caster, strToEnt(entGetClanGod(caster),entWhereIs(caster)), ent, TO_VICT );
	nact( "$n invoca el poder de $t para destruir a $N!", caster, strToEnt(entGetClanGod(caster),entWhereIs(caster)), ent, TO_NOTVICT );

	if ( !ent_is_npc(ent) || ent_saves_spell( level, ent, DAM_HOLY ) )
	{
		send_to_ent( "Nada pasa.\n\r", caster );
		return fFAIL;
	}

	act( "El poder de $t #BDESTRUYE#b a $n.", victim, strToEnt(entGetClanGod(caster),victim->in_room), NULL, TO_ROOM );
	extract_char( victim, TRUE );

	return victdead;
}

SPELL_FUN_DEC(spell_regeneracion)
{
	AFFECT_DATA af;

	if ( ent_is_affected(ent, sn) || ent_IS_AFFECTED(ent, AFF_REGENERATION) )
	{
		if (entComparar(caster,ent))
			send_to_ent( "Ya te estas regenerando mas rapidamente.\n\r", caster );
		else
			nact( "$N ya se esta regenerando rapidamente.", caster, NULL, ent, TO_CHAR );
		return fERROR;
	}

	af.where	= TO_AFFECTS;
	af.level	= level;
	af.type		= sn;
	af.bitvector	= AFF_REGENERATION;
	af.duration	= 2 + level / 2;
	af.modifier	= 0;
	af.location	= APPLY_NONE;
	affect_to_ent( ent, &af );

	send_to_ent( "Tu metabolismo se acelera.\n\r", ent );
	nact( "Las heridas de $n cicatrizan mas rapidamente.", ent, NULL, NULL, TO_ROOM );
	return fOK;
}

SPELL_FUN_DEC(spell_web)
{
	CHAR_DATA *victim;
	AFFECT_DATA af;

	CHECKENT()

	if ( IS_AFFECTED2(victim, AFF_HOLD) || ent_is_affected(ent, sn) )
	{
		nact( "$N ya esta enredado.", caster, 0, ent, TO_CHAR );
		return fERROR;
	}

	if ( ent_saves_spell( level, ent, DAM_OTHER) )
	{
		send_to_ent( "Nada sucede.\n\r", caster );
		return fFAIL;
	}

	af.where	= TO_AFFECTS2;
	af.type		= sn;
	af.level	= level;
	af.bitvector	= AFF_HOLD;
	af.duration	= 1 + level / 8;
	af.location	= APPLY_NONE;
	af.modifier	= 0;
	affect_to_ent( ent, &af );

	act( "Una telarana magica cae sobre $n!", victim, 0, 0, TO_ROOM );
	act( "Una telarana magica cae sobre ti!", victim, 0, 0, TO_CHAR );

	return fOK;
}

SPELL_FUN_DEC(spell_cansancio)
{
	CHAR_DATA *victim;

	CHECKENT()

	if ( ent_saves_spell( level, ent, DAM_MENTAL ) )
		return fFAIL;

	send_to_char( "Te estas quedando dormido.\n\r", victim );
	act( "$n empieza a cabecear.", victim, NULL, NULL, TO_ROOM );

	return fOK;
}

SPELL_FUN_DEC(spell_polymorph)
{
	Entity * victim;
	bool found = FALSE;
	int race = 0;
	char raza[MIL];
	AFFECT_DATA af;

	if ( !IS_NULLSTR(target_name) )
	{
		target_name = one_argument( target_name, raza );

		race = race_lookup( raza );

		if ( race == 0 )
		{
			send_to_ent( "Esa raza no existe.\n\r", caster );
			return fERROR;
		}

		if ( !IS_NULLSTR(target_name) )
			victim = chToEnt(ent_get_char_room( caster, target_name ));
		else
			victim = caster;
	}
	else
		victim = caster;

	if ( victim == NULL )
	{
		send_to_ent( "No esta aqui.\n\r", caster );
		return fERROR;
	}

	if ( ent_IS_AFFECTED(victim, AFF_POLYMORPH) )
	{
		if ( entComparar(caster, victim) )
			send_to_ent( "Ya tienes otra forma.\n\r", caster );
		else
			nact( "$n ya tiene otra forma.", victim, NULL, NULL, TO_CHAR );
		return fERROR;
	}

	if ( !entComparar(caster, victim) )
		if ( ent_saves_spell( level, victim, DAM_DISEASE ) )
		{
			send_to_ent( "Nada pasa.\n\r", caster );
			return fFAIL;
		}

	if ( (entComparar(caster, victim) && !ent_saves_spell( level, caster, DAM_DISEASE ))
	||    race == 0 )
		while ( found == FALSE )
		{
			race = number_range( 1, maxrace );

			if ( !race_table[race].pc_race
			||    race_table[race].remort_race
			||    race == entGetRace(victim) )
				continue;

			found = TRUE;
		}

	if ( race == entGetRace(victim) )
	{
		send_to_ent( "Fallaste.\n\r", caster );
		return fERROR;
	}

	af.where	= TO_AFFECTS;
	af.type		= sn;
	af.level	= level;
	af.duration	= level;
	af.modifier	= race - entGetRace(victim);
	af.location	= APPLY_RACE;
	af.bitvector	= AFF_POLYMORPH;
	affect_to_ent( victim, &af );

	nact( "$n se convierte en $t!", victim, strToEnt(race_table[race].name,entWhereIs(victim)), NULL, TO_ROOM );
	nact( "Te sientes extran$o.", victim, NULL, NULL, TO_CHAR );
	return fOK;
}

SPELL_FUN_DEC(spell_respirar_agua)
{
	AFFECT_DATA af;

	if (ent_is_affected(ent, sn)
	||  ent_is_part(ent, PART_AGALLAS) )
	{
		if (entComparar(caster, ent))
			send_to_ent( "Ya puedes respirar agua.\n\r", ent );
		else
			nact( "$N ya puede respirar agua.", caster, ent, NULL, TO_CHAR );
		return fFAIL;
	}

	af.where	= TO_PARTS;
	af.type		= sn;
	af.level	= level;
	af.duration	= level;
	af.modifier	= 0;
	af.location	= APPLY_NONE;
	af.bitvector	= PART_AGALLAS;
	affect_to_ent( ent, &af );

	if (!entComparar(caster, ent))
		send_to_ent( "Ok.\n\r", caster);

	send_to_ent( "Sientes que el agua puede fluir por tus pulmones.\n\r", ent );
	return fOK;
}