/* ************************************************************************
*  file: spells2.c , Implementation of magic.             Part of DIKUMUD *
*  Usage : All the non-offensive magic handling routines.                 *
*  Copyright (C) 1990, 1991 - see 'license.doc' for complete information. *
************************************************************************* */

#include <stdio.h>

#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "db.h"
#include "interpreter.h"
#include "spells.h"
#include "handler.h"


/* Global data */

extern struct room_data *world;
extern struct char_data *character_list;
extern struct spell_info_type spell_info[MAX_SPL_LIST];
extern struct obj_data  *object_list;
extern struct zone_data *zone_table;


/* Extern procedures */

void die(struct char_data *ch);
void update_pos( struct char_data *victim );
void damage(struct char_data *ch, struct char_data *victim,
            int damage, int weapontype);
void clone_char(struct char_data *ch);
void say_spell( struct char_data *ch, int si );
bool saves_spell(struct char_data *ch, sh_int spell);
void add_follower(struct char_data *ch, struct char_data *victim);
char *strdup(char *str);


void cast_armor( byte level, struct char_data *ch, char *arg, int type,
	struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
		case SPELL_TYPE_SPELL:
			if ( affected_by_spell(tar_ch, SPELL_ARMOR) ){
				send_to_char("Nothing seems to happen.\n\r", ch);
				return;
			}
			if (ch != tar_ch)
				act("$N is protected by your deity.", FALSE, ch, 0, tar_ch, TO_CHAR);

			spell_armor(level,ch,tar_ch,0);
			break;
		case SPELL_TYPE_POTION:
			if ( affected_by_spell(ch, SPELL_ARMOR) )
				return;
			spell_armor(level,ch,ch,0);
			break;
		case SPELL_TYPE_SCROLL:
			if (tar_obj) return;
         if (!tar_ch) tar_ch = ch;
			if ( affected_by_spell(tar_ch, SPELL_ARMOR) )
				return;
			spell_armor(level,ch,ch,0);
			break;
		case SPELL_TYPE_WAND:
			if (tar_obj) return;
			if ( affected_by_spell(tar_ch, SPELL_ARMOR) )
				return;
			spell_armor(level,ch,ch,0);
			break;
      default : 
         log("Serious screw-up in armor!");
         break;
	}
}



void cast_teleport( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
		case SPELL_TYPE_SCROLL:
		case SPELL_TYPE_POTION:
    case SPELL_TYPE_SPELL:
			if (!tar_ch)
				tar_ch = ch;
			spell_teleport(level, ch, tar_ch, 0);
			break;

		case SPELL_TYPE_WAND:
			if(!tar_ch) return;
			spell_teleport(level, ch, tar_ch, 0);
			break;

		case SPELL_TYPE_STAFF:
			for (tar_ch = world[ch->in_room].people ; 
					tar_ch ; tar_ch = tar_ch->next_in_room)
				if (tar_ch != ch) 
					spell_teleport(level, ch, tar_ch, 0);
			break;
			
		default: 
			log("Serious screw-up in teleport!");
			break;
	}
}


void cast_bless( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
	struct affected_type af;

  switch (type) {
    case SPELL_TYPE_SPELL:
			if (tar_obj) {        /* It's an object */
				if ( IS_SET(tar_obj->obj_flags.extra_flags, ITEM_BLESS) ) {
					send_to_char("Nothing seems to happen.\n\r", ch);
					return;
				}
				spell_bless(level,ch,0,tar_obj);

			} else {              /* Then it is a PC | NPC */

				if ( affected_by_spell(tar_ch, SPELL_BLESS) ||
					(GET_POS(tar_ch) == POSITION_FIGHTING)) {
					send_to_char("Nothing seems to happen.\n\r", ch);
					return;
				} 
				spell_bless(level,ch,tar_ch,0);
			}
			break;
	 case SPELL_TYPE_POTION:
   		if ( affected_by_spell(ch, SPELL_BLESS) ||
				(GET_POS(ch) == POSITION_FIGHTING))
				return;
			spell_bless(level,ch,ch,0);
         break;
    case SPELL_TYPE_SCROLL:
			if (tar_obj) {        /* It's an object */
				if ( IS_SET(tar_obj->obj_flags.extra_flags, ITEM_BLESS) )
					return;
				spell_bless(level,ch,0,tar_obj);

			} else {              /* Then it is a PC | NPC */

				if (!tar_ch) tar_ch = ch;
				
				if ( affected_by_spell(tar_ch, SPELL_BLESS) ||
					(GET_POS(tar_ch) == POSITION_FIGHTING))
					return;
				spell_bless(level,ch,tar_ch,0);
			}
			break;
    case SPELL_TYPE_WAND:
			if (tar_obj) {        /* It's an object */
				if ( IS_SET(tar_obj->obj_flags.extra_flags, ITEM_BLESS) )
					return;
				spell_bless(level,ch,0,tar_obj);

			} else {              /* Then it is a PC | NPC */

				if ( affected_by_spell(tar_ch, SPELL_BLESS) ||
					(GET_POS(tar_ch) == POSITION_FIGHTING))
					return;
				spell_bless(level,ch,tar_ch,0);
			}
			break;
    default : 
         log("Serious screw-up in bless!");
         break;
	}
}



