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-info/monk-data-type.h"
14 #include "player/attack-defense-types.h"
15 #include "player/player-status-flags.h"
16 #include "player/player-status.h"
17 #include "player/special-defense-types.h"
18 #include "spell-realm/spells-hex.h"
19 #include "status/base-status.h"
20 #include "status/buff-setter.h"
21 #include "system/player-type-definition.h"
22 #include "timed-effect/player-cut.h"
23 #include "timed-effect/player-stun.h"
24 #include "timed-effect/timed-effects.h"
25 #include "view/display-messages.h"
28 BadStatusSetter::BadStatusSetter(player_type *player_ptr)
29 : player_ptr(player_ptr)
34 * @brief 盲目の継続時間をセットする / Set "blind", notice observable changes
36 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
38 * Note the use of "PU_UN_LITE" and "PU_UN_VIEW", which is needed to\n
39 * memorize any terrain features which suddenly become "visible".\n
40 * Note that blindness is currently the only thing which can affect\n
41 * "player_can_see_bold()".\n
43 bool BadStatusSetter::blindness(const TIME_EFFECT tmp_v)
46 auto v = std::clamp<short>(tmp_v, 0, 10000);
47 if (this->player_ptr->is_dead) {
52 if (!this->player_ptr->blind) {
53 if (this->player_ptr->prace == player_race_type::ANDROID) {
54 msg_print(_("センサーをやられた!", "The sensor broke!"));
56 msg_print(_("目が見えなくなってしまった!", "You are blind!"));
60 chg_virtue(this->player_ptr, V_ENLIGHTEN, -1);
63 if (this->player_ptr->blind) {
64 if (this->player_ptr->prace == player_race_type::ANDROID) {
65 msg_print(_("センサーが復旧した。", "The sensor has been restored."));
67 msg_print(_("やっと目が見えるようになった。", "You can see again."));
74 this->player_ptr->blind = v;
75 this->player_ptr->redraw |= PR_STATUS;
81 disturb(this->player_ptr, false, false);
84 this->player_ptr->update |= PU_UN_VIEW | PU_UN_LITE | PU_VIEW | PU_LITE | PU_MONSTERS | PU_MON_LITE;
85 this->player_ptr->redraw |= PR_MAP;
86 this->player_ptr->window_flags |= PW_OVERHEAD | PW_DUNGEON;
87 handle_stuff(this->player_ptr);
91 bool BadStatusSetter::mod_blindness(const TIME_EFFECT tmp_v)
93 return this->blindness(this->player_ptr->blind + tmp_v);
97 * @brief 混乱の継続時間をセットする / Set "confused", notice observable changes
99 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
101 bool BadStatusSetter::confusion(const TIME_EFFECT tmp_v)
104 auto v = std::clamp<short>(tmp_v, 0, 10000);
105 if (this->player_ptr->is_dead) {
110 if (!this->player_ptr->confused) {
111 msg_print(_("あなたは混乱した!", "You are confused!"));
113 if (this->player_ptr->action == ACTION_LEARN) {
114 msg_print(_("学習が続けられない!", "You cannot continue learning!"));
115 auto bluemage_data = PlayerClass(player_ptr).get_specific_data<bluemage_data_type>();
116 bluemage_data->new_magic_learned = false;
118 this->player_ptr->redraw |= PR_STATE;
119 this->player_ptr->action = ACTION_NONE;
121 if (this->player_ptr->action == ACTION_KAMAE) {
122 msg_print(_("構えがとけた。", "You lose your stance."));
123 PlayerClass(player_ptr).set_kamae(MonkKamae::NONE);
124 this->player_ptr->update |= PU_BONUS;
125 this->player_ptr->redraw |= PR_STATE;
126 this->player_ptr->action = ACTION_NONE;
127 } else if (this->player_ptr->action == ACTION_KATA) {
128 msg_print(_("型が崩れた。", "You lose your stance."));
129 PlayerClass(player_ptr).lose_balance();
133 reset_concentration(this->player_ptr, true);
135 SpellHex spell_hex(this->player_ptr);
136 if (spell_hex.is_spelling_any()) {
137 (void)spell_hex.stop_all_spells();
141 this->player_ptr->counter = false;
142 chg_virtue(this->player_ptr, V_HARMONY, -1);
145 if (this->player_ptr->confused) {
146 msg_print(_("やっと混乱がおさまった。", "You feel less confused now."));
147 this->player_ptr->special_attack &= ~(ATTACK_SUIKEN);
152 this->player_ptr->confused = v;
153 this->player_ptr->redraw |= PR_STATUS;
159 disturb(this->player_ptr, false, false);
162 handle_stuff(this->player_ptr);
166 bool BadStatusSetter::mod_confusion(const TIME_EFFECT tmp_v)
168 return this->confusion(this->player_ptr->confused + tmp_v);
172 * @brief 毒の継続時間をセットする / Set "poisoned", notice observable changes
174 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
176 bool BadStatusSetter::poison(const TIME_EFFECT tmp_v)
179 auto v = std::clamp<short>(tmp_v, 0, 10000);
180 if (this->player_ptr->is_dead) {
185 if (!this->player_ptr->poisoned) {
186 msg_print(_("毒に侵されてしまった!", "You are poisoned!"));
190 if (this->player_ptr->poisoned) {
191 msg_print(_("やっと毒の痛みがなくなった。", "You are no longer poisoned."));
196 this->player_ptr->poisoned = v;
197 this->player_ptr->redraw |= PR_STATUS;
203 disturb(this->player_ptr, false, false);
206 handle_stuff(this->player_ptr);
210 bool BadStatusSetter::mod_poison(const TIME_EFFECT tmp_v)
212 return this->poison(this->player_ptr->poisoned + tmp_v);
216 * @brief 恐怖の継続時間をセットする / Set "afraid", notice observable changes
218 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
220 bool BadStatusSetter::afraidness(const TIME_EFFECT tmp_v)
223 auto v = std::clamp<short>(tmp_v, 0, 10000);
224 if (this->player_ptr->is_dead) {
229 if (!this->player_ptr->afraid) {
230 msg_print(_("何もかも恐くなってきた!", "You are terrified!"));
231 if (PlayerClass(this->player_ptr).lose_balance()) {
232 msg_print(_("型が崩れた。", "You lose your stance."));
236 this->player_ptr->counter = false;
237 chg_virtue(this->player_ptr, V_VALOUR, -1);
240 if (this->player_ptr->afraid) {
241 msg_print(_("やっと恐怖を振り払った。", "You feel bolder now."));
246 this->player_ptr->afraid = v;
247 this->player_ptr->redraw |= PR_STATUS;
253 disturb(this->player_ptr, false, false);
256 handle_stuff(this->player_ptr);
260 bool BadStatusSetter::mod_afraidness(const TIME_EFFECT tmp_v)
262 return this->afraidness(this->player_ptr->afraid + tmp_v);
266 * @brief 麻痺の継続時間をセットする / Set "paralyzed", notice observable changes
268 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
270 bool BadStatusSetter::paralysis(const TIME_EFFECT tmp_v)
273 auto v = std::clamp<short>(tmp_v, 0, 10000);
274 if (this->player_ptr->is_dead) {
279 if (!this->player_ptr->paralyzed) {
280 msg_print(_("体が麻痺してしまった!", "You are paralyzed!"));
281 reset_concentration(this->player_ptr, true);
283 SpellHex spell_hex(this->player_ptr);
284 if (spell_hex.is_spelling_any()) {
285 (void)spell_hex.stop_all_spells();
288 this->player_ptr->counter = false;
292 if (this->player_ptr->paralyzed) {
293 msg_print(_("やっと動けるようになった。", "You can move again."));
298 this->player_ptr->paralyzed = v;
299 this->player_ptr->redraw |= PR_STATUS;
305 disturb(this->player_ptr, false, false);
308 this->player_ptr->redraw |= PR_STATE;
309 handle_stuff(this->player_ptr);
313 bool BadStatusSetter::mod_paralysis(const TIME_EFFECT tmp_v)
315 return this->paralysis(this->player_ptr->paralyzed + tmp_v);
319 * @brief 幻覚の継続時間をセットする / Set "image", notice observable changes
321 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
322 * @details Note that we must redraw the map when hallucination changes.
324 bool BadStatusSetter::hallucination(const TIME_EFFECT tmp_v)
327 auto v = std::clamp<short>(tmp_v, 0, 10000);
328 if (this->player_ptr->is_dead) {
332 if (is_chargeman(this->player_ptr)) {
337 set_tsuyoshi(this->player_ptr, 0, true);
338 if (!this->player_ptr->hallucinated) {
339 msg_print(_("ワーオ!何もかも虹色に見える!", "Oh, wow! Everything looks so cosmic now!"));
340 reset_concentration(this->player_ptr, true);
342 this->player_ptr->counter = false;
346 if (this->player_ptr->hallucinated) {
347 msg_print(_("やっとはっきりと物が見えるようになった。", "You can see clearly again."));
352 this->player_ptr->hallucinated = v;
353 this->player_ptr->redraw |= PR_STATUS;
359 disturb(this->player_ptr, false, true);
362 this->player_ptr->redraw |= PR_MAP | PR_HEALTH | PR_UHEALTH;
363 this->player_ptr->update |= PU_MONSTERS;
364 this->player_ptr->window_flags |= PW_OVERHEAD | PW_DUNGEON;
365 handle_stuff(this->player_ptr);
369 bool BadStatusSetter::mod_hallucination(const TIME_EFFECT tmp_v)
371 return this->hallucination(this->player_ptr->hallucinated + tmp_v);
375 * @brief 減速の継続時間をセットする / Set "slow", notice observable changes
377 * @param do_dec 現在の継続時間より長い値のみ上書きする
378 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
380 bool BadStatusSetter::slowness(const TIME_EFFECT tmp_v, bool do_dec)
383 auto v = std::clamp<short>(tmp_v, 0, 10000);
384 if (this->player_ptr->is_dead) {
389 if (this->player_ptr->slow && !do_dec) {
390 if (this->player_ptr->slow > v) {
393 } else if (!this->player_ptr->slow) {
394 msg_print(_("体の動きが遅くなってしまった!", "You feel yourself moving slower!"));
398 if (this->player_ptr->slow) {
399 msg_print(_("動きの遅さがなくなったようだ。", "You feel yourself speed up."));
404 this->player_ptr->slow = v;
410 disturb(this->player_ptr, false, false);
413 this->player_ptr->update |= PU_BONUS;
414 handle_stuff(this->player_ptr);
418 bool BadStatusSetter::mod_slowness(const TIME_EFFECT tmp_v, bool do_dec)
420 return this->slowness(this->player_ptr->slow + tmp_v, do_dec);
424 * @brief 朦朧の継続時間をセットする / Set "stun", notice observable changes
426 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
428 * Note the special code to only notice "range" changes.
430 bool BadStatusSetter::stun(const TIME_EFFECT tmp_v)
432 auto v = std::clamp<short>(tmp_v, 0, 10000);
433 if (this->player_ptr->is_dead) {
437 if (PlayerRace(this->player_ptr).equals(player_race_type::GOLEM) || PlayerClass(this->player_ptr).can_resist_stun()) {
441 auto notice = this->process_stun_effect(v);
442 this->player_ptr->effects()->stun()->set(v);
448 disturb(this->player_ptr, false, false);
451 this->player_ptr->update |= PU_BONUS;
452 this->player_ptr->redraw |= PR_STUN;
453 handle_stuff(this->player_ptr);
457 bool BadStatusSetter::mod_stun(const TIME_EFFECT tmp_v)
459 return this->stun(this->player_ptr->effects()->stun()->current() + tmp_v);
463 * @brief 出血の継続時間をセットする / Set "cut", notice observable changes
465 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
467 * Note the special code to only notice "range" changes.
469 bool BadStatusSetter::cut(const TIME_EFFECT tmp_v)
471 auto v = std::clamp<short>(tmp_v, 0, 10000);
472 if (this->player_ptr->is_dead) {
476 if (PlayerRace(this->player_ptr).can_resist_cut() && !this->player_ptr->mimic_form) {
480 auto notice = this->process_cut_effect(v);
481 this->player_ptr->effects()->cut()->set(v);
487 disturb(this->player_ptr, false, false);
490 this->player_ptr->update |= PU_BONUS;
491 this->player_ptr->redraw |= PR_CUT;
492 handle_stuff(this->player_ptr);
496 bool BadStatusSetter::mod_cut(const TIME_EFFECT tmp_v)
498 return this->cut(this->player_ptr->effects()->cut()->current() + tmp_v);
501 bool BadStatusSetter::process_stun_effect(const short v)
503 auto old_rank = this->player_ptr->effects()->stun()->get_rank();
504 auto new_rank = PlayerStun::get_rank(v);
505 if (new_rank > old_rank) {
506 this->process_stun_status(new_rank, v);
510 if (new_rank < old_rank) {
518 void BadStatusSetter::process_stun_status(const PlayerStunRank new_rank, const short v)
520 auto stun_mes = PlayerStun::get_stun_mes(new_rank);
521 msg_print(stun_mes.data());
522 this->decrease_int_wis(v);
523 if (PlayerClass(this->player_ptr).lose_balance()) {
524 msg_print(_("型が崩れた。", "You lose your stance."));
527 reset_concentration(this->player_ptr, true);
529 SpellHex spell_hex(this->player_ptr);
530 if (spell_hex.is_spelling_any()) {
531 (void)spell_hex.stop_all_spells();
535 void BadStatusSetter::clear_head()
537 if (this->player_ptr->effects()->stun()->is_stunned()) {
541 msg_print(_("やっと朦朧状態から回復した。", "You are no longer stunned."));
543 disturb(this->player_ptr, false, false);
548 * @todo 後で知能と賢さが両方減る確率を減らす.
550 void BadStatusSetter::decrease_int_wis(const short v)
552 if ((v <= randint1(1000)) && !one_in_(16)) {
556 msg_print(_("割れるような頭痛がする。", "A vicious blow hits your head."));
557 auto rand = randint0(5);
560 if (has_sustain_int(this->player_ptr) == 0) {
561 (void)do_dec_stat(this->player_ptr, A_INT);
564 if (has_sustain_wis(this->player_ptr) == 0) {
565 (void)do_dec_stat(this->player_ptr, A_WIS);
571 if (has_sustain_int(this->player_ptr) == 0) {
572 (void)do_dec_stat(this->player_ptr, A_INT);
578 if (has_sustain_wis(this->player_ptr) == 0) {
579 (void)do_dec_stat(this->player_ptr, A_WIS);
584 throw("Invalid random number is specified!");
588 bool BadStatusSetter::process_cut_effect(const short v)
590 auto player_cut = this->player_ptr->effects()->cut();
591 auto old_rank = player_cut->get_rank();
592 auto new_rank = player_cut->get_rank(v);
593 if (new_rank > old_rank) {
594 this->decrease_charisma(new_rank, v);
598 if (new_rank < old_rank) {
599 this->stop_blooding(new_rank);
606 void BadStatusSetter::decrease_charisma(const PlayerCutRank new_rank, const short v)
608 auto player_cut = this->player_ptr->effects()->cut();
609 auto cut_mes = player_cut->get_cut_mes(new_rank);
610 msg_print(cut_mes.data());
611 if (v <= randint1(1000) && !one_in_(16)) {
615 if (has_sustain_chr(this->player_ptr)) {
619 msg_print(_("ひどい傷跡が残ってしまった。", "You have been horribly scarred."));
620 do_dec_stat(this->player_ptr, A_CHR);
623 void BadStatusSetter::stop_blooding(const PlayerCutRank new_rank)
625 if (new_rank >= PlayerCutRank::GRAZING) {
629 auto blood_stop_mes = PlayerRace(this->player_ptr).equals(player_race_type::ANDROID)
630 ? _("怪我が直った", "leaking fluid")
631 : _("出血が止まった", "bleeding");
632 msg_format(_("やっと%s。", "You are no longer %s."), blood_stop_mes);
634 disturb(this->player_ptr, false, false);