2 * @brief プレイヤーのステータスを下げるか、モンスター自身のステータスを上げるスペル類の処理
5 * @todo やや過密気味。モンスター自身のステータスとプレイヤーのステータスで分けてもいいかもしれない.
8 #include "mspell/mspell-status.h"
9 #include "blue-magic/blue-magic-checker.h"
10 #include "core/disturbance.h"
11 #include "effect/attribute-types.h"
12 #include "effect/effect-processor.h"
13 #include "mind/drs-types.h"
14 #include "monster-race/monster-race.h"
15 #include "monster-race/race-ability-flags.h"
16 #include "monster-race/race-flags1.h"
17 #include "monster-race/race-flags3.h"
18 #include "monster-race/race-indice-types.h"
19 #include "monster/monster-describer.h"
20 #include "monster/monster-description-types.h"
21 #include "monster/monster-info.h"
22 #include "monster/monster-status-setter.h"
23 #include "monster/monster-status.h"
24 #include "monster/monster-update.h"
25 #include "mspell/mspell-checker.h"
26 #include "mspell/mspell-damage-calculator.h"
27 #include "mspell/mspell-result.h"
28 #include "mspell/mspell-util.h"
29 #include "player/player-personality-types.h"
30 #include "player/player-status-flags.h"
31 #include "status/bad-status-setter.h"
32 #include "status/base-status.h"
33 #include "system/floor-type-definition.h"
34 #include "system/monster-entity.h"
35 #include "system/monster-race-info.h"
36 #include "system/player-type-definition.h"
37 #include "system/redrawing-flags-updater.h"
38 #include "timed-effect/player-blindness.h"
39 #include "timed-effect/timed-effects.h"
40 #include "view/display-messages.h"
42 mspell_cast_msg_bad_status_to_player::mspell_cast_msg_bad_status_to_player(concptr blind, concptr not_blind, concptr resist, concptr saved_throw)
44 , not_blind(not_blind)
46 , saved_throw(saved_throw)
50 mspell_cast_msg_bad_status_to_monster::mspell_cast_msg_bad_status_to_monster(concptr default_msg, concptr resist, concptr saved_throw, concptr success)
51 : default_msg(default_msg)
53 , saved_throw(saved_throw)
59 * @brief 状態異常呪文のメッセージ処理関数。 /
60 * @param player_ptr プレイヤーへの参照ポインタ
61 * @param m_idx 呪文を唱えるモンスターID
62 * @param msgs メッセージの構造体
63 * @param resist 耐性の有無を判別するフラグ
64 * @param saved_throw 抵抗に成功したか判別するフラグ
66 void spell_badstatus_message_to_player(PlayerType *player_ptr, MONSTER_IDX m_idx, const mspell_cast_msg_bad_status_to_player &msgs, bool resist,
69 const auto m_name = monster_name(player_ptr, m_idx);
71 disturb(player_ptr, true, true);
72 if (player_ptr->effects()->blindness()->is_blind()) {
73 msg_format(msgs.blind, m_name.data());
75 msg_format(msgs.not_blind, m_name.data());
79 msg_print(msgs.resist);
80 } else if (saved_throw) {
81 msg_print(msgs.saved_throw);
88 * @brief 状態異常呪文のメッセージ処理関数(対モンスター)。 /
89 * @param player_ptr プレーヤーへの参照ポインタ
90 * @param m_idx 呪文を唱えるモンスターID
91 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
92 * @param msgs メッセージの構造体
93 * @param resist 耐性の有無を判別するフラグ
94 * @param saved_throw 抵抗に成功したか判別するフラグ
96 void spell_badstatus_message_to_mons(PlayerType *player_ptr, MONSTER_IDX m_idx, MONSTER_IDX t_idx, const mspell_cast_msg_bad_status_to_monster &msgs, bool resist,
99 auto *floor_ptr = player_ptr->current_floor_ptr;
100 bool see_either = see_monster(player_ptr, m_idx) || see_monster(player_ptr, t_idx);
101 bool see_t = see_monster(player_ptr, t_idx);
102 bool known = monster_near_player(floor_ptr, m_idx, t_idx);
103 const auto m_name = monster_name(player_ptr, m_idx);
104 const auto t_name = monster_name(player_ptr, t_idx);
108 msg_format(msgs.default_msg, m_name.data(), t_name.data());
110 floor_ptr->monster_noise = true;
116 msg_format(msgs.resist, t_name.data());
118 } else if (saved_throw) {
120 msg_format(msgs.saved_throw, t_name.data());
124 msg_format(msgs.success, t_name.data());
128 set_monster_csleep(player_ptr, t_idx, 0);
132 * @brief RF5_DRAIN_MANAの処理。魔力吸収。 /
133 * @param player_ptr プレイヤーへの参照ポインタ
136 * @param m_idx 呪文を唱えるモンスターID
137 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
138 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
142 MonsterSpellResult spell_RF5_DRAIN_MANA(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
144 const auto m_name = monster_name(player_ptr, m_idx);
145 const auto t_name = monster_name(player_ptr, t_idx);
147 if (target_type == MONSTER_TO_PLAYER) {
148 disturb(player_ptr, true, true);
149 } else if (target_type == MONSTER_TO_MONSTER && see_monster(player_ptr, m_idx)) {
151 msg_format(_("%s^は精神エネルギーを%sから吸いとった。", "%s^ draws psychic energy from %s."), m_name.data(), t_name.data());
154 const auto dam = monspell_damage(player_ptr, MonsterAbilityType::DRAIN_MANA, m_idx, DAM_ROLL);
155 const auto proj_res = pointed(player_ptr, y, x, m_idx, AttributeType::DRAIN_MANA, dam, target_type);
156 if (target_type == MONSTER_TO_PLAYER) {
157 update_smart_learn(player_ptr, m_idx, DRS_MANA);
160 auto res = MonsterSpellResult::make_valid();
161 res.learnable = proj_res.affected_player;
167 * @brief RF5_MIND_BLASTの処理。精神攻撃。 /
168 * @param player_ptr プレイヤーへの参照ポインタ
171 * @param m_idx 呪文を唱えるモンスターID
172 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
173 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
177 MonsterSpellResult spell_RF5_MIND_BLAST(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
179 auto *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
180 bool seen = (!player_ptr->effects()->blindness()->is_blind() && m_ptr->ml);
181 const auto m_name = monster_name(player_ptr, m_idx);
182 const auto t_name = monster_name(player_ptr, t_idx);
184 if (target_type == MONSTER_TO_PLAYER) {
185 disturb(player_ptr, true, true);
187 msg_print(_("何かがあなたの精神に念を放っているようだ。", "You feel something focusing on your mind."));
189 msg_format(_("%s^があなたの瞳をじっとにらんでいる。", "%s^ gazes deep into your eyes."), m_name.data());
191 } else if (target_type == MONSTER_TO_MONSTER && see_monster(player_ptr, m_idx)) {
192 msg_format(_("%s^は%sをじっと睨んだ。", "%s^ gazes intently at %s."), m_name.data(), t_name.data());
195 const auto dam = monspell_damage(player_ptr, MonsterAbilityType::MIND_BLAST, m_idx, DAM_ROLL);
196 const auto proj_res = pointed(player_ptr, y, x, m_idx, AttributeType::MIND_BLAST, dam, target_type);
198 auto res = MonsterSpellResult::make_valid(dam);
199 res.learnable = proj_res.affected_player;
205 * @brief RF5_BRAIN_SMASHの処理。脳攻撃。 /
206 * @param player_ptr プレイヤーへの参照ポインタ
209 * @param m_idx 呪文を唱えるモンスターID
210 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
211 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
215 MonsterSpellResult spell_RF5_BRAIN_SMASH(PlayerType *player_ptr, POSITION y, POSITION x, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
217 auto *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
218 bool seen = (!player_ptr->effects()->blindness()->is_blind() && m_ptr->ml);
219 const auto m_name = monster_name(player_ptr, m_idx);
220 const auto t_name = monster_name(player_ptr, t_idx);
222 if (target_type == MONSTER_TO_PLAYER) {
223 disturb(player_ptr, true, true);
225 msg_print(_("何かがあなたの精神に念を放っているようだ。", "You feel something focusing on your mind."));
227 msg_format(_("%s^があなたの瞳をじっとにらんでいる。", "%s^ gazes deep into your eyes."), m_name.data());
229 } else if (target_type == MONSTER_TO_MONSTER && see_monster(player_ptr, m_idx)) {
230 msg_format(_("%s^は%sをじっと睨んだ。", "%s^ gazes intently at %s."), m_name.data(), t_name.data());
233 const auto dam = monspell_damage(player_ptr, MonsterAbilityType::BRAIN_SMASH, m_idx, DAM_ROLL);
234 const auto proj_res = pointed(player_ptr, y, x, m_idx, AttributeType::BRAIN_SMASH, dam, target_type);
236 auto res = MonsterSpellResult::make_valid(dam);
237 res.learnable = proj_res.affected_player;
243 * @brief RF5_SCAREの処理。恐怖。 /
244 * @param m_idx 呪文を唱えるモンスターID
245 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
246 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
250 MonsterSpellResult spell_RF5_SCARE(MONSTER_IDX m_idx, PlayerType *player_ptr, MONSTER_IDX t_idx, int target_type)
252 auto res = MonsterSpellResult::make_valid();
253 res.learnable = target_type == MONSTER_TO_PLAYER;
255 auto *floor_ptr = player_ptr->current_floor_ptr;
256 MonsterEntity *t_ptr = &floor_ptr->m_list[t_idx];
257 MonsterRaceInfo *tr_ptr = &t_ptr->get_monrace();
258 DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
259 bool resist, saving_throw;
261 if (target_type == MONSTER_TO_PLAYER) {
262 resist = (has_resist_fear(player_ptr) != 0);
263 saving_throw = (randint0(100 + rlev / 2) < player_ptr->skill_sav);
265 mspell_cast_msg_bad_status_to_player msg(_("%s^が何かをつぶやくと、恐ろしげな音が聞こえた。", "%s^ mumbles, and you hear scary noises."),
266 _("%s^が恐ろしげな幻覚を作り出した。", "%s^ casts a fearful illusion."), _("しかし恐怖に侵されなかった。", "You refuse to be frightened."),
267 _("しかし恐怖に侵されなかった。", "You refuse to be frightened."));
269 spell_badstatus_message_to_player(player_ptr, m_idx, msg, resist, saving_throw);
271 if (!resist && !saving_throw) {
272 (void)BadStatusSetter(player_ptr).mod_fear(randint0(4) + 4);
275 update_smart_learn(player_ptr, m_idx, DRS_FEAR);
279 if (target_type != MONSTER_TO_MONSTER) {
283 resist = ((tr_ptr->flags3 & RF3_NO_FEAR) != 0);
284 saving_throw = (tr_ptr->level > randint1((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10);
286 mspell_cast_msg_bad_status_to_monster msg(_("%s^が恐ろしげな幻覚を作り出した。", "%s^ casts a fearful illusion in front of %s."),
287 _("%s^は恐怖を感じない。", "%s^ refuses to be frightened."), _("%s^は恐怖を感じない。", "%s^ refuses to be frightened."),
288 _("%s^は恐怖して逃げ出した!", "%s^ flees in terror!"));
290 spell_badstatus_message_to_mons(player_ptr, m_idx, t_idx, msg, resist, saving_throw);
292 if (!resist && !saving_throw) {
293 set_monster_monfear(player_ptr, t_idx, t_ptr->get_remaining_fear() + randint0(4) + 4);
300 * @brief RF5_BLINDの処理。盲目。 /
301 * @param m_idx 呪文を唱えるモンスターID
302 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
303 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
307 MonsterSpellResult spell_RF5_BLIND(MONSTER_IDX m_idx, PlayerType *player_ptr, MONSTER_IDX t_idx, int target_type)
309 auto res = MonsterSpellResult::make_valid();
310 res.learnable = target_type == MONSTER_TO_PLAYER;
312 auto *floor_ptr = player_ptr->current_floor_ptr;
313 MonsterEntity *t_ptr = &floor_ptr->m_list[t_idx];
314 MonsterRaceInfo *tr_ptr = &t_ptr->get_monrace();
315 DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
316 bool resist, saving_throw;
318 if (target_type == MONSTER_TO_PLAYER) {
319 resist = (has_resist_blind(player_ptr) != 0);
320 saving_throw = (randint0(100 + rlev / 2) < player_ptr->skill_sav);
322 mspell_cast_msg_bad_status_to_player msg(_("%s^が何かをつぶやいた。", "%s^ mumbles."),
323 _("%s^が呪文を唱えてあなたの目をくらました!", "%s^ casts a spell, burning your eyes!"), _("しかし効果がなかった!", "You are unaffected!"),
324 _("しかし効力を跳ね返した!", "You resist the effects!"));
326 spell_badstatus_message_to_player(player_ptr, m_idx, msg, resist, saving_throw);
328 if (!resist && !saving_throw) {
329 (void)BadStatusSetter(player_ptr).set_blindness(12 + randint0(4));
332 update_smart_learn(player_ptr, m_idx, DRS_BLIND);
336 if (target_type != MONSTER_TO_MONSTER) {
341 const auto t_name = monster_name(player_ptr, t_idx);
343 if (streq(t_name.data(), "it")) {
344 msg_default = _("%sは呪文を唱えて%sの目を焼き付かせた。", "%s^ casts a spell, burning %ss eyes.");
346 msg_default = _("%sは呪文を唱えて%sの目を焼き付かせた。", "%s^ casts a spell, burning %s's eyes.");
349 resist = ((tr_ptr->flags3 & RF3_NO_CONF) != 0);
350 saving_throw = (tr_ptr->level > randint1((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10);
352 mspell_cast_msg_bad_status_to_monster msg(msg_default, _("%s^には効果がなかった。", "%s^ is unaffected."),
353 _("%s^には効果がなかった。", "%s^ is unaffected."), _("%s^は目が見えなくなった! ", "%s^ is blinded!"));
355 spell_badstatus_message_to_mons(player_ptr, m_idx, t_idx, msg, resist, saving_throw);
357 if (!resist && !saving_throw) {
358 (void)set_monster_confused(player_ptr, t_idx, t_ptr->get_remaining_confusion() + 12 + randint0(4));
365 * @brief RF5_CONFの処理。混乱。/
366 * @param m_idx 呪文を唱えるモンスターID
367 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
368 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
372 MonsterSpellResult spell_RF5_CONF(MONSTER_IDX m_idx, PlayerType *player_ptr, MONSTER_IDX t_idx, int target_type)
374 auto res = MonsterSpellResult::make_valid();
375 res.learnable = target_type == MONSTER_TO_PLAYER;
377 auto *floor_ptr = player_ptr->current_floor_ptr;
378 MonsterEntity *t_ptr = &floor_ptr->m_list[t_idx];
379 MonsterRaceInfo *tr_ptr = &t_ptr->get_monrace();
380 DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
381 bool resist, saving_throw;
383 if (target_type == MONSTER_TO_PLAYER) {
384 resist = (has_resist_conf(player_ptr) != 0);
385 saving_throw = (randint0(100 + rlev / 2) < player_ptr->skill_sav);
387 mspell_cast_msg_bad_status_to_player msg(_("%s^が何かをつぶやくと、頭を悩ます音がした。", "%s^ mumbles, and you hear puzzling noises."),
388 _("%s^が誘惑的な幻覚を作り出した。", "%s^ creates a mesmerising illusion."),
389 _("しかし幻覚にはだまされなかった。", "You disbelieve the feeble spell."),
390 _("しかし幻覚にはだまされなかった。", "You disbelieve the feeble spell."));
392 spell_badstatus_message_to_player(player_ptr, m_idx, msg, resist, saving_throw);
394 if (!resist && !saving_throw) {
395 (void)BadStatusSetter(player_ptr).mod_confusion(randint0(4) + 4);
398 update_smart_learn(player_ptr, m_idx, DRS_CONF);
402 if (target_type != MONSTER_TO_MONSTER) {
406 resist = ((tr_ptr->flags3 & RF3_NO_CONF) != 0);
407 saving_throw = (tr_ptr->level > randint1((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10);
409 mspell_cast_msg_bad_status_to_monster msg(_("%s^が%sの前に幻惑的な幻をつくり出した。", "%s^ casts a mesmerizing illusion in front of %s."),
410 _("%s^は惑わされなかった。", "%s^ disbelieves the feeble spell."), _("%s^は惑わされなかった。", "%s^ disbelieves the feeble spell."),
411 _("%s^は混乱したようだ。", "%s^ seems confused."));
413 spell_badstatus_message_to_mons(player_ptr, m_idx, t_idx, msg, resist, saving_throw);
415 if (!resist && !saving_throw) {
416 (void)set_monster_confused(player_ptr, t_idx, t_ptr->get_remaining_confusion() + 12 + randint0(4));
423 * @brief RF5_HOLDの処理。麻痺。 /
424 * @param m_idx 呪文を唱えるモンスターID
425 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
426 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
430 MonsterSpellResult spell_RF5_HOLD(MONSTER_IDX m_idx, PlayerType *player_ptr, MONSTER_IDX t_idx, int target_type)
432 auto res = MonsterSpellResult::make_valid();
433 res.learnable = target_type == MONSTER_TO_PLAYER;
435 auto *floor_ptr = player_ptr->current_floor_ptr;
436 MonsterEntity *t_ptr = &floor_ptr->m_list[t_idx];
437 MonsterRaceInfo *tr_ptr = &t_ptr->get_monrace();
438 DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
439 bool resist, saving_throw;
441 if (target_type == MONSTER_TO_PLAYER) {
442 resist = (player_ptr->free_act != 0);
443 saving_throw = (randint0(100 + rlev / 2) < player_ptr->skill_sav);
445 mspell_cast_msg_bad_status_to_player msg(_("%s^が何かをつぶやいた。", "%s^ mumbles."),
446 _("%s^があなたの目をじっと見つめた!", "%s^ stares deep into your eyes!"), _("しかし効果がなかった!", "You are unaffected!"),
447 _("しかし効力を跳ね返した!", "You resist the effects!"));
449 spell_badstatus_message_to_player(player_ptr, m_idx, msg, (bool)resist, saving_throw);
451 if (!resist && !saving_throw) {
452 (void)BadStatusSetter(player_ptr).mod_paralysis(randint0(4) + 4);
455 update_smart_learn(player_ptr, m_idx, DRS_FREE);
459 if (target_type != MONSTER_TO_MONSTER) {
463 resist = (tr_ptr->kind_flags.has(MonsterKindType::UNIQUE) || (tr_ptr->flags3 & RF3_NO_STUN) != 0);
464 saving_throw = (tr_ptr->level > randint1((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10);
466 mspell_cast_msg_bad_status_to_monster msg(_("%s^は%sをじっと見つめた。", "%s^ stares intently at %s."),
467 _("%s^には効果がなかった。", "%s^ is unaffected."), _("%s^には効果がなかった。", "%s^ is unaffected."), _("%s^は麻痺した!", "%s^ is paralyzed!"));
469 spell_badstatus_message_to_mons(player_ptr, m_idx, t_idx, msg, (bool)resist, saving_throw);
471 if (!resist && !saving_throw) {
472 (void)set_monster_stunned(player_ptr, t_idx, t_ptr->get_remaining_stun() + randint1(4) + 4);
479 * @brief RF6_HASTEの処理。加速。 /
480 * @param player_ptr プレイヤーへの参照ポインタ
481 * @param m_idx 呪文を唱えるモンスターID
482 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
483 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
487 MonsterSpellResult spell_RF6_HASTE(PlayerType *player_ptr, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
489 bool see_m = see_monster(player_ptr, m_idx);
490 auto *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
491 const auto m_name = monster_name(player_ptr, m_idx);
492 const auto m_poss = monster_desc(player_ptr, m_ptr, MD_PRON_VISIBLE | MD_POSSESSIVE);
494 mspell_cast_msg msg(_("%s^が何かをつぶやいた。", "%s^ mumbles."),
495 _("%s^が自分の体に念を送った。", format("%%s^ concentrates on %s body.", m_poss.data())),
496 _("%s^が自分の体に念を送った。", format("%%s^ concentrates on %s body.", m_poss.data())),
497 _("%s^が自分の体に念を送った。", format("%%s^ concentrates on %s body.", m_poss.data())));
499 monspell_message_base(player_ptr, m_idx, t_idx, msg, player_ptr->effects()->blindness()->is_blind(), target_type);
501 if (set_monster_fast(player_ptr, m_idx, m_ptr->get_remaining_acceleration() + 100)) {
502 if (target_type == MONSTER_TO_PLAYER || (target_type == MONSTER_TO_MONSTER && see_m)) {
503 msg_format(_("%s^の動きが速くなった。", "%s^ starts moving faster."), m_name.data());
507 return MonsterSpellResult::make_valid();
511 * @brief RF5_SLOWの処理。減速。 /
512 * @param m_idx 呪文を唱えるモンスターID
513 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
514 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
518 MonsterSpellResult spell_RF5_SLOW(MONSTER_IDX m_idx, PlayerType *player_ptr, MONSTER_IDX t_idx, int target_type)
520 auto res = MonsterSpellResult::make_valid();
521 res.learnable = target_type == MONSTER_TO_PLAYER;
523 auto *floor_ptr = player_ptr->current_floor_ptr;
524 MonsterEntity *t_ptr = &floor_ptr->m_list[t_idx];
525 MonsterRaceInfo *tr_ptr = &t_ptr->get_monrace();
526 DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
527 bool resist, saving_throw;
529 if (target_type == MONSTER_TO_PLAYER) {
530 resist = (has_resist_conf(player_ptr) != 0);
531 saving_throw = (randint0(100 + rlev / 2) < player_ptr->skill_sav);
533 mspell_cast_msg_bad_status_to_player msg(_("%s^があなたの筋力を吸い取ろうとした!", "%s^ drains power from your muscles!"),
534 _("%s^があなたの筋力を吸い取ろうとした!", "%s^ drains power from your muscles!"), _("しかし効果がなかった!", "You are unaffected!"),
535 _("しかし効力を跳ね返した!", "You resist the effects!"));
537 spell_badstatus_message_to_player(player_ptr, m_idx, msg, resist, saving_throw);
539 if (!resist && !saving_throw) {
540 (void)BadStatusSetter(player_ptr).mod_deceleration(randint0(4) + 4, false);
543 update_smart_learn(player_ptr, m_idx, DRS_FREE);
547 if (target_type != MONSTER_TO_MONSTER) {
552 const auto t_name = monster_name(player_ptr, t_idx);
554 if (streq(t_name.data(), "it")) {
555 msg_default = _("%sが%sの筋肉から力を吸いとった。", "%s^ drains power from %ss muscles.");
557 msg_default = _("%sが%sの筋肉から力を吸いとった。", "%s^ drains power from %s's muscles.");
560 resist = (tr_ptr->kind_flags.has(MonsterKindType::UNIQUE));
561 saving_throw = (tr_ptr->level > randint1((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10);
563 mspell_cast_msg_bad_status_to_monster msg(msg_default, _("%s^には効果がなかった。", "%s^ is unaffected."),
564 _("%s^には効果がなかった。", "%s^ is unaffected."), _("%sの動きが遅くなった。", "%s^ starts moving slower."));
566 spell_badstatus_message_to_mons(player_ptr, m_idx, t_idx, msg, resist, saving_throw);
568 if (!resist && !saving_throw) {
569 set_monster_slow(player_ptr, t_idx, t_ptr->get_remaining_deceleration() + 50);
576 * @brief RF6_HEALの処理。治癒。 /
577 * @param player_ptr プレイヤーへの参照ポインタ
578 * @param m_idx 呪文を唱えるモンスターID
579 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
580 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
584 MonsterSpellResult spell_RF6_HEAL(PlayerType *player_ptr, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
586 const auto res = MonsterSpellResult::make_valid();
589 auto *floor_ptr = player_ptr->current_floor_ptr;
590 auto *m_ptr = &floor_ptr->m_list[m_idx];
591 DEPTH rlev = monster_level_idx(floor_ptr, m_idx);
592 const auto is_blind = player_ptr->effects()->blindness()->is_blind();
593 const auto seen = (!is_blind && m_ptr->ml);
594 const auto m_poss = monster_desc(player_ptr, m_ptr, MD_PRON_VISIBLE | MD_POSSESSIVE);
596 msg.to_player_true = _("%s^が何かをつぶやいた。", "%s^ mumbles.");
597 msg.to_mons_true = _("%s^は自分の傷に念を集中した。", format("%%s^ concentrates on %s wounds.", m_poss.data()));
598 msg.to_player_false = _("%s^が自分の傷に集中した。", format("%%s^ concentrates on %s wounds.", m_poss.data()));
599 msg.to_mons_false = _("%s^は自分の傷に念を集中した。", format("%%s^ concentrates on %s wounds.", m_poss.data()));
601 monspell_message_base(player_ptr, m_idx, t_idx, msg, is_blind, target_type);
603 m_ptr->hp += (rlev * 6);
604 if (m_ptr->hp >= m_ptr->maxhp) {
606 m_ptr->hp = m_ptr->maxhp;
608 msg.to_player_true = _("%s^は完全に治ったようだ!", "%s^ sounds completely healed!");
609 msg.to_mons_true = _("%s^は完全に治ったようだ!", "%s^ sounds completely healed!");
610 msg.to_player_false = _("%s^は完全に治った!", "%s^ looks completely healed!");
611 msg.to_mons_false = _("%s^は完全に治った!", "%s^ looks completely healed!");
613 msg.to_player_true = _("%s^は体力を回復したようだ。", "%s^ sounds healthier.");
614 msg.to_mons_true = _("%s^は体力を回復したようだ。", "%s^ sounds healthier.");
615 msg.to_player_false = _("%s^は体力を回復したようだ。", "%s^ looks healthier.");
616 msg.to_mons_false = _("%s^は体力を回復したようだ。", "%s^ looks healthier.");
619 monspell_message_base(player_ptr, m_idx, t_idx, msg, !seen, target_type);
620 auto &rfu = RedrawingFlagsUpdater::get_instance();
621 if (player_ptr->health_who == m_idx) {
622 rfu.set_flag(MainWindowRedrawingFlag::HEALTH);
625 if (player_ptr->riding == m_idx) {
626 rfu.set_flag(MainWindowRedrawingFlag::UHEALTH);
629 if (!m_ptr->is_fearful()) {
633 (void)set_monster_monfear(player_ptr, m_idx, 0);
635 if (see_monster(player_ptr, m_idx)) {
636 const auto m_name = monster_name(player_ptr, m_idx);
637 msg_print(_(format("%s^は勇気を取り戻した。", m_name.data()), format("%s^ recovers %s courage.", m_name.data(), m_poss.data())));
644 * @brief RF6_INVULNERの処理。無敵。 /
645 * @param player_ptr プレイヤーへの参照ポインタ
646 * @param m_idx 呪文を唱えるモンスターID
647 * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
648 * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
652 MonsterSpellResult spell_RF6_INVULNER(PlayerType *player_ptr, MONSTER_IDX m_idx, MONSTER_IDX t_idx, int target_type)
654 auto *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
655 bool seen = (!player_ptr->effects()->blindness()->is_blind() && m_ptr->ml);
656 mspell_cast_msg msg(_("%s^が何かを力強くつぶやいた。", "%s^ mumbles powerfully."),
657 _("%s^が何かを力強くつぶやいた。", "%s^ mumbles powerfully."), _("%sは無傷の球の呪文を唱えた。", "%s^ casts a Globe of Invulnerability."),
658 _("%sは無傷の球の呪文を唱えた。", "%s^ casts a Globe of Invulnerability."));
660 monspell_message_base(player_ptr, m_idx, t_idx, msg, !seen, target_type);
663 MonsterRaceId r_idx = m_ptr->r_idx;
664 const auto m_name = monster_desc(player_ptr, m_ptr, MD_NONE);
666 case MonsterRaceId::MARIO:
667 case MonsterRaceId::LUIGI:
668 msg_format(_("%sはスターを取った!", "%s^ got a star!"), m_name.data());
670 case MonsterRaceId::DIAVOLO:
671 msg_print(_("『読める』………動きの『軌跡』が読める……", "'Read'......... I can read the 'trajectory' of movement..."));
674 msg_format(_("%sの身体がまばゆく輝き始めた!", "The body of %s^ began to shine dazzlingly!"), m_name.data());
679 if (!m_ptr->is_invulnerable()) {
680 (void)set_monster_invulner(player_ptr, m_idx, randint1(4) + 4, false);
683 return MonsterSpellResult::make_valid();
687 * @brief RF6_FORGETの処理。記憶消去。 /
688 * @param player_ptr プレイヤーへの参照ポインタ
689 * @param m_idx 呪文を唱えるモンスターID
693 MonsterSpellResult spell_RF6_FORGET(PlayerType *player_ptr, MONSTER_IDX m_idx)
695 DEPTH rlev = monster_level_idx(player_ptr->current_floor_ptr, m_idx);
696 const auto m_name = monster_name(player_ptr, m_idx);
698 disturb(player_ptr, true, true);
700 msg_format(_("%s^があなたの記憶を消去しようとしている。", "%s^ tries to blank your mind."), m_name.data());
702 if (randint0(100 + rlev / 2) < player_ptr->skill_sav) {
703 msg_print(_("しかし効力を跳ね返した!", "You resist the effects!"));
704 } else if (lose_all_info(player_ptr)) {
705 msg_print(_("記憶が薄れてしまった。", "Your memories fade away."));
708 auto res = MonsterSpellResult::make_valid();
709 res.learnable = true;