OSDN Git Service

[Refactor] #2523 PlayerType::blind をPlayerBlindnessの呼び出しに差し替えた
[hengbandforosx/hengbandosx.git] / src / status / bad-status-setter.cpp
index d91fca0..47ffb3b 100644 (file)
@@ -9,6 +9,8 @@
 #include "mind/mind-sniper.h"
 #include "player-base/player-class.h"
 #include "player-base/player-race.h"
+#include "player-info/bluemage-data-type.h"
+#include "player-info/monk-data-type.h"
 #include "player/attack-defense-types.h"
 #include "player/player-status-flags.h"
 #include "player/player-status.h"
 #include "status/base-status.h"
 #include "status/buff-setter.h"
 #include "system/player-type-definition.h"
+#include "timed-effect/player-blindness.h"
+#include "timed-effect/player-confusion.h"
 #include "timed-effect/player-cut.h"
+#include "timed-effect/player-deceleration.h"
+#include "timed-effect/player-fear.h"
+#include "timed-effect/player-hallucination.h"
+#include "timed-effect/player-paralysis.h"
+#include "timed-effect/player-poison.h"
 #include "timed-effect/player-stun.h"
 #include "timed-effect/timed-effects.h"
 #include "view/display-messages.h"
 #include <algorithm>
 
-BadStatusSetter::BadStatusSetter(player_type *player_ptr)
+BadStatusSetter::BadStatusSetter(PlayerType *player_ptr)
     : player_ptr(player_ptr)
+    , player_confusion(player_ptr->effects()->confusion())
 {
 }
 
@@ -46,9 +56,12 @@ bool BadStatusSetter::blindness(const TIME_EFFECT tmp_v)
         return false;
     }
 
