1 #include "spell-kind/earthquake.h"
2 #include "dungeon/dungeon.h"
3 #include "dungeon/quest.h"
4 #include "floor/floor-events.h"
5 #include "floor/floor-object.h"
6 #include "floor/floor.h"
7 #include "io/write-diary.h"
8 #include "monster-race/race-flags1.h"
9 #include "monster-race/race-flags2.h"
10 #include "monster/monster-describer.h"
11 #include "monster/monster-description-types.h"
12 #include "monster/monster-status.h"
13 #include "monster/monster-update.h"
14 #include "monster/monster2.h"
15 #include "monster/smart-learn-types.h"
16 #include "player/player-damage.h"
17 #include "player/player-effects.h"
18 #include "player/player-move.h"
22 * Induce an "earthquake" of the given radius at the given location.
23 * @param caster_ptrプレーヤーへの参照ポインタ
27 * @param m_idx 地震を起こしたモンスターID(0ならばプレイヤー)
28 * @return 効力があった場合TRUEを返す
30 bool earthquake(player_type *caster_ptr, POSITION cy, POSITION cx, POSITION r, MONSTER_IDX m_idx)
32 floor_type *floor_ptr = caster_ptr->current_floor_ptr;
33 if ((floor_ptr->inside_quest && is_fixed_quest_idx(floor_ptr->inside_quest)) || !floor_ptr->dun_level) {
41 for (POSITION y = 0; y < 32; y++) {
42 for (POSITION x = 0; x < 32; x++) {
49 for (POSITION dy = -r; dy <= r; dy++) {
50 for (POSITION dx = -r; dx <= r; dx++) {
51 POSITION yy = cy + dy;
52 POSITION xx = cx + dx;
54 if (!in_bounds(floor_ptr, yy, xx))
57 if (distance(cy, cx, yy, xx) > r)
61 g_ptr = &floor_ptr->grid_array[yy][xx];
62 g_ptr->info &= ~(CAVE_ROOM | CAVE_ICKY | CAVE_UNSAFE);
63 g_ptr->info &= ~(CAVE_GLOW | CAVE_MARK | CAVE_KNOWN);
67 if (randint0(100) < 85)
70 map[16 + yy - cy][16 + xx - cx] = TRUE;
71 if (player_bold(caster_ptr, yy, xx))
77 POSITION sy = 0, sx = 0;
78 if (hurt && !caster_ptr->pass_wall && !caster_ptr->kill_wall) {
79 for (DIRECTION i = 0; i < 8; i++) {
80 POSITION y = caster_ptr->y + ddy_ddd[i];
81 POSITION x = caster_ptr->x + ddx_ddd[i];
82 if (!is_cave_empty_bold(caster_ptr, y, x))
85 if (map[16 + y - cy][16 + x - cx])
88 if (floor_ptr->grid_array[y][x].m_idx)
99 switch (randint1(3)) {
101 msg_print(_("ダンジョンの壁が崩れた!", "The dungeon's ceiling collapses!"));
105 msg_print(_("ダンジョンの床が不自然にねじ曲がった!", "The dungeon's floor twists in an unnatural way!"));
109 msg_print(_("ダンジョンが揺れた!崩れた岩が頭に降ってきた!", "The dungeon quakes! You are pummeled with debris!"));
115 msg_print(_("あなたはひどい怪我を負った!", "You are severely crushed!"));
119 switch (randint1(3)) {
121 msg_print(_("降り注ぐ岩をうまく避けた!", "You nimbly dodge the blast!"));
126 msg_print(_("岩石があなたに直撃した!", "You are bashed by rubble!"));
127 damage = damroll(10, 4);
128 (void)set_stun(caster_ptr, caster_ptr->stun + randint1(50));
132 msg_print(_("あなたは床と壁との間に挟まれてしまった!", "You are crushed between the floor and ceiling!"));
133 damage = damroll(10, 4);
134 (void)set_stun(caster_ptr, caster_ptr->stun + randint1(50));
139 (void)move_player_effect(caster_ptr, sy, sx, MPE_DONT_PICKUP);
142 map[16 + caster_ptr->y - cy][16 + caster_ptr->x - cx] = FALSE;
147 GAME_TEXT m_name[MAX_NLEN];
148 monster_type *m_ptr = &floor_ptr->m_list[m_idx];
149 monster_desc(caster_ptr, m_name, m_ptr, MD_WRONGDOER_NAME);
150 killer = format(_("%sの起こした地震", "an earthquake caused by %s"), m_name);
152 killer = _("地震", "an earthquake");
155 take_hit(caster_ptr, DAMAGE_ATTACK, damage, killer, -1);
159 for (POSITION dy = -r; dy <= r; dy++) {
160 for (POSITION dx = -r; dx <= r; dx++) {
161 POSITION yy = cy + dy;
162 POSITION xx = cx + dx;
163 if (!map[16 + yy - cy][16 + xx - cx])
167 g_ptr = &floor_ptr->grid_array[yy][xx];
168 if (g_ptr->m_idx == caster_ptr->riding)
174 monster_type *m_ptr = &floor_ptr->m_list[g_ptr->m_idx];
175 monster_race *r_ptr = &r_info[m_ptr->r_idx];
176 if (r_ptr->flags1 & RF1_QUESTOR) {
177 map[16 + yy - cy][16 + xx - cx] = FALSE;
181 if ((r_ptr->flags2 & RF2_KILL_WALL) || (r_ptr->flags2 & RF2_PASS_WALL))
184 GAME_TEXT m_name[MAX_NLEN];
186 if (!(r_ptr->flags1 & RF1_NEVER_MOVE)) {
187 for (DIRECTION i = 0; i < 8; i++) {
188 POSITION y = yy + ddy_ddd[i];
189 POSITION x = xx + ddx_ddd[i];
190 if (!is_cave_empty_bold(caster_ptr, y, x))
193 if (is_glyph_grid(&floor_ptr->grid_array[y][x]))
196 if (is_explosive_rune_grid(&floor_ptr->grid_array[y][x]))
199 if (pattern_tile(floor_ptr, y, x))
202 if (map[16 + y - cy][16 + x - cx])
205 if (floor_ptr->grid_array[y][x].m_idx)
208 if (player_bold(caster_ptr, y, x))
213 if (randint0(sn) > 0)
221 monster_desc(caster_ptr, m_name, m_ptr, 0);
222 if (!ignore_unview || is_seen(m_ptr))
223 msg_format(_("%^sは苦痛で泣きわめいた!", "%^s wails out in pain!"), m_name);
225 damage = (sn ? damroll(4, 8) : (m_ptr->hp + 1));
226 (void)set_monster_csleep(caster_ptr, g_ptr->m_idx, 0);
229 if (!ignore_unview || is_seen(m_ptr))
230 msg_format(_("%^sは岩石に埋もれてしまった!", "%^s is embedded in the rock!"), m_name);
233 if (record_named_pet && is_pet(&floor_ptr->m_list[g_ptr->m_idx]) && floor_ptr->m_list[g_ptr->m_idx].nickname) {
234 char m2_name[MAX_NLEN];
236 monster_desc(caster_ptr, m2_name, m_ptr, MD_INDEF_VISIBLE);
237 exe_write_diary(caster_ptr, DIARY_NAMED_PET, RECORD_NAMED_PET_EARTHQUAKE, m2_name);
241 delete_monster(caster_ptr, yy, xx);
248 IDX m_idx_aux = floor_ptr->grid_array[yy][xx].m_idx;
249 floor_ptr->grid_array[yy][xx].m_idx = 0;
250 floor_ptr->grid_array[sy][sx].m_idx = m_idx_aux;
253 update_monster(caster_ptr, m_idx, TRUE);
254 lite_spot(caster_ptr, yy, xx);
255 lite_spot(caster_ptr, sy, sx);
259 clear_mon_lite(floor_ptr);
260 for (POSITION dy = -r; dy <= r; dy++) {
261 for (POSITION dx = -r; dx <= r; dx++) {
262 POSITION yy = cy + dy;
263 POSITION xx = cx + dx;
264 if (!map[16 + yy - cy][16 + xx - cx])
267 if (!cave_valid_bold(floor_ptr, yy, xx))
270 delete_all_items_from_floor(caster_ptr, yy, xx);
271 int t = cave_have_flag_bold(floor_ptr, yy, xx, FF_PROJECT) ? randint0(100) : 200;
273 cave_set_feat(caster_ptr, yy, xx, feat_granite);
278 cave_set_feat(caster_ptr, yy, xx, feat_quartz_vein);
283 cave_set_feat(caster_ptr, yy, xx, feat_magma_vein);
287 cave_set_feat(caster_ptr, yy, xx, feat_ground_type[randint0(100)]);
291 for (POSITION dy = -r; dy <= r; dy++) {
292 for (POSITION dx = -r; dx <= r; dx++) {
293 POSITION yy = cy + dy;
294 POSITION xx = cx + dx;
295 if (!in_bounds(floor_ptr, yy, xx))
298 if (distance(cy, cx, yy, xx) > r)
302 g_ptr = &floor_ptr->grid_array[yy][xx];
303 if (is_mirror_grid(g_ptr)) {
304 g_ptr->info |= CAVE_GLOW;
308 if ((d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS))
312 for (DIRECTION ii = 0; ii < 9; ii++) {
313 POSITION yyy = yy + ddy_ddd[ii];
314 POSITION xxx = xx + ddx_ddd[ii];
315 if (!in_bounds2(floor_ptr, yyy, xxx))
317 cc_ptr = &floor_ptr->grid_array[yyy][xxx];
318 if (have_flag(f_info[get_feat_mimic(cc_ptr)].flags, FF_GLOW)) {
319 g_ptr->info |= CAVE_GLOW;
326 caster_ptr->update |= (PU_UN_VIEW | PU_UN_LITE | PU_VIEW | PU_LITE | PU_FLOW | PU_MON_LITE | PU_MONSTERS);
327 caster_ptr->redraw |= (PR_HEALTH | PR_UHEALTH | PR_MAP);
328 caster_ptr->window |= (PW_OVERHEAD | PW_DUNGEON);
329 if (caster_ptr->special_defense & NINJA_S_STEALTH) {
330 if (floor_ptr->grid_array[caster_ptr->y][caster_ptr->x].info & CAVE_GLOW)
331 set_superstealth(caster_ptr, FALSE);