OSDN Git Service

[Fix] 玄武の構えによるAC修正の計算を適切な位置へ移動
[hengband/hengband.git] / src / specific-object / death-scythe.c
1 /*!
2  * @brief 死の大鎌に特有の処理
3  * @date 2020/05/23
4  * @author Hourier
5  * @details 現時点ではダメージ反射のみ。行数に注意して関数を追加しても良い.
6  */
7
8 #include "specific-object/death-scythe.h"
9 #include "combat/attack-criticality.h"
10 #include "core/player-redraw-types.h"
11 #include "core/stuff-handler.h"
12 #include "inventory/inventory-slot-types.h"
13 #include "main/sound-definitions-table.h"
14 #include "main/sound-of-music.h"
15 #include "object-enchant/tr-types.h"
16 #include "object/object-flags.h"
17 #include "player/player-damage.h"
18 #include "player/player-race.h"
19 #include "status/element-resistance.h"
20 #include "util/bit-flags-calculator.h"
21 #include "view/display-messages.h"
22 #include "player/player-status-flags.h"
23
24 /*!
25  * @brief 死の大鎌ダメージが跳ね返ってきた時の、種族ごとのダメージ倍率を返す
26  * @param attacker_ptr プレーヤーへの参照ポインタ
27  * @return 倍率 (実際は1/10になる)
28  */
29 static int calc_death_scythe_reflection_magnification_mimic_none(player_type *attacker_ptr)
30 {
31     switch (attacker_ptr->prace) {
32     case RACE_YEEK:
33     case RACE_KLACKON:
34     case RACE_HUMAN:
35     case RACE_AMBERITE:
36     case RACE_DUNADAN:
37     case RACE_BARBARIAN:
38     case RACE_BEASTMAN:
39         return 25;
40     case RACE_HALF_ORC:
41     case RACE_HALF_TROLL:
42     case RACE_HALF_OGRE:
43     case RACE_HALF_GIANT:
44     case RACE_HALF_TITAN:
45     case RACE_CYCLOPS:
46     case RACE_IMP:
47     case RACE_SKELETON:
48     case RACE_ZOMBIE:
49     case RACE_VAMPIRE:
50     case RACE_SPECTRE:
51     case RACE_BALROG:
52     case RACE_DRACONIAN:
53         return 30;
54     default:
55         return 10;
56     }
57 }
58
59 /*!
60  * @brief 死の大鎌ダメージが跳ね返ってきた時の、変身中の種族も考慮したダメージ倍率を返す
61  * @param attacker_ptr プレーヤーへの参照ポインタ
62  * @return 倍率 (実際は1/10になる)
63  */
64 static int calc_death_scythe_reflection_magnification(player_type *attacker_ptr)
65 {
66     switch (attacker_ptr->mimic_form) {
67     case MIMIC_NONE:
68         return calc_death_scythe_reflection_magnification_mimic_none(attacker_ptr);
69     case MIMIC_DEMON:
70     case MIMIC_DEMON_LORD:
71     case MIMIC_VAMPIRE:
72         return 30;
73     default:
74         return 10;
75     }
76 }
77
78 /*!
79  * @brief 耐性等に応じて死の大鎌による反射ダメージ倍率を補正する
80  * @param attacker_ptr プレーヤーへの参照ポインタ
81  * @param magnification ダメージ倍率
82  * @param death_scythe_flags 死の大鎌に関するオブジェクトフラグ配列
83  * @return なし
84  */
85 static void compensate_death_scythe_reflection_magnification(player_type *attacker_ptr, int *magnification, BIT_FLAGS *death_scythe_flags)
86 {
87     if ((attacker_ptr->align < 0) && (*magnification < 20))
88         *magnification = 20;
89
90     if (!(has_resist_acid(attacker_ptr) || is_oppose_acid(attacker_ptr) || has_immune_acid(attacker_ptr)) && (*magnification < 25))
91         *magnification = 25;
92
93     if (!(has_resist_elec(attacker_ptr) || is_oppose_elec(attacker_ptr) || has_immune_elec(attacker_ptr)) && (*magnification < 25))
94         *magnification = 25;
95
96     if (!(has_resist_fire(attacker_ptr) || is_oppose_fire(attacker_ptr) || has_immune_fire(attacker_ptr)) && (*magnification < 25))
97         *magnification = 25;
98
99     if (!(has_resist_cold(attacker_ptr) || is_oppose_cold(attacker_ptr) || has_immune_cold(attacker_ptr)) && (*magnification < 25))
100         *magnification = 25;
101
102     if (!(has_resist_pois(attacker_ptr) || is_oppose_pois(attacker_ptr)) && (*magnification < 25))
103         *magnification = 25;
104
105     if ((attacker_ptr->pclass != CLASS_SAMURAI) && (has_flag(death_scythe_flags, TR_FORCE_WEAPON)) && (attacker_ptr->csp > (attacker_ptr->msp / 30))) {
106         attacker_ptr->csp -= (1 + (attacker_ptr->msp / 30));
107         attacker_ptr->redraw |= (PR_MANA);
108         *magnification = *magnification * 3 / 2 + 20;
109     }
110 }
111
112 /*!
113  * @brief 死の大鎌による反射ダメージ倍率を更に上げる
114  * @param pa_ptr 直接攻撃構造体への参照ポインタ
115  * @return なし
116  */
117 static void death_scythe_reflection_critial_hit(player_attack_type *pa_ptr)
118 {
119     if (!one_in_(6))
120         return;
121
122     int more_magnification = 2;
123     msg_format(_("グッサリ切り裂かれた!", "Your weapon cuts deep into yourself!"));
124     while (one_in_(4))
125         more_magnification++;
126
127     pa_ptr->attack_damage *= (HIT_POINT)more_magnification;
128 }
129
130 /*!
131  * @brief 死の大鎌によるダメージ反射のメインルーチン
132  * @param attacker_ptr プレーヤーへの参照ポインタ
133  * @param pa_ptr 直接攻撃構造体への参照ポインタ
134  * @return なし
135  */
136 void process_death_scythe_reflection(player_type *attacker_ptr, player_attack_type *pa_ptr)
137 {
138     BIT_FLAGS death_scythe_flags[TR_FLAG_SIZE];
139     sound(SOUND_HIT);
140     msg_format(_("ミス! %sにかわされた。", "You miss %s."), pa_ptr->m_name);
141     msg_print(_("振り回した大鎌が自分自身に返ってきた!", "Your scythe returns to you!"));
142
143     object_type *o_ptr = &attacker_ptr->inventory_list[INVEN_MAIN_HAND + pa_ptr->hand];
144     object_flags(attacker_ptr, o_ptr, death_scythe_flags);
145     pa_ptr->attack_damage = damroll(o_ptr->dd + attacker_ptr->to_dd[pa_ptr->hand], o_ptr->ds + attacker_ptr->to_ds[pa_ptr->hand]);
146     int magnification = calc_death_scythe_reflection_magnification(attacker_ptr);
147     compensate_death_scythe_reflection_magnification(attacker_ptr, &magnification, death_scythe_flags);
148     pa_ptr->attack_damage *= (HIT_POINT)magnification;
149     pa_ptr->attack_damage /= 10;
150     pa_ptr->attack_damage = critical_norm(attacker_ptr, o_ptr->weight, o_ptr->to_h, pa_ptr->attack_damage, attacker_ptr->to_h[pa_ptr->hand], pa_ptr->mode);
151     death_scythe_reflection_critial_hit(pa_ptr);
152     pa_ptr->attack_damage += (attacker_ptr->to_d[pa_ptr->hand] + o_ptr->to_d);
153     if (pa_ptr->attack_damage < 0)
154         pa_ptr->attack_damage = 0;
155
156     take_hit(attacker_ptr, DAMAGE_FORCE, pa_ptr->attack_damage, _("死の大鎌", "Death scythe"), -1);
157     handle_stuff(attacker_ptr);
158 }