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);
90 * @brief 混乱の継続時間をセットする / Set "confused", notice observable changes
92 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
94 bool BadStatusSetter::confusion(const TIME_EFFECT tmp_v)
97 auto v = std::clamp<short>(tmp_v, 0, 10000);
98 if (this->player_ptr->is_dead) {
103 if (!this->player_ptr->confused) {
104 msg_print(_("あなたは混乱した!", "You are confused!"));
106 if (this->player_ptr->action == ACTION_LEARN) {
107 msg_print(_("学習が続けられない!", "You cannot continue learning!"));
108 this->player_ptr->new_mane = false;
110 this->player_ptr->redraw |= PR_STATE;
111 this->player_ptr->action = ACTION_NONE;
113 if (this->player_ptr->action == ACTION_KAMAE) {
114 msg_print(_("構えがとけた。", "You lose your stance."));
115 this->player_ptr->special_defense &= ~(KAMAE_MASK);
116 this->player_ptr->update |= PU_BONUS;
117 this->player_ptr->redraw |= PR_STATE;
118 this->player_ptr->action = ACTION_NONE;
119 } else if (this->player_ptr->action == ACTION_KATA) {
120 msg_print(_("型が崩れた。", "You lose your stance."));
121 this->player_ptr->special_defense &= ~(KATA_MASK);
122 this->player_ptr->update |= PU_BONUS;
123 this->player_ptr->update |= PU_MONSTERS;
124 this->player_ptr->redraw |= PR_STATE;
125 this->player_ptr->redraw |= PR_STATUS;
126 this->player_ptr->action = ACTION_NONE;
130 if (this->player_ptr->concent)
131 reset_concentration(this->player_ptr, true);
133 SpellHex spell_hex(this->player_ptr);
134 if (spell_hex.is_spelling_any()) {
135 (void)spell_hex.stop_all_spells();
139 this->player_ptr->counter = false;
140 chg_virtue(this->player_ptr, V_HARMONY, -1);
143 if (this->player_ptr->confused) {
144 msg_print(_("やっと混乱がおさまった。", "You feel less confused now."));
145 this->player_ptr->special_attack &= ~(ATTACK_SUIKEN);
150 this->player_ptr->confused = v;
151 this->player_ptr->redraw |= PR_STATUS;
157 disturb(this->player_ptr, false, false);
160 handle_stuff(this->player_ptr);
165 * @brief 毒の継続時間をセットする / Set "poisoned", notice observable changes
167 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
169 bool BadStatusSetter::poison(const TIME_EFFECT tmp_v)
172 auto v = std::clamp<short>(tmp_v, 0, 10000);
173 if (this->player_ptr->is_dead) {
178 if (!this->player_ptr->poisoned) {
179 msg_print(_("毒に侵されてしまった!", "You are poisoned!"));
183 if (this->player_ptr->poisoned) {
184 msg_print(_("やっと毒の痛みがなくなった。", "You are no longer poisoned."));
189 this->player_ptr->poisoned = v;
190 this->player_ptr->redraw |= PR_STATUS;
196 disturb(this->player_ptr, false, false);
199 handle_stuff(this->player_ptr);
204 * @brief 恐怖の継続時間をセットする / Set "afraid", notice observable changes
206 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
208 bool BadStatusSetter::afraidness(const TIME_EFFECT tmp_v)
211 auto v = std::clamp<short>(tmp_v, 0, 10000);
212 if (this->player_ptr->is_dead) {
217 if (!this->player_ptr->afraid) {
218 msg_print(_("何もかも恐くなってきた!", "You are terrified!"));
219 if (this->player_ptr->special_defense & KATA_MASK) {
220 msg_print(_("型が崩れた。", "You lose your stance."));
221 this->player_ptr->special_defense &= ~(KATA_MASK);
222 this->player_ptr->update |= PU_BONUS;
223 this->player_ptr->update |= PU_MONSTERS;
224 this->player_ptr->redraw |= PR_STATE;
225 this->player_ptr->redraw |= PR_STATUS;
226 this->player_ptr->action = ACTION_NONE;
230 this->player_ptr->counter = false;
231 chg_virtue(this->player_ptr, V_VALOUR, -1);
234 if (this->player_ptr->afraid) {
235 msg_print(_("やっと恐怖を振り払った。", "You feel bolder now."));
240 this->player_ptr->afraid = v;
241 this->player_ptr->redraw |= PR_STATUS;
247 disturb(this->player_ptr, false, false);
250 handle_stuff(this->player_ptr);
255 * @brief 麻痺の継続時間をセットする / Set "paralyzed", notice observable changes
257 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
259 bool BadStatusSetter::paralysis(const TIME_EFFECT tmp_v)
262 auto v = std::clamp<short>(tmp_v, 0, 10000);
263 if (this->player_ptr->is_dead) {
268 if (!this->player_ptr->paralyzed) {
269 msg_print(_("体が麻痺してしまった!", "You are paralyzed!"));
270 if (this->player_ptr->concent) {
271 reset_concentration(this->player_ptr, true);
274 SpellHex spell_hex(this->player_ptr);
275 if (spell_hex.is_spelling_any()) {
276 (void)spell_hex.stop_all_spells();
279 this->player_ptr->counter = false;
283 if (this->player_ptr->paralyzed) {
284 msg_print(_("やっと動けるようになった。", "You can move again."));
289 this->player_ptr->paralyzed = v;
290 this->player_ptr->redraw |= PR_STATUS;
296 disturb(this->player_ptr, false, false);
299 this->player_ptr->redraw |= PR_STATE;
300 handle_stuff(this->player_ptr);
305 * @brief 幻覚の継続時間をセットする / Set "image", notice observable changes
307 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
308 * @details Note that we must redraw the map when hallucination changes.
310 bool BadStatusSetter::hallucination(const TIME_EFFECT tmp_v)
313 auto v = std::clamp<short>(tmp_v, 0, 10000);
314 if (this->player_ptr->is_dead) {
318 if (is_chargeman(this->player_ptr)) {
323 set_tsuyoshi(this->player_ptr, 0, true);
324 if (!this->player_ptr->hallucinated) {
325 msg_print(_("ワーオ!何もかも虹色に見える!", "Oh, wow! Everything looks so cosmic now!"));
326 if (this->player_ptr->concent) {
327 reset_concentration(this->player_ptr, true);
330 this->player_ptr->counter = false;
334 if (this->player_ptr->hallucinated) {
335 msg_print(_("やっとはっきりと物が見えるようになった。", "You can see clearly again."));
340 this->player_ptr->hallucinated = v;
341 this->player_ptr->redraw |= PR_STATUS;
347 disturb(this->player_ptr, false, true);
350 this->player_ptr->redraw |= PR_MAP | PR_HEALTH | PR_UHEALTH;
351 this->player_ptr->update |= PU_MONSTERS;
352 this->player_ptr->window_flags |= PW_OVERHEAD | PW_DUNGEON;
353 handle_stuff(this->player_ptr);
358 * @brief 減速の継続時間をセットする / Set "slow", notice observable changes
360 * @param do_dec 現在の継続時間より長い値のみ上書きする
361 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
363 bool BadStatusSetter::slowness(const TIME_EFFECT tmp_v, bool do_dec)
366 auto v = std::clamp<short>(tmp_v, 0, 10000);
367 if (this->player_ptr->is_dead) {
372 if (this->player_ptr->slow && !do_dec) {
373 if (this->player_ptr->slow > v) {
376 } else if (!this->player_ptr->slow) {
377 msg_print(_("体の動きが遅くなってしまった!", "You feel yourself moving slower!"));
381 if (this->player_ptr->slow) {
382 msg_print(_("動きの遅さがなくなったようだ。", "You feel yourself speed up."));
387 this->player_ptr->slow = v;
393 disturb(this->player_ptr, false, false);
396 this->player_ptr->update |= PU_BONUS;
397 handle_stuff(this->player_ptr);
402 * @brief 朦朧の継続時間をセットする / Set "stun", notice observable changes
404 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
406 * Note the special code to only notice "range" changes.
408 bool BadStatusSetter::stun(const TIME_EFFECT tmp_v)
411 auto v = std::clamp<short>(tmp_v, 0, 10000);
412 if (this->player_ptr->is_dead) {
416 if (PlayerRace(this->player_ptr).equals(player_race_type::GOLEM) || PlayerClass(this->player_ptr).can_resist_stun()) {
420 auto player_stun = this->player_ptr->effects()->stun();
421 auto old_aux = player_stun->get_rank();
422 auto new_aux = PlayerStun::get_rank(v);
423 if (new_aux > old_aux) {
424 auto stun_mes = PlayerStun::get_stun_mes(new_aux);
425 msg_print(stun_mes.data());
426 if (randint1(1000) < v || one_in_(16)) {
427 msg_print(_("割れるような頭痛がする。", "A vicious blow hits your head."));
429 if (!has_sustain_int(this->player_ptr))
430 (void)do_dec_stat(this->player_ptr, A_INT);
431 if (!has_sustain_wis(this->player_ptr))
432 (void)do_dec_stat(this->player_ptr, A_WIS);
433 } else if (one_in_(2)) {
434 if (!has_sustain_int(this->player_ptr))
435 (void)do_dec_stat(this->player_ptr, A_INT);
437 if (!has_sustain_wis(this->player_ptr))
438 (void)do_dec_stat(this->player_ptr, A_WIS);
442 if (this->player_ptr->special_defense & KATA_MASK) {
443 msg_print(_("型が崩れた。", "You lose your stance."));
444 this->player_ptr->special_defense &= ~(KATA_MASK);
445 this->player_ptr->update |= PU_BONUS;
446 this->player_ptr->update |= PU_MONSTERS;
447 this->player_ptr->redraw |= PR_STATE;
448 this->player_ptr->redraw |= PR_STATUS;
449 this->player_ptr->action = ACTION_NONE;
452 if (this->player_ptr->concent) {
453 reset_concentration(this->player_ptr, true);
456 SpellHex spell_hex(this->player_ptr);
457 if (spell_hex.is_spelling_any()) {
458 (void)spell_hex.stop_all_spells();
462 } else if (new_aux < old_aux) {
463 if (new_aux == PlayerStunRank::NONE) {
464 msg_print(_("やっと朦朧状態から回復した。", "You are no longer stunned."));
466 disturb(this->player_ptr, false, false);
479 disturb(this->player_ptr, false, false);
482 this->player_ptr->update |= PU_BONUS;
483 this->player_ptr->redraw |= PR_STUN;
484 handle_stuff(this->player_ptr);
489 * @brief 出血の継続時間をセットする / Set "cut", notice observable changes
491 * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
493 * Note the special code to only notice "range" changes.
495 bool BadStatusSetter::cut(const TIME_EFFECT tmp_v)
497 auto v = std::clamp<short>(tmp_v, 0, 10000);
498 if (this->player_ptr->is_dead) {
502 if (PlayerRace(this->player_ptr).can_resist_cut() && !this->player_ptr->mimic_form) {
506 auto notice = this->process_cut_effect(v);
507 this->player_ptr->cut = v;
513 disturb(this->player_ptr, false, false);
516 this->player_ptr->update |= PU_BONUS;
517 this->player_ptr->redraw |= PR_CUT;
518 handle_stuff(this->player_ptr);
522 bool BadStatusSetter::process_cut_effect(const short v)
524 auto player_cut = this->player_ptr->effects()->cut();
525 auto old_aux = player_cut->get_rank();
526 auto new_aux = player_cut->get_rank(v);
527 if (new_aux > old_aux) {
528 this->decrease_charisma(new_aux, v);
532 if (new_aux < old_aux) {
533 this->stop_blooding(new_aux);
540 void BadStatusSetter::decrease_charisma(const PlayerCutRank new_aux, const short v)
542 auto player_cut = this->player_ptr->effects()->cut();
543 auto cut_mes = player_cut->get_cut_mes(new_aux);
544 msg_print(cut_mes.data());
545 if (v <= randint1(1000) && !one_in_(16)) {
549 if (has_sustain_chr(this->player_ptr)) {
553 msg_print(_("ひどい傷跡が残ってしまった。", "You have been horribly scarred."));
554 do_dec_stat(this->player_ptr, A_CHR);
557 void BadStatusSetter::stop_blooding(const PlayerCutRank new_aux)
559 if (new_aux >= PlayerCutRank::GRAZING) {
563 auto blood_stop_mes = PlayerRace(this->player_ptr).equals(player_race_type::ANDROID)
564 ? _("怪我が直った", "leaking fluid")
565 : _("出血が止まった", "bleeding");
566 msg_format(_("やっと%s。", "You are no longer %s."), blood_stop_mes);
568 disturb(this->player_ptr, false, false);