OSDN Git Service

Merge pull request #997 from sikabane-works/feature/fix-doxygen-return
[hengbandforosx/hengbandosx.git] / src / spell-realm / spells-chaos.cpp
1 #include "spell-realm/spells-chaos.h"
2 #include "core/player-redraw-types.h"
3 #include "core/player-update-types.h"
4 #include "core/window-redrawer.h"
5 #include "dungeon/quest.h"
6 #include "effect/effect-characteristics.h"
7 #include "effect/effect-processor.h"
8 #include "floor/cave.h"
9 #include "floor/geometry.h"
10 #include "grid/feature.h"
11 #include "grid/grid.h"
12 #include "monster/monster-describer.h"
13 #include "monster/monster-status-setter.h"
14 #include "monster/monster-status.h"
15 #include "player/player-class.h"
16 #include "player/player-damage.h"
17 #include "spell-kind/spells-floor.h"
18 #include "spell-kind/spells-launcher.h"
19 #include "spell/spell-types.h"
20 #include "system/floor-type-definition.h"
21 #include "system/monster-type-definition.h"
22 #include "system/player-type-definition.h"
23 #include "target/projection-path-calculator.h"
24 #include "util/bit-flags-calculator.h"
25 #include "view/display-messages.h"
26
27 /*!
28  * @brief 虚無招来処理 /
29  * @param caster_ptr プレーヤーへの参照ポインタ
30  * @details
31  * Sorry, it becomes not (void)...
32  */
33 void call_the_void(player_type *caster_ptr)
34 {
35     grid_type *g_ptr;
36     bool do_call = TRUE;
37     for (int i = 0; i < 9; i++) {
38         g_ptr = &caster_ptr->current_floor_ptr->grid_array[caster_ptr->y + ddy_ddd[i]][caster_ptr->x + ddx_ddd[i]];
39
40         if (!cave_has_flag_grid(g_ptr, FF_PROJECT)) {
41             if (!g_ptr->mimic || !has_flag(f_info[g_ptr->mimic].flags, FF_PROJECT) || !permanent_wall(&f_info[g_ptr->feat])) {
42                 do_call = FALSE;
43                 break;
44             }
45         }
46     }
47
48     if (do_call) {
49         for (int i = 1; i < 10; i++) {
50             if (i - 5)
51                 fire_ball(caster_ptr, GF_ROCKET, i, 175, 2);
52         }
53
54         for (int i = 1; i < 10; i++) {
55             if (i - 5)
56                 fire_ball(caster_ptr, GF_MANA, i, 175, 3);
57         }
58
59         for (int i = 1; i < 10; i++) {
60             if (i - 5)
61                 fire_ball(caster_ptr, GF_NUKE, i, 175, 4);
62         }
63
64         return;
65     }
66
67     bool is_special_fllor = caster_ptr->current_floor_ptr->inside_quest && is_fixed_quest_idx(caster_ptr->current_floor_ptr->inside_quest);
68     is_special_fllor |= !caster_ptr->current_floor_ptr->dun_level;
69     if (is_special_fllor) {
70         msg_print(_("地面が揺れた。", "The ground trembles."));
71         return;
72     }
73
74 #ifdef JP
75     msg_format("あなたは%sを壁に近すぎる場所で唱えてしまった!", ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "祈り" : "呪文"));
76 #else
77     msg_format("You %s the %s too close to a wall!", ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "recite" : "cast"),
78         ((mp_ptr->spell_book == TV_LIFE_BOOK) ? "prayer" : "spell"));
79 #endif
80     msg_print(_("大きな爆発音があった!", "There is a loud explosion!"));
81
82     if (one_in_(666)) {
83         if (!vanish_dungeon(caster_ptr))
84             msg_print(_("ダンジョンは一瞬静まり返った。", "The dungeon becomes quiet for a moment."));
85         take_hit(caster_ptr, DAMAGE_NOESCAPE, 100 + randint1(150), _("自殺的な虚無招来", "a suicidal Call the Void"));
86         return;
87     }
88
89     if (destroy_area(caster_ptr, caster_ptr->y, caster_ptr->x, 15 + caster_ptr->lev + randint0(11), FALSE))
90         msg_print(_("ダンジョンが崩壊した...", "The dungeon collapses..."));
91     else
92         msg_print(_("ダンジョンは大きく揺れた。", "The dungeon trembles."));
93     take_hit(caster_ptr, DAMAGE_NOESCAPE, 100 + randint1(150), _("自殺的な虚無招来", "a suicidal Call the Void"));
94 }
95
96 /*!
97  * @brief 虚無招来によるフロア中の全壁除去処理 /
98  * Vanish all walls in this floor
99  * @param caster_ptr プレーヤーへの参照ポインタ
100  * @param caster_ptr 術者の参照ポインタ
101  * @return 実際に処理が反映された場合TRUE
102  */
103 bool vanish_dungeon(player_type *caster_ptr)
104 {
105     bool is_special_floor = caster_ptr->current_floor_ptr->inside_quest && is_fixed_quest_idx(caster_ptr->current_floor_ptr->inside_quest);
106     is_special_floor |= !caster_ptr->current_floor_ptr->dun_level;
107     if (is_special_floor)
108         return FALSE;
109
110     grid_type *g_ptr;
111     feature_type *f_ptr;
112     monster_type *m_ptr;
113     GAME_TEXT m_name[MAX_NLEN];
114     for (POSITION y = 1; y < caster_ptr->current_floor_ptr->height - 1; y++) {
115         for (POSITION x = 1; x < caster_ptr->current_floor_ptr->width - 1; x++) {
116             g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][x];
117
118             f_ptr = &f_info[g_ptr->feat];
119             g_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY);
120             m_ptr = &caster_ptr->current_floor_ptr->m_list[g_ptr->m_idx];
121             if (g_ptr->m_idx && monster_csleep_remaining(m_ptr)) {
122                 (void)set_monster_csleep(caster_ptr, g_ptr->m_idx, 0);
123                 if (m_ptr->ml) {
124                     monster_desc(caster_ptr, m_name, m_ptr, 0);
125                     msg_format(_("%^sが目を覚ました。", "%^s wakes up."), m_name);
126                 }
127             }
128
129             if (has_flag(f_ptr->flags, FF_HURT_DISI))
130                 cave_alter_feat(caster_ptr, y, x, FF_HURT_DISI);
131         }
132     }
133
134     for (POSITION x = 0; x < caster_ptr->current_floor_ptr->width; x++) {
135         g_ptr = &caster_ptr->current_floor_ptr->grid_array[0][x];
136         f_ptr = &f_info[g_ptr->mimic];
137         g_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY);
138
139         if (g_ptr->mimic && has_flag(f_ptr->flags, FF_HURT_DISI)) {
140             g_ptr->mimic = feat_state(caster_ptr->current_floor_ptr, g_ptr->mimic, FF_HURT_DISI);
141             if (!has_flag(f_info[g_ptr->mimic].flags, FF_REMEMBER))
142                 g_ptr->info &= ~(CAVE_MARK);
143         }
144
145         g_ptr = &caster_ptr->current_floor_ptr->grid_array[caster_ptr->current_floor_ptr->height - 1][x];
146         f_ptr = &f_info[g_ptr->mimic];
147         g_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY);
148
149         if (g_ptr->mimic && has_flag(f_ptr->flags, FF_HURT_DISI)) {
150             g_ptr->mimic = feat_state(caster_ptr->current_floor_ptr, g_ptr->mimic, FF_HURT_DISI);
151             if (!has_flag(f_info[g_ptr->mimic].flags, FF_REMEMBER))
152                 g_ptr->info &= ~(CAVE_MARK);
153         }
154     }
155
156     /* Special boundary walls -- Left and right */
157     for (POSITION y = 1; y < (caster_ptr->current_floor_ptr->height - 1); y++) {
158         g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][0];
159         f_ptr = &f_info[g_ptr->mimic];
160         g_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY);
161
162         if (g_ptr->mimic && has_flag(f_ptr->flags, FF_HURT_DISI)) {
163             g_ptr->mimic = feat_state(caster_ptr->current_floor_ptr, g_ptr->mimic, FF_HURT_DISI);
164             if (!has_flag(f_info[g_ptr->mimic].flags, FF_REMEMBER))
165                 g_ptr->info &= ~(CAVE_MARK);
166         }
167
168         g_ptr = &caster_ptr->current_floor_ptr->grid_array[y][caster_ptr->current_floor_ptr->width - 1];
169         f_ptr = &f_info[g_ptr->mimic];
170         g_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY);
171
172         if (g_ptr->mimic && has_flag(f_ptr->flags, FF_HURT_DISI)) {
173             g_ptr->mimic = feat_state(caster_ptr->current_floor_ptr, g_ptr->mimic, FF_HURT_DISI);
174             if (!has_flag(f_info[g_ptr->mimic].flags, FF_REMEMBER))
175                 g_ptr->info &= ~(CAVE_MARK);
176         }
177     }
178
179     caster_ptr->update |= (PU_UN_VIEW | PU_UN_LITE | PU_VIEW | PU_LITE | PU_FLOW | PU_MON_LITE | PU_MONSTERS);
180     caster_ptr->redraw |= (PR_MAP);
181     caster_ptr->window_flags |= (PW_OVERHEAD | PW_DUNGEON);
182     return TRUE;
183 }
184
185 /*!
186  * @brief カオス魔法「流星群」/トランプ魔法「隕石のカード」の処理としてプレイヤーを中心に隕石落下処理を10+1d10回繰り返す。
187  * / Drop 10+1d10 meteor ball at random places near the player
188  * @param caster_ptr プレーヤーへの参照ポインタ
189  * @param dam ダメージ
190  * @param rad 効力の半径
191  * @details このファイルにいるのは、spells-trump.c と比べて行数が少なかったため。それ以上の意図はない
192  */
193 void cast_meteor(player_type *caster_ptr, HIT_POINT dam, POSITION rad)
194 {
195     int b = 10 + randint1(10);
196     for (int i = 0; i < b; i++) {
197         POSITION y = 0, x = 0;
198         int count;
199
200         for (count = 0; count <= 20; count++) {
201             int dy, dx, d;
202
203             x = caster_ptr->x - 8 + randint0(17);
204             y = caster_ptr->y - 8 + randint0(17);
205             dx = (caster_ptr->x > x) ? (caster_ptr->x - x) : (x - caster_ptr->x);
206             dy = (caster_ptr->y > y) ? (caster_ptr->y - y) : (y - caster_ptr->y);
207             d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
208
209             if (d >= 9)
210                 continue;
211
212             floor_type *floor_ptr = caster_ptr->current_floor_ptr;
213             if (!in_bounds(floor_ptr, y, x) || !projectable(caster_ptr, caster_ptr->y, caster_ptr->x, y, x)
214                 || !cave_has_flag_bold(floor_ptr, y, x, FF_PROJECT))
215                 continue;
216
217             break;
218         }
219
220         if (count > 20)
221             continue;
222
223         project(caster_ptr, 0, rad, y, x, dam, GF_METEOR, PROJECT_KILL | PROJECT_JUMP | PROJECT_ITEM);
224     }
225 }