OSDN Git Service

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