void t_script_give_spell::do_action(t_hero* hero) const
{
	g_mute_icons = true;
	
	if ( (hero == NULL) || (hero->in_spellbook(get_spell())) )
		return;

	g_mute_icons = !hero->learn_spell(get_spell());
}
Exemple #2
0
/**
 * Cast a spell from a book.
 */
void textui_obj_cast(void)
{
	int item;
	int spell;

	const char *verb = magic_desc[mp_ptr->spell_realm][SPELL_VERB];
	char q[80];
	char s[80];

	if (mp_ptr->spell_realm == REALM_NONE) {
		msg("You cannot read books!");
		return;
	}

	strnfmt(q, sizeof(q), "Use which %s?",
			magic_desc[mp_ptr->spell_realm][BOOK_NOUN]);
	strnfmt(s, sizeof(s), " You have no %ss that you can use.",
			magic_desc[mp_ptr->spell_realm][BOOK_LACK]);

	item_tester_hook = obj_can_cast_from;
	if (!get_item(&item, q, s, CMD_CAST, (USE_INVEN | USE_FLOOR)))
		return;

	/* Track the object kind */
	track_object(item);

	/* Ask for a spell */
	spell =
		get_spell(object_from_item_idx(item), verb, spell_okay_to_cast);
	if (spell >= 0) {
		cmd_insert(CMD_CAST);
		cmd_set_arg_choice(cmd_get_top(), 0, spell);
	}
}
Exemple #3
0
/**
 * Study a book to gain a new spell
 */
void textui_obj_study(void)
{
	int item;
	char q[80];
	char s[80];

	if (mp_ptr->spell_realm == REALM_NONE) {
		msg("You cannot read books!");
		return;
	}

	strnfmt(q, sizeof(q), "Study which %s?",
			magic_desc[mp_ptr->spell_realm][BOOK_NOUN]);
	strnfmt(s, sizeof(s), " You have no %ss that you can study.",
			magic_desc[mp_ptr->spell_realm][BOOK_LACK]);

	item_tester_hook = obj_can_study;
	if (!get_item(&item, q, s, CMD_STUDY_BOOK, (USE_INVEN | USE_FLOOR)))
		return;

	track_object(item);
	handle_stuff(p_ptr);

	if (mp_ptr->spell_book != TV_PRAYER_BOOK) {
		int spell = get_spell(object_from_item_idx(item),
							  "study", spell_okay_to_study);
		if (spell >= 0) {
			cmd_insert(CMD_STUDY_SPELL);
			cmd_set_arg_choice(cmd_get_top(), 0, spell);
		}
	} else {
		cmd_insert(CMD_STUDY_BOOK);
		cmd_set_arg_item(cmd_get_top(), 0, item);
	}
}
Exemple #4
0
/*
 * Pray a spell
 */
void do_pray(int book)
{
	int j;

	/* Ask for a spell, allow cancel */
	if (!get_spell(&j, "prayer", "Pray which prayer? ", &book, FALSE)) return;

	/* Additional */
	if (!do_cast_xtra(book, j)) return;

	/* Tell the server */
	Send_pray(book, j);
}
Exemple #5
0
/*
 * This function should be used anytime you are not 100% sure that you have
 * a valid spell/skill number.  A typical for() loop would not need to use
 * this because you can guarantee > 0 and <= TOP_SPELL_DEFINE.
 */
char *spell_name(int num)
{
    struct spell_info_type *sptr;

    sptr = get_spell(num, __FILE__, __FUNCTION__);

    if (num > 0 && num <= top_of_spellt)
        return (sptr->name);
    else if (num == -1)
        return ("UNUSED");
    else
        return ("UNDEFINED");
}
Exemple #6
0
/*
 * Cast a spell
 */
void do_cast(int book)
{
	int j;

	/* Ask for a spell, allow cancel */
	if (!get_spell(&j, "spell", "Cast which spell? ", &book, FALSE)) return;

	/* Additional */
	if (!do_cast_xtra(book, j)) return;

	/* Tell the server */
	Send_cast(book, j);
}
Exemple #7
0
/*
 * Use a ghost ability
 */
void do_ghost(void)
{
	int book = 10; /* HACK -- USE BOOK 10 -- */
	int j;

	/* Ask for an ability, allow cancel */ 
	if (!get_spell(&j, "power", "Use which power? ", &book, FALSE)) return;

	/* Additional */
	if (!do_cast_xtra(book, j)) return;

	/* Tell the server */
	Send_ghost(j);
}
Exemple #8
0
/*
 * Study a book to gain a new spell/prayer
 */
