2 * @brief モンスターからプレーヤーへの直接攻撃をその種別において振り分ける
5 * @details 長い処理はインクルード先の別ファイルにて行っている
8 #include "monster-attack/monster-attack-switcher.h"
9 #include "inventory/inventory-slot-types.h"
10 #include "mind/drs-types.h"
11 #include "mind/mind-mirror-master.h"
12 #include "monster-attack/monster-attack-lose.h"
13 #include "monster-attack/monster-attack-status.h"
14 #include "monster-attack/monster-eating.h"
15 #include "monster/monster-status.h"
16 #include "monster/monster-update.h"
17 #include "player/player-damage.h"
18 #include "player/player-status-flags.h"
19 #include "player/player-status-resist.h"
20 #include "spell-kind/earthquake.h"
21 #include "spell-kind/spells-equipment.h"
22 #include "status/bad-status-setter.h"
23 #include "status/base-status.h"
24 #include "status/element-resistance.h"
25 #include "status/experience.h"
26 #include "system/object-type-definition.h"
27 #include "view/display-messages.h"
31 * @param target_ptr プレーヤーへの参照ポインタ
32 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
34 * @detail 減衰の計算式がpoisではなくnukeなのは仕様 (1/3では減衰が強すぎると判断したため)
36 static void calc_blow_poison(player_type *target_ptr, monap_type *monap_ptr)
38 if (monap_ptr->explode)
41 if (!(target_ptr->resist_pois || is_oppose_pois(target_ptr)) && !check_multishadow(target_ptr)
42 && set_poisoned(target_ptr, target_ptr->poisoned + randint1(monap_ptr->rlev) + 5))
43 monap_ptr->obvious = TRUE;
45 monap_ptr->damage = monap_ptr->damage * calc_nuke_damage_rate(target_ptr) / 100;
46 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
47 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_POIS);
51 * @brief 劣化ダメージを計算する (耐性があれば、(1d4 + 4) / 9になる)
52 * @param target_ptr プレーヤーへの参照ポインタ
53 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
56 static void calc_blow_disenchant(player_type *target_ptr, monap_type *monap_ptr)
58 if (monap_ptr->explode)
61 if (!target_ptr->resist_disen && !check_multishadow(target_ptr) && apply_disenchant(target_ptr, 0)) {
62 update_creature(target_ptr);
63 monap_ptr->obvious = TRUE;
66 if (is_resist_disen(target_ptr))
67 monap_ptr->damage = monap_ptr->damage * (randint1(4) + 4) / 9;
69 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
70 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_DISEN);
74 * @brief 盲目ダメージを計算する (耐性があれば、(1d4 + 3) / 8になる)
75 * @param target_ptr プレーヤーへの参照ポインタ
76 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
79 static void calc_blow_blind(player_type *target_ptr, monap_type *monap_ptr)
81 if (is_resist_blind(target_ptr))
82 monap_ptr->damage = monap_ptr->damage * (randint1(4) + 3) / 8;
84 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
85 if (target_ptr->is_dead)
88 process_blind_attack(target_ptr, monap_ptr);
89 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_BLIND);
93 * @brief 混乱ダメージを計算する (耐性があれば、(1d4 + 3) / 8になる)
94 * @param target_ptr プレーヤーへの参照ポインタ
95 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
98 static void calc_blow_confusion(player_type *target_ptr, monap_type *monap_ptr)
100 if (monap_ptr->explode)
103 if (is_resist_conf(target_ptr))
104 monap_ptr->damage = monap_ptr->damage * (randint1(4) + 3) / 8;
106 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
107 if (target_ptr->is_dead)
110 if (!target_ptr->resist_conf && !check_multishadow(target_ptr) && set_confused(target_ptr, target_ptr->confused + 3 + randint1(monap_ptr->rlev)))
111 monap_ptr->obvious = TRUE;
113 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_CONF);
117 * @brief 恐怖ダメージを計算する (耐性があれば、(1d4 + 3) / 8になる)
118 * @param target_ptr プレーヤーへの参照ポインタ
119 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
122 static void calc_blow_fear(player_type *target_ptr, monap_type *monap_ptr)
124 if (is_resist_fear(target_ptr))
125 monap_ptr->damage = monap_ptr->damage * (randint1(4) + 3) / 8;
127 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
128 if (target_ptr->is_dead)
131 process_terrify_attack(target_ptr, monap_ptr);
132 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_FEAR);
136 * @brief 麻痺ダメージを計算する (耐性があれば、(1d4 + 3) / 8になる)
137 * @param target_ptr プレーヤーへの参照ポインタ
138 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
141 static void calc_blow_paralysis(player_type *target_ptr, monap_type *monap_ptr)
143 if (has_free_act(target_ptr))
144 monap_ptr->damage = monap_ptr->damage * (randint1(4) + 3) / 8;
146 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
147 if (target_ptr->is_dead)
150 process_paralyze_attack(target_ptr, monap_ptr);
151 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_FREE);
154 void switch_monster_blow_to_player(player_type *target_ptr, monap_type *monap_ptr)
156 switch (monap_ptr->effect) {
158 monap_ptr->obvious = TRUE;
159 monap_ptr->damage = 0;
161 case RBE_SUPERHURT: { /* AC軽減あり / Player armor reduces total damage */
162 if (((randint1(monap_ptr->rlev * 2 + 300) > (monap_ptr->ac + 200)) || one_in_(13)) && !check_multishadow(target_ptr)) {
163 int tmp_damage = monap_ptr->damage - (monap_ptr->damage * ((monap_ptr->ac < 150) ? monap_ptr->ac : 150) / 250);
164 msg_print(_("痛恨の一撃!", "It was a critical hit!"));
165 tmp_damage = MAX(monap_ptr->damage, tmp_damage * 2);
166 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, tmp_damage, monap_ptr->ddesc, -1);
171 case RBE_HURT: { /* AC軽減あり / Player armor reduces total damage */
172 monap_ptr->obvious = TRUE;
173 monap_ptr->damage -= (monap_ptr->damage * ((monap_ptr->ac < 150) ? monap_ptr->ac : 150) / 250);
174 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
178 calc_blow_poison(target_ptr, monap_ptr);
181 calc_blow_disenchant(target_ptr, monap_ptr);
184 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
185 if (target_ptr->is_dead || check_multishadow(target_ptr))
188 for (int i = 0; i < 10; i++) {
189 INVENTORY_IDX i_idx = (INVENTORY_IDX)randint0(INVEN_PACK);
190 monap_ptr->o_ptr = &target_ptr->inventory_list[i_idx];
191 if (monap_ptr->o_ptr->k_idx == 0)
194 if (process_un_power(target_ptr, monap_ptr))
201 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
202 if (monster_confused_remaining(monap_ptr->m_ptr))
205 if (target_ptr->is_dead || check_multishadow(target_ptr))
208 monap_ptr->obvious = TRUE;
209 process_eat_gold(target_ptr, monap_ptr);
213 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
214 if (!check_eat_item(target_ptr, monap_ptr))
217 process_eat_item(target_ptr, monap_ptr);
222 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
223 if (target_ptr->is_dead || check_multishadow(target_ptr))
226 process_eat_food(target_ptr, monap_ptr);
230 monap_ptr->o_ptr = &target_ptr->inventory_list[INVEN_LITE];
231 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
232 if (target_ptr->is_dead || check_multishadow(target_ptr))
235 process_eat_lite(target_ptr, monap_ptr);
239 if (monap_ptr->explode)
242 monap_ptr->obvious = TRUE;
243 msg_print(_("酸を浴びせられた!", "You are covered in acid!"));
244 monap_ptr->get_damage += acid_dam(target_ptr, monap_ptr->damage, monap_ptr->ddesc, -1, FALSE);
245 update_creature(target_ptr);
246 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_ACID);
250 if (monap_ptr->explode)
253 monap_ptr->obvious = TRUE;
254 msg_print(_("電撃を浴びせられた!", "You are struck by electricity!"));
255 monap_ptr->get_damage += elec_dam(target_ptr, monap_ptr->damage, monap_ptr->ddesc, -1, FALSE);
256 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_ELEC);
260 if (monap_ptr->explode)
263 monap_ptr->obvious = TRUE;
264 msg_print(_("全身が炎に包まれた!", "You are enveloped in flames!"));
265 monap_ptr->get_damage += fire_dam(target_ptr, monap_ptr->damage, monap_ptr->ddesc, -1, FALSE);
266 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_FIRE);
270 if (monap_ptr->explode)
273 monap_ptr->obvious = TRUE;
274 msg_print(_("全身が冷気で覆われた!", "You are covered with frost!"));
275 monap_ptr->get_damage += cold_dam(target_ptr, monap_ptr->damage, monap_ptr->ddesc, -1, FALSE);
276 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_COLD);
280 calc_blow_blind(target_ptr, monap_ptr);
283 calc_blow_confusion(target_ptr, monap_ptr);
286 calc_blow_fear(target_ptr, monap_ptr);
289 calc_blow_paralysis(target_ptr, monap_ptr);
292 calc_blow_lose_strength(target_ptr, monap_ptr);
295 calc_blow_lose_intelligence(target_ptr, monap_ptr);
298 calc_blow_lose_wisdom(target_ptr, monap_ptr);
301 calc_blow_lose_dexterity(target_ptr, monap_ptr);
304 calc_blow_lose_constitution(target_ptr, monap_ptr);
307 calc_blow_lose_charisma(target_ptr, monap_ptr);
310 calc_blow_lose_all(target_ptr, monap_ptr);
312 case RBE_SHATTER: { /* AC軽減あり / Player armor reduces total damage */
313 monap_ptr->obvious = TRUE;
314 monap_ptr->damage -= (monap_ptr->damage * ((monap_ptr->ac < 150) ? monap_ptr->ac : 150) / 250);
315 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
316 if (monap_ptr->damage > 23 || monap_ptr->explode)
317 earthquake(target_ptr, monap_ptr->m_ptr->fy, monap_ptr->m_ptr->fx, 8, monap_ptr->m_idx);
322 s32b d = damroll(10, 6) + (target_ptr->exp / 100) * MON_DRAIN_LIFE;
323 monap_ptr->obvious = TRUE;
324 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
325 if (target_ptr->is_dead || check_multishadow(target_ptr))
328 (void)drain_exp(target_ptr, d, d / 10, 95);
332 s32b d = damroll(20, 6) + (target_ptr->exp / 100) * MON_DRAIN_LIFE;
333 monap_ptr->obvious = TRUE;
334 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
335 if (target_ptr->is_dead || check_multishadow(target_ptr))
338 (void)drain_exp(target_ptr, d, d / 10, 90);
342 s32b d = damroll(40, 6) + (target_ptr->exp / 100) * MON_DRAIN_LIFE;
343 monap_ptr->obvious = TRUE;
344 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
345 if (target_ptr->is_dead || check_multishadow(target_ptr))
348 (void)drain_exp(target_ptr, d, d / 10, 75);
352 s32b d = damroll(80, 6) + (target_ptr->exp / 100) * MON_DRAIN_LIFE;
353 monap_ptr->obvious = TRUE;
354 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
355 if (target_ptr->is_dead || check_multishadow(target_ptr))
358 (void)drain_exp(target_ptr, d, d / 10, 50);
362 calc_blow_disease(target_ptr, monap_ptr);
365 if (monap_ptr->explode)
368 process_monster_attack_time(target_ptr, monap_ptr);
369 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
373 s32b d = damroll(60, 6) + (target_ptr->exp / 100) * MON_DRAIN_LIFE;
374 monap_ptr->obvious = TRUE;
375 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
376 if (target_ptr->is_dead || check_multishadow(target_ptr))
379 bool resist_drain = check_drain_hp(target_ptr, d);
380 process_drain_life(target_ptr, monap_ptr, resist_drain);
384 monap_ptr->obvious = TRUE;
385 process_drain_mana(target_ptr, monap_ptr);
386 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_MANA);
390 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
391 if (target_ptr->is_dead)
394 if (check_multishadow(target_ptr)) {
397 if (set_slow(target_ptr, (target_ptr->slow + 4 + randint0(monap_ptr->rlev / 10)), FALSE)) {
398 monap_ptr->obvious = TRUE;
405 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
406 if (target_ptr->is_dead)
409 process_stun_attack(target_ptr, monap_ptr);