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-elementalist.h"
13 #include "mind/mind-ninja.h"
14 #include "monster/monster-update.h"
15 #include "player/special-defense-types.h"
16 #include "room/door-definition.h"
17 #include "spell/spell-types.h"
18 #include "system/floor-type-definition.h"
19 #include "util/bit-flags-calculator.h"
20 #include "view/display-messages.h"
21 #include "world/world.h"
24 * Determine if a "legal" grid is an "naked" floor grid
26 * Line 1 -- forbid non-clean gird
27 * Line 2 -- forbid monsters
28 * Line 3 -- forbid the player
30 static bool cave_naked_bold(player_type *caster_ptr, POSITION y, POSITION x)
32 floor_type *floor_ptr = caster_ptr->current_floor_ptr;
33 return cave_clean_bold(floor_ptr, y, x) && (floor_ptr->grid_array[y][x].m_idx == 0) && !player_bold(caster_ptr, y, x);
37 * @brief 汎用的なビーム/ボルト/ボール系による地形効果処理 / We are called from "project()" to "damage" terrain features
38 * @param caster_ptr プレーヤーへの参照ポインタ
39 * @param who 魔法を発動したモンスター(0ならばプレイヤー) / Index of "source" monster (zero for "player")
40 * @param r 効果半径(ビーム/ボルト = 0 / ボール = 1以上) / Radius of explosion (0 = beam/bolt, 1 to 9 = ball)
41 * @param y 目標Y座標 / Target y location (or location to travel "towards")
42 * @param x 目標X座標 / Target x location (or location to travel "towards")
43 * @param dam 基本威力 / Base damage roll to apply to affected monsters (or player)
44 * @param typ 効果属性 / Type of damage to apply to monsters (and objects)
45 * @return 何か一つでも効力があればTRUEを返す / TRUE if any "effects" of the projection were observed, else FALSE
48 * We are called both for "beam" effects and "ball" effects.
50 * The "r" parameter is the "distance from ground zero".
52 * Note that we determine if the player can "see" anything that happens
53 * by taking into account: blindness, line-of-sight, and illumination.
55 * We return "TRUE" if the effect of the projection is "obvious".
57 * We also "see" grids which are "memorized", probably a hack
59 * Perhaps we should affect doors?
62 bool affect_feature(player_type *caster_ptr, MONSTER_IDX who, POSITION r, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID typ)
64 floor_type *floor_ptr = caster_ptr->current_floor_ptr;
65 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
66 feature_type *f_ptr = &f_info[g_ptr->feat];
69 bool known = player_has_los_bold(caster_ptr, y, x);
72 dam = (dam + r) / (r + 1);
74 if (has_flag(f_ptr->flags, FF_TREE)) {
80 message = _("枯れた", "was blasted.");
83 message = _("縮んだ", "shrank.");
86 message = _("溶けた", "melted.");
90 message = _("凍り、砕け散った", "was frozen and smashed.");
95 message = _("燃えた", "burns up!");
108 message = _("粉砕された", "was crushed.");
111 message = _("消滅した", "vanished.");
119 msg_format(_("木は%s。", "A tree %s"), message);
120 cave_set_feat(caster_ptr, y, x, one_in_(3) ? feat_brake : feat_grass);
123 if (g_ptr->info & (CAVE_MARK))
128 /* Analyze the type */
130 /* Ignore most effects */
164 if (is_hidden_door(caster_ptr, g_ptr)) {
165 disclose_grid(caster_ptr, y, x);
171 if (is_trap(caster_ptr, g_ptr->feat)) {
173 msg_print(_("まばゆい閃光が走った!", "There is a bright flash of light!"));
177 cave_alter_feat(caster_ptr, y, x, FF_DISARM);
180 if (is_closed_door(caster_ptr, g_ptr->feat) && f_ptr->power && has_flag(f_ptr->flags, FF_OPEN)) {
181 FEAT_IDX old_feat = g_ptr->feat;
182 cave_alter_feat(caster_ptr, y, x, FF_DISARM);
183 if (known && (old_feat != g_ptr->feat)) {
184 msg_print(_("カチッと音がした!", "Click!"));
189 if (caster_ptr->blind || !player_has_los_bold(caster_ptr, y, x))
192 g_ptr->info &= ~(CAVE_UNSAFE);
193 lite_spot(caster_ptr, y, x);
198 if (is_trap(caster_ptr, g_ptr->feat) || has_flag(f_ptr->flags, FF_DOOR)) {
200 msg_print(_("まばゆい閃光が走った!", "There is a bright flash of light!"));
204 cave_alter_feat(caster_ptr, y, x, FF_TUNNEL);
207 if (caster_ptr->blind || !player_has_los_bold(caster_ptr, y, x))
210 g_ptr->info &= ~(CAVE_UNSAFE);
211 lite_spot(caster_ptr, y, x);
216 if (!has_flag(f_ptr->flags, FF_SPIKE))
219 s16b old_mimic = g_ptr->mimic;
220 feature_type *mimic_f_ptr = &f_info[get_feat_mimic(g_ptr)];
222 cave_alter_feat(caster_ptr, y, x, FF_SPIKE);
223 g_ptr->mimic = old_mimic;
225 note_spot(caster_ptr, y, x);
226 lite_spot(caster_ptr, y, x);
228 if (!known || !has_flag(mimic_f_ptr->flags, FF_OPEN))
231 msg_format(_("%sに何かがつっかえて開かなくなった。", "The %s seems stuck."), mimic_f_ptr->name.c_str());
236 if (!has_flag(f_ptr->flags, FF_HURT_ROCK))
239 if (known && (g_ptr->info & (CAVE_MARK))) {
240 msg_format(_("%sが溶けて泥になった!", "The %s turns into mud!"), f_info[get_feat_mimic(g_ptr)].name.c_str());
244 cave_alter_feat(caster_ptr, y, x, FF_HURT_ROCK);
245 caster_ptr->update |= (PU_FLOW);
249 if (!cave_naked_bold(caster_ptr, y, x))
251 if (player_bold(caster_ptr, y, x))
253 cave_set_feat(caster_ptr, y, x, feat_door[DOOR_DOOR].closed);
254 if (g_ptr->info & (CAVE_MARK))
259 place_trap(caster_ptr, y, x);
263 if (!cave_naked_bold(caster_ptr, y, x))
265 if (player_bold(caster_ptr, y, x))
267 cave_set_feat(caster_ptr, y, x, feat_tree);
268 if (g_ptr->info & (CAVE_MARK))
272 case GF_MAKE_RUNE_PROTECTION: {
273 if (!cave_naked_bold(caster_ptr, y, x))
275 g_ptr->info |= CAVE_OBJECT;
276 g_ptr->mimic = feat_rune_protection;
277 note_spot(caster_ptr, y, x);
278 lite_spot(caster_ptr, y, x);
281 case GF_STONE_WALL: {
282 if (!cave_naked_bold(caster_ptr, y, x))
284 if (player_bold(caster_ptr, y, x))
286 cave_set_feat(caster_ptr, y, x, feat_granite);
290 if (has_flag(f_ptr->flags, FF_PERMANENT))
293 if (!has_flag(f_ptr->flags, FF_FLOOR))
295 cave_set_feat(caster_ptr, y, x, feat_shallow_lava);
297 cave_set_feat(caster_ptr, y, x, feat_deep_lava);
302 case GF_WATER_FLOW: {
303 if (has_flag(f_ptr->flags, FF_PERMANENT))
306 if (!has_flag(f_ptr->flags, FF_FLOOR))
308 cave_set_feat(caster_ptr, y, x, feat_shallow_water);
310 cave_set_feat(caster_ptr, y, x, feat_deep_water);
317 if ((d_info[caster_ptr->dungeon_idx].flags1 & DF1_DARKNESS) != 0)
320 g_ptr->info |= (CAVE_GLOW);
321 note_spot(caster_ptr, y, x);
322 lite_spot(caster_ptr, y, x);
323 update_local_illumination(caster_ptr, y, x);
325 if (player_can_see_bold(caster_ptr, y, x))
328 update_monster(caster_ptr, g_ptr->m_idx, FALSE);
330 if (caster_ptr->special_defense & NINJA_S_STEALTH) {
331 if (player_bold(caster_ptr, y, x))
332 set_superstealth(caster_ptr, FALSE);
340 bool do_dark = !caster_ptr->phase_out && !is_mirror_grid(g_ptr);
344 if ((floor_ptr->dun_level > 0) || !is_daytime()) {
345 for (int j = 0; j < 9; j++) {
346 int by = y + ddy_ddd[j];
347 int bx = x + ddx_ddd[j];
349 if (!in_bounds2(floor_ptr, by, bx))
352 grid_type *cc_ptr = &floor_ptr->grid_array[by][bx];
353 if (has_flag(f_info[get_feat_mimic(cc_ptr)].flags, FF_GLOW)) {
363 g_ptr->info &= ~(CAVE_GLOW);
365 /* Hack -- Forget "boring" grids */
366 if (!has_flag(f_ptr->flags, FF_REMEMBER) || has_element_resist(caster_ptr, ElementRealm::DARKNESS, 1)) {
368 g_ptr->info &= ~(CAVE_MARK);
369 note_spot(caster_ptr, y, x);
372 lite_spot(caster_ptr, y, x);
374 update_local_illumination(caster_ptr, y, x);
376 if (player_can_see_bold(caster_ptr, y, x))
379 update_monster(caster_ptr, g_ptr->m_idx, FALSE);
385 if (is_mirror_grid(g_ptr)) {
386 msg_print(_("鏡が割れた!", "The mirror was shattered!"));
388 remove_mirror(caster_ptr, y, x);
389 project(caster_ptr, 0, 2, y, x, caster_ptr->lev / 2 + 5, GF_SHARDS,
390 (PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_JUMP | PROJECT_NO_HANGEKI));
393 if (!has_flag(f_ptr->flags, FF_GLASS) || has_flag(f_ptr->flags, FF_PERMANENT) || (dam < 50))
396 if (known && (g_ptr->info & CAVE_MARK)) {
397 msg_format(_("%sが割れた!", "The %s crumbled!"), f_info[get_feat_mimic(g_ptr)].name.c_str());
401 cave_alter_feat(caster_ptr, y, x, FF_HURT_ROCK);
402 caster_ptr->update |= (PU_FLOW);
406 if (is_mirror_grid(g_ptr) && caster_ptr->lev < 40) {
407 msg_print(_("鏡が割れた!", "The mirror was shattered!"));
409 remove_mirror(caster_ptr, y, x);
410 project(caster_ptr, 0, 2, y, x, caster_ptr->lev / 2 + 5, GF_SHARDS,
411 (PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_JUMP | PROJECT_NO_HANGEKI));
414 if (!has_flag(f_ptr->flags, FF_GLASS) || has_flag(f_ptr->flags, FF_PERMANENT) || (dam < 200))
417 if (known && (g_ptr->info & CAVE_MARK)) {
418 msg_format(_("%sが割れた!", "The %s crumbled!"), f_info[get_feat_mimic(g_ptr)].name.c_str());
422 cave_alter_feat(caster_ptr, y, x, FF_HURT_ROCK);
423 caster_ptr->update |= (PU_FLOW);
426 case GF_DISINTEGRATE: {
427 if (is_mirror_grid(g_ptr) || is_rune_protection_grid(g_ptr) || is_rune_explosion_grid(g_ptr))
428 remove_mirror(caster_ptr, y, x);
430 if (!has_flag(f_ptr->flags, FF_HURT_DISI) || has_flag(f_ptr->flags, FF_PERMANENT))
433 cave_alter_feat(caster_ptr, y, x, FF_HURT_DISI);
434 caster_ptr->update |= (PU_FLOW);
439 lite_spot(caster_ptr, y, x);