OSDN Git Service

[Refactor] #40457 Moved the files relating monster's attack from combat/ to monster...
[hengband/hengband.git] / src / monster-attack / monster-attack-switcher.c
1 /*!
2  * @brief モンスターからプレーヤーへの直接攻撃をその種別において振り分ける
3  * @date 2020/05/31
4  * @author Hourier
5  * @details 長い処理はインクルード先の別ファイルにて行っている
6  */
7
8 #include "monster-attack/monster-attack-switcher.h"
9 #include "monster-attack/monster-attack-status.h"
10 #include "monster-attack/monster-eating.h"
11 #include "mind/mind-mirror-master.h"
12 #include "player/player-damage.h"
13 #include "player/player-effects.h"
14 #include "spell-kind/earthquake.h"
15 #include "spell/spells3.h"
16
17 void switch_monster_blow_to_player(player_type *target_ptr, monap_type *monap_ptr)
18 {
19     switch (monap_ptr->effect) {
20     case RBE_NONE: {
21         monap_ptr->obvious = TRUE;
22         monap_ptr->damage = 0;
23         break;
24     }
25     case RBE_SUPERHURT: { /* AC軽減あり / Player armor reduces total damage */
26         if (((randint1(monap_ptr->rlev * 2 + 300) > (monap_ptr->ac + 200)) || one_in_(13)) && !check_multishadow(target_ptr)) {
27             int tmp_damage = monap_ptr->damage - (monap_ptr->damage * ((monap_ptr->ac < 150) ? monap_ptr->ac : 150) / 250);
28             msg_print(_("痛恨の一撃!", "It was a critical hit!"));
29             tmp_damage = MAX(monap_ptr->damage, tmp_damage * 2);
30             monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, tmp_damage, monap_ptr->ddesc, -1);
31             break;
32         }
33     }
34         /* Fall through */
35     case RBE_HURT: { /* AC軽減あり / Player armor reduces total damage */
36         monap_ptr->obvious = TRUE;
37         monap_ptr->damage -= (monap_ptr->damage * ((monap_ptr->ac < 150) ? monap_ptr->ac : 150) / 250);
38         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
39         break;
40     }
41     case RBE_POISON: {
42         if (monap_ptr->explode)
43             break;
44
45         if (!(target_ptr->resist_pois || is_oppose_pois(target_ptr)) && !check_multishadow(target_ptr)) {
46             if (set_poisoned(target_ptr, target_ptr->poisoned + randint1(monap_ptr->rlev) + 5)) {
47                 monap_ptr->obvious = TRUE;
48             }
49         }
50
51         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
52         update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_POIS);
53         break;
54     }
55     case RBE_UN_BONUS: {
56         if (monap_ptr->explode)
57             break;
58
59         if (!target_ptr->resist_disen && !check_multishadow(target_ptr)) {
60             if (apply_disenchant(target_ptr, 0)) {
61                 update_creature(target_ptr);
62                 monap_ptr->obvious = TRUE;
63             }
64         }
65
66         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
67         update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_DISEN);
68         break;
69     }
70     case RBE_UN_POWER: {
71         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
72         if (target_ptr->is_dead || check_multishadow(target_ptr))
73             break;
74
75         for (int i = 0; i < 10; i++) {
76             INVENTORY_IDX i_idx = (INVENTORY_IDX)randint0(INVEN_PACK);
77             monap_ptr->o_ptr = &target_ptr->inventory_list[i_idx];
78             if (monap_ptr->o_ptr->k_idx == 0)
79                 continue;
80
81             if (process_un_power(target_ptr, monap_ptr))
82                 break;
83         }
84
85         break;
86     }
87     case RBE_EAT_GOLD: {
88         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
89         if (MON_CONFUSED(monap_ptr->m_ptr))
90             break;
91
92         if (target_ptr->is_dead || check_multishadow(target_ptr))
93             break;
94
95         monap_ptr->obvious = TRUE;
96         process_eat_gold(target_ptr, monap_ptr);
97         break;
98     }
99     case RBE_EAT_ITEM: {
100         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
101         if (!check_eat_item(target_ptr, monap_ptr))
102             break;
103
104         process_eat_item(target_ptr, monap_ptr);
105         break;
106     }
107
108     case RBE_EAT_FOOD: {
109         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
110         if (target_ptr->is_dead || check_multishadow(target_ptr))
111             break;
112
113         process_eat_food(target_ptr, monap_ptr);
114         break;
115     }
116     case RBE_EAT_LITE: {
117         monap_ptr->o_ptr = &target_ptr->inventory_list[INVEN_LITE];
118         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
119         if (target_ptr->is_dead || check_multishadow(target_ptr))
120             break;
121
122         process_eat_lite(target_ptr, monap_ptr);
123         break;
124     }
125     case RBE_ACID: {
126         if (monap_ptr->explode)
127             break;
128
129         monap_ptr->obvious = TRUE;
130         msg_print(_("酸を浴びせられた!", "You are covered in acid!"));
131         monap_ptr->get_damage += acid_dam(target_ptr, monap_ptr->damage, monap_ptr->ddesc, -1, FALSE);
132         update_creature(target_ptr);
133         update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_ACID);
134         break;
135     }
136     case RBE_ELEC: {
137         if (monap_ptr->explode)
138             break;
139         monap_ptr->obvious = TRUE;
140         msg_print(_("電撃を浴びせられた!", "You are struck by electricity!"));
141         monap_ptr->get_damage += elec_dam(target_ptr, monap_ptr->damage, monap_ptr->ddesc, -1, FALSE);
142         update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_ELEC);
143         break;
144     }
145     case RBE_FIRE: {
146         if (monap_ptr->explode)
147             break;
148         monap_ptr->obvious = TRUE;
149         msg_print(_("全身が炎に包まれた!", "You are enveloped in flames!"));
150         monap_ptr->get_damage += fire_dam(target_ptr, monap_ptr->damage, monap_ptr->ddesc, -1, FALSE);
151         update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_FIRE);
152         break;
153     }
154     case RBE_COLD: {
155         if (monap_ptr->explode)
156             break;
157         monap_ptr->obvious = TRUE;
158         msg_print(_("全身が冷気で覆われた!", "You are covered with frost!"));
159         monap_ptr->get_damage += cold_dam(target_ptr, monap_ptr->damage, monap_ptr->ddesc, -1, FALSE);
160         update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_COLD);
161         break;
162     }
163     case RBE_BLIND: {
164         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
165         if (target_ptr->is_dead)
166             break;
167
168         process_blind_attack(target_ptr, monap_ptr);
169         update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_BLIND);
170         break;
171     }
172     case RBE_CONFUSE: {
173         if (monap_ptr->explode)
174             break;
175
176         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
177         if (target_ptr->is_dead)
178             break;
179
180         if (!target_ptr->resist_conf && !check_multishadow(target_ptr)) {
181             if (set_confused(target_ptr, target_ptr->confused + 3 + randint1(monap_ptr->rlev))) {
182                 monap_ptr->obvious = TRUE;
183             }
184         }
185
186         update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_CONF);
187         break;
188     }
189     case RBE_TERRIFY: {
190         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
191         if (target_ptr->is_dead)
192             break;
193
194         process_terrify_attack(target_ptr, monap_ptr);
195         update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_FEAR);
196         break;
197     }
198     case RBE_PARALYZE: {
199         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
200
201         if (target_ptr->is_dead)
202             break;
203
204         process_paralyze_attack(target_ptr, monap_ptr);
205         update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_FREE);
206         break;
207     }
208     case RBE_LOSE_STR: {
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))
211             break;
212
213         if (do_dec_stat(target_ptr, A_STR))
214             monap_ptr->obvious = TRUE;
215
216         break;
217     }
218     case RBE_LOSE_INT: {
219         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
220         if (target_ptr->is_dead || check_multishadow(target_ptr))
221             break;
222
223         if (do_dec_stat(target_ptr, A_INT))
224             monap_ptr->obvious = TRUE;
225
226         break;
227     }
228     case RBE_LOSE_WIS: {
229         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
230         if (target_ptr->is_dead || check_multishadow(target_ptr))
231             break;
232
233         if (do_dec_stat(target_ptr, A_WIS))
234             monap_ptr->obvious = TRUE;
235
236         break;
237     }
238     case RBE_LOSE_DEX: {
239         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
240         if (target_ptr->is_dead || check_multishadow(target_ptr))
241             break;
242
243         if (do_dec_stat(target_ptr, A_DEX))
244             monap_ptr->obvious = TRUE;
245
246         break;
247     }
248     case RBE_LOSE_CON: {
249         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
250         if (target_ptr->is_dead || check_multishadow(target_ptr))
251             break;
252
253         if (do_dec_stat(target_ptr, A_CON))
254             monap_ptr->obvious = TRUE;
255
256         break;
257     }
258     case RBE_LOSE_CHR: {
259         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
260         if (target_ptr->is_dead || check_multishadow(target_ptr))
261             break;
262
263         if (do_dec_stat(target_ptr, A_CHR))
264             monap_ptr->obvious = TRUE;
265
266         break;
267     }
268     case RBE_LOSE_ALL: {
269         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
270         if (target_ptr->is_dead || check_multishadow(target_ptr))
271             break;
272
273         process_lose_all_attack(target_ptr, monap_ptr);
274         break;
275     }
276     case RBE_SHATTER: { /* AC軽減あり / Player armor reduces total damage */
277         monap_ptr->obvious = TRUE;
278         monap_ptr->damage -= (monap_ptr->damage * ((monap_ptr->ac < 150) ? monap_ptr->ac : 150) / 250);
279         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
280         if (monap_ptr->damage > 23 || monap_ptr->explode)
281             earthquake(target_ptr, monap_ptr->m_ptr->fy, monap_ptr->m_ptr->fx, 8, monap_ptr->m_idx);
282
283         break;
284     }
285     case RBE_EXP_10: {
286         s32b d = damroll(10, 6) + (target_ptr->exp / 100) * MON_DRAIN_LIFE;
287         monap_ptr->obvious = TRUE;
288         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
289         if (target_ptr->is_dead || check_multishadow(target_ptr))
290             break;
291
292         (void)drain_exp(target_ptr, d, d / 10, 95);
293         break;
294     }
295     case RBE_EXP_20: {
296         s32b d = damroll(20, 6) + (target_ptr->exp / 100) * MON_DRAIN_LIFE;
297         monap_ptr->obvious = TRUE;
298         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
299         if (target_ptr->is_dead || check_multishadow(target_ptr))
300             break;
301
302         (void)drain_exp(target_ptr, d, d / 10, 90);
303         break;
304     }
305     case RBE_EXP_40: {
306         s32b d = damroll(40, 6) + (target_ptr->exp / 100) * MON_DRAIN_LIFE;
307         monap_ptr->obvious = TRUE;
308         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
309         if (target_ptr->is_dead || check_multishadow(target_ptr))
310             break;
311
312         (void)drain_exp(target_ptr, d, d / 10, 75);
313         break;
314     }
315     case RBE_EXP_80: {
316         s32b d = damroll(80, 6) + (target_ptr->exp / 100) * MON_DRAIN_LIFE;
317         monap_ptr->obvious = TRUE;
318         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
319         if (target_ptr->is_dead || check_multishadow(target_ptr))
320             break;
321
322         (void)drain_exp(target_ptr, d, d / 10, 50);
323         break;
324     }
325     case RBE_DISEASE: {
326         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
327         if (target_ptr->is_dead || check_multishadow(target_ptr))
328             break;
329
330         if (!(target_ptr->resist_pois || is_oppose_pois(target_ptr))) {
331             if (set_poisoned(target_ptr, target_ptr->poisoned + randint1(monap_ptr->rlev) + 5)) {
332                 monap_ptr->obvious = TRUE;
333             }
334         }
335
336         if ((randint1(100) < 11) && (target_ptr->prace != RACE_ANDROID)) {
337             bool perm = one_in_(10);
338             if (dec_stat(target_ptr, A_CON, randint1(10), perm)) {
339                 msg_print(_("病があなたを蝕んでいる気がする。", "You feel sickly."));
340                 monap_ptr->obvious = TRUE;
341             }
342         }
343
344         break;
345     }
346     case RBE_TIME: {
347         if (monap_ptr->explode)
348             break;
349
350         process_monster_attack_time(target_ptr, monap_ptr);
351         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
352         break;
353     }
354     case RBE_DR_LIFE: {
355         s32b d = damroll(60, 6) + (target_ptr->exp / 100) * MON_DRAIN_LIFE;
356         monap_ptr->obvious = TRUE;
357         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
358         if (target_ptr->is_dead || check_multishadow(target_ptr))
359             break;
360
361         bool resist_drain = check_drain_hp(target_ptr, d);
362         process_drain_life(target_ptr, monap_ptr, resist_drain);
363         break;
364     }
365     case RBE_DR_MANA: {
366         monap_ptr->obvious = TRUE;
367         process_drain_mana(target_ptr, monap_ptr);
368         update_smart_learn(target_ptr, monap_ptr->m_idx, DRS_MANA);
369         break;
370     }
371     case RBE_INERTIA: {
372         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
373         if (target_ptr->is_dead)
374             break;
375
376         if (check_multishadow(target_ptr)) {
377             /* Do nothing */
378         } else {
379             if (set_slow(target_ptr, (target_ptr->slow + 4 + randint0(monap_ptr->rlev / 10)), FALSE)) {
380                 monap_ptr->obvious = TRUE;
381             }
382         }
383
384         break;
385     }
386     case RBE_STUN: {
387         monap_ptr->get_damage += take_hit(target_ptr, DAMAGE_ATTACK, monap_ptr->damage, monap_ptr->ddesc, -1);
388         if (target_ptr->is_dead)
389             break;
390
391         process_stun_attack(target_ptr, monap_ptr);
392         break;
393     }
394     }
395 }