Esempio n. 1
0
/* Add inscription */
void do_cmd_inscribe(cmd_code code, cmd_arg args[])
{
	object_type *o_ptr = object_from_item_idx(args[0].item);

	o_ptr->note = quark_add(args[1].string);

	p_ptr->notice |= (PN_COMBINE | PN_SQUELCH | PN_SORT_QUIVER);
	p_ptr->redraw |= (PR_INVEN | PR_EQUIP);
}
Esempio n. 2
0
/* Check if the given spell is in the given book. */
bool spell_in_book(int spell, int book)
{
	struct spell *sp;
	object_type *o_ptr = object_from_item_idx(book);

	for (sp = o_ptr->kind->spells; sp; sp = sp->next)
		if (spell == sp->spell_index)
			return TRUE;

	return FALSE;
}
Esempio n. 3
0
/* Check if the given spell is in the given book. */
bool spell_in_book(int spell, int book)
{
    object_type *o_ptr = object_from_item_idx(book);
    int start = mp_ptr->book_start_index[o_ptr->sval];
    int end = mp_ptr->book_start_index[o_ptr->sval + 1];

    if ((spell >= start) && (spell < end))
	return TRUE;

    return FALSE;
}
Esempio n. 4
0
/* Remove inscription */
void do_cmd_uninscribe(cmd_code code, cmd_arg args[])
{
	object_type *o_ptr = object_from_item_idx(args[0].item);

	if (obj_has_inscrip(o_ptr))
		msg("Inscription removed.");

	o_ptr->note = 0;

	p_ptr->notice |= (PN_COMBINE | PN_SQUELCH | PN_SORT_QUIVER);
	p_ptr->redraw |= (PR_INVEN | PR_EQUIP);
}
Esempio n. 5
0
/* Gain a random spell from the given book (for priests) */
void do_cmd_study_book(cmd_code code, cmd_arg args[])
{
    int book = args[0].item;
    object_type *o_ptr = object_from_item_idx(book);

    int spell = -1;
    int i, k = 0;

    cptr p = ((cp_ptr->spell_book == TV_MAGIC_BOOK) ? "spell" : "prayer");

    /* Check the player can study at all atm */
    if (!player_can_study())
        return;

    /* Check that the player has access to the nominated spell book. */
    if (!item_is_available(book, obj_can_browse, (USE_INVEN | USE_FLOOR)))
    {
        msg_format("That item is not within your reach.");
        return;
    }

    /* Extract spells */
    for (i = 0; i < SPELLS_PER_BOOK; i++)
    {
        int s = get_spell_index(o_ptr, i);

        /* Skip non-OK spells */
        if (s == -1) continue;
        if (!spell_okay_to_study(s)) continue;

        /* Apply the randomizer */
        if ((++k > 1) && (randint0(k) != 0)) continue;

        /* Track it */
        spell = s;
    }

    if (spell < 0)
    {
        msg_format("You cannot learn any %ss in that book.", p);
    }
    else
    {
        spell_learn(spell);
        p_ptr->energy_use = 100;
    }
}
Esempio n. 6
0
/* Take off an item */
void do_cmd_takeoff(cmd_code code, cmd_arg args[])
{
	int item = args[0].item;

	if (!item_is_available(item, NULL, USE_EQUIP))
	{
		msg("You are not wielding that item.");
		return;
	}

	if (!obj_can_takeoff(object_from_item_idx(item)))
	{
		msg("You cannot take off that item.");
		return;
	}

	(void)inven_takeoff(item, 255);
	pack_overflow();
	p_ptr->energy_use = 50;
}
Esempio n. 7
0
/* Gain a random spell from the given book (for priests) */
void do_cmd_study_book(cmd_code code, cmd_arg args[])
{
	int book = args[0].item;
	object_type *o_ptr = object_from_item_idx(book);

	int spell = -1;
	struct spell *sp;
	int k = 0;

	const char *p = ((cp_ptr->spell_book == TV_MAGIC_BOOK) ? "spell" : "prayer");

	/* Check the player can study at all atm */
	if (!player_can_study())
		return;

	/* Check that the player has access to the nominated spell book. */
	if (!item_is_available(book, obj_can_browse, (USE_INVEN | USE_FLOOR)))
	{
		msg("That item is not within your reach.");
		return;
	}

	/* Extract spells */
	for (sp = o_ptr->kind->spells; sp; sp = sp->next) {
		if (!spell_okay_to_study(sp->spell_index))
			continue;
		if ((++k > 1) && (randint0(k) != 0))
			continue;
		spell = sp->spell_index;
	}

	if (spell < 0)
	{
		msg("You cannot learn any %ss in that book.", p);
	}
	else
	{
		spell_learn(spell);
		p_ptr->energy_use = 100;	
	}
}
Esempio n. 8
0
void do_cmd_refill(cmd_code code, cmd_arg args[])
{
	object_type *j_ptr = &p_ptr->inventory[INVEN_LIGHT];
	bitflag f[OF_SIZE];

	int item = args[0].item;
	object_type *o_ptr = object_from_item_idx(item);

	if (!item_is_available(item, NULL, USE_INVEN | USE_FLOOR))
	{
		msg("You do not have that item to refill with it.");
		return;
	}

	/* Check what we're wielding. */
	object_flags(j_ptr, f);

	if (j_ptr->tval != TV_LIGHT)
	{
		msg("You are not wielding a light.");
		return;
	}

	else if (of_has(f, OF_NO_FUEL))
	{
		msg("Your light cannot be refilled.");
		return;
	}

	/* It's a lamp */
	if (j_ptr->sval == SV_LIGHT_LANTERN)
		refill_lamp(j_ptr, o_ptr, item);

	/* It's a torch */
	else if (j_ptr->sval == SV_LIGHT_TORCH)
		refuel_torch(j_ptr, o_ptr, item);

	p_ptr->energy_use = 50;
}
Esempio n. 9
0
/* Drop an item */
void do_cmd_drop(cmd_code code, cmd_arg args[])
{
	int item = args[0].item;
	object_type *o_ptr = object_from_item_idx(item);
	int amt = args[1].number;

	if (!item_is_available(item, NULL, USE_INVEN | USE_EQUIP))
	{
		msg("You do not have that item to drop it.");
		return;
	}

	/* Hack -- Cannot remove cursed items */
	if ((item >= INVEN_WIELD) && cursed_p(o_ptr->flags))
	{
		msg("Hmmm, it seems to be cursed.");
		return;
	}

	inven_drop(item, amt);
	p_ptr->energy_use = 50;
}
Esempio n. 10
0
static void context_menu_player_display_floor(void)
{
	/* there is an item on the floor, show the inventory screen starting
	 * from the floor */
	//Term_keypress('i',0);
	int diff = weight_remaining();

	/* Hack -- Start in "inventory" mode */
	p_ptr->command_wrk = (USE_FLOOR);

	/* Save screen */
	screen_save();

	/* Prompt for a command */
	prt(format("(Inventory) Burden %d.%d lb (%d.%d lb %s). Item for command: ",
			   p_ptr->total_weight / 10, p_ptr->total_weight % 10,
			   abs(diff) / 10, abs(diff) % 10,
			   (diff < 0 ? "overweight" : "remaining")),
		0, 0);


	/* Get an item to use a context command on */
	if (get_item(&diff, NULL, NULL, CMD_NULL, USE_EQUIP|USE_INVEN|USE_FLOOR|SHOW_EMPTY|IS_HARMLESS)) {
		object_type *o_ptr;

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

		o_ptr = object_from_item_idx(diff);

		context_menu_object(o_ptr, diff);
	}

	/* Load screen */
	screen_load();
}
void MainWindow::win_obj_recall_update()
{
    win_obj_recall_wipe();
    if (!win_obj_recall_settings.win_show) return;
    if (!character_generated) return;
    if (!p_ptr->object_kind_idx && !p_ptr->object_idx) return;

    obj_recall_area->setFont(win_obj_recall_settings.win_font);
    obj_recall_area->moveCursor(QTextCursor::Start);

    QString obj_recall;

    if (p_ptr->object_idx)
    {
        object_type *o_ptr = object_from_item_idx(p_ptr->object_idx);
        obj_recall = get_object_description(o_ptr);
    }
    else // p_ptr->object_kind_idx
    {
        s16b k_idx = p_ptr->object_kind_idx;

        // Initialize and prepare a fake object
        object_type object;
        object_type *o_ptr = &object;
        o_ptr->object_wipe();
        object_prep(o_ptr, k_idx);

        if (k_info[k_idx].aware) o_ptr->ident |= (IDENT_STORE);

        /* draw it */
        obj_recall = get_object_description(o_ptr);
    }


    obj_recall_area->insertHtml(obj_recall);
}
Esempio n. 12
0
/*
 * Use an object the right way.
 *
 * There may be a BIG problem with any "effect" that can cause "changes"
 * to the inventory.  For example, a "scroll of recharging" can cause
 * a wand/staff to "disappear", moving the inventory up.  Luckily, the
 * scrolls all appear BEFORE the staffs/wands, so this is not a problem.
 * But, for example, a "staff of recharging" could cause MAJOR problems.
 * In such a case, it will be best to either (1) "postpone" the effect
 * until the end of the function, or (2) "change" the effect, say, into
 * giving a staff "negative" charges, or "turning a staff into a stick".
 * It seems as though a "rod of recharging" might in fact cause problems.
 * The basic problem is that the act of recharging (and destroying) an
 * item causes the inducer of that action to "move", causing "o_ptr" to
 * no longer point at the correct item, with horrifying results.
 */
