OSDN Git Service

[Refactor] 乗馬スキルの上昇処理を PlayerSkill クラスに移設
[hengbandforosx/hengbandosx.git] / src / combat / shoot.cpp
index 3996a7c..eedd564 100644 (file)
@@ -46,7 +46,9 @@
 #include "object/object-info.h"
 #include "object/object-kind.h"
 #include "object/object-mark-types.h"
+#include "player-base/player-class.h"
 #include "player-info/class-info.h"
+#include "player-info/sniper-data-type.h"
 #include "player-status/player-energy.h"
 #include "player/player-personality-types.h"
 #include "player/player-skill.h"
@@ -91,9 +93,9 @@ static MULTIPLY calc_shot_damage_with_slay(
 
     /* Some "weapons" and "ammo" do extra damage */
     switch (arrow_ptr->tval) {
-    case TV_SHOT:
-    case TV_ARROW:
-    case TV_BOLT: {
+    case ItemKindType::SHOT:
+    case ItemKindType::ARROW:
+    case ItemKindType::BOLT: {
         if ((flags.has(TR_SLAY_ANIMAL)) && any_bits(race_ptr->flags3, RF3_ANIMAL)) {
             if (is_original_ap_and_seen(player_ptr, monster_ptr)) {
                 set_bits(race_ptr->r_flags3, RF3_ANIMAL);
@@ -399,8 +401,6 @@ void exe_fire(player_type *player_ptr, INVENTORY_IDX item, object_type *j_ptr, S
 
     uint16_t path_g[512]; /* For calcuration of path length */
 
-    int msec = delay_factor * delay_factor * delay_factor;
-
     /* STICK TO */
     bool stick_to = false;
 
@@ -429,9 +429,9 @@ void exe_fire(player_type *player_ptr, INVENTORY_IDX item, object_type *j_ptr, S
     /* Actually "fire" the object */
     bonus = (player_ptr->to_h_b + o_ptr->to_h + j_ptr->to_h);
     if ((j_ptr->sval == SV_LIGHT_XBOW) || (j_ptr->sval == SV_HEAVY_XBOW))
-        chance = (player_ptr->skill_thb + (player_ptr->weapon_exp[0][j_ptr->sval] / 400 + bonus) * BTH_PLUS_ADJ);
+        chance = (player_ptr->skill_thb + (player_ptr->weapon_exp[j_ptr->tval][j_ptr->sval] / 400 + bonus) * BTH_PLUS_ADJ);
     else
-        chance = (player_ptr->skill_thb + ((player_ptr->weapon_exp[0][j_ptr->sval] - (WEAPON_EXP_MASTER / 2)) / 200 + bonus) * BTH_PLUS_ADJ);
+        chance = (player_ptr->skill_thb + ((player_ptr->weapon_exp[j_ptr->tval][j_ptr->sval] - (PlayerSkill::weapon_exp_at(EXP_LEVEL_MASTER) / 2)) / 200 + bonus) * BTH_PLUS_ADJ);
 
     PlayerEnergy(player_ptr).set_player_turn_energy(bow_energy(j_ptr->sval));
     tmul = bow_tmul(j_ptr->sval);
@@ -446,13 +446,13 @@ void exe_fire(player_type *player_ptr, INVENTORY_IDX item, object_type *j_ptr, S
     tdam_base *= tmul;
     tdam_base /= 100;
 
+    auto sniper_data = PlayerClass(player_ptr).get_specific_data<sniper_data_type>();
+    auto sniper_concent = sniper_data ? sniper_data->concent : 0;
+
     /* Base range */
     tdis = 13 + tmul / 80;
     if ((j_ptr->sval == SV_LIGHT_XBOW) || (j_ptr->sval == SV_HEAVY_XBOW)) {
-        if (player_ptr->concent)
-            tdis -= (5 - (player_ptr->concent + 1) / 2);
-        else
-            tdis -= 5;
+        tdis -= (5 - (sniper_concent + 1) / 2);
     }
 
     project_length = tdis + 1;
@@ -502,7 +502,7 @@ void exe_fire(player_type *player_ptr, INVENTORY_IDX item, object_type *j_ptr, S
 
     /* Sniper - Difficult to shot twice at 1 turn */
     if (snipe_type == SP_DOUBLE)
-        player_ptr->concent = (player_ptr->concent + 1) / 2;
+        sniper_concent = (sniper_concent + 1) / 2;
 
     /* Sniper - Repeat shooting when double shots */
     for (i = 0; i < ((snipe_type == SP_DOUBLE) ? 2 : 1); i++) {
@@ -578,11 +578,11 @@ void exe_fire(player_type *player_ptr, INVENTORY_IDX item, object_type *j_ptr, S
                 byte a = object_attr(q_ptr);
 
                 /* Draw, Hilite, Fresh, Pause, Erase */
-                if (msec > 0) {
+                if (delay_factor > 0) {
                     print_rel(player_ptr, c, a, ny, nx);
                     move_cursor_relative(ny, nx);
                     term_fresh();
-                    term_xtra(TERM_XTRA_DELAY, msec);
+                    term_xtra(TERM_XTRA_DELAY, delay_factor);
                     lite_spot(player_ptr, ny, nx);
                     term_fresh();
                 }
@@ -591,8 +591,8 @@ void exe_fire(player_type *player_ptr, INVENTORY_IDX item, object_type *j_ptr, S
             /* The player cannot see the missile */
             else {
                 /* Pause anyway, for consistancy **/
-                if (msec > 0) {
-                    term_xtra(TERM_XTRA_DELAY, msec);
+                if (delay_factor > 0) {
+                    term_xtra(TERM_XTRA_DELAY, delay_factor);
                 }
             }
 
@@ -637,30 +637,11 @@ void exe_fire(player_type *player_ptr, INVENTORY_IDX item, object_type *j_ptr, S
                 }
 
                 if ((r_ptr->level + 10) > player_ptr->lev) {
-                    int now_exp = player_ptr->weapon_exp[0][j_ptr->sval];
-                    if (now_exp < s_info[player_ptr->pclass].w_max[0][j_ptr->sval]) {
-                        SUB_EXP amount = 0;
-                        if (now_exp < WEAPON_EXP_BEGINNER)
-                            amount = 80;
-                        else if (now_exp < WEAPON_EXP_SKILLED)
-                            amount = 25;
-                        else if ((now_exp < WEAPON_EXP_EXPERT) && (player_ptr->lev > 19))
-                            amount = 10;
-                        else if (player_ptr->lev > 34)
-                            amount = 2;
-                        player_ptr->weapon_exp[0][j_ptr->sval] += amount;
-                        set_bits(player_ptr->update, PU_BONUS);
-                    }
+                    PlayerSkill(player_ptr).gain_range_weapon_exp(j_ptr);
                 }
 
                 if (player_ptr->riding) {
-                    if ((player_ptr->skill_exp[SKILL_RIDING] < s_info[player_ptr->pclass].s_max[SKILL_RIDING])
-                        && ((player_ptr->skill_exp[SKILL_RIDING] - (RIDING_EXP_BEGINNER * 2)) / 200
-                            < r_info[player_ptr->current_floor_ptr->m_list[player_ptr->riding].r_idx].level)
-                        && one_in_(2)) {
-                        player_ptr->skill_exp[SKILL_RIDING] += 1;
-                        set_bits(player_ptr->update, PU_BONUS);
-                    }
+                    PlayerSkill(player_ptr).gain_riding_skill_exp_on_range_attack();
                 }
 
                 /* Did we hit it (penalize range) */
@@ -670,8 +651,7 @@ void exe_fire(player_type *player_ptr, INVENTORY_IDX item, object_type *j_ptr, S
                     auto base_dam = tdam; //!< @note 補正前の与えるダメージ(無傷、全ての耐性など)
 
                     /* Get extra damage from concentration */
-                    if (player_ptr->concent)
-                        tdam = boost_concentration_damage(player_ptr, tdam);
+                    tdam = boost_concentration_damage(player_ptr, tdam);
 
                     /* Handle unseen monster */
                     if (!visible) {
@@ -696,7 +676,7 @@ void exe_fire(player_type *player_ptr, INVENTORY_IDX item, object_type *j_ptr, S
                     }
 
                     if (snipe_type == SP_NEEDLE) {
-                        if ((randint1(randint1(r_ptr->level / (3 + player_ptr->concent)) + (8 - player_ptr->concent)) == 1)
+                        if ((randint1(randint1(r_ptr->level / (3 + sniper_concent)) + (8 - sniper_concent)) == 1)
                             && none_bits(r_ptr->flags1, RF1_UNIQUE) && none_bits(r_ptr->flags7, RF7_UNIQUE2)) {
                             GAME_TEXT m_name[MAX_NLEN];
 
@@ -732,7 +712,7 @@ void exe_fire(player_type *player_ptr, INVENTORY_IDX item, object_type *j_ptr, S
                         uint16_t flg = (PROJECT_STOP | PROJECT_JUMP | PROJECT_KILL | PROJECT_GRID);
 
                         sound(SOUND_EXPLODE); /* No explode sound - use breath fire instead */
-                        project(player_ptr, 0, ((player_ptr->concent + 1) / 2 + 1), ny, nx, base_dam, GF_MISSILE, flg);
+                        project(player_ptr, 0, ((sniper_concent + 1) / 2 + 1), ny, nx, base_dam, GF_MISSILE, flg);
                         break;
                     }
 
@@ -752,7 +732,7 @@ void exe_fire(player_type *player_ptr, INVENTORY_IDX item, object_type *j_ptr, S
                     /* No death */
                     else {
                         /* STICK TO */
-                        if (q_ptr->is_fixed_artifact() && (player_ptr->pclass != CLASS_SNIPER || player_ptr->concent == 0)) {
+                        if (q_ptr->is_fixed_artifact() && (sniper_concent == 0)) {
                             GAME_TEXT m_name[MAX_NLEN];
 
                             monster_desc(player_ptr, m_name, m_ptr, 0);
@@ -811,11 +791,11 @@ void exe_fire(player_type *player_ptr, INVENTORY_IDX item, object_type *j_ptr, S
 
                                 update_monster(player_ptr, m_idx, true);
 
-                                if (msec > 0) {
+                                if (delay_factor > 0) {
                                     lite_spot(player_ptr, ny, nx);
                                     lite_spot(player_ptr, oy, ox);
                                     term_fresh();
-                                    term_xtra(TERM_XTRA_DELAY, msec);
+                                    term_xtra(TERM_XTRA_DELAY, delay_factor);
                                 }
 
                                 x = nx;
@@ -828,10 +808,8 @@ void exe_fire(player_type *player_ptr, INVENTORY_IDX item, object_type *j_ptr, S
                 }
 
                 /* Sniper */
-                if (snipe_type == SP_PIERCE) {
-                    if (player_ptr->concent < 1)
-                        break;
-                    player_ptr->concent--;
+                if (snipe_type == SP_PIERCE && sniper_concent > 0) {
+                    sniper_concent--;
                     continue;
                 }
 
@@ -841,7 +819,7 @@ void exe_fire(player_type *player_ptr, INVENTORY_IDX item, object_type *j_ptr, S
         }
 
         /* Chance of breakage (during attacks) */
-        j = (hit_body ? breakage_chance(player_ptr, q_ptr, player_ptr->pclass == CLASS_ARCHER, snipe_type) : 0);
+        j = (hit_body ? breakage_chance(player_ptr, q_ptr, player_ptr->pclass == PlayerClassType::ARCHER, snipe_type) : 0);
 
         if (stick_to) {
             MONSTER_IDX m_idx = player_ptr->current_floor_ptr->grid_array[y][x].m_idx;
@@ -882,8 +860,7 @@ void exe_fire(player_type *player_ptr, INVENTORY_IDX item, object_type *j_ptr, S
     }
 
     /* Sniper - Loose his/her concentration after any shot */
-    if (player_ptr->concent)
-        reset_concentration(player_ptr, false);
+    reset_concentration(player_ptr, false);
 }
 
 /*!
@@ -905,8 +882,11 @@ bool test_hit_fire(player_type *player_ptr, int chance, monster_type *m_ptr, int
     /* Percentile dice */
     k = randint1(100);
 
+    auto sniper_data = PlayerClass(player_ptr).get_specific_data<sniper_data_type>();
+    auto sniper_concent = sniper_data ? sniper_data->concent : 0;
+
     /* Snipers with high-concentration reduce instant miss percentage.*/
-    k += player_ptr->concent;
+    k += sniper_concent;
 
     /* Hack -- Instant miss or hit */
     if (k <= 5)
@@ -914,7 +894,7 @@ bool test_hit_fire(player_type *player_ptr, int chance, monster_type *m_ptr, int
     if (k > 95)
         return true;
 
-    if (player_ptr->pseikaku == PERSONALITY_LAZY)
+    if (player_ptr->ppersonality == PERSONALITY_LAZY)
         if (one_in_(20))
             return false;
 
@@ -923,10 +903,7 @@ bool test_hit_fire(player_type *player_ptr, int chance, monster_type *m_ptr, int
         return false;
 
     ac = r_ptr->ac;
-    if (player_ptr->concent) {
-        ac *= (8 - player_ptr->concent);
-        ac /= 8;
-    }
+    ac = ac * (8 - sniper_concent) / 8;
 
     if (m_ptr->r_idx == MON_GOEMON && !monster_csleep_remaining(m_ptr))
         ac *= 3;
@@ -966,19 +943,21 @@ HIT_POINT critical_shot(player_type *player_ptr, WEIGHT weight, int plus_ammo, i
     /* Extract "shot" power */
     i = player_ptr->to_h_b + plus_ammo;
 
-    if (player_ptr->tval_ammo == TV_BOLT)
-        i = (player_ptr->skill_thb + (player_ptr->weapon_exp[0][j_ptr->sval] / 400 + i) * BTH_PLUS_ADJ);
+    if (player_ptr->tval_ammo == ItemKindType::BOLT)
+        i = (player_ptr->skill_thb + (player_ptr->weapon_exp[j_ptr->tval][j_ptr->sval] / 400 + i) * BTH_PLUS_ADJ);
     else
-        i = (player_ptr->skill_thb + ((player_ptr->weapon_exp[0][j_ptr->sval] - (WEAPON_EXP_MASTER / 2)) / 200 + i) * BTH_PLUS_ADJ);
+        i = (player_ptr->skill_thb + ((player_ptr->weapon_exp[j_ptr->tval][j_ptr->sval] - (PlayerSkill::weapon_exp_at(EXP_LEVEL_MASTER) / 2)) / 200 + i) * BTH_PLUS_ADJ);
+
+    auto sniper_data = PlayerClass(player_ptr).get_specific_data<sniper_data_type>();
+    auto sniper_concent = sniper_data ? sniper_data->concent : 0;
 
     /* Snipers can shot more critically with crossbows */
-    if (player_ptr->concent)
-        i += ((i * player_ptr->concent) / 5);
-    if ((player_ptr->pclass == CLASS_SNIPER) && (player_ptr->tval_ammo == TV_BOLT))
+    i += ((i * sniper_concent) / 5);
+    if ((player_ptr->pclass == PlayerClassType::SNIPER) && (player_ptr->tval_ammo == ItemKindType::BOLT))
         i *= 2;
 
     /* Good bow makes more critical */
-    i += plus_bow * 8 * (player_ptr->concent ? player_ptr->concent + 5 : 5);
+    i += plus_bow * 8 * (sniper_concent + 5);
 
     /* Critical hit */
     if (randint1(10000) <= i) {
@@ -1115,19 +1094,21 @@ HIT_POINT calc_crit_ratio_shot(player_type *player_ptr, HIT_POINT plus_ammo, HIT
     /* Extract "shot" power */
     i = player_ptr->to_h_b + plus_ammo;
 
-    if (player_ptr->tval_ammo == TV_BOLT)
-        i = (player_ptr->skill_thb + (player_ptr->weapon_exp[0][j_ptr->sval] / 400 + i) * BTH_PLUS_ADJ);
+    if (player_ptr->tval_ammo == ItemKindType::BOLT)
+        i = (player_ptr->skill_thb + (player_ptr->weapon_exp[j_ptr->tval][j_ptr->sval] / 400 + i) * BTH_PLUS_ADJ);
     else
-        i = (player_ptr->skill_thb + ((player_ptr->weapon_exp[0][j_ptr->sval] - (WEAPON_EXP_MASTER / 2)) / 200 + i) * BTH_PLUS_ADJ);
+        i = (player_ptr->skill_thb + ((player_ptr->weapon_exp[j_ptr->tval][j_ptr->sval] - (PlayerSkill::weapon_exp_at(EXP_LEVEL_MASTER) / 2)) / 200 + i) * BTH_PLUS_ADJ);
+
+    auto sniper_data = PlayerClass(player_ptr).get_specific_data<sniper_data_type>();
+    auto sniper_concent = sniper_data ? sniper_data->concent : 0;
 
     /* Snipers can shot more critically with crossbows */
-    if (player_ptr->concent)
-        i += ((i * player_ptr->concent) / 5);
-    if ((player_ptr->pclass == CLASS_SNIPER) && (player_ptr->tval_ammo == TV_BOLT))
+    i += ((i * sniper_concent) / 5);
+    if ((player_ptr->pclass == PlayerClassType::SNIPER) && (player_ptr->tval_ammo == ItemKindType::BOLT))
         i *= 2;
 
     /* Good bow makes more critical */
-    i += plus_bow * 8 * (player_ptr->concent ? player_ptr->concent + 5 : 5);
+    i += plus_bow * 8 * (sniper_concent + 5);
 
     if (i < 0)
         i = 0;
@@ -1152,11 +1133,11 @@ HIT_POINT calc_expect_crit_shot(player_type *player_ptr, WEIGHT weight, int plus
     k = 0;
     num = 0;
 
-    crit = MIN(500, 900 / weight);
+    crit = std::min(500, 900 / weight);
     num += dam * 3 / 2 * crit;
     k = crit;
 
-    crit = MIN(500, 1350 / weight);
+    crit = std::min(500, 1350 / weight);
     crit -= k;
     num += dam * 2 * crit;
     k += crit;
@@ -1216,7 +1197,7 @@ HIT_POINT calc_expect_crit(player_type *player_ptr, WEIGHT weight, int plus, HIT
         num += calc_weight_expect_dam(dam, weight);
     }
 
-    int pow = (player_ptr->pclass == CLASS_NINJA) ? 4444 : 5000;
+    int pow = (player_ptr->pclass == PlayerClassType::NINJA) ? 4444 : 5000;
     if (impact)
         pow /= 2;