EmlenMud2003LOC/
EmlenMud2003LOC/world/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "emlen.h"

void say_spell (CHAR_DATA * ch, int sn);
void
renew_affect (CHAR_DATA * ch, AFFECT_DATA * aff)
{
  AFFECT_DATA *paf;
  AFFECT_DATA pasaf;
  bool foundd;
  foundd = FALSE;
  bzero (&pasaf, sizeof (pasaf));
  pasaf.type = aff->type;
  pasaf.duration = aff->duration;
  pasaf.location = aff->location;
  pasaf.modifier = aff->modifier;
  pasaf.bitvector = aff->bitvector;
  pasaf.bitvector2 = aff->bitvector2;
  for (paf = ch->affected; paf != NULL; paf = paf->next)
    {
      if (paf->type == aff->type && paf->location == aff->location)
	{
	  paf->duration = aff->duration;
	  foundd = TRUE;
	}
    }
  if (!foundd)
    affect_to_char (ch, &pasaf);
  return;
}


void
mana (CHAR_DATA * ch, char *argy)
{
  char bufff[500];
  int mana_water = 0;
  int mana_earth = 0;
  int mana_fire = 0;
  int mana_air = 0;
  int mana_spirit = 0;
  int water_lev = 0;
  int earth_lev = 0;
  int fire_lev = 0;
  int air_lev = 0;
  int spirit_lev = 0;
  SINGLE_OBJECT *obj = NULL;
  int nat_level = 0;
  int bonus = 0;

 DEFINE_COMMAND ("mana", mana, POSITION_DEAD, 0, LOG_NORMAL, "Allows you to see your mana in different element types, and max spell levels you can cast.")

    if (IS_MOB (ch))
    return;

   bonus = (is_member(ch, GUILD_WIZARD) ? 1 : 0)+
   (is_member(ch, GUILD_HEALER) ? 1 : 0)+
   (is_member(ch, GUILD_MYSTIC) ? 1 : 0)+
   (is_member(ch, GUILD_CONJURER) ? 1: 0);
 if (IS_AUGMENTED(ch, AUG_CHANNEL))
   {
     bonus *=2;
     bonus +=2;
   }
 nat_level = (get_curr_int (ch) + get_curr_wis (ch)) / 2 + bonus + (ch->pcdata->remort_times+1)/2;

 /* Set up the base case. */

 fire_lev = nat_level;
 air_lev = nat_level;
 earth_lev = nat_level;
 spirit_lev = nat_level;
 water_lev = nat_level;
 if (ch->pcdata->n_mana < 0) ch->pcdata->n_mana = 0;
 mana_fire = ch->pcdata->n_mana;
 mana_air = ch->pcdata->n_mana;
 mana_water = ch->pcdata->n_mana;
 mana_earth = ch->pcdata->n_mana;
 mana_spirit = ch->pcdata->n_mana;


  if ((obj = get_item_held (ch, ITEM_GEM)) != NULL)
    {
      I_GEM *gem = (I_GEM *) obj->more;
      if (IS_SET (gem->gem_type, MANA_FIRE))
	{
	  fire_lev +=  gem->max_level;
	  mana_fire += gem->mana_now;
	}
      if (IS_SET (gem->gem_type, MANA_AIR))
	{
	  air_lev += gem->max_level;
	  mana_air += gem->mana_now;
	}
      if (IS_SET (gem->gem_type, MANA_EARTH))
	{
	  earth_lev += gem->max_level;
	  mana_earth += gem->mana_now;
	}
      if (IS_SET (gem->gem_type, MANA_WATER))
	{
	  water_lev +=  gem->max_level;
	  mana_water += gem->mana_now;
	}
      if (IS_SET (gem->gem_type, MANA_SPIRIT))
	{
	  spirit_lev += gem->max_level;
	  mana_spirit += gem->mana_now;
	}
    }


  sprintf (bufff, "Fire mana available is   : [\x1B[1m%3d\x1B[0m] (Max spell level \x1B[1m%d\x1B[0m).\n\r", mana_fire, fire_lev);
  send_to_char (bufff, ch);
  sprintf (bufff, "Air mana available is    : [\x1B[1m%3d\x1B[0m] (Max spell level \x1B[1m%d\x1B[0m).\n\r", mana_air, air_lev);
  send_to_char (bufff, ch);
  sprintf (bufff, "Water mana available is  : [\x1B[1m%3d\x1B[0m] (Max spell level \x1B[1m%d\x1B[0m).\n\r", mana_water, water_lev);
  send_to_char (bufff, ch);
  sprintf (bufff, "Earth mana available is  : [\x1B[1m%3d\x1B[0m] (Max spell level \x1B[1m%d\x1B[0m).\n\r", mana_earth, earth_lev);
  send_to_char (bufff, ch);
  sprintf (bufff, "Spirit mana available is : [\x1B[1m%3d\x1B[0m] (Max spell level \x1B[1m%d\x1B[0m).\n\r", mana_spirit, spirit_lev);
  send_to_char (bufff, ch);
  sprintf (bufff, "\n\rGeneral mana available is the max of the above values and spell levels.\n\r");
  send_to_char (bufff, ch);
  return;
}



