Example #1
0
/**
 * Helper function used with ranged_helper by do_cmd_throw.
 */
static struct attack_result make_ranged_throw(object_type *o_ptr, int y, int x) {
	struct attack_result result = {FALSE, 0, 0, "hit"};

	monster_type *m_ptr = cave_monster(cave, cave->m_idx[y][x]);
	monster_race *r_ptr = &r_info[m_ptr->r_idx];

	int bonus = p_ptr->state.to_h + o_ptr->to_h;
	int chance = p_ptr->state.skills[SKILL_TO_HIT_THROW] + bonus * BTH_PLUS_ADJ;
	int chance2 = chance - distance(p_ptr->py, p_ptr->px, y, x);

	int multiplier = 1;
	const struct slay *best_s_ptr = NULL;

	/* If we missed then we're done */
	if (!test_hit(chance2, r_ptr->ac, m_ptr->ml)) return result;

	result.success = TRUE;

	improve_attack_modifier(o_ptr, m_ptr, &best_s_ptr, TRUE, FALSE);

	/* If we have a slay, modify the multiplier appropriately */
	if (best_s_ptr != NULL) {
		result.hit_verb = best_s_ptr->range_verb;
		multiplier += best_s_ptr->mult;
	}

	/* Apply damage: multiplier, slays, criticals, bonuses */
	result.dmg = damroll(o_ptr->dd, o_ptr->ds);
	result.dmg += o_ptr->to_d;
	result.dmg *= multiplier;
	result.dmg = critical_norm(o_ptr->weight, o_ptr->to_h, result.dmg, &result.msg_type);

	return result;
}
Example #2
0
/**
 * Helper function used with ranged_helper by do_cmd_throw.
 */
static struct attack_result make_ranged_throw(struct object *obj, int y, int x)
{
	char *hit_verb = mem_alloc(20*sizeof(char));
	struct attack_result result = {FALSE, 0, 0, hit_verb};
	struct monster *mon = square_monster(cave, y, x);
	int chance = chance_of_missile_hit(player, obj, NULL, y, x);
	int multiplier = 1;
	const struct brand *b = NULL;
	const struct slay *s = NULL;

	my_strcpy(hit_verb, "hits", sizeof(hit_verb));

	/* If we missed then we're done */
	if (!test_hit(chance, mon->race->ac, mflag_has(mon->mflag, MFLAG_VISIBLE)))
		return result;

	result.success = TRUE;

	improve_attack_modifier(obj, mon, &b, &s, result.hit_verb, TRUE, TRUE,
							FALSE);

	result.dmg = ranged_damage(obj, NULL, b, s, multiplier);
	result.dmg = critical_norm(obj->weight, obj->to_h, result.dmg,
							   &result.msg_type);

	return result;
}
Example #3
0
critical_t monk_get_critical(martial_arts *ma_ptr, int hand, int mode)
{
    int min_level = ma_ptr->min_level;
    int weight = _get_weight();

    if (p_ptr->pclass == CLASS_FORCETRAINER) min_level = MAX(1, min_level - 3);

    return critical_norm(weight, min_level, p_ptr->weapon_info[hand].to_h, mode, 0);
}
Example #4
0
/**
 * Attack the monster at the given location with a single blow.
 */
static bool py_attack_real(int y, int x, bool *fear) {
	/* Information about the target of the attack */
	monster_type *m_ptr = cave_monster(cave, cave->m_idx[y][x]);
	monster_race *r_ptr = &r_info[m_ptr->r_idx];
	char m_name[80];
	bool stop = FALSE;

	/* The weapon used */
	object_type *o_ptr = &p_ptr->inventory[INVEN_WIELD];

	/* Information about the attack */
	int bonus = p_ptr->state.to_h + o_ptr->to_h;
	int chance = p_ptr->state.skills[SKILL_TO_HIT_MELEE] + bonus * BTH_PLUS_ADJ;
	bool do_quake = FALSE;
	bool success = FALSE;

	/* Default to punching for one damage */
	const char *hit_verb = "punch";
	int dmg = 1;
	u32b msg_type = MSG_HIT;

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

	/* Auto-Recall if possible and visible */
	if (m_ptr->ml) monster_race_track(m_ptr->r_idx);

	/* Track a new monster */
	if (m_ptr->ml) health_track(p_ptr, cave->m_idx[y][x]);

	/* Handle player fear (only for invisible monsters) */
	if (check_state(p_ptr, OF_AFRAID, p_ptr->state.flags)) {
		msgt(MSG_AFRAID, "You are too afraid to attack %s!", m_name);
		return FALSE;
	}

	/* Disturb the monster */
	mon_clear_timed(cave->m_idx[y][x], MON_TMD_SLEEP, MON_TMD_FLG_NOMESSAGE);

	/* See if the player hit */
	success = test_hit(chance, r_ptr->ac, m_ptr->ml);

	/* If a miss, skip this hit */
	if (!success) {
		msgt(MSG_MISS, "You miss %s.", m_name);
		return FALSE;
	}

	/* Handle normal weapon */
	if (o_ptr->kind) {
		int i;
		const struct slay *best_s_ptr = NULL;

		hit_verb = "hit";

		/* Get the best attack from all slays or
		 * brands on all non-launcher equipment */
		for (i = INVEN_LEFT; i < INVEN_TOTAL; i++) {
			struct object *obj = &p_ptr->inventory[i];
			if (obj->kind)
				improve_attack_modifier(obj, m_ptr, &best_s_ptr, TRUE, FALSE);
		}

		improve_attack_modifier(o_ptr, m_ptr, &best_s_ptr, TRUE, FALSE);
		if (best_s_ptr != NULL)
			hit_verb = best_s_ptr->melee_verb;

		dmg = damroll(o_ptr->dd, o_ptr->ds);
		dmg *= (best_s_ptr == NULL) ? 1 : best_s_ptr->mult;

		dmg += o_ptr->to_d;
		dmg = critical_norm(o_ptr->weight, o_ptr->to_h, dmg, &msg_type);

		/* Learn by use for the weapon */
		object_notice_attack_plusses(o_ptr);

		if (check_state(p_ptr, OF_IMPACT, p_ptr->state.flags) && dmg > 50) {
			do_quake = TRUE;
			wieldeds_notice_flag(p_ptr, OF_IMPACT);
		}
	}

	/* Learn by use for other equipped items */
	wieldeds_notice_on_attack();

	/* Apply the player damage bonuses */
	dmg += p_ptr->state.to_d;

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

	/* Tell the player what happened */
	if (dmg <= 0)
		msgt(MSG_MISS, "You fail to harm %s.", m_name);
	else if (msg_type == MSG_HIT)
		msgt(MSG_HIT, "You %s %s.", hit_verb, m_name);
	else if (msg_type == MSG_HIT_GOOD)
		msgt(MSG_HIT_GOOD, "You %s %s. %s", hit_verb, m_name, "It was a good hit!");
	else if (msg_type == MSG_HIT_GREAT)
		msgt(MSG_HIT_GREAT, "You %s %s. %s", hit_verb, m_name, "It was a great hit!");
	else if (msg_type == MSG_HIT_SUPERB)
		msgt(MSG_HIT_SUPERB, "You %s %s. %s", hit_verb, m_name, "It was a superb hit!");
	else if (msg_type == MSG_HIT_HI_GREAT)
		msgt(MSG_HIT_HI_GREAT, "You %s %s. %s", hit_verb, m_name, "It was a *GREAT* hit!");
	else if (msg_type == MSG_HIT_HI_SUPERB)
		msgt(MSG_HIT_HI_SUPERB, "You %s %s. %s", hit_verb, m_name, "It was a *SUPERB* hit!");

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

	/* Confusion attack */
	if (p_ptr->confusing) {
		p_ptr->confusing = FALSE;
		msg("Your hands stop glowing.");

		mon_inc_timed(cave->m_idx[y][x], MON_TMD_CONF,
				(10 + randint0(p_ptr->lev) / 10), MON_TMD_FLG_NOTIFY);
	}

	/* Damage, check for fear and death */
	stop = mon_take_hit(cave->m_idx[y][x], dmg, fear, NULL);

	if (stop)
		(*fear) = FALSE;

	/* Apply earthquake brand */
	if (do_quake) {
		earthquake(p_ptr->py, p_ptr->px, 10);
		if (cave->m_idx[y][x] == 0) stop = TRUE;
	}

	return stop;
}
Example #5
0
/**
 * Attack the monster at the given location with a single blow.
 */
