OSDN Git Service

[Refactor] struct player_type を class PlayerType に置換。
[hengbandforosx/hengbandosx.git] / src / monster-attack / monster-attack-player.cpp
index 16b0d25..e56b980 100644 (file)
@@ -38,6 +38,8 @@
 #include "object-hook/hook-armor.h"
 #include "object/item-tester-hooker.h"
 #include "pet/pet-fall-off.h"
+#include "player-base/player-class.h"
+#include "player-info/samurai-data-type.h"
 #include "player/attack-defense-types.h"
 #include "player/player-damage.h"
 #include "player/player-skill.h"
 #include "system/monster-type-definition.h"
 #include "system/object-type-definition.h"
 #include "system/player-type-definition.h"
+#include "timed-effect/player-cut.h"
 #include "timed-effect/player-stun.h"
-#include "timed-effect/timed-effects.h"
 #include "util/bit-flags-calculator.h"
 #include "view/display-messages.h"
 
-static bool check_no_blow(player_type *player_ptr, monap_type *monap_ptr)
+static bool check_no_blow(PlayerType *player_ptr, monap_type *monap_ptr)
 {
     auto *r_ptr = &r_info[monap_ptr->m_ptr->r_idx];
     if (any_bits(r_ptr->flags1, RF1_NEVER_BLOW)) {
         return false;
     }
 
-    if (d_info[player_ptr->dungeon_idx].flags.has(DF::NO_MELEE)) {
+    if (d_info[player_ptr->dungeon_idx].flags.has(DungeonFeatureType::NO_MELEE)) {
         return false;
     }
 
@@ -75,7 +77,7 @@ static bool check_no_blow(player_type *player_ptr, monap_type *monap_ptr)
  * @param monap_ptr モンスターからプレイヤーへの直接攻撃構造体への参照ポインタ
  * @return 攻撃続行ならばTRUE、打ち切りになったらFALSE
  */
-static bool check_monster_continuous_attack(player_type *player_ptr, monap_type *monap_ptr)
+static bool check_monster_continuous_attack(PlayerType *player_ptr, monap_type *monap_ptr)
 {
     if (!monster_is_valid(monap_ptr->m_ptr) || (monap_ptr->method == RBM_NONE)) {
         return false;
@@ -97,7 +99,7 @@ static bool check_monster_continuous_attack(player_type *player_ptr, monap_type
  * @param monap_ptr モンスターからプレイヤーへの直接攻撃構造体への参照ポインタ
  * @return briefに書いた条件+確率が満たされたらTRUE、それ以外はFALSE
  */
-static bool effect_protecion_from_evil(player_type *player_ptr, monap_type *monap_ptr)
+static bool effect_protecion_from_evil(PlayerType *player_ptr, monap_type *monap_ptr)
 {
     auto *r_ptr = &r_info[monap_ptr->m_ptr->r_idx];
     if ((player_ptr->protevil <= 0) || none_bits(r_ptr->flags3, RF3_EVIL) || (player_ptr->lev < monap_ptr->rlev) || ((randint0(100) + player_ptr->lev) <= 50)) {
@@ -164,101 +166,91 @@ static void select_cut_stun(monap_type *monap_ptr)
     }
 }
 
-static void calc_player_cut(player_type *player_ptr, monap_type *monap_ptr)
+static void calc_player_cut(PlayerType *player_ptr, monap_type *monap_ptr)
 {
     if (monap_ptr->do_cut == 0) {
         return;
     }
 
-    auto cut_plus = 0;
-    auto criticality = calc_monster_critical(monap_ptr->d_dice, monap_ptr->d_side, monap_ptr->damage);
-    switch (criticality) {
-    case 0:
-        cut_plus = 0;
-        break;
-    case 1:
-        cut_plus = randint1(5);
-        break;
-    case 2:
-        cut_plus = randint1(5) + 5;
-        break;
-    case 3:
-        cut_plus = randint1(20) + 20;
-        break;
-    case 4:
-        cut_plus = randint1(50) + 50;
-        break;
-    case 5:
-        cut_plus = randint1(100) + 100;
-        break;
-    case 6:
-        cut_plus = 300;
-        break;
-    default:
-        cut_plus = 500;
-        break;
+    auto cut_plus = PlayerCut::get_accumulation(monap_ptr->d_dice * monap_ptr->d_side, monap_ptr->damage);
+    if (cut_plus > 0) {
+        (void)BadStatusSetter(player_ptr).mod_cut(cut_plus);
     }
+}
 
-    if (cut_plus > 0) {
-        (void)set_cut(player_ptr, player_ptr->cut + cut_plus);
+/*!
+ * @brief 能力値の実値を求める
+ * @param raw PlayerTypeに格納されている生値
+ * @return 実値
+ * @details AD&Dの記法に則り、19以上の値を取らなくしているので、格納方法が面倒
+ */
+static int stat_value(const int raw)
+{
+    if (raw <= 18) {
+        return raw;
     }
+
+    return (raw - 18) / 10 + 18;
 }
 
-static void calc_player_stun(player_type *player_ptr, monap_type *monap_ptr)
+/*!
+ * @brief 朦朧を蓄積させる
+ * @param player_ptr プレイヤーへの参照ポインタ
+ * @param monap_ptr モンスター打撃への参照ポインタ
+ * @details
+ * 痛恨の一撃ならば朦朧蓄積ランクを1上げる.
+ * 2%の確率で朦朧蓄積ランクを1上げる.
+ * 肉体のパラメータが合計80を超える水準に強化されていたら朦朧蓄積ランクを1下げる.
+ */
+static void process_player_stun(PlayerType *player_ptr, monap_type *monap_ptr)
 {
     if (monap_ptr->do_stun == 0) {
         return;
     }
 
-    auto stun_plus = 0;
-    auto criticality = calc_monster_critical(monap_ptr->d_dice, monap_ptr->d_side, monap_ptr->damage);
-    switch (criticality) {
-    case 0:
-        stun_plus = 0;
-        break;
-    case 1:
-        stun_plus = randint1(5);
-        break;
-    case 2:
-        stun_plus = randint1(5) + 10;
-        break;
-    case 3:
-        stun_plus = randint1(10) + 20;
-        break;
-    case 4:
-        stun_plus = randint1(15) + 30;
-        break;
-    case 5:
-        stun_plus = randint1(20) + 40;
-        break;
-    case 6:
-        stun_plus = 80;
-        break;
-    default:
-        stun_plus = 150;
-        break;
+    auto total = monap_ptr->d_dice * monap_ptr->d_side;
+    auto accumulation_rank = PlayerStun::get_accumulation_rank(total, monap_ptr->damage);
+    if (accumulation_rank == 0) {
+        return;
+    }
+
+    if ((total < monap_ptr->damage) && (accumulation_rank <= 6)) {
+        accumulation_rank++;
+    }
+
+    if (one_in_(50)) {
+        accumulation_rank++;
+    }
+
+    auto str = stat_value(player_ptr->stat_cur[A_STR]);
+    auto dex = stat_value(player_ptr->stat_cur[A_DEX]);
+    auto con = stat_value(player_ptr->stat_cur[A_CON]);
+    auto is_powerful_body = str + dex + con > 80;
+    if (is_powerful_body) {
+        accumulation_rank--;
     }
 
+    auto stun_plus = PlayerStun::get_accumulation(accumulation_rank);
     if (stun_plus > 0) {
-        (void)set_stun(player_ptr, player_ptr->effects()->stun()->current() + stun_plus);
+        (void)BadStatusSetter(player_ptr).mod_stun(stun_plus);
     }
 }
 
-static void monster_explode(player_type *player_ptr, monap_type *monap_ptr)
+static void monster_explode(PlayerType *player_ptr, monap_type *monap_ptr)
 {
     if (!monap_ptr->explode) {
         return;
     }
 
     sound(SOUND_EXPLODE);
-    MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, monap_ptr->m_ptr->hp + 1, &monap_ptr->fear);
+    MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, monap_ptr->m_ptr->hp + 1, &monap_ptr->fear, AttributeType::NONE);
     if (mdp.mon_take_hit(nullptr)) {
         monap_ptr->blinked = false;
         monap_ptr->alive = false;
     }
 }
 
-static void describe_attack_evasion(player_type *player_ptr, monap_type *monap_ptr)
+static void describe_attack_evasion(PlayerType *player_ptr, monap_type *monap_ptr)
 {
     if (!monap_ptr->m_ptr->ml) {
         return;
@@ -279,7 +271,7 @@ static void describe_attack_evasion(player_type *player_ptr, monap_type *monap_p
 #endif
 }
 
-static void gain_armor_exp(player_type *player_ptr, monap_type *monap_ptr)
+static void gain_armor_exp(PlayerType *player_ptr, monap_type *monap_ptr)
 {
     const auto o_ptr_mh = &player_ptr->inventory_list[INVEN_MAIN_HAND];
     const auto o_ptr_sh = &player_ptr->inventory_list[INVEN_SUB_HAND];
@@ -287,21 +279,21 @@ static void gain_armor_exp(player_type *player_ptr, monap_type *monap_ptr)
         return;
     }
 
-    auto cur = player_ptr->skill_exp[SKILL_SHIELD];
-    auto max = s_info[player_ptr->pclass].s_max[SKILL_SHIELD];
+    auto cur = player_ptr->skill_exp[PlayerSkillKindType::SHIELD];
+    auto max = s_info[enum2i(player_ptr->pclass)].s_max[PlayerSkillKindType::SHIELD];
     if (cur >= max) {
         return;
     }
 
     auto *r_ptr = &r_info[monap_ptr->m_ptr->r_idx];
     auto target_level = r_ptr->level;
-    auto increment = 0;
+    short increment = 0;
     if ((cur / 100) < target_level) {
         auto addition = (cur / 100 + 15) < target_level ? (target_level - (cur / 100 + 15)) : 0;
         increment += 1 + addition;
     }
 
-    player_ptr->skill_exp[SKILL_SHIELD] = MIN(max, cur + increment);
+    player_ptr->skill_exp[PlayerSkillKindType::SHIELD] = std::min<short>(max, cur + increment);
     player_ptr->update |= (PU_BONUS);
 }
 
@@ -312,7 +304,7 @@ static void gain_armor_exp(player_type *player_ptr, monap_type *monap_ptr)
  * @param monap_ptr モンスターからプレイヤーへの直接攻撃構造体への参照ポインタ
  * @details 最大4 回/モンスター/ターン、このルーチンを通る
  */
-static bool process_monster_attack_hit(player_type *player_ptr, monap_type *monap_ptr)
+static bool process_monster_attack_hit(PlayerType *player_ptr, monap_type *monap_ptr)
 {
     disturb(player_ptr, true, true);
     if (effect_protecion_from_evil(player_ptr, monap_ptr)) {
@@ -332,7 +324,7 @@ static bool process_monster_attack_hit(player_type *player_ptr, monap_type *mona
     switch_monster_blow_to_player(player_ptr, monap_ptr);
     select_cut_stun(monap_ptr);
     calc_player_cut(player_ptr, monap_ptr);
-    calc_player_stun(player_ptr, monap_ptr);
+    process_player_stun(player_ptr, monap_ptr);
     monster_explode(player_ptr, monap_ptr);
     process_aura_counterattack(player_ptr, monap_ptr);
     return true;
@@ -343,7 +335,7 @@ static bool process_monster_attack_hit(player_type *player_ptr, monap_type *mona
  * @param player_ptr プレイヤーへの参照ポインタ
  * @param monap_ptr モンスターからプレイヤーへの直接攻撃構造体への参照ポインタ
  */
-static void process_monster_attack_evasion(player_type *player_ptr, monap_type *monap_ptr)
+static void process_monster_attack_evasion(PlayerType *player_ptr, monap_type *monap_ptr)
 {
     switch (monap_ptr->method) {
     case RBM_HIT:
@@ -376,7 +368,7 @@ static void process_monster_attack_evasion(player_type *player_ptr, monap_type *
  * 非自明な類の打撃については、そのダメージが 0 ならば基本的に知識が増えない.
  * 但し、既に一定以上の知識があれば常に知識が増える(何をされたのか察知できる).
  */
-static void increase_blow_type_seen(player_type *player_ptr, monap_type *monap_ptr, const int ap_cnt)
+static void increase_blow_type_seen(PlayerType *player_ptr, monap_type *monap_ptr, const int ap_cnt)
 {
     if (!is_original_ap_and_seen(player_ptr, monap_ptr->m_ptr) || monap_ptr->do_silly_attack) {
         return;
@@ -396,7 +388,7 @@ static void increase_blow_type_seen(player_type *player_ptr, monap_type *monap_p
  * @brief モンスターからプレイヤーへの打撃処理本体
  * @return 打撃に反応してプレイヤーがその場から離脱したかどうか
  */
-static bool process_monster_blows(player_type *player_ptr, monap_type *monap_ptr)
+static bool process_monster_blows(PlayerType *player_ptr, monap_type *monap_ptr)
 {
     auto *r_ptr = &r_info[monap_ptr->m_ptr->r_idx];
     for (auto ap_cnt = 0; ap_cnt < MAX_NUM_BLOWS; ap_cnt++) {
@@ -412,11 +404,11 @@ static bool process_monster_blows(player_type *player_ptr, monap_type *monap_ptr
             break;
         }
 
-        // effect が RBE_NONE (無効値)になることはあり得ないはずだが、万一そう
+        // effect が RaceBlowEffectType::NONE (無効値)になることはあり得ないはずだが、万一そう
         // なっていたら単に攻撃を打ち切る。
         // r_info.txt の "B:" トークンに effect 以降を書き忘れた場合が該当する。
-        if (monap_ptr->effect == RBE_NONE) {
-            plog("unexpected: monap_ptr->effect == RBE_NONE");
+        if (monap_ptr->effect == RaceBlowEffectType::NONE) {
+            plog("unexpected: monap_ptr->effect == RaceBlowEffectType::NONE");
             break;
         }
 
@@ -427,10 +419,10 @@ static bool process_monster_blows(player_type *player_ptr, monap_type *monap_ptr
         // フレーバーの打撃は必中扱い。それ以外は通常の命中判定を行う。
         monap_ptr->ac = player_ptr->ac + player_ptr->to_a;
         bool hit;
-        if (monap_ptr->effect == RBE_FLAVOR) {
+        if (monap_ptr->effect == RaceBlowEffectType::FLAVOR) {
             hit = true;
         } else {
-            const int power = mbe_info[monap_ptr->effect].power;
+            const int power = mbe_info[enum2i(monap_ptr->effect)].power;
             hit = check_hit_from_monster_to_player(player_ptr, power, monap_ptr->rlev, monster_stunned_remaining(monap_ptr->m_ptr));
         }
 
@@ -446,10 +438,10 @@ static bool process_monster_blows(player_type *player_ptr, monap_type *monap_ptr
 
             // 撃退失敗時は落馬処理、変わり身のテレポート処理を行う。
             check_fall_off_horse(player_ptr, monap_ptr);
-            if (player_ptr->special_defense & NINJA_KAWARIMI) {
-                // 変わり身のテレポートが成功したら攻撃を打ち切り、プレイヤーが離脱した旨を返す。
-                if (kawarimi(player_ptr, false))
-                    return true;
+
+            // 変わり身のテレポートが成功したら攻撃を打ち切り、プレイヤーが離脱した旨を返す。
+            if (kawarimi(player_ptr, false)) {
+                return true;
             }
         } else {
             // 命中しなかった。回避時の処理、思い出処理を行う。
@@ -462,7 +454,7 @@ static bool process_monster_blows(player_type *player_ptr, monap_type *monap_ptr
     return false;
 }
 
-static void postprocess_monster_blows(player_type *player_ptr, monap_type *monap_ptr)
+static void postprocess_monster_blows(PlayerType *player_ptr, monap_type *monap_ptr)
 {
     SpellHex spell_hex(player_ptr, monap_ptr);
     spell_hex.store_vengeful_damage(monap_ptr->get_damage);
@@ -479,9 +471,7 @@ static void postprocess_monster_blows(player_type *player_ptr, monap_type *monap
         msg_format(_("%^sは恐怖で逃げ出した!", "%^s flees in terror!"), monap_ptr->m_name);
     }
 
-    if (player_ptr->special_defense & KATA_IAI) {
-        set_action(player_ptr, ACTION_NONE);
-    }
+    PlayerClass(player_ptr).break_samurai_stance({ SamuraiStanceType::IAI });
 }
 
 /*!
@@ -489,7 +479,7 @@ static void postprocess_monster_blows(player_type *player_ptr, monap_type *monap
  * @param m_idx 打撃を行うモンスターのID
  * @return 実際に攻撃処理を行った場合TRUEを返す
  */
-bool make_attack_normal(player_type *player_ptr, MONSTER_IDX m_idx)
+bool make_attack_normal(PlayerType *player_ptr, MONSTER_IDX m_idx)
 {
     monap_type tmp_monap;
     monap_type *monap_ptr = initialize_monap_type(player_ptr, &tmp_monap, m_idx);
@@ -501,16 +491,15 @@ bool make_attack_normal(player_type *player_ptr, MONSTER_IDX m_idx)
     monap_ptr->rlev = ((r_ptr->level >= 1) ? r_ptr->level : 1);
     monster_desc(player_ptr, monap_ptr->m_name, monap_ptr->m_ptr, 0);
     monster_desc(player_ptr, monap_ptr->ddesc, monap_ptr->m_ptr, MD_WRONGDOER_NAME);
-    if (any_bits(player_ptr->special_defense, KATA_IAI)) {
+    if (PlayerClass(player_ptr).samurai_stance_is(SamuraiStanceType::IAI)) {
         msg_format(_("相手が襲いかかる前に素早く武器を振るった。", "You took sen, drew and cut in one motion before %s moved."), monap_ptr->m_name);
         if (do_cmd_attack(player_ptr, monap_ptr->m_ptr->fy, monap_ptr->m_ptr->fx, HISSATSU_IAI)) {
             return true;
         }
     }
 
-    auto is_kawarimi = any_bits(player_ptr->special_defense, NINJA_KAWARIMI);
     auto can_activate_kawarimi = randint0(55) < (player_ptr->lev * 3 / 5 + 20);
-    if (is_kawarimi && can_activate_kawarimi && kawarimi(player_ptr, true)) {
+    if (can_activate_kawarimi && kawarimi(player_ptr, true)) {
         return true;
     }