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-status.h"
13 #include "monster-attack/monster-eating.h"
14 #include "monster/monster-status.h"
15 #include "monster/monster-update.h"
16 #include "player/player-damage.h"
17 #include "player/player-status-flags.h"
18 #include "player/player-status-resist.h"
19 #include "spell-kind/earthquake.h"
20 #include "spell-kind/spells-equipment.h"
21 #include "status/bad-status-setter.h"
22 #include "status/base-status.h"
23 #include "status/element-resistance.h"
24 #include "status/experience.h"
25 #include "system/object-type-definition.h"
26 #include "view/display-messages.h"
30 * @param target_ptr プレーヤーへの参照ポインタ
31 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
33 * @detail 減衰の計算式がpoisではなくnukeなのは仕様 (1/3では減衰が強すぎると判断したため)
35 static void calc_blow_poison(player_type *target_ptr, monap_type *monap_ptr)
37 if (monap_ptr->explode)
40 if (!(target_ptr->resist_pois || is_oppose_pois(target_ptr)) && !check_multishadow(target_ptr)
41 && set_poisoned(target_ptr, target_ptr->poisoned + randint1(monap_ptr->rlev) + 5))
42 monap_ptr->obvious = TRUE;
44 monap_ptr->damage = monap_ptr->damage * calc_nuke_damage_rate(target_ptr) / 100;
45 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
46 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_POIS);
50 * @brief 劣化ダメージを計算する (耐性があれば、(1d4 + 4) / 9になる)
51 * @param target_ptr プレーヤーへの参照ポインタ
52 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
55 static void calc_blow_disenchant(player_type *target_ptr, monap_type *monap_ptr)
57 if (monap_ptr->explode)
60 if (!target_ptr->resist_disen && !check_multishadow(target_ptr) && apply_disenchant(target_ptr, 0)) {
61 update_creature(target_ptr);
62 monap_ptr->obvious = TRUE;
65 if (is_resist_disen(target_ptr))
66 monap_ptr->damage = monap_ptr->damage * (randint1(4) + 4) / 9;
68 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
69 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_DISEN);
73 * @brief 盲目ダメージを計算する (耐性があれば、(1d4 + 3) / 8になる)
74 * @param target_ptr プレーヤーへの参照ポインタ
75 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
78 static void calc_blow_blind(player_type *target_ptr, monap_type *monap_ptr)
80 if (is_resist_blind(target_ptr))
81 monap_ptr->damage = monap_ptr->damage * (randint1(4) + 3) / 8;
83 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
84 if (target_ptr->is_dead)
87 process_blind_attack(target_ptr, monap_ptr);
88 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_BLIND);
92 * @brief 混乱ダメージを計算する (耐性があれば、(1d4 + 3) / 8になる)
93 * @param target_ptr プレーヤーへの参照ポインタ
94 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
97 static void calc_blow_confusion(player_type *target_ptr, monap_type *monap_ptr)
99 if (monap_ptr->explode)
102 if (is_resist_conf(target_ptr))
103 monap_ptr->damage = monap_ptr->damage * (randint1(4) + 3) / 8;
105 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
106 if (target_ptr->is_dead)
109 if (!target_ptr->resist_conf && !check_multishadow(target_ptr) && set_confused(target_ptr, target_ptr->confused + 3 + randint1(monap_ptr->rlev)))
110 monap_ptr->obvious = TRUE;
112 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_CONF);
116 * @brief 恐怖ダメージを計算する (耐性があれば、(1d4 + 3) / 8になる)
117 * @param target_ptr プレーヤーへの参照ポインタ
118 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
121 static void calc_blow_fear(player_type *target_ptr, monap_type *monap_ptr)
123 if (is_resist_fear(target_ptr))
124 monap_ptr->damage = monap_ptr->damage * (randint1(4) + 3) / 8;
126 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
127 if (target_ptr->is_dead)
130 process_terrify_attack(target_ptr, monap_ptr);
131 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_FEAR);
135 * @brief 麻痺ダメージを計算する (耐性があれば、(1d4 + 3) / 8になる)
136 * @param target_ptr プレーヤーへの参照ポインタ
137 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
140 static void calc_blow_paralysis(player_type *target_ptr, monap_type *monap_ptr)
142 if (has_free_act(target_ptr))
143 monap_ptr->damage = monap_ptr->damage * (randint1(4) + 3) / 8;
145 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
146 if (target_ptr->is_dead)
149 process_paralyze_attack(target_ptr, monap_ptr);
150 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_FREE);
154 * @brief 病気ダメージを計算する (毒耐性があれば、(1d4 + 4) / 9になる。二重耐性なら更に(1d4 + 4) / 9)
155 * @param target_ptr プレーヤーへの参照ポインタ
156 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
158 * @details 10% (毒の一次耐性があれば4%、二重耐性ならば1.6%)の確率で耐久が低下し、更に1/10の確率で永久低下する
160 static void calc_blow_disease(player_type *target_ptr, monap_type *monap_ptr)
162 if (is_resist_pois(target_ptr))
163 monap_ptr->damage = monap_ptr->damage * (randint1(4) + 4) / 9;
165 if (is_oppose_pois(target_ptr))
166 monap_ptr->damage = monap_ptr->damage * (randint1(4) + 4) / 9;
168 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
169 if (target_ptr->is_dead || check_multishadow(target_ptr))
172 if (!(target_ptr->resist_pois || is_oppose_pois(target_ptr)) && set_poisoned(target_ptr, target_ptr->poisoned + randint1(monap_ptr->rlev) + 5))
173 monap_ptr->obvious = TRUE;
175 bool disease_possibility = randint1(100) > calc_nuke_damage_rate(target_ptr);
176 if (disease_possibility || (randint1(100) > 10) || (target_ptr->prace == RACE_ANDROID))
179 bool perm = one_in_(10);
180 if (dec_stat(target_ptr, A_CON, randint1(10), perm)) {
181 msg_print(_("病があなたを蝕んでいる気がする。", "You feel sickly."));
182 monap_ptr->obvious = TRUE;
187 * @brief 腕力低下ダメージを計算する (維持があれば、(1d4 + 4) / 9になる)
188 * @param target_ptr プレーヤーへの参照ポインタ
189 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
192 static void calc_blow_lose_strength(player_type *target_ptr, monap_type *monap_ptr)
194 if (is_sustain_str(target_ptr))
195 monap_ptr->get_damage = monap_ptr->get_damage * (randint1(4) + 4) / 9;
197 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
198 if (target_ptr->is_dead || check_multishadow(target_ptr))
201 if (do_dec_stat(target_ptr, A_STR))
202 monap_ptr->obvious = TRUE;
206 * @brief 知能低下ダメージを計算する (維持があれば、(1d4 + 4) / 9になる)
207 * @param target_ptr プレーヤーへの参照ポインタ
208 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
211 static void calc_blow_lose_intelligence(player_type *target_ptr, monap_type *monap_ptr)
213 if (is_sustain_int(target_ptr))
214 monap_ptr->get_damage = monap_ptr->get_damage * (randint1(4) + 4) / 9;
216 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
217 if (target_ptr->is_dead || check_multishadow(target_ptr))
220 if (do_dec_stat(target_ptr, A_INT))
221 monap_ptr->obvious = TRUE;
225 * @brief 賢さ低下ダメージを計算する (維持があれば、(1d4 + 4) / 9になる)
226 * @param target_ptr プレーヤーへの参照ポインタ
227 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
230 static void calc_blow_lose_wisdom(player_type *target_ptr, monap_type *monap_ptr)
232 if (is_sustain_wis(target_ptr))
233 monap_ptr->get_damage = monap_ptr->get_damage * (randint1(4) + 4) / 9;
235 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
236 if (target_ptr->is_dead || check_multishadow(target_ptr))
239 if (do_dec_stat(target_ptr, A_WIS))
240 monap_ptr->obvious = TRUE;
244 * @brief 器用低下ダメージを計算する (維持があれば、(1d4 + 4) / 9になる)
245 * @param target_ptr プレーヤーへの参照ポインタ
246 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
249 static void calc_blow_lose_dexterity(player_type *target_ptr, monap_type *monap_ptr)
251 if (is_sustain_dex(target_ptr))
252 monap_ptr->get_damage = monap_ptr->get_damage * (randint1(4) + 4) / 9;
254 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
255 if (target_ptr->is_dead || check_multishadow(target_ptr))
258 if (do_dec_stat(target_ptr, A_DEX))
259 monap_ptr->obvious = TRUE;
263 * @brief 耐久低下ダメージを計算する (維持があれば、(1d4 + 4) / 9になる)
264 * @param target_ptr プレーヤーへの参照ポインタ
265 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
268 static void calc_blow_lose_constitution(player_type *target_ptr, monap_type *monap_ptr)
270 if (is_sustain_con(target_ptr))
271 monap_ptr->get_damage = monap_ptr->get_damage * (randint1(4) + 4) / 9;
273 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
274 if (target_ptr->is_dead || check_multishadow(target_ptr))
277 if (do_dec_stat(target_ptr, A_CON))
278 monap_ptr->obvious = TRUE;
282 * @brief 魅力低下ダメージを計算する (維持があれば、(1d4 + 4) / 9になる)
283 * @param target_ptr プレーヤーへの参照ポインタ
284 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
287 static void calc_blow_lose_charisma(player_type *target_ptr, monap_type *monap_ptr)
289 if (is_sustain_chr(target_ptr))
290 monap_ptr->get_damage = monap_ptr->get_damage * (randint1(4) + 4) / 9;
292 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
293 if (target_ptr->is_dead || check_multishadow(target_ptr))
296 if (do_dec_stat(target_ptr, A_CHR))
297 monap_ptr->obvious = TRUE;
301 * @brief 全能力低下ダメージを計算する (維持があれば、1つに付き-3%軽減する)
302 * @param target_ptr プレーヤーへの参照ポインタ
303 * @param monap_ptr モンスターからプレーヤーへの直接攻撃構造体への参照ポインタ
306 static void calc_blow_lose_all(player_type *target_ptr, monap_type *monap_ptr)
308 int damage_ratio = 100;
309 if (is_sustain_str(target_ptr))
312 if (is_sustain_int(target_ptr))
315 if (is_sustain_wis(target_ptr))
318 if (is_sustain_dex(target_ptr))
321 if (is_sustain_con(target_ptr))
324 if (is_sustain_chr(target_ptr))
327 monap_ptr->damage = monap_ptr->damage * damage_ratio / 100;
328 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
329 if (target_ptr->is_dead || check_multishadow(target_ptr))
332 process_lose_all_attack(target_ptr, monap_ptr);
335 void switch_monster_blow_to_player(player_type *target_ptr, monap_type *monap_ptr)
337 switch (monap_ptr->effect) {
339 monap_ptr->obvious = TRUE;
340 monap_ptr->damage = 0;
342 case RBE_SUPERHURT: { /* AC軽減あり / Player armor reduces total damage */
343 if (((randint1(monap_ptr->rlev * 2 + 300) > (monap_ptr->ac + 200)) || one_in_(13)) && !check_multishadow(target_ptr)) {
344 int tmp_damage = monap_ptr->damage - (monap_ptr->damage * ((monap_ptr->ac < 150) ? monap_ptr->ac : 150) / 250);
345 msg_print(_("痛恨の一撃!", "It was a critical hit!"));
346 tmp_damage = MAX(monap_ptr->damage, tmp_damage * 2);
347 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, tmp_damage, monap_ptr->ddesc, -1);
352 case RBE_HURT: { /* AC軽減あり / Player armor reduces total damage */
353 monap_ptr->obvious = TRUE;
354 monap_ptr->damage -= (monap_ptr->damage * ((monap_ptr->ac < 150) ? monap_ptr->ac : 150) / 250);
355 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
359 calc_blow_poison(target_ptr, monap_ptr);
362 calc_blow_disenchant(target_ptr, monap_ptr);
365 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
366 if (target_ptr->is_dead || check_multishadow(target_ptr))
369 for (int i = 0; i < 10; i++) {
370 INVENTORY_IDX i_idx = (INVENTORY_IDX)randint0(INVEN_PACK);
371 monap_ptr->o_ptr = &target_ptr->inventory_list[i_idx];
372 if (monap_ptr->o_ptr->k_idx == 0)
375 if (process_un_power(target_ptr, monap_ptr))
382 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
383 if (monster_confused_remaining(monap_ptr->m_ptr))
386 if (target_ptr->is_dead || check_multishadow(target_ptr))
389 monap_ptr->obvious = TRUE;
390 process_eat_gold(target_ptr, monap_ptr);
394 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
395 if (!check_eat_item(target_ptr, monap_ptr))
398 process_eat_item(target_ptr, monap_ptr);
403 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
404 if (target_ptr->is_dead || check_multishadow(target_ptr))
407 process_eat_food(target_ptr, monap_ptr);
411 monap_ptr->o_ptr = &target_ptr->inventory_list[INVEN_LITE];
412 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
413 if (target_ptr->is_dead || check_multishadow(target_ptr))
416 process_eat_lite(target_ptr, monap_ptr);
420 if (monap_ptr->explode)
423 monap_ptr->obvious = TRUE;
424 msg_print(_("酸を浴びせられた!", "You are covered in acid!"));
425 monap_ptr->get_damage += acid_dam(target_ptr, monap_ptr->damage, monap_ptr->ddesc, -1, FALSE);
426 update_creature(target_ptr);
427 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_ACID);
431 if (monap_ptr->explode)
434 monap_ptr->obvious = TRUE;
435 msg_print(_("電撃を浴びせられた!", "You are struck by electricity!"));
436 monap_ptr->get_damage += elec_dam(target_ptr, monap_ptr->damage, monap_ptr->ddesc, -1, FALSE);
437 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_ELEC);
441 if (monap_ptr->explode)
444 monap_ptr->obvious = TRUE;
445 msg_print(_("全身が炎に包まれた!", "You are enveloped in flames!"));
446 monap_ptr->get_damage += fire_dam(target_ptr, monap_ptr->damage, monap_ptr->ddesc, -1, FALSE);
447 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_FIRE);
451 if (monap_ptr->explode)
454 monap_ptr->obvious = TRUE;
455 msg_print(_("全身が冷気で覆われた!", "You are covered with frost!"));
456 monap_ptr->get_damage += cold_dam(target_ptr, monap_ptr->damage, monap_ptr->ddesc, -1, FALSE);
457 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_COLD);
461 calc_blow_blind(target_ptr, monap_ptr);
464 calc_blow_confusion(target_ptr, monap_ptr);
467 calc_blow_fear(target_ptr, monap_ptr);
470 calc_blow_paralysis(target_ptr, monap_ptr);
473 calc_blow_lose_strength(target_ptr, monap_ptr);
476 calc_blow_lose_intelligence(target_ptr, monap_ptr);
479 calc_blow_lose_wisdom(target_ptr, monap_ptr);
482 calc_blow_lose_dexterity(target_ptr, monap_ptr);
485 calc_blow_lose_constitution(target_ptr, monap_ptr);
488 calc_blow_lose_charisma(target_ptr, monap_ptr);
491 calc_blow_lose_all(target_ptr, monap_ptr);
493 case RBE_SHATTER: { /* AC軽減あり / Player armor reduces total damage */
494 monap_ptr->obvious = TRUE;
495 monap_ptr->damage -= (monap_ptr->damage * ((monap_ptr->ac < 150) ? monap_ptr->ac : 150) / 250);
496 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
497 if (monap_ptr->damage > 23 || monap_ptr->explode)
498 earthquake(target_ptr, monap_ptr->m_ptr->fy, monap_ptr->m_ptr->fx, 8, monap_ptr->m_idx);
503 s32b d = damroll(10, 6) + (target_ptr->exp / 100) * MON_DRAIN_LIFE;
504 monap_ptr->obvious = TRUE;
505 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
506 if (target_ptr->is_dead || check_multishadow(target_ptr))
509 (void)drain_exp(target_ptr, d, d / 10, 95);
513 s32b d = damroll(20, 6) + (target_ptr->exp / 100) * MON_DRAIN_LIFE;
514 monap_ptr->obvious = TRUE;
515 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
516 if (target_ptr->is_dead || check_multishadow(target_ptr))
519 (void)drain_exp(target_ptr, d, d / 10, 90);
523 s32b d = damroll(40, 6) + (target_ptr->exp / 100) * MON_DRAIN_LIFE;
524 monap_ptr->obvious = TRUE;
525 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
526 if (target_ptr->is_dead || check_multishadow(target_ptr))
529 (void)drain_exp(target_ptr, d, d / 10, 75);
533 s32b d = damroll(80, 6) + (target_ptr->exp / 100) * MON_DRAIN_LIFE;
534 monap_ptr->obvious = TRUE;
535 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
536 if (target_ptr->is_dead || check_multishadow(target_ptr))
539 (void)drain_exp(target_ptr, d, d / 10, 50);
543 calc_blow_didease(target_ptr, monap_ptr);
546 if (monap_ptr->explode)
549 process_monster_attack_time(target_ptr, monap_ptr);
550 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
554 s32b d = damroll(60, 6) + (target_ptr->exp / 100) * MON_DRAIN_LIFE;
555 monap_ptr->obvious = TRUE;
556 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
557 if (target_ptr->is_dead || check_multishadow(target_ptr))
560 bool resist_drain = check_drain_hp(target_ptr, d);
561 process_drain_life(target_ptr, monap_ptr, resist_drain);
565 monap_ptr->obvious = TRUE;
566 process_drain_mana(target_ptr, monap_ptr);
567 update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_MANA);
571 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
572 if (target_ptr->is_dead)
575 if (check_multishadow(target_ptr)) {
578 if (set_slow(target_ptr, (target_ptr->slow + 4 + randint0(monap_ptr->rlev / 10)), FALSE)) {
579 monap_ptr->obvious = TRUE;
586 monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
587 if (target_ptr->is_dead)
590 process_stun_attack(target_ptr, monap_ptr);