2 * 本ファイル内の行数はまともなレベルに落ち着いているので、一旦ここに留め置くこととする
3 * @brief 魔法種別による各種処理切り替え
6 * @todo どうしても「その他」に分類せざるを得ない魔法種別が残った
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"
41 ProcessResult effect_monster_hypodynamia(PlayerType *player_ptr, EffectMonster *em_ptr)
44 em_ptr->obvious = true;
47 if (em_ptr->m_ptr->has_living_flag()) {
48 em_ptr->do_time = (em_ptr->dam + 7) / 8;
49 return ProcessResult::PROCESS_CONTINUE;
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);
56 if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNDEAD)) {
57 em_ptr->r_ptr->r_kind_flags.set(MonsterKindType::UNDEAD);
59 if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::NONLIVING)) {
60 em_ptr->r_ptr->r_kind_flags.set(MonsterKindType::NONLIVING);
64 em_ptr->note = _("には効果がなかった。", " is unaffected.");
65 em_ptr->obvious = false;
67 return ProcessResult::PROCESS_CONTINUE;
71 * @todo リファクタリング前のコード時点で、単に耐性があるだけでもダメージ0だった.
73 ProcessResult effect_monster_death_ray(PlayerType *player_ptr, EffectMonster *em_ptr)
76 em_ptr->obvious = true;
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);
84 if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNDEAD)) {
85 em_ptr->r_ptr->r_kind_flags.set(MonsterKindType::UNDEAD);
87 if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::NONLIVING)) {
88 em_ptr->r_ptr->r_kind_flags.set(MonsterKindType::NONLIVING);
92 em_ptr->note = _("には完全な耐性がある!", " is immune.");
93 em_ptr->obvious = false;
95 return ProcessResult::PROCESS_CONTINUE;
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);
101 if (has_resistance) {
102 em_ptr->note = _("には耐性がある!", " resists!");
103 em_ptr->obvious = false;
107 return ProcessResult::PROCESS_CONTINUE;
110 ProcessResult effect_monster_kill_wall(PlayerType *player_ptr, EffectMonster *em_ptr)
112 if (em_ptr->r_ptr->resistance_flags.has_not(MonsterResistanceType::HURT_ROCK)) {
114 return ProcessResult::PROCESS_CONTINUE;
118 em_ptr->obvious = true;
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);
125 em_ptr->note = _("の皮膚がただれた!", " loses some skin!");
126 em_ptr->note_dies = _("はドロドロに溶けた!", " dissolves!");
127 return ProcessResult::PROCESS_CONTINUE;
130 ProcessResult effect_monster_hand_doom(EffectMonster *em_ptr)
133 em_ptr->obvious = true;
136 if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
137 em_ptr->note = _("には効果がなかった。", " is unaffected.");
139 return ProcessResult::PROCESS_CONTINUE;
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;
149 em_ptr->note = _("は破滅の手に耐え切った!", "resists!");
153 return ProcessResult::PROCESS_CONTINUE;
157 * @brief 剣術「幻惑」の効果をモンスターに与える
158 * @param player_ptr プレイヤーの情報へのポインタ
159 * @param effect_monster_type モンスターの効果情報へのポインタ
161 * 精神のないモンスター、寝ているモンスターには無効。
166 ProcessResult effect_monster_engetsu(PlayerType *player_ptr, EffectMonster *em_ptr)
169 em_ptr->obvious = true;
172 if (any_bits(em_ptr->r_ptr->flags2, RF2_EMPTY_MIND)) {
173 em_ptr->note = _("には効果がなかった。", " is unaffected.");
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);
179 return ProcessResult::PROCESS_CONTINUE;
182 if (em_ptr->m_ptr->is_asleep()) {
183 em_ptr->note = _("には効果がなかった。", " is unaffected.");
185 em_ptr->skipped = true;
186 return ProcessResult::PROCESS_CONTINUE;
190 for (int i = 0; i < 3; i++) {
191 if (randint0(5) < 2) {
195 int power = 10 + randint1((em_ptr->dam - 10) < 1 ? 1 : (em_ptr->dam - 10));
196 if (em_ptr->r_ptr->level > power) {
200 switch (randint0(4)) {
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.");
210 if (em_ptr->r_ptr->kind_flags.has(MonsterKindType::UNIQUE)) {
213 em_ptr->do_stun = damroll((player_ptr->lev / 10) + 3, (em_ptr->dam)) + 1;
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);
226 /* Go to sleep (much) later */
227 em_ptr->note = _("は混乱したようだ。", " looks confused.");
228 em_ptr->do_conf = 10 + randint1(15);
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);
239 em_ptr->do_sleep = 0;
241 /* Go to sleep (much) later */
242 em_ptr->note = _("は眠り込んでしまった!", " falls asleep!");
243 em_ptr->do_sleep = 500;
249 if (em_ptr->do_sleep > 0) {
255 em_ptr->note = _("には効果がなかった。", " is unaffected.");
256 em_ptr->obvious = false;
260 return ProcessResult::PROCESS_CONTINUE;
263 ProcessResult effect_monster_genocide(PlayerType *player_ptr, EffectMonster *em_ptr)
266 em_ptr->obvious = true;
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);
274 chg_virtue(player_ptr, Virtue::VITALITY, -1);
275 return ProcessResult::PROCESS_TRUE;
278 em_ptr->skipped = true;
279 return ProcessResult::PROCESS_CONTINUE;
282 ProcessResult effect_monster_photo(PlayerType *player_ptr, EffectMonster *em_ptr)
285 msg_format(_("%sを写真に撮った。", "You take a photograph of %s."), em_ptr->m_name);
288 if (em_ptr->r_ptr->resistance_flags.has(MonsterResistanceType::HURT_LITE)) {
290 em_ptr->obvious = true;
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);
297 em_ptr->note = _("は光に身をすくめた!", " cringes from the light!");
298 em_ptr->note_dies = _("は光を受けてしぼんでしまった!", " shrivels away in the light!");
303 em_ptr->photo = enum2i(em_ptr->m_ptr->r_idx);
304 return ProcessResult::PROCESS_CONTINUE;
307 ProcessResult effect_monster_wounds(EffectMonster *em_ptr)
310 em_ptr->obvious = true;
313 if (randint0(100 + em_ptr->dam) < (em_ptr->r_ptr->level + 50)) {
314 em_ptr->note = _("には効果がなかった。", " is unaffected.");
318 return ProcessResult::PROCESS_CONTINUE;
322 * @brief 魔法の効果によって様々なメッセーを出力したり与えるダメージの増減を行ったりする
323 * @param em_ptr モンスター効果構造体への参照ポインタ
324 * @return ここのスイッチングで終るならTRUEかFALSE、後続処理を実行するならCONTINUE
326 ProcessResult switch_effects_monster(PlayerType *player_ptr, EffectMonster *em_ptr, std::optional<CapturedMonsterType *> cap_mon_ptr)
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);
501 em_ptr->skipped = true;
503 return ProcessResult::PROCESS_CONTINUE;