1 #include "effect/effect-feature.h"
2 #include "core/player-update-types.h"
3 #include "dungeon/dungeon-flag-types.h"
4 #include "dungeon/dungeon.h"
5 #include "effect/effect-characteristics.h"
6 #include "effect/effect-processor.h" // 暫定、後で消す.
7 #include "floor/cave.h"
10 #include "main/sound-definitions-table.h"
11 #include "main/sound-of-music.h"
12 #include "mind/mind-ninja.h"
13 #include "monster/monster-update.h"
14 #include "player/special-defense-types.h"
15 #include "room/door-definition.h"
16 #include "spell/spell-types.h"
17 #include "system/floor-type-definition.h"
18 #include "util/bit-flags-calculator.h"
19 #include "view/display-messages.h"
20 #include "world/world.h"
23 * Determine if a "legal" grid is an "naked" floor grid
25 * Line 1 -- forbid non-clean gird
26 * Line 2 -- forbid monsters
27 * Line 3 -- forbid the player
29 static bool cave_naked_bold(player_type *caster_ptr, POSITION y, POSITION x)
31 floor_type *floor_ptr = caster_ptr->current_floor_ptr;
32 return cave_clean_bold(floor_ptr, y, x) && (floor_ptr->grid_array[y][x].m_idx == 0) && !player_bold(caster_ptr, y, x);
36 * @brief 汎用的なビーム/ボルト/ボール系による地形効果処理 / We are called from "project()" to "damage" terrain features
37 * @param caster_ptr プレーヤーへの参照ポインタ
38 * @param who 魔法を発動したモンスター(0ならばプレイヤー) / Index of "source" monster (zero for "player")
39 * @param r 効果半径(ビーム/ボルト = 0 / ボール = 1以上) / Radius of explosion (0 = beam/bolt, 1 to 9 = ball)
40 * @param y 目標Y座標 / Target y location (or location to travel "towards")
41 * @param x 目標X座標 / Target x location (or location to travel "towards")
42 * @param dam 基本威力 / Base damage roll to apply to affected monsters (or player)
43 * @param typ 効果属性 / Type of damage to apply to monsters (and objects)
44 * @return 何か一つでも効力があればTRUEを返す / TRUE if any "effects" of the projection were observed, else FALSE
47 * We are called both for "beam" effects and "ball" effects.
49 * The "r" parameter is the "distance from ground zero".
51 * Note that we determine if the player can "see" anything that happens
52 * by taking into account: blindness, line-of-sight, and illumination.
54 * We return "TRUE" if the effect of the projection is "obvious".
56 * We also "see" grids which are "memorized", probably a hack
58 * Perhaps we should affect doors?
61 bool affect_feature(player_type *caster_ptr, MONSTER_IDX who, POSITION r, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID typ)
63 floor_type *floor_ptr = caster_ptr->current_floor_ptr;
64 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
65 feature_type *f_ptr = &f_info[g_ptr->feat];
68 bool known = player_has_los_bold(caster_ptr, y, x);
71 dam = (dam + r) / (r + 1);
73 if (have_flag(f_ptr->flags, FF_TREE)) {
79 message = _("枯れた", "was blasted.");
82 message = _("縮んだ", "shrank.");
85 message = _("溶けた", "melted.");
89 message = _("凍り、砕け散った", "was frozen and smashed.");
94 message = _("燃えた", "burns up!");
107 message = _("粉砕された", "was crushed.");
115 msg_format(_("木は%s。", "A tree %s"), message);
116 cave_set_feat(caster_ptr, y, x, one_in_(3) ? feat_brake : feat_grass);
119 if (g_ptr->info & (CAVE_MARK))
124 /* Analyze the type */
126 /* Ignore most effects */
160 if (is_hidden_door(caster_ptr, g_ptr)) {
161 disclose_grid(caster_ptr, y, x);
167 if (is_trap(caster_ptr, g_ptr->feat)) {
169 msg_print(_("まばゆい閃光が走った!", "There is a bright flash of light!"));
173 cave_alter_feat(caster_ptr, y, x, FF_DISARM);
176 if (is_closed_door(caster_ptr, g_ptr->feat) && f_ptr->power && have_flag(f_ptr->flags, FF_OPEN)) {
177 FEAT_IDX old_feat = g_ptr->feat;
178 cave_alter_feat(caster_ptr, y, x, FF_DISARM);
179 if (known && (old_feat != g_ptr->feat)) {
180 msg_print(_("カチッと音がした!", "Click!"));
185 if (caster_ptr->blind || !player_has_los_bold(caster_ptr, y, x))
188 g_ptr->info &= ~(CAVE_UNSAFE);
189 lite_spot(caster_ptr, y, x);
194 if (is_trap(caster_ptr, g_ptr->feat) || have_flag(f_ptr->flags, FF_DOOR)) {
196 msg_print(_("まばゆい閃光が走った!", "There is a bright flash of light!"));
200 cave_alter_feat(caster_ptr, y, x, FF_TUNNEL);
203 if (caster_ptr->blind || !player_has_los_bold(caster_ptr, y, x))
206 g_ptr->info &= ~(CAVE_UNSAFE);
207 lite_spot(caster_ptr, y, x);
212 if (!have_flag(f_ptr->flags, FF_SPIKE))
215 s16b old_mimic = g_ptr->mimic;
216 feature_type *mimic_f_ptr = &f_info[get_feat_mimic(g_ptr)];
218 cave_alter_feat(caster_ptr, y, x, FF_SPIKE);
219 g_ptr->mimic = old_mimic;
221 note_spot(caster_ptr, y, x);
222 lite_spot(caster_ptr, y, x);
224 if (!known || !have_flag(mimic_f_ptr->flags, FF_OPEN))
227 msg_format(_("%sに何かがつっかえて開かなくなった。", "The %s seems stuck."), f_name + mimic_f_ptr->name);
232 if (!have_flag(f_ptr->flags, FF_HURT_ROCK))
235 if (known && (g_ptr->info & (CAVE_MARK))) {
236 msg_format(_("%sが溶けて泥になった!", "The %s turns into mud!"), f_name + f_info[get_feat_mimic(g_ptr)].name);
240 cave_alter_feat(caster_ptr, y, x, FF_HURT_ROCK);
241 caster_ptr->update |= (PU_FLOW);
245 if (!cave_naked_bold(caster_ptr, y, x))
247 if (player_bold(caster_ptr, y, x))
249 cave_set_feat(caster_ptr, y, x, feat_door[DOOR_DOOR].closed);
250 if (g_ptr->info & (CAVE_MARK))
255 place_trap(caster_ptr, y, x);
259 if (!cave_naked_bold(caster_ptr, y, x))
261 if (player_bold(caster_ptr, y, x))
263 cave_set_feat(caster_ptr, y, x, feat_tree);
264 if (g_ptr->info & (CAVE_MARK))
268 case GF_MAKE_GLYPH: {
269 if (!cave_naked_bold(caster_ptr, y, x))
271 g_ptr->info |= CAVE_OBJECT;
272 g_ptr->mimic = feat_glyph;
273 note_spot(caster_ptr, y, x);
274 lite_spot(caster_ptr, y, x);
277 case GF_STONE_WALL: {
278 if (!cave_naked_bold(caster_ptr, y, x))
280 if (player_bold(caster_ptr, y, x))
282 cave_set_feat(caster_ptr, y, x, feat_granite);
286 if (have_flag(f_ptr->flags, FF_PERMANENT))
289 if (!have_flag(f_ptr->flags, FF_FLOOR))
291 cave_set_feat(caster_ptr, y, x, feat_shallow_lava);
293 cave_set_feat(caster_ptr, y, x, feat_deep_lava);
298 case GF_WATER_FLOW: {
299 if (have_flag(f_ptr->flags, FF_PERMANENT))
302 if (!have_flag(f_ptr->flags, FF_FLOOR))
304 cave_set_feat(caster_ptr, y, x, feat_shallow_water);
306 cave_set_feat(caster_ptr, y, x, feat_deep_water);
313 if ((d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS) != 0)
316 g_ptr->info |= (CAVE_GLOW);
317 note_spot(caster_ptr, y, x);
318 lite_spot(caster_ptr, y, x);
319 update_local_illumination(caster_ptr, y, x);
321 if (player_can_see_bold(caster_ptr, y, x))
324 update_monster(caster_ptr, g_ptr->m_idx, FALSE);
326 if (caster_ptr->special_defense & NINJA_S_STEALTH) {
327 if (player_bold(caster_ptr, y, x))
328 set_superstealth(caster_ptr, FALSE);
335 bool do_dark = !caster_ptr->phase_out && !is_mirror_grid(g_ptr);
339 if ((floor_ptr->dun_level > 0) || !is_daytime()) {
340 for (int j = 0; j < 9; j++) {
341 int by = y + ddy_ddd[j];
342 int bx = x + ddx_ddd[j];
344 if (!in_bounds2(floor_ptr, by, bx))
347 grid_type *cc_ptr = &floor_ptr->grid_array[by][bx];
348 if (have_flag(f_info[get_feat_mimic(cc_ptr)].flags, FF_GLOW)) {
358 g_ptr->info &= ~(CAVE_GLOW);
360 /* Hack -- Forget "boring" grids */
361 if (!have_flag(f_ptr->flags, FF_REMEMBER)) {
363 g_ptr->info &= ~(CAVE_MARK);
364 note_spot(caster_ptr, y, x);
367 lite_spot(caster_ptr, y, x);
369 update_local_illumination(caster_ptr, y, x);
371 if (player_can_see_bold(caster_ptr, y, x))
374 update_monster(caster_ptr, g_ptr->m_idx, FALSE);
380 if (is_mirror_grid(g_ptr)) {
381 msg_print(_("鏡が割れた!", "The mirror was shattered!"));
383 remove_mirror(caster_ptr, y, x);
384 project(caster_ptr, 0, 2, y, x, caster_ptr->lev / 2 + 5, GF_SHARDS,
385 (PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_JUMP | PROJECT_NO_HANGEKI), -1);
388 if (!have_flag(f_ptr->flags, FF_GLASS) || have_flag(f_ptr->flags, FF_PERMANENT) || (dam < 50))
391 if (known && (g_ptr->info & CAVE_MARK)) {
392 msg_format(_("%sが割れた!", "The %s crumbled!"), f_name + f_info[get_feat_mimic(g_ptr)].name);
396 cave_alter_feat(caster_ptr, y, x, FF_HURT_ROCK);
397 caster_ptr->update |= (PU_FLOW);
401 if (is_mirror_grid(g_ptr) && caster_ptr->lev < 40) {
402 msg_print(_("鏡が割れた!", "The mirror was shattered!"));
404 remove_mirror(caster_ptr, y, x);
405 project(caster_ptr, 0, 2, y, x, caster_ptr->lev / 2 + 5, GF_SHARDS,
406 (PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_JUMP | PROJECT_NO_HANGEKI), -1);
409 if (!have_flag(f_ptr->flags, FF_GLASS) || have_flag(f_ptr->flags, FF_PERMANENT) || (dam < 200))
412 if (known && (g_ptr->info & CAVE_MARK)) {
413 msg_format(_("%sが割れた!", "The %s crumbled!"), f_name + f_info[get_feat_mimic(g_ptr)].name);
417 cave_alter_feat(caster_ptr, y, x, FF_HURT_ROCK);
418 caster_ptr->update |= (PU_FLOW);
421 case GF_DISINTEGRATE: {
422 if (is_mirror_grid(g_ptr) || is_glyph_grid(g_ptr) || is_explosive_rune_grid(g_ptr))
423 remove_mirror(caster_ptr, y, x);
425 if (!have_flag(f_ptr->flags, FF_HURT_DISI) || have_flag(f_ptr->flags, FF_PERMANENT))
428 cave_alter_feat(caster_ptr, y, x, FF_HURT_DISI);
429 caster_ptr->update |= (PU_FLOW);
434 lite_spot(caster_ptr, y, x);