OSDN Git Service

[Refactor] #40413 Separated display-messages.c/h from util.c/h
[hengband/hengband.git] / src / player / eldritch-horror.c
1 /*!
2  * @brief エルドリッチホラー処理
3  * @date 2020/06/07
4  * @author Hourier
5  */
6
7 #include "player/eldritch-horror.h"
8 #include "core/stuff-handler.h"
9 #include "floor/floor.h"
10 #include "monster-race/race-flags1.h"
11 #include "monster-race/race-flags2.h"
12 #include "monster-race/race-flags3.h"
13 #include "monster-race/monster-race-hook.h"
14 #include "monster/horror-descriptions.h"
15 #include "monster/monster-describer.h"
16 #include "monster/monster-info.h"
17 #include "monster/monster-list.h"
18 #include "monster/monster-util.h"
19 #include "monster/smart-learn-types.h"
20 #include "player/player-effects.h"
21 #include "player/player-status.h"
22 #include "player/mimic-info-table.h"
23 #include "view/display-messages.h"
24 #include "world/world.h"
25
26 /*!
27  * @brief エルドリッチホラーの形容詞種別を決める
28  * @param r_ptr モンスター情報への参照ポインタ
29  * @return
30  */
31 static concptr decide_horror_message(monster_race *r_ptr)
32 {
33     int horror_num = randint0(MAX_SAN_HORROR_SUM);
34     if (horror_num < MAX_SAN_HORROR_COMMON) {
35         return horror_desc_common[horror_num];
36     }
37
38     if ((r_ptr->flags3 & RF3_EVIL) != 0) {
39         return horror_desc_evil[horror_num - MAX_SAN_HORROR_COMMON];
40     }
41
42     return horror_desc_neutral[horror_num - MAX_SAN_HORROR_COMMON];
43 }
44
45 /*!
46  * todo m_nameとdescで何が違うのかは良く分からない
47  * @brief エルドリッチホラー持ちのモンスターを見た時の反応 (モンスター名版)
48  * @param m_name モンスター名
49  * @param r_ptr モンスター情報への参照ポインタ
50  * @return なし
51  */
52 static void see_eldritch_horror(GAME_TEXT *m_name, monster_race *r_ptr)
53 {
54     concptr horror_message = decide_horror_message(r_ptr);
55     msg_format(_("%s%sの顔を見てしまった!", "You behold the %s visage of %s!"), horror_message, m_name);
56     r_ptr->r_flags2 |= RF2_ELDRITCH_HORROR;
57 }
58
59 /*!
60  * @brief エルドリッチホラー持ちのモンスターを見た時の反応 (モンスター名版)
61  * @param desc モンスター名 (エルドリッチホラー持ちの全モンスターからランダム…のはず)
62  * @param r_ptr モンスターへの参照ポインタ
63  * @return なし
64  */
65 static void feel_eldritch_horror(concptr desc, monster_race *r_ptr)
66 {
67     concptr horror_message = decide_horror_message(r_ptr);
68     msg_format(_("%s%sの顔を見てしまった!", "You behold the %s visage of %s!"), horror_message, desc);
69     r_ptr->r_flags2 |= RF2_ELDRITCH_HORROR;
70 }
71
72 /*!
73  * @brief ELDRITCH_HORRORによるプレイヤーの精神破壊処理
74  * @param m_ptr ELDRITCH_HORRORを引き起こしたモンスターの参照ポインタ。薬・罠・魔法の影響ならNULL
75  * @param necro 暗黒領域魔法の詠唱失敗によるものならばTRUEを返す
76  * @return なし
77  */
78 void sanity_blast(player_type *creature_ptr, monster_type *m_ptr, bool necro)
79 {
80     if (creature_ptr->phase_out || !current_world_ptr->character_dungeon)
81         return;
82
83     int power = 100;
84     if (!necro && m_ptr) {
85         GAME_TEXT m_name[MAX_NLEN];
86         monster_race *r_ptr = &r_info[m_ptr->ap_r_idx];
87         power = r_ptr->level / 2;
88         monster_desc(creature_ptr, m_name, m_ptr, 0);
89         if (!(r_ptr->flags1 & RF1_UNIQUE)) {
90             if (r_ptr->flags1 & RF1_FRIENDS)
91                 power /= 2;
92         } else
93             power *= 2;
94
95         if (!current_world_ptr->is_loading_now)
96             return;
97
98         if (!m_ptr->ml)
99             return;
100
101         if (!(r_ptr->flags2 & RF2_ELDRITCH_HORROR))
102             return;
103
104         if (is_pet(m_ptr))
105             return;
106
107         if (randint1(100) > power)
108             return;
109
110         if (saving_throw(creature_ptr->skill_sav - power))
111             return;
112
113         if (creature_ptr->image) {
114             msg_format(_("%s%sの顔を見てしまった!", "You behold the %s visage of %s!"), funny_desc[randint0(MAX_SAN_FUNNY)], m_name);
115
116             if (one_in_(3)) {
117                 msg_print(funny_comments[randint0(MAX_SAN_COMMENT)]);
118                 creature_ptr->image = creature_ptr->image + randint1(r_ptr->level);
119             }
120
121             return;
122         }
123
124         see_eldritch_horror(m_name, r_ptr);
125         if (is_specific_player_race(creature_ptr, RACE_IMP) || is_specific_player_race(creature_ptr, RACE_BALROG) || (mimic_info[creature_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_DEMON)
126             || current_world_ptr->wizard)
127             return;
128
129         if (is_specific_player_race(creature_ptr, RACE_SKELETON) || is_specific_player_race(creature_ptr, RACE_ZOMBIE) || is_specific_player_race(creature_ptr, RACE_VAMPIRE)
130             || is_specific_player_race(creature_ptr, RACE_SPECTRE) || (mimic_info[creature_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_UNDEAD)) {
131             if (saving_throw(25 + creature_ptr->lev))
132                 return;
133         }
134     } else if (!necro) {
135         monster_race *r_ptr;
136         GAME_TEXT m_name[MAX_NLEN];
137         concptr desc;
138         get_mon_num_prep(creature_ptr, get_nightmare, NULL);
139         r_ptr = &r_info[get_mon_num(creature_ptr, MAX_DEPTH, 0)];
140         power = r_ptr->level + 10;
141         desc = r_name + r_ptr->name;
142         get_mon_num_prep(creature_ptr, NULL, NULL);
143 #ifdef JP
144 #else
145
146         if (!(r_ptr->flags1 & RF1_UNIQUE))
147             sprintf(m_name, "%s %s", (is_a_vowel(desc[0]) ? "an" : "a"), desc);
148         else
149 #endif
150         sprintf(m_name, "%s", desc);
151
152         if (!(r_ptr->flags1 & RF1_UNIQUE)) {
153             if (r_ptr->flags1 & RF1_FRIENDS)
154                 power /= 2;
155         } else
156             power *= 2;
157
158         if (saving_throw(creature_ptr->skill_sav * 100 / power)) {
159             msg_format(_("夢の中で%sに追いかけられた。", "%^s chases you through your dreams."), m_name);
160             return;
161         }
162
163         if (creature_ptr->image) {
164             msg_format(_("%s%sの顔を見てしまった!", "You behold the %s visage of %s!"), funny_desc[randint0(MAX_SAN_FUNNY)], m_name);
165
166             if (one_in_(3)) {
167                 msg_print(funny_comments[randint0(MAX_SAN_COMMENT)]);
168                 creature_ptr->image = creature_ptr->image + randint1(r_ptr->level);
169             }
170
171             return;
172         }
173
174         feel_eldritch_horror(desc, r_ptr);
175         if (!creature_ptr->mimic_form) {
176             switch (creature_ptr->prace) {
177             case RACE_IMP:
178             case RACE_BALROG:
179                 if (saving_throw(20 + creature_ptr->lev))
180                     return;
181                 break;
182             case RACE_SKELETON:
183             case RACE_ZOMBIE:
184             case RACE_SPECTRE:
185             case RACE_VAMPIRE:
186                 if (saving_throw(10 + creature_ptr->lev))
187                     return;
188                 break;
189             }
190         } else {
191             if (mimic_info[creature_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_DEMON) {
192                 if (saving_throw(20 + creature_ptr->lev))
193                     return;
194             } else if (mimic_info[creature_ptr->mimic_form].MIMIC_FLAGS & MIMIC_IS_UNDEAD) {
195                 if (saving_throw(10 + creature_ptr->lev))
196                     return;
197             }
198         }
199     } else {
200         msg_print(_("ネクロノミコンを読んで正気を失った!", "Your sanity is shaken by reading the Necronomicon!"));
201     }
202
203     /* 過去の効果無効率再現のため5回saving_throw 実行 */
204     if (saving_throw(creature_ptr->skill_sav - power) && saving_throw(creature_ptr->skill_sav - power) && saving_throw(creature_ptr->skill_sav - power)
205         && saving_throw(creature_ptr->skill_sav - power) && saving_throw(creature_ptr->skill_sav - power)) {
206         return;
207     }
208
209     switch (randint1(22)) {
210     case 1: {
211         if (!(creature_ptr->muta3 & MUT3_MORONIC)) {
212             if ((creature_ptr->stat_use[A_INT] < 4) && (creature_ptr->stat_use[A_WIS] < 4)) {
213                 msg_print(_("あなたは完璧な馬鹿になったような気がした。しかしそれは元々だった。", "You turn into an utter moron!"));
214             } else {
215                 msg_print(_("あなたは完璧な馬鹿になった!", "You turn into an utter moron!"));
216             }
217
218             if (creature_ptr->muta3 & MUT3_HYPER_INT) {
219                 msg_print(_("あなたの脳は生体コンピュータではなくなった。", "Your brain is no longer a living computer."));
220                 creature_ptr->muta3 &= ~(MUT3_HYPER_INT);
221             }
222
223             creature_ptr->muta3 |= MUT3_MORONIC;
224         }
225
226         break;
227     }
228     case 2: {
229         if (!(creature_ptr->muta2 & MUT2_COWARDICE) && !creature_ptr->resist_fear) {
230             msg_print(_("あなたはパラノイアになった!", "You become paranoid!"));
231             if (creature_ptr->muta3 & MUT3_FEARLESS) {
232                 msg_print(_("あなたはもう恐れ知らずではなくなった。", "You are no longer fearless."));
233                 creature_ptr->muta3 &= ~(MUT3_FEARLESS);
234             }
235
236             creature_ptr->muta2 |= MUT2_COWARDICE;
237         }
238
239         break;
240     }
241     case 3: {
242         if (!(creature_ptr->muta2 & MUT2_HALLU) && !creature_ptr->resist_chaos) {
243             msg_print(_("幻覚をひき起こす精神錯乱に陥った!", "You are afflicted by a hallucinatory insanity!"));
244             creature_ptr->muta2 |= MUT2_HALLU;
245         }
246
247         break;
248     }
249     case 4: {
250         if (!(creature_ptr->muta2 & MUT2_BERS_RAGE) && !creature_ptr->resist_conf) {
251             msg_print(_("激烈な感情の発作におそわれるようになった!", "You become subject to fits of berserk rage!"));
252             creature_ptr->muta2 |= MUT2_BERS_RAGE;
253         }
254
255         break;
256     }
257     case 5:
258     case 6:
259     case 7:
260     case 8:
261     case 9:
262     case 10:
263     case 11:
264     case 12: {
265         if (!creature_ptr->resist_conf) {
266             (void)set_confused(creature_ptr, creature_ptr->confused + randint0(4) + 4);
267         }
268
269         if (!creature_ptr->resist_chaos && one_in_(3)) {
270             (void)set_image(creature_ptr, creature_ptr->image + randint0(250) + 150);
271         }
272
273         /* todo いつからかは不明だがreturnとbreakが同時に存在している。どちらがデッドコードか不明瞭なので保留 */
274         return;
275         break;
276     }
277     case 13:
278     case 14:
279     case 15: {
280         if (!creature_ptr->resist_conf) {
281             (void)set_confused(creature_ptr, creature_ptr->confused + randint0(4) + 4);
282         }
283         if (!creature_ptr->free_act) {
284             (void)set_paralyzed(creature_ptr, creature_ptr->paralyzed + randint0(4) + 4);
285         }
286         if (!creature_ptr->resist_chaos) {
287             (void)set_image(creature_ptr, creature_ptr->image + randint0(250) + 150);
288         }
289
290         do {
291             (void)do_dec_stat(creature_ptr, A_INT);
292         } while (randint0(100) > creature_ptr->skill_sav && one_in_(2));
293
294         do {
295             (void)do_dec_stat(creature_ptr, A_WIS);
296         } while (randint0(100) > creature_ptr->skill_sav && one_in_(2));
297
298         break;
299     }
300     case 16:
301     case 17: {
302         if (lose_all_info(creature_ptr))
303             msg_print(_("あまりの恐怖に全てのことを忘れてしまった!", "You forget everything in your utmost terror!"));
304         break;
305     }
306     case 18:
307     case 19:
308     case 20:
309     case 21:
310     case 22: {
311         do_dec_stat(creature_ptr, A_INT);
312         do_dec_stat(creature_ptr, A_WIS);
313         break;
314     }
315     default:
316         break;
317     }
318
319     creature_ptr->update |= PU_BONUS;
320     handle_stuff(creature_ptr);
321 }