OSDN Git Service

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