1 #include "status/buff-setter.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 "monster/monster-status-setter.h"
10 #include "player-base/player-class.h"
11 #include "player-info/class-info.h"
12 #include "player-info/race-info.h"
13 #include "player/attack-defense-types.h"
14 #include "player/player-status.h"
15 #include "realm/realm-song-numbers.h"
16 #include "spell-realm/spells-song.h"
17 #include "status/base-status.h"
18 #include "status/buff-setter.h"
19 #include "status/element-resistance.h"
20 #include "system/player-type-definition.h"
21 #include "system/redrawing-flags-updater.h"
22 #include "timed-effect/player-acceleration.h"
23 #include "timed-effect/player-blindness.h"
24 #include "timed-effect/player-confusion.h"
25 #include "timed-effect/player-cut.h"
26 #include "timed-effect/player-deceleration.h"
27 #include "timed-effect/player-fear.h"
28 #include "timed-effect/player-hallucination.h"
29 #include "timed-effect/player-paralysis.h"
30 #include "timed-effect/player-poison.h"
31 #include "timed-effect/player-stun.h"
32 #include "timed-effect/timed-effects.h"
33 #include "view/display-messages.h"
36 * @brief プレイヤーの全ての時限効果をリセットする。 / reset timed flags
38 void reset_tim_flags(PlayerType *player_ptr)
40 auto effects = player_ptr->effects();
41 effects->acceleration()->reset();
42 player_ptr->lightspeed = 0;
43 effects->deceleration()->reset();
44 effects->blindness()->reset();
45 effects->paralysis()->reset();
46 effects->confusion()->reset();
47 effects->fear()->reset();
48 effects->hallucination()->reset();
49 effects->poison()->reset();
50 effects->cut()->reset();
51 effects->stun()->reset();
53 player_ptr->protevil = 0; /* Timed -- Protection */
54 player_ptr->invuln = 0; /* Timed -- Invulnerable */
55 player_ptr->ult_res = 0;
56 player_ptr->hero = 0; /* Timed -- Heroism */
57 player_ptr->shero = 0; /* Timed -- Super Heroism */
58 player_ptr->shield = 0; /* Timed -- Shield Spell */
59 player_ptr->blessed = 0; /* Timed -- Blessed */
60 player_ptr->tim_invis = 0; /* Timed -- Invisibility */
61 player_ptr->tim_infra = 0; /* Timed -- Infra Vision */
62 player_ptr->tim_regen = 0; /* Timed -- Regeneration */
63 player_ptr->tim_stealth = 0; /* Timed -- Stealth */
64 player_ptr->tim_esp = 0;
65 player_ptr->wraith_form = 0; /* Timed -- Wraith Form */
66 player_ptr->tim_levitation = 0;
67 player_ptr->tim_sh_touki = 0;
68 player_ptr->tim_sh_fire = 0;
69 player_ptr->tim_sh_holy = 0;
70 player_ptr->tim_eyeeye = 0;
71 player_ptr->magicdef = 0;
72 player_ptr->resist_magic = 0;
73 player_ptr->tsuyoshi = 0;
74 player_ptr->tim_pass_wall = 0;
75 player_ptr->tim_res_nether = 0;
76 player_ptr->tim_res_time = 0;
77 player_ptr->tim_mimic = 0;
78 player_ptr->mimic_form = MimicKindType::NONE;
79 player_ptr->tim_reflect = 0;
80 player_ptr->multishadow = 0;
81 player_ptr->dustrobe = 0;
82 player_ptr->action = ACTION_NONE;
84 player_ptr->oppose_acid = 0; /* Timed -- oppose acid */
85 player_ptr->oppose_elec = 0; /* Timed -- oppose lightning */
86 player_ptr->oppose_fire = 0; /* Timed -- oppose heat */
87 player_ptr->oppose_cold = 0; /* Timed -- oppose cold */
88 player_ptr->oppose_pois = 0; /* Timed -- oppose poison */
90 player_ptr->word_recall = 0;
91 player_ptr->alter_reality = 0;
92 player_ptr->sutemi = false;
93 player_ptr->counter = false;
94 player_ptr->ele_attack = 0;
95 player_ptr->ele_immune = 0;
96 player_ptr->special_attack = 0L;
97 player_ptr->special_defense = 0L;
99 while (player_ptr->energy_need < 0) {
100 player_ptr->energy_need += ENERGY_NEED();
103 player_ptr->timewalk = false;
105 if (player_ptr->riding) {
106 (void)set_monster_fast(player_ptr, player_ptr->riding, 0);
107 (void)set_monster_slow(player_ptr, player_ptr->riding, 0);
108 (void)set_monster_invulner(player_ptr, player_ptr->riding, 0, false);
111 if (PlayerClass(player_ptr).equals(PlayerClassType::BARD)) {
112 set_singing_song_effect(player_ptr, MUSIC_NONE);
113 set_singing_song_id(player_ptr, 0);
118 * @brief 加速の継続時間をセットする / Set "fast", notice observable changes
120 * @param do_dec 現在の継続時間より長い値のみ上書きする
121 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
123 bool set_acceleration(PlayerType *player_ptr, TIME_EFFECT v, bool do_dec)
126 v = (v > 10000) ? 10000 : (v < 0) ? 0
129 if (player_ptr->is_dead) {
133 auto acceleration = player_ptr->effects()->acceleration();
135 if (acceleration->is_fast() && !do_dec) {
136 if (acceleration->current() > v) {
139 } else if (!is_fast(player_ptr) && !player_ptr->lightspeed) {
140 msg_print(_("素早く動けるようになった!", "You feel yourself moving much faster!"));
142 chg_virtue(player_ptr, Virtue::PATIENCE, -1);
143 chg_virtue(player_ptr, Virtue::DILIGENCE, 1);
146 if (acceleration->is_fast() && !player_ptr->lightspeed) {
147 auto is_singing = music_singing(player_ptr, MUSIC_SPEED);
148 is_singing |= music_singing(player_ptr, MUSIC_SHERO);
150 msg_print(_("動きの素早さがなくなったようだ。", "You feel yourself slow down."));
156 acceleration->set(v);
162 disturb(player_ptr, false, false);
164 RedrawingFlagsUpdater::get_instance().set_flag(StatusRedrawingFlag::BONUS);
165 handle_stuff(player_ptr);
169 bool mod_acceleration(PlayerType *player_ptr, const TIME_EFFECT v, const bool do_dec)
171 return set_acceleration(player_ptr, player_ptr->effects()->acceleration()->current() + v, do_dec);
175 * @brief 肌石化の継続時間をセットする / Set "shield", notice observable changes
177 * @param do_dec 現在の継続時間より長い値のみ上書きする
178 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
180 bool set_shield(PlayerType *player_ptr, TIME_EFFECT v, bool do_dec)
183 v = (v > 10000) ? 10000 : (v < 0) ? 0
186 if (player_ptr->is_dead) {
191 if (player_ptr->shield && !do_dec) {
192 if (player_ptr->shield > v) {
195 } else if (!player_ptr->shield) {
196 msg_print(_("肌が石になった。", "Your skin turns to stone."));
200 if (player_ptr->shield) {
201 msg_print(_("肌が元に戻った。", "Your skin returns to normal."));
206 player_ptr->shield = v;
207 auto &rfu = RedrawingFlagsUpdater::get_instance();
208 rfu.set_flag(MainWindowRedrawingFlag::TIMED_EFFECT);
214 disturb(player_ptr, false, false);
217 rfu.set_flag(StatusRedrawingFlag::BONUS);
218 handle_stuff(player_ptr);
223 * @brief 魔法の鎧の継続時間をセットする / Set "magicdef", notice observable changes
225 * @param do_dec 現在の継続時間より長い値のみ上書きする
226 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
228 bool set_magicdef(PlayerType *player_ptr, TIME_EFFECT v, bool do_dec)
231 v = (v > 10000) ? 10000 : (v < 0) ? 0
234 if (player_ptr->is_dead) {
239 if (player_ptr->magicdef && !do_dec) {
240 if (player_ptr->magicdef > v) {
243 } else if (!player_ptr->magicdef) {
244 msg_print(_("魔法の防御力が増したような気がする。", "You feel more resistant to magic."));
248 if (player_ptr->magicdef) {
249 msg_print(_("魔法の防御力が元に戻った。", "You feel less resistant to magic."));
254 player_ptr->magicdef = v;
255 auto &rfu = RedrawingFlagsUpdater::get_instance();
256 rfu.set_flag(MainWindowRedrawingFlag::TIMED_EFFECT);
262 disturb(player_ptr, false, false);
265 rfu.set_flag(StatusRedrawingFlag::BONUS);
266 handle_stuff(player_ptr);
271 * @brief 祝福の継続時間をセットする / Set "blessed", notice observable changes
273 * @param do_dec 現在の継続時間より長い値のみ上書きする
274 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
276 bool set_blessed(PlayerType *player_ptr, TIME_EFFECT v, bool do_dec)
279 v = (v > 10000) ? 10000 : (v < 0) ? 0
282 if (player_ptr->is_dead) {
287 if (player_ptr->blessed && !do_dec) {
288 if (player_ptr->blessed > v) {
291 } else if (!is_blessed(player_ptr)) {
292 msg_print(_("高潔な気分になった!", "You feel righteous!"));
296 if (player_ptr->blessed && !music_singing(player_ptr, MUSIC_BLESS)) {
297 msg_print(_("高潔な気分が消え失せた。", "The prayer has expired."));
302 player_ptr->blessed = v;
303 auto &rfu = RedrawingFlagsUpdater::get_instance();
304 rfu.set_flag(MainWindowRedrawingFlag::TIMED_EFFECT);
310 disturb(player_ptr, false, false);
313 rfu.set_flag(StatusRedrawingFlag::BONUS);
314 handle_stuff(player_ptr);
319 * @brief 士気高揚の継続時間をセットする / Set "hero", notice observable changes
321 * @param do_dec 現在の継続時間より長い値のみ上書きする
322 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
324 bool set_hero(PlayerType *player_ptr, TIME_EFFECT v, bool do_dec)
327 v = (v > 10000) ? 10000 : (v < 0) ? 0
330 if (player_ptr->is_dead) {
335 if (player_ptr->hero && !do_dec) {
336 if (player_ptr->hero > v) {
339 } else if (!is_hero(player_ptr)) {
340 msg_print(_("ヒーローになった気がする!", "You feel like a hero!"));
344 if (player_ptr->hero && !music_singing(player_ptr, MUSIC_HERO) && !music_singing(player_ptr, MUSIC_SHERO)) {
345 msg_print(_("ヒーローの気分が消え失せた。", "The heroism wears off."));
350 player_ptr->hero = v;
351 auto &rfu = RedrawingFlagsUpdater::get_instance();
352 rfu.set_flag(MainWindowRedrawingFlag::TIMED_EFFECT);
358 disturb(player_ptr, false, false);
362 StatusRedrawingFlag::BONUS,
363 StatusRedrawingFlag::HP,
365 RedrawingFlagsUpdater::get_instance().set_flags(flags);
366 handle_stuff(player_ptr);
371 * @brief 変身効果の継続時間と変身先をセットする / Set "tim_mimic", and "mimic_form", notice observable changes
373 * @param mimic_race_idx 変身内容
374 * @param do_dec 現在の継続時間より長い値のみ上書きする
375 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
377 bool set_mimic(PlayerType *player_ptr, TIME_EFFECT v, MimicKindType mimic_race_idx, bool do_dec)
380 v = (v > 10000) ? 10000 : (v < 0) ? 0
383 if (player_ptr->is_dead) {
388 if (player_ptr->tim_mimic && (player_ptr->mimic_form == mimic_race_idx) && !do_dec) {
389 if (player_ptr->tim_mimic > v) {
392 } else if ((!player_ptr->tim_mimic) || (player_ptr->mimic_form != mimic_race_idx)) {
393 msg_print(_("自分の体が変わってゆくのを感じた。", "You feel that your body changes."));
394 player_ptr->mimic_form = mimic_race_idx;
400 if (player_ptr->tim_mimic) {
401 msg_print(_("変身が解けた。", "You are no longer transformed."));
402 if (player_ptr->mimic_form == MimicKindType::DEMON) {
403 set_oppose_fire(player_ptr, 0, true);
405 player_ptr->mimic_form = MimicKindType::NONE;
407 mimic_race_idx = MimicKindType::NONE;
411 player_ptr->tim_mimic = v;
417 disturb(player_ptr, false, true);
420 auto &rfu = RedrawingFlagsUpdater::get_instance();
421 const auto flags_mwrf = {
422 MainWindowRedrawingFlag::BASIC,
423 MainWindowRedrawingFlag::TIMED_EFFECT,
425 rfu.set_flags(flags_mwrf);
426 const auto flags_srf = {
427 StatusRedrawingFlag::BONUS,
428 StatusRedrawingFlag::HP,
430 rfu.set_flags(flags_srf);
431 handle_stuff(player_ptr);
436 * @brief 狂戦士化の継続時間をセットする / Set "shero", notice observable changes
437 * @param v 継続時間/ 0ならば無条件にリセット
438 * @param do_dec FALSEの場合現在の継続時間より長い値のみ上書きする
439 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
441 bool set_shero(PlayerType *player_ptr, TIME_EFFECT v, bool do_dec)
444 v = (v > 10000) ? 10000 : (v < 0) ? 0
447 if (player_ptr->is_dead) {
451 if (PlayerClass(player_ptr).equals(PlayerClassType::BERSERKER)) {
457 if (player_ptr->shero && !do_dec) {
458 if (player_ptr->shero > v) {
461 } else if (!player_ptr->shero) {
462 msg_print(_("殺戮マシーンになった気がする!", "You feel like a killing machine!"));
466 if (player_ptr->shero) {
467 msg_print(_("野蛮な気持ちが消え失せた。", "You feel less berserk."));
472 player_ptr->shero = v;
473 auto &rfu = RedrawingFlagsUpdater::get_instance();
474 rfu.set_flag(MainWindowRedrawingFlag::TIMED_EFFECT);
480 disturb(player_ptr, false, false);
484 StatusRedrawingFlag::BONUS,
485 StatusRedrawingFlag::HP,
487 RedrawingFlagsUpdater::get_instance().set_flags(flags);
488 handle_stuff(player_ptr);
493 * @brief 幽体化の継続時間をセットする / Set "wraith_form", notice observable changes
495 * @param do_dec 現在の継続時間より長い値のみ上書きする
496 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
498 bool set_wraith_form(PlayerType *player_ptr, TIME_EFFECT v, bool do_dec)
501 v = (v > 10000) ? 10000 : (v < 0) ? 0
504 if (player_ptr->is_dead) {
508 auto &rfu = RedrawingFlagsUpdater::get_instance();
510 if (player_ptr->wraith_form && !do_dec) {
511 if (player_ptr->wraith_form > v) {
514 } else if (!player_ptr->wraith_form) {
515 msg_print(_("物質界を離れて幽鬼のような存在になった!", "You leave the physical world and turn into a wraith-being!"));
517 chg_virtue(player_ptr, Virtue::UNLIFE, 3);
518 chg_virtue(player_ptr, Virtue::HONOUR, -2);
519 chg_virtue(player_ptr, Virtue::SACRIFICE, -2);
520 chg_virtue(player_ptr, Virtue::VALOUR, -5);
521 rfu.set_flag(MainWindowRedrawingFlag::MAP);
522 rfu.set_flag(StatusRedrawingFlag::MONSTER_STATUSES);
523 player_ptr->window_flags |= (PW_OVERHEAD | PW_DUNGEON);
526 if (player_ptr->wraith_form) {
527 msg_print(_("不透明になった感じがする。", "You feel opaque."));
529 rfu.set_flag(MainWindowRedrawingFlag::MAP);
530 rfu.set_flag(StatusRedrawingFlag::MONSTER_STATUSES);
531 player_ptr->window_flags |= (PW_OVERHEAD | PW_DUNGEON);
535 player_ptr->wraith_form = v;
536 rfu.set_flag(MainWindowRedrawingFlag::TIMED_EFFECT);
542 disturb(player_ptr, false, false);
545 rfu.set_flag(StatusRedrawingFlag::BONUS);
546 handle_stuff(player_ptr);
551 * @brief オクレ兄さんの継続時間をセットする / Set "tsuyoshi", notice observable changes
553 * @param do_dec 現在の継続時間より長い値のみ上書きする
554 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
556 bool set_tsuyoshi(PlayerType *player_ptr, TIME_EFFECT v, bool do_dec)
559 v = (v > 10000) ? 10000 : (v < 0) ? 0
562 if (player_ptr->is_dead) {
567 if (player_ptr->tsuyoshi && !do_dec) {
568 if (player_ptr->tsuyoshi > v) {
571 } else if (!player_ptr->tsuyoshi) {
572 msg_print(_("「オクレ兄さん!」", "Brother OKURE!"));
574 chg_virtue(player_ptr, Virtue::VITALITY, 2);
577 if (player_ptr->tsuyoshi) {
578 msg_print(_("肉体が急速にしぼんでいった。", "Your body has quickly shriveled."));
580 (void)dec_stat(player_ptr, A_CON, 20, true);
581 (void)dec_stat(player_ptr, A_STR, 20, true);
584 chg_virtue(player_ptr, Virtue::VITALITY, -3);
588 player_ptr->tsuyoshi = v;
589 auto &rfu = RedrawingFlagsUpdater::get_instance();
590 rfu.set_flag(MainWindowRedrawingFlag::TIMED_EFFECT);
596 disturb(player_ptr, false, false);
600 StatusRedrawingFlag::BONUS,
601 StatusRedrawingFlag::HP,
603 rfu.set_flags(flags);
604 handle_stuff(player_ptr);