OSDN Git Service

Merge pull request #41337 (taotao/hengband/feature/RefreshMonList into develop).
[hengband/hengband.git] / src / effect / effect-monster-psi.c
1 #include "effect/effect-monster-psi.h"
2 #include "core/player-redraw-types.h"
3 #include "core/window-redrawer.h"
4 #include "effect/effect-monster-util.h"
5 #include "floor/line-of-sight.h"
6 #include "mind/mind-mirror-master.h"
7 #include "monster-race/monster-race.h"
8 #include "monster-race/race-flags1.h"
9 #include "monster-race/race-flags2.h"
10 #include "monster-race/race-flags3.h"
11 #include "monster/monster-describer.h"
12 #include "monster/monster-description-types.h"
13 #include "monster/monster-info.h"
14 #include "status/bad-status-setter.h"
15 #include "player/player-damage.h"
16 #include "view/display-messages.h"
17 #include "world/world.h"
18
19 static bool effect_monster_psi_empty_mind(player_type *caster_ptr, effect_monster_type *em_ptr)
20 {
21         if ((em_ptr->r_ptr->flags2 & RF2_EMPTY_MIND) == 0) return FALSE;
22
23         em_ptr->dam = 0;
24         em_ptr->note = _("には完全な耐性がある!", " is immune.");
25         if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr))
26                 em_ptr->r_ptr->r_flags2 |= (RF2_EMPTY_MIND);
27
28         return TRUE;
29 }
30
31
32 static bool effect_monster_psi_weird_mind(effect_monster_type *em_ptr)
33 {
34         bool has_resistance = ((em_ptr->r_ptr->flags2 & (RF2_STUPID | RF2_WEIRD_MIND)) != 0) ||
35                 ((em_ptr->r_ptr->flags3 & RF3_ANIMAL) != 0) ||
36                 (em_ptr->r_ptr->level > randint1(3 * em_ptr->dam));
37         if (!has_resistance) return FALSE;
38
39         em_ptr->note = _("には耐性がある!", " resists!");
40         em_ptr->dam /= 3;
41         return TRUE;
42 }
43
44
45 static bool effect_monster_psi_corrupted(player_type *caster_ptr, effect_monster_type *em_ptr)
46 {
47         bool is_powerful = ((em_ptr->r_ptr->flags3 & (RF3_UNDEAD | RF3_DEMON)) != 0) &&
48                 (em_ptr->r_ptr->level > caster_ptr->lev / 2) &&
49                 one_in_(2);
50         if (!is_powerful) return FALSE;
51
52         em_ptr->note = NULL;
53         msg_format(_("%^sの堕落した精神は攻撃を跳ね返した!",
54                 (em_ptr->seen ? "%^s's corrupted mind backlashes your attack!" :
55                         "%^ss corrupted mind backlashes your attack!")), em_ptr->m_name);
56         return TRUE;
57 }
58
59
60 static void effect_monster_psi_resist_addition(player_type *caster_ptr, effect_monster_type *em_ptr)
61 {
62         switch (randint1(4))
63         {
64         case 1:
65                 set_confused(caster_ptr, caster_ptr->confused + 3 + randint1(em_ptr->dam));
66                 break;
67         case 2:
68                 set_stun(caster_ptr, caster_ptr->stun + randint1(em_ptr->dam));
69                 break;
70         case 3:
71         {
72                 if (em_ptr->r_ptr->flags3 & RF3_NO_FEAR)
73                         em_ptr->note = _("には効果がなかった。", " is unaffected.");
74                 else
75                         set_afraid(caster_ptr, caster_ptr->afraid + 3 + randint1(em_ptr->dam));
76
77                 break;
78         }
79         default:
80                 if (!caster_ptr->free_act)
81                         (void)set_paralyzed(caster_ptr, caster_ptr->paralyzed + randint1(em_ptr->dam));
82
83                 break;
84         }
85 }
86
87
88 // Powerful demons & undead can turn a mindcrafter's attacks back on them.
89 static void effect_monster_psi_resist(player_type *caster_ptr, effect_monster_type *em_ptr)
90 {
91         if (effect_monster_psi_empty_mind(caster_ptr, em_ptr)) return;
92         if (effect_monster_psi_weird_mind(em_ptr)) return;
93         if (!effect_monster_psi_corrupted(caster_ptr, em_ptr)) return;
94
95         if ((randint0(100 + em_ptr->r_ptr->level / 2) < caster_ptr->skill_sav) && !check_multishadow(caster_ptr))
96         {
97                 msg_print(_("しかし効力を跳ね返した!", "You resist the effects!"));
98                 em_ptr->dam = 0;
99                 return;
100         }
101
102         /* Injure +/- confusion */
103         monster_desc(caster_ptr, em_ptr->killer, em_ptr->m_ptr, MD_WRONGDOER_NAME);
104         take_hit(caster_ptr, DAMAGE_ATTACK, em_ptr->dam, em_ptr->killer, -1);
105         if (!one_in_(4) || check_multishadow(caster_ptr))
106         {
107                 em_ptr->dam = 0;
108                 return;
109         }
110
111         effect_monster_psi_resist_addition(caster_ptr, em_ptr);
112         em_ptr->dam = 0;
113 }
114
115
116 static void effect_monster_psi_addition(effect_monster_type *em_ptr)
117 {
118         if ((em_ptr->dam <= 0) || !one_in_(4)) return;
119
120         switch (randint1(4))
121         {
122         case 1:
123                 em_ptr->do_conf = 3 + randint1(em_ptr->dam);
124                 break;
125         case 2:
126                 em_ptr->do_stun = 3 + randint1(em_ptr->dam);
127                 break;
128         case 3:
129                 em_ptr->do_fear = 3 + randint1(em_ptr->dam);
130                 break;
131         default:
132                 em_ptr->note = _("は眠り込んでしまった!", " falls asleep!");
133                 em_ptr->do_sleep = 3 + randint1(em_ptr->dam);
134                 break;
135         }
136 }
137
138
139 process_result effect_monster_psi(player_type *caster_ptr, effect_monster_type *em_ptr)
140 {
141         if (em_ptr->seen) em_ptr->obvious = TRUE;
142         if (!(los(caster_ptr, em_ptr->m_ptr->fy, em_ptr->m_ptr->fx, caster_ptr->y, caster_ptr->x)))
143         {
144                 if (em_ptr->seen_msg)
145                         msg_format(_("%sはあなたが見えないので影響されない!", "%^s can't see you, and isn't affected!"), em_ptr->m_name);
146
147                 em_ptr->skipped = TRUE;
148                 return PROCESS_CONTINUE;
149         }
150
151         effect_monster_psi_resist(caster_ptr, em_ptr);
152         effect_monster_psi_addition(em_ptr);
153         em_ptr->note_dies = _("の精神は崩壊し、肉体は抜け殻となった。", " collapses, a mindless husk.");
154         return PROCESS_CONTINUE;
155 }
156
157
158 static bool effect_monster_psi_drain_corrupted(player_type *caster_ptr, effect_monster_type *em_ptr)
159 {
160         bool is_corrupted = ((em_ptr->r_ptr->flags3 & (RF3_UNDEAD | RF3_DEMON)) != 0) &&
161                 (em_ptr->r_ptr->level > caster_ptr->lev / 2) &&
162                 (one_in_(2));
163         if (!is_corrupted) return FALSE;
164
165         em_ptr->note = NULL;
166         msg_format(_("%^sの堕落した精神は攻撃を跳ね返した!",
167                 (em_ptr->seen ? "%^s's corrupted mind backlashes your attack!" :
168                         "%^ss corrupted mind backlashes your attack!")), em_ptr->m_name);
169         return TRUE;
170 }
171
172
173 // Powerful demons & undead can turn a mindcrafter's attacks back on them.
174 static void effect_monster_psi_drain_resist(player_type *caster_ptr, effect_monster_type *em_ptr)
175 {
176         em_ptr->note = _("には耐性がある!", " resists!");
177         em_ptr->dam /= 3;
178         if (effect_monster_psi_drain_corrupted(caster_ptr, em_ptr)) return;
179
180         if ((randint0(100 + em_ptr->r_ptr->level / 2) < caster_ptr->skill_sav) && !check_multishadow(caster_ptr))
181         {
182                 msg_print(_("あなたは効力を跳ね返した!", "You resist the effects!"));
183                 em_ptr->dam = 0;
184                 return;
185         }
186
187         monster_desc(caster_ptr, em_ptr->killer, em_ptr->m_ptr, MD_WRONGDOER_NAME);
188         if (check_multishadow(caster_ptr))
189         {
190                 take_hit(caster_ptr, DAMAGE_ATTACK, em_ptr->dam, em_ptr->killer, -1);
191                 em_ptr->dam = 0;
192                 return;
193         }
194
195         msg_print(_("超能力パワーを吸いとられた!", "Your psychic energy is drained!"));
196         caster_ptr->csp -= damroll(5, em_ptr->dam) / 2;
197         if (caster_ptr->csp < 0) caster_ptr->csp = 0;
198
199         caster_ptr->redraw |= PR_MANA;
200         caster_ptr->window |= (PW_SPELL);
201         take_hit(caster_ptr, DAMAGE_ATTACK, em_ptr->dam, em_ptr->killer, -1);
202         em_ptr->dam = 0;
203 }
204
205
206 static void effect_monster_psi_drain_change_power(player_type *caster_ptr, effect_monster_type *em_ptr)
207 {
208         int b = damroll(5, em_ptr->dam) / 4;
209         concptr str = (caster_ptr->pclass == CLASS_MINDCRAFTER) ? _("超能力パワー", "psychic energy") : _("魔力", "mana");
210         concptr msg = _("あなたは%sの苦痛を%sに変換した!",
211                 (em_ptr->seen ? "You convert %s's pain into %s!" : "You convert %ss pain into %s!"));
212         msg_format(msg, em_ptr->m_name, str);
213
214         b = MIN(caster_ptr->msp, caster_ptr->csp + b);
215         caster_ptr->csp = b;
216         caster_ptr->redraw |= PR_MANA;
217         caster_ptr->window |= (PW_SPELL);
218 }
219
220
221 process_result effect_monster_psi_drain(player_type *caster_ptr, effect_monster_type *em_ptr)
222 {
223         if (em_ptr->seen) em_ptr->obvious = TRUE;
224
225         if (em_ptr->r_ptr->flags2 & RF2_EMPTY_MIND)
226         {
227                 em_ptr->dam = 0;
228                 em_ptr->note = _("には完全な耐性がある!", " is immune.");
229         }
230         else if ((em_ptr->r_ptr->flags2 & (RF2_STUPID | RF2_WEIRD_MIND)) ||
231                 (em_ptr->r_ptr->flags3 & RF3_ANIMAL) ||
232                 (em_ptr->r_ptr->level > randint1(3 * em_ptr->dam)))
233         {
234                 effect_monster_psi_drain_resist(caster_ptr, em_ptr);
235         }
236         else if (em_ptr->dam > 0)
237         {
238                 effect_monster_psi_drain_change_power(caster_ptr, em_ptr);
239         }
240
241         em_ptr->note_dies = _("の精神は崩壊し、肉体は抜け殻となった。", " collapses, a mindless husk.");
242         return PROCESS_CONTINUE;
243 }
244
245
246 process_result effect_monster_telekinesis(player_type *caster_ptr, effect_monster_type *em_ptr)
247 {
248         if (em_ptr->seen) em_ptr->obvious = TRUE;
249         if (one_in_(4))
250         {
251                 if (caster_ptr->riding && (em_ptr->g_ptr->m_idx == caster_ptr->riding)) em_ptr->do_dist = 0;
252                 else em_ptr->do_dist = 7;
253         }
254
255         em_ptr->do_stun = damroll((em_ptr->caster_lev / 20) + 3, em_ptr->dam) + 1;
256         if ((em_ptr->r_ptr->flags1 & RF1_UNIQUE) ||
257                 (em_ptr->r_ptr->level > 5 + randint1(em_ptr->dam)))
258         {
259                 em_ptr->do_stun = 0;
260                 em_ptr->obvious = FALSE;
261         }
262
263         return PROCESS_CONTINUE;
264 }