OSDN Git Service

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