Example #1
0
/*
 * Set a smart trap effect.  Return false if it could not be set.
 */
bool set_effect_trap_smart(int f_idx, byte y, byte x, u16b flags)
{
	int x_idx = x_pop();
	int countdown;
	int trap_power;

	feature_type *f_ptr = &f_info[f_idx];

	/*All full*/
	if (!x_idx) return (FALSE);

	trap_power = (f_ptr->x_damage * (MAX(1, effective_depth(p_ptr->depth))) / 100);

	/*
	 * Avoid unfair instadeaths for the player by creating the trap only partially charged.
	 */
	countdown = (f_ptr->x_timeout_set + rand_int(f_ptr->x_timeout_rand)) /2;
	if (countdown <=3) countdown = 4;

	/*Keep it in bounds*/
	if (countdown >= MAX_UCHAR) countdown = MAX_UCHAR - 1;

	flags |= (EF1_TRAP_SMART | EF1_PERMANENT | EF1_HIDDEN | EF1_HURT_PLAY);

	effect_prep(x_idx, EFFECT_TRAP_SMART, f_idx, y, x, (byte)countdown, 1, trap_power, SOURCE_TRAP, flags);

	return (TRUE);
}
Example #2
0
/*
 * Helper function for monster_death -
 * Drop the monster's normal objects
 */
static void mon_drop_loot(int m_idx)
{
	monster_type *m_ptr = &mon_list[m_idx];

	monster_race *r_ptr = &r_info[m_ptr->r_idx];

	int j;
	bool chest = (r_ptr->flags1 & (RF1_DROP_CHEST)) ? TRUE : FALSE;
	bool good = (r_ptr->flags1 & (RF1_DROP_GOOD)) ? TRUE : FALSE;
	bool great = (r_ptr->flags1 & (RF1_DROP_GREAT)) ? TRUE : FALSE;

	bool do_gold = (!(r_ptr->flags1 & (RF1_ONLY_ITEM)));
	bool do_item = (!(r_ptr->flags1 & (RF1_ONLY_GOLD)));
	bool visible = (m_ptr->ml || (r_ptr->flags1 & (RF1_UNIQUE)));

	int force_coin = get_coin_type(r_ptr);

	int dump_item = 0;
	int dump_gold = 0;

	int number_drops = 0;

	object_type *i_ptr;
	object_type object_type_body;

	/* Average dungeon and monster levels */
	s16b set_object_level = object_level = (effective_depth(p_ptr->depth) + r_ptr->level) / 2;

	/* Determine how much we can drop */
	if ((r_ptr->flags1 & (RF1_DROP_60)) && (rand_int(100) < 60)) number_drops++;
	if ((r_ptr->flags1 & (RF1_DROP_90)) && (rand_int(100) < 90)) number_drops++;
	if (r_ptr->flags1 & (RF1_DROP_1D2)) number_drops += damroll(1, 2);
	if (r_ptr->flags1 & (RF1_DROP_2D2)) number_drops += damroll(2, 2);
	if (r_ptr->flags1 & (RF1_DROP_3D2)) number_drops += damroll(3, 2);
	if (r_ptr->flags1 & (RF1_DROP_4D2)) number_drops += damroll(4, 2);

	/* Hack -- handle creeping coins */
	coin_type = force_coin;

	/* Drop some objects */
	for (j = 0; j < number_drops; j++)
	{
		bool interesting = FALSE;

		/* Re-set the object level */
		object_level = set_object_level;

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

		/* Wipe the object */
		object_wipe(i_ptr);

		/* work on the "too much junk" problem, large drops sometimes are less items with a "boost". */
		if ((randint(750) < (number_drops * number_drops)) && (!(r_ptr->flags1 & (RF1_UNIQUE))))
		{
			interesting = TRUE;
			number_drops -= 5;
			object_level += 5;

			/*Boundry Control*/
			if (number_drops < 0) number_drops = 0;
			if (object_level > MAX_DEPTH) object_level = MAX_DEPTH;
		}

		/* Make Gold */
		if (do_gold && (!chest) && (!do_item || (rand_int(100) < 50)))
		{
			/* Make some gold */
			if (!make_gold(i_ptr)) continue;

			/* Assume seen XXX XXX XXX */
			dump_gold++;
		}

		/* Make Object */
		else
		{
			if (chest)
			{
				if (!make_object(i_ptr, good, great, DROP_TYPE_CHEST, FALSE)) continue;
			}

			/* Make an object */
			else if (!make_object(i_ptr, good, great, DROP_TYPE_UNTHEMED, interesting)) continue;

			/* Remember history */
			if (visible) object_history(i_ptr, ORIGIN_DROP_KNOWN, m_ptr->r_idx);
			else object_history(i_ptr, ORIGIN_DROP_UNKNOWN, 0);

			/* Assume seen XXX XXX XXX */
			dump_item++;
		}

		/* Drop it in the dungeon */
		drop_near(i_ptr, -1, m_ptr->fy, m_ptr->fx);
	}

	/* Re-set the object level */
	object_level = set_object_level;

	/*If marked for a bonus item, create it and drop it */
	if (m_ptr->mflag & (MFLAG_BONUS_ITEM))
	{
		bool this_good = good;
		bool this_great = great;
		bool this_chest = chest;
		bool interesting = FALSE;

		char o_name[80];

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

		/* Wipe the object */
		object_wipe(i_ptr);

		if (one_in_(50)) this_chest = TRUE;
		if (one_in_(15)) this_great = TRUE;
		if (one_in_(5)) this_good = TRUE;
		if ((!this_good) && (!this_great) && (!this_chest))
		{
			object_level += 5;
			if (object_level > MAX_DEPTH) object_level = MAX_DEPTH;
			interesting = TRUE;
		}

		if (this_chest)
		{
			while (!make_object(i_ptr, TRUE, TRUE, DROP_TYPE_CHEST, FALSE)) continue;
		}

		/* Make an object */
		else while (!make_object(i_ptr, this_good, this_good, DROP_TYPE_UNTHEMED, interesting)) continue;

		/* Remember history */
		if (visible) object_history(i_ptr, ORIGIN_DROP_KNOWN, m_ptr->r_idx);
		else object_history(i_ptr, ORIGIN_DROP_UNKNOWN, 0);

		object_desc(o_name, sizeof(o_name), i_ptr, ODESC_PREFIX | ODESC_FULL);

		/* Drop it in the dungeon */
		drop_near(i_ptr, -1, m_ptr->fy, m_ptr->fx);


	}

	/* Reset the object level */
	object_level = effective_depth(p_ptr->depth);

	/* Reset "coin" type */
	coin_type = 0;

	/* Take note of any dropped treasure */
	if (visible && (dump_item || dump_gold))
	{
		/* Take notes on treasure */
		lore_treasure(m_idx, dump_item, dump_gold);
	}

}
Example #3
0
/*
 * Handle the "death" of a monster.
 *
 * Disperse treasures centered at the monster location based on the
 * various flags contained in the monster flags fields.
 *
 * Check for "Quest" completion when a quest monster is killed.
 *
 * Note that only the player can induce "monster_death()" on Uniques or quest monsters.
 *
 * Note that monsters can now carry objects, and when a monster dies,
 * it drops all of its objects, which may disappear in crowded rooms.
 */