void cast_blindness( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
	struct affected_type af;

  if (IS_SET(world[ch->in_room].room_flags,SAFE)){
	send_to_char("You can't blind anyone in a safe area!\n\r",ch);
	return;
  }
  switch (type) {
    case SPELL_TYPE_SPELL:
			if ( IS_AFFECTED(tar_ch, AFF_BLIND) ){
				send_to_char("Nothing seems to happen.\n\r", ch);
				return;
			}
			spell_blindness(level,ch,tar_ch,0);
			break;
    case SPELL_TYPE_POTION:
			if ( IS_AFFECTED(ch, AFF_BLIND) )
				return;
			spell_blindness(level,ch,ch,0);
			break;
    case SPELL_TYPE_SCROLL:
         if (tar_obj) return;
         if (!tar_ch) tar_ch = ch;
			if ( IS_AFFECTED(ch, AFF_BLIND) )
				return;
			spell_blindness(level,ch,ch,0);
			break;
    case SPELL_TYPE_WAND:
         if (tar_obj) return;
			if ( IS_AFFECTED(ch, AFF_BLIND) )
				return;
			spell_blindness(level,ch,ch,0);
			break;
    case SPELL_TYPE_STAFF:
         for (tar_ch = world[ch->in_room].people ; 
              tar_ch ; tar_ch = tar_ch->next_in_room)
            if (tar_ch != ch) 
               if (!(IS_AFFECTED(tar_ch, AFF_BLIND)))
                  spell_blindness(level,ch,tar_ch,0);
         break;
    default : 
         log("Serious screw-up in blindness!");
         break;
	}
}


void cast_clone( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
	struct char_data *vict;
	char buf[MAX_STRING_LENGTH];

	send_to_char("Not *YET* implemented.", ch);
	return;

  /* clone both char and obj !!*/

/*
  switch (type) {
    case SPELL_TYPE_SPELL:
			if (tar_ch) {	
				sprintf(buf, "You create a duplicate of %s.\n\r", GET_NAME(tar_ch));
				send_to_char(buf, ch);
				sprintf(buf, "%%s creates a duplicate of %s,\n\r", GET_NAME(tar_ch));
				perform(buf, ch, FALSE);

				spell_clone(level,ch,tar_ch,0);
			} else {
				sprintf(buf, "You create a duplicate of %s %s.\n\r",SANA(tar_obj),tar_obj->short_description);
				send_to_char(buf, ch);
				sprintf(buf, "%%s creates a duplicate of %s %s,\n\r",SANA(tar_obj),tar_obj->short_description);
				perform(buf, ch, FALSE);

				spell_clone(level,ch,0,tar_obj);
			};
			break;


    default : 
         log("Serious screw-up in clone!");
         break;
	}
*/
		 /* MISSING REST OF SWITCH -- POTION, SCROLL, WAND */
}


