OSDN Git Service

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