+    PlayerRace pr(this->player_ptr);
+    const auto blindness = this->player_ptr->effects()->blindness();
+    const auto is_blind = blindness->is_blind();
     if (v > 0) {
-        if (!this->player_ptr->blind) {
-            if (this->player_ptr->prace == player_race_type::ANDROID) {
+        if (!is_blind) {
+            if (pr.equals(PlayerRaceType::ANDROID)) {
                 msg_print(_("センサーをやられた!", "The sensor broke!"));
             } else {
                 msg_print(_("目が見えなくなってしまった!", "You are blind!"));
@@ -58,8 +71,8 @@ bool BadStatusSetter::blindness(const TIME_EFFECT tmp_v)
             chg_virtue(this->player_ptr, V_ENLIGHTEN, -1);
         }
     } else {
-        if (this->player_ptr->blind) {
-            if (this->player_ptr->prace == player_race_type::ANDROID) {
+        if (is_blind) {
+            if (pr.equals(PlayerRaceType::ANDROID)) {
                 msg_print(_("センサーが復旧した。", "The sensor has been restored."));
             } else {
                 msg_print(_("やっと目が見えるようになった。", "You can see again."));
@@ -69,7 +82,7 @@ bool BadStatusSetter::blindness(const TIME_EFFECT tmp_v)
         }
     }
 
-    this->player_ptr->blind = v;
+    blindness->set(v);
     this->player_ptr->redraw |= PR_STATUS;
     if (!notice) {
         return false;
@@ -86,6 +99,11 @@ bool BadStatusSetter::blindness(const TIME_EFFECT tmp_v)
     return true;
 }
 
+bool BadStatusSetter::mod_blindness(const TIME_EFFECT tmp_v)
+{
+    return this->blindness(this->player_ptr->effects()->blindness()->current() + tmp_v);
+}
+
 /*!
  * @brief 混乱の継続時間をセットする / Set "confused", notice observable changes
  * @param v 継続時間
@@ -99,36 +117,32 @@ bool BadStatusSetter::confusion(const TIME_EFFECT tmp_v)
         return false;
     }
 
+    auto is_confused = this->player_confusion->is_confused();
     if (v > 0) {
-        if (!this->player_ptr->confused) {
+        if (!is_confused) {
             msg_print(_("あなたは混乱した!", "You are confused!"));
 
             if (this->player_ptr->action == ACTION_LEARN) {
                 msg_print(_("学習が続けられない!", "You cannot continue learning!"));
-                this->player_ptr->new_mane = false;
+                auto bluemage_data = PlayerClass(player_ptr).get_specific_data<bluemage_data_type>();
+                bluemage_data->new_magic_learned = false;
 
                 this->player_ptr->redraw |= PR_STATE;
                 this->player_ptr->action = ACTION_NONE;
             }
-            if (this->player_ptr->action == ACTION_KAMAE) {
+            if (this->player_ptr->action == ACTION_MONK_STANCE) {
                 msg_print(_("構えがとけた。", "You lose your stance."));
-                this->player_ptr->special_defense &= ~(KAMAE_MASK);
+                PlayerClass(player_ptr).set_monk_stance(MonkStanceType::NONE);
                 this->player_ptr->update |= PU_BONUS;
                 this->player_ptr->redraw |= PR_STATE;
                 this->player_ptr->action = ACTION_NONE;
-            } else if (this->player_ptr->action == ACTION_KATA) {
+            } else if (this->player_ptr->action == ACTION_SAMURAI_STANCE) {
                 msg_print(_("型が崩れた。", "You lose your stance."));
-                this->player_ptr->special_defense &= ~(KATA_MASK);
-                this->player_ptr->update |= PU_BONUS;
-                this->player_ptr->update |= PU_MONSTERS;
-                this->player_ptr->redraw |= PR_STATE;
-                this->player_ptr->redraw |= PR_STATUS;
-                this->player_ptr->action = ACTION_NONE;
+                PlayerClass(player_ptr).lose_balance();
             }
 
             /* Sniper */
-            if (this->player_ptr->concent)
-                reset_concentration(this->player_ptr, true);
+            reset_concentration(this->player_ptr, true);
 
             SpellHex spell_hex(this->player_ptr);
             if (spell_hex.is_spelling_any()) {
@@ -140,14 +154,14 @@ bool BadStatusSetter::confusion(const TIME_EFFECT tmp_v)
             chg_virtue(this->player_ptr, V_HARMONY, -1);
         }
     } else {
-        if (this->player_ptr->confused) {
+        if (is_confused) {
             msg_print(_("やっと混乱がおさまった。", "You feel less confused now."));
             this->player_ptr->special_attack &= ~(ATTACK_SUIKEN);
             notice = true;
         }
     }
 
-    this->player_ptr->confused = v;
+    this->player_confusion->set(v);
     this->player_ptr->redraw |= PR_STATUS;
     if (!notice) {
         return false;
@@ -161,12 +175,17 @@ bool BadStatusSetter::confusion(const TIME_EFFECT tmp_v)
     return true;
 }
 
+bool BadStatusSetter::mod_confusion(const TIME_EFFECT tmp_v)
+{
+    return this->confusion(this->player_confusion->current() + tmp_v);
+}
+
 /*!
  * @brief 毒の継続時間をセットする / Set "poisoned", notice observable changes
  * @param v 継続時間
  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
  */
-bool BadStatusSetter::poison(const TIME_EFFECT tmp_v)
+bool BadStatusSetter::set_poison(const TIME_EFFECT tmp_v)
 {
     auto notice = false;
     auto v = std::clamp<short>(tmp_v, 0, 10000);
@@ -174,19 +193,21 @@ bool BadStatusSetter::poison(const TIME_EFFECT tmp_v)
         return false;
     }
 
+    const auto player_poison = this->player_ptr->effects()->poison();
+    const auto is_poisoned = player_poison->is_poisoned();
     if (v > 0) {
-        if (!this->player_ptr->poisoned) {
+        if (!is_poisoned) {
             msg_print(_("毒に侵されてしまった!", "You are poisoned!"));
             notice = true;
         }
     } else {
-        if (this->player_ptr->poisoned) {
+        if (is_poisoned) {
             msg_print(_("やっと毒の痛みがなくなった。", "You are no longer poisoned."));
             notice = true;
         }
     }
 
-    this->player_ptr->poisoned = v;
+    player_poison->set(v);
     this->player_ptr->redraw |= PR_STATUS;
     if (!notice) {
         return false;
@@ -200,12 +221,17 @@ bool BadStatusSetter::poison(const TIME_EFFECT tmp_v)
     return true;
 }
 
+bool BadStatusSetter::mod_poison(const TIME_EFFECT tmp_v)
+{
+    return this->set_poison(this->player_ptr->effects()->poison()->current() + tmp_v);
+}
+
 /*!
- * @brief 恐怖の継続時間をセットする / Set "afraid", notice observable changes
+ * @brief 恐怖の継続時間をセットする / Set "fearful", notice observable changes
  * @param v 継続時間
  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
  */
-bool BadStatusSetter::afraidness(const TIME_EFFECT tmp_v)
+bool BadStatusSetter::fear(const TIME_EFFECT tmp_v)
 {
     auto notice = false;
     auto v = std::clamp<short>(tmp_v, 0, 10000);
@@ -213,17 +239,12 @@ bool BadStatusSetter::afraidness(const TIME_EFFECT tmp_v)
         return false;
     }
 
+    auto fear = this->player_ptr->effects()->fear();
     if (v > 0) {
-        if (!this->player_ptr->afraid) {
+        if (!fear->is_fearful()) {
             msg_print(_("何もかも恐くなってきた!", "You are terrified!"));
-            if (this->player_ptr->special_defense & KATA_MASK) {
+            if (PlayerClass(this->player_ptr).lose_balance()) {
                 msg_print(_("型が崩れた。", "You lose your stance."));
-                this->player_ptr->special_defense &= ~(KATA_MASK);
-                this->player_ptr->update |= PU_BONUS;
-                this->player_ptr->update |= PU_MONSTERS;
-                this->player_ptr->redraw |= PR_STATE;
-                this->player_ptr->redraw |= PR_STATUS;
-                this->player_ptr->action = ACTION_NONE;
             }
 
             notice = true;
@@ -231,13 +252,13 @@ bool BadStatusSetter::afraidness(const TIME_EFFECT tmp_v)
             chg_virtue(this->player_ptr, V_VALOUR, -1);
         }
     } else {
-        if (this->player_ptr->afraid) {
+        if (fear->is_fearful()) {
             msg_print(_("やっと恐怖を振り払った。", "You feel bolder now."));
             notice = true;
         }
     }
 
-    this->player_ptr->afraid = v;
+    fear->set(v);
     this->player_ptr->redraw |= PR_STATUS;
     if (!notice) {
         return false;
@@ -251,6 +272,11 @@ bool BadStatusSetter::afraidness(const TIME_EFFECT tmp_v)
     return true;
 }
 
+bool BadStatusSetter::mod_fear(const TIME_EFFECT tmp_v)
+{
+    return this->fear(this->player_ptr->effects()->fear()->current() + tmp_v);
+}
+
 /*!
  * @brief 麻痺の継続時間をセットする / Set "paralyzed", notice observable changes
  * @param v 継続時間
@@ -264,12 +290,11 @@ bool BadStatusSetter::paralysis(const TIME_EFFECT tmp_v)
         return false;
     }
 
+    auto paralysis = this->player_ptr->effects()->paralysis();
     if (v > 0) {
-        if (!this->player_ptr->paralyzed) {
+        if (!paralysis->is_paralyzed()) {
             msg_print(_("体が麻痺してしまった!", "You are paralyzed!"));
-            if (this->player_ptr->concent) {
-                reset_concentration(this->player_ptr, true);
-            }
+            reset_concentration(this->player_ptr, true);
 
             SpellHex spell_hex(this->player_ptr);
             if (spell_hex.is_spelling_any()) {
@@ -280,13 +305,13 @@ bool BadStatusSetter::paralysis(const TIME_EFFECT tmp_v)
             notice = true;
         }
     } else {
-        if (this->player_ptr->paralyzed) {
+        if (paralysis->is_paralyzed()) {
             msg_print(_("やっと動けるようになった。", "You can move again."));
             notice = true;
         }
     }
 
-    this->player_ptr->paralyzed = v;
+    paralysis->set(v);
     this->player_ptr->redraw |= PR_STATUS;
     if (!notice) {
         return false;
@@ -301,6 +326,11 @@ bool BadStatusSetter::paralysis(const TIME_EFFECT tmp_v)
     return true;
 }
 
+bool BadStatusSetter::mod_paralysis(const TIME_EFFECT tmp_v)
+{
+    return this->paralysis(this->player_ptr->effects()->paralysis()->current() + tmp_v);
+}
+
 /*!
  * @brief 幻覚の継続時間をセットする / Set "image", notice observable changes
  * @param v 継続時間
@@ -319,25 +349,24 @@ bool BadStatusSetter::hallucination(const TIME_EFFECT tmp_v)
         v = 0;
     }
 
+    auto hallucination = this->player_ptr->effects()->hallucination();
     if (v > 0) {
         set_tsuyoshi(this->player_ptr, 0, true);
-        if (!this->player_ptr->hallucinated) {
+        if (!hallucination->is_hallucinated()) {
             msg_print(_("ワーオ!何もかも虹色に見える!", "Oh, wow! Everything looks so cosmic now!"));
-            if (this->player_ptr->concent) {
-                reset_concentration(this->player_ptr, true);
-            }
+            reset_concentration(this->player_ptr, true);
 
             this->player_ptr->counter = false;
             notice = true;
         }
     } else {
-        if (this->player_ptr->hallucinated) {
+        if (hallucination->is_hallucinated()) {
             msg_print(_("やっとはっきりと物が見えるようになった。", "You can see clearly again."));
             notice = true;
         }
     }
 
-    this->player_ptr->hallucinated = v;
+    hallucination->set(v);
     this->player_ptr->redraw |= PR_STATUS;
     if (!notice) {
         return false;
@@ -354,13 +383,18 @@ bool BadStatusSetter::hallucination(const TIME_EFFECT tmp_v)
     return true;
 }
 
+bool BadStatusSetter::mod_hallucination(const TIME_EFFECT tmp_v)
+{
+    return this->hallucination(this->player_ptr->effects()->hallucination()->current() + tmp_v);
+}
+
 /*!
  * @brief 減速の継続時間をセットする / Set "slow", notice observable changes
  * @param v 継続時間
  * @param do_dec 現在の継続時間より長い値のみ上書きする
  * @return ステータスに影響を及ぼす変化があった場合TRUEを返す。
  */
-bool BadStatusSetter::slowness(const TIME_EFFECT tmp_v, bool do_dec)
+bool BadStatusSetter::set_deceleration(const TIME_EFFECT tmp_v, bool do_dec)
 {
     auto notice = false;
     auto v = std::clamp<short>(tmp_v, 0, 10000);
@@ -368,23 +402,25 @@ bool BadStatusSetter::slowness(const TIME_EFFECT tmp_v, bool do_dec)
         return false;
     }
 
+    auto deceleration = this->player_ptr->effects()->deceleration();
+    auto is_slow = deceleration->is_slow();
     if (v > 0) {
-        if (this->player_ptr->slow && !do_dec) {
-            if (this->player_ptr->slow > v) {
+        if (is_slow && !do_dec) {
+            if (deceleration->current() > v) {
                 return false;
             }
-        } else if (!this->player_ptr->slow) {
+        } else if (!is_slow) {
             msg_print(_("体の動きが遅くなってしまった!", "You feel yourself moving slower!"));
             notice = true;
         }
     } else {
-        if (this->player_ptr->slow) {
+        if (is_slow) {
             msg_print(_("動きの遅さがなくなったようだ。", "You feel yourself speed up."));
             notice = true;
         }
     }
 
-    this->player_ptr->slow = v;
+    deceleration->set(v);
     if (!notice) {
         return false;
     }
@@ -398,6 +434,11 @@ bool BadStatusSetter::slowness(const TIME_EFFECT tmp_v, bool do_dec)
     return true;
 }
 
+bool BadStatusSetter::mod_deceleration(const TIME_EFFECT tmp_v, bool do_dec)
+{
+    return this->set_deceleration(this->player_ptr->effects()->deceleration()->current() + tmp_v, do_dec);
+}
+
 /*!
  * @brief 朦朧の継続時間をセットする / Set "stun", notice observable changes
  * @param v 継続時間
@@ -407,50 +448,17 @@ bool BadStatusSetter::slowness(const TIME_EFFECT tmp_v, bool do_dec)
  */
 bool BadStatusSetter::stun(const TIME_EFFECT tmp_v)
 {
-    auto notice = false;
     auto v = std::clamp<short>(tmp_v, 0, 10000);
     if (this->player_ptr->is_dead) {
         return false;
     }
 
-    PlayerClass player_class(this->player_ptr);
-    if (PlayerRace(this->player_ptr).equals(player_race_type::GOLEM) || player_class.can_resist_stun()) {
+    if (PlayerRace(this->player_ptr).has_stun_immunity() || PlayerClass(this->player_ptr).has_stun_immunity()) {
         v = 0;
     }
 
-    auto player_stun = this->player_ptr->effects()->stun();
-    auto old_aux = player_stun->get_rank();
-    auto new_aux = PlayerStun::get_rank(v);
-    if (new_aux > old_aux) {
-        auto stun_mes = PlayerStun::get_stun_mes(new_aux);
-        msg_print(stun_mes.data());
-        this->decrease_int_wis(v);
-        if (player_class.lose_balance()) {
-            msg_print(_("型が崩れた。", "You lose your stance."));
-        }
-
-        if (this->player_ptr->concent) {
-            reset_concentration(this->player_ptr, true);
-        }
-
-        SpellHex spell_hex(this->player_ptr);
-        if (spell_hex.is_spelling_any()) {
-            (void)spell_hex.stop_all_spells();
-        }
-
-        notice = true;
-    } else if (new_aux < old_aux) {
-        if (new_aux == PlayerStunRank::NONE) {
-            msg_print(_("やっと朦朧状態から回復した。", "You are no longer stunned."));
-            if (disturb_state) {
-                disturb(this->player_ptr, false, false);
-            }
-        }
-
-        notice = true;
-    }
-
-    player_stun->set(v);
+    auto notice = this->process_stun_effect(v);
+    this->player_ptr->effects()->stun()->set(v);
     if (!notice) {
         return false;
     }
@@ -465,6 +473,11 @@ bool BadStatusSetter::stun(const TIME_EFFECT tmp_v)
     return true;
 }
 
+bool BadStatusSetter::mod_stun(const TIME_EFFECT tmp_v)
+{
+    return this->stun(this->player_ptr->effects()->stun()->current() + tmp_v);
+}
+
 /*!
  * @brief 出血の継続時間をセットする / Set "cut", notice observable changes
  * @param v 継続時間
@@ -479,12 +492,12 @@ bool BadStatusSetter::cut(const TIME_EFFECT tmp_v)
         return false;
     }
 
-    if (PlayerRace(this->player_ptr).can_resist_cut() && !this->player_ptr->mimic_form) {
+    if (PlayerRace(this->player_ptr).has_cut_immunity()) {
         v = 0;
     }
 
     auto notice = this->process_cut_effect(v);
-    this->player_ptr->cut = v;
+    this->player_ptr->effects()->cut()->set(v);
     if (!notice) {
         return false;
     }
@@ -499,6 +512,57 @@ bool BadStatusSetter::cut(const TIME_EFFECT tmp_v)
     return true;
 }
 
+bool BadStatusSetter::mod_cut(const TIME_EFFECT tmp_v)
+{
+    return this->cut(this->player_ptr->effects()->cut()->current() + tmp_v);
+}
+
+bool BadStatusSetter::process_stun_effect(const short v)
+{
+    auto old_rank = this->player_ptr->effects()->stun()->get_rank();
+    auto new_rank = PlayerStun::get_rank(v);
+    if (new_rank > old_rank) {
+        this->process_stun_status(new_rank, v);
+        return true;
+    }
+
+    if (new_rank < old_rank) {
+        this->clear_head();
+        return true;
+    }
+
+    return false;
+}
+
+void BadStatusSetter::process_stun_status(const PlayerStunRank new_rank, const short v)
+{
+    auto stun_mes = PlayerStun::get_stun_mes(new_rank);
+    msg_print(stun_mes);
+    this->decrease_int_wis(v);
+    if (PlayerClass(this->player_ptr).lose_balance()) {
+        msg_print(_("型が崩れた。", "You lose your stance."));
+    }
+
+    reset_concentration(this->player_ptr, true);
+
+    SpellHex spell_hex(this->player_ptr);
+    if (spell_hex.is_spelling_any()) {
+        (void)spell_hex.stop_all_spells();
+    }
+}
+
+void BadStatusSetter::clear_head()
+{
+    if (this->player_ptr->effects()->stun()->is_stunned()) {
+        return;
+    }
+
+    msg_print(_("やっと朦朧状態から回復した。", "You are no longer stunned."));
+    if (disturb_state) {
+        disturb(this->player_ptr, false, false);
+    }
+}
+
 /*!
  * @todo 後で知能と賢さが両方減る確率を減らす.
  */
@@ -509,7 +573,7 @@ void BadStatusSetter::decrease_int_wis(const short v)
     }
 
     msg_print(_("割れるような頭痛がする。", "A vicious blow hits your head."));
-    auto rand = randint0(3);
+    auto rand = randint0(5);
     switch (rand) {
     case 0:
         if (has_sustain_int(this->player_ptr) == 0) {
@@ -522,45 +586,47 @@ void BadStatusSetter::decrease_int_wis(const short v)
 
         return;
     case 1:
+    case 2:
         if (has_sustain_int(this->player_ptr) == 0) {
             (void)do_dec_stat(this->player_ptr, A_INT);
         }
-        
+
         return;
-    case 2:
+    case 3:
+    case 4:
         if (has_sustain_wis(this->player_ptr) == 0) {
             (void)do_dec_stat(this->player_ptr, A_WIS);
         }
 
         return;
     default:
-        return;
+        throw("Invalid random number is specified!");
     }
 }
 
 bool BadStatusSetter::process_cut_effect(const short v)
 {
     auto player_cut = this->player_ptr->effects()->cut();
-    auto old_aux = player_cut->get_rank();
-    auto new_aux = player_cut->get_rank(v);
-    if (new_aux > old_aux) {
-        this->decrease_charisma(new_aux, v);
+    auto old_rank = player_cut->get_rank();
+    auto new_rank = player_cut->get_rank(v);
+    if (new_rank > old_rank) {
+        this->decrease_charisma(new_rank, v);
         return true;
     }
 
-    if (new_aux < old_aux) {
-        this->stop_blooding(new_aux);
+    if (new_rank < old_rank) {
+        this->stop_blooding(new_rank);
         return true;
     }
 
     return false;
 }
 
-void BadStatusSetter::decrease_charisma(const PlayerCutRank new_aux, const short v)
+void BadStatusSetter::decrease_charisma(const PlayerCutRank new_rank, const short v)
 {
     auto player_cut = this->player_ptr->effects()->cut();
-    auto cut_mes = player_cut->get_cut_mes(new_aux);
-    msg_print(cut_mes.data());
+    auto cut_mes = player_cut->get_cut_mes(new_rank);
+    msg_print(cut_mes);
     if (v <= randint1(1000) && !one_in_(16)) {
         return;
     }
@@ -573,15 +639,15 @@ void BadStatusSetter::decrease_charisma(const PlayerCutRank new_aux, const short
     do_dec_stat(this->player_ptr, A_CHR);
 }
 
-void BadStatusSetter::stop_blooding(const PlayerCutRank new_aux)
+void BadStatusSetter::stop_blooding(const PlayerCutRank new_rank)
 {
-    if (new_aux >= PlayerCutRank::GRAZING) {
+    if (new_rank >= PlayerCutRank::GRAZING) {
         return;
     }
 
-    auto blood_stop_mes = PlayerRace(this->player_ptr).equals(player_race_type::ANDROID)
-        ? _("怪我が直った", "leaking fluid")
-        : _("出血が止まった", "bleeding");
+    auto blood_stop_mes = PlayerRace(this->player_ptr).equals(PlayerRaceType::ANDROID)
+                              ? _("怪我が直った", "leaking fluid")
+                              : _("出血が止まった", "bleeding");
     msg_format(_("やっと%s。", "You are no longer %s."), blood_stop_mes);
     if (disturb_state) {
         disturb(this->player_ptr, false, false);