Esempio n. 1
0
int
cast_spell (struct char_data *ch, struct char_data *tch,
			struct obj_data *tobj, int spellnum)
{
	if (spellnum < 0 || spellnum > TOP_SPELL_DEFINE)
	{
		log ("SYSERR: cast_spell trying to call spellnum %d/%d.\n", spellnum,
			 TOP_SPELL_DEFINE);
		return (0);
	}

	if (GET_POS (ch) < SINFO.min_position)
	{
		switch (GET_POS (ch))
		{
		case POS_SLEEPING:
			send_to_char ("You dream about great magical powers.\r\n", ch);
			break;
		case POS_RESTING:
			send_to_char ("You cannot concentrate while resting.\r\n", ch);
			break;
		case POS_SITTING:
			send_to_char ("You can't do this sitting!\r\n", ch);
			break;
		case POS_FIGHTING:
			send_to_char ("Impossible!  You can't concentrate enough!\r\n",
						  ch);
			break;
		default:
			send_to_char ("You can't do much of anything like this!\r\n", ch);
			break;
		}
		return (0);
	}
	if (AFF_FLAGGED (ch, AFF_CHARM) && (ch->master == tch))
	{
		send_to_char ("You are afraid you might hurt your master!\r\n", ch);
		return (0);
	}
	if ((tch != ch) && IS_SET (SINFO.targets, TAR_SELF_ONLY))
	{
		send_to_char ("You can only cast this spell upon yourself!\r\n", ch);
		return (0);
	}
	if ((tch == ch) && IS_SET (SINFO.targets, TAR_NOT_SELF))
	{
		send_to_char ("You cannot cast this spell upon yourself!\r\n", ch);
		return (0);
	}
	if (IS_SET (SINFO.routines, MAG_GROUPS) && !AFF_FLAGGED (ch, AFF_GROUP))
	{
		send_to_char
			("You can't cast this spell if you're not in a group!\r\n", ch);
		return (0);
	}
	send_to_char (OK, ch);
	say_spell (ch, spellnum, tch, tobj);

	return (call_magic (ch, tch, tobj, spellnum, GET_LEVEL (ch), CAST_SPELL));
}
Esempio n. 2
0
/* mag_objectmagic: This is the entry-point for all magic items.  This should
 * only be called by the 'quaff', 'use', 'recite', etc. routines.
 * For reference, object values 0-3:
 * staff  - [0]	level	[1] max charges	[2] num charges	[3] spell num
 * wand   - [0]	level	[1] max charges	[2] num charges	[3] spell num
 * scroll - [0]	level	[1] spell num	[2] spell num	[3] spell num
 * potion - [0] level	[1] spell num	[2] spell num	[3] spell num
 * Staves and wands will default to level 14 if the level is not specified; the
 * DikuMUD format did not specify staff and wand levels in the world files */
