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 (!(has_resist_pois(target_ptr) || 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 (!has_resist_disen(target_ptr) && !check_multishadow(target_ptr) && apply_disenchant(target_ptr, 0)) {
62 update_creature(target_ptr);
63 monap_ptr->obvious = TRUE;
66 if (has_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 魔道具吸収ダメージを計算する (消費魔力減少、呪文失敗率減少、魔道具使用能力向上があればそれぞれ-7.5%)
75 * @param target_ptr プレーヤーへの参照ポインタ
76 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
78 * @detals 魔道具使用能力向上フラグがあれば、吸収対象のアイテムをスキャンされる回数が半分で済む
80 static void calc_blow_un_power(player_type *target_ptr, monap_type *monap_ptr)
82 int damage_ratio = 1000;
83 if (has_dec_mana(target_ptr))
86 if (has_easy_spell(target_ptr))
89 bool is_magic_mastery = has_magic_mastery(target_ptr) != 0;
93 monap_ptr->damage = monap_ptr->damage * damage_ratio / 1000;
94 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
95 if (target_ptr->is_dead || check_multishadow(target_ptr))
98 int max_draining_item = is_magic_mastery ? 5 : 10;
99 for (int i = 0; i < max_draining_item; i++) {
100 INVENTORY_IDX i_idx = (INVENTORY_IDX)randint0(INVEN_PACK);
101 monap_ptr->o_ptr = &target_ptr->inventory_list[i_idx];
102 if (monap_ptr->o_ptr->k_idx == 0)
105 if (process_un_power(target_ptr, monap_ptr))
111 * @brief 盲目ダメージを計算する (耐性があれば、(1d4 + 3) / 8になる)
112 * @param target_ptr プレーヤーへの参照ポインタ
113 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
116 static void calc_blow_blind(player_type *target_ptr, monap_type *monap_ptr)
118 if (has_resist_blind(target_ptr))
119 monap_ptr->damage = monap_ptr->damage * (randint1(4) + 3) / 8;
121 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
122 if (target_ptr->is_dead)
125 process_blind_attack(target_ptr, monap_ptr);
126 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_BLIND);
130 * @brief 混乱ダメージを計算する (耐性があれば、(1d4 + 3) / 8になる)
131 * @param target_ptr プレーヤーへの参照ポインタ
132 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
135 static void calc_blow_confusion(player_type *target_ptr, monap_type *monap_ptr)
137 if (monap_ptr->explode)
140 if (has_resist_conf(target_ptr))
141 monap_ptr->damage = monap_ptr->damage * (randint1(4) + 3) / 8;
143 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
144 if (target_ptr->is_dead)
147 if (!has_resist_conf(target_ptr) && !check_multishadow(target_ptr) && set_confused(target_ptr, target_ptr->confused + 3 + randint1(monap_ptr->rlev)))
148 monap_ptr->obvious = TRUE;
150 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_CONF);
154 * @brief 恐怖ダメージを計算する (耐性があれば、(1d4 + 3) / 8になる)
155 * @param target_ptr プレーヤーへの参照ポインタ
156 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
159 static void calc_blow_fear(player_type *target_ptr, monap_type *monap_ptr)
161 if (has_resist_fear(target_ptr))
162 monap_ptr->damage = monap_ptr->damage * (randint1(4) + 3) / 8;
164 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
165 if (target_ptr->is_dead)
168 process_terrify_attack(target_ptr, monap_ptr);
169 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_FEAR);
173 * @brief 麻痺ダメージを計算する (耐性があれば、(1d4 + 3) / 8になる)
174 * @param target_ptr プレーヤーへの参照ポインタ
175 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
178 static void calc_blow_paralysis(player_type *target_ptr, monap_type *monap_ptr)
180 if (has_free_act(target_ptr))
181 monap_ptr->damage = monap_ptr->damage * (randint1(4) + 3) / 8;
183 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
184 if (target_ptr->is_dead)
187 process_paralyze_attack(target_ptr, monap_ptr);
188 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_FREE);
192 * @brief 経験値吸収ダメージを計算する (経験値保持と地獄耐性があれば、それぞれ-7.5%)
193 * @param target_ptr プレーヤーへの参照ポインタ
194 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
197 static void calc_blow_drain_exp(player_type *target_ptr, monap_type *monap_ptr, const int drain_value, const int hold_exp_prob)
199 s32b d = damroll(drain_value, 6) + (target_ptr->exp / 100) * MON_DRAIN_LIFE;
200 monap_ptr->obvious = TRUE;
201 int damage_ratio = 1000;
202 if (has_hold_exp(target_ptr))
205 if (has_resist_neth(target_ptr))
208 monap_ptr->damage = monap_ptr->damage * damage_ratio / 1000;
209 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
210 if (target_ptr->is_dead || check_multishadow(target_ptr))
213 (void)drain_exp(target_ptr, d, d / 10, hold_exp_prob);
217 * @brief 時間逆転ダメージを計算する (耐性があれば、(1d4 + 4) / 9になる)
218 * @param target_ptr プレーヤーへの参照ポインタ
219 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
222 static void calc_blow_time(player_type *target_ptr, monap_type *monap_ptr)
224 if (monap_ptr->explode)
227 process_monster_attack_time(target_ptr, monap_ptr);
228 if (has_resist_time(target_ptr))
229 monap_ptr->damage = monap_ptr->damage * (randint1(4) + 4) / 9;
231 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
235 * @brief 生命力吸収ダメージを計算する (経験値維持があれば9/10になる)
236 * @param target_ptr プレーヤーへの参照ポインタ
237 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
240 static void calc_blow_drain_life(player_type *target_ptr, monap_type *monap_ptr)
242 s32b d = damroll(60, 6) + (target_ptr->exp / 100) * MON_DRAIN_LIFE;
243 monap_ptr->obvious = TRUE;
244 if (target_ptr->hold_exp)
245 monap_ptr->damage = monap_ptr->damage * 9 / 10;
247 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
248 if (target_ptr->is_dead || check_multishadow(target_ptr))
251 bool resist_drain = check_drain_hp(target_ptr, d);
252 process_drain_life(target_ptr, monap_ptr, resist_drain);
256 * @brief MPダメージを計算する (消費魔力減少、呪文失敗率減少、魔道具使用能力向上があればそれぞれ-5%)
257 * @param target_ptr プレーヤーへの参照ポインタ
258 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
261 static void calc_blow_drain_mana(player_type *target_ptr, monap_type *monap_ptr)
263 monap_ptr->obvious = TRUE;
264 int damage_ratio = 100;
265 if (has_dec_mana(target_ptr))
268 if (has_easy_spell(target_ptr))
271 if (has_magic_mastery(target_ptr))
274 monap_ptr->damage = monap_ptr->damage * damage_ratio / 100;
275 process_drain_mana(target_ptr, monap_ptr);
276 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_MANA);
279 static void calc_blow_inertia(player_type *target_ptr, monap_type *monap_ptr)
281 if ((target_ptr->fast > 0) || (target_ptr->pspeed >= 130))
282 monap_ptr->damage = monap_ptr->damage * (randint1(4) + 4) / 9;
284 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
285 if (target_ptr->is_dead || check_multishadow(target_ptr))
288 if (set_slow(target_ptr, (target_ptr->slow + 4 + randint0(monap_ptr->rlev / 10)), FALSE))
289 monap_ptr->obvious = TRUE;
292 void switch_monster_blow_to_player(player_type *target_ptr, monap_type *monap_ptr)
294 switch (monap_ptr->effect) {
296 monap_ptr->obvious = TRUE;
297 monap_ptr->damage = 0;
299 case RBE_SUPERHURT: { /* AC軽減あり / Player armor reduces total damage */
300 if (((randint1(monap_ptr->rlev * 2 + 300) > (monap_ptr->ac + 200)) || one_in_(13)) && !check_multishadow(target_ptr)) {
301 int tmp_damage = monap_ptr->damage - (monap_ptr->damage * ((monap_ptr->ac < 150) ? monap_ptr->ac : 150) / 250);
302 msg_print(_("痛恨の一撃!", "It was a critical hit!"));
303 tmp_damage = MAX(monap_ptr->damage, tmp_damage * 2);
304 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, tmp_damage, monap_ptr->ddesc, -1);
309 case RBE_HURT: { /* AC軽減あり / Player armor reduces total damage */
310 monap_ptr->obvious = TRUE;
311 monap_ptr->damage -= (monap_ptr->damage * ((monap_ptr->ac < 150) ? monap_ptr->ac : 150) / 250);
312 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
316 calc_blow_poison(target_ptr, monap_ptr);
319 calc_blow_disenchant(target_ptr, monap_ptr);
322 calc_blow_un_power(target_ptr, monap_ptr);
325 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
326 if (monster_confused_remaining(monap_ptr->m_ptr) || target_ptr->is_dead || check_multishadow(target_ptr))
329 monap_ptr->obvious = TRUE;
330 process_eat_gold(target_ptr, monap_ptr);
333 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
334 if (!check_eat_item(target_ptr, monap_ptr))
337 process_eat_item(target_ptr, monap_ptr);
342 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
343 if (target_ptr->is_dead || check_multishadow(target_ptr))
346 process_eat_food(target_ptr, monap_ptr);
350 monap_ptr->o_ptr = &target_ptr->inventory_list[INVEN_LITE];
351 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
352 if (target_ptr->is_dead || check_multishadow(target_ptr))
355 process_eat_lite(target_ptr, monap_ptr);
359 if (monap_ptr->explode)
362 monap_ptr->obvious = TRUE;
363 msg_print(_("酸を浴びせられた!", "You are covered in acid!"));
364 monap_ptr->get_damage += acid_dam(target_ptr, monap_ptr->damage, monap_ptr->ddesc, -1, FALSE);
365 update_creature(target_ptr);
366 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_ACID);
370 if (monap_ptr->explode)
373 monap_ptr->obvious = TRUE;
374 msg_print(_("電撃を浴びせられた!", "You are struck by electricity!"));
375 monap_ptr->get_damage += elec_dam(target_ptr, monap_ptr->damage, monap_ptr->ddesc, -1, FALSE);
376 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_ELEC);
380 if (monap_ptr->explode)
383 monap_ptr->obvious = TRUE;
384 msg_print(_("全身が炎に包まれた!", "You are enveloped in flames!"));
385 monap_ptr->get_damage += fire_dam(target_ptr, monap_ptr->damage, monap_ptr->ddesc, -1, FALSE);
386 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_FIRE);
390 if (monap_ptr->explode)
393 monap_ptr->obvious = TRUE;
394 msg_print(_("全身が冷気で覆われた!", "You are covered with frost!"));
395 monap_ptr->get_damage += cold_dam(target_ptr, monap_ptr->damage, monap_ptr->ddesc, -1, FALSE);
396 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_COLD);
400 calc_blow_blind(target_ptr, monap_ptr);
403 calc_blow_confusion(target_ptr, monap_ptr);
406 calc_blow_fear(target_ptr, monap_ptr);
409 calc_blow_paralysis(target_ptr, monap_ptr);
412 calc_blow_lose_strength(target_ptr, monap_ptr);
415 calc_blow_lose_intelligence(target_ptr, monap_ptr);
418 calc_blow_lose_wisdom(target_ptr, monap_ptr);
421 calc_blow_lose_dexterity(target_ptr, monap_ptr);
424 calc_blow_lose_constitution(target_ptr, monap_ptr);
427 calc_blow_lose_charisma(target_ptr, monap_ptr);
430 calc_blow_lose_all(target_ptr, monap_ptr);
432 case RBE_SHATTER: { /* AC軽減あり / Player armor reduces total damage */
433 monap_ptr->obvious = TRUE;
434 monap_ptr->damage -= (monap_ptr->damage * ((monap_ptr->ac < 150) ? monap_ptr->ac : 150) / 250);
435 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
436 if (monap_ptr->damage > 23 || monap_ptr->explode)
437 earthquake(target_ptr, monap_ptr->m_ptr->fy, monap_ptr->m_ptr->fx, 8, monap_ptr->m_idx);
442 calc_blow_drain_exp(target_ptr, monap_ptr, 10, 95);
445 calc_blow_drain_exp(target_ptr, monap_ptr, 20, 90);
448 calc_blow_drain_exp(target_ptr, monap_ptr, 40, 75);
451 calc_blow_drain_exp(target_ptr, monap_ptr, 80, 50);
454 calc_blow_disease(target_ptr, monap_ptr);
457 calc_blow_time(target_ptr, monap_ptr);
460 calc_blow_drain_life(target_ptr, monap_ptr);
463 calc_blow_drain_mana(target_ptr, monap_ptr);
466 calc_blow_inertia(target_ptr, monap_ptr);
469 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
470 if (target_ptr->is_dead)
473 process_stun_attack(target_ptr, monap_ptr);