void do_cmd_use(cmd_code code, cmd_arg args[])
{
	int item = args[0].item;
	object_type *o_ptr = object_from_item_idx(item);
	int effect;
	bool ident = FALSE, used = FALSE;
	bool was_aware = object_flavor_is_aware(o_ptr);
	int dir = 5;
	int px = p_ptr->px, py = p_ptr->py;
	int snd, boost, level;
	use_type use;
	int items_allowed = 0;

	/* Determine how this item is used. */
	if (obj_is_rod(o_ptr))
	{
		if (!obj_can_zap(o_ptr))
		{
			msg("That rod is still charging.");
			return;
		}

		use = USE_TIMEOUT;
		snd = MSG_ZAP_ROD;
		items_allowed = USE_INVEN | USE_FLOOR;
	}
	else if (obj_is_wand(o_ptr))
	{
		if (!obj_has_charges(o_ptr))
		{
			msg("That wand has no charges.");
			return;
		}

		use = USE_CHARGE;
		snd = MSG_ZAP_ROD;
		items_allowed = USE_INVEN | USE_FLOOR;
	}
	else if (obj_is_staff(o_ptr))
	{
		if (!obj_has_charges(o_ptr))
		{
			msg("That staff has no charges.");
			return;
		}

		use = USE_CHARGE;
		snd = MSG_USE_STAFF;
		items_allowed = USE_INVEN | USE_FLOOR;
	}
	else if (obj_is_food(o_ptr))
	{
		use = USE_SINGLE;
		snd = MSG_EAT;
		items_allowed = USE_INVEN | USE_FLOOR;
	}
	else if (obj_is_potion(o_ptr))
	{
		use = USE_SINGLE;
		snd = MSG_QUAFF;
		items_allowed = USE_INVEN | USE_FLOOR;
	}
	else if (obj_is_scroll(o_ptr))
	{
		/* Check player can use scroll */
		if (!player_can_read())
			return;

		use = USE_SINGLE;
		snd = MSG_GENERIC;
		items_allowed = USE_INVEN | USE_FLOOR;
	}
	else if (obj_is_activatable(o_ptr))
	{
		if (!obj_can_activate(o_ptr))
		{
			msg("That item is still charging.");
			return;
		}

		use = USE_TIMEOUT;
		snd = MSG_ACT_ARTIFACT;
		items_allowed = USE_EQUIP;
	}
	else
	{
		msg("The item cannot be used at the moment");
	}

	/* Check if item is within player's reach. */
	if (items_allowed == 0 || !item_is_available(item, NULL, items_allowed))
	{
		msg("You cannot use that item from its current location.");
		return;
	}

	/* track the object used */
	track_object(item);

	/* Figure out effect to use */
	effect = object_effect(o_ptr);

	/* If the item requires a direction, get one (allow cancelling) */
	if (obj_needs_aim(o_ptr))
		dir = args[1].direction;

	/* Check for use if necessary, and execute the effect */
	if ((use != USE_CHARGE && use != USE_TIMEOUT) || check_devices(o_ptr))
	{
		int beam = beam_chance(o_ptr->tval);

		/* Special message for artifacts */
		if (o_ptr->artifact)
		{
			msgt(snd, "You activate it.");
			if (o_ptr->artifact->effect_msg)
				activation_message(o_ptr, o_ptr->artifact->effect_msg);
			level = o_ptr->artifact->level;
		}
		else
		{
			/* Make a noise! */
			sound(snd);
			level = o_ptr->kind->level;
		}

		/* A bit of a hack to make ID work better.
			-- Check for "obvious" effects beforehand. */
		if (effect_obvious(effect)) object_flavor_aware(o_ptr);

		/* Boost damage effects if skill > difficulty */
		boost = MAX(p_ptr->state.skills[SKILL_DEVICE] - level, 0);

		/* Do effect */
		used = effect_do(effect, &ident, was_aware, dir, beam, boost);

		/* Quit if the item wasn't used and no knowledge was gained */
		if (!used && (was_aware || !ident)) return;
	}

	/* If the item is a null pointer or has been wiped, be done now */
	if (!o_ptr || !o_ptr->kind) return;

	if (ident) object_notice_effect(o_ptr);

	/* Food feeds the player */
	if (o_ptr->tval == TV_FOOD || o_ptr->tval == TV_POTION)
		(void)set_food(p_ptr->food + o_ptr->pval[DEFAULT_PVAL]);

	/* Use the turn */
	p_ptr->energy_use = 100;

	/* Mark as tried and redisplay */
	p_ptr->notice |= (PN_COMBINE | PN_REORDER);
	p_ptr->redraw |= (PR_INVEN | PR_EQUIP | PR_OBJECT);

	/*
	 * If the player becomes aware of the item's function, then mark it as
	 * aware and reward the player with some experience.  Otherwise, mark
	 * it as "tried".
	 */
	if (ident && !was_aware)
	{
		/* Object level */
		int lev = o_ptr->kind->level;

		object_flavor_aware(o_ptr);
		if (o_ptr->tval == TV_ROD) object_notice_everything(o_ptr);
		player_exp_gain(p_ptr, (lev + (p_ptr->lev / 2)) / p_ptr->lev);
		p_ptr->notice |= PN_SQUELCH;
	}
	else if (used)
	{
		object_flavor_tried(o_ptr);
	}

	/* If there are no more of the item left, then we're done. */
	if (!o_ptr->number) return;

	/* Chargeables act differently to single-used items when not used up */
	if (used && use == USE_CHARGE)
	{
		/* Use a single charge */
		o_ptr->pval[DEFAULT_PVAL]--;

		/* Describe charges */
		if (item >= 0)
			inven_item_charges(item);
		else
			floor_item_charges(0 - item);
	}
	else if (used && use == USE_TIMEOUT)
	{
		/* Artifacts use their own special field */
		if (o_ptr->artifact)
			o_ptr->timeout = randcalc(o_ptr->artifact->time, 0, RANDOMISE);
		else
			o_ptr->timeout += randcalc(o_ptr->kind->time, 0, RANDOMISE);
	}
	else if (used && use == USE_SINGLE)
	{
		/* Destroy a potion in the pack */
		if (item >= 0)
		{
			inven_item_increase(item, -1);
			inven_item_describe(item);
			inven_item_optimize(item);
		}

		/* Destroy a potion on the floor */
		else
		{
			floor_item_increase(0 - item, -1);
			floor_item_describe(0 - item);
			floor_item_optimize(0 - item);
		}
	}
	
	/* Hack to make Glyph of Warding work properly */
	if (cave->feat[py][px] == FEAT_GLYPH)
	{
		/* Push objects off the grid */
		if (cave->o_idx[py][px]) push_object(py, px);
	}


}
Esempio n. 13
0
/* Wield or wear an item */
void do_cmd_wield(cmd_code code, cmd_arg args[])
{
	object_type *equip_o_ptr;
	char o_name[80];

	unsigned n;

	int item = args[0].item;
	int slot = args[1].number;
	object_type *o_ptr = object_from_item_idx(item);

	if (!item_is_available(item, NULL, USE_INVEN | USE_FLOOR))
	{
		msg("You do not have that item to wield.");
		return;
	}

	/* Check the slot */
	if (!slot_can_wield_item(slot, o_ptr))
	{
		msg("You cannot wield that item there.");
		return;
	}

	equip_o_ptr = &p_ptr->inventory[slot];

	/* If the slot is open, wield and be done */
	if (!equip_o_ptr->kind)
	{
		wield_item(o_ptr, item, slot);
		return;
	}

	/* If the slot is in the quiver and objects can be combined */
	if (obj_is_ammo(equip_o_ptr) && object_similar(equip_o_ptr, o_ptr,
		OSTACK_QUIVER))
	{
		wield_item(o_ptr, item, slot);
		return;
	}

	/* Prevent wielding into a cursed slot */
	if (cursed_p(equip_o_ptr->flags))
	{
		object_desc(o_name, sizeof(o_name), equip_o_ptr, ODESC_BASE);
		msg("The %s you are %s appears to be cursed.", o_name,
				   describe_use(slot));
		return;
	}

	/* "!t" checks for taking off */
	n = check_for_inscrip(equip_o_ptr, "!t");
	while (n--)
	{
		/* Prompt */
		object_desc(o_name, sizeof(o_name), equip_o_ptr,
					ODESC_PREFIX | ODESC_FULL);
		
		/* Forget it */
		if (!get_check(format("Really take off %s? ", o_name))) return;
	}

	wield_item(o_ptr, item, slot);
}
Esempio n. 14
0
/*
 * Request a game command from the uI and carry out whatever actions
 * go along with it.
 */