int
find_char_mana (CHAR_DATA * ch, int bit, int sn)
{
  SINGLE_OBJECT *gem;
  int mana = 0;
  SPELL_DATA *spell = NULL;
  int level = 0;
  if (IS_MOB(ch) || LEVEL(ch) >= 100) return 500;
  spell = skill_lookup (NULL, sn);
  level = (is_member(ch, GUILD_WIZARD) ? 1 : 0)+
    (is_member(ch, GUILD_HEALER) ? 1 : 0)+
    (is_member(ch, GUILD_MYSTIC) ? 1 : 0)+
    (is_member(ch, GUILD_CONJURER) ? 1: 0);
  if (IS_AUGMENTED(ch, AUG_CHANNEL))
    {
      level *=2;
      level +=2;
    }
  level += ((get_curr_int (ch) + get_curr_wis (ch)) / 2) +(ch->pcdata->remort_times+1);
   if (ch->pcdata->n_mana < 0) ch->pcdata->n_mana = 0;
  mana = ch->pcdata->n_mana;
  if ((gem = ch->hold1) != NULL && gem->pIndexData->item_type == ITEM_GEM && IS_SET(((I_GEM *) gem->more)->gem_type, bit))
    {
      mana += ((I_GEM *)gem->more)->mana_now;
      level += ((I_GEM *)gem->more)->max_level;
    }
  else if ((gem = ch->hold2) != NULL && gem->pIndexData->item_type == ITEM_GEM && IS_SET(((I_GEM *) gem->more)->gem_type, bit))
    {
      mana += ((I_GEM *)gem->more)->mana_now;
      level += ((I_GEM *)gem->more)->max_level;
    }
  if (spell->spell_level > level)
    {
      send_to_char("You cannot cast this spell without the proper type of gem!\n\r", ch);
      return 0;
    }
  return mana;
}


/*
   * Lookup a skill by slot number.
   * Used for object loading.
 */
int
slot_lookup (int slot)
{
  extern bool fBootDb;
  int sn;
  SPELL_DATA *spell;
  if (slot <= 0)
    return -1;
  return slot;
  for (sn = 0; sn < SKILL_COUNT; sn++)
    {
      if ((spell = skill_lookup (NULL, sn)) == NULL)
	continue;
      if (slot == spell->gsn /*spell->slot */ )
	return sn;
    }
  if (fBootDb)
    {
      bug ("Slot_lookup: bad slot %d.", slot);
      return 1;
      /*abort( ); */
    }
  return -1;
}

/* bah this crap is useless - taken from other code */

