OSDN Git Service

[Refactor] #3359 'const auto flags_mwrf = {' を'static constexpr auto flags_mwrf ...
[hengbandforosx/hengbandosx.git] / src / spell-realm / spells-song.cpp
1 #include "spell-realm/spells-song.h"
2 #include "core/disturbance.h"
3 #include "core/stuff-handler.h"
4 #include "core/window-redrawer.h"
5 #include "game-option/disturbance-options.h"
6 #include "player-base/player-class.h"
7 #include "player-info/bard-data-type.h"
8 #include "player/attack-defense-types.h"
9 #include "player/player-skill.h"
10 #include "player/player-status.h"
11 #include "realm/realm-song-numbers.h"
12 #include "spell/spell-info.h"
13 #include "spell/spells-execution.h"
14 #include "spell/technic-info-table.h"
15 #include "status/action-setter.h"
16 #include "system/floor-type-definition.h"
17 #include "system/player-type-definition.h"
18 #include "system/redrawing-flags-updater.h"
19 #include "util/bit-flags-calculator.h"
20 #include "view/display-messages.h"
21
22 /*!
23  * @brief プレイヤーの歌に関する継続処理
24  */
25 void check_music(PlayerType *player_ptr)
26 {
27     if (!PlayerClass(player_ptr).equals(PlayerClassType::BARD)) {
28         return;
29     }
30
31     auto interupting_song_effect = get_interrupting_song_effect(player_ptr);
32     if ((get_singing_song_effect(player_ptr) == 0) && (interupting_song_effect == 0)) {
33         return;
34     }
35
36     if (player_ptr->anti_magic) {
37         stop_singing(player_ptr);
38         return;
39     }
40
41     int spell = get_singing_song_id(player_ptr);
42     const magic_type *s_ptr;
43     s_ptr = &technic_info[REALM_MUSIC - MIN_TECHNIC][spell];
44
45     MANA_POINT need_mana = mod_need_mana(player_ptr, s_ptr->smana, spell, REALM_MUSIC);
46     uint32_t need_mana_frac = 0;
47
48     s64b_rshift(&need_mana, &need_mana_frac, 1);
49     if (s64b_cmp(player_ptr->csp, player_ptr->csp_frac, need_mana, need_mana_frac) < 0) {
50         stop_singing(player_ptr);
51         return;
52     }
53
54     s64b_sub(&(player_ptr->csp), &(player_ptr->csp_frac), need_mana, need_mana_frac);
55     auto &rfu = RedrawingFlagsUpdater::get_instance();
56     rfu.set_flag(MainWindowRedrawingFlag::MP);
57     if (interupting_song_effect != 0) {
58         set_singing_song_effect(player_ptr, interupting_song_effect);
59         set_interrupting_song_effect(player_ptr, MUSIC_NONE);
60         msg_print(_("歌を再開した。", "You resume singing."));
61         player_ptr->action = ACTION_SING;
62         static constexpr auto flags_srf = {
63             StatusRedrawingFlag::BONUS,
64             StatusRedrawingFlag::HP,
65             StatusRedrawingFlag::MONSTER_STATUSES,
66         };
67         rfu.set_flags(flags_srf);
68         static constexpr auto flags_mwrf = {
69             MainWindowRedrawingFlag::MAP,
70             MainWindowRedrawingFlag::TIMED_EFFECT,
71             MainWindowRedrawingFlag::ACTION,
72         };
73         rfu.set_flags(flags_mwrf);
74         const auto flags_swrf = {
75             SubWindowRedrawingFlag::OVERHEAD,
76             SubWindowRedrawingFlag::DUNGEON,
77         };
78         rfu.set_flags(flags_swrf);
79     }
80
81     PlayerSkill(player_ptr).gain_continuous_spell_skill_exp(REALM_MUSIC, spell);
82     exe_spell(player_ptr, REALM_MUSIC, spell, SpellProcessType::CONTNUATION);
83 }
84
85 /*!
86  * @brief 隠遁の歌の継続時間をセットする / Set "tim_stealth", notice observable changes
87  * @param v 継続時間
88  * @param do_dec 現在の継続時間より長い値のみ上書きする
89  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
90  */
91 bool set_tim_stealth(PlayerType *player_ptr, TIME_EFFECT v, bool do_dec)
92 {
93     bool notice = false;
94     v = (v > 10000) ? 10000 : (v < 0) ? 0
95                                       : v;
96
97     if (player_ptr->is_dead) {
98         return false;
99     }
100
101     if (v) {
102         if (player_ptr->tim_stealth && !do_dec) {
103             if (player_ptr->tim_stealth > v) {
104                 return false;
105             }
106         } else if (!is_time_limit_stealth(player_ptr)) {
107             msg_print(_("足音が小さくなった!", "You begin to walk silently!"));
108             notice = true;
109         }
110     } else {
111         if (player_ptr->tim_stealth && !music_singing(player_ptr, MUSIC_STEALTH)) {
112             msg_print(_("足音が大きくなった。", "You no longer walk silently."));
113             notice = true;
114         }
115     }
116
117     player_ptr->tim_stealth = v;
118     auto &rfu = RedrawingFlagsUpdater::get_instance();
119     rfu.set_flag(MainWindowRedrawingFlag::TIMED_EFFECT);
120     if (!notice) {
121         return false;
122     }
123
124     if (disturb_state) {
125         disturb(player_ptr, false, false);
126     }
127
128     rfu.set_flag(StatusRedrawingFlag::BONUS);
129     handle_stuff(player_ptr);
130     return true;
131 }
132
133 /*!
134  * @brief 歌の停止を処理する / Stop singing if the player is a Bard
135  */
136 void stop_singing(PlayerType *player_ptr)
137 {
138     if (!PlayerClass(player_ptr).equals(PlayerClassType::BARD)) {
139         return;
140     }
141
142     if (get_interrupting_song_effect(player_ptr) != 0) {
143         set_interrupting_song_effect(player_ptr, MUSIC_NONE);
144         return;
145     }
146
147     if (get_singing_song_effect(player_ptr) == 0) {
148         return;
149     }
150
151     if (player_ptr->action == ACTION_SING) {
152         set_action(player_ptr, ACTION_NONE);
153     }
154
155     (void)exe_spell(player_ptr, REALM_MUSIC, get_singing_song_id(player_ptr), SpellProcessType::STOP);
156     set_singing_song_effect(player_ptr, MUSIC_NONE);
157     set_singing_song_id(player_ptr, 0);
158     auto &rfu = RedrawingFlagsUpdater::get_instance();
159     rfu.set_flag(StatusRedrawingFlag::BONUS);
160     rfu.set_flag(MainWindowRedrawingFlag::TIMED_EFFECT);
161 }
162
163 bool music_singing(PlayerType *player_ptr, int music_songs)
164 {
165     auto bird_data = PlayerClass(player_ptr).get_specific_data<bard_data_type>();
166     return bird_data && (bird_data->singing_song == music_songs);
167 }
168
169 bool music_singing_any(PlayerType *player_ptr)
170 {
171     auto bird_data = PlayerClass(player_ptr).get_specific_data<bard_data_type>();
172     return bird_data && (bird_data->singing_song != MUSIC_NONE);
173 }
174
175 int32_t get_singing_song_effect(PlayerType *player_ptr)
176 {
177     auto bird_data = PlayerClass(player_ptr).get_specific_data<bard_data_type>();
178     if (!bird_data) {
179         return 0;
180     }
181
182     return bird_data->singing_song;
183 }
184
185 void set_singing_song_effect(PlayerType *player_ptr, const int32_t magic_num)
186 {
187     auto bird_data = PlayerClass(player_ptr).get_specific_data<bard_data_type>();
188     if (!bird_data) {
189         return;
190     }
191
192     bird_data->singing_song = i2enum<realm_song_type>(magic_num);
193 }
194
195 int32_t get_interrupting_song_effect(PlayerType *player_ptr)
196 {
197     auto bird_data = PlayerClass(player_ptr).get_specific_data<bard_data_type>();
198     if (!bird_data) {
199         return 0;
200     }
201
202     return bird_data->interrputing_song;
203 }
204
205 void set_interrupting_song_effect(PlayerType *player_ptr, const int32_t magic_num)
206 {
207     auto bird_data = PlayerClass(player_ptr).get_specific_data<bard_data_type>();
208     if (!bird_data) {
209         return;
210     }
211
212     bird_data->interrputing_song = i2enum<realm_song_type>(magic_num);
213 }
214
215 int32_t get_singing_count(PlayerType *player_ptr)
216 {
217     auto bird_data = PlayerClass(player_ptr).get_specific_data<bard_data_type>();
218     if (!bird_data) {
219         return 0;
220     }
221
222     return bird_data->singing_duration;
223 }
224
225 void set_singing_count(PlayerType *player_ptr, const int32_t magic_num)
226 {
227     auto bird_data = PlayerClass(player_ptr).get_specific_data<bard_data_type>();
228     if (!bird_data) {
229         return;
230     }
231
232     bird_data->singing_duration = magic_num;
233 }
234
235 byte get_singing_song_id(PlayerType *player_ptr)
236 {
237     auto bird_data = PlayerClass(player_ptr).get_specific_data<bard_data_type>();
238     if (!bird_data) {
239         return 0;
240     }
241
242     return bird_data->singing_song_spell_idx;
243 }
244
245 void set_singing_song_id(PlayerType *player_ptr, const byte magic_num)
246 {
247     auto bird_data = PlayerClass(player_ptr).get_specific_data<bard_data_type>();
248     if (!bird_data) {
249         return;
250     }
251
252     bird_data->singing_song_spell_idx = magic_num;
253 }