void monster_death(int m_idx, int who)
{
	int i, j, y, x;

	int dump_item = 0;
	int dump_gold = 0;

	int number_drops = 0;
	int total = 0;

	bool questlevel = FALSE;
	bool completed = FALSE;
	bool fixedquest = FALSE;
	bool writenote = TRUE;
	bool need_stairs = FALSE;

	s16b set_object_level;

	s16b this_o_idx, next_o_idx = 0;

	monster_type *m_ptr = &mon_list[m_idx];

	monster_race *r_ptr = &r_info[m_ptr->r_idx];

	bool visible = (m_ptr->ml || (r_ptr->flags1 & (RF1_UNIQUE)));

	bool chest = (r_ptr->flags1 & (RF1_DROP_CHEST)) ? TRUE : FALSE;
	bool good = (r_ptr->flags1 & (RF1_DROP_GOOD)) ? TRUE : FALSE;
	bool great = (r_ptr->flags1 & (RF1_DROP_GREAT)) ? TRUE : FALSE;

	bool do_gold = (!(r_ptr->flags1 & (RF1_ONLY_ITEM)));
	bool do_item = (!(r_ptr->flags1 & (RF1_ONLY_GOLD)));

	int force_coin = get_coin_type(r_ptr);

	object_type *i_ptr;
	object_type object_type_body;

	/* Get the location */
	y = m_ptr->fy;
	x = m_ptr->fx;

	/* Drop objects being carried */
	for (this_o_idx = m_ptr->hold_o_idx; this_o_idx; this_o_idx = next_o_idx)
	{
		object_type *o_ptr;

		/* Get the object */
		o_ptr = &o_list[this_o_idx];

		/*Remove the mark to hide when monsters carry this object*/
		o_ptr->ident &= ~(IDENT_HIDE_CARRY);

		/* Get the next object */
		next_o_idx = o_ptr->next_o_idx;

		/* Paranoia */
		o_ptr->held_m_idx = 0;

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

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

		/* Delete the object */
		delete_object_idx(this_o_idx);

		/* Drop it */
		drop_near(i_ptr, -1, y, x);
	}

	/* Forget objects */
	m_ptr->hold_o_idx = 0;

	/* Mega-Hack -- drop "winner" treasures */
	if (r_ptr->flags1 & (RF1_DROP_CHOSEN))
	{
		/* Get local object */
		i_ptr = &object_type_body;

		/* Mega-Hack -- Prepare to make "Grond" */
		object_prep(i_ptr, lookup_kind(TV_HAFTED, SV_GROND));

		/* Mega-Hack -- Mark this item as "Grond" */
		i_ptr->art_num = ART_GROND;

		/* Mega-Hack -- Actually create "Grond" */
		apply_magic(i_ptr, -1, TRUE, TRUE, TRUE, FALSE);

		/* Remember history */
		object_history(i_ptr, ORIGIN_MORGOTH, 0);

		/* Drop it in the dungeon */
		drop_near(i_ptr, -1, y, x);

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

		/* Mega-Hack -- Prepare to make "Morgoth's crown" */
		object_prep(i_ptr, lookup_kind(TV_CROWN, SV_MORGOTH));

		/* Mega-Hack -- Mark this item as "Morgoth" */
		i_ptr->art_num = ART_MORGOTH;

		/* Mega-Hack -- Actually create "Morgoth" */
		apply_magic(i_ptr, -1, TRUE, TRUE, TRUE, FALSE);

		/* Remember history */
		object_history(i_ptr, ORIGIN_MORGOTH, 0);

		/* Drop it in the dungeon */
		drop_near(i_ptr, -1, y, x);
	}


	/* Determine how much we can drop */
	if ((r_ptr->flags1 & (RF1_DROP_60)) && (rand_int(100) < 60)) number_drops++;
	if ((r_ptr->flags1 & (RF1_DROP_90)) && (rand_int(100) < 90)) number_drops++;
	if (r_ptr->flags1 & (RF1_DROP_1D2)) number_drops += damroll(1, 2);
	if (r_ptr->flags1 & (RF1_DROP_2D2)) number_drops += damroll(2, 2);
	if (r_ptr->flags1 & (RF1_DROP_3D2)) number_drops += damroll(3, 2);
	if (r_ptr->flags1 & (RF1_DROP_4D2)) number_drops += damroll(4, 2);

	/* Hack -- handle creeping coins */
	coin_type = force_coin;

	/* Average dungeon and monster levels */
	set_object_level = object_level = (effective_depth(p_ptr->depth) + r_ptr->level) / 2;

	/* Drop some objects */
	for (j = 0; j < number_drops; j++)
	{
		bool interesting = FALSE;

		/* Re-set the object level */
		object_level = set_object_level;

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

		/* Wipe the object */
		object_wipe(i_ptr);

		/* work on the "too much junk" problem, large drops sometimes are less items with a "boost". */
		if ((randint(750) < (number_drops * number_drops)) && (!(r_ptr->flags1 & (RF1_UNIQUE))))
		{
			interesting = TRUE;
			number_drops -= 5;
			object_level += 5;

			/*Boundry Control*/
			if (number_drops < 0) number_drops = 0;
			if (object_level > MAX_DEPTH) object_level = MAX_DEPTH;
		}

		/* Make Gold */
		if (do_gold && (!chest) && (!do_item || (rand_int(100) < 70)))
		{
			/* Make some gold */
			if (!make_gold(i_ptr)) continue;

			/* Assume seen XXX XXX XXX */
			dump_gold++;
		}

		/* Make Object */
		else
		{
			if (chest)
			{
				if (!make_object(i_ptr, good, great, DROP_TYPE_CHEST, FALSE)) continue;
			}

			/* Make an object */
			else if (!make_object(i_ptr, good, great, DROP_TYPE_UNTHEMED, interesting)) continue;

			/* Remember history */
			if (visible) object_history(i_ptr, ORIGIN_DROP_KNOWN, m_ptr->r_idx);
			else object_history(i_ptr, ORIGIN_DROP_UNKNOWN, 0);

			/* Assume seen XXX XXX XXX */
			dump_item++;
		}

		/* Drop it in the dungeon */
		drop_near(i_ptr, -1, y, x);
	}

	/* Re-set the object level */
	object_level = set_object_level;

	/*If marked for a bonus item, create it and drop it */
	if (m_ptr->mflag & (MFLAG_BONUS_ITEM))
	{
		bool this_good = good;
		bool this_great = great;
		bool this_chest = chest;
		bool interesting = FALSE;

		char o_name[80];

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

		/* Wipe the object */
		object_wipe(i_ptr);

		if (one_in_(50)) this_chest = TRUE;
		if (one_in_(15)) this_great = TRUE;
		if (one_in_(5)) this_good = TRUE;
		if ((!this_good) && (!this_great) && (!this_chest))
		{
			object_level += 5;
			if (object_level > MAX_DEPTH) object_level = MAX_DEPTH;
			interesting = TRUE;
		}

		if (this_chest)
		{
			while (!make_object(i_ptr, TRUE, TRUE, DROP_TYPE_CHEST, FALSE)) continue;
		}

		/* Make an object */
		else while (!make_object(i_ptr, this_good, this_good, DROP_TYPE_UNTHEMED, interesting)) continue;

		/* Remember history */
		if (visible) object_history(i_ptr, ORIGIN_DROP_KNOWN, m_ptr->r_idx);
		else object_history(i_ptr, ORIGIN_DROP_UNKNOWN, 0);

		object_desc(o_name, sizeof(o_name), i_ptr, ODESC_PREFIX | ODESC_FULL);

		/* Drop it in the dungeon */
		drop_near(i_ptr, -1, y, x);


	}

	/* Reset the object level */
	object_level = effective_depth(p_ptr->depth);

	/* Reset "coin" type */
	coin_type = 0;

	/* Take note of any dropped treasure */
	if (visible && (dump_item || dump_gold))
	{
		/* Take notes on treasure */
		lore_treasure(m_idx, dump_item, dump_gold);
	}

	/* Update monster list window */
	p_ptr->redraw |= (PR_MONLIST);

	/* Count incomplete quests */
	for (i = 0; i < z_info->q_max; i++)
	{
		quest_type *q_ptr = &q_info[i];

		/*
		 * Hack - don't count if player didn't kill, or on a town level
		 * This assumes only a player can kill quest monsters!!!!!
		 * This line is also ugly coding. :)
		 */
		if (((who != SOURCE_PLAYER) && (who != SOURCE_TRAP)) || (!p_ptr->depth)) continue;

		/* Quest level? */
		if ((q_ptr->active_level == p_ptr->depth) && (p_ptr->depth > 0))
		{
			/* One on the level */
			questlevel = TRUE;

			/* Require "Quest Monsters" */
			if 	(q_ptr->mon_idx == m_ptr->r_idx)
			{
				char race_name[80];

				/* Get the monster race name (singular)*/
				monster_desc_race(race_name, sizeof(race_name), q_ptr->mon_idx);

				/* Mark kills */
				q_ptr->cur_num++;

				/* Redraw quest indicator */
				p_ptr->redraw |= (PR_QUEST_ST);

				/* Completed quest? */
				if (q_ptr->cur_num == q_ptr->max_num)
				{
					/* Mark complete */
					q_ptr->active_level = 0;

					/* Mark fixed quests */
					if ((q_ptr->q_type == QUEST_FIXED) ||
						(q_ptr->q_type == QUEST_FIXED_U))
						fixedquest = TRUE;

					if (q_ptr->q_type == QUEST_GUARDIAN) need_stairs = TRUE;

					/* One complete */
					completed = TRUE;

					/*make a note of the completed quest, but not for fixed or
				     * fixed unique quests
					 */
					if ((adult_take_notes) && (!fixedquest))
					{
						char note[120];

						/* Multiple quest monsters */
						if (q_ptr->max_num > 1)
						{
							plural_aux(race_name, sizeof(race_name));
						}

						if (r_ptr->flags1 & (RF1_UNIQUE))
						{
							/*write note*/
							if monster_nonliving(r_ptr)
								sprintf(note, "Quest: Destroyed %s", race_name);
							else sprintf(note, "Quest: Killed %s", race_name);
						}

						else
						{
							/* Write note */
							if monster_nonliving(r_ptr)