void mag_objectmagic(struct char_data *ch, struct obj_data *obj,
		          char *argument)
{
  char arg[MAX_INPUT_LENGTH];
  int i, k;
  struct char_data *tch = NULL, *next_tch;
  struct obj_data *tobj = NULL;

  one_argument(argument, arg);

  k = generic_find(arg, FIND_CHAR_ROOM | FIND_OBJ_INV | FIND_OBJ_ROOM |
		   FIND_OBJ_EQUIP, ch, &tch, &tobj);

  switch (GET_OBJ_TYPE(obj)) {
  case ITEM_STAFF:
    act("You tap $p three times on the ground.", FALSE, ch, obj, 0, TO_CHAR);
    if (obj->action_description)
      act(obj->action_description, FALSE, ch, obj, 0, TO_ROOM);
    else
      act("$n taps $p three times on the ground.", FALSE, ch, obj, 0, TO_ROOM);

    if (GET_OBJ_VAL(obj, 2) <= 0) {
      send_to_char(ch, "It seems powerless.\r\n");
      act("Nothing seems to happen.", FALSE, ch, obj, 0, TO_ROOM);
    } else {
      GET_OBJ_VAL(obj, 2)--;
      WAIT_STATE(ch, PULSE_VIOLENCE);
      /* Level to cast spell at. */
      k = GET_OBJ_VAL(obj, 0) ? GET_OBJ_VAL(obj, 0) : DEFAULT_STAFF_LVL;

      /* Area/mass spells on staves can cause crashes. So we use special cases
       * for those spells spells here. */
      if (HAS_SPELL_ROUTINE(GET_OBJ_VAL(obj, 3), MAG_MASSES | MAG_AREAS)) {
        for (i = 0, tch = world[IN_ROOM(ch)].people; tch; tch = tch->next_in_room)
	  i++;
	while (i-- > 0)
	  call_magic(ch, NULL, NULL, GET_OBJ_VAL(obj, 3), k, CAST_STAFF);
      } else {
	for (tch = world[IN_ROOM(ch)].people; tch; tch = next_tch) {
	  next_tch = tch->next_in_room;
	  if (ch != tch)
	    call_magic(ch, tch, NULL, GET_OBJ_VAL(obj, 3), k, CAST_STAFF);
	}
      }
    }
    break;
  case ITEM_WAND:
    if (k == FIND_CHAR_ROOM) {
      if (tch == ch) {
	act("You point $p at yourself.", FALSE, ch, obj, 0, TO_CHAR);
	act("$n points $p at $mself.", FALSE, ch, obj, 0, TO_ROOM);
      } else {
	act("You point $p at $N.", FALSE, ch, obj, tch, TO_CHAR);
	if (obj->action_description)
	  act(obj->action_description, FALSE, ch, obj, tch, TO_ROOM);
	else
	  act("$n points $p at $N.", TRUE, ch, obj, tch, TO_ROOM);
      }
    } else if (tobj != NULL) {
      act("You point $p at $P.", FALSE, ch, obj, tobj, TO_CHAR);
      if (obj->action_description)
	act(obj->action_description, FALSE, ch, obj, tobj, TO_ROOM);
      else
	act("$n points $p at $P.", TRUE, ch, obj, tobj, TO_ROOM);
    } else if (IS_SET(spell_info[GET_OBJ_VAL(obj, 3)].routines, MAG_AREAS | MAG_MASSES)) {
      /* Wands with area spells don't need to be pointed. */
      act("You point $p outward.", FALSE, ch, obj, NULL, TO_CHAR);
      act("$n points $p outward.", TRUE, ch, obj, NULL, TO_ROOM);
    } else {
      act("At what should $p be pointed?", FALSE, ch, obj, NULL, TO_CHAR);
      return;
    }

    if (GET_OBJ_VAL(obj, 2) <= 0) {
      send_to_char(ch, "It seems powerless.\r\n");
      act("Nothing seems to happen.", FALSE, ch, obj, 0, TO_ROOM);
      return;
    }
    GET_OBJ_VAL(obj, 2)--;
    WAIT_STATE(ch, PULSE_VIOLENCE);
    if (GET_OBJ_VAL(obj, 0))
      call_magic(ch, tch, tobj, GET_OBJ_VAL(obj, 3),
		 GET_OBJ_VAL(obj, 0), CAST_WAND);
    else
      call_magic(ch, tch, tobj, GET_OBJ_VAL(obj, 3),
		 DEFAULT_WAND_LVL, CAST_WAND);
    break;
  case ITEM_SCROLL:
    if (*arg) {
      if (!k) {
	act("There is nothing to here to affect with $p.", FALSE,
	    ch, obj, NULL, TO_CHAR);
	return;
      }
    } else
      tch = ch;

    act("You recite $p which dissolves.", TRUE, ch, obj, 0, TO_CHAR);
    if (obj->action_description)
      act(obj->action_description, FALSE, ch, obj, tch, TO_ROOM);
    else
      act("$n recites $p.", FALSE, ch, obj, NULL, TO_ROOM);

    WAIT_STATE(ch, PULSE_VIOLENCE);
    for (i = 1; i <= 3; i++)
      if (call_magic(ch, tch, tobj, GET_OBJ_VAL(obj, i),
		       GET_OBJ_VAL(obj, 0), CAST_SCROLL) <= 0)
	break;

    if (obj != NULL)
      extract_obj(obj);
    break;
  case ITEM_POTION:
    tch = ch;

  if (!consume_otrigger(obj, ch, OCMD_QUAFF))  /* check trigger */
    return;

    act("You quaff $p.", FALSE, ch, obj, NULL, TO_CHAR);
    if (obj->action_description)
      act(obj->action_description, FALSE, ch, obj, NULL, TO_ROOM);
    else
      act("$n quaffs $p.", TRUE, ch, obj, NULL, TO_ROOM);

    WAIT_STATE(ch, PULSE_VIOLENCE);
    for (i = 1; i <= 3; i++)
      if (call_magic(ch, ch, NULL, GET_OBJ_VAL(obj, i),
		       GET_OBJ_VAL(obj, 0), CAST_POTION) <= 0)
	break;

    if (obj != NULL)
      extract_obj(obj);
    break;
  default:
    log("SYSERR: Unknown object_type %d in mag_objectmagic.",
	GET_OBJ_TYPE(obj));
    break;
  }
}
Esempio n. 3
0
/* code borrowed from do_cast() */
void do_dg_cast(void *go, struct script_data *sc, trig_data *trig,
		 int type, char *cmd)
{
  struct char_data *caster = NULL;
  struct char_data *tch = NULL;
  struct obj_data *tobj = NULL;
  struct room_data *caster_room = NULL;
  char *s, *t;
  int spellnum, target = 0;


  /* need to get the caster or the room of the temporary caster */
  switch (type) {
    case MOB_TRIGGER:
      caster = (struct char_data *)go;
      break;
    case WLD_TRIGGER:
      caster_room = (struct room_data *)go;
      break;
    case OBJ_TRIGGER:
      caster_room = dg_room_of_obj((struct obj_data *)go);
      if (!caster_room) {
        script_log("dg_do_cast: unknown room for object-caster!");
        return;
      }
      break;
    default:
      script_log("dg_do_cast: unknown trigger type!");
      return;
  }

  /* get: blank, spell name, target name */
  s = strtok(cmd, "'");
  if (s == NULL) {
    sprintf(buf2, "Trigger: %s, VNum %d. dg_cast needs spell name.",
      GET_TRIG_NAME(trig), GET_TRIG_VNUM(trig));
    script_log(buf2);
    return;
  }
  s = strtok(NULL, "'");
  if (s == NULL) {
    sprintf(buf2, "Trigger: %s, VNum %d. dg_cast needs spell name in `'s.",
      GET_TRIG_NAME(trig), GET_TRIG_VNUM(trig));
    script_log(buf2);
    return;
  }
  t = strtok(NULL, "\0");

  /* spellnum = search_block(s, spells, 0); */
  spellnum = find_abil_num(s,spells);
  if ((spellnum < 1) || (spellnum > MAX_SPELLS)) {
    sprintf(buf2, "Trigger: %s, VNum %d. dg_cast: invalid spell name (%s)",
      GET_TRIG_NAME(trig), GET_TRIG_VNUM(trig), cmd);
    script_log(buf2);
    return;
  }

  /* Find the target */
  if (t != NULL) {
    one_argument(strcpy(arg, t), t);
    skip_spaces(&t);
  }
  if (IS_SET(SINFO.targets, TAR_IGNORE)) {
    target = TRUE;
  } else if (t != NULL && *t) {
    if (!target &&
          (IS_SET(SINFO.targets, TAR_CHAR_ROOM) ||
           IS_SET(SINFO.targets, TAR_CHAR_WORLD))) {
      if ((tch = get_char(t)) != NULL)
        target = TRUE; 
    }

    if (!target &&
          (IS_SET(SINFO.targets, TAR_OBJ_INV) ||
           IS_SET(SINFO.targets, TAR_OBJ_EQUIP) ||
           IS_SET(SINFO.targets, TAR_OBJ_ROOM) ||
           IS_SET(SINFO.targets, TAR_OBJ_WORLD))) {
      if ((tobj = get_obj(t)) != NULL)
        target = TRUE; 
    }

    if (!target) {
      sprintf(buf2, "Trigger: %s, VNum %d. dg_cast: target not found (%s)",
        GET_TRIG_NAME(trig), GET_TRIG_VNUM(trig), cmd);
      script_log(buf2);
      return;
    }
  }

  if (IS_SET(SINFO.routines, MAG_GROUPS)) {
    sprintf(buf2,
      "Trigger: %s, VNum %d. dg_cast: group spells not permitted (%s)",
      GET_TRIG_NAME(trig), GET_TRIG_VNUM(trig), cmd);
    script_log(buf2);
    return;
  }

  if (!caster) {
    caster = read_mobile(DG_CASTER_PROXY, VIRTUAL);
    if (!caster) {
      script_log("dg_cast: Cannot load the caster mob!");
      return;
    }
    /* set the caster's name to that of the object, or the gods.... */
    /* take select pieces from char_to_room(); */
    if (type==OBJ_TRIGGER)
      caster->player.short_descr = 
        str_dup(((struct obj_data *)go)->short_description);
    else if (type==WLD_TRIGGER)
      caster->player.short_descr = str_dup("The gods");
    caster->next_in_room = caster_room->people;
    caster_room->people = caster;
    caster->in_room = real_room(caster_room->number);
    call_magic(caster, tch, tobj, spellnum, ABT_SPELL, GET_LEVEL(caster), CAST_SPELL, FALSE);
    extract_char(caster);
  } else
    call_magic(caster, tch, tobj, spellnum, ABT_SPELL, GET_LEVEL(caster), CAST_SPELL, FALSE);
}
Esempio n. 4
0
/* =========================================================================
   NAME       : use_tattoo()
   DESCRIPTION: 
   RETURNS    : TRUE if a tattoo was used
   WARNINGS   :
   HISTORY    : Created by dlkarnes 970417
   OTHER      :
   ========================================================================= */
