OSDN Git Service

3ad7291850f6e5fe6a47a682760665aa1cfec149
[hengbandforosx/hengbandosx.git] / src / combat / aura-counterattack.cpp
1 /*!
2  * @brief モンスターから直接攻撃を受けた時に、プレイヤーのオーラダメージで反撃する処理
3  * @date 2020/05/31
4  * @author Hourier
5  */
6
7 #include "combat/aura-counterattack.h"
8 #include "effect/attribute-types.h"
9 #include "effect/effect-characteristics.h"
10 #include "effect/effect-processor.h"
11 #include "grid/grid.h"
12 #include "inventory/inventory-slot-types.h"
13 #include "monster-attack/monster-attack-player.h"
14 #include "monster-race/monster-race.h"
15 #include "monster-race/race-flags-resistance.h"
16 #include "monster-race/race-flags3.h"
17 #include "monster/monster-damage.h"
18 #include "monster/monster-info.h"
19 #include "monster/monster-status.h"
20 #include "object-hook/hook-armor.h"
21 #include "player/player-status-flags.h"
22 #include "realm/realm-hex-numbers.h"
23 #include "spell-kind/spells-teleport.h"
24 #include "spell-realm/spells-hex.h"
25 #include "system/floor-type-definition.h"
26 #include "system/grid-type-definition.h"
27 #include "system/monster-race-definition.h"
28 #include "system/monster-type-definition.h"
29 #include "system/object-type-definition.h"
30 #include "system/player-type-definition.h"
31 #include "view/display-messages.h"
32
33 static void aura_fire_by_monster_attack(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr)
34 {
35     if (!has_sh_fire(player_ptr) || !monap_ptr->alive || player_ptr->is_dead)
36         return;
37
38     auto *r_ptr = &r_info[monap_ptr->m_ptr->r_idx];
39     if ((r_ptr->flagsr & RFR_EFF_IM_FIRE_MASK) != 0) {
40         if (is_original_ap_and_seen(player_ptr, monap_ptr->m_ptr))
41             r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_FIRE_MASK);
42
43         return;
44     }
45
46     HIT_POINT dam = damroll(2, 6);
47     dam = mon_damage_mod(player_ptr, monap_ptr->m_ptr, dam, false);
48     msg_format(_("%^sは突然熱くなった!", "%^s is suddenly very hot!"), monap_ptr->m_name);
49     MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear, AttributeType::FIRE);
50     if (mdp.mon_take_hit(_("は灰の山になった。", " turns into a pile of ash."))) {
51         monap_ptr->blinked = false;
52         monap_ptr->alive = false;
53     }
54 }
55
56 static void aura_elec_by_monster_attack(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr)
57 {
58     if (!has_sh_elec(player_ptr) || !monap_ptr->alive || player_ptr->is_dead)
59         return;
60
61     auto *r_ptr = &r_info[monap_ptr->m_ptr->r_idx];
62     if ((r_ptr->flagsr & RFR_EFF_IM_ELEC_MASK) != 0) {
63         if (is_original_ap_and_seen(player_ptr, monap_ptr->m_ptr))
64             r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_ELEC_MASK);
65
66         return;
67     }
68
69     HIT_POINT dam = damroll(2, 6);
70     dam = mon_damage_mod(player_ptr, monap_ptr->m_ptr, dam, false);
71     msg_format(_("%^sは電撃をくらった!", "%^s gets zapped!"), monap_ptr->m_name);
72     MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear, AttributeType::ELEC);
73     if (mdp.mon_take_hit(_("は燃え殻の山になった。", " turns into a pile of cinders."))) {
74         monap_ptr->blinked = false;
75         monap_ptr->alive = false;
76     }
77 }
78
79 static void aura_cold_by_monster_attack(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr)
80 {
81     if (!has_sh_cold(player_ptr) || !monap_ptr->alive || player_ptr->is_dead)
82         return;
83
84     auto *r_ptr = &r_info[monap_ptr->m_ptr->r_idx];
85     if ((r_ptr->flagsr & RFR_EFF_IM_COLD_MASK) != 0) {
86         if (is_original_ap_and_seen(player_ptr, monap_ptr->m_ptr))
87             r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_IM_COLD_MASK);
88
89         return;
90     }
91
92     HIT_POINT dam = damroll(2, 6);
93     dam = mon_damage_mod(player_ptr, monap_ptr->m_ptr, dam, false);
94     msg_format(_("%^sは冷気をくらった!", "%^s is very cold!"), monap_ptr->m_name);
95     MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear, AttributeType::COLD);
96     if (mdp.mon_take_hit(_("は凍りついた。", " was frozen."))) {
97         monap_ptr->blinked = false;
98         monap_ptr->alive = false;
99     }
100 }
101
102 static void aura_shards_by_monster_attack(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr)
103 {
104     if (!player_ptr->dustrobe || !monap_ptr->alive || player_ptr->is_dead)
105         return;
106
107     auto *r_ptr = &r_info[monap_ptr->m_ptr->r_idx];
108     if ((r_ptr->flagsr & RFR_EFF_RES_SHAR_MASK) != 0) {
109         if (is_original_ap_and_seen(player_ptr, monap_ptr->m_ptr))
110             r_ptr->r_flagsr |= (r_ptr->flagsr & RFR_EFF_RES_SHAR_MASK);
111     } else {
112         HIT_POINT dam = damroll(2, 6);
113         dam = mon_damage_mod(player_ptr, monap_ptr->m_ptr, dam, false);
114         msg_format(_("%^sは鏡の破片をくらった!", "%^s gets sliced!"), monap_ptr->m_name);
115         MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear, AttributeType::SHARDS);
116         if (mdp.mon_take_hit(_("はズタズタになった。", " is torn to pieces."))) {
117             monap_ptr->blinked = false;
118             monap_ptr->alive = false;
119         }
120     }
121
122     if (player_ptr->current_floor_ptr->grid_array[player_ptr->y][player_ptr->x].is_mirror())
123         teleport_player(player_ptr, 10, TELEPORT_SPONTANEOUS);
124 }
125
126 static void aura_holy_by_monster_attack(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr)
127 {
128     if (!player_ptr->tim_sh_holy || !monap_ptr->alive || player_ptr->is_dead)
129         return;
130
131     auto *r_ptr = &r_info[monap_ptr->m_ptr->r_idx];
132     if (r_ptr->kind_flags.has_not(MonsterKindType::EVIL))
133         return;
134
135     if ((r_ptr->flagsr & RFR_RES_ALL) != 0) {
136         if (is_original_ap_and_seen(player_ptr, monap_ptr->m_ptr))
137             r_ptr->r_flagsr |= RFR_RES_ALL;
138
139         return;
140     }
141
142     HIT_POINT dam = damroll(2, 6);
143     dam = mon_damage_mod(player_ptr, monap_ptr->m_ptr, dam, false);
144     msg_format(_("%^sは聖なるオーラで傷ついた!", "%^s is injured by holy power!"), monap_ptr->m_name);
145     MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear, AttributeType::HOLY_FIRE);
146     if (mdp.mon_take_hit(_("は倒れた。", " is destroyed."))) {
147         monap_ptr->blinked = false;
148         monap_ptr->alive = false;
149     }
150
151     if (is_original_ap_and_seen(player_ptr, monap_ptr->m_ptr))
152         r_ptr->r_kind_flags.set(MonsterKindType::EVIL);
153 }
154
155 static void aura_force_by_monster_attack(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr)
156 {
157     if (!player_ptr->tim_sh_touki || !monap_ptr->alive || player_ptr->is_dead)
158         return;
159
160     auto *r_ptr = &r_info[monap_ptr->m_ptr->r_idx];
161     if ((r_ptr->flagsr & RFR_RES_ALL) != 0) {
162         if (is_original_ap_and_seen(player_ptr, monap_ptr->m_ptr))
163             r_ptr->r_flagsr |= RFR_RES_ALL;
164
165         return;
166     }
167
168     HIT_POINT dam = damroll(2, 6);
169     dam = mon_damage_mod(player_ptr, monap_ptr->m_ptr, dam, false);
170     msg_format(_("%^sが鋭い闘気のオーラで傷ついた!", "%^s is injured by the Force"), monap_ptr->m_name);
171     MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear, AttributeType::MANA);
172     if (mdp.mon_take_hit(_("は倒れた。", " is destroyed."))) {
173         monap_ptr->blinked = false;
174         monap_ptr->alive = false;
175     }
176 }
177
178 static void aura_shadow_by_monster_attack(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr)
179 {
180     if (!SpellHex(player_ptr).is_spelling_specific(HEX_SHADOW_CLOAK) || !monap_ptr->alive || player_ptr->is_dead)
181         return;
182
183     HIT_POINT dam = 1;
184     ObjectType *o_armed_ptr = &player_ptr->inventory_list[INVEN_MAIN_HAND];
185     auto *r_ptr = &r_info[monap_ptr->m_ptr->r_idx];
186     if (((r_ptr->flagsr & RFR_RES_ALL) != 0) || ((r_ptr->flagsr & RFR_RES_DARK) != 0)) {
187         if (is_original_ap_and_seen(player_ptr, monap_ptr->m_ptr))
188             r_ptr->r_flagsr |= (RFR_RES_ALL | RFR_RES_DARK);
189
190         return;
191     }
192
193     if (o_armed_ptr->k_idx) {
194         int basedam = ((o_armed_ptr->dd + player_ptr->to_dd[0]) * (o_armed_ptr->ds + player_ptr->to_ds[0] + 1));
195         dam = basedam / 2 + o_armed_ptr->to_d + player_ptr->to_d[0];
196     }
197
198     o_armed_ptr = &player_ptr->inventory_list[INVEN_BODY];
199     if ((o_armed_ptr->k_idx) && o_armed_ptr->is_cursed())
200         dam *= 2;
201
202     dam = mon_damage_mod(player_ptr, monap_ptr->m_ptr, dam, false);
203     msg_format(_("影のオーラが%^sに反撃した!", "Enveloping shadows attack %^s."), monap_ptr->m_name);
204     MonsterDamageProcessor mdp(player_ptr, monap_ptr->m_idx, dam, &monap_ptr->fear, AttributeType::DARK);
205     if (mdp.mon_take_hit(_("は倒れた。", " is destroyed."))) {
206         monap_ptr->blinked = false;
207         monap_ptr->alive = false;
208         return;
209     }
210
211     struct attribute_table {
212         inventory_slot_type slot;
213         AttributeType type;
214     };
215
216     const int TABLE_SIZE = 4;
217     attribute_table table[TABLE_SIZE] = { { INVEN_HEAD, AttributeType::OLD_CONF }, { INVEN_SUB_HAND, AttributeType::OLD_SLEEP },
218         { INVEN_ARMS, AttributeType::TURN_ALL }, { INVEN_FEET, AttributeType::OLD_SLOW } };
219
220     BIT_FLAGS flg = PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL;
221
222     /* Some cursed armours gives an extra effect */
223     for (int j = 0; j < TABLE_SIZE; j++) {
224         o_armed_ptr = &player_ptr->inventory_list[table[j].slot];
225         if ((o_armed_ptr->k_idx) && o_armed_ptr->is_cursed() && o_armed_ptr->is_armour())
226             project(player_ptr, 0, 0, monap_ptr->m_ptr->fy, monap_ptr->m_ptr->fx, (player_ptr->lev * 2), table[j].type, flg);
227     }
228 }
229
230 void process_aura_counterattack(PlayerType *player_ptr, MonsterAttackPlayer *monap_ptr)
231 {
232     if (!monap_ptr->touched)
233         return;
234
235     aura_fire_by_monster_attack(player_ptr, monap_ptr);
236     aura_elec_by_monster_attack(player_ptr, monap_ptr);
237     aura_cold_by_monster_attack(player_ptr, monap_ptr);
238     aura_shards_by_monster_attack(player_ptr, monap_ptr);
239     aura_holy_by_monster_attack(player_ptr, monap_ptr);
240     aura_force_by_monster_attack(player_ptr, monap_ptr);
241     aura_shadow_by_monster_attack(player_ptr, monap_ptr);
242 }