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"
8 #include "floor/geometry.h"
9 #include "grid/feature.h"
10 #include "grid/grid.h"
11 #include "grid/trap.h"
12 #include "main/sound-definitions-table.h"
13 #include "main/sound-of-music.h"
14 #include "mind/mind-elementalist.h"
15 #include "mind/mind-ninja.h"
16 #include "monster/monster-update.h"
17 #include "player/special-defense-types.h"
18 #include "room/door-definition.h"
19 #include "spell/spell-types.h"
20 #include "system/floor-type-definition.h"
21 #include "system/grid-type-definition.h"
22 #include "system/player-type-definition.h"
23 #include "util/bit-flags-calculator.h"
24 #include "view/display-messages.h"
25 #include "world/world.h"
28 * Determine if a "legal" grid is an "naked" floor grid
30 * Line 1 -- forbid non-clean gird
31 * Line 2 -- forbid monsters
32 * Line 3 -- forbid the player
34 static bool cave_naked_bold(player_type *player_ptr, POSITION y, POSITION x)
36 floor_type *floor_ptr = player_ptr->current_floor_ptr;
37 return cave_clean_bold(floor_ptr, y, x) && (floor_ptr->grid_array[y][x].m_idx == 0) && !player_bold(player_ptr, y, x);
41 * @brief 汎用的なビーム/ボルト/ボール系による地形効果処理 / We are called from "project()" to "damage" terrain features
42 * @param player_ptr プレイヤーへの参照ポインタ
43 * @param who 魔法を発動したモンスター(0ならばプレイヤー) / Index of "source" monster (zero for "player")
44 * @param r 効果半径(ビーム/ボルト = 0 / ボール = 1以上) / Radius of explosion (0 = beam/bolt, 1 to 9 = ball)
45 * @param y 目標Y座標 / Target y location (or location to travel "towards")
46 * @param x 目標X座標 / Target x location (or location to travel "towards")
47 * @param dam 基本威力 / Base damage roll to apply to affected monsters (or player)
48 * @param typ 効果属性 / Type of damage to apply to monsters (and objects)
49 * @return 何か一つでも効力があればTRUEを返す / TRUE if any "effects" of the projection were observed, else FALSE
52 * We are called both for "beam" effects and "ball" effects.
54 * The "r" parameter is the "distance from ground zero".
56 * Note that we determine if the player can "see" anything that happens
57 * by taking into account: blindness, line-of-sight, and illumination.
59 * We return "TRUE" if the effect of the projection is "obvious".
61 * We also "see" grids which are "memorized", probably a hack
63 * Perhaps we should affect doors?
66 bool affect_feature(player_type *player_ptr, MONSTER_IDX who, POSITION r, POSITION y, POSITION x, HIT_POINT dam, EFFECT_ID typ)
68 floor_type *floor_ptr = player_ptr->current_floor_ptr;
69 grid_type *g_ptr = &floor_ptr->grid_array[y][x];
70 feature_type *f_ptr = &f_info[g_ptr->feat];
73 bool known = player_has_los_bold(player_ptr, y, x);
76 dam = (dam + r) / (r + 1);
78 if (f_ptr->flags.has(FF::TREE)) {
84 message = _("枯れた", "was blasted.");
87 message = _("縮んだ", "shrank.");
90 message = _("溶けた", "melted.");
94 message = _("凍り、砕け散った", "was frozen and smashed.");
99 message = _("燃えた", "burns up!");
112 message = _("粉砕された", "was crushed.");
115 message = _("消滅した", "vanished.");
123 msg_format(_("木は%s。", "A tree %s"), message);
124 cave_set_feat(player_ptr, y, x, one_in_(3) ? feat_brake : feat_grass);
127 if (g_ptr->is_mark())
132 /* Analyze the type */
134 /* Ignore most effects */
168 if (is_hidden_door(player_ptr, g_ptr)) {
169 disclose_grid(player_ptr, y, x);
175 if (is_trap(player_ptr, g_ptr->feat)) {
177 msg_print(_("まばゆい閃光が走った!", "There is a bright flash of light!"));
181 cave_alter_feat(player_ptr, y, x, FF::DISARM);
184 if (is_closed_door(player_ptr, g_ptr->feat) && f_ptr->power && f_ptr->flags.has(FF::OPEN)) {
185 FEAT_IDX old_feat = g_ptr->feat;
186 cave_alter_feat(player_ptr, y, x, FF::DISARM);
187 if (known && (old_feat != g_ptr->feat)) {
188 msg_print(_("カチッと音がした!", "Click!"));
193 if (player_ptr->blind || !player_has_los_bold(player_ptr, y, x))
196 g_ptr->info &= ~(CAVE_UNSAFE);
197 lite_spot(player_ptr, y, x);
202 if (is_trap(player_ptr, g_ptr->feat) || f_ptr->flags.has(FF::DOOR)) {
204 msg_print(_("まばゆい閃光が走った!", "There is a bright flash of light!"));
208 cave_alter_feat(player_ptr, y, x, FF::TUNNEL);
211 if (player_ptr->blind || !player_has_los_bold(player_ptr, y, x))
214 g_ptr->info &= ~(CAVE_UNSAFE);
215 lite_spot(player_ptr, y, x);
220 if (f_ptr->flags.has_not(FF::SPIKE))
223 int16_t old_mimic = g_ptr->mimic;
224 feature_type *mimic_f_ptr = &f_info[g_ptr->get_feat_mimic()];
226 cave_alter_feat(player_ptr, y, x, FF::SPIKE);
227 g_ptr->mimic = old_mimic;
229 note_spot(player_ptr, y, x);
230 lite_spot(player_ptr, y, x);
232 if (!known || mimic_f_ptr->flags.has_not(FF::OPEN))
235 msg_format(_("%sに何かがつっかえて開かなくなった。", "The %s seems stuck."), mimic_f_ptr->name.c_str());
240 if (f_ptr->flags.has_not(FF::HURT_ROCK))
243 if (known && g_ptr->is_mark()) {
244 msg_format(_("%sが溶けて泥になった!", "The %s turns into mud!"), f_info[g_ptr->get_feat_mimic()].name.c_str());
248 cave_alter_feat(player_ptr, y, x, FF::HURT_ROCK);
249 player_ptr->update |= (PU_FLOW);
253 if (!cave_naked_bold(player_ptr, y, x))
255 if (player_bold(player_ptr, y, x))
257 cave_set_feat(player_ptr, y, x, feat_door[DOOR_DOOR].closed);
258 if (g_ptr->is_mark())
263 place_trap(player_ptr, y, x);
267 if (!cave_naked_bold(player_ptr, y, x))
269 if (player_bold(player_ptr, y, x))
271 cave_set_feat(player_ptr, y, x, feat_tree);
272 if (g_ptr->is_mark())
276 case GF_MAKE_RUNE_PROTECTION: {
277 if (!cave_naked_bold(player_ptr, y, x))
279 g_ptr->info |= CAVE_OBJECT;
280 g_ptr->mimic = feat_rune_protection;
281 note_spot(player_ptr, y, x);
282 lite_spot(player_ptr, y, x);
285 case GF_STONE_WALL: {
286 if (!cave_naked_bold(player_ptr, y, x))
288 if (player_bold(player_ptr, y, x))
290 cave_set_feat(player_ptr, y, x, feat_granite);
294 if (f_ptr->flags.has(FF::PERMANENT))
297 if (f_ptr->flags.has_not(FF::FLOOR))
299 cave_set_feat(player_ptr, y, x, feat_shallow_lava);
301 cave_set_feat(player_ptr, y, x, feat_deep_lava);
306 case GF_WATER_FLOW: {
307 if (f_ptr->flags.has(FF::PERMANENT))
310 if (f_ptr->flags.has_not(FF::FLOOR))
312 cave_set_feat(player_ptr, y, x, feat_shallow_water);
314 cave_set_feat(player_ptr, y, x, feat_deep_water);
321 if (d_info[player_ptr->dungeon_idx].flags.has(DF::DARKNESS))
324 g_ptr->info |= (CAVE_GLOW);
325 note_spot(player_ptr, y, x);
326 lite_spot(player_ptr, y, x);
327 update_local_illumination(player_ptr, y, x);
329 if (player_can_see_bold(player_ptr, y, x))
332 update_monster(player_ptr, g_ptr->m_idx, false);
334 if (player_bold(player_ptr, y, x)) {
335 set_superstealth(player_ptr, false);
343 bool do_dark = !player_ptr->phase_out && !g_ptr->is_mirror();
347 if ((floor_ptr->dun_level > 0) || !is_daytime()) {
348 for (int j = 0; j < 9; j++) {
349 int by = y + ddy_ddd[j];
350 int bx = x + ddx_ddd[j];
352 if (!in_bounds2(floor_ptr, by, bx))
355 grid_type *cc_ptr = &floor_ptr->grid_array[by][bx];
356 if (f_info[cc_ptr->get_feat_mimic()].flags.has(FF::GLOW)) {
366 g_ptr->info &= ~(CAVE_GLOW);
368 /* Hack -- Forget "boring" grids */
369 if (f_ptr->flags.has_not(FF::REMEMBER) || has_element_resist(player_ptr, ElementRealm::DARKNESS, 1)) {
371 g_ptr->info &= ~(CAVE_MARK);
372 note_spot(player_ptr, y, x);
375 lite_spot(player_ptr, y, x);
377 update_local_illumination(player_ptr, y, x);
379 if (player_can_see_bold(player_ptr, y, x))
382 update_monster(player_ptr, g_ptr->m_idx, false);
388 if (g_ptr->is_mirror()) {
389 msg_print(_("鏡が割れた!", "The mirror was shattered!"));
391 remove_mirror(player_ptr, y, x);
392 project(player_ptr, 0, 2, y, x, player_ptr->lev / 2 + 5, GF_SHARDS,
393 (PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_JUMP | PROJECT_NO_HANGEKI));
396 if (f_ptr->flags.has_not(FF::GLASS) || f_ptr->flags.has(FF::PERMANENT) || (dam < 50))
399 if (known && (g_ptr->is_mark())) {
400 msg_format(_("%sが割れた!", "The %s crumbled!"), f_info[g_ptr->get_feat_mimic()].name.c_str());
404 cave_alter_feat(player_ptr, y, x, FF::HURT_ROCK);
405 player_ptr->update |= (PU_FLOW);
409 if (g_ptr->is_mirror() && player_ptr->lev < 40) {
410 msg_print(_("鏡が割れた!", "The mirror was shattered!"));
412 remove_mirror(player_ptr, y, x);
413 project(player_ptr, 0, 2, y, x, player_ptr->lev / 2 + 5, GF_SHARDS,
414 (PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | PROJECT_JUMP | PROJECT_NO_HANGEKI));
417 if (f_ptr->flags.has_not(FF::GLASS) || f_ptr->flags.has(FF::PERMANENT) || (dam < 200))
420 if (known && (g_ptr->is_mark())) {
421 msg_format(_("%sが割れた!", "The %s crumbled!"), f_info[g_ptr->get_feat_mimic()].name.c_str());
425 cave_alter_feat(player_ptr, y, x, FF::HURT_ROCK);
426 player_ptr->update |= (PU_FLOW);
429 case GF_DISINTEGRATE: {
430 if (g_ptr->is_mirror() || g_ptr->is_rune_protection() || g_ptr->is_rune_explosion())
431 remove_mirror(player_ptr, y, x);
433 if (f_ptr->flags.has_not(FF::HURT_DISI) || f_ptr->flags.has(FF::PERMANENT))
436 cave_alter_feat(player_ptr, y, x, FF::HURT_DISI);
437 player_ptr->update |= (PU_FLOW);
442 lite_spot(player_ptr, y, x);