OSDN Git Service

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