OSDN Git Service

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