void
say_spell (CHAR_DATA * ch, int sn)
{
  char buf[STD_LENGTH];
  char buf2[STD_LENGTH];
  CHAR_DATA *rch;
  char *pName;
  int iSyl;
  int length;
  SPELL_DATA *spell;
  struct syl_type
    {
      char *old;
      char *new;
    }
   ;
  static const struct syl_type syl_table[] =
  {
    {
      " ", " "
    }
    ,
    {
      "ar", "zad"
    }
    ,
    {
      "au", "lju"
    }
    ,
    {
      "bless", "ufc"
    }
    ,
    {
      "blind", "plina"
    }
    ,
    {
      "bur", "gna"
    }
    ,
    {
      "cu", "laq"
    }
    ,
    {
      "de", "byn"
    }
    ,
    {
      "en", "oog"
    }
    ,
    {
      "light", "solg"
    }
    ,
    {
      "lo", "qg"
    }
    ,
    {
      "mor", "fel"
    }
    ,
    {
      "move", "ewa"
    }
    ,
    {
      "ness", "kuj"
    }
    ,
    {
      "ning", "mnab"
    }
    ,
    {
      "per", "dew"
    }
    ,
    {
      "balefire", "Pika......CHHUUUUUUUUU!!!"
    }
    ,
    {
      "ra", "jih"
    }
    ,
    {
      "re", "cus"
    }
    ,
    {
      "son", "bru"
    }
    ,
    {
      "tect", "ira"
    }
    ,
    {
      "tri", "fel"
    }
    ,
    {
      "ven", "xaq"
    }
    ,
    {
      "a", "e"
    }
    ,
    {
      "b", "d"
    }
    ,
    {
      "c", "w"
    }
    ,
    {
      "d", "j"
    }
    ,
    {
      "e", "k"
    }
    ,
    {
      "f", "e"
    }
    ,
    {
      "g", "m"
    }
    ,
    {
      "h", "y"
    }
    ,
    {
      "i", "s"
    }
    ,
    {
      "j", "i"
    }
    ,
    {
      "k", "p"
    }
    ,
    {
      "l", "x"
    }
    ,
    {
      "m", "a"
    }
    ,
    {
      "n", "r"
    }
    ,
    {
      "o", "u"
    }
    ,
    {
      "p", "g"
    }
    ,
    {
      "q", "z"
    }
    ,
    {
      "r", "n"
    }
    ,
    {
      "s", "l"
    }
    ,
    {
      "t", "d"
    }
    ,
    {
      "u", "h"
    }
    ,
    {
      "v", "b"
    }
    ,
    {
      "w", "o"
    }
    ,
    {
      "x", "a"
    }
    ,
    {
      "y", "i"
    }
    ,
    {
      "z", "b"
    }
    ,
    {
      "", ""
    }
  }
   ;
  if ((spell = skill_lookup (NULL, sn)) == NULL)
    return;
  buf[0] = '\0';
  for (pName = spell->spell_funky_name; *pName != '\0'; pName += length)
    {
      for (iSyl = 0; (length = strlen (syl_table[iSyl].old)) != 0; iSyl++)
	{
	  if (!str_prefix (syl_table[iSyl].old, pName))
	    {
	      strcat (buf, syl_table[iSyl].new);
	      break;
	    }
	}
      if (length == 0)
	length = 1;
    }
  sprintf (buf2, "$n utters the words, '%s'", buf);
  sprintf (buf, "$n utters the words, '%s'", spell->spell_funky_name);
  for (rch = ch->in_room->more->people; rch; rch = rch->next_in_room)
    {
      if (rch != ch)
	{
	  if (IS_MOB (rch))
	    act (buf, ch, NULL, rch, TO_VICT);
	  else if (rch->pcdata->learned[sn] > 30)
	    act (buf, ch, NULL, rch, TO_VICT);
	  else
	    act (buf2, ch, NULL, rch, TO_VICT);
	}
    }
  return;
}

/*
   * Compute a saving throw.
   * Negative apply's make saving throw better.
 */
bool
saves_spell (int level, CHAR_DATA * victim)
{
  int save;
  save = 40 + (((LEVEL (victim) - level) -
(victim->pcdata->saving_throw)));
  if (IS_AUGMENTED(victim, AUG_MENTAL_ARMOR)) save += 10;
  if (IS_AFFECTED_EXTRA(victim, AFF_MINDSHIELD)) save += 15;
  save = URANGE (10, save, 90);
  return number_percent () < save;
}

int
mana_now (CHAR_DATA * ch)
{
  SINGLE_OBJECT *obj;
  int mana = 0;
  if (IS_MOB (ch)) return 500;
  if (ch->pcdata->n_mana < 0) ch->pcdata->n_mana = 0;
  mana = ch->pcdata->n_mana;
  if ((obj = get_item_held(ch, ITEM_GEM)) != NULL)
    mana += ((I_GEM *) obj->more)->mana_now;
  return mana;
}

void
take_mana_char (CHAR_DATA * ch, int mana, int bit)
{

  SINGLE_OBJECT *gem;
  if (IS_MOB (ch))
    return;
  if (ch->pcdata->n_mana < 0) ch->pcdata->n_mana = 0;
    if (ch->pcdata->n_mana >= mana)
      {
	ch->pcdata->n_mana -= mana;
	return;
      }
    else
      {
	mana -= ch->pcdata->n_mana;
	ch->pcdata->n_mana = 0;
	if ((gem = ch->hold1) != NULL && gem->pIndexData->item_type == ITEM_GEM && IS_SET(((I_GEM *) gem->more)->gem_type, bit))
	  {
	    ((I_GEM *) gem->more)->mana_now -= mana;
	  }
	else if ((gem = ch->hold2) != NULL && gem->pIndexData->item_type == ITEM_GEM && IS_SET(((I_GEM *) gem->more)->gem_type, bit))
	  {
	    ((I_GEM *) gem->more)->mana_now -= mana;
	  }
	return;
      }
  return;
}



