OSDN Git Service

[Refactor] #1473 Reshaped realm-hex.cpp partially
[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/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 "util/bit-flags-calculator.h"
19 #include "view/display-messages.h"
20
21 /*!
22  * @brief プレイヤーの歌に関する継続処理
23  */
24 void check_music(player_type *player_ptr)
25 {
26     if (player_ptr->pclass != CLASS_BARD)
27         return;
28
29     auto interupting_song_effect = get_interrupting_song_effect(player_ptr);
30     if ((get_singing_song_effect(player_ptr) == 0) && (interupting_song_effect == 0))
31         return;
32
33     if (player_ptr->anti_magic) {
34         stop_singing(player_ptr);
35         return;
36     }
37
38     int spell = get_singing_song_id(player_ptr);
39     const magic_type *s_ptr;
40     s_ptr = &technic_info[REALM_MUSIC - MIN_TECHNIC][spell];
41
42     MANA_POINT need_mana = mod_need_mana(player_ptr, s_ptr->smana, spell, REALM_MUSIC);
43     uint32_t need_mana_frac = 0;
44
45     s64b_rshift(&need_mana, &need_mana_frac, 1);
46     if (s64b_cmp(player_ptr->csp, player_ptr->csp_frac, need_mana, need_mana_frac) < 0) {
47         stop_singing(player_ptr);
48         return;
49     } else {
50         s64b_sub(&(player_ptr->csp), &(player_ptr->csp_frac), need_mana, need_mana_frac);
51
52         player_ptr->redraw |= PR_MANA;
53         if (interupting_song_effect != 0) {
54             set_singing_song_effect(player_ptr, interupting_song_effect);
55             set_interrupting_song_effect(player_ptr, MUSIC_NONE);
56             msg_print(_("歌を再開した。", "You resume singing."));
57             player_ptr->action = ACTION_SING;
58             player_ptr->update |= (PU_BONUS | PU_HP | PU_MONSTERS);
59             player_ptr->redraw |= (PR_MAP | PR_STATUS | PR_STATE);
60             player_ptr->window_flags |= (PW_OVERHEAD | PW_DUNGEON);
61         }
62     }
63
64     if (player_ptr->spell_exp[spell] < SPELL_EXP_BEGINNER)
65         player_ptr->spell_exp[spell] += 5;
66     else if (player_ptr->spell_exp[spell] < SPELL_EXP_SKILLED) {
67         if (one_in_(2) && (player_ptr->current_floor_ptr->dun_level > 4) && ((player_ptr->current_floor_ptr->dun_level + 10) > player_ptr->lev))
68             player_ptr->spell_exp[spell] += 1;
69     } else if (player_ptr->spell_exp[spell] < SPELL_EXP_EXPERT) {
70         if (one_in_(5) && ((player_ptr->current_floor_ptr->dun_level + 5) > player_ptr->lev)
71             && ((player_ptr->current_floor_ptr->dun_level + 5) > s_ptr->slevel))
72             player_ptr->spell_exp[spell] += 1;
73     } else if (player_ptr->spell_exp[spell] < SPELL_EXP_MASTER) {
74         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))
75             player_ptr->spell_exp[spell] += 1;
76     }
77
78     exe_spell(player_ptr, REALM_MUSIC, spell, SPELL_CONTNUATION);
79 }
80
81 /*!
82  * @brief 隠遁の歌の継続時間をセットする / Set "tim_stealth", notice observable changes
83  * @param v 継続時間
84  * @param do_dec 現在の継続時間より長い値のみ上書きする
85  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
86  */
87 bool set_tim_stealth(player_type *player_ptr, TIME_EFFECT v, bool do_dec)
88 {
89     bool notice = false;
90     v = (v > 10000) ? 10000 : (v < 0) ? 0 : v;
91
92     if (player_ptr->is_dead)
93         return false;
94
95     if (v) {
96         if (player_ptr->tim_stealth && !do_dec) {
97             if (player_ptr->tim_stealth > v)
98                 return false;
99         } else if (!is_time_limit_stealth(player_ptr)) {
100             msg_print(_("足音が小さくなった!", "You begin to walk silently!"));
101             notice = true;
102         }
103     } else {
104         if (player_ptr->tim_stealth && !music_singing(player_ptr, MUSIC_STEALTH)) {
105             msg_print(_("足音が大きくなった。", "You no longer walk silently."));
106             notice = true;
107         }
108     }
109
110     player_ptr->tim_stealth = v;
111     player_ptr->redraw |= (PR_STATUS);
112
113     if (!notice)
114         return false;
115
116     if (disturb_state)
117         disturb(player_ptr, false, false);
118     player_ptr->update |= (PU_BONUS);
119     handle_stuff(player_ptr);
120     return true;
121 }
122
123 /*!
124  * @brief 歌の停止を処理する / Stop singing if the player is a Bard
125  */
126 void stop_singing(player_type *player_ptr)
127 {
128     if (player_ptr->pclass != CLASS_BARD)
129         return;
130
131     if (get_interrupting_song_effect(player_ptr) != 0) {
132         set_interrupting_song_effect(player_ptr, MUSIC_NONE);
133         return;
134     }
135
136     if (get_singing_song_effect(player_ptr) == 0)
137         return;
138
139     if (player_ptr->action == ACTION_SING)
140         set_action(player_ptr, ACTION_NONE);
141
142     (void)exe_spell(player_ptr, REALM_MUSIC, get_singing_song_id(player_ptr), SPELL_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(player_type *player_ptr, int music_songs)
150 {
151     return (player_ptr->pclass == CLASS_BARD) && (player_ptr->magic_num1[0] == music_songs);
152 }
153
154 bool music_singing_any(player_type *player_ptr)
155 {
156     return (player_ptr->pclass == CLASS_BARD) && (player_ptr->magic_num1[0] != 0);
157 }
158
159 int32_t get_singing_song_effect(const player_type *player_ptr)
160 {
161     return player_ptr->magic_num1[0];
162 }
163
164 void set_singing_song_effect(player_type *player_ptr, const int32_t magic_num)
165 {
166     player_ptr->magic_num1[0] = magic_num;
167 }
168
169 int32_t get_interrupting_song_effect(const player_type *player_ptr)
170 {
171     return player_ptr->magic_num1[1];
172 }
173
174 void set_interrupting_song_effect(player_type *player_ptr, const int32_t magic_num)
175 {
176     player_ptr->magic_num1[1] = magic_num;
177 }
178
179 int32_t get_singing_count(const player_type *player_ptr)
180 {
181     return player_ptr->magic_num1[2];
182 }
183
184 void set_singing_count(player_type *player_ptr, const int32_t magic_num)
185 {
186     player_ptr->magic_num1[2] = magic_num;
187 }
188
189 byte get_singing_song_id(const player_type *player_ptr)
190 {
191     return player_ptr->magic_num2[0];
192 }
193
194 void set_singing_song_id(player_type *player_ptr, const byte magic_num)
195 {
196     player_ptr->magic_num2[0] = magic_num;
197 }