OSDN Git Service

Merge pull request #2313 from Slimebreath6078/feature/remove_lyeh
[hengbandforosx/hengbandosx.git] / src / monster-floor / monster-death.cpp
1 #include "monster-floor/monster-death.h"
2 #include "artifact/fixed-art-generator.h"
3 #include "cmd-building/cmd-building.h"
4 #include "core/player-redraw-types.h"
5 #include "core/player-update-types.h"
6 #include "dungeon/dungeon.h"
7 #include "dungeon/quest-completion-checker.h"
8 #include "effect/effect-characteristics.h"
9 #include "effect/effect-processor.h"
10 #include "floor/floor-object.h"
11 #include "game-option/birth-options.h"
12 #include "game-option/play-record-options.h"
13 #include "io/write-diary.h"
14 #include "lore/lore-store.h"
15 #include "main/music-definitions-table.h"
16 #include "main/sound-of-music.h"
17 #include "market/arena-info-table.h"
18 #include "monster-floor/monster-death-util.h"
19 #include "monster-floor/monster-object.h"
20 #include "monster-floor/special-death-switcher.h"
21 #include "monster-race/monster-race-hook.h"
22 #include "monster-race/monster-race.h"
23 #include "monster-race/race-flags1.h"
24 #include "monster-race/race-flags2.h"
25 #include "monster-race/race-flags7.h"
26 #include "monster-race/race-flags9.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-flag-types.h"
31 #include "monster/monster-info.h"
32 #include "monster/monster-list.h"
33 #include "object-enchant/apply-magic.h"
34 #include "object-enchant/item-apply-magic.h"
35 #include "object/object-kind-hook.h"
36 #include "pet/pet-fall-off.h"
37 #include "player/patron.h"
38 #include "sv-definition/sv-other-types.h"
39 #include "sv-definition/sv-scroll-types.h"
40 #include "system/artifact-type-definition.h"
41 #include "system/building-type-definition.h"
42 #include "system/floor-type-definition.h"
43 #include "system/monster-race-definition.h"
44 #include "system/monster-type-definition.h"
45 #include "system/player-type-definition.h"
46 #include "system/system-variables.h"
47 #include "timed-effect/player-hallucination.h"
48 #include "timed-effect/timed-effects.h"
49 #include "util/bit-flags-calculator.h"
50 #include "view/display-messages.h"
51 #include "world/world.h"
52
53 static void write_pet_death(PlayerType *player_ptr, monster_death_type *md_ptr)
54 {
55     md_ptr->md_y = md_ptr->m_ptr->fy;
56     md_ptr->md_x = md_ptr->m_ptr->fx;
57     if (record_named_pet && is_pet(md_ptr->m_ptr) && md_ptr->m_ptr->nickname) {
58         GAME_TEXT m_name[MAX_NLEN];
59         monster_desc(player_ptr, m_name, md_ptr->m_ptr, MD_INDEF_VISIBLE);
60         exe_write_diary(player_ptr, DIARY_NAMED_PET, 3, m_name);
61     }
62 }
63
64 static void on_dead_explosion(PlayerType *player_ptr, monster_death_type *md_ptr)
65 {
66     for (int i = 0; i < 4; i++) {
67         if (md_ptr->r_ptr->blow[i].method != RaceBlowMethodType::EXPLODE) {
68             continue;
69         }
70
71         BIT_FLAGS flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
72         AttributeType typ = mbe_info[enum2i(md_ptr->r_ptr->blow[i].effect)].explode_type;
73         DICE_NUMBER d_dice = md_ptr->r_ptr->blow[i].d_dice;
74         DICE_SID d_side = md_ptr->r_ptr->blow[i].d_side;
75         int damage = damroll(d_dice, d_side);
76         (void)project(player_ptr, md_ptr->m_idx, 3, md_ptr->md_y, md_ptr->md_x, damage, typ, flg);
77         break;
78     }
79 }
80
81 static void on_defeat_arena_monster(PlayerType *player_ptr, monster_death_type *md_ptr)
82 {
83     auto *floor_ptr = player_ptr->current_floor_ptr;
84     if (!floor_ptr->inside_arena || is_pet(md_ptr->m_ptr)) {
85         return;
86     }
87
88     player_ptr->exit_bldg = true;
89     if (player_ptr->arena_number > MAX_ARENA_MONS) {
90         msg_print(_("素晴らしい!君こそ真の勝利者だ。", "You are a Genuine Champion!"));
91     } else {
92         msg_print(_("勝利!チャンピオンへの道を進んでいる。", "Victorious! You're on your way to becoming Champion."));
93     }
94
95     if (arena_info[player_ptr->arena_number].tval > ItemKindType::NONE) {
96         ObjectType forge;
97         auto *q_ptr = &forge;
98         q_ptr->prep(lookup_kind(arena_info[player_ptr->arena_number].tval, arena_info[player_ptr->arena_number].sval));
99         apply_magic_to_object(player_ptr, q_ptr, floor_ptr->object_level, AM_NO_FIXED_ART);
100         (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
101     }
102
103     if (player_ptr->arena_number > MAX_ARENA_MONS) {
104         player_ptr->arena_number++;
105     }
106
107     player_ptr->arena_number++;
108     if (!record_arena) {
109         return;
110     }
111
112     GAME_TEXT m_name[MAX_NLEN];
113     monster_desc(player_ptr, m_name, md_ptr->m_ptr, MD_WRONGDOER_NAME);
114     exe_write_diary(player_ptr, DIARY_ARENA, player_ptr->arena_number, m_name);
115 }
116
117 static void drop_corpse(PlayerType *player_ptr, monster_death_type *md_ptr)
118 {
119     auto *floor_ptr = player_ptr->current_floor_ptr;
120     bool is_drop_corpse = one_in_(md_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE) ? 1 : 4);
121     is_drop_corpse &= (md_ptr->r_ptr->flags9 & (RF9_DROP_CORPSE | RF9_DROP_SKELETON)) != 0;
122     is_drop_corpse &= !(floor_ptr->inside_arena || player_ptr->phase_out || md_ptr->cloned || ((md_ptr->m_ptr->r_idx == w_ptr->today_mon) && is_pet(md_ptr->m_ptr)));
123     if (!is_drop_corpse) {
124         return;
125     }
126
127     bool corpse = false;
128     if (!(md_ptr->r_ptr->flags9 & RF9_DROP_SKELETON)) {
129         corpse = true;
130     } else if ((md_ptr->r_ptr->flags9 & RF9_DROP_CORPSE) && md_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
131         corpse = true;
132     } else if (md_ptr->r_ptr->flags9 & RF9_DROP_CORPSE) {
133         if ((0 - ((md_ptr->m_ptr->maxhp) / 4)) > md_ptr->m_ptr->hp) {
134             if (one_in_(5)) {
135                 corpse = true;
136             }
137         } else {
138             if (!one_in_(5)) {
139                 corpse = true;
140             }
141         }
142     }
143
144     ObjectType forge;
145     auto *q_ptr = &forge;
146     q_ptr->prep(lookup_kind(ItemKindType::CORPSE, (corpse ? SV_CORPSE : SV_SKELETON)));
147     apply_magic_to_object(player_ptr, q_ptr, floor_ptr->object_level, AM_NO_FIXED_ART);
148     q_ptr->pval = md_ptr->m_ptr->r_idx;
149     (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
150 }
151
152 /*!
153  * @brief アーティファクトのドロップ判定処理
154  * @param player_ptr プレイヤーへの参照ポインタ
155  * @param md_ptr モンスター死亡構造体への参照ポインタ
156  * @return 何かドロップするなら1以上、何もドロップしないなら0
157  */
158 static ARTIFACT_IDX drop_artifact_index(PlayerType *player_ptr, monster_death_type *md_ptr)
159 {
160     ARTIFACT_IDX a_idx = 0;
161     PERCENTAGE chance = 0;
162     for (int i = 0; i < 4; i++) {
163         if (!md_ptr->r_ptr->artifact_id[i]) {
164             break;
165         }
166
167         a_idx = md_ptr->r_ptr->artifact_id[i];
168         chance = md_ptr->r_ptr->artifact_percent[i];
169         if ((randint0(100) >= chance) && !w_ptr->wizard) {
170             continue;
171         }
172
173         if (drop_single_artifact(player_ptr, md_ptr, a_idx)) {
174             break;
175         }
176     }
177
178     return a_idx;
179 }
180
181 /*!
182  * @brief 特定アーティファクトのドロップ処理
183  * @param player_ptr プレイヤーへの参照ポインタ
184  * @param md_ptr モンスター死亡構造体への参照ポインタ
185  * @param a_ix ドロップを試みるアーティファクトID
186  * @return ドロップするならtrue
187  */
188 bool drop_single_artifact(PlayerType *player_ptr, monster_death_type *md_ptr, ARTIFACT_IDX a_idx)
189 {
190     auto *a_ptr = &a_info[a_idx];
191     if (a_ptr->cur_num == 1) {
192         return false;
193     }
194
195     if (create_named_art(player_ptr, a_idx, md_ptr->md_y, md_ptr->md_x)) {
196         a_ptr->cur_num = 1;
197
198         if (w_ptr->character_dungeon) {
199             a_ptr->floor_id = player_ptr->floor_id;
200         }
201
202         if (!preserve_mode) {
203             a_ptr->cur_num = 1;
204         }
205
206         return true;
207     }
208     return false;
209 }
210
211 static KIND_OBJECT_IDX drop_dungeon_final_artifact(PlayerType *player_ptr, monster_death_type *md_ptr, ARTIFACT_IDX a_idx)
212 {
213     auto k_idx = d_info[player_ptr->dungeon_idx].final_object != 0 ? d_info[player_ptr->dungeon_idx].final_object : lookup_kind(ItemKindType::SCROLL, SV_SCROLL_ACQUIREMENT);
214     if (d_info[player_ptr->dungeon_idx].final_artifact == 0) {
215         return k_idx;
216     }
217
218     a_idx = d_info[player_ptr->dungeon_idx].final_artifact;
219     auto *a_ptr = &a_info[a_idx];
220     if (a_ptr->cur_num == 1) {
221         return k_idx;
222     }
223     if (create_named_art(player_ptr, a_idx, md_ptr->md_y, md_ptr->md_x)) {
224         a_ptr->cur_num = 1;
225         if (w_ptr->character_dungeon) {
226             a_ptr->floor_id = player_ptr->floor_id;
227         }
228     } else if (!preserve_mode) {
229         a_ptr->cur_num = 1;
230     }
231
232     return d_info[player_ptr->dungeon_idx].final_object ? k_idx : 0;
233 }
234
235 static void drop_artifact(PlayerType *player_ptr, monster_death_type *md_ptr)
236 {
237     if (!md_ptr->drop_chosen_item) {
238         return;
239     }
240
241     ARTIFACT_IDX a_idx = drop_artifact_index(player_ptr, md_ptr);
242     if (((md_ptr->r_ptr->flags7 & RF7_GUARDIAN) == 0) || (d_info[player_ptr->dungeon_idx].final_guardian != md_ptr->m_ptr->r_idx)) {
243         return;
244     }
245
246     KIND_OBJECT_IDX k_idx = drop_dungeon_final_artifact(player_ptr, md_ptr, a_idx);
247     if (k_idx != 0) {
248         ObjectType forge;
249         auto *q_ptr = &forge;
250         q_ptr->prep(k_idx);
251         apply_magic_to_object(player_ptr, q_ptr, player_ptr->current_floor_ptr->object_level, AM_NO_FIXED_ART | AM_GOOD);
252         (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
253     }
254
255     msg_format(_("あなたは%sを制覇した!", "You have conquered %s!"), d_info[player_ptr->dungeon_idx].name.c_str());
256 }
257
258 static void decide_drop_quality(monster_death_type *md_ptr)
259 {
260     md_ptr->mo_mode = 0L;
261     if (md_ptr->r_ptr->flags1 & RF1_DROP_GOOD) {
262         md_ptr->mo_mode |= AM_GOOD;
263     }
264
265     if (md_ptr->r_ptr->flags1 & RF1_DROP_GREAT) {
266         md_ptr->mo_mode |= (AM_GOOD | AM_GREAT);
267     }
268 }
269
270 static int decide_drop_numbers(PlayerType *player_ptr, monster_death_type *md_ptr, const bool drop_item)
271 {
272     int drop_numbers = 0;
273     if ((md_ptr->r_ptr->flags1 & RF1_DROP_60) && (randint0(100) < 60)) {
274         drop_numbers++;
275     }
276
277     if ((md_ptr->r_ptr->flags1 & RF1_DROP_90) && (randint0(100) < 90)) {
278         drop_numbers++;
279     }
280
281     if (md_ptr->r_ptr->flags1 & RF1_DROP_1D2) {
282         drop_numbers += damroll(1, 2);
283     }
284
285     if (md_ptr->r_ptr->flags1 & RF1_DROP_2D2) {
286         drop_numbers += damroll(2, 2);
287     }
288
289     if (md_ptr->r_ptr->flags1 & RF1_DROP_3D2) {
290         drop_numbers += damroll(3, 2);
291     }
292
293     if (md_ptr->r_ptr->flags1 & RF1_DROP_4D2) {
294         drop_numbers += damroll(4, 2);
295     }
296
297     if (md_ptr->cloned && md_ptr->r_ptr->kind_flags.has_not(MonsterKindType::UNIQUE)) {
298         drop_numbers = 0;
299     }
300
301     if (is_pet(md_ptr->m_ptr) || player_ptr->phase_out || player_ptr->current_floor_ptr->inside_arena) {
302         drop_numbers = 0;
303     }
304
305     if (!drop_item && (md_ptr->r_ptr->d_char != '$')) {
306         drop_numbers = 0;
307     }
308
309     if ((md_ptr->r_ptr->flags2 & (RF2_MULTIPLY)) && (md_ptr->r_ptr->r_akills > 1024)) {
310         drop_numbers = 0;
311     }
312
313     return drop_numbers;
314 }
315
316 static void drop_items_golds(PlayerType *player_ptr, monster_death_type *md_ptr, int drop_numbers)
317 {
318     int dump_item = 0;
319     int dump_gold = 0;
320     for (int i = 0; i < drop_numbers; i++) {
321         ObjectType forge;
322         auto *q_ptr = &forge;
323         q_ptr->wipe();
324         if (md_ptr->do_gold && (!md_ptr->do_item || (randint0(100) < 50))) {
325             if (!make_gold(player_ptr, q_ptr)) {
326                 continue;
327             }
328
329             dump_gold++;
330         } else {
331             if (!make_object(player_ptr, q_ptr, md_ptr->mo_mode)) {
332                 continue;
333             }
334
335             dump_item++;
336         }
337
338         (void)drop_near(player_ptr, q_ptr, -1, md_ptr->md_y, md_ptr->md_x);
339     }
340
341     auto *floor_ptr = player_ptr->current_floor_ptr;
342     floor_ptr->object_level = floor_ptr->base_level;
343     coin_type = 0;
344     bool visible = (md_ptr->m_ptr->ml && !player_ptr->effects()->hallucination()->is_hallucinated()) || (md_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE));
345     if (visible && (dump_item || dump_gold)) {
346         lore_treasure(player_ptr, md_ptr->m_idx, dump_item, dump_gold);
347     }
348 }
349
350 /*!
351  * @brief 最終ボス(混沌のサーペント)を倒したときの処理
352  * @param player_ptr プレイヤー情報への参照ポインタ
353  */
354 static void on_defeat_last_boss(PlayerType *player_ptr)
355 {
356     w_ptr->total_winner = true;
357     add_winner_class(player_ptr->pclass);
358     player_ptr->redraw |= PR_TITLE;
359     play_music(TERM_XTRA_MUSIC_BASIC, MUSIC_BASIC_FINAL_QUEST_CLEAR);
360     exe_write_diary(player_ptr, DIARY_DESCRIPTION, 0, _("見事に変愚蛮怒の勝利者となった!", "finally became *WINNER* of Hengband!"));
361     patron_list[player_ptr->chaos_patron].admire(player_ptr);
362     msg_print(_("*** おめでとう ***", "*** CONGRATULATIONS ***"));
363     msg_print(_("あなたはゲームをコンプリートしました。", "You have won the game!"));
364     msg_print(_("準備が整ったら引退(自殺コマンド)しても結構です。", "You may retire (commit suicide) when you are ready."));
365 }
366
367 /*!
368  * @brief モンスターが死亡した時の処理 /
369  * Handle the "death" of a monster.
370  * @param m_idx 死亡したモンスターのID
371  * @param drop_item TRUEならばモンスターのドロップ処理を行う
372  * @param type ラストアタックの属性 (単一属性)
373  */
374 void monster_death(PlayerType *player_ptr, MONSTER_IDX m_idx, bool drop_item, AttributeType type)
375 {
376     AttributeFlags flags;
377     flags.clear();
378     flags.set(type);
379     monster_death(player_ptr, m_idx, drop_item, flags);
380 }
381
382 /*!
383  * @brief モンスターが死亡した時の処理 /
384  * Handle the "death" of a monster.
385  * @param m_idx 死亡したモンスターのID
386  * @param drop_item TRUEならばモンスターのドロップ処理を行う
387  * @param attribute_flags ラストアタックの属性 (複数属性)
388  * @details
389  * <pre>
390  * Disperse treasures centered at the monster location based on the
391  * various flags contained in the monster flags fields.
392  * Check for "Quest" completion when a quest monster is killed.
393  * Note that only the player can induce "monster_death()" on Uniques.
394  * Thus (for now) all Quest monsters should be Uniques.
395  * Note that monsters can now carry objects, and when a monster dies,
396  * it drops all of its objects, which may disappear in crowded rooms.
397  * </pre>
398  */
399 void monster_death(PlayerType *player_ptr, MONSTER_IDX m_idx, bool drop_item, AttributeFlags attribute_flags)
400 {
401     monster_death_type tmp_md;
402     monster_death_type *md_ptr = initialize_monster_death_type(player_ptr, &tmp_md, m_idx, drop_item);
403     if (w_ptr->timewalk_m_idx && w_ptr->timewalk_m_idx == m_idx) {
404         w_ptr->timewalk_m_idx = 0;
405     }
406
407     // プレイヤーしかユニークを倒せないのでここで時間を記録
408     if (md_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE) && md_ptr->m_ptr->mflag2.has_not(MonsterConstantFlagType::CLONED)) {
409         update_playtime();
410         md_ptr->r_ptr->defeat_time = w_ptr->play_time;
411         md_ptr->r_ptr->defeat_level = player_ptr->lev;
412     }
413
414     if (md_ptr->r_ptr->flags7 & (RF7_LITE_MASK | RF7_DARK_MASK)) {
415         player_ptr->update |= PU_MON_LITE;
416     }
417
418     write_pet_death(player_ptr, md_ptr);
419     on_dead_explosion(player_ptr, md_ptr);
420     if (md_ptr->m_ptr->mflag2.has(MonsterConstantFlagType::CHAMELEON)) {
421         choose_new_monster(player_ptr, m_idx, true, MON_CHAMELEON);
422         md_ptr->r_ptr = &r_info[md_ptr->m_ptr->r_idx];
423     }
424
425     QuestCompletionChecker(player_ptr, md_ptr->m_ptr).complete();
426     on_defeat_arena_monster(player_ptr, md_ptr);
427     if (m_idx == player_ptr->riding && process_fall_off_horse(player_ptr, -1, false)) {
428         msg_print(_("地面に落とされた。", "You have fallen from the pet you were riding."));
429     }
430
431     drop_corpse(player_ptr, md_ptr);
432     monster_drop_carried_objects(player_ptr, md_ptr->m_ptr);
433     decide_drop_quality(md_ptr);
434     switch_special_death(player_ptr, md_ptr, attribute_flags);
435     drop_artifact(player_ptr, md_ptr);
436     int drop_numbers = decide_drop_numbers(player_ptr, md_ptr, drop_item);
437     coin_type = md_ptr->force_coin;
438     auto *floor_ptr = player_ptr->current_floor_ptr;
439     floor_ptr->object_level = (floor_ptr->dun_level + md_ptr->r_ptr->level) / 2;
440     drop_items_golds(player_ptr, md_ptr, drop_numbers);
441     if (((md_ptr->r_ptr->flags1 & RF1_QUESTOR) == 0) || player_ptr->phase_out || (md_ptr->m_ptr->r_idx != MON_SERPENT) || md_ptr->cloned) {
442         return;
443     }
444
445     on_defeat_last_boss(player_ptr);
446 }
447
448 /*!
449  * @brief モンスターを撃破した際の述語メッセージを返す /
450  * Return monster death string
451  * @param r_ptr 撃破されたモンスターの種族情報を持つ構造体の参照ポインタ
452  * @return 撃破されたモンスターの述語
453  */
454 concptr extract_note_dies(MONRACE_IDX r_idx)
455 {
456     auto *r_ptr = &r_info[r_idx];
457     if (monster_living(r_idx)) {
458         return _("は死んだ。", " dies.");
459     }
460
461     for (int i = 0; i < 4; i++) {
462         if (r_ptr->blow[i].method == RaceBlowMethodType::EXPLODE) {
463             return _("は爆発して粉々になった。", " explodes into tiny shreds.");
464         }
465     }
466
467     return _("を倒した。", " is destroyed.");
468 }