void process_command(cmd_context ctx, bool no_request)
{
	int idx;
	game_command cmd;

	/* If we've got a command to process, do it. */
	if (cmd_get(ctx, &cmd, !no_request) == 0)
	{
		idx = cmd_idx(cmd.command);

		if (idx == -1) return;

		/* Do some sanity checking on those arguments that might have
		   been declared as "unknown", such as directions and targets. */
		switch (cmd.command)
		{
			case CMD_WALK:
			case CMD_RUN:
			case CMD_JUMP:
			case CMD_OPEN:
			case CMD_CLOSE:
			case CMD_TUNNEL:
			case CMD_DISARM:
			case CMD_BASH:
			case CMD_ALTER:
			case CMD_JAM:
			case CMD_MAKE_TRAP:
			{
				/* Direction hasn't been specified, so we ask for one. */
				if (cmd.args[0].direction == DIR_UNKNOWN)
				{
					if (!get_rep_dir(&cmd.args[0].direction))
						return;
				}

				break;
			}

			/*
			 * These take an item number and a  "target" as arguments,
			 * though a target isn't always actually needed, so we'll
			 * only prompt for it via callback if the item being used needs it.
			 */
			case CMD_USE_WAND:
			case CMD_USE_ROD:
			case CMD_QUAFF:
			case CMD_ACTIVATE:
			case CMD_READ_SCROLL:
			case CMD_FIRE:
			case CMD_THROW:
			case CMD_STEAL:
			{
				bool get_target = FALSE;

				if (cmd.command == CMD_FIRE ||
					cmd.command == CMD_THROW ||
					obj_needs_aim(object_from_item_idx(cmd.args[0].choice)))
				{
					if (cmd.args[1].direction == DIR_UNKNOWN)
						get_target = TRUE;

					if (cmd.args[1].direction == DIR_TARGET && !target_okay())
						get_target = TRUE;
				}

				if (get_target && !get_aim_dir(&cmd.args[1].direction, FALSE))
						return;

				break;
			}

			/* This takes a choice and a direction. */
			case CMD_CAST:
			{
				bool get_target = FALSE;

				if (spell_needs_aim(cp_ptr->spell_book, cmd.args[0].choice))
				{
					if (cmd.args[1].direction == DIR_UNKNOWN)
						get_target = TRUE;

					if (cmd.args[1].direction == DIR_TARGET && !target_okay())
						get_target = TRUE;

				}

				if (get_target && !get_aim_dir(&cmd.args[1].direction, FALSE))
						return;

				break;
			}

			default:
			{
				/* I can see the point of the compiler warning, but still... */
				break;
			}
		}

		/* Command repetition */
		if (game_cmds[idx].repeat_allowed)
		{
			/* Auto-repeat */
			if (game_cmds[idx].auto_repeat_n > 0 && p_ptr->command_arg == 0 && p_ptr->command_rep == 0)
				p_ptr->command_arg = game_cmds[idx].auto_repeat_n;

			allow_repeated_command();
		}

		repeat_prev_allowed = TRUE;

		if (game_cmds[idx].fn)
			game_cmds[idx].fn(cmd.command, cmd.args);
	}
}
Esempio n. 15
0
/*
 * Throw an object from the pack or floor.
 *
 * Note: "unseen" monsters are very hard to hit.
 *
 * Should throwing a weapon do full damage?  Should it allow the magic
 * to hit bonus of the weapon to have an effect?  Should it ever cause
 * the item to be destroyed?  Should it do any damage at all?
 */
