OSDN Git Service

Merge pull request #3569 from sikabane-works/release/3.0.0.88-alpha
[hengbandforosx/hengbandosx.git] / src / effect / effect-monster-switcher.cpp
1 /*!
2  * 本ファイル内の行数はまともなレベルに落ち着いているので、一旦ここに留め置くこととする
3  * @brief 魔法種別による各種処理切り替え
4  * @date 2020/04/29
5  * @author Hourier
6  * @todo どうしても「その他」に分類せざるを得ない魔法種別が残った
7  */
8
9 #include "effect/effect-monster-switcher.h"
10 #include "avatar/avatar.h"
11 #include "cmd-action/cmd-attack.h"
12 #include "effect/attribute-types.h"
13 #include "effect/effect-monster-charm.h"
14 #include "effect/effect-monster-curse.h"
15 #include "effect/effect-monster-evil.h"
16 #include "effect/effect-monster-lite-dark.h"
17 #include "effect/effect-monster-oldies.h"
18 #include "effect/effect-monster-psi.h"
19 #include "effect/effect-monster-resist-hurt.h"
20 #include "effect/effect-monster-spirit.h"
21 #include "effect/effect-monster-util.h"
22 #include "mind/mind-elementalist.h"
23 #include "monster-floor/monster-death.h"
24 #include "monster-race/monster-race-hook.h"
25 #include "monster-race/monster-race.h"
26 #include "monster-race/race-flags1.h"
27 #include "monster-race/race-flags2.h"
28 #include "monster-race/race-flags3.h"
29 #include "monster/monster-info.h"
30 #include "monster/monster-status-setter.h"
31 #include "monster/monster-status.h"
32 #include "player/player-damage.h"
33 #include "spell-kind/spells-genocide.h"
34 #include "system/grid-type-definition.h"
35 #include "system/monster-entity.h"
36 #include "system/monster-race-info.h"
37 #include "system/player-type-definition.h"
38 #include "util/bit-flags-calculator.h"
39 #include "view/display-messages.h"
40
41 ProcessResult effect_monster_hypodynamia(PlayerType *player_ptr, EffectMonster *em_ptr)
42 {
43     if (em_ptr->seen) {
44         em_ptr->obvious = true;
45     }
46
47     if (em_ptr->m_ptr->has_living_flag()) {
48         em_ptr->do_time = (em_ptr->dam + 7) / 8;
49         return ProcessResult::PROCESS_CONTINUE;
50     }
51
52     if (is_original_ap_and_seen(player_ptr, em_ptr->m_ptr)) {
53         if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::DEMON)) {
54             em_ptr->r_ptr->r_kind_flags.set(MonsterKindType::DEMON);
55         }
56         if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNDEAD)) {
57             em_ptr->r_ptr->r_kind_flags.set(MonsterKindType::UNDEAD);
58         }
59         if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::NONLIVING)) {
60             em_ptr->r_ptr->r_kind_flags.set(MonsterKindType::NONLIVING);
61         }
62     }
63
64     em_ptr->note = _("には効果がなかった。", " is unaffected.");
65     em_ptr->obvious = false;
66     em_ptr->dam = 0;
67     return ProcessResult::PROCESS_CONTINUE;
68 }
69
70 /*!
71  * @todo リファクタリング前のコード時点で、単に耐性があるだけでもダメージ0だった.
72  */
73 ProcessResult effect_monster_death_ray(PlayerType *player_ptr, EffectMonster *em_ptr)
74 {
75     if (em_ptr->seen) {
76         em_ptr->obvious = true;
77     }
78
79     if (!em_ptr->m_ptr->has_living_flag()) {
80         if (is_original_ap_and_seen(player_ptr, em_ptr->m_ptr)) {
81             if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::DEMON)) {
82                 em_ptr->r_ptr->r_kind_flags.set(MonsterKindType::DEMON);
83             }
84             if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNDEAD)) {
85                 em_ptr->r_ptr->r_kind_flags.set(MonsterKindType::UNDEAD);
86             }
87             if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::NONLIVING)) {
88                 em_ptr->r_ptr->r_kind_flags.set(MonsterKindType::NONLIVING);
89             }
90         }
91
92         em_ptr->note = _("には完全な耐性がある!", " is immune.");
93         em_ptr->obvious = false;
94         em_ptr->dam = 0;
95         return ProcessResult::PROCESS_CONTINUE;
96     }
97
98     bool has_resistance = (em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE) && (randint1(888) != 666));
99     has_resistance |= (((em_ptr->r_ptr->level + randint1(20)) > randint1((em_ptr->caster_lev / 2) + randint1(10))) && randint1(100) != 66);
100
101     if (has_resistance) {
102         em_ptr->note = _("には耐性がある!", " resists!");
103         em_ptr->obvious = false;
104         em_ptr->dam = 0;
105     }
106
107     return ProcessResult::PROCESS_CONTINUE;
108 }
109
110 ProcessResult effect_monster_kill_wall(PlayerType *player_ptr, EffectMonster *em_ptr)
111 {
112     if (em_ptr->r_ptr->resistance_flags.has_not(MonsterResistanceType::HURT_ROCK)) {
113         em_ptr->dam = 0;
114         return ProcessResult::PROCESS_CONTINUE;
115     }
116
117     if (em_ptr->seen) {
118         em_ptr->obvious = true;
119     }
120
121     if (is_original_ap_and_seen(player_ptr, em_ptr->m_ptr)) {
122         em_ptr->r_ptr->r_resistance_flags.set(MonsterResistanceType::HURT_ROCK);
123     }
124
125     em_ptr->note = _("の皮膚がただれた!", " loses some skin!");
126     em_ptr->note_dies = _("はドロドロに溶けた!", " dissolves!");
127     return ProcessResult::PROCESS_CONTINUE;
128 }
129
130 ProcessResult effect_monster_hand_doom(EffectMonster *em_ptr)
131 {
132     if (em_ptr->seen) {
133         em_ptr->obvious = true;
134     }
135
136     if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
137         em_ptr->note = _("には効果がなかった。", " is unaffected.");
138         em_ptr->dam = 0;
139         return ProcessResult::PROCESS_CONTINUE;
140     }
141
142     if ((em_ptr->who > 0) ? ((em_ptr->caster_lev + randint1(em_ptr->dam)) > (em_ptr->r_ptr->level + 10 + randint1(20)))
143                           : (((em_ptr->caster_lev / 2) + randint1(em_ptr->dam)) > (em_ptr->r_ptr->level + randint1(200)))) {
144         em_ptr->dam = ((40 + randint1(20)) * em_ptr->m_ptr->hp) / 100;
145         if (em_ptr->m_ptr->hp < em_ptr->dam) {
146             em_ptr->dam = em_ptr->m_ptr->hp - 1;
147         }
148     } else {
149         em_ptr->note = _("は破滅の手に耐え切った!", "resists!");
150         em_ptr->dam = 0;
151     }
152
153     return ProcessResult::PROCESS_CONTINUE;
154 }
155
156 /*!
157  * @brief 剣術「幻惑」の効果をモンスターに与える
158  * @param player_ptr プレイヤーの情報へのポインタ
159  * @param effect_monster_type モンスターの効果情報へのポインタ
160  * @details
161  * 精神のないモンスター、寝ているモンスターには無効。
162  * 3回試行し、それぞれ2/5で失敗。
163  * 寝た場合は試行終了。
164  * 与える効果は減速、朦朧、混乱、睡眠。
165  */
166 ProcessResult effect_monster_engetsu(PlayerType *player_ptr, EffectMonster *em_ptr)
167 {
168     if (em_ptr->seen) {
169         em_ptr->obvious = true;
170     }
171
172     if (any_bits(em_ptr->r_ptr->flags2, RF2_EMPTY_MIND)) {
173         em_ptr->note = _("には効果がなかった。", " is unaffected.");
174         em_ptr->dam = 0;
175         em_ptr->skipped = true;
176         if (is_original_ap_and_seen(player_ptr, em_ptr->m_ptr)) {
177             set_bits(em_ptr->r_ptr->r_flags2, RF2_EMPTY_MIND);
178         }
179         return ProcessResult::PROCESS_CONTINUE;
180     }
181
182     if (em_ptr->m_ptr->is_asleep()) {
183         em_ptr->note = _("には効果がなかった。", " is unaffected.");
184         em_ptr->dam = 0;
185         em_ptr->skipped = true;
186         return ProcessResult::PROCESS_CONTINUE;
187     }
188
189     bool done = false;
190     for (int i = 0; i < 3; i++) {
191         if (randint0(5) < 2) {
192             continue;
193         }
194
195         int power = 10 + randint1((em_ptr->dam - 10) < 1 ? 1 : (em_ptr->dam - 10));
196         if (em_ptr->r_ptr->level > power) {
197             continue;
198         }
199
200         switch (randint0(4)) {
201         case 0:
202             if (em_ptr->r_ptr->kind_flags.has_not(MonsterKindType::UNIQUE)) {
203                 if (set_monster_slow(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->m_ptr->get_remaining_deceleration() + 50)) {
204                     em_ptr->note = _("の動きが遅くなった。", " starts moving slower.");
205                 }
206                 done = true;
207             }
208             break;
209         case 1:
210             if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
211                 em_ptr->do_stun = 0;
212             } else {
213                 em_ptr->do_stun = damroll((player_ptr->lev / 10) + 3, (em_ptr->dam)) + 1;
214                 done = true;
215             }
216             break;
217         case 2:
218             if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE) || any_bits(em_ptr->r_ptr->flags3, RF3_NO_CONF)) {
219                 if (any_bits(em_ptr->r_ptr->flags3, RF3_NO_CONF)) {
220                     if (is_original_ap_and_seen(player_ptr, em_ptr->m_ptr)) {
221                         set_bits(em_ptr->r_ptr->r_flags3, RF3_NO_CONF);
222                     }
223                 }
224                 em_ptr->do_conf = 0;
225             } else {
226                 /* Go to sleep (much) later */
227                 em_ptr->note = _("は混乱したようだ。", " looks confused.");
228                 em_ptr->do_conf = 10 + randint1(15);
229                 done = true;
230             }
231             break;
232         default:
233             if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE) || any_bits(em_ptr->r_ptr->flags3, RF3_NO_SLEEP)) {
234                 if (any_bits(em_ptr->r_ptr->flags3, RF3_NO_SLEEP)) {
235                     if (is_original_ap_and_seen(player_ptr, em_ptr->m_ptr)) {
236                         set_bits(em_ptr->r_ptr->r_flags3, RF3_NO_SLEEP);
237                     }
238                 }
239                 em_ptr->do_sleep = 0;
240             } else {
241                 /* Go to sleep (much) later */
242                 em_ptr->note = _("は眠り込んでしまった!", " falls asleep!");
243                 em_ptr->do_sleep = 500;
244                 done = true;
245             }
246             break;
247         }
248
249         if (em_ptr->do_sleep > 0) {
250             break;
251         }
252     }
253
254     if (!done) {
255         em_ptr->note = _("には効果がなかった。", " is unaffected.");
256         em_ptr->obvious = false;
257     }
258
259     em_ptr->dam = 0;
260     return ProcessResult::PROCESS_CONTINUE;
261 }
262
263 ProcessResult effect_monster_genocide(PlayerType *player_ptr, EffectMonster *em_ptr)
264 {
265     if (em_ptr->seen) {
266         em_ptr->obvious = true;
267     }
268
269     std::string_view spell_name(_("モンスター消滅", "Genocide One"));
270     if (genocide_aux(player_ptr, em_ptr->g_ptr->m_idx, em_ptr->dam, !em_ptr->who, (em_ptr->r_ptr->level + 1) / 2, spell_name.data())) {
271         if (em_ptr->seen_msg) {
272             msg_format(_("%sは消滅した!", "%s^ disappeared!"), em_ptr->m_name);
273         }
274         chg_virtue(player_ptr, Virtue::VITALITY, -1);
275         return ProcessResult::PROCESS_TRUE;
276     }
277
278     em_ptr->skipped = true;
279     return ProcessResult::PROCESS_CONTINUE;
280 }
281
282 ProcessResult effect_monster_photo(PlayerType *player_ptr, EffectMonster *em_ptr)
283 {
284     if (!em_ptr->who) {
285         msg_format(_("%sを写真に撮った。", "You take a photograph of %s."), em_ptr->m_name);
286     }
287
288     if (em_ptr->r_ptr->resistance_flags.has(MonsterResistanceType::HURT_LITE)) {
289         if (em_ptr->seen) {
290             em_ptr->obvious = true;
291         }
292
293         if (is_original_ap_and_seen(player_ptr, em_ptr->m_ptr)) {
294             em_ptr->r_ptr->r_resistance_flags.set(MonsterResistanceType::HURT_LITE);
295         }
296
297         em_ptr->note = _("は光に身をすくめた!", " cringes from the light!");
298         em_ptr->note_dies = _("は光を受けてしぼんでしまった!", " shrivels away in the light!");
299     } else {
300         em_ptr->dam = 0;
301     }
302
303     em_ptr->photo = enum2i(em_ptr->m_ptr->r_idx);
304     return ProcessResult::PROCESS_CONTINUE;
305 }
306
307 ProcessResult effect_monster_wounds(EffectMonster *em_ptr)
308 {
309     if (em_ptr->seen) {
310         em_ptr->obvious = true;
311     }
312
313     if (randint0(100 + em_ptr->dam) < (em_ptr->r_ptr->level + 50)) {
314         em_ptr->note = _("には効果がなかった。", " is unaffected.");
315         em_ptr->dam = 0;
316     }
317
318     return ProcessResult::PROCESS_CONTINUE;
319 }
320
321 /*!
322  * @brief 魔法の効果によって様々なメッセーを出力したり与えるダメージの増減を行ったりする
323  * @param em_ptr モンスター効果構造体への参照ポインタ
324  * @return ここのスイッチングで終るならTRUEかFALSE、後続処理を実行するならCONTINUE
325  */
326 ProcessResult switch_effects_monster(PlayerType *player_ptr, EffectMonster *em_ptr, std::optional<CapturedMonsterType *> cap_mon_ptr)
327 {
328     switch (em_ptr->attribute) {
329     case AttributeType::PSY_SPEAR:
330     case AttributeType::MISSILE:
331     case AttributeType::DEBUG:
332     case AttributeType::MANA:
333     case AttributeType::METEOR:
334     case AttributeType::BLOOD_CURSE:
335     case AttributeType::SEEKER:
336     case AttributeType::SUPER_RAY:
337     case AttributeType::MONSTER_MELEE:
338     case AttributeType::MONSTER_SHOOT:
339         return effect_monster_nothing(em_ptr);
340     case AttributeType::ACID:
341         return effect_monster_acid(player_ptr, em_ptr);
342     case AttributeType::ELEC:
343         return effect_monster_elec(player_ptr, em_ptr);
344     case AttributeType::FIRE:
345         return effect_monster_fire(player_ptr, em_ptr);
346     case AttributeType::COLD:
347         return effect_monster_cold(player_ptr, em_ptr);
348     case AttributeType::POIS:
349         return effect_monster_pois(player_ptr, em_ptr);
350     case AttributeType::NUKE:
351         return effect_monster_nuke(player_ptr, em_ptr);
352     case AttributeType::HELL_FIRE:
353         return effect_monster_hell_fire(player_ptr, em_ptr);
354     case AttributeType::HOLY_FIRE:
355         return effect_monster_holy_fire(player_ptr, em_ptr);
356     case AttributeType::PLASMA:
357         return effect_monster_plasma(player_ptr, em_ptr);
358     case AttributeType::NETHER:
359         return effect_monster_nether(player_ptr, em_ptr);
360     case AttributeType::WATER:
361         return effect_monster_water(player_ptr, em_ptr);
362     case AttributeType::CHAOS:
363         return effect_monster_chaos(player_ptr, em_ptr);
364     case AttributeType::SHARDS:
365         return effect_monster_shards(player_ptr, em_ptr);
366     case AttributeType::ROCKET:
367         return effect_monster_rocket(player_ptr, em_ptr);
368     case AttributeType::SOUND:
369         return effect_monster_sound(player_ptr, em_ptr);
370     case AttributeType::CONFUSION:
371         return effect_monster_confusion(player_ptr, em_ptr);
372     case AttributeType::DISENCHANT:
373         return effect_monster_disenchant(player_ptr, em_ptr);
374     case AttributeType::NEXUS:
375         return effect_monster_nexus(player_ptr, em_ptr);
376     case AttributeType::FORCE:
377         return effect_monster_force(player_ptr, em_ptr);
378     case AttributeType::INERTIAL:
379         return effect_monster_inertial(player_ptr, em_ptr);
380     case AttributeType::TIME:
381         return effect_monster_time(player_ptr, em_ptr);
382     case AttributeType::GRAVITY:
383         return effect_monster_gravity(player_ptr, em_ptr);
384     case AttributeType::DISINTEGRATE:
385         return effect_monster_disintegration(player_ptr, em_ptr);
386     case AttributeType::PSI:
387         return effect_monster_psi(player_ptr, em_ptr);
388     case AttributeType::PSI_DRAIN:
389         return effect_monster_psi_drain(player_ptr, em_ptr);
390     case AttributeType::TELEKINESIS:
391         return effect_monster_telekinesis(player_ptr, em_ptr);
392     case AttributeType::DOMINATION:
393         return effect_monster_domination(player_ptr, em_ptr);
394     case AttributeType::ICE:
395         return effect_monster_icee_bolt(player_ptr, em_ptr);
396     case AttributeType::HYPODYNAMIA:
397         return effect_monster_hypodynamia(player_ptr, em_ptr);
398     case AttributeType::DEATH_RAY:
399         return effect_monster_death_ray(player_ptr, em_ptr);
400     case AttributeType::OLD_POLY:
401         return effect_monster_old_poly(em_ptr);
402     case AttributeType::OLD_CLONE:
403         return effect_monster_old_clone(player_ptr, em_ptr);
404     case AttributeType::STAR_HEAL:
405         return effect_monster_star_heal(player_ptr, em_ptr);
406     case AttributeType::OLD_HEAL:
407         return effect_monster_old_heal(player_ptr, em_ptr);
408     case AttributeType::OLD_SPEED:
409         return effect_monster_old_speed(player_ptr, em_ptr);
410     case AttributeType::OLD_SLOW:
411         return effect_monster_old_slow(player_ptr, em_ptr);
412     case AttributeType::OLD_SLEEP:
413         return effect_monster_old_sleep(player_ptr, em_ptr);
414     case AttributeType::STASIS_EVIL:
415         return effect_monster_stasis(em_ptr, true);
416     case AttributeType::STASIS:
417         return effect_monster_stasis(em_ptr, false);
418     case AttributeType::CHARM:
419         return effect_monster_charm(player_ptr, em_ptr);
420     case AttributeType::CONTROL_UNDEAD:
421         return effect_monster_control_undead(player_ptr, em_ptr);
422     case AttributeType::CONTROL_DEMON:
423         return effect_monster_control_demon(player_ptr, em_ptr);
424     case AttributeType::CONTROL_ANIMAL:
425         return effect_monster_control_animal(player_ptr, em_ptr);
426     case AttributeType::CHARM_LIVING:
427         return effect_monster_charm_living(player_ptr, em_ptr);
428     case AttributeType::OLD_CONF:
429         return effect_monster_old_conf(player_ptr, em_ptr);
430     case AttributeType::STUN:
431         return effect_monster_stun(em_ptr);
432     case AttributeType::LITE_WEAK:
433         return effect_monster_lite_weak(player_ptr, em_ptr);
434     case AttributeType::LITE:
435         return effect_monster_lite(player_ptr, em_ptr);
436     case AttributeType::DARK:
437         return effect_monster_dark(player_ptr, em_ptr);
438     case AttributeType::KILL_WALL:
439         return effect_monster_kill_wall(player_ptr, em_ptr);
440     case AttributeType::AWAY_UNDEAD:
441         return effect_monster_away_undead(player_ptr, em_ptr);
442     case AttributeType::AWAY_EVIL:
443         return effect_monster_away_evil(player_ptr, em_ptr);
444     case AttributeType::AWAY_ALL:
445         return effect_monster_away_all(player_ptr, em_ptr);
446     case AttributeType::TURN_UNDEAD:
447         return effect_monster_turn_undead(player_ptr, em_ptr);
448     case AttributeType::TURN_EVIL:
449         return effect_monster_turn_evil(player_ptr, em_ptr);
450     case AttributeType::TURN_ALL:
451         return effect_monster_turn_all(em_ptr);
452     case AttributeType::DISP_UNDEAD:
453         return effect_monster_disp_undead(player_ptr, em_ptr);
454     case AttributeType::DISP_EVIL:
455         return effect_monster_disp_evil(player_ptr, em_ptr);
456     case AttributeType::DISP_GOOD:
457         return effect_monster_disp_good(player_ptr, em_ptr);
458     case AttributeType::DISP_LIVING:
459         return effect_monster_disp_living(em_ptr);
460     case AttributeType::DISP_DEMON:
461         return effect_monster_disp_demon(player_ptr, em_ptr);
462     case AttributeType::DISP_ALL:
463         return effect_monster_disp_all(em_ptr);
464     case AttributeType::DRAIN_MANA:
465         return effect_monster_drain_mana(player_ptr, em_ptr);
466     case AttributeType::MIND_BLAST:
467         return effect_monster_mind_blast(player_ptr, em_ptr);
468     case AttributeType::BRAIN_SMASH:
469         return effect_monster_brain_smash(player_ptr, em_ptr);
470     case AttributeType::CAUSE_1:
471         return effect_monster_curse_1(em_ptr);
472     case AttributeType::CAUSE_2:
473         return effect_monster_curse_2(em_ptr);
474     case AttributeType::CAUSE_3:
475         return effect_monster_curse_3(em_ptr);
476     case AttributeType::CAUSE_4:
477         return effect_monster_curse_4(em_ptr);
478     case AttributeType::HAND_DOOM:
479         return effect_monster_hand_doom(em_ptr);
480     case AttributeType::CAPTURE:
481         return effect_monster_capture(player_ptr, em_ptr, cap_mon_ptr);
482     case AttributeType::ATTACK:
483         return do_cmd_attack(player_ptr, em_ptr->y, em_ptr->x, i2enum<combat_options>(em_ptr->dam)) ? ProcessResult::PROCESS_TRUE : ProcessResult::PROCESS_FALSE;
484     case AttributeType::ENGETSU:
485         return effect_monster_engetsu(player_ptr, em_ptr);
486     case AttributeType::GENOCIDE:
487         return effect_monster_genocide(player_ptr, em_ptr);
488     case AttributeType::PHOTO:
489         return effect_monster_photo(player_ptr, em_ptr);
490     case AttributeType::CRUSADE:
491         return effect_monster_crusade(player_ptr, em_ptr);
492     case AttributeType::WOUNDS:
493         return effect_monster_wounds(em_ptr);
494     case AttributeType::E_GENOCIDE:
495         return effect_monster_elemental_genocide(player_ptr, em_ptr);
496     case AttributeType::VOID_MAGIC:
497         return effect_monster_void(player_ptr, em_ptr);
498     case AttributeType::ABYSS:
499         return effect_monster_abyss(player_ptr, em_ptr);
500     default: {
501         em_ptr->skipped = true;
502         em_ptr->dam = 0;
503         return ProcessResult::PROCESS_CONTINUE;
504     }
505     }
506 }