OSDN Git Service

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