void do_study(int book)
{
	int j;

	/* Mage -- Learn a selected spell */
	if (c_info[pclass].spell_book == TV_MAGIC_BOOK)
	{
		/* Ask for a spell, allow cancel */
		if (!get_spell(&j, "spell", "Study which spell? ", &book, FALSE)) return;
	}

	/* Priest -- Learn random spell */
	else j = -1;

	/* Tell the server */
	/* Note that if we are a priest, the server ignores the spell parameter */
	Send_gain(book, j);
}
void creature_cast_spell(creature_t* creature, creature_t* target)
{
  bool did_cast = false;

  // TODO: Cast specific spells depending on circumstance.

  spell_id spellid = creature->spellbook.spell[random(0,
      creature->spellbook.number_of_spells - 1)];
  const spell_t* spell = &get_spell(spellid);
  if ((spell->flag & SF_MISSILE)|| (spell->flag & SF_RAY))
  {
    if (in_range_of_spell(spell, creature, target->pos.x, target->pos.y)
        && !_is_ally_in_ray(creature, target))
    {
      cast_spell(spell, creature, target->pos.x, target->pos.y);
      did_cast = true;
    }
  }
  else if (spell->range == RANGE_SELF)
  {
    cast_spell(spell, creature, creature->pos.x, creature->pos.y);
    did_cast = true;
  }
  else
  {
    if (!_other_spells(spell, creature, target, did_cast))
    {
      // Smite targeted
      if (in_range_of_spell(spell, creature, target->pos.x, target->pos.y))
      {
        cast_spell(spell, creature, target->pos.x, target->pos.y);
        did_cast = true;
      }
    }
  }

  if (!did_cast)
  {
    creature->step_toward(target->pos.x, target->pos.y, target);
  }
}
Exemple #10
0
/* pick the context menu options appropiate for the item */
int context_menu_object(const object_type *o_ptr, const int slot)
{
	menu_type *m;
	region r;
	int selected;
	char *labels;
	char header[120];

	textblock *tb;
	region area = { 0, 0, 0, 0 };

	bool allowed = TRUE;
	int mode = OPT(rogue_like_commands) ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG;
	unsigned char cmdkey;

	m = menu_dynamic_new();
	if (!m || !o_ptr) {
		return 0;
	}
	object_desc(header, sizeof(header), o_ptr, ODESC_PREFIX | ODESC_BASE);

	labels = string_make(lower_case);
	m->selections = labels;

	/* 'I' is used for inspect in both keymaps. */
	menu_dynamic_add_label(m, "Inspect", 'I', MENU_VALUE_INSPECT, labels);

	if (obj_can_browse(o_ptr)) {
		if (obj_can_cast_from(o_ptr) && player_can_cast(p_ptr, FALSE)) {
			ADD_LABEL("Cast", CMD_CAST, MN_ROW_VALID);
		}

		if (obj_can_study(o_ptr) && player_can_study(p_ptr, FALSE)) {
			cmd_code study_cmd = player_has(PF_CHOOSE_SPELLS) ? CMD_STUDY_SPELL : CMD_STUDY_BOOK;
			/* Hack - Use the STUDY_BOOK command key so that we get the correct command key. */
			cmdkey = cmd_lookup_key_unktrl(CMD_STUDY_BOOK, mode);
			menu_dynamic_add_label(m, "Study", cmdkey, study_cmd, labels);
		}

		if (player_can_read(p_ptr, FALSE)) {
			ADD_LABEL("Browse", CMD_BROWSE_SPELL, MN_ROW_VALID);
		}
	}
	else if (obj_is_useable(o_ptr)) {
		if (obj_is_wand(o_ptr)) {
			menu_row_validity_t valid = (obj_has_charges(o_ptr)) ? MN_ROW_VALID : MN_ROW_INVALID;
			ADD_LABEL("Aim", CMD_USE_WAND, valid);
		}
		else if (obj_is_rod(o_ptr)) {
			menu_row_validity_t valid = (obj_can_zap(o_ptr)) ? MN_ROW_VALID : MN_ROW_INVALID;
			ADD_LABEL("Zap", CMD_USE_ROD, valid);
		}
		else if (obj_is_staff(o_ptr)) {
			menu_row_validity_t valid = (obj_has_charges(o_ptr)) ? MN_ROW_VALID : MN_ROW_INVALID;
			ADD_LABEL("Use", CMD_USE_STAFF, valid);
		}
		else if (obj_is_scroll(o_ptr)) {
			menu_row_validity_t valid = (player_can_read(p_ptr, FALSE)) ? MN_ROW_VALID : MN_ROW_INVALID;
			ADD_LABEL("Read", CMD_READ_SCROLL, valid);
		}
		else if (obj_is_potion(o_ptr)) {
			ADD_LABEL("Quaff", CMD_QUAFF, MN_ROW_VALID);
		}
		else if (obj_is_food(o_ptr)) {
			ADD_LABEL("Eat", CMD_EAT, MN_ROW_VALID);
		}
		else if (obj_is_activatable(o_ptr)) {
			menu_row_validity_t valid = (slot >= INVEN_WIELD && obj_can_activate(o_ptr)) ? MN_ROW_VALID : MN_ROW_INVALID;
			ADD_LABEL("Activate", CMD_ACTIVATE, valid);
		}
		else if (obj_can_fire(o_ptr)) {
			ADD_LABEL("Fire", CMD_FIRE, MN_ROW_VALID);
		}
		else {
			ADD_LABEL("Use", CMD_USE_ANY, MN_ROW_VALID);
		}
	}

	if (obj_can_refill(o_ptr)) {
		ADD_LABEL("Refill", CMD_REFILL, MN_ROW_VALID);
	}

	if (slot >= INVEN_WIELD && obj_can_takeoff(o_ptr)) {
		ADD_LABEL("Take off", CMD_TAKEOFF, MN_ROW_VALID);
	}
	else if (slot < INVEN_WIELD && obj_can_wear(o_ptr)) {
		//if (obj_is_armor(o_ptr)) {
		//	menu_dynamic_add(m, "Wear", 2);
		//} else {
		// 	menu_dynamic_add(m, "Wield", 2);
		//}
		ADD_LABEL("Equip", CMD_WIELD, MN_ROW_VALID);
	}

	if (slot >= 0) {
		if (!store_in_store || cave_shopnum(cave, p_ptr->py, p_ptr->px) == STORE_HOME) {
			ADD_LABEL("Drop", CMD_DROP, MN_ROW_VALID);

			if (o_ptr->number > 1) {
				/* 'D' is used for squelch in rogue keymap, so we'll just swap letters. */
				cmdkey = (mode == KEYMAP_MODE_ORIG) ? 'D' : 'k';
				menu_dynamic_add_label(m, "Drop All", cmdkey, MENU_VALUE_DROP_ALL, labels);
			}
		}
	}
	else {
		menu_row_validity_t valid = (inven_carry_okay(o_ptr)) ? MN_ROW_VALID : MN_ROW_INVALID;
		ADD_LABEL("Pick up", CMD_PICKUP, valid);
	}

	ADD_LABEL("Throw", CMD_THROW, MN_ROW_VALID);
	ADD_LABEL("Inscribe", CMD_INSCRIBE, MN_ROW_VALID);

	if (obj_has_inscrip(o_ptr)) {
		ADD_LABEL("Uninscribe", CMD_UNINSCRIBE, MN_ROW_VALID);
	}

	ADD_LABEL( (object_is_squelched(o_ptr) ? "Unignore" : "Ignore"), CMD_DESTROY, MN_ROW_VALID);

	/* work out display region */
	r.width = (int)menu_dynamic_longest_entry(m) + 3 + 2; /* +3 for tag, 2 for pad */
	r.col = Term->wid - r.width - 1;
	r.row = 1;
	r.page_rows = m->count;

	area.width = -(r.width + 2);

	/* Hack -- no flush needed */
	msg_flag = FALSE;
	screen_save();

	/* Display info */
	tb = object_info(o_ptr, OINFO_NONE);
	object_desc(header, sizeof(header), o_ptr, ODESC_PREFIX | ODESC_FULL);

	textui_textblock_place(tb, area, format("%s", header));
	textblock_free(tb);

	menu_layout(m, &r);
	region_erase_bordered(&r);

	prt(format("(Enter to select, ESC) Command for %s:", header), 0, 0);
	selected = menu_dynamic_select(m);

	menu_dynamic_free(m);
	string_free(labels);

	screen_load();

	cmdkey = cmd_lookup_key(selected, mode);

	switch (selected) {
		case -1:
			/* User cancelled the menu. */
			return 3;

		case MENU_VALUE_INSPECT:
			/* copied from textui_obj_examine */
			/* Display info */
			tb = object_info(o_ptr, OINFO_NONE);
			object_desc(header, sizeof(header), o_ptr, ODESC_PREFIX | ODESC_FULL);

			textui_textblock_show(tb, area, format("%s", header));
			textblock_free(tb);
			return 2;

		case MENU_VALUE_DROP_ALL:
			/* Drop entire stack with confirmation. */
			if (get_check(format("Drop %s? ", header))) {
				cmd_insert(store_in_store ? CMD_STASH : CMD_DROP);
				cmd_set_arg_item(cmd_get_top(), 0, slot);
				cmd_set_arg_number(cmd_get_top(), 1, o_ptr->number);
			}
			return 1;

		case CMD_STUDY_SPELL:
			/* Hack - Use the STUDY_BOOK command key so that get_item_allow() works properly. */
			cmdkey = cmd_lookup_key(CMD_STUDY_BOOK, mode);
			/* Fall through. */
		case CMD_BROWSE_SPELL:
		case CMD_STUDY_BOOK:
		case CMD_CAST:
		case CMD_DESTROY:
		case CMD_WIELD:
		case CMD_TAKEOFF:
		case CMD_INSCRIBE:
		case CMD_UNINSCRIBE:
		case CMD_PICKUP:
		case CMD_DROP:
		case CMD_REFILL:
		case CMD_THROW:
		case CMD_USE_WAND:
		case CMD_USE_ROD:
		case CMD_USE_STAFF:
		case CMD_READ_SCROLL:
		case CMD_QUAFF:
		case CMD_EAT:
		case CMD_ACTIVATE:
		case CMD_FIRE:
		case CMD_USE_ANY:
			/* Check for inscriptions that trigger confirmation. */
			allowed = key_confirm_command(cmdkey) && get_item_allow(slot, cmdkey, selected, FALSE);
			break;
		default:
			/* Invalid command; prevent anything from happening. */
			bell("Invalid context menu command.");
			allowed = FALSE;
			break;
	}

	if (!allowed)
		return 1;

	if (selected == CMD_DESTROY) {
		/* squelch or unsquelch the item */
		textui_cmd_destroy_menu(slot);
	}
	else if (selected == CMD_BROWSE_SPELL) {
		/* browse a spellbook */
		/* copied from textui_spell_browse */
		textui_book_browse(o_ptr);
		return 2;
	}
	else if (selected == CMD_STUDY_SPELL) {
		/* study a spell book */
		/* copied from textui_obj_study */
		int spell = get_spell(o_ptr, "study", spell_okay_to_study);

		if (spell >= 0) {
			cmd_insert(CMD_STUDY_SPELL);
			cmd_set_arg_choice(cmd_get_top(), 0, spell);
		}
	}
	else if (selected == CMD_CAST) {
		if (obj_can_browse(o_ptr)) {
			/* copied from textui_obj_cast */
			const char *verb = ((p_ptr->class->spell_book == TV_MAGIC_BOOK) ? "cast" : "recite");
			int spell = get_spell(o_ptr, verb, spell_okay_to_cast);

			if (spell >= 0) {
				cmd_insert(CMD_CAST);
				cmd_set_arg_choice(cmd_get_top(), 0, spell);
			}
		}
	}
	else {
Exemple #11
0
/*
 * Eat some food (from the pack or floor)
 */
void do_cmd_eat_food(void)
{
    int item, ident, lev;

    /* Must be true to let us cancel */
    bool cancel = TRUE;

    object_type *o_ptr;

    cptr q, s;

    int power;

    /* Restrict choices to food */
    item_tester_tval = TV_FOOD;

    /* Get an item */
    q = "Eat which item? ";
    s = "You have nothing to eat.";
    if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR | USE_FEATU))) return;

    /* Get the feature */
    if (item >= INVEN_TOTAL+1)
    {
        object_type object_type_body;

        o_ptr = &object_type_body;

        if (!make_feat(o_ptr, cave_feat[p_ptr->py][p_ptr->px])) return;
    }

    /* Get the item (in the pack) */
    else if (item >= 0)
    {
        o_ptr = &inventory[item];
    }

    /* Get the item (on the floor) */
    else
    {
        o_ptr = &o_list[0 - item];
    }


    /* Sound */
    sound(MSG_EAT);


    /* Take a (partial) turn */
    if ((variant_fast_floor) && (item < 0)) p_ptr->energy_use = 50;
    else if ((variant_fast_equip) && (item >= INVEN_WIELD)) p_ptr->energy_use = 50;
    else p_ptr->energy_use = 100;

    /* Identity not known yet */
    ident = FALSE;

    /* Object level */
    lev = k_info[o_ptr->k_idx].level;

    /* Get food effect */
    get_spell(&power, "use", o_ptr, FALSE);

    /* Paranoia */
    if (power < 0) return;

    /* Apply food effect */
    if (process_spell_eaten(power,0,&cancel)) ident = TRUE;

    /* Combine / Reorder the pack (later) */
    p_ptr->notice |= (PN_COMBINE | PN_REORDER);

    /* We have tried it */
    object_tried(o_ptr);

    /* The player is now aware of the object */
    if (ident && !object_aware_p(o_ptr))
    {
        object_aware(o_ptr);
        gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev);
    }
