OSDN Git Service

[Refactor] #1752 PlayerClassTypeをenumからenum classへ変更した
[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(player_type *player_ptr)
27 {
28     if (player_ptr->pclass != PlayerClassType::BARD)
29         return;
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     if (player_ptr->anti_magic) {
36         stop_singing(player_ptr);
37         return;
38     }
39
40     int spell = get_singing_song_id(player_ptr);
41     const magic_type *s_ptr;
42     s_ptr = &technic_info[REALM_MUSIC - MIN_TECHNIC][spell];
43
44     MANA_POINT need_mana = mod_need_mana(player_ptr, s_ptr->smana, spell, REALM_MUSIC);
45     uint32_t need_mana_frac = 0;
46
47     s64b_rshift(&need_mana, &need_mana_frac, 1);
48     if (s64b_cmp(player_ptr->csp, player_ptr->csp_frac, need_mana, need_mana_frac) < 0) {
49         stop_singing(player_ptr);
50         return;
51     } else {
52         s64b_sub(&(player_ptr->csp), &(player_ptr->csp_frac), need_mana, need_mana_frac);
53
54         player_ptr->redraw |= PR_MANA;
55         if (interupting_song_effect != 0) {
56             set_singing_song_effect(player_ptr, interupting_song_effect);
57             set_interrupting_song_effect(player_ptr, MUSIC_NONE);
58             msg_print(_("歌を再開した。", "You resume singing."));
59             player_ptr->action = ACTION_SING;
60             player_ptr->update |= (PU_BONUS | PU_HP | PU_MONSTERS);
61             player_ptr->redraw |= (PR_MAP | PR_STATUS | PR_STATE);
62             player_ptr->window_flags |= (PW_OVERHEAD | PW_DUNGEON);
63         }
64     }
65
66     if (player_ptr->spell_exp[spell] < SPELL_EXP_BEGINNER)
67         player_ptr->spell_exp[spell] += 5;
68     else if (player_ptr->spell_exp[spell] < SPELL_EXP_SKILLED) {
69         if (one_in_(2) && (player_ptr->current_floor_ptr->dun_level > 4) && ((player_ptr->current_floor_ptr->dun_level + 10) > player_ptr->lev))
70             player_ptr->spell_exp[spell] += 1;
71     } else if (player_ptr->spell_exp[spell] < SPELL_EXP_EXPERT) {
72         if (one_in_(5) && ((player_ptr->current_floor_ptr->dun_level + 5) > player_ptr->lev)
73             && ((player_ptr->current_floor_ptr->dun_level + 5) > s_ptr->slevel))
74             player_ptr->spell_exp[spell] += 1;
75     } else if (player_ptr->spell_exp[spell] < SPELL_EXP_MASTER) {
76         if (one_in_(5) && ((player_ptr->current_floor_ptr->dun_level + 5) > player_ptr->lev) && (player_ptr->current_floor_ptr->dun_level > s_ptr->slevel))
77             player_ptr->spell_exp[spell] += 1;
78     }
79
80     exe_spell(player_ptr, REALM_MUSIC, spell, SPELL_CONTNUATION);
81 }
82
83 /*!
84  * @brief 隠遁の歌の継続時間をセットする / Set "tim_stealth", notice observable changes
85  * @param v 継続時間
86  * @param do_dec 現在の継続時間より長い値のみ上書きする
87  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
88  */
89 bool set_tim_stealth(player_type *player_ptr, TIME_EFFECT v, bool do_dec)
90 {
91     bool notice = false;
92     v = (v > 10000) ? 10000 : (v < 0) ? 0 : v;
93
94     if (player_ptr->is_dead)
95         return false;
96
97     if (v) {
98         if (player_ptr->tim_stealth && !do_dec) {
99             if (player_ptr->tim_stealth > v)
100                 return false;
101         } else if (!is_time_limit_stealth(player_ptr)) {
102             msg_print(_("足音が小さくなった!", "You begin to walk silently!"));
103             notice = true;
104         }
105     } else {
106         if (player_ptr->tim_stealth && !music_singing(player_ptr, MUSIC_STEALTH)) {
107             msg_print(_("足音が大きくなった。", "You no longer walk silently."));
108             notice = true;
109         }
110     }
111
112     player_ptr->tim_stealth = v;
113     player_ptr->redraw |= (PR_STATUS);
114
115     if (!notice)
116         return false;
117
118     if (disturb_state)
119         disturb(player_ptr, false, false);
120     player_ptr->update |= (PU_BONUS);
121     handle_stuff(player_ptr);
122     return true;
123 }
124
125 /*!
126  * @brief 歌の停止を処理する / Stop singing if the player is a Bard
127  */
128 void stop_singing(player_type *player_ptr)
129 {
130     if (player_ptr->pclass != PlayerClassType::BARD)
131         return;
132
133     if (get_interrupting_song_effect(player_ptr) != 0) {
134         set_interrupting_song_effect(player_ptr, MUSIC_NONE);
135         return;
136     }
137
138     if (get_singing_song_effect(player_ptr) == 0)
139         return;
140
141     if (player_ptr->action == ACTION_SING)
142         set_action(player_ptr, ACTION_NONE);
143
144     (void)exe_spell(player_ptr, REALM_MUSIC, get_singing_song_id(player_ptr), SPELL_STOP);
145     set_singing_song_effect(player_ptr, MUSIC_NONE);
146     set_singing_song_id(player_ptr, 0);
147     set_bits(player_ptr->update, PU_BONUS);
148     set_bits(player_ptr->redraw, PR_STATUS);
149 }
150
151 bool music_singing(player_type *player_ptr, int music_songs)
152 {
153     auto bird_data = PlayerClass(player_ptr).get_specific_data<bard_data_type>();
154     return bird_data && (bird_data->singing_song == music_songs);
155 }
156
157 bool music_singing_any(player_type *player_ptr)
158 {
159     auto bird_data = PlayerClass(player_ptr).get_specific_data<bard_data_type>();
160     return bird_data && (bird_data->singing_song != MUSIC_NONE);
161 }
162
163 int32_t get_singing_song_effect(player_type *player_ptr)
164 {
165     auto bird_data = PlayerClass(player_ptr).get_specific_data<bard_data_type>();
166     if (!bird_data) {
167         return 0;
168     }
169
170     return bird_data->singing_song;
171 }
172
173 void set_singing_song_effect(player_type *player_ptr, const int32_t magic_num)
174 {
175     auto bird_data = PlayerClass(player_ptr).get_specific_data<bard_data_type>();
176     if (!bird_data) {
177         return;
178     }
179
180     bird_data->singing_song = i2enum<realm_song_type>(magic_num);
181 }
182
183 int32_t get_interrupting_song_effect(player_type *player_ptr)
184 {
185     auto bird_data = PlayerClass(player_ptr).get_specific_data<bard_data_type>();
186     if (!bird_data) {
187         return 0;
188     }
189
190     return bird_data->interrputing_song;
191 }
192
193 void set_interrupting_song_effect(player_type *player_ptr, const int32_t magic_num)
194 {
195     auto bird_data = PlayerClass(player_ptr).get_specific_data<bard_data_type>();
196     if (!bird_data) {
197         return;
198     }
199
200     bird_data->interrputing_song = i2enum<realm_song_type>(magic_num);
201 }
202
203 int32_t get_singing_count(player_type *player_ptr)
204 {
205     auto bird_data = PlayerClass(player_ptr).get_specific_data<bard_data_type>();
206     if (!bird_data) {
207         return 0;
208     }
209
210     return bird_data->singing_duration;
211 }
212
213 void set_singing_count(player_type *player_ptr, const int32_t magic_num)
214 {
215     auto bird_data = PlayerClass(player_ptr).get_specific_data<bard_data_type>();
216     if (!bird_data) {
217         return;
218     }
219
220     bird_data->singing_duration = magic_num;
221 }
222
223 byte get_singing_song_id(player_type *player_ptr)
224 {
225     auto bird_data = PlayerClass(player_ptr).get_specific_data<bard_data_type>();
226     if (!bird_data) {
227         return 0;
228     }
229
230     return bird_data->singing_song_spell_idx;
231 }
232
233 void set_singing_song_id(player_type *player_ptr, const byte magic_num)
234 {
235     auto bird_data = PlayerClass(player_ptr).get_specific_data<bard_data_type>();
236     if (!bird_data) {
237         return;
238     }
239
240     bird_data->singing_song_spell_idx = magic_num;
241 }