void cast_control_weather(byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
	int var;
	char buffer[MAX_STRING_LENGTH];
	struct zone_data *zone;

	/*char *variables[] = {"cold","warm","wet","dry","windy","calm"}; */
	char *variables[] = {"cold","warm","wet","dry","windy","calm", "\n"};

	switch (type) {
		case SPELL_TYPE_SPELL:

			one_argument(arg,buffer);

			var=old_search_block(buffer,0,strlen(buffer),variables,0);
			if (var==-1) {
				send_to_char("What kind of weather do you want?\n\r(cold, warm, wet, dry, windy, calm)\n\r",ch);
				return;
			}

			zone=&zone_table[world[ch->in_room].zone];
			if((zone->climate.flags & NON_CONTROLLABLE) ||
			(zone->conditions.flags & WEATHER_CONTROLLED)) {
				send_to_char("Someone seems to have control already of the weather here.\n\r",ch);
				return;
			}

			switch(var-1) {
				case 0: /* cold */
					zone->conditions.temp=MAX(zone->conditions.temp-level/2,-level);
					send_to_zone_outdoor(world[ch->in_room].zone,"The temperature suddenly dips.\n\r");
					break;
				case 1: /* warm */
					zone->conditions.temp=MIN(zone->conditions.temp+level/2,45+level);
					send_to_zone_outdoor(world[ch->in_room].zone,"The temperature suddenly rises.\n\r");
					break;
				case 2: /* wet */
					if(zone->climate.season_precip[get_season(zone)]==SEASON_NO_PRECIP_EVER) {
						send_to_char("There is no moisture in the area!\n\r",ch);
						return;
					}
					if(!zone->conditions.precip_rate) {
						zone->conditions.precip_rate++;
						if(zone->conditions.temp>0)
							send_to_zone_outdoor(world[ch->in_room].zone,"A few drops of rain begin to fall.\n\r");
						else
							send_to_zone_outdoor(world[ch->in_room].zone,"A few flakes of snow begin to fall.\n\r");
					} else {
						zone->conditions.precip_rate+=level;
						if(zone->conditions.temp>0)
							send_to_zone_outdoor(world[ch->in_room].zone,"It rains a bit faster.\n\r");
						else
							send_to_zone_outdoor(world[ch->in_room].zone,"The snow comes down a bit harder.\n\r");
					}
					zone->conditions.humidity=MIN(100,zone->conditions.humidity+level);
					break;
				case 3: /* dry */
					if(!zone->conditions.humidity && !zone->conditions.precip_rate) {
						send_to_char("There's no more moisture left in the air!\n\r",ch);
						return;
					} else {
						if(zone->conditions.precip_rate) {
							zone->conditions.precip_rate=MAX(0,zone->conditions.precip_rate-level);
							if(zone->conditions.precip_rate) {
								if(zone->conditions.temp>0)
									send_to_zone_outdoor(world[ch->in_room].zone,"The rain lets up suddenly.\n\r");
								else
									send_to_zone_outdoor(world[ch->in_room].zone,"The snow comes suddenly lets up a bit.\n\r");
							}
						} else {
							zone->conditions.humidity=MAX(0,zone->conditions.humidity-level);
							send_to_zone_outdoor(world[ch->in_room].zone,"The air feels a bit drier.\n\r");
						}
					}
					break;
				case 4: /* windy */
					zone->conditions.windspeed+=level/2;
					send_to_zone_outdoor(world[ch->in_room].zone,"The wind picks up.\n\r");
					break;
				case 5: /* calm */
					zone->conditions.windspeed-=level;
					if(zone->conditions.windspeed <= 0) {
						zone->conditions.windspeed=0;
						send_to_zone_outdoor(world[ch->in_room].zone,"The air seems to come to a stagnant, dead halt.\n\r");
					} else
						send_to_zone_outdoor(world[ch->in_room].zone,"The wind calms down a bit.\n\r");
					break;
				default:
					break;
			}
			SET_BIT(zone->conditions.flags,WEATHER_CONTROLLED);
			break;
		default: 
			log("Serious screw-up in control weather!");
			break;
	}
}



void cast_create_food( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{

  switch (type) {
    case SPELL_TYPE_SPELL:
			act("$n magically creates a mushroom.",FALSE, ch, 0, 0, TO_ROOM);
         spell_create_food(level,ch,0,0);
			break;
    case SPELL_TYPE_SCROLL:
         if(tar_obj) return;
         if(tar_ch) return;
         spell_create_food(level,ch,0,0);
			break;
    default : 
         log("Serious screw-up in create food!");
         break;
	}
}



void cast_create_water( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
			if (tar_obj->obj_flags.type_flag != ITEM_DRINKCON) {
				send_to_char("It is unable to hold water.\n\r", ch);
				return;
			}
			spell_create_water(level,ch,0,tar_obj);
			break;
      default : 
         log("Serious screw-up in create water!");
         break;
	}
}



void cast_cure_blind( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
			spell_cure_blind(level,ch,tar_ch,0);
			break;
    case SPELL_TYPE_POTION:
			spell_cure_blind(level,ch,ch,0);
			break;
    case SPELL_TYPE_STAFF:
         for (tar_ch = world[ch->in_room].people ; 
              tar_ch ; tar_ch = tar_ch->next_in_room)
            if (tar_ch != ch) 
               spell_cure_blind(level,ch,tar_ch,0);
         break;
    default : 
         log("Serious screw-up in cure blind!");
         break;
	}
}



void cast_cure_critic( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
			spell_cure_critic(level,ch,tar_ch,0);
			break;
    case SPELL_TYPE_POTION:
			spell_cure_critic(level,ch,ch,0);
			break;
    case SPELL_TYPE_STAFF:
         for (tar_ch = world[ch->in_room].people ; 
              tar_ch ; tar_ch = tar_ch->next_in_room)
            if (tar_ch != ch) 
               spell_cure_critic(level,ch,tar_ch,0);
         break;
      default : 
         log("Serious screw-up in cure critic!");
         break;

	}
}



void cast_cure_light( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
      spell_cure_light(level,ch,tar_ch,0);
      break;
    case SPELL_TYPE_POTION:
			spell_cure_light(level,ch,ch,0);
			break;
    case SPELL_TYPE_STAFF:
         for (tar_ch = world[ch->in_room].people ; 
              tar_ch ; tar_ch = tar_ch->next_in_room)
            if (tar_ch != ch) 
               spell_cure_light(level,ch,tar_ch,0);
         break;
    default : 
         log("Serious screw-up in cure light!");
         break;
  }
}


