1 #include "status/bad-status-setter.h"
2 #include "avatar/avatar.h"
3 #include "core/disturbance.h"
4 #include "core/player-redraw-types.h"
5 #include "core/player-update-types.h"
6 #include "core/stuff-handler.h"
7 #include "core/window-redrawer.h"
8 #include "game-option/disturbance-options.h"
9 #include "mind/mind-sniper.h"
10 #include "player-base/player-class.h"
11 #include "player-base/player-race.h"
12 #include "player-info/bluemage-data-type.h"
13 #include "player/attack-defense-types.h"
14 #include "player/player-status-flags.h"
15 #include "player/player-status.h"
16 #include "player/special-defense-types.h"
17 #include "spell-realm/spells-hex.h"
18 #include "status/base-status.h"
19 #include "status/buff-setter.h"
20 #include "system/player-type-definition.h"
21 #include "timed-effect/player-cut.h"
22 #include "timed-effect/player-stun.h"
23 #include "timed-effect/timed-effects.h"
24 #include "view/display-messages.h"
27 BadStatusSetter::BadStatusSetter(player_type *player_ptr)
28 : player_ptr(player_ptr)
33 * @brief 盲目の継続時間をセットする / Set "blind", notice observable changes
35 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
37 * Note the use of "PU_UN_LITE" and "PU_UN_VIEW", which is needed to\n
38 * memorize any terrain features which suddenly become "visible".\n
39 * Note that blindness is currently the only thing which can affect\n
40 * "player_can_see_bold()".\n
42 bool BadStatusSetter::blindness(const TIME_EFFECT tmp_v)
45 auto v = std::clamp<short>(tmp_v, 0, 10000);
46 if (this->player_ptr->is_dead) {
51 if (!this->player_ptr->blind) {
52 if (this->player_ptr->prace == player_race_type::ANDROID) {
53 msg_print(_("センサーをやられた!", "The sensor broke!"));
55 msg_print(_("目が見えなくなってしまった!", "You are blind!"));
59 chg_virtue(this->player_ptr, V_ENLIGHTEN, -1);
62 if (this->player_ptr->blind) {
63 if (this->player_ptr->prace == player_race_type::ANDROID) {
64 msg_print(_("センサーが復旧した。", "The sensor has been restored."));
66 msg_print(_("やっと目が見えるようになった。", "You can see again."));
73 this->player_ptr->blind = v;
74 this->player_ptr->redraw |= PR_STATUS;
80 disturb(this->player_ptr, false, false);
83 this->player_ptr->update |= PU_UN_VIEW | PU_UN_LITE | PU_VIEW | PU_LITE | PU_MONSTERS | PU_MON_LITE;
84 this->player_ptr->redraw |= PR_MAP;
85 this->player_ptr->window_flags |= PW_OVERHEAD | PW_DUNGEON;
86 handle_stuff(this->player_ptr);
90 bool BadStatusSetter::mod_blindness(const TIME_EFFECT tmp_v)
92 return this->blindness(this->player_ptr->blind + tmp_v);
96 * @brief 混乱の継続時間をセットする / Set "confused", notice observable changes
98 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
100 bool BadStatusSetter::confusion(const TIME_EFFECT tmp_v)
103 auto v = std::clamp<short>(tmp_v, 0, 10000);
104 if (this->player_ptr->is_dead) {
109 if (!this->player_ptr->confused) {
110 msg_print(_("あなたは混乱した!", "You are confused!"));
112 if (this->player_ptr->action == ACTION_LEARN) {
113 msg_print(_("学習が続けられない!", "You cannot continue learning!"));
114 auto bluemage_data = PlayerClass(player_ptr).get_specific_data<bluemage_data_type>();
115 bluemage_data->new_magic_learned = false;
117 this->player_ptr->redraw |= PR_STATE;
118 this->player_ptr->action = ACTION_NONE;
120 if (this->player_ptr->action == ACTION_KAMAE) {
121 msg_print(_("構えがとけた。", "You lose your stance."));
122 this->player_ptr->special_defense &= ~(KAMAE_MASK);
123 this->player_ptr->update |= PU_BONUS;
124 this->player_ptr->redraw |= PR_STATE;
125 this->player_ptr->action = ACTION_NONE;
126 } else if (this->player_ptr->action == ACTION_KATA) {
127 msg_print(_("型が崩れた。", "You lose your stance."));
128 this->player_ptr->special_defense &= ~(KATA_MASK);
129 this->player_ptr->update |= PU_BONUS;
130 this->player_ptr->update |= PU_MONSTERS;
131 this->player_ptr->redraw |= PR_STATE;
132 this->player_ptr->redraw |= PR_STATUS;
133 this->player_ptr->action = ACTION_NONE;
137 reset_concentration(this->player_ptr, true);
139 SpellHex spell_hex(this->player_ptr);
140 if (spell_hex.is_spelling_any()) {
141 (void)spell_hex.stop_all_spells();
145 this->player_ptr->counter = false;
146 chg_virtue(this->player_ptr, V_HARMONY, -1);
149 if (this->player_ptr->confused) {
150 msg_print(_("やっと混乱がおさまった。", "You feel less confused now."));
151 this->player_ptr->special_attack &= ~(ATTACK_SUIKEN);
156 this->player_ptr->confused = v;
157 this->player_ptr->redraw |= PR_STATUS;
163 disturb(this->player_ptr, false, false);
166 handle_stuff(this->player_ptr);
170 bool BadStatusSetter::mod_confusion(const TIME_EFFECT tmp_v)
172 return this->confusion(this->player_ptr->confused + tmp_v);
176 * @brief 毒の継続時間をセットする / Set "poisoned", notice observable changes
178 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
180 bool BadStatusSetter::poison(const TIME_EFFECT tmp_v)
183 auto v = std::clamp<short>(tmp_v, 0, 10000);
184 if (this->player_ptr->is_dead) {
189 if (!this->player_ptr->poisoned) {
190 msg_print(_("毒に侵されてしまった!", "You are poisoned!"));
194 if (this->player_ptr->poisoned) {
195 msg_print(_("やっと毒の痛みがなくなった。", "You are no longer poisoned."));
200 this->player_ptr->poisoned = v;
201 this->player_ptr->redraw |= PR_STATUS;
207 disturb(this->player_ptr, false, false);
210 handle_stuff(this->player_ptr);
214 bool BadStatusSetter::mod_poison(const TIME_EFFECT tmp_v)
216 return this->poison(this->player_ptr->poisoned + tmp_v);
220 * @brief 恐怖の継続時間をセットする / Set "afraid", notice observable changes
222 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
224 bool BadStatusSetter::afraidness(const TIME_EFFECT tmp_v)
227 auto v = std::clamp<short>(tmp_v, 0, 10000);
228 if (this->player_ptr->is_dead) {
233 if (!this->player_ptr->afraid) {
234 msg_print(_("何もかも恐くなってきた!", "You are terrified!"));
235 if (this->player_ptr->special_defense & KATA_MASK) {
236 msg_print(_("型が崩れた。", "You lose your stance."));
237 this->player_ptr->special_defense &= ~(KATA_MASK);
238 this->player_ptr->update |= PU_BONUS;
239 this->player_ptr->update |= PU_MONSTERS;
240 this->player_ptr->redraw |= PR_STATE;
241 this->player_ptr->redraw |= PR_STATUS;
242 this->player_ptr->action = ACTION_NONE;
246 this->player_ptr->counter = false;
247 chg_virtue(this->player_ptr, V_VALOUR, -1);
250 if (this->player_ptr->afraid) {
251 msg_print(_("やっと恐怖を振り払った。", "You feel bolder now."));
256 this->player_ptr->afraid = v;
257 this->player_ptr->redraw |= PR_STATUS;
263 disturb(this->player_ptr, false, false);
266 handle_stuff(this->player_ptr);
270 bool BadStatusSetter::mod_afraidness(const TIME_EFFECT tmp_v)
272 return this->afraidness(this->player_ptr->afraid + tmp_v);
276 * @brief 麻痺の継続時間をセットする / Set "paralyzed", notice observable changes
278 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
280 bool BadStatusSetter::paralysis(const TIME_EFFECT tmp_v)
283 auto v = std::clamp<short>(tmp_v, 0, 10000);
284 if (this->player_ptr->is_dead) {
289 if (!this->player_ptr->paralyzed) {
290 msg_print(_("体が麻痺してしまった!", "You are paralyzed!"));
291 reset_concentration(this->player_ptr, true);
293 SpellHex spell_hex(this->player_ptr);
294 if (spell_hex.is_spelling_any()) {
295 (void)spell_hex.stop_all_spells();
298 this->player_ptr->counter = false;
302 if (this->player_ptr->paralyzed) {
303 msg_print(_("やっと動けるようになった。", "You can move again."));
308 this->player_ptr->paralyzed = v;
309 this->player_ptr->redraw |= PR_STATUS;
315 disturb(this->player_ptr, false, false);
318 this->player_ptr->redraw |= PR_STATE;
319 handle_stuff(this->player_ptr);
323 bool BadStatusSetter::mod_paralysis(const TIME_EFFECT tmp_v)
325 return this->paralysis(this->player_ptr->paralyzed + tmp_v);
329 * @brief 幻覚の継続時間をセットする / Set "image", notice observable changes
331 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
332 * @details Note that we must redraw the map when hallucination changes.
334 bool BadStatusSetter::hallucination(const TIME_EFFECT tmp_v)
337 auto v = std::clamp<short>(tmp_v, 0, 10000);
338 if (this->player_ptr->is_dead) {
342 if (is_chargeman(this->player_ptr)) {
347 set_tsuyoshi(this->player_ptr, 0, true);
348 if (!this->player_ptr->hallucinated) {
349 msg_print(_("ワーオ!何もかも虹色に見える!", "Oh, wow! Everything looks so cosmic now!"));
350 reset_concentration(this->player_ptr, true);
352 this->player_ptr->counter = false;
356 if (this->player_ptr->hallucinated) {
357 msg_print(_("やっとはっきりと物が見えるようになった。", "You can see clearly again."));
362 this->player_ptr->hallucinated = v;
363 this->player_ptr->redraw |= PR_STATUS;
369 disturb(this->player_ptr, false, true);
372 this->player_ptr->redraw |= PR_MAP | PR_HEALTH | PR_UHEALTH;
373 this->player_ptr->update |= PU_MONSTERS;
374 this->player_ptr->window_flags |= PW_OVERHEAD | PW_DUNGEON;
375 handle_stuff(this->player_ptr);
379 bool BadStatusSetter::mod_hallucination(const TIME_EFFECT tmp_v)
381 return this->hallucination(this->player_ptr->hallucinated + tmp_v);
385 * @brief 減速の継続時間をセットする / Set "slow", notice observable changes
387 * @param do_dec 現在の継続時間より長い値のみ上書きする
388 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
390 bool BadStatusSetter::slowness(const TIME_EFFECT tmp_v, bool do_dec)
393 auto v = std::clamp<short>(tmp_v, 0, 10000);
394 if (this->player_ptr->is_dead) {
399 if (this->player_ptr->slow && !do_dec) {
400 if (this->player_ptr->slow > v) {
403 } else if (!this->player_ptr->slow) {
404 msg_print(_("体の動きが遅くなってしまった!", "You feel yourself moving slower!"));
408 if (this->player_ptr->slow) {
409 msg_print(_("動きの遅さがなくなったようだ。", "You feel yourself speed up."));
414 this->player_ptr->slow = v;
420 disturb(this->player_ptr, false, false);
423 this->player_ptr->update |= PU_BONUS;
424 handle_stuff(this->player_ptr);
428 bool BadStatusSetter::mod_slowness(const TIME_EFFECT tmp_v, bool do_dec)
430 return this->slowness(this->player_ptr->slow + tmp_v, do_dec);
434 * @brief 朦朧の継続時間をセットする / Set "stun", notice observable changes
436 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
438 * Note the special code to only notice "range" changes.
440 bool BadStatusSetter::stun(const TIME_EFFECT tmp_v)
442 auto v = std::clamp<short>(tmp_v, 0, 10000);
443 if (this->player_ptr->is_dead) {
447 if (PlayerRace(this->player_ptr).equals(player_race_type::GOLEM) || PlayerClass(this->player_ptr).can_resist_stun()) {
451 auto notice = this->process_stun_effect(v);
452 this->player_ptr->effects()->stun()->set(v);
458 disturb(this->player_ptr, false, false);
461 this->player_ptr->update |= PU_BONUS;
462 this->player_ptr->redraw |= PR_STUN;
463 handle_stuff(this->player_ptr);
467 bool BadStatusSetter::mod_stun(const TIME_EFFECT tmp_v)
469 return this->stun(this->player_ptr->effects()->stun()->current() + tmp_v);
473 * @brief 出血の継続時間をセットする / Set "cut", notice observable changes
475 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
477 * Note the special code to only notice "range" changes.
479 bool BadStatusSetter::cut(const TIME_EFFECT tmp_v)
481 auto v = std::clamp<short>(tmp_v, 0, 10000);
482 if (this->player_ptr->is_dead) {
486 if (PlayerRace(this->player_ptr).can_resist_cut() && !this->player_ptr->mimic_form) {
490 auto notice = this->process_cut_effect(v);
491 this->player_ptr->effects()->cut()->set(v);
497 disturb(this->player_ptr, false, false);
500 this->player_ptr->update |= PU_BONUS;
501 this->player_ptr->redraw |= PR_CUT;
502 handle_stuff(this->player_ptr);
506 bool BadStatusSetter::mod_cut(const TIME_EFFECT tmp_v)
508 return this->cut(this->player_ptr->effects()->cut()->current() + tmp_v);
511 bool BadStatusSetter::process_stun_effect(const short v)
513 auto old_rank = this->player_ptr->effects()->stun()->get_rank();
514 auto new_rank = PlayerStun::get_rank(v);
515 if (new_rank > old_rank) {
516 this->process_stun_status(new_rank, v);
520 if (new_rank < old_rank) {
528 void BadStatusSetter::process_stun_status(const PlayerStunRank new_rank, const short v)
530 auto stun_mes = PlayerStun::get_stun_mes(new_rank);
531 msg_print(stun_mes.data());
532 this->decrease_int_wis(v);
533 if (PlayerClass(this->player_ptr).lose_balance()) {
534 msg_print(_("型が崩れた。", "You lose your stance."));
537 reset_concentration(this->player_ptr, true);
539 SpellHex spell_hex(this->player_ptr);
540 if (spell_hex.is_spelling_any()) {
541 (void)spell_hex.stop_all_spells();
545 void BadStatusSetter::clear_head()
547 if (this->player_ptr->effects()->stun()->is_stunned()) {
551 msg_print(_("やっと朦朧状態から回復した。", "You are no longer stunned."));
553 disturb(this->player_ptr, false, false);
558 * @todo 後で知能と賢さが両方減る確率を減らす.
560 void BadStatusSetter::decrease_int_wis(const short v)
562 if ((v <= randint1(1000)) && !one_in_(16)) {
566 msg_print(_("割れるような頭痛がする。", "A vicious blow hits your head."));
567 auto rand = randint0(3);
570 if (has_sustain_int(this->player_ptr) == 0) {
571 (void)do_dec_stat(this->player_ptr, A_INT);
574 if (has_sustain_wis(this->player_ptr) == 0) {
575 (void)do_dec_stat(this->player_ptr, A_WIS);
580 if (has_sustain_int(this->player_ptr) == 0) {
581 (void)do_dec_stat(this->player_ptr, A_INT);
586 if (has_sustain_wis(this->player_ptr) == 0) {
587 (void)do_dec_stat(this->player_ptr, A_WIS);
596 bool BadStatusSetter::process_cut_effect(const short v)
598 auto player_cut = this->player_ptr->effects()->cut();
599 auto old_rank = player_cut->get_rank();
600 auto new_rank = player_cut->get_rank(v);
601 if (new_rank > old_rank) {
602 this->decrease_charisma(new_rank, v);
606 if (new_rank < old_rank) {
607 this->stop_blooding(new_rank);
614 void BadStatusSetter::decrease_charisma(const PlayerCutRank new_rank, const short v)
616 auto player_cut = this->player_ptr->effects()->cut();
617 auto cut_mes = player_cut->get_cut_mes(new_rank);
618 msg_print(cut_mes.data());
619 if (v <= randint1(1000) && !one_in_(16)) {
623 if (has_sustain_chr(this->player_ptr)) {
627 msg_print(_("ひどい傷跡が残ってしまった。", "You have been horribly scarred."));
628 do_dec_stat(this->player_ptr, A_CHR);
631 void BadStatusSetter::stop_blooding(const PlayerCutRank new_rank)
633 if (new_rank >= PlayerCutRank::GRAZING) {
637 auto blood_stop_mes = PlayerRace(this->player_ptr).equals(player_race_type::ANDROID)
638 ? _("怪我が直った", "leaking fluid")
639 : _("出血が止まった", "bleeding");
640 msg_format(_("やっと%s。", "You are no longer %s."), blood_stop_mes);
642 disturb(this->player_ptr, false, false);