OSDN Git Service

Merge pull request #3569 from sikabane-works/release/3.0.0.88-alpha
[hengbandforosx/hengbandosx.git] / src / mspell / mspell-dispel.cpp
1 #include "mspell/mspell-dispel.h"
2 #include "blue-magic/blue-magic-checker.h"
3 #include "core/speed-table.h"
4 #include "core/window-redrawer.h"
5 #include "mind/mind-force-trainer.h"
6 #include "mind/mind-magic-resistance.h"
7 #include "mind/mind-mirror-master.h"
8 #include "monster/monster-info.h"
9 #include "monster/monster-status-setter.h"
10 #include "monster/monster-status.h"
11 #include "mspell/mspell-result.h"
12 #include "mspell/mspell-util.h"
13 #include "player-info/race-info.h"
14 #include "player/attack-defense-types.h"
15 #include "player/player-status.h"
16 #include "realm/realm-song-numbers.h"
17 #include "spell-realm/spells-craft.h"
18 #include "spell-realm/spells-crusade.h"
19 #include "spell-realm/spells-demon.h"
20 #include "spell-realm/spells-hex.h"
21 #include "spell-realm/spells-song.h"
22 #include "status/bad-status-setter.h"
23 #include "status/body-improvement.h"
24 #include "status/buff-setter.h"
25 #include "status/element-resistance.h"
26 #include "status/shape-changer.h"
27 #include "status/sight-setter.h"
28 #include "status/temporary-resistance.h"
29 #include "system/player-type-definition.h"
30 #include "system/redrawing-flags-updater.h"
31 #include "view/display-messages.h"
32
33 /*!
34  * @brief プレイヤーに魔力消去効果を与える。
35  */
36 static void dispel_player(PlayerType *player_ptr)
37 {
38     (void)set_acceleration(player_ptr, 0, true);
39     set_lightspeed(player_ptr, 0, true);
40     (void)BadStatusSetter(player_ptr).set_deceleration(0, true);
41     (void)set_shield(player_ptr, 0, true);
42     (void)set_blessed(player_ptr, 0, true);
43     (void)set_tsuyoshi(player_ptr, 0, true);
44     (void)set_hero(player_ptr, 0, true);
45     (void)set_shero(player_ptr, 0, true);
46     (void)set_protevil(player_ptr, 0, true);
47     (void)set_invuln(player_ptr, 0, true);
48     (void)set_wraith_form(player_ptr, 0, true);
49     (void)set_pass_wall(player_ptr, 0, true);
50     (void)set_tim_res_nether(player_ptr, 0, true);
51     (void)set_tim_res_time(player_ptr, 0, true);
52     (void)set_tim_reflect(player_ptr, 0, true);
53     (void)set_multishadow(player_ptr, 0, true);
54     (void)set_dustrobe(player_ptr, 0, true);
55
56     (void)set_tim_invis(player_ptr, 0, true);
57     (void)set_tim_infra(player_ptr, 0, true);
58     (void)set_tim_esp(player_ptr, 0, true);
59     (void)set_tim_regen(player_ptr, 0, true);
60     (void)set_tim_stealth(player_ptr, 0, true);
61     (void)set_tim_levitation(player_ptr, 0, true);
62     (void)set_tim_sh_force(player_ptr, 0, true);
63     (void)set_tim_sh_fire(player_ptr, 0, true);
64     (void)set_tim_sh_holy(player_ptr, 0, true);
65     (void)set_tim_eyeeye(player_ptr, 0, true);
66     (void)set_magicdef(player_ptr, 0, true);
67     (void)set_resist_magic(player_ptr, 0, true);
68     (void)set_oppose_acid(player_ptr, 0, true);
69     (void)set_oppose_elec(player_ptr, 0, true);
70     (void)set_oppose_fire(player_ptr, 0, true);
71     (void)set_oppose_cold(player_ptr, 0, true);
72     (void)set_oppose_pois(player_ptr, 0, true);
73     (void)set_ultimate_res(player_ptr, 0, true);
74     (void)set_mimic(player_ptr, 0, MimicKindType::NONE, true);
75     (void)set_ele_attack(player_ptr, 0, 0);
76     (void)set_ele_immune(player_ptr, 0, 0);
77
78     if (player_ptr->special_attack & ATTACK_CONFUSE) {
79         player_ptr->special_attack &= ~(ATTACK_CONFUSE);
80         msg_print(_("手の輝きがなくなった。", "Your hands stop glowing."));
81     }
82
83     auto song_interruption = music_singing_any(player_ptr);
84     auto spellhex_interruption = SpellHex(player_ptr).is_spelling_any();
85
86     if (song_interruption || spellhex_interruption) {
87         if (song_interruption) {
88             set_interrupting_song_effect(player_ptr, get_singing_song_effect(player_ptr));
89             set_singing_song_effect(player_ptr, MUSIC_NONE);
90             msg_print(_("歌が途切れた。", "Your singing is interrupted."));
91         }
92         if (spellhex_interruption) {
93             SpellHex(player_ptr).interrupt_spelling();
94             msg_print(_("呪文が途切れた。", "Your casting is interrupted."));
95         }
96
97         player_ptr->action = ACTION_NONE;
98         auto &rfu = RedrawingFlagsUpdater::get_instance();
99         static constexpr auto flags_srf = {
100             StatusRecalculatingFlag::BONUS,
101             StatusRecalculatingFlag::HP,
102             StatusRecalculatingFlag::MONSTER_STATUSES,
103         };
104         rfu.set_flags(flags_srf);
105         static constexpr auto flags_mwrf = {
106             MainWindowRedrawingFlag::MAP,
107             MainWindowRedrawingFlag::TIMED_EFFECT,
108             MainWindowRedrawingFlag::ACTION,
109         };
110         rfu.set_flags(flags_mwrf);
111         static constexpr auto flags_swrf = {
112             SubWindowRedrawingFlag::OVERHEAD,
113             SubWindowRedrawingFlag::DUNGEON,
114         };
115         rfu.set_flags(flags_swrf);
116         player_ptr->energy_need += ENERGY_NEED();
117     }
118 }
119
120 /*!
121  * @brief RF4_DISPELの処理。魔力消去。 /
122  * @param m_idx 呪文を唱えるモンスターID
123  * @param player_ptr プレイヤーへの参照ポインタ
124  * @param t_idx 呪文を受けるモンスターID。プレイヤーの場合はdummyで0とする。
125  * @param target_type プレイヤーを対象とする場合MONSTER_TO_PLAYER、モンスターを対象とする場合MONSTER_TO_MONSTER
126  *
127  * プレイヤーが対象ならラーニング可。
128  */
129 MonsterSpellResult spell_RF4_DISPEL(MONSTER_IDX m_idx, PlayerType *player_ptr, MONSTER_IDX t_idx, int target_type)
130 {
131     auto res = MonsterSpellResult::make_valid();
132     res.learnable = target_type == MONSTER_TO_PLAYER;
133
134     mspell_cast_msg_blind msg(_("%s^が何かを力強くつぶやいた。", "%s^ mumbles powerfully."),
135         _("%s^が魔力消去の呪文を念じた。", "%s^ invokes a dispel magic."), _("%s^が%sに対して魔力消去の呪文を念じた。", "%s^ invokes a dispel magic at %s."));
136
137     monspell_message(player_ptr, m_idx, t_idx, msg, target_type);
138
139     if (target_type == MONSTER_TO_PLAYER) {
140         dispel_player(player_ptr);
141         if (player_ptr->riding) {
142             dispel_monster_status(player_ptr, player_ptr->riding);
143         }
144
145         if (is_echizen(player_ptr)) {
146             msg_print(_("やりやがったな!", ""));
147         } else if (is_chargeman(player_ptr)) {
148             if (randint0(2) == 0) {
149                 msg_print(_("ジュラル星人め!", ""));
150             } else {
151                 msg_print(_("弱い者いじめは止めるんだ!", ""));
152             }
153         }
154
155         return res;
156     }
157
158     if (target_type == MONSTER_TO_MONSTER) {
159         if (t_idx == player_ptr->riding) {
160             dispel_player(player_ptr);
161         }
162
163         dispel_monster_status(player_ptr, t_idx);
164     }
165
166     return res;
167 }