void cast_curse( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  if (IS_SET(world[ch->in_room].room_flags,SAFE)){
	send_to_char("You can't curse someone in a safe area!\n\r",ch);
	return;
  }
  switch (type) {
    case SPELL_TYPE_SPELL:
			if (tar_obj)   /* It is an object */ 
				spell_curse(level,ch,0,tar_obj);
			else {              /* Then it is a PC | NPC */
				spell_curse(level,ch,tar_ch,0);
			}
			break;
    case SPELL_TYPE_POTION:
			spell_curse(level,ch,ch,0);
			break;
    case SPELL_TYPE_SCROLL:
			if (tar_obj)   /* It is an object */ 
				spell_curse(level,ch,0,tar_obj);
			else {              /* Then it is a PC | NPC */
				if (!tar_ch) tar_ch = ch;
				spell_curse(level,ch,tar_ch,0);
			}
			break;
    case SPELL_TYPE_STAFF:
         for (tar_ch = world[ch->in_room].people ; 
              tar_ch ; tar_ch = tar_ch->next_in_room)
            if (tar_ch != ch) 
               spell_curse(level,ch,tar_ch,0);
         break;
    default : 
         log("Serious screw-up in curse!");
         break;
	}
}


void cast_detect_evil( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
			if ( affected_by_spell(tar_ch, SPELL_DETECT_EVIL) ){
				send_to_char("Nothing seems to happen.\n\r", tar_ch);
				return;
			}
			spell_detect_evil(level,ch,tar_ch,0);
			break;
    case SPELL_TYPE_POTION:
			if ( affected_by_spell(ch, SPELL_DETECT_EVIL) )
				return;
			spell_detect_evil(level,ch,ch,0);
			break;
    case SPELL_TYPE_STAFF:
         for (tar_ch = world[ch->in_room].people ; 
              tar_ch ; tar_ch = tar_ch->next_in_room)
            if (tar_ch != ch) 
               if(!(IS_AFFECTED(tar_ch, SPELL_DETECT_EVIL)))
                  spell_detect_evil(level,ch,tar_ch,0);
         break;
    default : 
         log("Serious screw-up in detect evil!");
         break;
	}
}



void cast_detect_invisibility( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
			if ( affected_by_spell(tar_ch, SPELL_DETECT_INVISIBLE) ){
				send_to_char("Nothing seems to happen.\n\r", tar_ch);
				return;
			}
			spell_detect_invisibility(level,ch,tar_ch,0);
			break;
    case SPELL_TYPE_POTION:
			if ( affected_by_spell(ch, SPELL_DETECT_INVISIBLE) )
				return;
			spell_detect_invisibility(level,ch,ch,0);
			break;
    case SPELL_TYPE_STAFF:
         for (tar_ch = world[ch->in_room].people ; 
              tar_ch ; tar_ch = tar_ch->next_in_room)
            if (tar_ch != ch) 
               if(!(IS_AFFECTED(tar_ch, SPELL_DETECT_INVISIBLE)))
                  spell_detect_invisibility(level,ch,tar_ch,0);
         break;
    default : 
         log("Serious screw-up in detect invisibility!");
         break;
	}
}



void cast_detect_magic( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
			if ( affected_by_spell(tar_ch, SPELL_DETECT_MAGIC) ){
				send_to_char("Nothing seems to happen.\n\r", tar_ch);
				return;
			}
			spell_detect_magic(level,ch,tar_ch,0);
			break;
    case SPELL_TYPE_POTION:
			if ( affected_by_spell(ch, SPELL_DETECT_MAGIC) )
				return;
			spell_detect_magic(level,ch,ch,0);
			break;
    case SPELL_TYPE_STAFF:
         for (tar_ch = world[ch->in_room].people ; 
              tar_ch ; tar_ch = tar_ch->next_in_room)
            if (tar_ch != ch) 
               if (!(IS_AFFECTED(tar_ch, SPELL_DETECT_MAGIC)))
                  spell_detect_magic(level,ch,tar_ch,0);
         break;
    default : 
         log("Serious screw-up in detect magic!");
         break;
	}
}



void cast_detect_poison( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
			spell_detect_poison(level, ch, tar_ch,tar_obj);
			break;
    case SPELL_TYPE_POTION:
			spell_detect_poison(level, ch, ch,0);
			break;
    case SPELL_TYPE_SCROLL:
         if (tar_obj) {
				spell_detect_poison(level, ch, 0, tar_obj);
            return;
         }
         if (!tar_ch) tar_ch = ch;
			spell_detect_poison(level, ch, tar_ch, 0);
			break;
    default : 
         log("Serious screw-up in detect poison!");
         break;
	}
}