static bool py_attack_real(int y, int x, bool *fear)
{
	size_t i;

	/* Information about the target of the attack */
	struct monster *mon = square_monster(cave, y, x);
	char m_name[80];
	bool stop = FALSE;

	/* The weapon used */
	struct object *obj = equipped_item_by_slot_name(player, "weapon");

	/* Information about the attack */
	int chance = py_attack_hit_chance(obj);
	bool do_quake = FALSE;
	bool success = FALSE;

	/* Default to punching for one damage */
	char verb[20];
	int dmg = 1;
	u32b msg_type = MSG_HIT;

	/* Default to punching for one damage */
	my_strcpy(verb, "punch", sizeof(verb));

	/* Extract monster name (or "it") */
	monster_desc(m_name, sizeof(m_name), mon, 
				 MDESC_OBJE | MDESC_IND_HID | MDESC_PRO_HID);

	/* Auto-Recall if possible and visible */
	if (mflag_has(mon->mflag, MFLAG_VISIBLE))
		monster_race_track(player->upkeep, mon->race);

	/* Track a new monster */
	if (mflag_has(mon->mflag, MFLAG_VISIBLE))
		health_track(player->upkeep, mon);

	/* Handle player fear (only for invisible monsters) */
	if (player_of_has(player, OF_AFRAID)) {
		msgt(MSG_AFRAID, "You are too afraid to attack %s!", m_name);
		return FALSE;
	}

	/* Disturb the monster */
	mon_clear_timed(mon, MON_TMD_SLEEP, MON_TMD_FLG_NOMESSAGE, FALSE);

	/* See if the player hit */
	success = test_hit(chance, mon->race->ac,
					   mflag_has(mon->mflag, MFLAG_VISIBLE));

	/* If a miss, skip this hit */
	if (!success) {
		msgt(MSG_MISS, "You miss %s.", m_name);
		return FALSE;
	}

	/* Handle normal weapon */
	if (obj) {
		int j;
		const struct brand *b = NULL;
		const struct slay *s = NULL;

		my_strcpy(verb, "hit", sizeof(verb));

		/* Get the best attack from all slays or
		 * brands on all non-launcher equipment */
		for (j = 2; j < player->body.count; j++) {
			struct object *obj = slot_object(player, j);
			if (obj)
				improve_attack_modifier(obj, mon, &b, &s, verb, FALSE, TRUE,
										FALSE);
		}

		improve_attack_modifier(obj, mon, &b, &s, verb, FALSE, TRUE, FALSE);

		dmg = melee_damage(obj, b, s);
		dmg = critical_norm(obj->weight, obj->to_h, dmg, &msg_type);

		/* Learn by use for the weapon */
		object_notice_attack_plusses(obj);

		if (player_of_has(player, OF_IMPACT) && dmg > 50) {
			do_quake = TRUE;
			equip_notice_flag(player, OF_IMPACT);
		}
	}

	/* Learn by use for other equipped items */
	equip_notice_on_attack(player);

	/* Apply the player damage bonuses */
	dmg += player_damage_bonus(&player->state);

	/* No negative damage; change verb if no damage done */
	if (dmg <= 0) {
		dmg = 0;
		msg_type = MSG_MISS;
		my_strcpy(verb, "fail to harm", sizeof(verb));
	}

	for (i = 0; i < N_ELEMENTS(melee_hit_types); i++) {
		const char *dmg_text = "";

		if (msg_type != melee_hit_types[i].msg)
			continue;

		if (OPT(show_damage))
			dmg_text = format(" (%d)", dmg);

		if (melee_hit_types[i].text)
			msgt(msg_type, "You %s %s%s. %s", verb, m_name, dmg_text,
					melee_hit_types[i].text);
		else
			msgt(msg_type, "You %s %s%s.", verb, m_name, dmg_text);
	}

	/* Pre-damage side effects */
	blow_side_effects(player, mon);

	/* Damage, check for fear and death */
	stop = mon_take_hit(mon, dmg, fear, NULL);

	if (stop)
		(*fear) = FALSE;

	/* Post-damage effects */
	if (blow_after_effects(y, x, do_quake))
		stop = TRUE;

	return stop;
}
Example #6
0
/*
 * Attack the monster at the given location
 *
 * If no "weapon" is available, then "punch" the monster one time.
 *
 * We get blows until energy drops below that required for another blow, or
 * until the target monster dies. We use a wrapper to work out the number of
 * blows. We don't allow @ to spend more than 100 energy in one go, to avoid
 * slower monsters getting double moves.
 */