void t_script_give_spell::add_icons(t_basic_dialog* dialog) const
{
	if (g_mute_icons == false)
		dialog->add_spell(get_spell());
}
Exemple #13
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;
    }
}
Exemple #14
0
	void instance::on_cast_spell(const Event& inEvt) {
    if (!inEvt.hasProperty("Spell")) {
      Event evt(inEvt);
      reject(evt);
      return;
    }

		// find the spell object
    Spell* lSpell;
		try {
      lSpell = get_spell(convertTo<int>(inEvt.getProperty("Spell")));
    } catch (invalid_uid& e) {
      // reject the event
      log_->errorStream() << "couldn't find requested Spell with id " << inEvt.getProperty("Spell");
      Event evt(inEvt);
		  reject(evt);
      return;
    }

		Entity* lCaster = lSpell->getCaster();

    assert(lCaster && lSpell);
    log_->debugStream() << "spell cast: " << lSpell->getUID() << "#" << lSpell->getName();
    log_->debugStream() << "caster: " << lCaster->getUID() << "#" << lCaster->getName();

    // allow only ALL or CASTING spells to be cast by active puppets
    if (lSpell->getPhase() != BLOCKING && active_puppet_->getUID() != lCaster->getOwner()->getUID())
    {
      Event evt(inEvt);
		  return reject(evt);
    }
    // blocking spells can only be cast when the active is not the caster
    else if (lSpell->getPhase() == BLOCKING && active_puppet_->getUID() == lCaster->getOwner()->getUID())
    {
      Event evt(inEvt);
		  return reject(evt);
    }

    Entity* lTarget = 0;
    if (inEvt.hasProperty("T")) {
      try {
        // is the target a puppet?
        lTarget = get_puppet(convertTo<int>(inEvt.getProperty("T"))).get();
        log_->debugStream() << "target: " << lTarget->getUID() << "#" << lTarget->getName();
      } catch (invalid_uid& e) {
        try {
          // a unit?
          lTarget = get_unit(convertTo<int>(inEvt.getProperty("T")));
          log_->debugStream() << "target: " << lTarget->getUID() << "#" << lTarget->getName();
        } catch (invalid_uid& e) {
          // invalid UID
          log_->errorStream() << "couldn't find spell target with id " << inEvt.getProperty("T");
          Event evt(inEvt);
          reject(evt);
          return;
        }
      }

      assert(lTarget);
      lSpell->setTarget(lTarget);
    } else {
      // if the spell requires a target, it must be given
#ifdef PARANOID
      assert(!lSpell->requiresTarget());
#else
      // gracefully reject the event
      if (lSpell->requiresTarget())
      {
        log_->errorStream()
          << "an invalid spell request#" << lSpell->getUID()
          << "; target is required but not given";
        Event e(inEvt);
        return reject(e);
      }
#endif
      // otherwise, the spell's target is the caster itself
      lSpell->setTarget(lCaster);
    }

    // verify the caster having enough resources to cast the spell
    {
      bool valid = true;
      if (lCaster->getRank() == PUPPET)
      {
        if (lSpell->getCostWP() > ((Puppet*)lCaster)->getWP())
          valid = valid && false;

        // heroes can't have less than 1 channel
        if (lSpell->getCostChannels() >= ((Puppet*)lCaster)->getChannels())
          valid = valid && false;
      }

      if (lSpell->getCostHP() > lCaster->getHP())
        valid = valid && false;


      if (!valid)
      {
        if (lCaster->getRank() == PUPPET)
        {
          Puppet* tCaster = (Puppet*)lCaster;
          log_->errorStream()
            << "caster" << tCaster->getUID()
            << " failed the resources requirements of the spell" << lSpell->getUID()
            << " : \t "
            << lSpell->getCostWP() << ":" << lSpell->getCostHP() << ":" << lSpell->getCostChannels()
            << " vs "
            << tCaster->getWP() << ":" << tCaster->getHP() << ":" << tCaster->getChannels();
        }

        Event e(inEvt);
        return reject(e);
      }
    }

    // prepare the response event
    Event resp(inEvt);
    resp.setProperty("Spell", lSpell->getUID());
    resp.setProperty("C", lSpell->getCaster()->getUID());
    if (lSpell->requiresTarget())
      resp.setProperty("T", lSpell->getTarget()->getUID());

		// dispatch to Lua
		/*lua_getfield(lua_, LUA_GLOBALSINDEX, "process_spell");
		if(!lua_isfunction(lua_, 1))
		{
			log_->errorStream() << "could not find Lua event processor!";
			lua_pop(lua_,1);
      Event e(inEvt);
      return reject(e);
		}

    log_->debugStream() << "\t things are looking good, passing to lua: "
      << ", cost: " << lSpell->getCostWP() << ":" << lSpell->getCostHP() << ":"
      << lSpell->getCostChannels();

		tolua_pushusertype(lua_,(void*)lCaster,"Pixy::Entity");
    tolua_pushusertype(lua_,(void*)lTarget,"Pixy::Entity");
		tolua_pushusertype(lua_,(void*)lSpell,"Pixy::Spell");
		tolua_pushusertype(lua_,(void*)&inEvt,"Pixy::Event");
		try {
			lua_call(lua_, 4, 1);
		} catch (std::exception& e) {
			log_->errorStream() << "Lua Handler: " << e.what();
		}

		bool result = lua_toboolean(lua_, lua_gettop(lua_));

		lua_remove(lua_, lua_gettop(lua_));*/
    bool result = pass_to_lua(
      "Spells.onCastSpell",
      3,
      "Pixy::Entity", lCaster,
      "Pixy::Entity", lTarget,
      "Pixy::Spell", lSpell);

    log_->debugStream() << "\t back from lua: "
      << ", cost: " << lSpell->getCostWP() << ":" << lSpell->getCostHP() << ":"
      << lSpell->getCostChannels();

    // if the spell cast was successful, we first broadcast the command to
    // the clients, then detach the spell from the caster, and finally
    // we apply any resource changes to the caster and broadcast them too
    if (result) {

      // broadcast the CastSpell event to players, confirming it
      {
        resp.Feedback = EventFeedback::Ok;
        broadcast(resp);
      }

      // update the caster stats and broadcast them
      {
        Event evt(EventUID::Unassigned, EventFeedback::Ok);
        evt.setProperty("UID", lCaster->getUID());

        if (lCaster->getRank() == PUPPET)
        {
          Puppet* tCaster = static_cast<Puppet*>(lCaster);
          evt.UID = EventUID::UpdatePuppet;
          // apply WP cost, if any
          if (lSpell->getCostWP() > 0) {
            tCaster->setWP(tCaster->getWP() - lSpell->getCostWP());
            evt.setProperty("WP", tCaster->getWP());
            log_->debugStream()
              << tCaster->getName() << " paid " << lSpell->getCostWP() << " wp,"
              << " and now has " << tCaster->getWP() << " wp.";
          }
          // apply the Channels cost, if any
          if (lSpell->getCostChannels() > 0) {
            tCaster->setChannels(tCaster->getChannels() - lSpell->getCostChannels());
            evt.setProperty("Channels", tCaster->getChannels());
            log_->debugStream()
              << tCaster->getName() << " paid " << lSpell->getCostChannels() << " channels,"
              << " and now has " << tCaster->getChannels() << " channels.";
          }
        } else
          evt.UID = EventUID::UpdateUnit;

        // apply HP cost, if any
        if (lSpell->getCostHP() > 0) {
          lCaster->setHP(lCaster->getHP() - lSpell->getCostHP());
          evt.setProperty("HP", lCaster->getHP());
          log_->debugStream()
              << lCaster->getName() << " paid " << lSpell->getCostHP() << " hp,"
              << " and now has " << lCaster->getHP() << " hp.";
        }

        broadcast(evt);
      }

      // don't delete the spell object if it's a buff
      lCaster->detachSpell(lSpell->getUID(), lSpell->getDuration() == 0);

    } else {
      // we reject the request
      //Event e(inEvt);
      resp.Feedback = EventFeedback::Error;
      return reject(resp);
    }

    lSpell = 0;
    lCaster = 0;
    lTarget = 0;

		//return result;
	}