void cast_dispel_evil( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
			spell_dispel_evil(level, ch, tar_ch,0);
			break;
    case SPELL_TYPE_POTION:
			spell_dispel_evil(level,ch,ch,0);
			break;
    case SPELL_TYPE_SCROLL:
      if (tar_obj) return;
      if (!tar_ch) tar_ch = ch;
			spell_dispel_evil(level, ch, tar_ch,0);
			break;
    case SPELL_TYPE_WAND:
      if (tar_obj) return;
			spell_dispel_evil(level, ch, tar_ch,0);
			break;
    case SPELL_TYPE_STAFF:
         for (tar_ch = world[ch->in_room].people ; 
              tar_ch ; tar_ch = tar_ch->next_in_room)
            if (tar_ch != ch) 
              spell_dispel_evil(level,ch,tar_ch,0);
         break;
    default : 
         log("Serious screw-up in dispel evil!");
         break;
	}
}


void cast_enchant_weapon( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
			spell_enchant_weapon(level, ch, 0,tar_obj);
			break;

    case SPELL_TYPE_SCROLL:
			if(!tar_obj) return;
			spell_enchant_weapon(level, ch, 0,tar_obj);
			break;
    default : 
      log("Serious screw-up in enchant weapon!");
      break;
	}
}


void cast_heal( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
			act("$n heals $N.", FALSE, ch, 0, tar_ch, TO_NOTVICT);
			act("You heal $N.", FALSE, ch, 0, tar_ch, TO_CHAR);
			spell_heal(level, ch, tar_ch, 0);
			break;
    case SPELL_TYPE_POTION:
         spell_heal(level, ch, ch, 0);
         break;
    case SPELL_TYPE_STAFF:
         for (tar_ch = world[ch->in_room].people ; 
              tar_ch ; tar_ch = tar_ch->next_in_room)
            if (tar_ch != ch) 
              spell_heal(level,ch,tar_ch,0);
         break;
    default : 
         log("Serious screw-up in heal!");
         break;
	}
}


void cast_invisibility( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
			if (tar_obj) {
				if ( IS_SET(tar_obj->obj_flags.extra_flags, ITEM_INVISIBLE) )
					send_to_char("Nothing new seems to happen.\n\r", ch);
				else
					spell_invisibility(level, ch, 0, tar_obj);
			} else { /* tar_ch */
				if ( IS_AFFECTED(tar_ch, AFF_INVISIBLE) )
					send_to_char("Nothing new seems to happen.\n\r", ch);
				else
					spell_invisibility(level, ch, tar_ch, 0);
			}
			break;
    case SPELL_TYPE_POTION:
         if (!IS_AFFECTED(ch, AFF_INVISIBLE) )
            spell_invisibility(level, ch, ch, 0);
         break;
    case SPELL_TYPE_SCROLL:
			if (tar_obj) {
				if (!(IS_SET(tar_obj->obj_flags.extra_flags, ITEM_INVISIBLE)) )
					spell_invisibility(level, ch, 0, tar_obj);
			} else { /* tar_ch */
            if (!tar_ch) tar_ch = ch;

				if (!( IS_AFFECTED(tar_ch, AFF_INVISIBLE)) )
					spell_invisibility(level, ch, tar_ch, 0);
			}
			break;
    case SPELL_TYPE_WAND:
			if (tar_obj) {
				if (!(IS_SET(tar_obj->obj_flags.extra_flags, ITEM_INVISIBLE)) )
					spell_invisibility(level, ch, 0, tar_obj);
			} else { /* tar_ch */
				if (!( IS_AFFECTED(tar_ch, AFF_INVISIBLE)) )
					spell_invisibility(level, ch, tar_ch, 0);
			}
			break;
    case SPELL_TYPE_STAFF:
         for (tar_ch = world[ch->in_room].people ; 
              tar_ch ; tar_ch = tar_ch->next_in_room)
            if (tar_ch != ch)
               if (!( IS_AFFECTED(tar_ch, AFF_INVISIBLE)) )
                  spell_invisibility(level,ch,tar_ch,0);
         break;
    default : 
         log("Serious screw-up in invisibility!");
         break;
	}
}




void cast_locate_object( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
	struct obj_data dummy;

	switch (type) {
		case SPELL_TYPE_SPELL:
			for(; *arg && (*arg == ' '); arg++);
			dummy.name=arg;
			spell_locate_object(level, ch, 0, &dummy);
			break;
		default: 
			log("Serious screw-up in locate object!");
			break;
	}
}


