OSDN Git Service

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