OSDN Git Service

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