void do_cmd_throw(cmd_code code, cmd_arg args[])
{
	int dir, item;
	int i, j, y, x;
	s16b ty, tx;
	int chance, tdam, tdis;
	int weight;

	object_type *o_ptr;

	object_type *i_ptr;
	object_type object_type_body;

	bool hit_body = FALSE;

	byte missile_attr;
	char missile_char;

	char o_name[80];

	u32b msg_type = 0;

	int path_n;
	u16b path_g[256];

	int msec = op_ptr->delay_factor * op_ptr->delay_factor;

	/* Get item to throw and direction in which to throw it. */
	item = args[0].item;
	dir = args[1].direction;

	/* Make sure the player isn't throwing wielded items */
	if (item >= INVEN_WIELD && item < QUIVER_START)
	{
		msg_print("You have cannot throw wielded items.");
		return;
	}

	/* Check the item being thrown is usable by the player. */
	if (!item_is_available(item, NULL, (USE_EQUIP | USE_INVEN | USE_FLOOR)))
	{
		msg_format("That item is not within your reach.");
		return;
	}

	/* Get the object */
	o_ptr = object_from_item_idx(item);
	object_notice_on_firing(o_ptr);

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

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

	/* Distribute the charges of rods/wands/staves between the stacks */
	distribute_charges(o_ptr, i_ptr, 1);

	/* Single object */
	i_ptr->number = 1;

	/* Reduce and describe inventory */
	if (item >= 0)
	{
		inven_item_increase(item, -1);
		inven_item_describe(item);
		inven_item_optimize(item);
	}

	/* Reduce and describe floor item */
	else
	{
		floor_item_increase(0 - item, -1);
		floor_item_optimize(0 - item);
	}


	/* Description */
	object_desc(o_name, sizeof(o_name), i_ptr, ODESC_FULL);

	/* Find the color and symbol for the object for throwing */
	missile_attr = object_attr(i_ptr);
	missile_char = object_char(i_ptr);


	/* Enforce a minimum "weight" of one pound */
	weight = ((i_ptr->weight > 10) ? i_ptr->weight : 10);

	/* Hack -- Distance -- Reward strength, penalize weight */
	tdis = (adj_str_blow[p_ptr->state.stat_ind[A_STR]] + 20) * 10 / weight;

	/* Max distance of 10 */
	if (tdis > 10) tdis = 10;

	/* Hack -- Base damage from thrown object */
	tdam = damroll(i_ptr->dd, i_ptr->ds);
	if (!tdam) tdam = 1;
	tdam += i_ptr->to_d;

	/* Chance of hitting */
	chance = (p_ptr->state.skills[SKILL_TO_HIT_THROW] + (p_ptr->state.to_h * BTH_PLUS_ADJ));


	/* Take a turn */
	p_ptr->energy_use = 100;


	/* Start at the player */
	y = p_ptr->py;
	x = p_ptr->px;

	/* Predict the "target" location */
	ty = p_ptr->py + 99 * ddy[dir];
	tx = p_ptr->px + 99 * ddx[dir];

	/* Check for "target request" */
	if ((dir == 5) && target_okay())
	{
		target_get(&tx, &ty);
	}

	/* Calculate the path */
	path_n = project_path(path_g, tdis, p_ptr->py, p_ptr->px, ty, tx, 0);


	/* Hack -- Handle stuff */
	handle_stuff();

	/* Project along the path */
	for (i = 0; i < path_n; ++i)
	{
		int ny = GRID_Y(path_g[i]);
		int nx = GRID_X(path_g[i]);

		/* Hack -- Stop before hitting walls */
		if (!cave_floor_bold(ny, nx)) break;

		/* Advance */
		x = nx;
		y = ny;

		/* Only do visuals if the player can "see" the missile */
		if (player_can_see_bold(y, x))
		{
			/* Visual effects */
			print_rel(missile_char, missile_attr, y, x);
			move_cursor_relative(y, x);

			Term_fresh();
			if (p_ptr->redraw) redraw_stuff();

			Term_xtra(TERM_XTRA_DELAY, msec);
			light_spot(y, x);

			Term_fresh();
			if (p_ptr->redraw) redraw_stuff();
		}

		/* Delay anyway for consistency */
		else
		{
			/* Pause anyway, for consistancy */
			Term_xtra(TERM_XTRA_DELAY, msec);
		}

		/* Handle monster */
		if (cave_m_idx[y][x] > 0)
		{
			monster_type *m_ptr = &mon_list[cave_m_idx[y][x]];
			monster_race *r_ptr = &r_info[m_ptr->r_idx];

			int chance2 = chance - distance(p_ptr->py, p_ptr->px, y, x);

			int visible = m_ptr->ml;

			/* Note the collision */
			hit_body = TRUE;

			/* Did we hit it (penalize range) */
			if (test_hit(chance2, r_ptr->ac, m_ptr->ml))
			{
				const char *hit_verb = "hits";
				bool fear = FALSE;
				const slay_t *best_s_ptr = NULL;

				/* Assume a default death */
				cptr note_dies = " dies.";

				/* Some monsters get "destroyed" */
				if (monster_is_unusual(r_ptr))
				{
					/* Special note at death */
					note_dies = " is destroyed.";
				}

				/* Apply special damage  - brought forward to fill in hit_verb XXX XXX XXX */
				improve_attack_modifier(i_ptr, m_ptr, &best_s_ptr);
				if (best_s_ptr != NULL)
				{
					tdam *= best_s_ptr->mult;
					hit_verb = best_s_ptr->range_verb;
				}
				/* Apply special damage XXX XXX XXX */
				tdam = critical_shot(i_ptr->weight, i_ptr->to_h, tdam, &msg_type);

				/* No negative damage; change verb if no damage done */
				if (tdam <= 0)
				{
					tdam = 0;
					hit_verb = "fail to harm";
				}

				/* Handle unseen monster */
				if (!visible)
				{
					/* Invisible monster */
					msg_format("The %s finds a mark.", o_name);
				}

				/* Handle visible monster */
				else
				{
					char m_name[80];

					/* Get "the monster" or "it" */
					monster_desc(m_name, sizeof(m_name), m_ptr, 0);

					/* Tell the player what happened */
					if (msg_type == MSG_SHOOT_HIT)
						message_format(MSG_SHOOT_HIT, 0, "The %s %s %s.", o_name, hit_verb, m_name);
					else
					{
						if (msg_type == MSG_HIT_GOOD)
						{
							message_format(MSG_HIT_GOOD, 0, "The %s %s %s. %s", o_name, hit_verb, m_name,
										   "It was a good hit!");
						}
						else if (msg_type == MSG_HIT_GREAT)
						{
							message_format(MSG_HIT_GREAT, 0, "The %s %s %s. %s", o_name, hit_verb, m_name,
										   "It was a great hit!");
						}
						else if (msg_type == MSG_HIT_SUPERB)
						{
							message_format(MSG_HIT_SUPERB, 0, "The %s %s %s. %s", o_name, hit_verb, m_name,
										   "It was a superb hit!");
						}
					}
					/* Hack -- Track this monster race */
					if (m_ptr->ml) monster_race_track(m_ptr->r_idx);

					/* Hack -- Track this monster */
					if (m_ptr->ml) health_track(cave_m_idx[y][x]);
				}

				/* Learn the bonuses */
				/* XXX Eddie This is messed up, better done for firing, */
				/* should use that method [split last] instead */
				/* check if inven_optimize removed what o_ptr referenced */
				if (object_similar(i_ptr, o_ptr, OSTACK_PACK))
					object_notice_attack_plusses(o_ptr);
				object_notice_attack_plusses(i_ptr);

				/* Complex message */
				if (p_ptr->wizard)
					msg_format("You do %d (out of %d) damage.",
							   tdam, m_ptr->hp);

				/* Hit the monster, check for death */
				if (mon_take_hit(cave_m_idx[y][x], tdam, &fear, note_dies))
				{
					/* Dead monster */
				}

				/* No death */
				else
				{
					/* Message */
					message_pain(cave_m_idx[y][x], tdam);

					/* Take note */
					if (fear && m_ptr->ml)
					{
						char m_name[80];

						/* Get the monster name (or "it") */
						monster_desc(m_name, sizeof(m_name), m_ptr, 0);

						/* Message */
						message_format(MSG_FLEE, m_ptr->r_idx,
						               "%^s flees in terror!", m_name);
					}
				}
			}

			/* Stop looking */
			break;
		}
	}

	/* Chance of breakage (during attacks) */
	j = (hit_body ? breakage_chance(i_ptr) : 0);

	/* Drop (or break) near that location */
	drop_near(i_ptr, j, y, x, TRUE);
}
Esempio n. 16
0
/*
 * Play with an item. Options include:
 *   - Output statistics (via wiz_roll_item)
 *   - Reroll item (via wiz_reroll_item)
 *   - Change properties (via wiz_tweak_item)
 *   - Change the number of items (via wiz_quantity_item)
 */
