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/attack-defense-types.h"
13 #include "player/player-status-flags.h"
14 #include "player/player-status.h"
15 #include "player/special-defense-types.h"
16 #include "spell-realm/spells-hex.h"
17 #include "status/base-status.h"
18 #include "status/buff-setter.h"
19 #include "system/player-type-definition.h"
20 #include "timed-effect/player-cut.h"
21 #include "timed-effect/player-stun.h"
22 #include "timed-effect/timed-effects.h"
23 #include "view/display-messages.h"
26 BadStatusSetter::BadStatusSetter(player_type *player_ptr)
27 : player_ptr(player_ptr)
32 * @brief 盲目の継続時間をセットする / Set "blind", notice observable changes
34 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
36 * Note the use of "PU_UN_LITE" and "PU_UN_VIEW", which is needed to\n
37 * memorize any terrain features which suddenly become "visible".\n
38 * Note that blindness is currently the only thing which can affect\n
39 * "player_can_see_bold()".\n
41 bool BadStatusSetter::blindness(const TIME_EFFECT tmp_v)
44 auto v = std::clamp<short>(tmp_v, 0, 10000);
45 if (this->player_ptr->is_dead) {
50 if (!this->player_ptr->blind) {
51 if (this->player_ptr->prace == player_race_type::ANDROID) {
52 msg_print(_("センサーをやられた!", "The sensor broke!"));
54 msg_print(_("目が見えなくなってしまった!", "You are blind!"));
58 chg_virtue(this->player_ptr, V_ENLIGHTEN, -1);
61 if (this->player_ptr->blind) {
62 if (this->player_ptr->prace == player_race_type::ANDROID) {
63 msg_print(_("センサーが復旧した。", "The sensor has been restored."));
65 msg_print(_("やっと目が見えるようになった。", "You can see again."));
72 this->player_ptr->blind = v;
73 this->player_ptr->redraw |= PR_STATUS;
79 disturb(this->player_ptr, false, false);
82 this->player_ptr->update |= PU_UN_VIEW | PU_UN_LITE | PU_VIEW | PU_LITE | PU_MONSTERS | PU_MON_LITE;
83 this->player_ptr->redraw |= PR_MAP;
84 this->player_ptr->window_flags |= PW_OVERHEAD | PW_DUNGEON;
85 handle_stuff(this->player_ptr);
89 bool BadStatusSetter::mod_blindness(const TIME_EFFECT tmp_v)
91 return this->blindness(this->player_ptr->blind + tmp_v);
95 * @brief 混乱の継続時間をセットする / Set "confused", notice observable changes
97 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
99 bool BadStatusSetter::confusion(const TIME_EFFECT tmp_v)
102 auto v = std::clamp<short>(tmp_v, 0, 10000);
103 if (this->player_ptr->is_dead) {
108 if (!this->player_ptr->confused) {
109 msg_print(_("あなたは混乱した!", "You are confused!"));
111 if (this->player_ptr->action == ACTION_LEARN) {
112 msg_print(_("学習が続けられない!", "You cannot continue learning!"));
113 this->player_ptr->new_mane = false;
115 this->player_ptr->redraw |= PR_STATE;
116 this->player_ptr->action = ACTION_NONE;
118 if (this->player_ptr->action == ACTION_KAMAE) {
119 msg_print(_("構えがとけた。", "You lose your stance."));
120 this->player_ptr->special_defense &= ~(KAMAE_MASK);
121 this->player_ptr->update |= PU_BONUS;
122 this->player_ptr->redraw |= PR_STATE;
123 this->player_ptr->action = ACTION_NONE;
124 } else if (this->player_ptr->action == ACTION_KATA) {
125 msg_print(_("型が崩れた。", "You lose your stance."));
126 this->player_ptr->special_defense &= ~(KATA_MASK);
127 this->player_ptr->update |= PU_BONUS;
128 this->player_ptr->update |= PU_MONSTERS;
129 this->player_ptr->redraw |= PR_STATE;
130 this->player_ptr->redraw |= PR_STATUS;
131 this->player_ptr->action = ACTION_NONE;
135 if (this->player_ptr->concent)
136 reset_concentration(this->player_ptr, true);
138 SpellHex spell_hex(this->player_ptr);
139 if (spell_hex.is_spelling_any()) {
140 (void)spell_hex.stop_all_spells();
144 this->player_ptr->counter = false;
145 chg_virtue(this->player_ptr, V_HARMONY, -1);
148 if (this->player_ptr->confused) {
149 msg_print(_("やっと混乱がおさまった。", "You feel less confused now."));
150 this->player_ptr->special_attack &= ~(ATTACK_SUIKEN);
155 this->player_ptr->confused = v;
156 this->player_ptr->redraw |= PR_STATUS;
162 disturb(this->player_ptr, false, false);
165 handle_stuff(this->player_ptr);
170 * @brief 毒の継続時間をセットする / Set "poisoned", notice observable changes
172 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
174 bool BadStatusSetter::poison(const TIME_EFFECT tmp_v)
177 auto v = std::clamp<short>(tmp_v, 0, 10000);
178 if (this->player_ptr->is_dead) {
183 if (!this->player_ptr->poisoned) {
184 msg_print(_("毒に侵されてしまった!", "You are poisoned!"));
188 if (this->player_ptr->poisoned) {
189 msg_print(_("やっと毒の痛みがなくなった。", "You are no longer poisoned."));
194 this->player_ptr->poisoned = v;
195 this->player_ptr->redraw |= PR_STATUS;
201 disturb(this->player_ptr, false, false);
204 handle_stuff(this->player_ptr);
209 * @brief 恐怖の継続時間をセットする / Set "afraid", notice observable changes
211 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
213 bool BadStatusSetter::afraidness(const TIME_EFFECT tmp_v)
216 auto v = std::clamp<short>(tmp_v, 0, 10000);
217 if (this->player_ptr->is_dead) {
222 if (!this->player_ptr->afraid) {
223 msg_print(_("何もかも恐くなってきた!", "You are terrified!"));
224 if (this->player_ptr->special_defense & KATA_MASK) {
225 msg_print(_("型が崩れた。", "You lose your stance."));
226 this->player_ptr->special_defense &= ~(KATA_MASK);
227 this->player_ptr->update |= PU_BONUS;
228 this->player_ptr->update |= PU_MONSTERS;
229 this->player_ptr->redraw |= PR_STATE;
230 this->player_ptr->redraw |= PR_STATUS;
231 this->player_ptr->action = ACTION_NONE;
235 this->player_ptr->counter = false;
236 chg_virtue(this->player_ptr, V_VALOUR, -1);
239 if (this->player_ptr->afraid) {
240 msg_print(_("やっと恐怖を振り払った。", "You feel bolder now."));
245 this->player_ptr->afraid = v;
246 this->player_ptr->redraw |= PR_STATUS;
252 disturb(this->player_ptr, false, false);
255 handle_stuff(this->player_ptr);
260 * @brief 麻痺の継続時間をセットする / Set "paralyzed", notice observable changes
262 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
264 bool BadStatusSetter::paralysis(const TIME_EFFECT tmp_v)
267 auto v = std::clamp<short>(tmp_v, 0, 10000);
268 if (this->player_ptr->is_dead) {
273 if (!this->player_ptr->paralyzed) {
274 msg_print(_("体が麻痺してしまった!", "You are paralyzed!"));
275 if (this->player_ptr->concent) {
276 reset_concentration(this->player_ptr, true);
279 SpellHex spell_hex(this->player_ptr);
280 if (spell_hex.is_spelling_any()) {
281 (void)spell_hex.stop_all_spells();
284 this->player_ptr->counter = false;
288 if (this->player_ptr->paralyzed) {
289 msg_print(_("やっと動けるようになった。", "You can move again."));
294 this->player_ptr->paralyzed = v;
295 this->player_ptr->redraw |= PR_STATUS;
301 disturb(this->player_ptr, false, false);
304 this->player_ptr->redraw |= PR_STATE;
305 handle_stuff(this->player_ptr);
310 * @brief 幻覚の継続時間をセットする / Set "image", notice observable changes
312 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
313 * @details Note that we must redraw the map when hallucination changes.
315 bool BadStatusSetter::hallucination(const TIME_EFFECT tmp_v)
318 auto v = std::clamp<short>(tmp_v, 0, 10000);
319 if (this->player_ptr->is_dead) {
323 if (is_chargeman(this->player_ptr)) {
328 set_tsuyoshi(this->player_ptr, 0, true);
329 if (!this->player_ptr->hallucinated) {
330 msg_print(_("ワーオ!何もかも虹色に見える!", "Oh, wow! Everything looks so cosmic now!"));
331 if (this->player_ptr->concent) {
332 reset_concentration(this->player_ptr, true);
335 this->player_ptr->counter = false;
339 if (this->player_ptr->hallucinated) {
340 msg_print(_("やっとはっきりと物が見えるようになった。", "You can see clearly again."));
345 this->player_ptr->hallucinated = v;
346 this->player_ptr->redraw |= PR_STATUS;
352 disturb(this->player_ptr, false, true);
355 this->player_ptr->redraw |= PR_MAP | PR_HEALTH | PR_UHEALTH;
356 this->player_ptr->update |= PU_MONSTERS;
357 this->player_ptr->window_flags |= PW_OVERHEAD | PW_DUNGEON;
358 handle_stuff(this->player_ptr);
363 * @brief 減速の継続時間をセットする / Set "slow", notice observable changes
365 * @param do_dec 現在の継続時間より長い値のみ上書きする
366 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
368 bool BadStatusSetter::slowness(const TIME_EFFECT tmp_v, bool do_dec)
371 auto v = std::clamp<short>(tmp_v, 0, 10000);
372 if (this->player_ptr->is_dead) {
377 if (this->player_ptr->slow && !do_dec) {
378 if (this->player_ptr->slow > v) {
381 } else if (!this->player_ptr->slow) {
382 msg_print(_("体の動きが遅くなってしまった!", "You feel yourself moving slower!"));
386 if (this->player_ptr->slow) {
387 msg_print(_("動きの遅さがなくなったようだ。", "You feel yourself speed up."));
392 this->player_ptr->slow = v;
398 disturb(this->player_ptr, false, false);
401 this->player_ptr->update |= PU_BONUS;
402 handle_stuff(this->player_ptr);
407 * @brief 朦朧の継続時間をセットする / Set "stun", notice observable changes
409 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
411 * Note the special code to only notice "range" changes.
413 bool BadStatusSetter::stun(const TIME_EFFECT tmp_v)
415 auto v = std::clamp<short>(tmp_v, 0, 10000);
416 if (this->player_ptr->is_dead) {
420 if (PlayerRace(this->player_ptr).equals(player_race_type::GOLEM) || PlayerClass(this->player_ptr).can_resist_stun()) {
424 auto notice = this->process_stun_effect(v);
425 this->player_ptr->effects()->stun()->set(v);
431 disturb(this->player_ptr, false, false);
434 this->player_ptr->update |= PU_BONUS;
435 this->player_ptr->redraw |= PR_STUN;
436 handle_stuff(this->player_ptr);
441 * @brief 出血の継続時間をセットする / Set "cut", notice observable changes
443 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
445 * Note the special code to only notice "range" changes.
447 bool BadStatusSetter::cut(const TIME_EFFECT tmp_v)
449 auto v = std::clamp<short>(tmp_v, 0, 10000);
450 if (this->player_ptr->is_dead) {
454 if (PlayerRace(this->player_ptr).can_resist_cut() && !this->player_ptr->mimic_form) {
458 auto notice = this->process_cut_effect(v);
459 this->player_ptr->effects()->cut()->set(v);
465 disturb(this->player_ptr, false, false);
468 this->player_ptr->update |= PU_BONUS;
469 this->player_ptr->redraw |= PR_CUT;
470 handle_stuff(this->player_ptr);
474 bool BadStatusSetter::process_stun_effect(const short v)
476 auto old_rank = this->player_ptr->effects()->stun()->get_rank();
477 auto new_rank = PlayerStun::get_rank(v);
478 if (new_rank > old_rank) {
479 this->process_stun_status(new_rank, v);
483 if (new_rank < old_rank) {
484 this->clear_head(new_rank);
491 void BadStatusSetter::process_stun_status(const PlayerStunRank new_rank, const short v)
493 auto stun_mes = PlayerStun::get_stun_mes(new_rank);
494 msg_print(stun_mes.data());
495 this->decrease_int_wis(v);
496 if (PlayerClass(this->player_ptr).lose_balance()) {
497 msg_print(_("型が崩れた。", "You lose your stance."));
500 if (this->player_ptr->concent) {
501 reset_concentration(this->player_ptr, true);
504 SpellHex spell_hex(this->player_ptr);
505 if (spell_hex.is_spelling_any()) {
506 (void)spell_hex.stop_all_spells();
510 void BadStatusSetter::clear_head(const PlayerStunRank new_rank)
512 if (new_rank >= PlayerStunRank::NORMAL) {
516 msg_print(_("やっと朦朧状態から回復した。", "You are no longer stunned."));
518 disturb(this->player_ptr, false, false);
523 * @todo 後で知能と賢さが両方減る確率を減らす.
525 void BadStatusSetter::decrease_int_wis(const short v)
527 if ((v <= randint1(1000)) && !one_in_(16)) {
531 msg_print(_("割れるような頭痛がする。", "A vicious blow hits your head."));
532 auto rand = randint0(3);
535 if (has_sustain_int(this->player_ptr) == 0) {
536 (void)do_dec_stat(this->player_ptr, A_INT);
539 if (has_sustain_wis(this->player_ptr) == 0) {
540 (void)do_dec_stat(this->player_ptr, A_WIS);
545 if (has_sustain_int(this->player_ptr) == 0) {
546 (void)do_dec_stat(this->player_ptr, A_INT);
551 if (has_sustain_wis(this->player_ptr) == 0) {
552 (void)do_dec_stat(this->player_ptr, A_WIS);
561 bool BadStatusSetter::process_cut_effect(const short v)
563 auto player_cut = this->player_ptr->effects()->cut();
564 auto old_rank = player_cut->get_rank();
565 auto new_rank = player_cut->get_rank(v);
566 if (new_rank > old_rank) {
567 this->decrease_charisma(new_rank, v);
571 if (new_rank < old_rank) {
572 this->stop_blooding(new_rank);
579 void BadStatusSetter::decrease_charisma(const PlayerCutRank new_rank, const short v)
581 auto player_cut = this->player_ptr->effects()->cut();
582 auto cut_mes = player_cut->get_cut_mes(new_rank);
583 msg_print(cut_mes.data());
584 if (v <= randint1(1000) && !one_in_(16)) {
588 if (has_sustain_chr(this->player_ptr)) {
592 msg_print(_("ひどい傷跡が残ってしまった。", "You have been horribly scarred."));
593 do_dec_stat(this->player_ptr, A_CHR);
596 void BadStatusSetter::stop_blooding(const PlayerCutRank new_rank)
598 if (new_rank >= PlayerCutRank::GRAZING) {
602 auto blood_stop_mes = PlayerRace(this->player_ptr).equals(player_race_type::ANDROID)
603 ? _("怪我が直った", "leaking fluid")
604 : _("出血が止まった", "bleeding");
605 msg_format(_("やっと%s。", "You are no longer %s."), blood_stop_mes);
607 disturb(this->player_ptr, false, false);