void cast_poison( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  if(IS_SET(world[ch->in_room].room_flags,SAFE)){
	send_to_char("You can't poision someone in a safe area!\n\r",ch);
	return;
  }
  switch (type) {
    case SPELL_TYPE_SPELL:
			spell_poison(level, ch, tar_ch, tar_obj);
			break;
    case SPELL_TYPE_POTION:
			spell_poison(level, ch, ch, 0);
			break;
    case SPELL_TYPE_STAFF:
         for (tar_ch = world[ch->in_room].people ; 
              tar_ch ; tar_ch = tar_ch->next_in_room)
            if (tar_ch != ch) 
                  spell_poison(level,ch,tar_ch,0);
         break;
    default : 
         log("Serious screw-up in poison!");
         break;
	}
}


void cast_protection_from_evil( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
			spell_protection_from_evil(level, ch, tar_ch, 0);
			break;
    case SPELL_TYPE_POTION:
         spell_protection_from_evil(level, ch, ch, 0);
         break;
    case SPELL_TYPE_SCROLL:
         if(tar_obj) return;
         if(!tar_ch) tar_ch = ch;
			spell_protection_from_evil(level, ch, tar_ch, 0);
			break;
    case SPELL_TYPE_STAFF:
         for (tar_ch = world[ch->in_room].people ; 
              tar_ch ; tar_ch = tar_ch->next_in_room)
            if (tar_ch != ch) 
                  spell_protection_from_evil(level,ch,tar_ch,0);
         break;
    default : 
         log("Serious screw-up in protection from evil!");
         break;
	}
}


void cast_remove_curse( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
			spell_remove_curse(level, ch, tar_ch, tar_obj);
			break;
    case SPELL_TYPE_POTION:
         spell_remove_curse(level, ch, ch, 0);
         break;
    case SPELL_TYPE_SCROLL:
         if(tar_obj) {
				spell_remove_curse(level, ch, 0, tar_obj);
 				return;
			}
         if(!tar_ch) tar_ch = ch;
			spell_remove_curse(level, ch, tar_ch, 0);
			break;
    case SPELL_TYPE_STAFF:
         for (tar_ch = world[ch->in_room].people ; 
              tar_ch ; tar_ch = tar_ch->next_in_room)
            if (tar_ch != ch) 
                  spell_remove_curse(level,ch,tar_ch,0);
         break;
    default : 
         log("Serious screw-up in remove curse!");
         break;
	}
}



void cast_remove_poison( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
			spell_remove_poison(level, ch, tar_ch, tar_obj);
			break;
    case SPELL_TYPE_POTION:
         spell_remove_poison(level, ch, ch, 0);
         break;
    case SPELL_TYPE_STAFF:
         for (tar_ch = world[ch->in_room].people ; 
              tar_ch ; tar_ch = tar_ch->next_in_room)
            if (tar_ch != ch) 
                  spell_remove_poison(level,ch,tar_ch,0);
         break;
    default : 
         log("Serious screw-up in remove poison!");
         break;
	}
}



void cast_sanctuary( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
			spell_sanctuary(level, ch, tar_ch, 0);
			break;
    case SPELL_TYPE_POTION:
         spell_sanctuary(level, ch, ch, 0);
         break;
    case SPELL_TYPE_SCROLL:
         if(tar_obj)
 				return;
         if(!tar_ch) tar_ch = ch;
			spell_sanctuary(level, ch, tar_ch, 0);
			break;
    case SPELL_TYPE_STAFF:
         for (tar_ch = world[ch->in_room].people ; 
              tar_ch ; tar_ch = tar_ch->next_in_room)
            if (tar_ch != ch) 
                  spell_sanctuary(level,ch,tar_ch,0);
         break;
    default : 
         log("Serious screw-up in sanctuary!");
         break;
	}
}


void cast_sleep( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  if (IS_SET(world[ch->in_room].room_flags,SAFE)){
	send_to_char("You can't sleep someone in a safe area!\n\r",ch);
	return;
  }
  switch (type) {
    case SPELL_TYPE_SPELL:
			spell_sleep(level, ch, tar_ch, 0);
			break;
    case SPELL_TYPE_POTION:
			spell_sleep(level, ch, ch, 0);
			break;
    case SPELL_TYPE_SCROLL:
         if(tar_obj) return;
         if (!tar_ch) tar_ch = ch;
         spell_sleep(level, ch, tar_ch, 0);
         break;
    case SPELL_TYPE_WAND:
         if(tar_obj) return;
         spell_sleep(level, ch, tar_ch, 0);
         break;
    case SPELL_TYPE_STAFF:
         for (tar_ch = world[ch->in_room].people ; 
              tar_ch ; tar_ch = tar_ch->next_in_room)
            if (tar_ch != ch) 
                  spell_sleep(level,ch,tar_ch,0);
         break;
    default : 
         log("Serious screw-up in sleep!");
         break;
	}
}


