OSDN Git Service

Merge pull request #3608 from habu1010/feature/fix-crash-on-charcter-dump-to-invalid...
[hengbandforosx/hengbandosx.git] / src / spell-kind / blood-curse.cpp
1 #include "spell-kind/blood-curse.h"
2 #include "effect/attribute-types.h"
3 #include "effect/effect-characteristics.h"
4 #include "effect/effect-processor.h"
5 #include "monster-floor/monster-summon.h"
6 #include "monster-floor/place-monster-types.h"
7 #include "monster-race/monster-race.h"
8 #include "spell-kind/earthquake.h"
9 #include "spell-kind/spells-sight.h"
10 #include "spell-kind/spells-teleport.h"
11 #include "spell/spells-summon.h"
12 #include "spell/summon-types.h"
13 #include "status/base-status.h"
14 #include "status/experience.h"
15 #include "system/floor-type-definition.h"
16 #include "system/grid-type-definition.h"
17 #include "system/monster-entity.h"
18 #include "system/player-type-definition.h"
19 #include "view/display-messages.h"
20
21 void blood_curse_to_enemy(PlayerType *player_ptr, MONSTER_IDX m_idx)
22 {
23     auto *m_ptr = &player_ptr->current_floor_ptr->m_list[m_idx];
24     auto *g_ptr = &player_ptr->current_floor_ptr->grid_array[m_ptr->fy][m_ptr->fx];
25     BIT_FLAGS curse_flg = (PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_JUMP);
26     int count = 0;
27     bool is_first_loop = true;
28     while (is_first_loop || one_in_(5)) {
29         is_first_loop = false;
30         switch (randint1(28)) {
31         case 1:
32         case 2:
33             if (!count) {
34                 msg_print(_("地面が揺れた...", "The ground trembles..."));
35                 earthquake(player_ptr, m_ptr->fy, m_ptr->fx, 4 + randint0(4), 0);
36                 if (!one_in_(6)) {
37                     break;
38                 }
39             }
40             [[fallthrough]];
41         case 3:
42         case 4:
43         case 5:
44         case 6:
45             if (!count) {
46                 int extra_dam = damroll(10, 10);
47                 msg_print(_("純粋な魔力の次元への扉が開いた!", "A portal opens to a plane of raw mana!"));
48                 project(player_ptr, 0, 8, m_ptr->fy, m_ptr->fx, extra_dam, AttributeType::MANA, curse_flg);
49                 if (!one_in_(6)) {
50                     break;
51                 }
52             }
53             [[fallthrough]];
54         case 7:
55         case 8:
56             if (!count) {
57                 msg_print(_("空間が歪んだ!", "Space warps about you!"));
58                 if (MonsterRace(m_ptr->r_idx).is_valid()) {
59                     teleport_away(player_ptr, g_ptr->m_idx, damroll(10, 10), TELEPORT_PASSIVE);
60                 }
61                 if (one_in_(13)) {
62                     count += activate_hi_summon(player_ptr, m_ptr->fy, m_ptr->fx, true);
63                 }
64                 if (!one_in_(6)) {
65                     break;
66                 }
67             }
68             [[fallthrough]];
69         case 9:
70         case 10:
71         case 11:
72             msg_print(_("エネルギーのうねりを感じた!", "You feel a surge of energy!"));
73             project(player_ptr, 0, 7, m_ptr->fy, m_ptr->fx, 50, AttributeType::DISINTEGRATE, curse_flg);
74             if (!one_in_(6)) {
75                 break;
76             }
77             [[fallthrough]];
78         case 12:
79         case 13:
80         case 14:
81         case 15:
82         case 16:
83             aggravate_monsters(player_ptr, 0);
84             if (!one_in_(6)) {
85                 break;
86             }
87             [[fallthrough]];
88         case 17:
89         case 18:
90             count += activate_hi_summon(player_ptr, m_ptr->fy, m_ptr->fx, true);
91             if (!one_in_(6)) {
92                 break;
93             }
94             [[fallthrough]];
95         case 19:
96         case 20:
97         case 21:
98         case 22: {
99             bool pet = !one_in_(3);
100             BIT_FLAGS mode = PM_ALLOW_GROUP;
101
102             if (pet) {
103                 mode |= PM_FORCE_PET;
104             } else {
105                 mode |= (PM_NO_PET | PM_FORCE_FRIENDLY);
106             }
107
108             count += summon_specific(player_ptr, (pet ? -1 : 0), player_ptr->y, player_ptr->x,
109                 (pet ? player_ptr->lev * 2 / 3 + randint1(player_ptr->lev / 2) : player_ptr->current_floor_ptr->dun_level), SUMMON_NONE, mode);
110             if (!one_in_(6)) {
111                 break;
112             }
113         }
114             [[fallthrough]];
115         case 23:
116         case 24:
117         case 25:
118             if (player_ptr->hold_exp && (randint0(100) < 75)) {
119                 break;
120             }
121
122             msg_print(_("経験値が体から吸い取られた気がする!", "You feel your experience draining away..."));
123             if (player_ptr->hold_exp) {
124                 lose_exp(player_ptr, player_ptr->exp / 160);
125             } else {
126                 lose_exp(player_ptr, player_ptr->exp / 16);
127             }
128             if (!one_in_(6)) {
129                 break;
130             }
131             [[fallthrough]];
132         case 26:
133         case 27:
134         case 28:
135         default: {
136             if (one_in_(13)) {
137                 for (int i = 0; i < A_MAX; i++) {
138                     do {
139                         (void)do_dec_stat(player_ptr, i);
140                     } while (one_in_(2));
141                 }
142             } else {
143                 (void)do_dec_stat(player_ptr, randint0(6));
144             }
145
146             break;
147         }
148         }
149     }
150 }