/* FIX THIS UP!! */

char *target_name;
void
do_cast (CHAR_DATA * ch, char *argy)
{
  SINGLE_OBJECT *obj;
  int mana;
  CHAR_DATA *victim;
  int char_mana;
  int range = 0;
  bool ranged = FALSE;
  SPELL_DATA *spell;
  char arg1[SML_LENGTH];
  char arg2[SML_LENGTH];
  DEFINE_COMMAND ("cast", do_cast, POSITION_FIGHTING, 0, LOG_NORMAL, "Allows you to cast a spell.  Format is: cast 'spellname' <target>.")

    if (IS_MOB (ch))
    return;
  if (IS_AFFECTED_EXTRA(ch, AFF_SPELL_REFLECT))
   {
    affect_strip (ch, gsn_spell_reflect);
   }

  if (ch->pcdata->tickcounts > 11 && (FIGHTING (ch) != NULL))
    {
      send_to_char ("You can't cast another spell this soon after your last one!\n\r", ch);
      return;
    }
  if (ch->position == POSITION_GROUNDFIGHTING)
    {
      send_to_char ("You can't concentrate enough! You are groundfighting!\n\r", ch);
      return;
    }
  if (ch->position == POSITION_BASHED)
    {
      send_to_char ("You can't cast while you are sitting on your butt!\n\r", ch);
      return;
    }
  if (ch->position == POSITION_CASTING)
    {
      send_to_char ("You are already casting a spell!\n\r", ch);
      return;
    }
  if (IS_PLAYER(ch) && ch->pcdata->learned[gsn_ranged] > pow.max_prac_spells)
    {
      range = 1;
      if (LEVEL(ch) > 90) range++;
      if (ch->pcdata->remort_times > 3) range++;
      if (ch->pcdata->remort_times > 6) range++;
      skill_gain(ch, gsn_ranged, TRUE);
    }
  if (strlen (argy) > 40)
    return;
  target_name = one_argy (argy, arg1);
  one_argy (target_name, arg2);
  if (IS_MOB (ch) && ch->desc == NULL)
    return;
  if (IS_SET (ch->in_room->room_flags, ROOM_NOMAGIC))
    {
      send_to_char ("The ground absorbs your magical incantations, preventing you from casting!\n\r", ch);
      return;
    }
  if (((spell = skill_lookup (arg1, -1)) == NULL)
      || (IS_PLAYER (ch) && LEVEL (ch) < spell->spell_level) || (IS_PLAYER(ch) && (ch->pcdata->learned[spell->gsn] <= 0))) 
    {
      send_to_char ("You can't do that.\n\r", ch);
      return;
    }
  if (spell->slot != 1)
    {
      send_to_char ("That is not a spell!\n\r", ch);
      return;
    }
  if (ch->position < spell->position && ch->position !=POSITION_MEDITATING)
    {
      send_to_char ("You can't concentrate enough.\n\r", ch);
      return;
    }
  switch (spell->spell_type)
    {
    default:
      bug ("Do_cast: bad target for sn %d.", spell->gsn);
      return;
    case TAR_IGNORE:
      break;
    case TAR_CHAR_OFFENSIVE:
      if (arg2[0] == '\0')
	{
	  if ((victim = FIGHTING (ch)) == NULL)
	    {
	      send_to_char ("Cast the spell on whom?\n\r", ch);
	      return;
	    }
	}
      else if (arg2[0] == '1' && arg2[1] == '.')

        {
          send_to_char ("Syntax: cast <spell name> <victim name> can not use 1. to target with a spell!\n\r", ch);
          return;
        }
      else
	{
	  if ((victim = get_char_room_near (ch, ch->in_room, range, arg2)) == NULL)
	    {
	      send_to_char ("They aren't here.\n\r", ch);
	      return;
	    }
	  else if (victim != ch)
	    {
	      if (ch->in_room == victim->in_room)
		ranged = FALSE;
	      else
		ranged = TRUE;
	    }
	}


      if (ch == victim)
	{
	  send_to_char ("You can't do that to yourself.\n\r", ch);
	  return;
	}

	/* ----------------------------------------------------------------------------
		Protect Neutral align from direct offensive spells and prevent them from
		casting these as well
	  ----------------------------------------------------------------------------  */
	if ( IS_PLAYER(ch) && IS_PLAYER(victim) && ALIGN (victim) == 0 && !IN_BATTLE (ch)
		&& ch->fgt->challenge != 10 )
	{
		send_to_char ("A strange force prevents you from harming this person.\n\r", ch);
		return;
	}

	if ( IS_PLAYER(ch) && IS_PLAYER(victim) && ALIGN (ch) == 0 && !IN_BATTLE (ch)
		&& ch->fgt->challenge != 10 )
	{
		send_to_char ("A strange force prevents you from attacking other players.\n\r", ch);
		return;
	}

      /* --------------------------------------------- */
      /* 	 Protect LinkDead-NoPKTimers	       */
      /* --------------------------------------------- */
      if(IS_PLAYER(victim) && victim->desc == NULL) {
	if(!(victim->pcdata->no_quit_pk > 0)) {
	  send_to_char ("Your magic cannot harm someone who's existance is questionable.\n\r", ch);
	  return;
	}
      }

    break;
    case TAR_CHAR_DEFENSIVE:
      if (arg2[0] == '\0')
	{
	  victim = ch;
	}
      else
	{
	  if ((victim = get_char_room_near (ch, ch->in_room, range, arg2)) == NULL)
	    {
	      send_to_char ("They aren't here.\n\r", ch);
	      return;
	    }
	  else if(victim != ch)
	    {
	      if (ch->in_room == victim->in_room)
		ranged = FALSE;
	      else
		ranged = TRUE;
	    }
	}
      break;
    case TAR_CHAR_SELF:
      if (arg2[0] != '\0' && !is_name (arg2, RNAME (ch)))
	{
	  send_to_char ("You can't cast this spell on another.\n\r", ch);
	  return;
	}
      break;
    case TAR_OBJ_INV:
      if (arg2[0] == '\0')
	{
	  send_to_char ("What should the spell be cast upon?\n\r", ch);
	  return;
	}
      if ((obj = get_obj_inv (ch, arg2)) == NULL)
	{
	  send_to_char ("You are not carrying that.\n\r", ch);
	  return;
	}
	  break;
	case TAR_OBJ_ROOM:
		if (arg2[0] == '\0')
		{
			send_to_char ("What should the spell be cast upon?\n\r", ch);
			return;
		}
	  
         obj = get_obj_list (ch, arg2, ch->in_room->more->contents);
	    if (obj == NULL || IS_SET (obj->extra_flags, ITEM_UNSEEN))
	    {
	      send_to_char("Nothing like that on the ground.\n\r", ch);
	      return;
	    }
      break;
    }
  char_mana = find_char_mana (ch, spell->mana_type, spell->gsn);
  if (2 + LEVEL (ch) - spell->spell_level == 0)
    mana = spell->mana;
  else
    {
      mana = IS_MOB (ch) ? 0 : UMAX (
				      spell->mana,
			       100 / (2 + LEVEL (ch) - spell->spell_level));
    }
  if (IS_PLAYER (ch) && mana > char_mana && LEVEL(ch) < MAX_LEVEL)
    {
      send_to_char ("You don't have enough magical energy of the right element to cast that spell.\n\r", ch);
      return;
    }
  if (strlen (argy) > 140)
    return;
  if (ch->desc) ch->desc->repeat = 0;
  NEW_POSITION(ch, POSITION_CASTING);
  act ("You begin to utter some strange incantations...", ch, NULL, ch, TO_CHAR);
  act("$N begins to utter some strange incantations...", ch, NULL, ch, TO_ROOM);

  check_temp (ch);
  strcpy (ch->pcdata->temp->temp_string, argy);
  if (IS_PLAYER (ch))
    if ((LEVEL (ch) < 100) || (LEVEL (ch) > 99 && IS_SET (ch->pcdata->act2, PLR_HOLYLAG)))
      {
	int bonus =
	  (is_member(ch, GUILD_MYSTIC) ? 4 : 0) +
	  (is_member(ch, GUILD_WIZARD) ? 4 : 0) +
	  (is_member(ch, GUILD_HEALER) ? 4 : 0) +
	  (is_member(ch, GUILD_CONJURER) ? 4 : 0) +
	  (IS_AUGMENTED(ch, AUG_MIND_POWER) ? 3 : 0) +
	  (IS_AUGMENTED(ch, AUG_MIND_FOCUS) ? 3 : 0) +
	  (IS_AUGMENTED(ch, AUG_FOCUS) ? 7 : 0) +
	  ch->pcdata->remort_times*0;
	check_fgt (ch);
	ch->pcdata->tickcounts = ((spell->casting_time) * (100-bonus))/100;
	if (ranged && (ch->pcdata->learned[gsn_ranged] > pow.max_prac_spells))
		ch->pcdata->tickcounts +=5;


      }
  return;
}