bool py_attack_real(int y, int x)
{
	int bonus, chance;

	monster_type *m_ptr = &mon_list[cave_m_idx[y][x]];
	monster_race *r_ptr = &r_info[m_ptr->r_idx];
	monster_lore *l_ptr = &l_list[m_ptr->r_idx];

	object_type *o_ptr;

	char m_name[80];

	bool fear = FALSE;

	bool do_quake = FALSE;
	bool dead = FALSE;

	u32b msg_type = 0;
	bool success = FALSE;
	
	const char *hit_verb = "ERROR";
	int dmg = 1;
	
	/* Default to punching for one damage */
	/* Maybe handle monster melee here -Simon */
	if(!rp_ptr->p_monster_index)
	{
		hit_verb = "punch";
		msg_type = MSG_HIT;
	}

	/*
	 * Hack -- if advanced innate attacks are disabled for this race, fall back
	 * on defaults <player>'s 1d1.
	 */
	 /* TODO: this -Simon */
	/* if (p_ptr->flags[NO_INNATE])
	{
			p_ptr = &r_info[0];
	} */


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

	/* Auto-Recall if possible and visible */
	if (m_ptr->ml) monster_race_track(m_ptr->r_idx);

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

	/* Handle player fear (only for invisible monsters) */
	if (p_ptr->state.afraid)
	{
		message_format(MSG_AFRAID, 0,
				"You are too afraid to attack %s!",
				m_name);
		return (FALSE);
	}

	/* Disturb the monster */
	wake_monster(m_ptr);

	/* Get the weapon */
	o_ptr = &p_ptr->inventory[INVEN_WIELD];
	
		/* Calculate the "attack quality" */
	bonus = p_ptr->state.to_h + o_ptr->to_h;
	chance = (p_ptr->state.skills[SKILL_TO_HIT_MELEE] + (bonus * BTH_PLUS_ADJ));

	/* Handle innate melee -Simon */
	if(!o_ptr->k_idx && rp_ptr->p_monster_index)
	{
		for (int num = 0; (num < MONSTER_BLOW_MAX) && !dead; num++)
		{
			const slay_t *best_s_ptr = NULL;
			int type = GF_ARROW, type2 = 0, i;
			int flg = PROJECT_KILL | PROJECT_STOP | PROJECT_HIDE; // | PROJECT_PASS; TODO: figure out what this is and implement it -Simon
			char *p = "";
						
			if (!r_info[rp_ptr->p_monster_index].blow[num].method && !dead)
				continue;
					
			/* Test for hit */
			if (test_hit(chance, r_info[m_ptr->r_idx].ac, m_ptr->ml))
			{
				int mul = 1;
				int k = 0;
				
				/* Get the method */
				switch (r_info[rp_ptr->p_monster_index].blow[num].method)
				{
					case RBM_HIT:	p = "hit"; break;
					case RBM_TOUCH:	p = "touch"; break;
					case RBM_PUNCH:	p = "punch"; break;
					case RBM_KICK:	p = "kick"; break;
					case RBM_CLAW:	p = "claw"; break;
					case RBM_BITE:	p = "bite"; break;
					case RBM_STING:	p = "sting"; break;
					case RBM_BUTT:	p = "butt"; break;
					case RBM_CRUSH:	p = "crush"; break;
					case RBM_ENGULF:p = "engulf"; break;
					case RBM_PECK:	p = "peck"; break;
					case RBM_CRAWL:	p = "crawl on"; break;
					case RBM_DROOL:	p = "drool on"; break;
					case RBM_SPIT:	p = "spit on"; break;
					case RBM_SLIME:	p = "slime"; break;
					case RBM_GAZE:	p = "gaze at"; break;
					case RBM_WAIL:	p = "wail at"; break;
					case RBM_SPORE:	p = "release spores at"; break;
					case RBM_BEG:	p = "beg for money"; break;
					case RBM_INSULT:	p = "insult"; break;
					default: p = "attack";
				}

				/* Get the effect */
				switch (r_info[rp_ptr->p_monster_index].blow[num].effect)
				{
					case RBE_HURT: type = GF_ARROW; break;
					case RBE_DISEASE: type = GF_POIS; mul = 2; break;
					case RBE_POISON: type = GF_POIS; mul = 2; break;
					case RBE_LOSE_MANA: type = GF_DISENCHANT; break;
					case RBE_UN_BONUS: type = GF_DISENCHANT; mul = 2; break;
					case RBE_UN_POWER: type = GF_DISENCHANT; mul = 2; break; /* ? */
					case RBE_EAT_LIGHT: type = GF_DARK; mul = 2; break;
					case RBE_ACID: type = GF_ACID; mul = 2; break;
					case RBE_ELEC: type = GF_ELEC; mul = 2; break;
					case RBE_FIRE: type = GF_FIRE; mul = 2; break;
					case RBE_COLD: type = GF_COLD; mul = 2; break;
					case RBE_BLIND: type2 = GF_OLD_CONF; break; /* ? */
					case RBE_CONFUSE: type2 = GF_OLD_CONF; break;
					case RBE_TERRIFY: type2 = GF_TURN_ALL; break; /* ? */
					case RBE_PARALYZE: type2 = GF_OLD_SLEEP; break; /* ? */
					/* Earthquake would be natural, but all monsters
					 * with RBE_SHATTER are already humanoids
					 */
					case RBE_SHATTER: type = GF_ARROW; break;
					case RBE_EXP_10: type = GF_NETHER; mul = 2; break;
					case RBE_EXP_20: type = GF_NETHER; mul = 2; break;
					case RBE_EXP_40: type = GF_NETHER; mul = 2; break;
					case RBE_EXP_80: type = GF_NETHER; mul = 2; break;
					/* GF_CHAOS will polymorph, so it is bad */
					case RBE_HALLU: type = GF_DISENCHANT; mul = 2; break;
					default: type = GF_ARROW;
				}
			
				k = damroll(r_info[rp_ptr->p_monster_index].blow[num].d_dice, r_info[rp_ptr->p_monster_index].blow[num].d_side);
				/* Get the best attack from all slays or
				 * brands on all non-launcher equipment */
				for (i = INVEN_FINGER; i < INVEN_TOTAL; i++)
					improve_attack_modifier(&p_ptr->inventory[i], m_ptr, &best_s_ptr);
					
				if (best_s_ptr != NULL)
				{
					if (best_s_ptr->mult > mul)
					{
						p = best_s_ptr->melee_verb;
						mul = best_s_ptr->mult;
						if (best_s_ptr->resist_flag == RF_IM_ACID)
							type = GF_ACID;
						else if (best_s_ptr->resist_flag == RF_IM_ELEC)
							type = GF_ELEC;
						else if (best_s_ptr->resist_flag == RF_IM_FIRE)
							type = GF_FIRE;
						else if (best_s_ptr->resist_flag == RF_IM_COLD)
							type = GF_COLD;
						else if (best_s_ptr->resist_flag == RF_IM_POIS)
							type = GF_POIS;
					}
				}
				
				k *= mul;
				message_format(MSG_HIT, m_ptr->r_idx, "You %s %s.", p, m_name);
				/* Add to-dam bonus only if did some damage */
				if (k) k += p_ptr->state.to_d;
				if (k < 0) k = 0;
				
				/* Learn by use for other equipped items */
				wieldeds_notice_on_attack();
					
				/* If there is an extra effect, project it also, using 4*level as power */
				if (type2)
				{
					project(-1, 0, y, x, 4 * p_ptr->lev, type2, flg);
				}
							       
				/* Confusion attack */
				if (p_ptr->confusing)
				{
					/* Message */
					if (p_ptr->confusing)
						msg_print("Your limbs stop glowing.");
				
					/* Cancel glowing hands */
					p_ptr->confusing = FALSE;

					/* Confuse the monster */
					if (rf_has(r_ptr->flags, RF_NO_CONF))
					{
						if (m_ptr->ml)
						{
							rf_on(l_ptr->flags, RF_NO_CONF);
						}
						msg_format("%^s is unaffected.", m_name);
					}
					else if (randint0(100) < r_ptr->level)
					{
						msg_format("%^s appears slightly perplexed.", m_name);
					}
					else
					{
						msg_format("%^s appears confused.", m_name);
						m_ptr->confused += 10 + randint0(p_ptr->lev) / 5;
					}
				}
				
				/* Damage, check for fear and death */
				/* Makes elemental attacks do half their damage physically -Simon */
				if (type != GF_ARROW)
				{
					project(-1, 0, y, x, (k + 1)/2, type, flg);
					/* Make the physical portion TOP SECRET -Simon */
					flg &= ~(PROJECT_AWARE);
					project(-1, 0, y, x, k/2, GF_ARROW, flg);
				}
				else
					project(-1, 0, y, x, k, type, flg);
				/* Hack: check if the square is empty after we project the attack into it -Simon */
				dead = (cave_m_idx[y][x] == 0);
			
				/* Hack -- delay fear messages */
				if (fear && m_ptr->ml && !dead)
					message_format(MSG_FLEE, m_ptr->r_idx, "%^s flees in terror!", m_name);
			}
			/* Player misses */
			else
			{
				/* Message */
				message_format(MSG_MISS, m_ptr->r_idx, "You miss %s.", m_name);
			}
		}	
		return (TRUE);
	}
	
	else
	{
		/* See if the player hit */
		success = test_hit(chance, r_ptr->ac, m_ptr->ml);

		/* If a miss, skip this hit */
		if (!success)
		{
			message_format(MSG_MISS, m_ptr->r_idx, "You miss %s.", m_name);
			return (FALSE);
		}

		/* Handle normal weapon */
		if (o_ptr->k_idx)
		{
			int i;
			const slay_t *best_s_ptr = NULL;

			hit_verb = "hit";

			/* Get the best attack from all slays or
			 * brands on all non-launcher equipment */
			for (i = INVEN_FINGER; i < INVEN_TOTAL; i++)
				improve_attack_modifier(&p_ptr->inventory[i], m_ptr,
				&best_s_ptr);

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

			dmg = damroll(o_ptr->dd, o_ptr->ds);
			dmg *= (best_s_ptr == NULL) ? 1 : best_s_ptr->mult;

			if (p_ptr->state.impact && (dmg > 50))
				do_quake = TRUE;

			dmg += o_ptr->to_d;
			dmg = critical_norm(o_ptr->weight, o_ptr->to_h, dmg, &msg_type);

			/* Learn by use for the weapon */
			object_notice_attack_plusses(o_ptr);

			if (do_quake)
				wieldeds_notice_flag(OF_IMPACT);
		}

		/* Learn by use for other equipped items */
		wieldeds_notice_on_attack();

		/* Apply the player damage bonuses */
		dmg += p_ptr->state.to_d;

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

		/* Tell the player what happened */
		if (dmg <= 0)
			message_format(MSG_MISS, m_ptr->r_idx,
						   "You fail to harm %s.", m_name);
		else if (msg_type == MSG_HIT)
			message_format(MSG_HIT, m_ptr->r_idx, "You %s %s.",
						   hit_verb, m_name);
		else if (msg_type == MSG_HIT_GOOD)
			message_format(MSG_HIT_GOOD, m_ptr->r_idx, "You %s %s. %s",
						   hit_verb, m_name, "It was a good hit!");
		else if (msg_type == MSG_HIT_GREAT)
			message_format(MSG_HIT_GREAT, m_ptr->r_idx, "You %s %s. %s",
						   hit_verb, m_name, "It was a great hit!");
		else if (msg_type == MSG_HIT_SUPERB)
			message_format(MSG_HIT_SUPERB, m_ptr->r_idx, "You %s %s. %s",
						   hit_verb, m_name, "It was a superb hit!");
		else if (msg_type == MSG_HIT_HI_GREAT)
			message_format(MSG_HIT_HI_GREAT, m_ptr->r_idx, "You %s %s. %s",
						   hit_verb, m_name, "It was a *GREAT* hit!");
		else if (msg_type == MSG_HIT_HI_SUPERB)
			message_format(MSG_HIT_HI_SUPERB, m_ptr->r_idx, "You %s %s. %s",
						   hit_verb, m_name, "It was a *SUPERB* hit!");

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

		/* Confusion attack */
		if (p_ptr->confusing)
		{
			/* Cancel glowing hands */
			p_ptr->confusing = FALSE;

			/* Message */
			msg_print("Your limbs stop glowing.");

			/* Update the lore */
			if (m_ptr->ml)
				rf_on(l_ptr->flags, RF_NO_CONF);

			/* Confuse the monster */
			if (rf_has(r_ptr->flags, RF_NO_CONF))
				msg_format("%^s is unaffected.", m_name);
			else if (randint0(100) < r_ptr->level)
				msg_format("%^s is unaffected.", m_name);
			else
			{
				msg_format("%^s appears confused.", m_name);
				m_ptr->confused += 10 + randint0(p_ptr->lev) / 5;
			}
		}

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

		/* Hack -- delay fear messages */
		if (fear && m_ptr->ml)
			message_format(MSG_FLEE, m_ptr->r_idx, "%^s flees in terror!",
			m_name);

		/* Mega-Hack -- apply earthquake brand */
		if (do_quake) earthquake(p_ptr->py, p_ptr->px, 10);

		return (dead);
	}
}
Example #7
0
void display_innate_attack_info(doc_ptr doc, int which)
{
    innate_attack_ptr a = &p_ptr->innate_attacks[which];
    int blows, min, max, min_base, max_base, min2, max2;
    int i;
    int to_h = p_ptr->to_h_m + a->to_h;
    int to_d = p_ptr->to_d_m + a->to_d;
    int dd = a->dd + p_ptr->innate_attack_info.to_dd;
    int mult;
    doc_ptr cols[2] = {0};

    blows = a->blows;
    if (which == 0)
        blows += p_ptr->innate_attack_info.xtra_blow;

    cols[0] = doc_alloc(60);
    cols[1] = doc_alloc(10);

    /* First Column */
    if (a->flags & INNATE_NO_DAM)
        doc_printf(cols[0], "<color:y> %-7.7s</color>: Your %s\n", "Attack", a->name);
    else
        doc_printf(cols[0], "<color:y> %-7.7s</color>: Your %s (%dd%d)\n", "Attack", a->name, dd, a->ds);

    if (a->weight && !(a->flags & INNATE_NO_DAM))
        doc_printf(cols[0], " %-7.7s: %d.%d lbs\n", "Weight", a->weight/10, a->weight%10);

    {
        cptr name = skills_innate_calc_name(a);
        doc_printf(cols[0], " %-7.7s: %s (%+d To Hit)\n",
                    "Profic",
                    skills_innate_describe_current(name),
                    skills_innate_calc_bonus(name));
    }

    doc_printf(cols[0], " %-7.7s: %d + %d = %d\n", "To Hit", a->to_h, p_ptr->to_h_m, to_h);

    if (!(a->flags & INNATE_NO_DAM))
        doc_printf(cols[0], " %-7.7s: %d + %d = %d\n", "To Dam", a->to_d, p_ptr->to_d_m, to_d);

    doc_printf(cols[0], " %-7.7s: %d.%2.2d\n", "Blows", blows/100, blows%100);

    mult = 100;

    if (!(a->flags & INNATE_NO_DAM))
    {
        doc_printf(cols[0], "<color:G> %-7.7s</color>\n", "Damage");
        if (a->flags & INNATE_VORPAL)
        {
            mult = mult * 11 / 9;
            doc_printf(cols[0], " %-7.7s: %d.%02dx\n", "Vorpal", mult/100, mult%100);
        }
    }

    if (!(a->flags & INNATE_NO_DAM))
    {
        critical_t crit = {0};
        const int ct = 10 * 1000;
        for (i = 0; i < ct; i++)
        {
            critical_t tmp = critical_norm(a->weight, to_h, 0, 0, HAND_NONE);
            if (tmp.desc)
            {
                crit.mul += tmp.mul;
                crit.to_d += tmp.to_d;
            }
            else
                crit.mul += 100;
        }
        crit.mul = crit.mul / ct;
        crit.to_d = crit.to_d * 100 / ct;
        if (crit.to_d)
            doc_printf(cols[0], " %-7.7s: %d.%02dx + %d.%02d\n", "Crits", crit.mul/100, crit.mul%100, crit.to_d/100, crit.to_d%100);
        else
            doc_printf(cols[0], " %-7.7s: %d.%02dx\n", "Crits", crit.mul/100, crit.mul%100);
        crit.to_d /= 100;
        mult = mult * crit.mul / 100;
        to_d = to_d + crit.to_d;
    }

    min_base = mult * dd / 100;
    min = min_base + to_d;
    min2 = 2*(min_base + a->to_d) + p_ptr->to_d_m;
    max_base = mult * dd * a->ds / 100;
    max = max_base + to_d;
    max2 = 2*(max_base + a->to_d) + p_ptr->to_d_m;
    
    if (a->effect[0] == GF_OLD_CONF) /* Hack for Umber Hulk ... */
    {
        doc_insert(cols[0], "<tab:10><color:B>Confuses</color>\n");
    }
    else if (!(a->flags & INNATE_NO_DAM))
    {
        doc_printf(cols[0], " %-7.7s: %d (%d-%d)\n",
                _effect_name(a->effect[0]),
                blows * (min + max)/200,
                blows * min/100,
                blows * max/100
        );
    }

    for (i = 1; i < MAX_INNATE_EFFECTS; i++)
    {
        int p = a->effect_chance[i];
        char xtra[255];
        if (!a->effect[i]) continue;
        if (!p)
            sprintf(xtra, "%s", "");
        else
            sprintf(xtra, " (%d%%)", p);

        switch (a->effect[i])
        {
        case GF_STEAL: 
            doc_printf(cols[0], "<tab:10><color:B>Steals%s</color>\n", xtra);
            break;
        case GF_OLD_SLOW: 
            doc_printf(cols[0], "<tab:10><color:B>Slows%s</color>\n", xtra);
            break;
        case GF_OLD_CONF: 
            doc_printf(cols[0], "<tab:10><color:B>Confuses%s</color>\n", xtra);
            break;
        case GF_OLD_SLEEP: 
            doc_printf(cols[0], "<tab:10><color:B>Sleeps%s</color>\n", xtra);
            break;
        case GF_STASIS:
        case GF_PARALYSIS:
            doc_printf(cols[0], "<tab:10><color:B>Paralyzes%s</color>\n", xtra);
            break;
        case GF_DRAIN_MANA:
            doc_printf(cols[0], "<tab:10><color:B>Drains Mana%s</color>\n", xtra);
            break;
        case GF_STUN:
            doc_printf(cols[0], "<tab:10><color:B>Stuns%s</color>\n", xtra);
            break;
        case GF_TURN_ALL:
            doc_printf(cols[0], "<tab:10><color:r>Terrifies%s</color>\n", xtra);
            break;
        case GF_QUAKE:
            doc_printf(cols[0], "<tab:10><color:B>Shatters%s</color>\n", xtra);
            break;
        default:
            doc_printf(cols[0], "<color:r> %-7.7s</color>: %d (%d-%d)\n",
                    _effect_name(a->effect[i]),
                    blows * (min2 + max2)/200,
                    blows * min2/100,
                    blows * max2/100
            );
        }
    }

    /* Second Column */
    doc_insert(cols[1], "<color:G>Accuracy</color>\n");
    doc_insert(cols[1], " AC Hit\n");

    doc_printf(cols[1], "%3d %2d%%\n", 25, hit_chance_innate(to_h, 25));
    doc_printf(cols[1], "%3d %2d%%\n", 50, hit_chance_innate(to_h, 50));
    doc_printf(cols[1], "%3d %2d%%\n", 75, hit_chance_innate(to_h, 75));
    doc_printf(cols[1], "%3d %2d%%\n", 100, hit_chance_innate(to_h, 100));
    doc_printf(cols[1], "%3d %2d%%\n", 125, hit_chance_innate(to_h, 125));
    doc_printf(cols[1], "%3d %2d%%\n", 150, hit_chance_innate(to_h, 150));
    doc_printf(cols[1], "%3d %2d%%\n", 175, hit_chance_innate(to_h, 175));
    doc_printf(cols[1], "%3d %2d%%\n", 200, hit_chance_innate(to_h, 200));

    doc_insert_cols(doc, cols, 2, 1);
    doc_free(cols[0]);
    doc_free(cols[1]);
}
Example #8
0
void display_weapon_info(doc_ptr doc, int hand)
{
    object_type *o_ptr = equip_obj(p_ptr->weapon_info[hand].slot);
    char o_name[MAX_NLEN];
    u32b flgs[TR_FLAG_SIZE];
    int dd;
    int ds;
    int to_d = 0;
    int to_h = 0;
    int mult;
    critical_t crit = {0};
    int crit_pct = 0;
    int num_blow = NUM_BLOWS(hand);
    bool force = FALSE;
    doc_ptr cols[2] = {0};

    if (p_ptr->weapon_info[hand].wield_how == WIELD_NONE) return;
    if (!o_ptr) return;

    dd = o_ptr->dd + p_ptr->weapon_info[hand].to_dd;
    ds = o_ptr->ds + p_ptr->weapon_info[hand].to_ds;
    if (object_is_known(o_ptr))
    {
        to_d = o_ptr->to_d;
        to_h = o_ptr->to_h;
    }

    switch (display_weapon_mode)
    {
    case MAULER_STUNNING_BLOW:
    case MAULER_CRITICAL_BLOW:
    case MAULER_CRUSHING_BLOW:
    case MAULER_KNOCKBACK:
        num_blow = 100;
        break;
    case MAULER_KNOCKOUT_BLOW:
        num_blow = 100;
        to_h -= 50;
        break;
    case PY_POWER_ATTACK:
        to_h += 10;
        to_d += p_ptr->lev / 2;
        break;
    }

    weapon_flags_known(hand, flgs);
    if ( (have_flag(flgs, TR_FORCE_WEAPON) || p_ptr->tim_force) 
      && (p_ptr->csp > o_ptr->dd*o_ptr->ds/5) )
    {
        force = TRUE;
    }

    if (weaponmaster_get_toggle() == TOGGLE_SHIELD_BASH && object_is_shield(o_ptr))
    {
        dd = 3 + p_ptr->weapon_info[hand].to_dd;
        ds = o_ptr->ac + p_ptr->weapon_info[hand].to_ds;
        if (object_is_known(o_ptr))
        {
            to_h = o_ptr->to_a;
            to_d = o_ptr->to_a;
            to_h += 2*o_ptr->to_h;
            to_d += 2*o_ptr->to_d;
        }
    }

    mult = 100;
    if (have_flag(flgs, TR_VORPAL2))
        mult = mult * 5 / 3;
    else if (have_flag(flgs, TR_VORPAL))
        mult = mult * 11 / 9;

    mult += mult * p_ptr->weapon_info[hand].to_mult / 100;

    if (display_weapon_mode == MAULER_CRUSHING_BLOW)
    {
        int d = p_ptr->lev/5;
        int n = 10*(1 + d)/2; /* scale by 10 */

        mult = mult * (50 + n)/30;
    }

    if (!have_flag(flgs, TR_ORDER))
    {
        const int attempts = 10 * 1000;
        int i;
        int crits = 0;
        /* Compute Average Effects of Criticals by sampling */
        for (i = 0; i < attempts; i++)
        {
            critical_t tmp = critical_norm(o_ptr->weight, to_h, p_ptr->weapon_info[hand].to_h, display_weapon_mode, hand);
            if (tmp.desc)
            {
                crit.mul += tmp.mul;
                crit.to_d += tmp.to_d;
                crits++;
            }
            else
                crit.mul += 100;
        }
        crit.mul = crit.mul / attempts;
        crit.to_d = crit.to_d * 100 / attempts;
        crit_pct = crits * 1000 / attempts;
    }
    else
        crit.mul = 100;


    /* Display in 2 columns, side by side */
    cols[0] = doc_alloc(60);
    cols[1] = doc_alloc(10);

    /* Column #1 */
    object_desc(o_name, o_ptr, OD_COLOR_CODED | OD_NAME_AND_ENCHANT);
    if (prace_is_(RACE_MON_SWORD))
        doc_printf(cols[0], "<color:y> You    :</color> <indent><style:indent>%s</style></indent>\n", o_name);
    else
        doc_printf(cols[0], "<color:y> Hand #%d:</color> <indent><style:indent>%s</style></indent>\n", hand+1, o_name);

    doc_printf(cols[0], " %-7.7s: %d.%d lbs\n", "Weight", o_ptr->weight/10, o_ptr->weight%10);

    if (weaponmaster_get_toggle() == TOGGLE_SHIELD_BASH)
    {
        assert(o_ptr->tval == TV_SHIELD);
        doc_printf(cols[0], " %-7.7s: %dd%d (%+d,%+d)\n", "Bash", dd, ds, to_h, to_d);
        doc_printf(cols[0], " %-7.7s: %s (%+d To Hit)\n",
                    "Profic",
                    skills_shield_describe_current(o_ptr->sval),
                    skills_shield_calc_bonus(o_ptr->sval));
    }
    else
    {
        doc_printf(cols[0], " %-7.7s: %s (%+d To Hit)\n",
                    "Profic",
                    skills_weapon_describe_current(o_ptr->tval, o_ptr->sval),
                    skills_weapon_calc_bonus(o_ptr->tval, o_ptr->sval));
    }
    doc_printf(cols[0], " %-7.7s: %d + %d = %d\n", "To Hit", to_h, p_ptr->weapon_info[hand].to_h, to_h + p_ptr->weapon_info[hand].to_h);
    doc_printf(cols[0], " %-7.7s: %d + %d = %d\n", "To Dam", to_d, p_ptr->weapon_info[hand].to_d, to_d + p_ptr->weapon_info[hand].to_d);
    doc_printf(cols[0], " %-7.7s: %d.%2.2d\n", "Blows", num_blow/100, num_blow%100);

    if (p_ptr->weapon_info[hand].dual_wield_pct < 1000)
    {
        doc_printf(cols[0], " %-7.7s: %d.%d%%\n", "Skill",
            p_ptr->weapon_info[hand].dual_wield_pct/ 10,
            p_ptr->weapon_info[hand].dual_wield_pct % 10);
    }

    mult = mult * crit.mul / 100;
    to_d = to_d + crit.to_d/100 + p_ptr->weapon_info[hand].to_d;

    doc_printf(cols[0], "<color:G> %-7.7s</color>\n", "Damage");

    if (!have_flag(flgs, TR_ORDER))
    {
        if (crit.to_d)
        {
            doc_printf(cols[0], " %-7.7s: %d.%02dx + %d.%02d\n", "Crits",
                            crit.mul/100, crit.mul%100, crit.to_d/100, crit.to_d%100);
        }
        else
        {
            doc_printf(cols[0], " %-7.7s: %d.%02dx (%d.%d%%)\n", "Crits",
                            crit.mul/100, crit.mul%100, crit_pct / 10, crit_pct % 10);
        }
    }
    if (p_ptr->weapon_info[hand].to_mult)
    {
        int m = 100 + p_ptr->weapon_info[hand].to_mult;
        doc_printf(cols[0], " %-7.7s: %d.%02dx\n", "Mauler", m / 100, m % 100);
    }


    _display_weapon_slay(mult, 100, FALSE, num_blow, dd, ds, to_d, "Normal", TERM_WHITE, cols[0]);
    if (force)
        _display_weapon_slay(mult, 100, force, num_blow, dd, ds, to_d, "Force", TERM_L_BLUE, cols[0]);

    if (p_ptr->tim_slay_sentient)
        _display_weapon_slay(mult, 200, force, num_blow, dd, ds, to_d, "Sent.", TERM_YELLOW, cols[0]);
    
    if (have_flag(flgs, TR_KILL_ANIMAL)) 
        _display_weapon_slay(mult, 400, force, num_blow, dd, ds, to_d, "Animals", TERM_YELLOW, cols[0]);
    else if (have_flag(flgs, TR_SLAY_ANIMAL))
        _display_weapon_slay(mult, 250, force, num_blow, dd, ds, to_d, "Animals", TERM_YELLOW, cols[0]);
    
    if (have_flag(flgs, TR_KILL_EVIL))   
        _display_weapon_slay(mult, 350, force, num_blow, dd, ds, to_d, "Evil", TERM_YELLOW, cols[0]);
    else if (have_flag(flgs, TR_SLAY_EVIL))
        _display_weapon_slay(mult, 200, force, num_blow, dd, ds, to_d, "Evil", TERM_YELLOW, cols[0]);

    if (have_flag(flgs, TR_SLAY_GOOD))
        _display_weapon_slay(mult, 200, force, num_blow, dd, ds, to_d, "Good", TERM_YELLOW, cols[0]);

    if (have_flag(flgs, TR_SLAY_LIVING))
        _display_weapon_slay(mult, 200, force, num_blow, dd, ds, to_d, "Living", TERM_YELLOW, cols[0]);

    if (have_flag(flgs, TR_KILL_HUMAN))
        _display_weapon_slay(mult, 400, force, num_blow, dd, ds, to_d, "Human", TERM_YELLOW, cols[0]);
    else if (have_flag(flgs, TR_SLAY_HUMAN))
        _display_weapon_slay(mult, 250, force, num_blow, dd, ds, to_d, "Human", TERM_YELLOW, cols[0]);

    if (have_flag(flgs, TR_KILL_UNDEAD))
        _display_weapon_slay(mult, 500, force, num_blow, dd, ds, to_d, "Undead", TERM_YELLOW, cols[0]);
    else if (have_flag(flgs, TR_SLAY_UNDEAD))
        _display_weapon_slay(mult, 300, force, num_blow, dd, ds, to_d, "Undead", TERM_YELLOW, cols[0]);
    
    if (have_flag(flgs, TR_KILL_DEMON))  
        _display_weapon_slay(mult, 500, force, num_blow, dd, ds, to_d, "Demons", TERM_YELLOW, cols[0]);
    else if (have_flag(flgs, TR_SLAY_DEMON))
        _display_weapon_slay(mult, 300, force, num_blow, dd, ds, to_d, "Demons", TERM_YELLOW, cols[0]);

    if (have_flag(flgs, TR_KILL_ORC))  
        _display_weapon_slay(mult, 500, force, num_blow, dd, ds, to_d, "Orcs", TERM_YELLOW, cols[0]);
    else if (have_flag(flgs, TR_SLAY_ORC))
        _display_weapon_slay(mult, 300, force, num_blow, dd, ds, to_d, "Orcs", TERM_YELLOW, cols[0]);

    if (have_flag(flgs, TR_KILL_TROLL))  
        _display_weapon_slay(mult, 500, force, num_blow, dd, ds, to_d, "Trolls", TERM_YELLOW, cols[0]);
    else if (have_flag(flgs, TR_SLAY_TROLL))
        _display_weapon_slay(mult, 300, force, num_blow, dd, ds, to_d, "Trolls", TERM_YELLOW, cols[0]);

    if (have_flag(flgs, TR_KILL_GIANT))  
        _display_weapon_slay(mult, 500, force, num_blow, dd, ds, to_d, "Giants", TERM_YELLOW, cols[0]);
    else if (have_flag(flgs, TR_SLAY_GIANT))
        _display_weapon_slay(mult, 300, force, num_blow, dd, ds, to_d, "Giants", TERM_YELLOW, cols[0]);

    if (have_flag(flgs, TR_KILL_DRAGON))  
        _display_weapon_slay(mult, 500, force, num_blow, dd, ds, to_d, "Dragons", TERM_YELLOW, cols[0]);
    else if (have_flag(flgs, TR_SLAY_DRAGON))
        _display_weapon_slay(mult, 300, force, num_blow, dd, ds, to_d, "Dragons", TERM_YELLOW, cols[0]);
    
    if (have_flag(flgs, TR_BRAND_ACID))
        _display_weapon_slay(mult, 250, force, num_blow, dd, ds, to_d, "Acid", TERM_RED, cols[0]);

    if (have_flag(flgs, TR_BRAND_ELEC))
        _display_weapon_slay(mult, 250, force, num_blow, dd, ds, to_d, "Elec", TERM_RED, cols[0]);

    if (have_flag(flgs, TR_BRAND_FIRE))
        _display_weapon_slay(mult, 250, force, num_blow, dd, ds, to_d, "Fire", TERM_RED, cols[0]);

    if (have_flag(flgs, TR_BRAND_COLD))
        _display_weapon_slay(mult, 250, force, num_blow, dd, ds, to_d, "Cold", TERM_RED, cols[0]);

    if (have_flag(flgs, TR_BRAND_POIS))
        _display_weapon_slay(mult, 250, force, num_blow, dd, ds, to_d, "Poison", TERM_RED, cols[0]);

    if (p_ptr->weapon_info[hand].wield_how == WIELD_TWO_HANDS)
    {
        if (p_ptr->weapon_info[hand].omoi)
            doc_insert(cols[0], " Your weapon requires two hands to wield properly.\n");
    }

    if (p_ptr->weapon_info[hand].info)
    {
        byte a = p_ptr->weapon_info[hand].info_attr;
        if (!a) a = TERM_WHITE; /* uninitialized is TERM_DARK???! */
        doc_printf(cols[0], " <color:%c>%s</color>\n", attr_to_attr_char(a), p_ptr->weapon_info[hand].info);
    }

    /* Column #1 */
    doc_insert(cols[1], "<color:G>Accuracy</color>\n");
    doc_insert(cols[1], " AC Hit\n");

    doc_printf(cols[1], "%3d %2d%%\n", 25, hit_chance(hand, to_h, 25));
    doc_printf(cols[1], "%3d %2d%%\n", 50, hit_chance(hand, to_h, 50));
    doc_printf(cols[1], "%3d %2d%%\n", 75, hit_chance(hand, to_h, 75));
    doc_printf(cols[1], "%3d %2d%%\n", 100, hit_chance(hand, to_h, 100));
    doc_printf(cols[1], "%3d %2d%%\n", 125, hit_chance(hand, to_h, 125));
    doc_printf(cols[1], "%3d %2d%%\n", 150, hit_chance(hand, to_h, 150));
    doc_printf(cols[1], "%3d %2d%%\n", 175, hit_chance(hand, to_h, 175));
    doc_printf(cols[1], "%3d %2d%%\n", 200, hit_chance(hand, to_h, 200));

    /* Assemble the result */
    doc_insert_cols(doc, cols, 2, 1);
    doc_free(cols[0]);
    doc_free(cols[1]);
}
Example #9
0
/*
 * 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);
		}
	}
}