void cast_strength( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
			spell_strength(level, ch, tar_ch, 0);
			break;
    case SPELL_TYPE_POTION:
			spell_strength(level, ch, ch, 0);
			break;
    case SPELL_TYPE_SCROLL:
         if(tar_obj) return;
         if (!tar_ch) tar_ch = ch;
         spell_strength(level, ch, tar_ch, 0);
         break;
    case SPELL_TYPE_STAFF:
         for (tar_ch = world[ch->in_room].people ; 
              tar_ch ; tar_ch = tar_ch->next_in_room)
            if (tar_ch != ch) 
                  spell_strength(level,ch,tar_ch,0);
         break;
    default : 
         log("Serious screw-up in strength!");
         break;
	}
}


void cast_ventriloquate( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
	struct char_data *tmp_ch;
	char buf1[MAX_STRING_LENGTH];
	char buf2[MAX_STRING_LENGTH];
	char buf3[MAX_STRING_LENGTH];

	if (type != SPELL_TYPE_SPELL) {
		log("Attempt to ventriloquate by non-cast-spell.");
		return;
	}
	for(; *arg && (*arg == ' '); arg++);
	arg=one_argument(arg,buf1);
	if (tar_obj) {
		sprintf(buf1, "The %s says '%s'\n\r", fname(tar_obj->name), arg);
		sprintf(buf2, "Someone makes it sound like the %s says '%s'.\n\r",
		  fname(tar_obj->name), arg);
	}	else {
		sprintf(buf1, "%s says '%s'\n\r", GET_NAME(tar_ch), arg);
		sprintf(buf2, "Someone makes it sound like %s says '%s'\n\r",
		  GET_NAME(tar_ch), arg);
	}

	sprintf(buf3, "Someone says, '%s'\n\r", arg);

	for (tmp_ch = world[ch->in_room].people; tmp_ch;
	  tmp_ch = tmp_ch->next_in_room) {

		if ((tmp_ch != ch) && (tmp_ch != tar_ch)) {
			if ( saves_spell(tmp_ch, SAVING_SPELL) )
				send_to_char(buf2, tmp_ch);
			else
				send_to_char(buf1, tmp_ch);
		} else {
			if (tmp_ch == tar_ch)
				send_to_char(buf3, tar_ch);
		}
	}
}



void cast_word_of_recall( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
			spell_word_of_recall(level, ch, ch, 0);
			break;
    case SPELL_TYPE_POTION:
			spell_word_of_recall(level, ch, ch, 0);
			break;
    case SPELL_TYPE_SCROLL:
         if(tar_obj) return;
         if (!tar_ch) tar_ch = ch;
         spell_word_of_recall(level, ch, tar_ch, 0);
         break;
    case SPELL_TYPE_WAND:
         if(tar_obj) return;
         spell_word_of_recall(level, ch, tar_ch, 0);
         break;
    case SPELL_TYPE_STAFF:
         for (tar_ch = world[ch->in_room].people ; 
              tar_ch ; tar_ch = tar_ch->next_in_room)
            if (tar_ch != ch) 
                  spell_word_of_recall(level,ch,tar_ch,0);
         break;
    default : 
         log("Serious screw-up in word of recall!");
         break;
	}
}



void cast_summon( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
			spell_summon(level, ch, tar_ch, 0);
			break;
      default : 
         log("Serious screw-up in summon!");
         break;
	}
}



void cast_charm_person( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
		case SPELL_TYPE_SPELL:
			spell_charm_person(level, ch, tar_ch, 0);
			break;
      case SPELL_TYPE_SCROLL:
         if(!tar_ch) return;
         spell_charm_person(level, ch, tar_ch, 0);
         break;
      case SPELL_TYPE_STAFF:
         for (tar_ch = world[ch->in_room].people ; 
              tar_ch ; tar_ch = tar_ch->next_in_room)
            if (tar_ch != ch) 
                  spell_charm_person(level,ch,tar_ch,0);
         break;
      default : 
         log("Serious screw-up in charm person!");
         break;
	}
}



void cast_sense_life( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
		case SPELL_TYPE_SPELL:
			spell_sense_life(level, ch, ch, 0);
			break;
      case SPELL_TYPE_POTION:
         spell_sense_life(level, ch, ch, 0);
         break;
      case SPELL_TYPE_STAFF:
         for (tar_ch = world[ch->in_room].people ; 
              tar_ch ; tar_ch = tar_ch->next_in_room)
            if (tar_ch != ch) 
                  spell_sense_life(level,ch,tar_ch,0);
         break;
      default : 
         log("Serious screw-up in sense life!");
         break;
	}
}


void cast_identify( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
		case SPELL_TYPE_SCROLL:
			spell_identify(level, ch, tar_ch, tar_obj);
			break;
		default : 
			log("Serious screw-up in identify!");
			break;
	}
}


void cast_fire_breath( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
			spell_fire_breath(level, ch, tar_ch, 0);
			break;   /* It's a spell.. But people can'c cast it! */
      default : 
         log("Serious screw-up in firebreath!");
         break;
	}
}

