OSDN Git Service

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