void
do_actual_cast (CHAR_DATA * ch, char *argy)
{
  char arg1[SML_LENGTH];
  char arg2[SML_LENGTH];
  CHAR_DATA *victim;
  SINGLE_OBJECT *obj;
  void *vo;
  int mana;
  int range = 0;
  int char_mana;
  int sn;
  SPELL_DATA *spell;
/*
   * Switched NPC's can cast spells, but others can't.
 */
  MARK_CHAR_DEBUG ("Actual_cast", ch)
    if (IS_MOB (ch) && ch->desc == NULL)
    return;
  if (ch->position == POSITION_GROUNDFIGHTING)
    return;
  if (FIGHTING (ch) == NULL && ch->position == POSITION_CASTING)
    NEW_POSITION(ch, POSITION_STANDING);
  if (FIGHTING (ch) != NULL && ch->position == POSITION_CASTING)
    NEW_POSITION(ch, POSITION_FIGHTING);
  target_name = one_argy (argy, arg1);
  one_argy (target_name, arg2);
  if (IS_SET (ch->in_room->room_flags, ROOM_NOMAGIC) && LEVEL(ch) <MAX_LEVEL)
    {
      send_to_char ("The ground absorbs your magical incantations, preventing you from casting!\n\r", ch);
      return;
    }
  if (IS_SET (ch->in_room->room_flags, ROOM_LOWMAGIC) && LEVEL(ch)<MAX_LEVEL && (number_range(1,3) == 3))
    {
      send_to_char ("The ground absorbs your magical incantations, preventing you from casting!\n\r", ch);
      return;
    }
  if (IS_PLAYER(ch) && ch->pcdata->learned[gsn_ranged] >= pow.max_prac_spells)
    {
      range = 1;
      if (LEVEL(ch) > 60) range++;
      if (ch->pcdata->remort_times > 3) range++;
      if (ch->pcdata->remort_times > 5) range++;
    }

  if (arg1[0] == '\0')
    {
      send_to_char ("Cast which what where?\n\r", ch);
      return;
    }
  if ((spell = skill_lookup (arg1, -1)) == NULL
      || (IS_PLAYER (ch) && LEVEL (ch) < spell->spell_level))
    {
      send_to_char ("You can't do that.\n\r", ch);
      return;
    }
  sn = spell->gsn;
  if (ch->position == POSITION_CASTING)
    NEW_POSITION(ch, POSITION_STANDING);
  if (ch->position < spell->position)
    {
      send_to_char ("You can't concentrate enough.\n\r", ch);
      return;
    }
  if (2 + LEVEL (ch) - spell->spell_level == 0)
    mana = spell->mana;
  else
    {
      mana = IS_MOB (ch) ? 0 : UMAX (spell->mana,
				      100 / (2 + LEVEL (ch) - spell->spell_level));
    }
/*
   * Locate targets.
 */
  victim = NULL;
  obj = NULL;
  vo = NULL;
  switch (spell->spell_type)
    {
    default:
      bug ("Do_cast: bad target for sn %d.", sn);
      return;
    case TAR_IGNORE:
      break;
    case TAR_CHAR_OFFENSIVE:
      if (arg2[0] == '\0')
	{
	  if ((victim = FIGHTING (ch)) == NULL)
	    {
	      send_to_char ("Cast the spell on whom?\n\r", ch);
	      return;
	    }
	}
      else
	{
	  if ((victim = get_char_room_near (ch, ch->in_room, range, arg2)) == NULL)
	    {
	      send_to_char ("They aren't here.\n\r", ch);
	      return;
	    }
	}
      if (ch == victim && LEVEL (ch) < 10)
	{
	  send_to_char ("You can't do that to yourself.\n\r", ch);
	  return;
	}
      if (ch->position != POSITION_FIGHTING || FIGHTING (ch) != victim)
	if (!pkill (ch, victim))
	  return;
      if (IS_PLAYER (ch) && LEVEL(ch) < MAX_LEVEL)
	ch->pcdata->tickcounts = spell->casting_time/2+3;
      if (is_member(ch, GUILD_MYSTIC))
	ch->pcdata->tickcounts /= 2;
      /* if ( IS_PLAYER(ch) )
         {
         * Removed no-char fuzzyness *
         if ( IS_AFFECTED(ch, AFF_CHARM) && ch->master == victim )
         {
         send_to_char( "You can't do that on your own follower.\n\r",
         ch );
         return;
         }
         }
       */
      vo = (void *) victim;
      break;
    case TAR_CHAR_DEFENSIVE:
      if (arg2[0] == '\0')
	{
	  victim = ch;
	}
      else
	{
	  if ((victim = get_char_room_near (ch, ch->in_room, range, arg2)) == NULL)
	    {
	      send_to_char ("They aren't here.\n\r", ch);
	      return;
	    }
	}
      vo = (void *) victim;
      break;
    case TAR_CHAR_SELF:
      if (arg2[0] != '\0' && !is_name (arg2, RNAME (ch)))
	{
	  send_to_char ("You can't cast this spell on another.\n\r", ch);
	  return;
	}
      vo = (void *) ch;
      break;
    case TAR_OBJ_INV:
      if (arg2[0] == '\0')
	{
	  send_to_char ("What should the spell be cast upon?\n\r", ch);
	  return;
	}
      if ((obj = get_obj_inv (ch, arg2)) == NULL)
	{
	  send_to_char ("You are not carrying that in your hand.\n\r", ch);
	  return;
	}
      vo = (void *) obj;
      break;
    
	case TAR_OBJ_ROOM:
		if (arg2[0] == '\0')
		{
			send_to_char ("What should the spell be cast upon?\n\r", ch);
			return;
		}
	  
       obj = get_obj_list (ch, arg2, ch->in_room->more->contents);
	   if (obj == NULL || IS_SET (obj->extra_flags, ITEM_UNSEEN))
	    {
	      send_to_char("Nothing like that on the ground...\n\r", ch);
	      return;
	    }
	  vo = (void *) obj;
      break;
	}

  MARK_CHAR_DEBUG ("Actual_cast_find_char_mana", ch)

    char_mana = find_char_mana (ch, spell->mana_type, sn);

  MARK_CHAR_DEBUG ("Actual_cast_after_find_char_mana", ch)

    if (victim != NULL && spell->spell_type == TAR_CHAR_OFFENSIVE &&
	is_safe (ch, victim) && ((IS_PLAYER (ch) && !IS_MOB (victim) && !DIFF_ALIGN (ch, victim)) || IS_MOB (victim)))
    {
      send_to_char ("You are in a safe zone. No casting nasty spells like that!\n\r", ch);
      return;
    }
  if (IS_PLAYER (ch) && mana > char_mana)
    {
      switch (spell->mana_type)
	{
	default:
	  send_to_char ("You don't have enough mana to cast that spell.\n\r", ch);
	  break;
	case MANA_FIRE:
	  send_to_char ("You don't have enough mana to contain the Fire.\n\r", ch);
	  break;
	case MANA_AIR:
	  send_to_char ("You require more mana for Air.\n\r", ch);
	  break;
	case MANA_WATER:
	  send_to_char ("You don't have enough mana for Water.\n\r", ch);
	  break;
	case MANA_EARTH:
	  send_to_char ("Your Earth mana is insufficient.\n\r", ch);
	  break;
	case MANA_SPIRIT:
	  send_to_char ("Your Spirit mana is insufficient.\n\r", ch);
	  break;
	}
      return;
    }

  if( IS_PLAYER(ch) && (LEVEL(ch) < 100) &&
      (number_range(1,125) >
      (ch->pcdata->learned[spell->gsn]
       + (is_member (ch, GUILD_WIZARD) ? 6 : 0)
       + (is_member (ch, GUILD_HEALER) ? 6 : 0)
       + (is_member (ch, GUILD_MYSTIC) ? 6 : 0)
       + (is_member (ch, GUILD_CONJURER) ? 6 : 0)
       + (IS_AUGMENTED(ch, AUG_FOCUS) ? 7 :0)
       + (IS_AUGMENTED(ch, AUG_MIND_POWER) ? 3 : 0)
       + (IS_AUGMENTED(ch, AUG_MIND_FOCUS) ? 3 : 0))))
    {
      send_to_char ("You lost your concentration.\n\r", ch);
      take_mana_char (ch, mana / 2, spell->mana_type);
    }
  else
    {
      say_spell (ch, sn);
      if (IS_PLAYER(ch) && LEVEL(ch) < 100)
	{
	  if (spell->spell_lag > 0 && ch->pcdata->no_quit > 0)
	    {
	      char buf[200];
	      sprintf(buf, "You must wait %d hours before casting %s!\n\r", ch->pcdata->no_quit, spell->spell_name);
	      send_to_char(buf, ch);
	      return;
	    }
          take_mana_char (ch, mana, spell->mana_type);
	  if (number_percent() < spell->fail_chance)
	    {
	      send_to_char("The spell failed...\n\r", ch);
	      return;
	    }
	  if (ch->pcdata->no_quit_pk > 0 && number_percent() < spell->pk_fail_chance)
	    {
	      send_to_char("The spell failed...\n\r", ch);
	      return;
	    }

	  if (spell->guilds != 0)
	    {
	      int i;
	      for (i = 0; str_cmp(guild_data[i].what_you_type, "end_of_list"); i++)
		{
		  if(IS_SET(spell->guilds, guild_data[i].mob_guildmaster_bit) && !IS_SET(ch->pcdata->guilds, guild_data[i].mob_guildmaster_bit))
		    {
		      send_to_char("You do not have the proper guilds to cast this!\n\r", ch);
		      return;
		    }
		}
	    }
	}
      general_spell (spell, LEVEL (ch), ch, vo);
      if (victim && victim->data_type==50)
	{
	  return;
	}
    }


    if (spell->spell_type == TAR_CHAR_OFFENSIVE
	&& victim != ch
	&& MASTER (victim) != ch)
    {
      CHAR_DATA *vch;
      CHAR_DATA *vch_next;
      for (vch = ch->in_room->more->people; vch; vch = vch_next)
	{
	  vch_next = vch->next_in_room;
	  if (victim == vch && FIGHTING (victim) == NULL)
	    {
	      multi_hit (victim, ch, TYPE_UNDEFINED);
	      break;
	    }
	}
    }
return;
}