static void do_cmd_wiz_play(void)
{
	int item;

	object_type *i_ptr;
	object_type object_type_body;

	object_type *o_ptr;

	struct keypress ch;

	const char *q, *s;

	bool changed = FALSE;
	bool all = TRUE;


	/* Get an item */
	q = "Play with which object? ";
	s = "You have nothing to play with.";
	if (!get_item(&item, q, s, 0, (USE_EQUIP | USE_INVEN | USE_FLOOR))) return;

	o_ptr = object_from_item_idx(item);

	/* Save screen */
	screen_save();


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

	/* Copy object */
	object_copy(i_ptr, o_ptr);


	/* The main loop */
	while (TRUE)
	{
		/* Display the item */
		wiz_display_item(i_ptr, all);

		/* Get choice */
		if (!get_com("[a]ccept [s]tatistics [r]eroll [t]weak [c]urse [q]uantity [k]nown? ", &ch))
			break;

		if (ch.code == 'A' || ch.code == 'a')
		{
			changed = TRUE;
			break;
		}
		else if (ch.code == 'c' || ch.code == 'C')
			wiz_tweak_curse(i_ptr);
		else if (ch.code == 's' || ch.code == 'S')
			wiz_statistics(i_ptr, p_ptr->depth);
		else if (ch.code == 'r' || ch.code == 'R')
			wiz_reroll_item(i_ptr);
		else if (ch.code == 't' || ch.code == 'T')
			wiz_tweak_item(i_ptr);
		else if (ch.code == 'k' || ch.code == 'K')
			all = !all;
		else if (ch.code == 'q' || ch.code == 'Q')
		{
			bool carried = (item >= 0) ? TRUE : FALSE;
			wiz_quantity_item(i_ptr, carried);
		}
	}


	/* Load screen */
	screen_load();


	/* Accept change */
	if (changed)
	{
		/* Message */
		msg("Changes accepted.");

		/* Change */
		object_copy(o_ptr, i_ptr);

		/* Recalculate bonuses */
		p_ptr->update |= (PU_BONUS);

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

		/* Window stuff */
		p_ptr->redraw |= (PR_INVEN | PR_EQUIP );
	}

	/* Ignore change */
	else
	{
		msg("Changes ignored.");
	}
}
Esempio n. 17
0
// Repeat the previous command
// Assumes the command and args were properly saved
void do_cmd_repeat(void)
{
    if (!character_dungeon) return;
    if (!p_ptr->command_previous) return;

    // repeat the previous command
    command_type *command_ptr = &command_info[p_ptr->command_previous];

    // Make sure we are dealing with the same item
    if (command_ptr->cmd_needs & (ARG_ITEM))
    {
        object_type *o_ptr = object_from_item_idx(p_ptr->command_previous_args.item);

        if (o_ptr->k_idx != p_ptr->command_previous_args.k_idx)
        {
            pop_up_message_box("Unable to repeat command.<br>Item has been moved or changed.");
            p_ptr->player_previous_command_wipe();
            return;
        }
    }

    if (p_ptr->command_previous == CMD_CAST)
    {

        if (!spell_needs_aim(cp_ptr->spell_book, p_ptr->command_previous_args.number)) p_ptr->command_previous_args.direction = DIR_UNKNOWN;
        else if (p_ptr->command_previous_args.direction == DIR_CLOSEST)
        {
            int mode = TARGET_QUIET;

            if (!is_trap_spell(cp_ptr->spell_book, p_ptr->command_previous_args.number)) mode |= TARGET_KILL;
            else mode |= TARGET_TRAP;

            if (!target_set_closest(mode)) p_ptr->command_previous_args.direction = DIR_UNKNOWN;
        }
    }

    else if (p_ptr->command_previous == CMD_ITEM_USE)
    {
        object_type *o_ptr = object_from_item_idx(p_ptr->command_previous_args.item);

        if (!obj_needs_aim(o_ptr)) p_ptr->command_previous_args.direction = DIR_UNKNOWN;
        else if (p_ptr->command_previous_args.direction == DIR_CLOSEST)
        {
            int mode = TARGET_QUIET;

            if (!k_info[o_ptr->k_idx].is_trap_object_kind()) mode |= TARGET_KILL;
            else mode |= TARGET_TRAP;

            if (!target_set_closest(mode)) p_ptr->command_previous_args.direction = DIR_UNKNOWN;
        }
    }


    else if (!command_ptr->keep_direction())
    {
        p_ptr->command_previous_args.direction = DIR_UNKNOWN;
    }

    // Get the direction, if necessary
    if (command_ptr->needs_direction())
    {
        if (!get_aim_dir(&p_ptr->command_previous_args.direction, FALSE)) return;
    }

    command_ptr->command_function(p_ptr->command_previous_args);
}
Esempio n. 18
0
/*
 * Fire an object from the pack or floor.
 *
 * You may only fire items that "match" your missile launcher.
 *
 * See "calc_bonuses()" for more calculations and such.
 *
 * Note that "firing" a missile is MUCH better than "throwing" it.
 *
 * Note: "unseen" monsters are very hard to hit.
 *
 * Objects are more likely to break if they "attempt" to hit a monster.
 *
 * Rangers (with Bows) and Anyone (with "Extra Shots") get extra shots.
 * The "extra shot" code works by decreasing the amount of energy
 * required to make each shot, spreading the shots out over time.
 *
 * Note that when firing missiles, the launcher multiplier is applied
 * after all the bonuses are added in, making multipliers very useful.
 *
 * Note that Bows of "Extra Might" get extra range and an extra bonus
 * for the damage multiplier.
 */
