OSDN Git Service

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