void cast_frost_breath( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
			spell_frost_breath(level, ch, tar_ch, 0);
			break;   /* It's a spell.. But people can'c cast it! */
      default : 
         log("Serious screw-up in frostbreath!");
         break;
	}
}

void cast_acid_breath( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
			spell_acid_breath(level, ch, tar_ch, 0);
			break;   /* It's a spell.. But people can'c cast it! */
      default : 
         log("Serious screw-up in acidbreath!");
         break;
	}
}

void cast_gas_breath( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
		for (tar_ch = world[ch->in_room].people ; 
				tar_ch ; tar_ch = tar_ch->next_in_room)
			if (tar_ch != ch) 
				spell_gas_breath(level,ch,tar_ch,0);
         break;
			/* THIS ONE HURTS!! */
      default : 
         log("Serious screw-up in gasbreath!");
         break;
	}
}

void cast_lightning_breath( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
			spell_lightning_breath(level, ch, tar_ch, 0);
			break;   /* It's a spell.. But people can'c cast it! */
      default : 
         log("Serious screw-up in lightningbreath!");
         break;
	}
}

void cast_levitate( byte level, struct char_data *ch, char *arg, int type,
	struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
		case SPELL_TYPE_SPELL:
			if (IS_AFFECTED(tar_ch, AFF_LEVITATE) ){
				send_to_char("Nothing seems to happen.\n\r", ch);
				return;
			}

			spell_levitate(level,ch,tar_ch,0);
			break;
		case SPELL_TYPE_POTION:
			if (IS_AFFECTED (ch, AFF_LEVITATE) )
				return;
			spell_levitate(level,ch,ch,0);
			break;
		case SPELL_TYPE_SCROLL:
			if (tar_obj) return;
			if (!tar_ch) tar_ch = ch;
			if (IS_AFFECTED(tar_ch, AFF_LEVITATE) )
				return;
			spell_levitate(level,ch,ch,0);
			break;
		case SPELL_TYPE_WAND:
			if (tar_obj) return;
			if (IS_AFFECTED(tar_ch, AFF_LEVITATE) )
				return;
			spell_levitate(level,ch,ch,0);
			break;
		case SPELL_TYPE_STAFF:
			for (tar_ch = world[ch->in_room].people ; 
					tar_ch ; tar_ch = tar_ch->next_in_room)
				if (tar_ch != ch && !IS_AFFECTED(tar_ch,AFF_LEVITATE)) 
					spell_fly(level, ch, tar_ch, 0);
			break;
		default: 
			log("Serious screw-up in levitate!");
			break;
	}
}
void cast_fly( byte level, struct char_data *ch, char *arg, int type,
	struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
		case SPELL_TYPE_SPELL:
			if (IS_AFFECTED(tar_ch, AFF_FLY) ){
				send_to_char("Nothing seems to happen.\n\r", ch);
				return;
			}

			spell_fly(level,ch,tar_ch,0);
			break;
		case SPELL_TYPE_POTION:
			if (IS_AFFECTED(ch, AFF_FLY) )
				return;
			spell_fly(level,ch,ch,0);
			break;
		case SPELL_TYPE_SCROLL:
			if (tar_obj) return;
			if (!tar_ch) tar_ch = ch;
			if (IS_AFFECTED(tar_ch, AFF_FLY) )
				return;
			spell_fly(level,ch,ch,0);
			break;
		case SPELL_TYPE_WAND:
			if (tar_obj) return;
			if (IS_AFFECTED(tar_ch, AFF_FLY) )
				return;
			spell_fly(level,ch,ch,0);
			break;
		case SPELL_TYPE_STAFF:
			for (tar_ch = world[ch->in_room].people ; 
					tar_ch ; tar_ch = tar_ch->next_in_room)
				if (tar_ch != ch && !IS_AFFECTED(tar_ch,AFF_FLY)) 
					spell_fly(level, ch, tar_ch, 0);
			break;
		default: 
			log("Serious screw-up in fly!");
			break;
	}
}


void cast_quickness( byte level, struct char_data *ch, char *arg, int type,
  struct char_data *tar_ch, struct obj_data *tar_obj )
{
  switch (type) {
    case SPELL_TYPE_SPELL:
			spell_quickness(level, ch, tar_ch, 0);
			break;
    case SPELL_TYPE_POTION:
			spell_quickness(level, ch, ch, 0);
			break;
    case SPELL_TYPE_SCROLL:
         if(tar_obj) return;
         if (!tar_ch) tar_ch = ch;
         spell_quickness(level, ch, tar_ch, 0);
         break;
    case SPELL_TYPE_STAFF:
         for (tar_ch = world[ch->in_room].people ;
              tar_ch ; tar_ch = tar_ch->next_in_room)
            if (tar_ch != ch)
                  spell_quickness(level,ch,tar_ch,0);
         break;
    default :
         log("Serious screw-up in quickness!");
         break;
	}
}