2 * @brief モンスター死亡時の特殊処理switch (一般的な処理もdefaultで実施)
7 #include "monster-floor/special-death-switcher.h"
8 #include "artifact/fixed-art-generator.h"
9 #include "artifact/fixed-art-types.h"
10 #include "artifact/random-art-generator.h"
11 #include "effect/attribute-types.h"
12 #include "effect/effect-characteristics.h"
13 #include "effect/effect-processor.h"
14 #include "floor/cave.h"
15 #include "floor/floor-object.h"
16 #include "floor/floor-util.h"
17 #include "floor/geometry.h"
18 #include "game-option/birth-options.h"
19 #include "grid/grid.h"
20 #include "main/sound-definitions-table.h"
21 #include "main/sound-of-music.h"
22 #include "monster-floor/monster-death-util.h"
23 #include "monster-floor/monster-death.h"
24 #include "monster-floor/monster-summon.h"
25 #include "monster-floor/place-monster-types.h"
26 #include "monster-race/monster-race.h"
27 #include "monster-race/race-indice-types.h"
28 #include "monster/monster-describer.h"
29 #include "monster/monster-description-types.h"
30 #include "monster/monster-info.h"
31 #include "object-enchant/item-apply-magic.h"
32 #include "object-enchant/item-magic-applier.h"
33 #include "object/object-kind-hook.h"
34 #include "spell/summon-types.h"
35 #include "sv-definition/sv-other-types.h"
36 #include "sv-definition/sv-protector-types.h"
37 #include "sv-definition/sv-weapon-types.h"
38 #include "system/artifact-type-definition.h"
39 #include "system/baseitem-info-definition.h"
40 #include "system/floor-type-definition.h"
41 #include "system/item-entity.h"
42 #include "system/monster-race-definition.h"
43 #include "system/monster-type-definition.h"
44 #include "system/player-type-definition.h"
45 #include "view/display-messages.h"
46 #include "world/world.h"
49 * @brief 死亡召喚に使用するモード選択
50 * @param md_ptr モンスター撃破構造体への参照ポインタ
51 * @return 撃破モンスターがPETであればPM_FORCE_PETを、CLONEであればPM_CLONEを立てる
53 static BIT_FLAGS dead_mode(monster_death_type *md_ptr)
55 bool pet = md_ptr->m_ptr->is_pet();
56 bool clone = md_ptr->m_ptr->mflag2.has(MonsterConstantFlagType::CLONED);
57 BIT_FLAGS mode = pet ? PM_FORCE_PET : PM_NONE;
59 mode = mode | PM_CLONE;
66 * @brief 死亡時召喚処理 (今のところ自分自身のみ)
67 * @param player_ptr プレイヤーへの参照ポインタ
68 * @param md_ptr モンスター撃破構造体への参照ポインタ
70 * @param probability 召喚確率 (計算式:1 - 1/probability)
71 * @param radius 召喚半径 (モンスターが死亡した座標から半径何マス以内に召喚させるか)
72 * @param message 召喚時のメッセージ
74 static void summon_self(PlayerType *player_ptr, monster_death_type *md_ptr, summon_type type, int probability, POSITION radius, concptr message)
76 auto *floor_ptr = player_ptr->current_floor_ptr;
77 if (floor_ptr->inside_arena || player_ptr->phase_out || one_in_(probability)) {
81 POSITION wy = md_ptr->md_y;
82 POSITION wx = md_ptr->md_x;
84 bool pet = md_ptr->m_ptr->is_pet();
86 scatter(player_ptr, &wy, &wx, md_ptr->md_y, md_ptr->md_x, radius, PROJECT_NONE);
87 } while (!(in_bounds(floor_ptr, wy, wx) && is_cave_empty_bold2(player_ptr, wy, wx)) && --attempts);
93 BIT_FLAGS mode = dead_mode(md_ptr);
94 if (summon_specific(player_ptr, (pet ? -1 : md_ptr->m_idx), wy, wx, 100, type, mode) && player_can_see_bold(player_ptr, wy, wx)) {
99 static void on_dead_pink_horror(PlayerType *player_ptr, monster_death_type *md_ptr)
101 if (player_ptr->current_floor_ptr->inside_arena || player_ptr->phase_out) {
106 const int blue_horrors = 2;
107 for (int i = 0; i < blue_horrors; i++) {
108 POSITION wy = md_ptr->md_y;
109 POSITION wx = md_ptr->md_x;
110 bool pet = md_ptr->m_ptr->is_pet();
111 BIT_FLAGS mode = dead_mode(md_ptr);
112 if (summon_specific(player_ptr, (pet ? -1 : md_ptr->m_idx), wy, wx, 100, SUMMON_BLUE_HORROR, mode) && player_can_see_bold(player_ptr, wy, wx)) {
119 msg_print(_("ピンク・ホラーは分裂した!", "The Pink horror divides!"));
123 static void on_dead_bloodletter(PlayerType *player_ptr, monster_death_type *md_ptr)
125 if (!md_ptr->drop_chosen_item || (randint1(100) >= 15)) {
130 auto *q_ptr = &forge;
131 q_ptr->prep(lookup_baseitem_id({ ItemKindType::SWORD, SV_BLADE_OF_CHAOS }));
132 ItemMagicApplier(player_ptr, q_ptr, player_ptr->current_floor_ptr->object_level, AM_NO_FIXED_ART | md_ptr->mo_mode).execute();
133 (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
136 static void on_dead_raal(PlayerType *player_ptr, monster_death_type *md_ptr)
138 auto *floor_ptr = player_ptr->current_floor_ptr;
139 if (!md_ptr->drop_chosen_item || (floor_ptr->dun_level <= 9)) {
144 auto *q_ptr = &forge;
146 if ((floor_ptr->dun_level > 49) && one_in_(5)) {
147 get_obj_index_hook = kind_is_good_book;
149 get_obj_index_hook = kind_is_book;
152 (void)make_object(player_ptr, q_ptr, md_ptr->mo_mode);
153 (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
157 * @brief 6/7の確率で、20マス以内に暁の戦士自身を召喚する
158 * @param player_ptr プレイヤーへの参照ポインタ
159 * @param md_ptr モンスター撃破構造体への参照ポインタ
161 static void on_dead_dawn(PlayerType *player_ptr, monster_death_type *md_ptr)
163 summon_self(player_ptr, md_ptr, SUMMON_DAWN, 7, 20, _("新たな戦士が現れた!", "A new warrior steps forth!"));
166 static void on_dead_sacred_treasures(PlayerType *player_ptr, monster_death_type *md_ptr)
168 if ((player_ptr->ppersonality != PERSONALITY_LAZY) || !md_ptr->drop_chosen_item) {
172 FixedArtifactId a_idx = FixedArtifactId::NONE;
173 ArtifactType *a_ptr = nullptr;
175 switch (randint0(3)) {
177 a_idx = FixedArtifactId::NAMAKE_HAMMER;
180 a_idx = FixedArtifactId::NAMAKE_BOW;
183 a_idx = FixedArtifactId::NAMAKE_ARMOR;
187 a_ptr = &artifacts_info.at(a_idx);
188 } while (a_ptr->is_generated);
190 if (!create_named_art(player_ptr, a_idx, md_ptr->md_y, md_ptr->md_x)) {
194 if (w_ptr->character_dungeon) {
195 a_ptr->floor_id = player_ptr->floor_id;
199 static void on_dead_serpent(PlayerType *player_ptr, monster_death_type *md_ptr)
201 if (!md_ptr->drop_chosen_item) {
206 auto *q_ptr = &forge;
207 q_ptr->prep(lookup_baseitem_id({ ItemKindType::HAFTED, SV_GROND }));
208 q_ptr->fixed_artifact_idx = FixedArtifactId::GROND;
209 ItemMagicApplier(player_ptr, q_ptr, -1, AM_GOOD | AM_GREAT).execute();
210 (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
212 q_ptr->prep(lookup_baseitem_id({ ItemKindType::CROWN, SV_CHAOS }));
213 q_ptr->fixed_artifact_idx = FixedArtifactId::CHAOS;
214 ItemMagicApplier(player_ptr, q_ptr, -1, AM_GOOD | AM_GREAT).execute();
215 (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
218 static void on_dead_death_sword(PlayerType *player_ptr, monster_death_type *md_ptr)
220 if (!md_ptr->drop_chosen_item) {
225 auto *q_ptr = &forge;
226 q_ptr->prep(lookup_baseitem_id({ ItemKindType::SWORD, randint1(2) }));
227 (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
230 static void on_dead_can_angel(PlayerType *player_ptr, monster_death_type *md_ptr)
232 bool is_drop_can = md_ptr->drop_chosen_item;
233 bool is_silver = md_ptr->m_ptr->r_idx == MonsterRaceId::A_SILVER;
234 is_silver &= md_ptr->r_ptr->r_akills % 5 == 0;
235 is_drop_can &= (md_ptr->m_ptr->r_idx == MonsterRaceId::A_GOLD) || is_silver;
241 auto *q_ptr = &forge;
242 q_ptr->prep(lookup_baseitem_id({ ItemKindType::CHEST, SV_CHEST_KANDUME }));
243 ItemMagicApplier(player_ptr, q_ptr, player_ptr->current_floor_ptr->object_level, AM_NO_FIXED_ART).execute();
244 (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
247 static void on_dead_aqua_illusion(PlayerType *player_ptr, monster_death_type *md_ptr)
249 if (player_ptr->current_floor_ptr->inside_arena || player_ptr->phase_out) {
254 const int popped_bubbles = 4;
255 for (int i = 0; i < popped_bubbles; i++) {
256 POSITION wy = md_ptr->md_y;
257 POSITION wx = md_ptr->md_x;
258 bool pet = md_ptr->m_ptr->is_pet();
259 BIT_FLAGS mode = dead_mode(md_ptr);
260 auto smaller_bubble = md_ptr->m_ptr->r_idx - 1;
261 if (summon_named_creature(player_ptr, (pet ? -1 : md_ptr->m_idx), wy, wx, smaller_bubble, mode) && player_can_see_bold(player_ptr, wy, wx)) {
267 msg_print(_("泡が弾けた!", "The bubble pops!"));
273 * @brief 7/8の確率で、5マス以内にトーテムモアイ自身を召喚する
274 * @param player_ptr プレイヤーへの参照ポインタ
275 * @param md_ptr モンスター撃破構造体への参照ポインタ
277 static void on_dead_totem_moai(PlayerType *player_ptr, monster_death_type *md_ptr)
279 summon_self(player_ptr, md_ptr, SUMMON_TOTEM_MOAI, 8, 5, _("新たなモアイが現れた!", "A new moai steps forth!"));
282 static void on_dead_dragon_centipede(PlayerType *player_ptr, monster_death_type *md_ptr)
284 if (player_ptr->current_floor_ptr->inside_arena || player_ptr->phase_out) {
289 const int reproduced_centipede = 2;
290 for (int i = 0; i < reproduced_centipede; i++) {
291 POSITION wy = md_ptr->md_y;
292 POSITION wx = md_ptr->md_x;
293 bool pet = md_ptr->m_ptr->is_pet();
294 BIT_FLAGS mode = dead_mode(md_ptr);
296 auto smaller_centipede = md_ptr->m_ptr->r_idx - 1;
297 if (summon_named_creature(player_ptr, (pet ? -1 : md_ptr->m_idx), wy, wx, smaller_centipede, mode) && player_can_see_bold(player_ptr, wy, wx)) {
302 GAME_TEXT m_name[MAX_NLEN];
303 monster_desc(player_ptr, m_name, md_ptr->m_ptr, MD_NONE);
305 msg_format(_("%sが再生した!", "The %s reproduced!"), m_name);
312 * @param player_ptr プレイヤーへの参照ポインタ
313 * @param q_ptr 生成中アイテムへの参照ポインタ
314 * @param drop_mode ドロップ品の質
315 * @param is_object_hook_null アイテム種別が何でもありならtrue、指定されていればfalse
316 * @return 生成したアイテムが装備品ならtrue、それ以外ならfalse
317 * @todo 汎用的に使えそうだがどこかにいいファイルはないか?
319 static bool make_equipment(PlayerType *player_ptr, ItemEntity *q_ptr, const BIT_FLAGS drop_mode, const bool is_object_hook_null)
322 (void)make_object(player_ptr, q_ptr, drop_mode);
323 if (!is_object_hook_null) {
327 auto tval = q_ptr->tval;
329 case ItemKindType::BOW:
330 case ItemKindType::DIGGING:
331 case ItemKindType::HAFTED:
332 case ItemKindType::POLEARM:
333 case ItemKindType::SWORD:
334 case ItemKindType::BOOTS:
335 case ItemKindType::GLOVES:
336 case ItemKindType::HELM:
337 case ItemKindType::CROWN:
338 case ItemKindType::SHIELD:
339 case ItemKindType::CLOAK:
340 case ItemKindType::SOFT_ARMOR:
341 case ItemKindType::HARD_ARMOR:
342 case ItemKindType::DRAG_ARMOR:
343 case ItemKindType::LITE:
344 case ItemKindType::AMULET:
345 case ItemKindType::RING:
353 * @brief 死亡時ドロップとしてランダムアーティファクトのみを生成する
354 * @param player_ptr プレイヤーへの参照ポインタ
355 * @param md_ptr モンスター撃破構造体への参照ポインタ
356 * @param object_hook_pf アイテム種別指定、特になければnullptrで良い
359 * 最初のアイテム生成でいきなり☆が生成された場合を除き、中途半端な☆ (例:呪われている)は生成しない.
360 * このルーチンで★は生成されないので、★生成フラグのキャンセルも不要
362 static void on_dead_random_artifact(PlayerType *player_ptr, monster_death_type *md_ptr, bool (*object_hook_pf)(KIND_OBJECT_IDX k_idx))
365 auto *q_ptr = &forge;
366 auto is_object_hook_null = object_hook_pf == nullptr;
367 auto drop_mode = md_ptr->mo_mode | AM_NO_FIXED_ART;
369 // make_object() の中でアイテム種別をキャンセルしている
370 // よってこのwhileループ中へ入れないと、引数で指定していない種別のアイテムが選ばれる可能性がある
371 get_obj_index_hook = object_hook_pf;
372 if (!make_equipment(player_ptr, q_ptr, drop_mode, is_object_hook_null)) {
376 if (q_ptr->art_name > 0) {
380 if (q_ptr->is_ego()) {
384 (void)become_random_artifact(player_ptr, q_ptr, false);
385 auto is_good_random_art = !q_ptr->is_cursed();
386 is_good_random_art &= q_ptr->to_h > 0;
387 is_good_random_art &= q_ptr->to_d > 0;
388 is_good_random_art &= q_ptr->to_a > 0;
389 is_good_random_art &= q_ptr->pval > 0;
390 if (is_good_random_art) {
395 (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
399 * @brief マニマニのあくま撃破時メッセージ
400 * @todo 死亡時の特殊メッセージを表示するだけの処理を複数作るなら、switch/case文に分けられるように汎用化すること
402 static void on_dead_manimani(PlayerType *player_ptr, monster_death_type *md_ptr)
404 if (!is_seen(player_ptr, md_ptr->m_ptr)) {
408 msg_print(_("どこからか声が聞こえる…「ハロー! そして…グッドバイ!」", "Heard a voice from somewhere... 'Hello! And... good bye!'"));
411 static void drop_specific_item_on_dead(PlayerType *player_ptr, monster_death_type *md_ptr, bool (*object_hook_pf)(KIND_OBJECT_IDX k_idx))
414 auto *q_ptr = &forge;
416 get_obj_index_hook = object_hook_pf;
417 (void)make_object(player_ptr, q_ptr, md_ptr->mo_mode);
418 (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
421 static void on_dead_chest_mimic(PlayerType *player_ptr, monster_death_type *md_ptr)
423 if (player_ptr->current_floor_ptr->inside_arena || player_ptr->phase_out) {
428 auto mimic_inside = MonsterRace::empty_id();
429 auto num_summons = 0;
430 auto r_idx = md_ptr->m_ptr->r_idx;
432 case MonsterRaceId::CHEST_MIMIC_03:
433 mimic_inside = MonsterRaceId::CHEST_MIMIC_02;
436 case MonsterRaceId::CHEST_MIMIC_04:
437 mimic_inside = MonsterRaceId::CHEST_MIMIC_03;
440 case MonsterRaceId::CHEST_MIMIC_11:
441 mimic_inside = MonsterRaceId::CHEST_MIMIC_04;
442 num_summons = one_in_(2) ? 3 : 2;
448 for (auto i = 0; i < num_summons; i++) {
449 auto wy = md_ptr->md_y;
450 auto wx = md_ptr->md_x;
451 auto pet = md_ptr->m_ptr->is_pet();
452 BIT_FLAGS mode = dead_mode(md_ptr);
453 if (summon_named_creature(player_ptr, (pet ? -1 : md_ptr->m_idx), wy, wx, mimic_inside, (BIT_FLAGS)mode) && player_can_see_bold(player_ptr, wy, wx)) {
459 msg_print(_("箱の中から新たなミミックが現れた!", "A new mimic appears in the dead mimic!"));
464 static void on_dead_mimics(PlayerType *player_ptr, monster_death_type *md_ptr)
466 if (!md_ptr->drop_chosen_item) {
470 switch (md_ptr->r_ptr->d_char) {
472 if (player_ptr->current_floor_ptr->dun_level <= 0) {
476 drop_specific_item_on_dead(player_ptr, md_ptr, kind_is_cloak);
479 if (player_ptr->current_floor_ptr->dun_level <= 4) {
483 drop_specific_item_on_dead(player_ptr, md_ptr, kind_is_polearm);
486 if (player_ptr->current_floor_ptr->dun_level <= 19) {
490 drop_specific_item_on_dead(player_ptr, md_ptr, kind_is_armor);
493 if (player_ptr->current_floor_ptr->dun_level <= 4) {
497 drop_specific_item_on_dead(player_ptr, md_ptr, kind_is_hafted);
500 if (md_ptr->m_ptr->r_idx == MonsterRaceId::STORMBRINGER) {
504 drop_specific_item_on_dead(player_ptr, md_ptr, kind_is_sword);
507 if (player_ptr->current_floor_ptr->dun_level <= 19) {
511 drop_specific_item_on_dead(player_ptr, md_ptr, kind_is_boots);
518 static void on_dead_swordfish(PlayerType *player_ptr, monster_death_type *md_ptr, AttributeFlags attribute_flags)
520 if (attribute_flags.has_not(AttributeType::COLD) || !md_ptr->drop_chosen_item || (randint1(100) >= 10)) {
524 drop_single_artifact(player_ptr, md_ptr, FixedArtifactId::FROZEN_SWORDFISH);
527 void switch_special_death(PlayerType *player_ptr, monster_death_type *md_ptr, AttributeFlags attribute_flags)
529 switch (md_ptr->m_ptr->r_idx) {
530 case MonsterRaceId::PINK_HORROR:
531 on_dead_pink_horror(player_ptr, md_ptr);
533 case MonsterRaceId::BLOODLETTER:
534 on_dead_bloodletter(player_ptr, md_ptr);
536 case MonsterRaceId::RAAL:
537 on_dead_raal(player_ptr, md_ptr);
539 case MonsterRaceId::DAWN:
540 on_dead_dawn(player_ptr, md_ptr);
542 case MonsterRaceId::UNMAKER:
543 (void)project(player_ptr, md_ptr->m_idx, 6, md_ptr->md_y, md_ptr->md_x, 100, AttributeType::CHAOS, PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL);
545 case MonsterRaceId::UNICORN_ORD:
546 case MonsterRaceId::MORGOTH:
547 case MonsterRaceId::ONE_RING:
548 on_dead_sacred_treasures(player_ptr, md_ptr);
550 case MonsterRaceId::SERPENT:
551 on_dead_serpent(player_ptr, md_ptr);
553 case MonsterRaceId::B_DEATH_SWORD:
554 on_dead_death_sword(player_ptr, md_ptr);
556 case MonsterRaceId::A_GOLD:
557 case MonsterRaceId::A_SILVER:
558 on_dead_can_angel(player_ptr, md_ptr);
560 case MonsterRaceId::ROLENTO:
561 (void)project(player_ptr, md_ptr->m_idx, 3, md_ptr->md_y, md_ptr->md_x, damroll(20, 10), AttributeType::FIRE, PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL);
563 case MonsterRaceId::MIDDLE_AQUA_FIRST:
564 case MonsterRaceId::LARGE_AQUA_FIRST:
565 case MonsterRaceId::EXTRA_LARGE_AQUA_FIRST:
566 case MonsterRaceId::MIDDLE_AQUA_SECOND:
567 case MonsterRaceId::LARGE_AQUA_SECOND:
568 case MonsterRaceId::EXTRA_LARGE_AQUA_SECOND:
569 on_dead_aqua_illusion(player_ptr, md_ptr);
571 case MonsterRaceId::TOTEM_MOAI:
572 on_dead_totem_moai(player_ptr, md_ptr);
574 case MonsterRaceId::DRAGON_CENTIPEDE:
575 case MonsterRaceId::DRAGON_WORM:
576 on_dead_dragon_centipede(player_ptr, md_ptr);
578 case MonsterRaceId::CAIT_SITH:
579 drop_specific_item_on_dead(player_ptr, md_ptr, kind_is_boots);
581 case MonsterRaceId::YENDOR_WIZARD_1:
582 on_dead_random_artifact(player_ptr, md_ptr, kind_is_amulet);
584 case MonsterRaceId::YENDOR_WIZARD_2:
585 drop_specific_item_on_dead(player_ptr, md_ptr, kind_is_amulet);
587 case MonsterRaceId::MANIMANI:
588 on_dead_manimani(player_ptr, md_ptr);
590 case MonsterRaceId::LOSTRINGIL:
591 on_dead_random_artifact(player_ptr, md_ptr, kind_is_sword);
593 case MonsterRaceId::CHEST_MIMIC_03:
594 case MonsterRaceId::CHEST_MIMIC_04:
595 case MonsterRaceId::CHEST_MIMIC_11:
596 on_dead_chest_mimic(player_ptr, md_ptr);
598 case MonsterRaceId::SWORDFISH:
599 on_dead_swordfish(player_ptr, md_ptr, attribute_flags);
602 on_dead_mimics(player_ptr, md_ptr);