示例#1
0
文件: trap.c 项目: Daedelus01/angband
/**
 * Hit a trap. 
 */
extern void hit_trap(int y, int x)
{
	bool ident;
	struct trap *trap;
	struct effect *effect;

    /* Count the hidden traps here */
    int num = num_traps(cave, y, x, -1);

    /* Oops.  We've walked right into trouble. */
    if      (num == 1) msg("You stumble upon a trap!");
    else if (num >  1) msg("You stumble upon some traps!");


	/* Look at the traps in this grid */
	for (trap = cave->squares[y][x].trap; trap; trap = trap->next) {
		/* Require that trap be capable of affecting the character */
		if (!trf_has(trap->kind->flags, TRF_TRAP)) continue;
	    
		/* Disturb the player */
		disturb(player, 0);

		/* Fire off the trap */
		effect = trap->kind->effect;
		effect_do(effect, &ident, FALSE, 0, 0, 0);

		/* Trap becomes visible (always XXX) */
		trf_on(trap->flags, TRF_VISIBLE);
		sqinfo_on(cave->squares[y][x].info, SQUARE_MARK);
	}

    /* Verify traps (remove marker if appropriate) */
    (void)square_verify_trap(cave, y, x, 0);
}
示例#2
0
文件: trap.c 项目: Abigail/angband
/*
 * Handle player hitting a real trap
 */
void hit_trap(int y, int x)
{
	bool ident;
	struct feature *trap = &f_info[cave->feat[y][x]];

	/* Disturb the player */
	disturb(p_ptr, 0, 0);

	/* Run the effect */
	effect_do(trap->effect, &ident, FALSE, 0, 0, 0);
}
示例#3
0
/**
 * Process a monster spell 
 *
 * \param index is the monster spell flag (RSF_FOO)
 * \param mon is the attacking monster
 * \param seen is whether the player can see the monster at this moment
 */
void do_mon_spell(int index, struct monster *mon, bool seen)
{
	char m_name[80];
	bool ident, hits = FALSE;

	/* Extract the monster level */
	int rlev = ((mon->race->level >= 1) ? mon->race->level : 1);

	const struct monster_spell *spell = monster_spell_by_index(index);

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

	/* See if it hits */
	if (spell->hit == 100)
		hits = TRUE;
	else if (spell->hit == 0)
		hits = FALSE;
	else
		hits = check_hit(player, spell->hit, rlev);

	/* Tell the player what's going on */
	disturb(player, 1);
	spell_message(mon, spell, seen, hits);

	if (!hits) return;

	/* Try a saving throw if available */
	if (spell->save_message &&
		randint0(100) < player->state.skills[SKILL_SAVE]) {
		msg("%s", spell->save_message);
		return;
	}

	/* Do effects */
	effect_do(spell->effect, NULL, &ident, TRUE, 0, 0, 0);

	return;
}
示例#4
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);
	}


}
示例#5
0
文件: trap.c 项目: magnate/angband
/**
 * Hit a trap. 
 */
extern void hit_trap(int y, int x)
{
	bool ident = false;
	struct trap *trap;
	struct effect *effect;

    /* Count the hidden traps here */
    int num = num_traps(cave, y, x, -1);

	/* The player is safe from all traps */
	if (player_is_trapsafe(player)) return;

    /* Oops.  We've walked right into trouble. */
    if      (num == 1) msg("You stumble upon a trap!");
    else if (num >  1) msg("You stumble upon some traps!");


	/* Look at the traps in this grid */
	for (trap = square_trap(cave, y, x); trap; trap = trap->next) {
		int flag;
		bool saved = false;

		/* Require that trap be capable of affecting the character */
		if (!trf_has(trap->kind->flags, TRF_TRAP)) continue;
		if (trap->timeout) continue;

		/* Disturb the player */
		disturb(player, 0);

		/* Give a message */
		if (trap->kind->msg)
			msg(trap->kind->msg);

		/* Test for save due to flag */
		for (flag = of_next(trap->kind->save_flags, FLAG_START);
			 flag != FLAG_END;
			 flag = of_next(trap->kind->save_flags, flag + 1))
			if (player_of_has(player, flag)) {
				saved = true;
				equip_learn_flag(player, flag);
			}

		/* Test for save due to armor */
		if (trf_has(trap->kind->flags, TRF_SAVE_ARMOR) && !trap_check_hit(125))
			saved = true;

		/* Test for save due to saving throw */
		if (trf_has(trap->kind->flags, TRF_SAVE_THROW) &&
			(randint0(100) < player->state.skills[SKILL_SAVE]))
			saved = true;

		/* Save, or fire off the trap */
		if (saved) {
			if (trap->kind->msg_good)
				msg(trap->kind->msg_good);
		} else {
			if (trap->kind->msg_bad)
				msg(trap->kind->msg_bad);
			effect = trap->kind->effect;
			effect_do(effect, source_trap(trap), NULL, &ident, false, 0, 0, 0);

			/* Do any extra effects */
			if (trap->kind->effect_xtra && one_in_(2)) {
				if (trap->kind->msg_xtra)
					msg(trap->kind->msg_xtra);
				effect = trap->kind->effect_xtra;
				effect_do(effect, source_trap(trap), NULL, &ident, false, 0, 0, 0);
			}
		}

		/* Some traps drop you a dungeon level */
		if (trf_has(trap->kind->flags, TRF_DOWN))
			dungeon_change_level(player,
								 dungeon_get_next_level(player->depth, 1));

		/* Some traps drop you onto them */
		if (trf_has(trap->kind->flags, TRF_PIT))
			monster_swap(player->py, player->px, trap->fy, trap->fx);

		/* Some traps disappear after activating, all have a chance to */
		if (trf_has(trap->kind->flags, TRF_ONETIME) || one_in_(3)) {
			square_destroy_trap(cave, y, x);
			square_forget(cave, y, x);
		}

		/* Trap may have gone */
		if (!square_trap(cave, y, x)) break;

		/* Trap becomes visible (always XXX) */
		trf_on(trap->flags, TRF_VISIBLE);
		square_memorize(cave, y, x);
	}

    /* Verify traps (remove marker if appropriate) */
    (void)square_verify_trap(cave, y, x, 0);
}