void do_cmd_fire(cmd_code code, cmd_arg args[])
{
	int dir, item;
	int i, j, y, x;
	s16b ty, tx;
	int tdam, tdis, thits;
	int bonus, chance;

	object_type *o_ptr;
	object_type *j_ptr;

	object_type *i_ptr;
	object_type object_type_body;

	bool hit_body = FALSE;

	byte missile_attr;
	char missile_char;

	char o_name[80];

	u32b msg_type = 0;

	int path_n;
	u16b path_g[256];

	int msec = op_ptr->delay_factor * op_ptr->delay_factor;

	/* Get the "bow" */
	j_ptr = &p_ptr->inventory[INVEN_BOW];

	/* Require a usable launcher */
	if (!j_ptr->tval || !p_ptr->state.ammo_tval)
	{
		msg_print("You have nothing to fire with.");
		return;
	}

	/* Get item to fire and direction to fire in. */
	item = args[0].item;
	dir = args[1].direction;

	/* Check the item being fired is usable by the player. */
	if (!item_is_available(item, NULL, (USE_EQUIP | USE_INVEN | USE_FLOOR)))
	{
		msg_format("That item is not within your reach.");
		return;
	}

	/* Get the object for the ammo */
	o_ptr = object_from_item_idx(item);

	/* Check the ammo can be used with the launcher */
	if (o_ptr->tval != p_ptr->state.ammo_tval)
	{
		msg_format("That ammo cannot be fired by your current weapon.");
		return;
	}

	/* Base range XXX XXX */
	tdis = 6 + 2 * p_ptr->state.ammo_mult;

	/* Start at the player */
	x = p_ptr->px;
	y = p_ptr->py;

	/* Predict the "target" location */
	ty = y + 99 * ddy[dir];
	tx = x + 99 * ddx[dir];

	/* Check for target validity */
	if ((dir == 5) && target_okay())
	{
		target_get(&tx, &ty);
		if (distance(y, x, ty, tx) > tdis)
		{
			if (!get_check("Target out of range.  Fire anyway? "))
				return;
		}
	}

	/* Sound */
	sound(MSG_SHOOT);

	object_notice_on_firing(o_ptr);

	/* Describe the object */
	object_desc(o_name, sizeof(o_name), o_ptr, ODESC_FULL | ODESC_SINGULAR);

	/* Find the color and symbol for the object for throwing */
	missile_attr = object_attr(o_ptr);
	missile_char = object_char(o_ptr);

	/* Use the proper number of shots */
	thits = p_ptr->state.num_fire;

	/* Actually "fire" the object */
	bonus = (p_ptr->state.to_h + o_ptr->to_h + j_ptr->to_h);
	chance = p_ptr->state.skills[SKILL_TO_HIT_BOW] +
			(bonus * BTH_PLUS_ADJ);

	/* Take a (partial) turn */
	p_ptr->energy_use = (100 / thits);

	/* Calculate the path */
	path_n = project_path(path_g, tdis, y, x, ty, tx, 0);

	/* Hack -- Handle stuff */
	handle_stuff();

	/* Project along the path */
	for (i = 0; i < path_n; ++i)
	{
		int ny = GRID_Y(path_g[i]);
		int nx = GRID_X(path_g[i]);

		/* Hack -- Stop before hitting walls */
		if (!cave_floor_bold(ny, nx)) break;

		/* Advance */
		x = nx;
		y = ny;

		/* Only do visuals if the player can "see" the missile */
		if (player_can_see_bold(y, x))
		{
			/* Visual effects */
			print_rel(missile_char, missile_attr, y, x);
			move_cursor_relative(y, x);

			Term_fresh();
			if (p_ptr->redraw) redraw_stuff();

			Term_xtra(TERM_XTRA_DELAY, msec);
			light_spot(y, x);

			Term_fresh();
			if (p_ptr->redraw) redraw_stuff();
		}

		/* Delay anyway for consistency */
		else
		{
			/* Pause anyway, for consistancy */
			Term_xtra(TERM_XTRA_DELAY, msec);
		}

		/* Handle monster */
		if (cave_m_idx[y][x] > 0)
		{
			monster_type *m_ptr = &mon_list[cave_m_idx[y][x]];
			monster_race *r_ptr = &r_info[m_ptr->r_idx];

			int chance2 = chance - distance(p_ptr->py, p_ptr->px, y, x);
			int visible = m_ptr->ml;
			int multiplier = 1;

			const char *hit_verb = "hits";
			const slay_t *best_s_ptr = NULL;

			/* Note the collision */
			hit_body = TRUE;

			/* Did we hit it (penalize distance travelled) */
			if (test_hit(chance2, r_ptr->ac, m_ptr->ml))
			{
				bool fear = FALSE;

				/* Assume a default death */
				cptr note_dies = " dies.";

				improve_attack_modifier(o_ptr, m_ptr, &best_s_ptr);
				improve_attack_modifier(j_ptr, m_ptr, &best_s_ptr);
				if (best_s_ptr != NULL)
					hit_verb = best_s_ptr->range_verb;

				/* Some monsters get "destroyed" */
				if (monster_is_unusual(r_ptr))
				{
					/* Special note at death */
					note_dies = " is destroyed.";
				}

				/* Calculate multiplier */
				multiplier = p_ptr->state.ammo_mult;
				if (best_s_ptr != NULL) multiplier += best_s_ptr->mult;

				/* Apply damage: multiplier, slays, criticals, bonuses */
				tdam = damroll(o_ptr->dd, o_ptr->ds);
				tdam += o_ptr->to_d + j_ptr->to_d;
				tdam *= multiplier;
				tdam = critical_shot(o_ptr->weight, o_ptr->to_h, tdam, &msg_type);

				object_notice_attack_plusses(o_ptr);
				object_notice_attack_plusses(&p_ptr->inventory[INVEN_BOW]);

				/* No negative damage; change verb if no damage done */
				if (tdam <= 0)
				{
					tdam = 0;
					hit_verb = "fail to harm";
				}

				/* Handle unseen monster */
				if (!visible)
				{
					/* Invisible monster */
					message_format(MSG_SHOOT_HIT, 0, "The %s finds a mark.", o_name);
				}

				/* Handle visible monster */
				else
				{
					char m_name[80];

					/* Get "the monster" or "it" */
					monster_desc(m_name, sizeof(m_name), m_ptr, 0);

					/* Tell the player what happened */
					if (msg_type == MSG_SHOOT_HIT)
						message_format(MSG_SHOOT_HIT, 0, "The %s %s %s.", o_name, hit_verb, m_name);
					else
					{
						if (msg_type == MSG_HIT_GOOD)
						{
							message_format(MSG_HIT_GOOD, 0, "The %s %s %s. %s", o_name, hit_verb, m_name,
										   "It was a good hit!");
						}
						else if (msg_type == MSG_HIT_GREAT)
						{
							message_format(MSG_HIT_GREAT, 0, "The %s %s %s. %s", o_name, hit_verb, m_name,
										   "It was a great hit!");
						}
						else if (msg_type == MSG_HIT_SUPERB)
						{
							message_format(MSG_HIT_SUPERB, 0, "The %s %s %s. %s", o_name, hit_verb, m_name,
										   "It was a superb hit!");
						}
					}
					/* Hack -- Track this monster race */
					if (m_ptr->ml) monster_race_track(m_ptr->r_idx);

					/* Hack -- Track this monster */
					if (m_ptr->ml) health_track(cave_m_idx[y][x]);

				}

				/* Complex message */
				if (p_ptr->wizard)
				{
					msg_format("You do %d (out of %d) damage.",
					           tdam, m_ptr->hp);
				}

				/* Hit the monster, check for death */
				if (mon_take_hit(cave_m_idx[y][x], tdam, &fear, note_dies))
				{
					/* Dead monster */
				}

				/* No death */
				else
				{
					/* Message */
					message_pain(cave_m_idx[y][x], tdam);

					/* Take note */
					if (fear && m_ptr->ml)
					{
						char m_name[80];

						/* Get the monster name (or "it") */
						monster_desc(m_name, sizeof(m_name), m_ptr, 0);

						/* Message */
						message_format(MSG_FLEE, m_ptr->r_idx,
						               "%^s flees in terror!", m_name);
					}
				}
			}

			/* Stop looking */
			break;
		}
	}



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

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

	/* Single object */
	i_ptr->number = 1;

	if (item >= 0)
	{
		inven_item_increase(item, -1);
		inven_item_describe(item);
		inven_item_optimize(item);
	}

	/* Reduce and describe floor item */
	else
	{
		floor_item_increase(0 - item, -1);
		floor_item_optimize(0 - item);
	}


	/* Chance of breakage (during attacks) */
	j = (hit_body ? breakage_chance(i_ptr) : 0);

	/* Drop (or break) near that location */
	drop_near(i_ptr, j, y, x, TRUE);
}
Esempio n. 19
0
/**
 * This is a helper function used by do_cmd_throw and do_cmd_fire.
 *
 * It abstracts out the projectile path, display code, identify and clean up
 * logic, while using the 'attack' parameter to do work particular to each
 * kind of attack.
 */
