OSDN Git Service

d4521b485da1d6021c6f0f1ae74bbb1035933f04
[hengband/hengband.git] / src / shoot.c
1 #include "angband.h"
2
3 /*!
4 * @brief プレイヤーからモンスターへの射撃命中判定 /
5 * Determine if the player "hits" a monster (normal combat).
6 * @param chance 基本命中値
7 * @param m_ptr モンスターの構造体参照ポインタ
8 * @param vis 目標を視界に捕らえているならばTRUEを指定
9 * @param o_name メッセージ表示時のモンスター名
10 * @return 命中と判定された場合TRUEを返す
11 * @note Always miss 5%, always hit 5%, otherwise random.
12 */
13 bool test_hit_fire(int chance, monster_type *m_ptr, int vis, char* o_name)
14 {
15         int k;
16         ARMOUR_CLASS ac;
17         monster_race *r_ptr = &r_info[m_ptr->r_idx];
18
19         /* Percentile dice */
20         k = randint1(100);
21
22         /* Snipers with high-concentration reduce instant miss percentage.*/
23         k += p_ptr->concent;
24
25         /* Hack -- Instant miss or hit */
26         if (k <= 5) return (FALSE);
27         if (k > 95) return (TRUE);
28
29         if (p_ptr->pseikaku == SEIKAKU_NAMAKE)
30                 if (one_in_(20)) return (FALSE);
31
32         /* Never hit */
33         if (chance <= 0) return (FALSE);
34
35         ac = r_ptr->ac;
36         if (p_ptr->concent)
37         {
38                 ac *= (8 - p_ptr->concent);
39                 ac /= 8;
40         }
41
42         if (m_ptr->r_idx == MON_GOEMON && !MON_CSLEEP(m_ptr)) ac *= 3;
43
44         /* Invisible monsters are harder to hit */
45         if (!vis) chance = (chance + 1) / 2;
46
47         /* Power competes against armor */
48         if (randint0(chance) < (ac * 3 / 4))
49         {
50                 if (m_ptr->r_idx == MON_GOEMON && !MON_CSLEEP(m_ptr))
51                 {
52                         GAME_TEXT m_name[MAX_NLEN];
53
54                         /* Extract monster name */
55                         monster_desc(m_name, m_ptr, 0);
56                         msg_format(_("%sは%sを斬り捨てた!", "%s cuts down %s!"), m_name, o_name);
57                 }
58                 return (FALSE);
59         }
60
61         /* Assume hit */
62         return (TRUE);
63 }
64
65
66
67
68 /*!
69 * @brief プレイヤーからモンスターへの射撃クリティカル判定 /
70 * Critical hits (from objects thrown by player) Factor in item weight, total plusses, and player level.
71 * @param weight 矢弾の重量
72 * @param plus_ammo 矢弾の命中修正
73 * @param plus_bow 弓の命中修正
74 * @param dam 現在算出中のダメージ値
75 * @return クリティカル修正が入ったダメージ値
76 */
77 HIT_POINT critical_shot(WEIGHT weight, int plus_ammo, int plus_bow, HIT_POINT dam)
78 {
79         int i, k;
80         object_type *j_ptr = &inventory[INVEN_BOW];
81
82         /* Extract "shot" power */
83         i = p_ptr->to_h_b + plus_ammo;
84
85         if (p_ptr->tval_ammo == TV_BOLT)
86                 i = (p_ptr->skill_thb + (p_ptr->weapon_exp[0][j_ptr->sval] / 400 + i) * BTH_PLUS_ADJ);
87         else
88                 i = (p_ptr->skill_thb + ((p_ptr->weapon_exp[0][j_ptr->sval] - (WEAPON_EXP_MASTER / 2)) / 200 + i) * BTH_PLUS_ADJ);
89
90
91         /* Snipers can shot more critically with crossbows */
92         if (p_ptr->concent) i += ((i * p_ptr->concent) / 5);
93         if ((p_ptr->pclass == CLASS_SNIPER) && (p_ptr->tval_ammo == TV_BOLT)) i *= 2;
94
95         /* Good bow makes more critical */
96         i += plus_bow * 8 * (p_ptr->concent ? p_ptr->concent + 5 : 5);
97
98         /* Critical hit */
99         if (randint1(10000) <= i)
100         {
101                 k = weight * randint1(500);
102
103                 if (k < 900)
104                 {
105                         msg_print(_("手ごたえがあった!", "It was a good hit!"));
106                         dam += (dam / 2);
107                 }
108                 else if (k < 1350)
109                 {
110                         msg_print(_("かなりの手ごたえがあった!", "It was a great hit!"));
111                         dam *= 2;
112                 }
113                 else
114                 {
115                         msg_print(_("会心の一撃だ!", "It was a superb hit!"));
116                         dam *= 3;
117                 }
118         }
119
120         return (dam);
121 }
122
123