/* * 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); } }
static void describe_monster_drop(int r_idx, const monster_lore *l_ptr) { const monster_race *r_ptr = &r_info[r_idx]; bool sin = FALSE; int n; cptr p; int msex = 0; /* Extract a gender (if applicable) */ if (r_ptr->flags1 & RF1_FEMALE) msex = 2; else if (r_ptr->flags1 & RF1_MALE) msex = 1; /* Drops gold and/or items */ if (l_ptr->drop_gold || l_ptr->drop_item) { /* Intro */ text_out(format("%^s may carry", wd_he[msex])); /* Count maximum drop */ n = MAX(l_ptr->drop_gold, l_ptr->drop_item); /* One drop (may need an "n") */ if (n == 1) { text_out(" a"); sin = TRUE; } /* Two drops */ else if (n == 2) { text_out(" one or two"); } /* Many drops */ else { text_out(format(" up to %d", n)); } /* Great */ if (l_ptr->flags1 & RF1_DROP_GREAT) { p = " exceptional"; } /* Good (no "n" needed) */ else if (l_ptr->flags1 & RF1_DROP_GOOD) { p = " good"; sin = FALSE; } /* Okay */ else { p = NULL; } /* Objects */ if (l_ptr->drop_item) { /* Dump "object(s)" */ if (p) text_out(p); if (get_food_type(r_ptr)) text_out(" mushroom"); else text_out(" object"); if (n != 1) text_out("s"); /* Conjunction replaces variety, if needed for "gold" below */ p = " or"; } /* Treasures */ if (l_ptr->drop_gold) { /* Cancel prefix */ if (!p) sin = FALSE; /* Dump "treasure(s)" */ if (p) text_out(p); if (get_coin_type(r_ptr)) text_out(" precious metal"); text_out(" treasure"); if (n != 1) text_out("s"); } /* End this sentence */ text_out(". "); } }
static void describe_monster_drop(const monster_race *r_ptr, const monster_lore *l_ptr) { bool sin = FALSE; bool plu = TRUE; int n; cptr p; int msex = 0; int vn; cptr vp[64]; /* Extract a gender (if applicable) */ if (r_ptr->flags1 & RF1_FEMALE) msex = 2; else if (r_ptr->flags1 & RF1_MALE) msex = 1; /* Drops gold and/or items */ if (l_ptr->drop_gold || l_ptr->drop_item) { /* Count maximum drop */ n = MAX(l_ptr->drop_gold, l_ptr->drop_item); /* Intro */ text_out(format("%^s may carry", wd_he[msex])); /* One drop (may need an "n") */ if (n == 1) { text_out(" a"); sin = TRUE; plu = FALSE; } /* Two drops */ else if (n == 2) { text_out(" one or two"); } /* Many drops */ else { text_out(format(" up to %d", n)); } /* Great */ if (l_ptr->flags1 & RF1_DROP_GREAT) { p = " exceptional "; } /* Good (no "n" needed) */ else if (l_ptr->flags1 & RF1_DROP_GOOD) { p = " good "; sin = FALSE; } /* Okay */ else { p = " "; } /* Collect special abilities. */ vn = 0; /* Objects */ if (l_ptr->drop_item) { if (l_ptr->flags8 & (RF8_DROP_CHEST)) vp[vn++] = "chest"; if (l_ptr->flags8 & (RF8_DROP_WEAPON)) vp[vn++] = "weapon"; if (l_ptr->flags8 & (RF8_DROP_MISSILE)) vp[vn++] = "missile weapon"; if (l_ptr->flags8 & (RF8_DROP_ARMOR)) vp[vn++] = "armour"; if (l_ptr->flags8 & (RF8_DROP_CLOTHES)) vp[vn++] = "garment"; if (l_ptr->flags8 & (RF8_DROP_TOOL)) vp[vn++] = "tool"; if (l_ptr->flags8 & (RF8_DROP_LITE)) vp[vn++] = "lite"; if (l_ptr->flags8 & (RF8_DROP_JEWELRY)) vp[vn++] = "adornment"; if (l_ptr->flags8 & (RF8_DROP_RSW)) vp[vn++] = "magical device"; if (l_ptr->flags8 & (RF8_DROP_WRITING)) vp[vn++] = "written item"; if (l_ptr->flags8 & (RF8_DROP_MUSIC)) vp[vn++] = "musical item"; if (l_ptr->flags8 & (RF8_DROP_POTION)) vp[vn++] = "potion"; if (l_ptr->flags8 & (RF8_DROP_FOOD)) vp[vn++] = "edible item"; if (l_ptr->flags8 & (RF8_DROP_JUNK)) vp[vn++] = "junk item"; if (l_ptr->flags9 & (RF9_DROP_ESSENCE)) vp[vn++] = "essence"; /* Only drop mushrooms? */ if (l_ptr->flags9 & (RF9_DROP_MUSHROOM)) { vn = 0; vp[vn++] = "mushroom"; } if (!vn) vp[vn++] = "special object"; } /* Treasures */ if (l_ptr->drop_gold) { /* Dump "treasure(s)" */ if (l_ptr->flags9 & (RF9_DROP_MINERAL)) { int coin_type = get_coin_type(r_ptr); switch (k_info[coin_type + OBJ_GOLD_LIST].tval) { case TV_GOLD: vp[vn++] = "precious metal"; break; case TV_GEMS: vp[vn++] = "gem stone"; break; } } else vp[vn++] = "treasure"; } /* Fix up singular */ if ((vn) && !(is_a_vowel(vp[0][0]))) sin = FALSE; /* Describe special abilities. */ if (vn) { /* Scan */ for (n = 0; n < vn; n++) { /* Intro */ if (n == 0) { if (sin) text_out("n"); text_out(p); } else if (n < vn-1) text_out(", "); else text_out(" or "); /* Dump */ text_out(format("%s%s", vp[n], (plu ? "s" : ""))); } /* End */ text_out(". "); } } }
/* * 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)