/*
   * Cast spells at targets using a magical object.
 */
void
obj_cast_spell (int sn, int level, CHAR_DATA * ch, CHAR_DATA * victim, SINGLE_OBJECT * obj)
{
  void *vo;
  SPELL_DATA *spell;
  if (IS_SET (ch->in_room->room_flags, ROOM_NOMAGIC))
    {
      send_to_char ("The ground seems to absorb the spell...!\n\r", ch);
      return;
    }
  if (sn <= 0 || (spell = skill_lookup (NULL, sn)) == NULL)
    return;
  switch (spell->spell_type)
    {
    default:
      bug ("Obj_cast_spell: bad target for sn %d.", sn);
      return;
    case TAR_IGNORE:
      vo = NULL;
      break;
    case TAR_CHAR_OFFENSIVE:
      if (victim == NULL)
	victim = FIGHTING (ch);
      if (victim == NULL)
	{
	  send_to_char ("You can't do that.\n\r", ch);
	  return;
	}
      if (IS_PLAYER (ch))
	{
	  if (ch->pcdata->tickcounts > 2)
	    {
	      send_to_char ("The wand refuses to respond!\n\r", ch);
	      return;
	    }
	}
      if (ch->position != POSITION_FIGHTING || FIGHTING (ch) != victim)
	if (!pkill (ch, victim))
	  return;
      vo = (void *) victim;
      break;
    case TAR_CHAR_DEFENSIVE:
      if (victim == NULL)
	victim = ch;
      vo = (void *) victim;
      break;
    case TAR_CHAR_SELF:
      vo = (void *) ch;
      break;
    case TAR_OBJ_INV:
      if (obj == NULL)
	{
	  send_to_char ("You can't do that.\n\r", ch);
	  return;
	}
      vo = (void *) obj;
      break;
    }
  target_name = "";
  general_spell (spell, level, ch, vo);
/* (*skill_table[sn].spell_fun) ( sn, level, ch, vo ); */
  if (IS_PLAYER (ch))
    ch->pcdata->tickcounts = spell->casting_time + 10;
  if (spell->spell_type == TAR_CHAR_OFFENSIVE
      && victim != ch
      && MASTER (victim) != ch)
    {
      CHAR_DATA *vch;
      CHAR_DATA *vch_next;
      for (vch = ch->in_room->more->people; vch; vch = vch_next)
	{
	  vch_next = vch->next_in_room;
	  if (victim == vch && FIGHTING (victim) == NULL)
	    {
	      check_fgt (victim);
	      multi_hit (victim, ch, TYPE_UNDEFINED);
	      victim->fgt->fighting = ch;
	      NEW_POSITION(victim, POSITION_FIGHTING);
	      break;
	    }
	}
    }
  return;
}