OSDN Git Service

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