OSDN Git Service

455e10e8cf81dfda513384f81dbff76e9760ffd5
[hengbandforosx/hengbandosx.git] / src / status / body-improvement.cpp
1 #include "status/body-improvement.h"
2 #include "avatar/avatar.h"
3 #include "core/disturbance.h"
4 #include "core/player-redraw-types.h"
5 #include "core/speed-table.h"
6 #include "core/stuff-handler.h"
7 #include "core/window-redrawer.h"
8 #include "game-option/disturbance-options.h"
9 #include "player/player-status.h"
10 #include "realm/realm-song-numbers.h"
11 #include "spell-realm/spells-song.h"
12 #include "system/player-type-definition.h"
13 #include "system/redrawing-flags-updater.h"
14 #include "view/display-messages.h"
15
16 /*!
17  * @brief 対邪悪結界の継続時間をセットする / Set "protevil", notice observable changes
18  * @param v 継続時間
19  * @param do_dec 現在の継続時間より長い値のみ上書きする
20  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
21  */
22 bool set_protevil(PlayerType *player_ptr, TIME_EFFECT v, bool do_dec)
23 {
24     bool notice = false;
25     v = (v > 10000) ? 10000 : (v < 0) ? 0
26                                       : v;
27
28     if (player_ptr->is_dead) {
29         return false;
30     }
31
32     if (v) {
33         if (player_ptr->protevil && !do_dec) {
34             if (player_ptr->protevil > v) {
35                 return false;
36             }
37         } else if (!player_ptr->protevil) {
38             msg_print(_("邪悪なる存在から守られているような感じがする!", "You feel safe from evil!"));
39             notice = true;
40         }
41     } else {
42         if (player_ptr->protevil) {
43             msg_print(_("邪悪なる存在から守られている感じがなくなった。", "You no longer feel safe from evil."));
44             notice = true;
45         }
46     }
47
48     player_ptr->protevil = v;
49     RedrawingFlagsUpdater::get_instance().set_flag(MainWindowRedrawingFlag::TIMED_EFFECT);
50
51     if (!notice) {
52         return false;
53     }
54
55     if (disturb_state) {
56         disturb(player_ptr, false, false);
57     }
58
59     handle_stuff(player_ptr);
60     return true;
61 }
62
63 /*!
64  * @brief 無傷球の継続時間をセットする / Set "invuln", notice observable changes
65  * @param v 継続時間
66  * @param do_dec 現在の継続時間より長い値のみ上書きする
67  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
68  */
69 bool set_invuln(PlayerType *player_ptr, TIME_EFFECT v, bool do_dec)
70 {
71     bool notice = false;
72     v = (v > 10000) ? 10000 : (v < 0) ? 0
73                                       : v;
74
75     if (player_ptr->is_dead) {
76         return false;
77     }
78
79     auto &rfu = RedrawingFlagsUpdater::get_instance();
80     if (v) {
81         if (player_ptr->invuln && !do_dec) {
82             if (player_ptr->invuln > v) {
83                 return false;
84             }
85         } else if (!is_invuln(player_ptr)) {
86             msg_print(_("無敵だ!", "Invulnerability!"));
87             notice = true;
88             chg_virtue(player_ptr, Virtue::UNLIFE, -2);
89             chg_virtue(player_ptr, Virtue::HONOUR, -2);
90             chg_virtue(player_ptr, Virtue::SACRIFICE, -3);
91             chg_virtue(player_ptr, Virtue::VALOUR, -5);
92             rfu.set_flag(MainWindowRedrawingFlag::MAP);
93             rfu.set_flag(StatusRedrawingFlag::MONSTER_STATUSES);
94             player_ptr->window_flags |= (PW_OVERHEAD | PW_DUNGEON);
95         }
96     } else {
97         if (player_ptr->invuln && !music_singing(player_ptr, MUSIC_INVULN)) {
98             msg_print(_("無敵ではなくなった。", "The invulnerability wears off."));
99             notice = true;
100             rfu.set_flag(MainWindowRedrawingFlag::MAP);
101             rfu.set_flag(StatusRedrawingFlag::MONSTER_STATUSES);
102             player_ptr->window_flags |= (PW_OVERHEAD | PW_DUNGEON);
103             player_ptr->energy_need += ENERGY_NEED();
104         }
105     }
106
107     player_ptr->invuln = v;
108     rfu.set_flag(MainWindowRedrawingFlag::TIMED_EFFECT);
109
110     if (!notice) {
111         return false;
112     }
113
114     if (disturb_state) {
115         disturb(player_ptr, false, false);
116     }
117
118     rfu.set_flag(StatusRedrawingFlag::BONUS);
119     handle_stuff(player_ptr);
120     return true;
121 }
122
123 /*!
124  * @brief 時限急回復の継続時間をセットする / Set "tim_regen", notice observable changes
125  * @param v 継続時間
126  * @param do_dec 現在の継続時間より長い値のみ上書きする
127  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
128  */
129 bool set_tim_regen(PlayerType *player_ptr, TIME_EFFECT v, bool do_dec)
130 {
131     bool notice = false;
132     v = (v > 10000) ? 10000 : (v < 0) ? 0
133                                       : v;
134
135     if (player_ptr->is_dead) {
136         return false;
137     }
138
139     if (v) {
140         if (player_ptr->tim_regen && !do_dec) {
141             if (player_ptr->tim_regen > v) {
142                 return false;
143             }
144         } else if (!player_ptr->tim_regen) {
145             msg_print(_("回復力が上がった!", "You feel yourself regenerating quickly!"));
146             notice = true;
147         }
148     } else {
149         if (player_ptr->tim_regen) {
150             msg_print(_("素早く回復する感じがなくなった。", "You feel you are no longer regenerating quickly."));
151             notice = true;
152         }
153     }
154
155     player_ptr->tim_regen = v;
156     auto &rfu = RedrawingFlagsUpdater::get_instance();
157     rfu.set_flag(MainWindowRedrawingFlag::TIMED_EFFECT);
158     if (!notice) {
159         return false;
160     }
161
162     if (disturb_state) {
163         disturb(player_ptr, false, false);
164     }
165
166     rfu.set_flag(StatusRedrawingFlag::BONUS);
167     handle_stuff(player_ptr);
168     return true;
169 }
170
171 /*!
172  * @brief 一時的反射の継続時間をセットする / Set "tim_reflect", notice observable changes
173  * @param v 継続時間
174  * @param do_dec 現在の継続時間より長い値のみ上書きする
175  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
176  */
177 bool set_tim_reflect(PlayerType *player_ptr, TIME_EFFECT v, bool do_dec)
178 {
179     bool notice = false;
180     v = (v > 10000) ? 10000 : (v < 0) ? 0
181                                       : v;
182
183     if (player_ptr->is_dead) {
184         return false;
185     }
186
187     if (v) {
188         if (player_ptr->tim_reflect && !do_dec) {
189             if (player_ptr->tim_reflect > v) {
190                 return false;
191             }
192         } else if (!player_ptr->tim_reflect) {
193             msg_print(_("体の表面が滑かになった気がする。", "Your body becames smooth."));
194             notice = true;
195         }
196     } else {
197         if (player_ptr->tim_reflect) {
198             msg_print(_("体の表面が滑かでなくなった。", "Your body is no longer smooth."));
199             notice = true;
200         }
201     }
202
203     player_ptr->tim_reflect = v;
204     auto &rfu = RedrawingFlagsUpdater::get_instance();
205     rfu.set_flag(MainWindowRedrawingFlag::TIMED_EFFECT);
206     if (!notice) {
207         return false;
208     }
209
210     if (disturb_state) {
211         disturb(player_ptr, false, false);
212     }
213
214     rfu.set_flag(StatusRedrawingFlag::BONUS);
215     handle_stuff(player_ptr);
216     return true;
217 }
218
219 /*!
220  * @brief 一時的壁抜けの継続時間をセットする / Set "tim_pass_wall", notice observable changes
221  * @param v 継続時間
222  * @param do_dec 現在の継続時間より長い値のみ上書きする
223  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
224  */
225 bool set_pass_wall(PlayerType *player_ptr, TIME_EFFECT v, bool do_dec)
226 {
227     bool notice = false;
228     v = (v > 10000) ? 10000 : (v < 0) ? 0
229                                       : v;
230
231     if (player_ptr->is_dead) {
232         return false;
233     }
234
235     if (v) {
236         if (player_ptr->tim_pass_wall && !do_dec) {
237             if (player_ptr->tim_pass_wall > v) {
238                 return false;
239             }
240         } else if (!player_ptr->tim_pass_wall) {
241             msg_print(_("体が半物質の状態になった。", "You became ethereal."));
242             notice = true;
243         }
244     } else {
245         if (player_ptr->tim_pass_wall) {
246             msg_print(_("体が物質化した。", "You are no longer ethereal."));
247             notice = true;
248         }
249     }
250
251     player_ptr->tim_pass_wall = v;
252     auto &rfu = RedrawingFlagsUpdater::get_instance();
253     rfu.set_flag(MainWindowRedrawingFlag::TIMED_EFFECT);
254     if (!notice) {
255         return false;
256     }
257
258     if (disturb_state) {
259         disturb(player_ptr, false, false);
260     }
261
262     rfu.set_flag(StatusRedrawingFlag::BONUS);
263     handle_stuff(player_ptr);
264     return true;
265 }