OSDN Git Service

Merge pull request #857 from sikabane-works/feature/fix-doxygen-syntax
[hengbandforosx/hengbandosx.git] / src / effect / effect-monster-psi.cpp
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 "player/player-damage.h"
15 #include "status/bad-status-setter.h"
16 #include "util/bit-flags-calculator.h"
17 #include "view/display-messages.h"
18 #include "world/world.h"
19
20 /*!
21  * @brief 精神のないモンスターのPsi攻撃に対する完全な耐性を発動する
22  * @param caster_ptr プレイヤーへの参照ポインタ
23  * @param em_ptr モンスター効果への参照ポインタ
24  * @return 完全な耐性を発動した場合TRUE、そうでなければFALSE
25  */
26 static bool resisted_psi_because_empty_mind(player_type *caster_ptr, effect_monster_type *em_ptr)
27 {
28     if (none_bits(em_ptr->r_ptr->flags2, RF2_EMPTY_MIND))
29         return FALSE;
30
31     em_ptr->dam = 0;
32     em_ptr->note = _("には完全な耐性がある!", " is immune.");
33     if (is_original_ap_and_seen(caster_ptr, em_ptr->m_ptr))
34         set_bits(em_ptr->r_ptr->r_flags2, RF2_EMPTY_MIND);
35
36     return TRUE;
37 }
38
39 /*!
40  * @brief 異質な精神のモンスター及び強力なモンスターのPsi攻撃に対する耐性を発動する
41  * @param em_ptr モンスター効果への参照ポインタ
42  * @return 耐性を発動した場合TRUE、そうでなければFALSE
43  * @details
44  * 以下のいずれかの場合は耐性がある
45  * 1) STUPIDまたはWIERD_MINDである
46  * 2) ANIMALである
47  * 3) レベルが d(3*ダメージ) より大きい
48  */
49 static bool resisted_psi_because_weird_mind_or_powerful(effect_monster_type *em_ptr)
50 {
51     bool has_resistance = any_bits(em_ptr->r_ptr->flags2, RF2_STUPID | RF2_WEIRD_MIND) || any_bits(em_ptr->r_ptr->flags3, RF3_ANIMAL)
52         || (em_ptr->r_ptr->level > randint1(3 * em_ptr->dam));
53     if (!has_resistance)
54         return FALSE;
55
56     em_ptr->note = _("には耐性がある!", " resists!");
57     em_ptr->dam /= 3;
58     return TRUE;
59 }
60
61 /*!
62  * @brief 堕落した精神のモンスターへのPsi攻撃のダメージ反射を発動する
63  * @param caster_ptr プレイヤーへの参照ポインタ
64  * @param em_ptr モンスター効果への参照ポインタ
65  * @return ダメージ反射を発動した場合TRUE、そうでなければFALSE
66  * @details
67  * 以下の条件を満たす場合に 1/2 の確率でダメージ反射する
68  * 1) UNDEADまたはDEMONである
69  * 2) レベルが詠唱者の レベル/2 より大きい
70  */
71 static bool reflects_psi_with_currupted_mind(player_type *caster_ptr, effect_monster_type *em_ptr)
72 {
73     bool is_corrupted = any_bits(em_ptr->r_ptr->flags3, RF3_UNDEAD | RF3_DEMON) && (em_ptr->r_ptr->level > caster_ptr->lev / 2) && one_in_(2);
74     if (!is_corrupted)
75         return FALSE;
76
77     em_ptr->note = NULL;
78     msg_format(_("%^sの堕落した精神は攻撃を跳ね返した!",
79                    (em_ptr->seen ? "%^s's corrupted mind backlashes your attack!" : "%^ss corrupted mind backlashes your attack!")),
80         em_ptr->m_name);
81     return TRUE;
82 }
83
84 /*!
85  * @brief モンスターがPsi攻撃をダメージ反射した場合のプレイヤーへの追加効果を発動する
86  * @param caster_ptr プレイヤーへの参照ポインタ
87  * @param em_ptr モンスター効果への参照ポインタ
88  * @return なし
89  * @details
90  * 効果は、混乱、朦朧、恐怖、麻痺
91  * 3/4の確率または影分身時はダメージ及び追加効果はない。
92  */
93 static void effect_monster_psi_reflect_extra_effect(player_type *caster_ptr, effect_monster_type *em_ptr)
94 {
95     if (!one_in_(4) || check_multishadow(caster_ptr))
96         return;
97
98     switch (randint1(4)) {
99     case 1:
100         set_confused(caster_ptr, caster_ptr->confused + 3 + randint1(em_ptr->dam));
101         break;
102     case 2:
103         set_stun(caster_ptr, caster_ptr->stun + randint1(em_ptr->dam));
104         break;
105     case 3: {
106         if (any_bits(em_ptr->r_ptr->flags3, RF3_NO_FEAR))
107             em_ptr->note = _("には効果がなかった。", " is unaffected.");
108         else
109             set_afraid(caster_ptr, caster_ptr->afraid + 3 + randint1(em_ptr->dam));
110
111         break;
112     }
113     default:
114         if (!caster_ptr->free_act)
115             (void)set_paralyzed(caster_ptr, caster_ptr->paralyzed + randint1(em_ptr->dam));
116
117         break;
118     }
119 }
120
121 /*!
122  * @brief モンスターのPsi攻撃に対する耐性を発動する
123  * @param caster_ptr プレイヤーへの参照ポインタ
124  * @param em_ptr モンスター効果への参照ポインタ
125  * @return なし
126  * @details
127  * 耐性を発動した精神の堕落したモンスターは効力を跳ね返すことがある。
128  */
129 static void effect_monster_psi_resist(player_type *caster_ptr, effect_monster_type *em_ptr)
130 {
131     if (resisted_psi_because_empty_mind(caster_ptr, em_ptr))
132         return;
133     if (!resisted_psi_because_weird_mind_or_powerful(em_ptr))
134         return;
135     if (!reflects_psi_with_currupted_mind(caster_ptr, em_ptr))
136         return;
137
138     /* プレイヤーの反射判定 */
139     if ((randint0(100 + em_ptr->r_ptr->level / 2) < caster_ptr->skill_sav) && !check_multishadow(caster_ptr)) {
140         msg_print(_("しかし効力を跳ね返した!", "You resist the effects!"));
141         em_ptr->dam = 0;
142         return;
143     }
144
145     /* Injure +/- confusion */
146     monster_desc(caster_ptr, em_ptr->killer, em_ptr->m_ptr, MD_WRONGDOER_NAME);
147     take_hit(caster_ptr, DAMAGE_ATTACK, em_ptr->dam, em_ptr->killer);
148     effect_monster_psi_reflect_extra_effect(caster_ptr, em_ptr);
149     em_ptr->dam = 0;
150 }
151
152 /*!
153  * @brief モンスターへのPsi攻撃の追加効果を発動する
154  * @param caster_ptr プレイヤーへの参照ポインタ
155  * @param em_ptr モンスター効果への参照ポインタ
156  * @return なし
157  * @details
158  * 効果は、混乱、朦朧、恐怖、麻痺(各耐性無効)
159  * ダメージがないか3/4の確率で効果なし
160  */
161 static void effect_monster_psi_extra_effect(effect_monster_type *em_ptr)
162 {
163     if ((em_ptr->dam <= 0) || !one_in_(4))
164         return;
165
166     switch (randint1(4)) {
167     case 1:
168         em_ptr->do_conf = 3 + randint1(em_ptr->dam);
169         break;
170     case 2:
171         em_ptr->do_stun = 3 + randint1(em_ptr->dam);
172         break;
173     case 3:
174         em_ptr->do_fear = 3 + randint1(em_ptr->dam);
175         break;
176     default:
177         em_ptr->note = _("は眠り込んでしまった!", " falls asleep!");
178         em_ptr->do_sleep = 3 + randint1(em_ptr->dam);
179         break;
180     }
181 }
182
183 /*!
184  * @brief モンスターへのPsi攻撃(GF_PSI)の効果を発動する
185  * @param caster_ptr プレイヤーへの参照ポインタ
186  * @param em_ptr モンスター効果への参照ポインタ
187  * @return PROICESS_CONTINUE
188  * @details
189  * 視界による影響を発動する。
190  * モンスターの耐性とそれに不随した効果を発動する。
191  */
192 process_result effect_monster_psi(player_type *caster_ptr, effect_monster_type *em_ptr)
193 {
194     if (em_ptr->seen)
195         em_ptr->obvious = TRUE;
196     if (!(los(caster_ptr, em_ptr->m_ptr->fy, em_ptr->m_ptr->fx, caster_ptr->y, caster_ptr->x))) {
197         if (em_ptr->seen_msg)
198             msg_format(_("%sはあなたが見えないので影響されない!", "%^s can't see you, and isn't affected!"), em_ptr->m_name);
199
200         em_ptr->skipped = TRUE;
201         return PROCESS_CONTINUE;
202     }
203
204     effect_monster_psi_resist(caster_ptr, em_ptr);
205     effect_monster_psi_extra_effect(em_ptr);
206     em_ptr->note_dies = _("の精神は崩壊し、肉体は抜け殻となった。", " collapses, a mindless husk.");
207     return PROCESS_CONTINUE;
208 }
209
210 /*!
211  * @brief モンスターのPsi攻撃(GF_PSI_DRAIN)に対する耐性を発動する
212  * @param caster_ptr プレイヤーへの参照ポインタ
213  * @param em_ptr モンスター効果への参照ポインタ
214  * @return なし
215  * @details
216  * 耐性を発動した精神の堕落したモンスターは効力を跳ね返すことがある。
217  */
218 static void effect_monster_psi_drain_resist(player_type *caster_ptr, effect_monster_type *em_ptr)
219 {
220     if (resisted_psi_because_empty_mind(caster_ptr, em_ptr))
221         return;
222     if (!resisted_psi_because_weird_mind_or_powerful(em_ptr))
223         return;
224     if (!reflects_psi_with_currupted_mind(caster_ptr, em_ptr))
225         return;
226
227     /* プレイヤーの反射判定 */
228     if ((randint0(100 + em_ptr->r_ptr->level / 2) < caster_ptr->skill_sav) && !check_multishadow(caster_ptr)) {
229         msg_print(_("あなたは効力を跳ね返した!", "You resist the effects!"));
230         em_ptr->dam = 0;
231         return;
232     }
233
234     monster_desc(caster_ptr, em_ptr->killer, em_ptr->m_ptr, MD_WRONGDOER_NAME);
235     if (check_multishadow(caster_ptr)) {
236         take_hit(caster_ptr, DAMAGE_ATTACK, em_ptr->dam, em_ptr->killer);
237         em_ptr->dam = 0;
238         return;
239     }
240
241     msg_print(_("超能力パワーを吸いとられた!", "Your psychic energy is drained!"));
242     caster_ptr->csp -= damroll(5, em_ptr->dam) / 2;
243     if (caster_ptr->csp < 0)
244         caster_ptr->csp = 0;
245
246     set_bits(caster_ptr->redraw, PR_MANA);
247     set_bits(caster_ptr->window_flags, PW_SPELL);
248     take_hit(caster_ptr, DAMAGE_ATTACK, em_ptr->dam, em_ptr->killer);
249     em_ptr->dam = 0;
250 }
251
252 /*!
253  * @brief モンスターへのPsi攻撃(GF_PSI_DRAIN)のダメージをMPに変換する
254  * @param caster_ptr プレイヤーへの参照ポインタ
255  * @param em_ptr モンスター効果への参照ポインタ
256  * @return なし
257  */
258 static void effect_monster_psi_drain_change_power(player_type *caster_ptr, effect_monster_type *em_ptr)
259 {
260     int b = damroll(5, em_ptr->dam) / 4;
261     concptr str = (caster_ptr->pclass == CLASS_MINDCRAFTER) ? _("超能力パワー", "psychic energy") : _("魔力", "mana");
262     concptr msg = _("あなたは%sの苦痛を%sに変換した!", (em_ptr->seen ? "You convert %s's pain into %s!" : "You convert %ss pain into %s!"));
263     msg_format(msg, em_ptr->m_name, str);
264
265     b = MIN(caster_ptr->msp, caster_ptr->csp + b);
266     caster_ptr->csp = b;
267     set_bits(caster_ptr->redraw, PR_MANA);
268     set_bits(caster_ptr->window_flags, PW_SPELL);
269 }
270
271 /*!
272  * @brief モンスターへのPsi攻撃(GF_PSI_DRAIN)の効果を発動する
273  * @param caster_ptr プレイヤーへの参照ポインタ
274  * @param em_ptr モンスター効果への参照ポインタ
275  * @return PROICESS_CONTINUE
276  * @details
277  * ダメージがないか3/4の確率で追加効果なし
278  */
279 process_result effect_monster_psi_drain(player_type *caster_ptr, effect_monster_type *em_ptr)
280 {
281     if (em_ptr->seen)
282         em_ptr->obvious = TRUE;
283
284     effect_monster_psi_drain_resist(caster_ptr, em_ptr);
285     if (em_ptr->dam > 0)
286         effect_monster_psi_drain_change_power(caster_ptr, em_ptr);
287
288     em_ptr->note_dies = _("の精神は崩壊し、肉体は抜け殻となった。", " collapses, a mindless husk.");
289     return PROCESS_CONTINUE;
290 }
291
292 /*!
293  * @brief モンスターへのテレキネシス(GF_TELEKINESIS)の効果を発動する
294  * @param caster_ptr プレイヤーへの参照ポインタ
295  * @param em_ptr モンスター効果への参照ポインタ
296  * @return PROICESS_CONTINUE
297  * @details
298  * 朦朧+ショートテレポートアウェイ
299  */
300 process_result effect_monster_telekinesis(player_type *caster_ptr, effect_monster_type *em_ptr)
301 {
302     if (em_ptr->seen)
303         em_ptr->obvious = TRUE;
304     if (one_in_(4)) {
305         if (caster_ptr->riding && (em_ptr->g_ptr->m_idx == caster_ptr->riding))
306             em_ptr->do_dist = 0;
307         else
308             em_ptr->do_dist = 7;
309     }
310
311     em_ptr->do_stun = damroll((em_ptr->caster_lev / 20) + 3, em_ptr->dam) + 1;
312     if (any_bits(em_ptr->r_ptr->flags1, RF1_UNIQUE) || (em_ptr->r_ptr->level > 5 + randint1(em_ptr->dam))) {
313         em_ptr->do_stun = 0;
314         em_ptr->obvious = FALSE;
315     }
316
317     return PROCESS_CONTINUE;
318 }