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"
21 * @brief 精神のないモンスターのPsi攻撃に対する完全な耐性を発動する
22 * @param caster_ptr プレイヤーへの参照ポインタ
23 * @param em_ptr モンスター効果への参照ポインタ
24 * @return 完全な耐性を発動した場合TRUE、そうでなければFALSE
26 static bool resisted_psi_because_empty_mind(player_type *caster_ptr, effect_monster_type *em_ptr)
28 if (none_bits(em_ptr->r_ptr->flags2, RF2_EMPTY_MIND))
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);
40 * @brief 異質な精神のモンスター及び強力なモンスターのPsi攻撃に対する耐性を発動する
41 * @param em_ptr モンスター効果への参照ポインタ
42 * @return 耐性を発動した場合TRUE、そうでなければFALSE
45 * 1) STUPIDまたはWIERD_MINDである
47 * 3) レベルが d(3*ダメージ) より大きい
49 static bool resisted_psi_because_weird_mind_or_powerful(effect_monster_type *em_ptr)
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));
56 em_ptr->note = _("には耐性がある!", " resists!");
62 * @brief 堕落した精神のモンスターへのPsi攻撃のダメージ反射を発動する
63 * @param caster_ptr プレイヤーへの参照ポインタ
64 * @param em_ptr モンスター効果への参照ポインタ
65 * @return ダメージ反射を発動した場合TRUE、そうでなければFALSE
67 * 以下の条件を満たす場合に 1/2 の確率でダメージ反射する
68 * 1) UNDEADまたはDEMONである
69 * 2) レベルが詠唱者の レベル/2 より大きい
71 static bool reflects_psi_with_currupted_mind(player_type *caster_ptr, effect_monster_type *em_ptr)
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);
78 msg_format(_("%^sの堕落した精神は攻撃を跳ね返した!",
79 (em_ptr->seen ? "%^s's corrupted mind backlashes your attack!" : "%^ss corrupted mind backlashes your attack!")),
85 * @brief モンスターがPsi攻撃をダメージ反射した場合のプレイヤーへの追加効果を発動する
86 * @param caster_ptr プレイヤーへの参照ポインタ
87 * @param em_ptr モンスター効果への参照ポインタ
91 * 3/4の確率または影分身時はダメージ及び追加効果はない。
93 static void effect_monster_psi_reflect_extra_effect(player_type *caster_ptr, effect_monster_type *em_ptr)
95 if (!one_in_(4) || check_multishadow(caster_ptr))
98 switch (randint1(4)) {
100 set_confused(caster_ptr, caster_ptr->confused + 3 + randint1(em_ptr->dam));
103 set_stun(caster_ptr, caster_ptr->stun + randint1(em_ptr->dam));
106 if (any_bits(em_ptr->r_ptr->flags3, RF3_NO_FEAR))
107 em_ptr->note = _("には効果がなかった。", " is unaffected.");
109 set_afraid(caster_ptr, caster_ptr->afraid + 3 + randint1(em_ptr->dam));
114 if (!caster_ptr->free_act)
115 (void)set_paralyzed(caster_ptr, caster_ptr->paralyzed + randint1(em_ptr->dam));
122 * @brief モンスターのPsi攻撃に対する耐性を発動する
123 * @param caster_ptr プレイヤーへの参照ポインタ
124 * @param em_ptr モンスター効果への参照ポインタ
127 * 耐性を発動した精神の堕落したモンスターは効力を跳ね返すことがある。
129 static void effect_monster_psi_resist(player_type *caster_ptr, effect_monster_type *em_ptr)
131 if (resisted_psi_because_empty_mind(caster_ptr, em_ptr))
133 if (!resisted_psi_because_weird_mind_or_powerful(em_ptr))
135 if (!reflects_psi_with_currupted_mind(caster_ptr, em_ptr))
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!"));
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);
153 * @brief モンスターへのPsi攻撃の追加効果を発動する
154 * @param caster_ptr プレイヤーへの参照ポインタ
155 * @param em_ptr モンスター効果への参照ポインタ
158 * 効果は、混乱、朦朧、恐怖、麻痺(各耐性無効)
159 * ダメージがないか3/4の確率で効果なし
161 static void effect_monster_psi_extra_effect(effect_monster_type *em_ptr)
163 if ((em_ptr->dam <= 0) || !one_in_(4))
166 switch (randint1(4)) {
168 em_ptr->do_conf = 3 + randint1(em_ptr->dam);
171 em_ptr->do_stun = 3 + randint1(em_ptr->dam);
174 em_ptr->do_fear = 3 + randint1(em_ptr->dam);
177 em_ptr->note = _("は眠り込んでしまった!", " falls asleep!");
178 em_ptr->do_sleep = 3 + randint1(em_ptr->dam);
184 * @brief モンスターへのPsi攻撃(GF_PSI)の効果を発動する
185 * @param caster_ptr プレイヤーへの参照ポインタ
186 * @param em_ptr モンスター効果への参照ポインタ
187 * @return PROICESS_CONTINUE
190 * モンスターの耐性とそれに不随した効果を発動する。
192 process_result effect_monster_psi(player_type *caster_ptr, effect_monster_type *em_ptr)
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);
200 em_ptr->skipped = TRUE;
201 return PROCESS_CONTINUE;
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;
211 * @brief モンスターのPsi攻撃(GF_PSI_DRAIN)に対する耐性を発動する
212 * @param caster_ptr プレイヤーへの参照ポインタ
213 * @param em_ptr モンスター効果への参照ポインタ
216 * 耐性を発動した精神の堕落したモンスターは効力を跳ね返すことがある。
218 static void effect_monster_psi_drain_resist(player_type *caster_ptr, effect_monster_type *em_ptr)
220 if (resisted_psi_because_empty_mind(caster_ptr, em_ptr))
222 if (!resisted_psi_because_weird_mind_or_powerful(em_ptr))
224 if (!reflects_psi_with_currupted_mind(caster_ptr, em_ptr))
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!"));
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);
241 msg_print(_("超能力パワーを吸いとられた!", "Your psychic energy is drained!"));
242 caster_ptr->csp -= damroll(5, em_ptr->dam) / 2;
243 if (caster_ptr->csp < 0)
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);
253 * @brief モンスターへのPsi攻撃(GF_PSI_DRAIN)のダメージをMPに変換する
254 * @param caster_ptr プレイヤーへの参照ポインタ
255 * @param em_ptr モンスター効果への参照ポインタ
258 static void effect_monster_psi_drain_change_power(player_type *caster_ptr, effect_monster_type *em_ptr)
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);
265 b = MIN(caster_ptr->msp, caster_ptr->csp + b);
267 set_bits(caster_ptr->redraw, PR_MANA);
268 set_bits(caster_ptr->window_flags, PW_SPELL);
272 * @brief モンスターへのPsi攻撃(GF_PSI_DRAIN)の効果を発動する
273 * @param caster_ptr プレイヤーへの参照ポインタ
274 * @param em_ptr モンスター効果への参照ポインタ
275 * @return PROICESS_CONTINUE
277 * ダメージがないか3/4の確率で追加効果なし
279 process_result effect_monster_psi_drain(player_type *caster_ptr, effect_monster_type *em_ptr)
282 em_ptr->obvious = TRUE;
284 effect_monster_psi_drain_resist(caster_ptr, em_ptr);
286 effect_monster_psi_drain_change_power(caster_ptr, em_ptr);
288 em_ptr->note_dies = _("の精神は崩壊し、肉体は抜け殻となった。", " collapses, a mindless husk.");
289 return PROCESS_CONTINUE;
293 * @brief モンスターへのテレキネシス(GF_TELEKINESIS)の効果を発動する
294 * @param caster_ptr プレイヤーへの参照ポインタ
295 * @param em_ptr モンスター効果への参照ポインタ
296 * @return PROICESS_CONTINUE
300 process_result effect_monster_telekinesis(player_type *caster_ptr, effect_monster_type *em_ptr)
303 em_ptr->obvious = TRUE;
305 if (caster_ptr->riding && (em_ptr->g_ptr->m_idx == caster_ptr->riding))
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))) {
314 em_ptr->obvious = FALSE;
317 return PROCESS_CONTINUE;