int
use_tattoo( struct char_data *ch )
{
  void add_follower_quiet(struct char_data *ch, struct char_data *leader);

  if (ch && !IS_NPC(ch))
  {
    if (TAT_TIMER(ch))
    {
      char mybuf[256];
      sprintf(mybuf, "You can't use your tattoo's magick for "
              "%d more hour%s.\r\n", TAT_TIMER(ch),TAT_TIMER(ch)>1?"s":"");
      send_to_char(mybuf, ch);
      return(FALSE);
    }
    switch (GET_TATTOO(ch))
    {
      case TATTOO_NONE:
	send_to_char ("You don't have a tattoo.\r\n", ch);
	break;
      case TATTOO_SKULL:
      {
	struct char_data *skull = read_mobile(9, VIRTUAL);
        struct affected_type af;

	char_to_room(skull, ch->in_room);
	add_follower_quiet(skull, ch);
        IS_CARRYING_W(skull) = 0;
        IS_CARRYING_N(skull) = 0;
 
        af.type = SPELL_CHARM;
        af.duration = 20;
        af.modifier = 0;
        af.location = 0;
        af.bitvector = AFF_CHARM;
        affect_to_char(skull, &af);

	act("$n's tattoo glows brightly for a second, and $N appears!",
		TRUE, ch, 0, skull, TO_ROOM);
	act("Your tattoo glows brightly for a second, and $N appears!",
		TRUE, ch, 0, skull, TO_CHAR);
      }
      break;
      case TATTOO_EYE:
        call_magic(ch, ch, NULL, SPELL_GREATPERCEPT, 
		   DEFAULT_WAND_LVL, CAST_WAND);
	break;
      case TATTOO_SHIP:
        call_magic(ch, ch, NULL, SPELL_CHANGE_DENSITY, 
		   DEFAULT_WAND_LVL, CAST_WAND);
	break;
      case TATTOO_ANGEL:
        call_magic(ch, ch, NULL, SPELL_BLESS, DEFAULT_WAND_LVL, CAST_WAND);
	break;
      default:  
	send_to_char("Your tattoo can't be 'use'd.\r\n", ch);
	return (FALSE);
    }
    TAT_TIMER(ch)=24;
  }

  return(FALSE); 
}
Esempio n. 5
0
void
perform_smoke(struct creature *ch, int type)
{

    const char *to_vict = NULL;
    struct affected_type af;
    int hp_mod = 0, mana_mod = 0, move_mod = 0, spell = 0;
    uint8_t lev = 0;
    int accum_dur = 0, accum_affect = 0;

    init_affect(&af);
    af.type = SMOKE_EFFECTS;
    af.level = 30;
    af.owner = GET_IDNUM(ch);

    switch (type) {
    case SMOKE_DIRTWEED:
        to_vict = "Your head hurts.";
        af.duration = 3;
        af.modifier = -2;
        af.location = APPLY_INT;
        af.bitvector = AFF_CONFUSION;
        af.aff_index = 1;
        accum_dur = 1;
        accum_affect = 1;
        move_mod = -number(3, 10);
        mana_mod = -number(1, 2);
        break;
    case SMOKE_DESERTWEED:
        af.location = APPLY_MOVE;
        af.duration = 4;
        af.modifier = 10;
        mana_mod = dice(1, 4);
        move_mod = dice(3, 4);
        break;
    case SMOKE_INDICA:
        to_vict = "Your mind is elevated to another plane.";
        af.location = APPLY_WIS;
        af.duration = 5;
        af.modifier = number(1, 2);
        mana_mod = dice(6, 4);
        move_mod = -number(1, 3);
        break;
    case SMOKE_UNHOLY_REEFER:
        af.location = APPLY_WIS;
        af.duration = 5;
        af.modifier = number(0, 2);
        mana_mod = number(1, 4);
        move_mod = -number(1, 3);
        spell = SPELL_ESSENCE_OF_EVIL;
        lev = 20;
        break;
    case SMOKE_MARIJUANA:
        to_vict = "You feel stoned.";
        af.location = APPLY_INT;
        af.duration = 3;
        af.modifier = -1;
        mana_mod = dice(4, 4);
        break;
    case SMOKE_TOBACCO:
        af.location = APPLY_MOVE;
        af.duration = 3;
        af.modifier = -number(10, 20);
        accum_dur = 1;
        mana_mod = dice(3, 3);
        break;
    case SMOKE_HEMLOCK:
        to_vict = "The smoke burns your lungs!";
        af.location = APPLY_HIT;
        af.duration = number(3, 6);
        af.modifier = -number(30, 60);
        accum_affect = 1;
        hp_mod = -number(10, 16);
        mana_mod = -10;
        move_mod = -10;
        spell = SPELL_POISON;
        lev = LVL_AMBASSADOR;
        break;
    case SMOKE_PEYOTE:
        to_vict = "You feel a strange sensation.";
        spell = SPELL_ASTRAL_SPELL;
        lev = LVL_GRIMP;
        af.location = APPLY_MANA;
        af.modifier = number(10, 20);
        af.duration = number(1, 3);
        move_mod = number(6, 12);
        break;
    case SMOKE_HOMEGROWN:
        to_vict = "There's no place like home...";
        spell = SPELL_WORD_OF_RECALL;
        lev = number(30, 60);
        mana_mod = number(20, 40);
        move_mod = number(2, 10);
        break;

    default:
        af.type = 0;
        break;
    }

    if (to_vict)
        act(to_vict, false, ch, NULL, NULL, TO_CHAR);

    GET_HIT(ch) = MIN(MAX(GET_HIT(ch) + hp_mod, 0), GET_MAX_HIT(ch));
    GET_MANA(ch) = MIN(MAX(GET_MANA(ch) + mana_mod, 0), GET_MAX_MANA(ch));
    GET_MOVE(ch) = MIN(MAX(GET_MOVE(ch) + move_mod, 0), GET_MAX_MOVE(ch));

    if (af.type &&
        (!affected_by_spell(ch, af.type) || accum_affect || accum_dur))
        affect_join(ch, &af, accum_dur, true, accum_affect, true);

    if (spell && lev)
        call_magic(ch, ch, NULL, NULL, spell, (int)lev, CAST_CHEM);

    WAIT_STATE(ch, 6);

}
Esempio n. 6
0
int	cast_spell(struct char_data *ch, struct char_data *tch,
               struct obj_data *tobj, struct spell_info_type *sptr,
               char *tar_str)
{

    if (!magic_enabled)
        return (0);

    if (!sptr) {
        extended_mudlog(NRM, SYSL_BUGS, TRUE, "cast_spell() called without a valid sptr: ch: %s, tch: %s",
                        GET_NAME(ch), GET_NAME(tch));
        return (0);
    }

    if (GET_POS(ch) < sptr->min_position) {
        switch (GET_POS(ch)) {
        case POS_SLEEPING:
            send_to_char("You dream about great magical powers.\r\n", ch);
            break;
        case POS_RESTING:
            send_to_char("You cannot concentrate while resting.\r\n", ch);
            break;
        case POS_SITTING:
            send_to_char("You can't do this sitting!\r\n", ch);
            break;
        case POS_FIGHTING:
            send_to_char("Impossible!  You can't concentrate enough!\r\n", ch);
            break;
        default:
            send_to_char("You can't do much of anything like this!\r\n", ch);
            break;
        }
        return (0);
    }
    if (AFF_FLAGGED(ch, AFF_CHARM) && (ch->master == tch)) {
        send_to_char("You are afraid you might hurt your master!\r\n", ch);
        return (0);
    }
    if ((tch != ch) && IS_SET(sptr->targets, TAR_SELF_ONLY)) {
        send_to_char("You can only cast this spell upon yourself!\r\n", ch);
        return (0);
    }
    if ((tch == ch) && IS_SET(sptr->targets, TAR_NOT_SELF)) {
        send_to_char("You cannot cast this spell upon yourself!\r\n", ch);
        return (0);
    }
    if (IS_SET(sptr->routines, MAG_GROUPS) && !AFF_FLAGGED(ch, AFF_GROUP)) {
        send_to_char("You can't cast this spell if you're not in a group!\r\n",ch);
        return (0);
    }

    if (cast_mtrigger(tch, ch, tar_str, sptr) == 0)
        return (0);
    if (cast_otrigger(tobj, ch, tar_str, sptr) == 0)
        return (0);
    if (cast_wtrigger(ch, tch, tobj, tar_str, sptr) == 0)
        return (0);

    send_to_char(OK, ch);
    say_spell(ch, sptr, tch, tobj);

    return (call_magic(ch, tch, tobj, sptr, (GET_SKILL(ch, sptr->skill)/100), CAST_SPELL,
                       tar_str));
}
Esempio n. 7
0
void mag_objectmagic(struct char_data *ch, struct obj_data *obj,
                     char *argument)
{
    int i, k;
    struct char_data *tch = NULL, *next_tch;
    struct obj_data *tobj = NULL;

    if (!magic_enabled)
        return;

    one_argument(argument, arg);

    k = generic_find(arg, FIND_CHAR_ROOM | FIND_OBJ_INV | FIND_OBJ_ROOM |
                     FIND_OBJ_EQUIP, ch, &tch, &tobj);

    switch (GET_OBJ_TYPE(obj)) {
    case ITEM_STAFF:
        act("You tap $p three times on the ground.", FALSE, ch, obj, 0, TO_CHAR);
        if (obj->action_description)
            act(obj->action_description, FALSE, ch, obj, 0, TO_ROOM);
        else
            act("$n taps $p three times on the ground.", FALSE, ch, obj, 0, TO_ROOM);

        if (GET_OBJ_VAL(obj, 2) <= 0) {
            send_to_char("It seems powerless.\r\n", ch);
            act("Nothing seems to happen.", FALSE, ch, obj, 0, TO_ROOM);
        } else {
            GET_OBJ_VAL(obj, 2)--;
            WAIT_STATE(ch, PULSE_VIOLENCE);
            /* Level to cast spell at. */
            k = GET_OBJ_VAL(obj, 0) ? GET_OBJ_VAL(obj, 0) : DEFAULT_STAFF_LVL;

            /*
             * Problem : Area/mass spells on staves can cause crashes.
             * Solution: Remove the special nature of area/mass spells on staves.
             * Problem : People like that behavior.
             * Solution: We special case the area/mass spells here.
             */
            if (HAS_SPELL_ROUTINE(get_spell(GET_OBJ_VAL(obj, 3), __FILE__, __FUNCTION__), MAG_MASSES | MAG_AREAS)) {
                for (i = 0, tch = world[IN_ROOM(ch)].people; tch; tch = tch->next_in_room)
                    i++;
                while (i-- > 0)
                    call_magic(ch, NULL, NULL, get_spell(GET_OBJ_VAL(obj, 3), __FILE__, __FUNCTION__), k, CAST_STAFF, 0);
            } else {
                for (tch = world[IN_ROOM(ch)].people; tch; tch = next_tch) {
                    next_tch = tch->next_in_room;
                    if (ch != tch)
                        call_magic(ch, tch, NULL, get_spell(GET_OBJ_VAL(obj, 3), __FILE__, __FUNCTION__), k, CAST_STAFF, 0);
                }
            }
        }
        break;
    case ITEM_WAND:
        if (k == FIND_CHAR_ROOM) {
            if (tch == ch) {
                act("You point $p at yourself.", FALSE, ch, obj, 0, TO_CHAR);
                act("$n points $p at $mself.", FALSE, ch, obj, 0, TO_ROOM);
            } else {
                act("You point $p at $N.", FALSE, ch, obj, tch, TO_CHAR);
                if (obj->action_description)
                    act(obj->action_description, FALSE, ch, obj, tch, TO_ROOM);
                else
                    act("$n points $p at $N.", TRUE, ch, obj, tch, TO_ROOM);
            }
        } else if (tobj != NULL) {
            act("You point $p at $P.", FALSE, ch, obj, tobj, TO_CHAR);
            if (obj->action_description)
                act(obj->action_description, FALSE, ch, obj, tobj, TO_ROOM);
            else
                act("$n points $p at $P.", TRUE, ch, obj, tobj, TO_ROOM);
        } else if (IS_SET(get_spell(GET_OBJ_VAL(obj, 3), __FILE__, __FUNCTION__)->routines, MAG_AREAS | MAG_MASSES)) {
            /* Wands with area spells don't need to be pointed. */
            act("You point $p outward.", FALSE, ch, obj, NULL, TO_CHAR);
            act("$n points $p outward.", TRUE, ch, obj, NULL, TO_ROOM);
        } else {
            act("At what should $p be pointed?", FALSE, ch, obj, NULL, TO_CHAR);
            return;
        }

        if (GET_OBJ_VAL(obj, 2) <= 0) {
            send_to_char("It seems powerless.\r\n", ch);
            act("Nothing seems to happen.", FALSE, ch, obj, 0, TO_ROOM);
            return;
        }
        GET_OBJ_VAL(obj, 2)--;
        WAIT_STATE(ch, PULSE_VIOLENCE);
        if (GET_OBJ_VAL(obj, 0))
            call_magic(ch, tch, tobj, get_spell(GET_OBJ_VAL(obj, 3), __FILE__, __FUNCTION__),
                       GET_OBJ_VAL(obj, 0), CAST_WAND, 0);
        else
            call_magic(ch, tch, tobj, get_spell(GET_OBJ_VAL(obj, 3), __FILE__, __FUNCTION__),
                       DEFAULT_WAND_LVL, CAST_WAND, 0);
        break;
    case ITEM_SCROLL:
        if (*arg) {
            if (!k) {
                act("There is nothing to here to affect with $p.", FALSE,
                    ch, obj, NULL, TO_CHAR);
                return;
            }
        } else
            tch = ch;

        act("You recite $p which dissolves.", TRUE, ch, obj, 0, TO_CHAR);
        if (obj->action_description)
            act(obj->action_description, FALSE, ch, obj, NULL, TO_ROOM);
        else
            act("$n recites $p.", FALSE, ch, obj, NULL, TO_ROOM);

        WAIT_STATE(ch, PULSE_VIOLENCE);
        for (i = 1; i <= 3; i++)
            if (call_magic(ch, tch, tobj, get_spell(GET_OBJ_VAL(obj, i), __FILE__, __FUNCTION__),
                           GET_OBJ_VAL(obj, 0), CAST_SCROLL, 0) <= 0)
                break;

        if (obj != NULL)
            extract_obj(obj);
        break;
    case ITEM_POTION:
        tch = ch;
        act("You quaff $p.", FALSE, ch, obj, NULL, TO_CHAR);
        if (obj->action_description)
            act(obj->action_description, FALSE, ch, obj, NULL, TO_ROOM);
        else
            act("$n quaffs $p.", TRUE, ch, obj, NULL, TO_ROOM);

        WAIT_STATE(ch, PULSE_VIOLENCE);
        for (i = 1; i <= 3; i++)
            if (call_magic(ch, ch, NULL, get_spell(GET_OBJ_VAL(obj, i), __FILE__, __FUNCTION__),
                           GET_OBJ_VAL(obj, 0), CAST_POTION, 0) <= 0)
                break;

        if (obj != NULL)
            extract_obj(obj);
        break;
    case ITEM_SPELLBOOK:
        tch = ch;
        act("You study $p.", FALSE, ch, obj, NULL, TO_CHAR);
        if (obj->action_description)
            act(obj->action_description, FALSE, ch, obj, NULL, TO_ROOM);
        else
            act("$n studies $p.", TRUE, ch, obj, NULL, TO_ROOM);

        WAIT_STATE(ch, PULSE_VIOLENCE);
        for (i = 1; i <= 3; i++) {
            if (GET_OBJ_VAL(obj, i) < 0) break;
            if (GET_SKILL(ch, GET_OBJ_VAL(obj, i)) < 1)
                SET_SKILL(ch, GET_OBJ_VAL(obj, i), GET_OBJ_VAL(obj, 0));
        }

        if (obj != NULL)
            extract_obj(obj);
        break;
    default:
        extended_mudlog(NRM, SYSL_BUGS, TRUE, "Unknown object_type %d in mag_objectmagic.",
                        GET_OBJ_TYPE(obj));
        break;
    }
}