OSDN Git Service

e8cdeb487e37f5ff1e36e05332e43ef0d788a117
[hengband/hengband.git] / src / combat / slaying.c
1 #include "combat/slaying.h"
2 #include "art-definition/art-sword-types.h"
3 #include "mind/mind-samurai.h"
4 #include "monster-race/race-flags-resistance.h"
5 #include "monster-race/race-flags2.h"
6 #include "monster-race/race-flags3.h"
7 #include "monster-race/race-indice-types.h"
8 #include "monster/monster-info.h"
9 #include "object-enchant/tr-types.h"
10 #include "object/object-flags.h"
11 #include "realm/realm-hex-numbers.h"
12 #include "specific-object/torch.h"
13 #include "spell-realm/spells-hex.h"
14 #include "util/bit-flags-calculator.h"
15
16 /*!
17  * @brief プレイヤー攻撃の種族スレイング倍率計算
18  * @param player_ptr プレーヤーへの参照ポインタ
19  * @param mult 算出前の基本倍率(/10倍)
20  * @param flgs スレイフラグ配列
21  * @param m_ptr 目標モンスターの構造体参照ポインタ
22  * @return スレイング加味後の倍率(/10倍)
23  */
24 MULTIPLY mult_slaying(player_type *player_ptr, MULTIPLY mult, const BIT_FLAGS *flgs, monster_type *m_ptr)
25 {
26     static const struct slay_table_t {
27         int slay_flag;
28         BIT_FLAGS affect_race_flag;
29         MULTIPLY slay_mult;
30         size_t flag_offset;
31         size_t r_flag_offset;
32     } slay_table[] = {
33 #define OFFSET(X) offsetof(monster_race, X)
34         { TR_SLAY_ANIMAL, RF3_ANIMAL, 25, OFFSET(flags3), OFFSET(r_flags3) },
35         { TR_KILL_ANIMAL, RF3_ANIMAL, 40, OFFSET(flags3), OFFSET(r_flags3) },
36         { TR_SLAY_EVIL, RF3_EVIL, 20, OFFSET(flags3), OFFSET(r_flags3) },
37         { TR_KILL_EVIL, RF3_EVIL, 35, OFFSET(flags3), OFFSET(r_flags3) },
38         { TR_SLAY_GOOD, RF3_GOOD, 20, OFFSET(flags3), OFFSET(r_flags3) },
39         { TR_KILL_GOOD, RF3_GOOD, 35, OFFSET(flags3), OFFSET(r_flags3) },
40         { TR_SLAY_HUMAN, RF2_HUMAN, 25, OFFSET(flags2), OFFSET(r_flags2) },
41         { TR_KILL_HUMAN, RF2_HUMAN, 40, OFFSET(flags2), OFFSET(r_flags2) },
42         { TR_SLAY_UNDEAD, RF3_UNDEAD, 30, OFFSET(flags3), OFFSET(r_flags3) },
43         { TR_KILL_UNDEAD, RF3_UNDEAD, 50, OFFSET(flags3), OFFSET(r_flags3) },
44         { TR_SLAY_DEMON, RF3_DEMON, 30, OFFSET(flags3), OFFSET(r_flags3) },
45         { TR_KILL_DEMON, RF3_DEMON, 50, OFFSET(flags3), OFFSET(r_flags3) },
46         { TR_SLAY_ORC, RF3_ORC, 30, OFFSET(flags3), OFFSET(r_flags3) },
47         { TR_KILL_ORC, RF3_ORC, 50, OFFSET(flags3), OFFSET(r_flags3) },
48         { TR_SLAY_TROLL, RF3_TROLL, 30, OFFSET(flags3), OFFSET(r_flags3) },
49         { TR_KILL_TROLL, RF3_TROLL, 50, OFFSET(flags3), OFFSET(r_flags3) },
50         { TR_SLAY_GIANT, RF3_GIANT, 30, OFFSET(flags3), OFFSET(r_flags3) },
51         { TR_KILL_GIANT, RF3_GIANT, 50, OFFSET(flags3), OFFSET(r_flags3) },
52         { TR_SLAY_DRAGON, RF3_DRAGON, 30, OFFSET(flags3), OFFSET(r_flags3) },
53         { TR_KILL_DRAGON, RF3_DRAGON, 50, OFFSET(flags3), OFFSET(r_flags3) },
54 #undef OFFSET
55     };
56
57     monster_race *r_ptr = &r_info[m_ptr->r_idx];
58     for (size_t i = 0; i < sizeof(slay_table) / sizeof(slay_table[0]); ++i) {
59         const struct slay_table_t *p = &slay_table[i];
60
61         if (!have_flag(flgs, p->slay_flag) || !(atoffset(BIT_FLAGS, r_ptr, p->flag_offset) & p->affect_race_flag))
62             continue;
63
64         if (is_original_ap_and_seen(player_ptr, m_ptr)) {
65             atoffset(BIT_FLAGS, r_ptr, p->r_flag_offset) |= p->affect_race_flag;
66         }
67
68         mult = MAX(mult, p->slay_mult);
69     }
70
71     return mult;
72 }
73
74 /*!
75  * @brief プレイヤー攻撃の属性スレイング倍率計算
76  * @param player_ptr プレーヤーへの参照ポインタ
77  * @param mult 算出前の基本倍率(/10倍)
78  * @param flgs スレイフラグ配列
79  * @param m_ptr 目標モンスターの構造体参照ポインタ
80  * @return スレイング加味後の倍率(/10倍)
81  */
82 MULTIPLY mult_brand(player_type *player_ptr, MULTIPLY mult, const BIT_FLAGS *flgs, monster_type *m_ptr)
83 {
84     static const struct brand_table_t {
85         int brand_flag;
86         BIT_FLAGS resist_mask;
87         BIT_FLAGS hurt_flag;
88     } brand_table[] = {
89         { TR_BRAND_ACID, RFR_EFF_IM_ACID_MASK, 0U },
90         { TR_BRAND_ELEC, RFR_EFF_IM_ELEC_MASK, 0U },
91         { TR_BRAND_FIRE, RFR_EFF_IM_FIRE_MASK, RF3_HURT_FIRE },
92         { TR_BRAND_COLD, RFR_EFF_IM_COLD_MASK, RF3_HURT_COLD },
93         { TR_BRAND_POIS, RFR_EFF_IM_POIS_MASK, 0U },
94     };
95
96     monster_race *r_ptr = &r_info[m_ptr->r_idx];
97     for (size_t i = 0; i < sizeof(brand_table) / sizeof(brand_table[0]); ++i) {
98         const struct brand_table_t *p = &brand_table[i];
99
100         if (!have_flag(flgs, p->brand_flag))
101             continue;
102
103         /* Notice immunity */
104         if (r_ptr->flagsr & p->resist_mask) {
105             if (is_original_ap_and_seen(player_ptr, m_ptr)) {
106                 r_ptr->r_flagsr |= (r_ptr->flagsr & p->resist_mask);
107             }
108
109             continue;
110         }
111
112         /* Otherwise, take the damage */
113         if (r_ptr->flags3 & p->hurt_flag) {
114             if (is_original_ap_and_seen(player_ptr, m_ptr)) {
115                 r_ptr->r_flags3 |= p->hurt_flag;
116             }
117
118             mult = MAX(mult, 50);
119             continue;
120         }
121
122         mult = MAX(mult, 25);
123     }
124
125     return mult;
126 }
127
128 /*!
129  * @brief ダメージにスレイ要素を加える総合処理ルーチン /
130  * Extract the "total damage" from a given object hitting a given monster.
131  * @param o_ptr 使用武器オブジェクトの構造体参照ポインタ
132  * @param tdam 現在算出途中のダメージ値
133  * @param m_ptr 目標モンスターの構造体参照ポインタ
134  * @param mode 剣術のID
135  * @param thrown 投擲処理ならばTRUEを指定する
136  * @return 総合的なスレイを加味したダメージ値
137  * @note
138  * Note that "flasks of oil" do NOT do fire damage, although they\n
139  * certainly could be made to do so.  XXX XXX\n
140  *\n
141  * Note that most brands and slays are x3, except Slay Animal (x2),\n
142  * Slay Evil (x2), and Kill dragon (x5).\n
143  */
144 HIT_POINT calc_attack_damage_with_slay(player_type *attacker_ptr, object_type *o_ptr, HIT_POINT tdam, monster_type *m_ptr, combat_options mode, bool thrown)
145 {
146     BIT_FLAGS flgs[TR_FLAG_SIZE];
147     object_flags(o_ptr, flgs);
148     torch_flags(o_ptr, flgs); /* torches has secret flags */
149
150     if (!thrown) {
151         if (attacker_ptr->special_attack & (ATTACK_ACID))
152             add_flag(flgs, TR_BRAND_ACID);
153         if (attacker_ptr->special_attack & (ATTACK_COLD))
154             add_flag(flgs, TR_BRAND_COLD);
155         if (attacker_ptr->special_attack & (ATTACK_ELEC))
156             add_flag(flgs, TR_BRAND_ELEC);
157         if (attacker_ptr->special_attack & (ATTACK_FIRE))
158             add_flag(flgs, TR_BRAND_FIRE);
159         if (attacker_ptr->special_attack & (ATTACK_POIS))
160             add_flag(flgs, TR_BRAND_POIS);
161     }
162
163     if (hex_spelling(attacker_ptr, HEX_RUNESWORD))
164         add_flag(flgs, TR_SLAY_GOOD);
165
166     MULTIPLY mult = 10;
167     switch (o_ptr->tval) {
168     case TV_SHOT:
169     case TV_ARROW:
170     case TV_BOLT:
171     case TV_HAFTED:
172     case TV_POLEARM:
173     case TV_SWORD:
174     case TV_DIGGING:
175     case TV_LITE: {
176         mult = mult_slaying(attacker_ptr, mult, flgs, m_ptr);
177
178         mult = mult_brand(attacker_ptr, mult, flgs, m_ptr);
179
180         if (attacker_ptr->pclass == CLASS_SAMURAI) {
181             mult = mult_hissatsu(attacker_ptr, mult, flgs, m_ptr, mode);
182         }
183
184         if ((attacker_ptr->pclass != CLASS_SAMURAI) && (have_flag(flgs, TR_FORCE_WEAPON)) && (attacker_ptr->csp > (o_ptr->dd * o_ptr->ds / 5))) {
185             attacker_ptr->csp -= (1 + (o_ptr->dd * o_ptr->ds / 5));
186             attacker_ptr->redraw |= (PR_MANA);
187             mult = mult * 3 / 2 + 20;
188         }
189
190         if ((o_ptr->name1 == ART_NOTHUNG) && (m_ptr->r_idx == MON_FAFNER))
191             mult = 150;
192         break;
193     }
194     }
195
196     if (mult > 150)
197         mult = 150;
198     return (tdam * mult / 10);
199 }