/*
 * Handle monster hitting a real trap.
 */
void mon_hit_trap(int m_idx, int y, int x)
{
	feature_type *f_ptr;
	monster_type *m_ptr = &m_list[m_idx];
	monster_race *r_ptr = &r_info[m_ptr->r_idx];

	int feat = cave_feat[y][x];

	bool fear;

	/* Option */
	if (!variant_hit_traps) return;

	/* Hack --- don't activate unknown invisible traps */
	if (cave_feat[y][x] == FEAT_INVIS) return;

	/* Get feature */
	f_ptr = &f_info[cave_feat[y][x]];

	/* Hack --- trapped doors */
	/* XXX XXX Dangerous */
	while (!(f_ptr->spell) && !(f_ptr->blow.method) && (f_ptr->flags1 & (FF1_TRAP)))
	{
		pick_trap(y,x);

		/* Error */
		if (cave_feat[y][x] == feat) break;

		feat = cave_feat[y][x];

		/* Get feature */
		f_ptr = &f_info[feat];

	}

	/* Use covered or bridged if necessary */
	if ((f_ptr->flags2 & (FF2_COVERED)) || (f_ptr->flags2 & (FF2_BRIDGED)))
	{
		f_ptr = &f_info[f_ptr->mimic];
	}

	/* Hack -- monster falls onto trap */
	if ((m_ptr->fy!=y)|| (m_ptr->fx !=x))
	{
		/* Move monster */
		monster_swap(m_ptr->fy, m_ptr->fx, y, x);
	}

	/* Apply the object */
	if ((cave_o_idx[y][x]) && (f_ptr->flags1 & (FF1_HIT_TRAP)))
	{
		object_type *o_ptr = &o_list[cave_o_idx[y][x]];

		char o_name[80];

		int power = 0;

		switch (o_ptr->tval)
		{
			case TV_BOW:
			{
				object_type *j_ptr;
				u32b f1,f2,f3;

				int i, shots = 1;

				/* Get bow */
				j_ptr = o_ptr;

				/* Get bow flags */
				object_flags(o_ptr,&f1,&f2,&f3);

				/* Apply extra shots */
				if (f1 & (TR1_SHOTS)) shots += j_ptr->pval;

				/* Test for hit */
				for (i = 0; i < shots; i++)
				{
					if (j_ptr->next_o_idx)
					{
						int ammo = j_ptr->next_o_idx;
						object_type *i_ptr;
						object_type object_type_body;

						/* Use ammo instead of bow */
						o_ptr = &o_list[ammo];

						/* Describe ammo */
						object_desc(o_name, sizeof(o_name), o_ptr, TRUE, 0);

						if ((ammo) && (test_hit_fire((j_ptr->to_h + o_ptr->to_h)* BTH_PLUS_ADJ + f_ptr->power,  r_ptr->ac * (r_ptr->flags2 & (RF2_ARMOR) ? 2 : 1), TRUE)))
						{
							int k, mult;

							switch (j_ptr->sval)
							{
								case SV_SLING:
								case SV_SHORT_BOW:
								mult = 2;
								break;
								case SV_LONG_BOW:
								case SV_LIGHT_XBOW:
									mult = 3;
									break;
								case SV_HEAVY_XBOW:
									mult = 4;
									break;
								default:
									mult = 1;
									break;
							}

							/* Apply extra might */
							if (f1 & (TR1_MIGHT)) mult += j_ptr->pval;

							k = damroll(o_ptr->dd, o_ptr->ds);
							k *= mult;

							k = tot_dam_aux(o_ptr, k, m_ptr);

							k = critical_shot(o_ptr->weight, o_ptr->to_h + j_ptr->to_h, k);
							k += o_ptr->to_d + j_ptr->to_d;

							/* No negative damage */
							if (k < 0) k = 0;

							/* Trap description */
							msg_format("%^s hits you.",o_name);

							/* Damage, check for fear and death */
							(void)mon_take_hit(cave_m_idx[y][x], k, &fear, NULL);

						}
						else
						{
							/* Trap description */
							msg_format("%^s narrowly misses you.",o_name);
						}

						/* Get local object */
						i_ptr = &object_type_body;

						/* Obtain a local object */
						object_copy(i_ptr, o_ptr);

						/* Modify quantity */
						i_ptr->number = 1;

						/* Drop nearby - some chance of breakage */
						drop_near(i_ptr,y,x,breakage_chance(i_ptr));

						/* Decrease the item */
						floor_item_increase(ammo, -1);
						floor_item_optimize(ammo);

						break;
					}
					else
					{
						/* Disarm */
						cave_alter_feat(y,x,FS_DISARM);
					}
				}
			}

			case TV_SHOT:
			case TV_ARROW:
			case TV_BOLT:
			case TV_HAFTED:
			case TV_SWORD:
			case TV_POLEARM:
			{
				object_type *i_ptr;
				object_type object_type_body;

				/* Describe ammo */
				object_desc(o_name, sizeof(o_name), o_ptr, TRUE, 0);

				/* Test for hit */
				if (test_hit_norm(o_ptr->to_h * BTH_PLUS_ADJ + f_ptr->power, r_ptr->ac, TRUE))
				{
					int k;

					k = damroll(o_ptr->dd, o_ptr->ds);

					k = tot_dam_aux(o_ptr, k, m_ptr);

					k = critical_norm(o_ptr->weight, o_ptr->to_h, k);
					k += o_ptr->to_d;

					/* Armour reduces total damage */
					k -= (k * ((p_ptr->ac < 150) ? p_ptr->ac : 150) / 250);

					/* No negative damage */
					if (k < 0) k = 0;

					/* Trap description */
					msg_format("%^s hits you.",o_name);

					/* Damage, check for fear and death */
					(void)mon_take_hit(cave_m_idx[y][x], k, &fear, NULL);

				}
				else
				{
					/* Trap description */
					msg_format("%^s narrowly misses you.",o_name);					
				}

				/* Get local object */
				i_ptr = &object_type_body;

				/* Obtain a local object */
				object_copy(i_ptr, o_ptr);

				/* Modify quantity */
				i_ptr->number = 1;

				/* Drop nearby - some chance of breakage */
				drop_near(i_ptr,y,x,breakage_chance(i_ptr));

				/* Decrease the item */
				floor_item_increase(cave_o_idx[y][x], -1);
				floor_item_optimize(cave_o_idx[y][x]);

				/* Disarm if runs out */
				if (!cave_o_idx[y][x]) cave_alter_feat(y,x,FS_DISARM);

				break;
			}

			case TV_WAND:
			case TV_STAFF:
			{
				if (o_ptr->pval > 0)
				{
					/* Get item effect */
					get_spell(&power, "use", o_ptr, FALSE);

					/* XXX Hack -- new unstacking code */
					o_ptr->stackc++;

					/* No spare charges */	
					if (o_ptr->stackc >= o_ptr->number)
					{
						/* Use a charge off the stack */
						o_ptr->pval--;

						/* Reset the stack count */
						o_ptr->stackc = 0;
					}

					/* XXX Hack -- unstack if necessary */
					if ((o_ptr->number > 1) &&
					((!variant_pval_stacks) || 
					((!object_known_p(o_ptr) && (o_ptr->pval == 2) && (o_ptr->stackc > 1)) ||
					  (!object_known_p(o_ptr) && (rand_int(o_ptr->number) <= o_ptr->stackc) &&
					  (o_ptr->stackc != 1) && (o_ptr->pval > 2)))))
					{
						object_type *i_ptr;
						object_type object_type_body;

						/* Get local object */
						i_ptr = &object_type_body;

						/* Obtain a local object */
						object_copy(i_ptr, o_ptr);

						/* Modify quantity */
						i_ptr->number = 1;

						/* Reset stack counter */
						i_ptr->stackc = 0;
 
				 		/* Unstack the used item */
				 		o_ptr->number--;

						/* Reduce the charges on the new item */
						if (o_ptr->stackc > 1)
						{
							i_ptr->pval-=2;
							o_ptr->stackc--;
						}
						else if (!o_ptr->stackc)
						{
							i_ptr->pval--;
							o_ptr->pval++;
							o_ptr->stackc = o_ptr->number-1;
						}

						(void)floor_carry(y,x,i_ptr);
					}
				}
				else
				{
					/* Disarm if runs out */
					cave_alter_feat(y,x,FS_DISARM);
				}

				break;
			}

			case TV_ROD:
			case TV_DRAG_ARMOR:
			{
				if (!((o_ptr->timeout) && ((!o_ptr->stackc) || (o_ptr->stackc >= o_ptr->number))))
				{
					int tmpval;

					/* Store pval */
					tmpval = o_ptr->timeout;

					/* Time rod out */
					o_ptr->timeout = o_ptr->pval;

					/* Get item effect */
					get_spell(&power, "use", o_ptr, FALSE);

					/* Has a power */
					/* Hack -- check if we are stacking rods */
					if ((o_ptr->timeout > 0) && (!(tmpval) || stack_force_times))
					{
						/* Hack -- one more rod charging */
						if (o_ptr->timeout) o_ptr->stackc++;

						/* Reset stack count */
						if (o_ptr->stackc == o_ptr->number) o_ptr->stackc = 0;

						/* Hack -- always use maximum timeout */
						if (tmpval > o_ptr->timeout) o_ptr->timeout = tmpval;
					}

					/* XXX Hack -- unstack if necessary */
					if ((o_ptr->number > 1) && (o_ptr->timeout > 0))
					{
						object_type *i_ptr;
						object_type object_type_body;

						/* Get local object */
						i_ptr = &object_type_body;

						/* Obtain a local object */
						object_copy(i_ptr, o_ptr);

						/* Modify quantity */
						i_ptr->number = 1;

						/* Clear stack counter */
						i_ptr->stackc = 0;

						/* Restore "charge" */
						o_ptr->timeout = tmpval;

						/* Unstack the used item */
						o_ptr->number--;

						/* Reset the stack if required */
						if (o_ptr->stackc == o_ptr->number) o_ptr->stackc = 0;

						(void)floor_carry(y,x,i_ptr);
					}
				}
				break;
			}

			case TV_POTION:
			case TV_SCROLL:
			case TV_FLASK:
			case TV_FOOD:
			{
				/* Hack -- boring food */
				if ((o_ptr->tval == TV_FOOD) && (o_ptr->sval >= SV_FOOD_MIN_FOOD))
				{
					/* Disarm */
					cave_alter_feat(y,x,FS_DISARM);
				}
				else
				{
					/* Get item effect */
					get_spell(&power, "use", o_ptr, FALSE);

					/* Decrease the item */
					floor_item_increase(cave_o_idx[y][x], -1);
					floor_item_optimize(cave_o_idx[y][x]);

					/* Disarm if runs out */
					if (!cave_o_idx[y][x]) cave_alter_feat(y,x,FS_DISARM);
				}

				break;
			}

			case TV_RUNESTONE:
			{
				u32b runes = p_ptr->cur_runes;

				int num = 0;
				s16b book[26];

				/* Hack -- use current rune */
				p_ptr->cur_runes = (2 << (o_ptr->sval-1));

				/* Fill the book with spells */
				fill_book(o_ptr,book,&num);

				/* Unhack */
				p_ptr->cur_runes = runes;

				/* Get a power */
				power = book[rand_int(num)];

				/* Decrease the item */
				floor_item_increase(cave_o_idx[y][x], -1);
				floor_item_optimize(cave_o_idx[y][x]);

				/* Disarm if runs out */
				if (!cave_o_idx[y][x]) cave_alter_feat(y,x,FS_DISARM);

				break;
			}

			default:
			{
				/* Disarm */
				cave_alter_feat(y,x,FS_DISARM);

				break;
			}
		}

		/* Has a power */
		if (power > 0)
		{
			spell_type *s_ptr = &s_info[power];

			int ap_cnt;

			/* Object is used */
			if (k_info[o_ptr->k_idx].used < MAX_SHORT) k_info[o_ptr->k_idx].used++;

			/* Scan through all four blows */
			for (ap_cnt = 0; ap_cnt < 4; ap_cnt++)
			{
				int damage = 0;

				/* Extract the attack infomation */
				int effect = s_ptr->blow[ap_cnt].effect;
				int method = s_ptr->blow[ap_cnt].method;
				int d_dice = s_ptr->blow[ap_cnt].d_dice;
				int d_side = s_ptr->blow[ap_cnt].d_side;
				int d_plus = s_ptr->blow[ap_cnt].d_plus;

				/* Hack -- no more attacks */
				if (!method) break;

				/* Mega hack -- dispel evil/undead objects */
				if (!d_side)
				{
					d_plus += 25 * d_dice;
				}

				/* Roll out the damage */
				if ((d_dice) && (d_side))
				{
					damage = damroll(d_dice, d_side) + d_plus;
				}
				else
				{
					damage = d_plus;
				}

				(void)project_m(0,0,y,x,damage, effect);
				(void)project_f(0,0,y,x,damage, effect);
			}
		}
	}

	/* Regular traps */
	else
	{
		if (f_ptr->spell)
		{
	      		make_attack_spell_aux(0,y,x,f_ptr->spell);
		}
		else if (f_ptr->blow.method)
		{
			int damage = damroll(f_ptr->blow.d_side,f_ptr->blow.d_dice);
   
			/* Apply the blow */
			project_m(0, 0, y, x, damage, f_ptr->blow.effect);
		}

		/* Get feature */
		f_ptr = &f_info[cave_feat[p_ptr->py][p_ptr->px]];

		if (f_ptr->flags1 & (FF1_HIT_TRAP))
		{
			/* Modify the location hit by the trap */
			cave_alter_feat(y,x,FS_HIT_TRAP);
		}
		else if (f_ptr->flags1 & (FF1_SECRET))
		{
			/* Discover */
			cave_alter_feat(y,x,FS_SECRET);
		}
	}
}