static void ranged_helper(int item, int dir, int range, int shots, ranged_attack attack) {
	/* Get the ammo */
	object_type *o_ptr = object_from_item_idx(item);

	int i, j;
	byte missile_attr = object_attr(o_ptr);
	char missile_char = object_char(o_ptr);

	object_type object_type_body;
	object_type *i_ptr = &object_type_body;

	char o_name[80];

	int path_n;
	u16b path_g[256];

	int msec = op_ptr->delay_factor;

	/* Start at the player */
	int x = p_ptr->px;
	int y = p_ptr->py;

	/* Predict the "target" location */
	s16b ty = y + 99 * ddy[dir];
	s16b tx = x + 99 * ddx[dir];

	bool hit_target = FALSE;

	/* Check for target validity */
	if ((dir == 5) && target_okay()) {
		int taim;
		char msg[80];
		target_get(&tx, &ty);
		taim = distance(y, x, ty, tx);
		if (taim > range) {
			sprintf (msg, "Target out of range by %d squares. Fire anyway? ",
				taim - range);
			if (!get_check(msg)) return;
		}
	}

	/* Sound */
	sound(MSG_SHOOT);

	object_notice_on_firing(o_ptr);

	/* Describe the object */
	object_desc(o_name, sizeof(o_name), o_ptr, ODESC_FULL | ODESC_SINGULAR);

	/* Actually "fire" the object -- Take a partial turn */
	p_ptr->energy_use = (100 / shots);

	/* Calculate the path */
	path_n = project_path(path_g, range, y, x, ty, tx, 0);

	/* Hack -- Handle stuff */
	handle_stuff(p_ptr);

	/* Start at the player */
	x = p_ptr->px;
	y = p_ptr->py;

	/* Project along the path */
	for (i = 0; i < path_n; ++i) {
		int ny = GRID_Y(path_g[i]);
		int nx = GRID_X(path_g[i]);

		/* Hack -- Stop before hitting walls */
		if (!cave_floor_bold(ny, nx)) break;

		/* Advance */
		x = nx;
		y = ny;

		/* Only do visuals if the player can "see" the missile */
		if (player_can_see_bold(y, x)) {
			print_rel(missile_char, missile_attr, y, x);
			move_cursor_relative(y, x);

			Term_fresh();
			if (p_ptr->redraw) redraw_stuff(p_ptr);

			Term_xtra(TERM_XTRA_DELAY, msec);
			cave_light_spot(cave, y, x);

			Term_fresh();
			if (p_ptr->redraw) redraw_stuff(p_ptr);
		} else {
			/* Delay anyway for consistency */
			Term_xtra(TERM_XTRA_DELAY, msec);
		}

		/* Handle monster */
		if (cave->m_idx[y][x] > 0) break;
	}

	/* Try the attack on the monster at (x, y) if any */
	if (cave->m_idx[y][x] > 0) {
		monster_type *m_ptr = cave_monster(cave, cave->m_idx[y][x]);
		monster_race *r_ptr = &r_info[m_ptr->r_idx];
		int visible = m_ptr->ml;

		bool fear = FALSE;
		char m_name[80];
		const char *note_dies = monster_is_unusual(r_ptr) ? " is destroyed." : " dies.";

		struct attack_result result = attack(o_ptr, y, x);
		int dmg = result.dmg;
		u32b msg_type = result.msg_type;
		const char *hit_verb = result.hit_verb;

		if (result.success) {
			hit_target = TRUE;

			/* Get "the monster" or "it" */
			monster_desc(m_name, sizeof(m_name), m_ptr, 0);
		
			object_notice_attack_plusses(o_ptr);
		
			/* No negative damage; change verb if no damage done */
			if (dmg <= 0) {
				dmg = 0;
				hit_verb = "fail to harm";
			}
		
			if (!visible) {
				/* Invisible monster */
				msgt(MSG_SHOOT_HIT, "The %s finds a mark.", o_name);
			} else {
				/* Visible monster */
				if (msg_type == MSG_SHOOT_HIT)
					msgt(MSG_SHOOT_HIT, "The %s %s %s.", o_name, hit_verb, m_name);
				else if (msg_type == MSG_HIT_GOOD) {
					msgt(MSG_HIT_GOOD, "The %s %s %s. %s", o_name, hit_verb, m_name, "It was a good hit!");
				} else if (msg_type == MSG_HIT_GREAT) {
					msgt(MSG_HIT_GREAT, "The %s %s %s. %s", o_name, hit_verb, m_name,
						 "It was a great hit!");
				} else if (msg_type == MSG_HIT_SUPERB) {
					msgt(MSG_HIT_SUPERB, "The %s %s %s. %s", o_name, hit_verb, m_name,
						 "It was a superb hit!");
				}
		
				/* Track this monster */
				if (m_ptr->ml) monster_race_track(m_ptr->r_idx);
				if (m_ptr->ml) health_track(p_ptr, cave->m_idx[y][x]);
			}
		
			/* Complex message */
			if (p_ptr->wizard)
				msg("You do %d (out of %d) damage.", dmg, m_ptr->hp);
		
			/* Hit the monster, check for death */
			if (!mon_take_hit(cave->m_idx[y][x], dmg, &fear, note_dies)) {
				message_pain(cave->m_idx[y][x], dmg);
				if (fear && m_ptr->ml)
					add_monster_message(m_name, cave->m_idx[y][x], MON_MSG_FLEE_IN_TERROR, TRUE);
			}
		}
	}

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

	/* See if the ammunition broke or not */
	j = breakage_chance(i_ptr, hit_target);

	/* Drop (or break) near that location */
	drop_near(cave, i_ptr, j, y, x, TRUE);

	if (item >= 0) {
		/* The ammo is from the inventory */
		inven_item_increase(item, -1);
		inven_item_describe(item);
		inven_item_optimize(item);
	} else {
		/* The ammo is from the floor */
		floor_item_increase(0 - item, -1);
		floor_item_optimize(0 - item);
	}
}
Esempio n. 20
0
void textui_cmd_destroy(void)
{
	int item;
	object_type *o_ptr;

	char out_val[160];

	menu_type *m;
	region r;
	int selected;

	/* Get an item */
	const char *q = "Ignore which item? ";
	const char *s = "You have nothing to ignore.";
	if (!get_item(&item, q, s, CMD_DESTROY, USE_INVEN | USE_EQUIP | USE_FLOOR))
		return;

	o_ptr = object_from_item_idx(item);

	m = menu_dynamic_new();
	m->selections = lower_case;

	/* Basic ignore option */
	if (!o_ptr->ignore) {
		menu_dynamic_add(m, "This item only", IGNORE_THIS_ITEM);
	} else {
		menu_dynamic_add(m, "Unignore this item", UNIGNORE_THIS_ITEM);
	}

	/* Flavour-aware squelch */
	if (squelch_tval(o_ptr->tval) &&
			(!o_ptr->artifact || !object_flavor_is_aware(o_ptr))) {
		bool squelched = kind_is_squelched_aware(o_ptr->kind) ||
				kind_is_squelched_unaware(o_ptr->kind);

		char tmp[70];
		object_desc(tmp, sizeof(tmp), o_ptr, ODESC_BASE | ODESC_PLURAL);
		if (!squelched) {
			strnfmt(out_val, sizeof out_val, "All %s", tmp);
			menu_dynamic_add(m, out_val, IGNORE_THIS_FLAVOR);
		} else {
			strnfmt(out_val, sizeof out_val, "Unignore all %s", tmp);
			menu_dynamic_add(m, out_val, UNIGNORE_THIS_FLAVOR);
		}
	}

	/* Quality squelching */
	if (object_was_sensed(o_ptr) || object_was_worn(o_ptr) ||
			object_is_known_not_artifact(o_ptr)) {
		byte value = squelch_level_of(o_ptr);
		int type = squelch_type_of(o_ptr);

		if (object_is_jewelry(o_ptr) &&
					squelch_level_of(o_ptr) != SQUELCH_BAD)
			value = SQUELCH_MAX;

		if (value != SQUELCH_MAX && type != TYPE_MAX) {
			strnfmt(out_val, sizeof out_val, "All %s %s",
					quality_values[value].name, quality_choices[type].name);

			menu_dynamic_add(m, out_val, IGNORE_THIS_QUALITY);
		}
	}

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

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

	prt("(Enter to select, ESC) Ignore:", 0, 0);
	selected = menu_dynamic_select(m);

	screen_load();

	if (selected == IGNORE_THIS_ITEM) {
		cmd_insert(CMD_DESTROY);
		cmd_set_arg_item(cmd_get_top(), 0, item);
	} else if (selected == UNIGNORE_THIS_ITEM) {
		o_ptr->ignore = FALSE;
	} else if (selected == IGNORE_THIS_FLAVOR) {
		object_squelch_flavor_of(o_ptr);
	} else if (selected == UNIGNORE_THIS_FLAVOR) {
		kind_squelch_clear(o_ptr->kind);
	} else if (selected == IGNORE_THIS_QUALITY) {
		byte value = squelch_level_of(o_ptr);
		int type = squelch_type_of(o_ptr);

		squelch_level[type] = value;
	}

	p_ptr->notice |= PN_SQUELCH;

	menu_dynamic_free(m);
}