OSDN Git Service

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