static bool _elemental_healing(int flag) { int dir, ct = 0; if (!cave_have_flag_bold(py, px, flag)) { msg_print("Failed! You are out of your element!"); return FALSE; } for (dir = 0; dir < 8; dir++) { int x = px + ddx_ddd[dir]; int y = py + ddy_ddd[dir]; if (!in_bounds(y, x)) continue; if (cave_have_flag_bold(y, x, flag)) ct++; } if (ct < 4) { msg_print("Failed! You need to be surrounded by your element!"); return FALSE; } msg_print("You bask in your element and slowly feel your life returning ... "); hp_player(100 + p_ptr->lev * 3); return TRUE; }
static void _excavation_spell(int cmd, variant *res) { switch (cmd) { case SPELL_NAME: var_set_string(res, "Excavation"); break; case SPELL_DESC: var_set_string(res, "You break walls on your quest for treasure! This takes a bit more time, though."); break; case SPELL_ENERGY: { int n = 200; if (equip_find_object(TV_DIGGING, SV_ANY)) n -= 120 * p_ptr->lev / 50; else n -= 80 * p_ptr->lev / 50; var_set_int(res, n); } break; case SPELL_CAST: { int dir = 5; bool b = FALSE; if ( get_rep_dir2(&dir) && dir != 5 ) { int x, y; y = py + ddy[dir]; x = px + ddx[dir]; if (!in_bounds(y, x)) { msg_print("You may excavate no further."); } else if ( cave_have_flag_bold(y, x, FF_WALL) || cave_have_flag_bold(y, x, FF_TREE) || cave_have_flag_bold(y, x, FF_CAN_DIG) ) { msg_print("You dig your way to treasure!"); cave_alter_feat(y, x, FF_TUNNEL); teleport_player_to(y, x, TELEPORT_NONMAGICAL); /*??*/ b = TRUE; } else { msg_print("There is nothing to excavate."); } } var_set_bool(res, b); } break; default: default_spell(cmd, res); break; } }
void _scatter_spell(int cmd, variant *res) { switch (cmd) { case SPELL_NAME: var_set_string(res, "Scatter"); break; case SPELL_DESC: var_set_string(res, "Attack all adjacent monsters with a single strike. If landed, your enemies will be scattered away from you."); break; case SPELL_CAST: { int dir, x, y; cave_type *c_ptr; monster_type *m_ptr; for (dir = 0; dir < 8; dir++) { y = py + ddy_ddd[dir]; x = px + ddx_ddd[dir]; c_ptr = &cave[y][x]; m_ptr = &m_list[c_ptr->m_idx]; if (c_ptr->m_idx && (m_ptr->ml || cave_have_flag_bold(y, x, FF_PROJECT))) py_attack(y, x, MAULER_SCATTER); } var_set_bool(res, TRUE); break; } default: default_spell(cmd, res); break; } }
static void _cavern_creation_spell(int cmd, variant *res) { switch (cmd) { case SPELL_NAME: var_set_string(res, "Cavern Creation"); break; case SPELL_DESC: var_set_string(res, "Stone to Mud all surrounding walls."); break; case SPELL_CAST: { int dir, x, y, ct = 0; for (dir = 0; dir < 8; dir++) { y = py + ddy_ddd[dir]; x = px + ddx_ddd[dir]; if (!in_bounds(y, x)) continue; if (!cave_have_flag_bold(y, x, FF_HURT_ROCK)) continue; cave_alter_feat(y, x, FF_HURT_ROCK); ct++; } if (ct) p_ptr->update |= (PU_FLOW | PU_BONUS); var_set_bool(res, TRUE); break; } default: default_spell(cmd, res); break; } }
static bool _cave_is_open(int y, int x) { if (cave_have_flag_bold(y, x, FF_HURT_ROCK)) return FALSE; if (cave[y][x].feat == feat_permanent) return FALSE; if (cave[y][x].feat == feat_permanent_glass_wall) return FALSE; if (cave[y][x].feat == feat_mountain) return FALSE; return TRUE; }
static void _smash_wall_spell(int cmd, variant *res) { switch (cmd) { case SPELL_NAME: var_set_string(res, "Smash"); break; case SPELL_DESC: var_set_string(res, "Destroys adjacent targeted wall, door, tree, or trap."); break; case SPELL_CAST: { int y, x, dir; var_set_bool(res, FALSE); if (!get_rep_dir2(&dir)) return; if (dir == 5) return; y = py + ddy[dir]; x = px + ddx[dir]; if (!in_bounds(y, x)) return; if (cave_have_flag_bold(y, x, FF_HURT_ROCK)) { cave_alter_feat(y, x, FF_HURT_ROCK); p_ptr->update |= PU_FLOW; } else if (cave_have_flag_bold(y, x, FF_TREE)) { cave_set_feat(y, x, one_in_(3) ? feat_brake : feat_grass); } else { int flg = PROJECT_GRID | PROJECT_ITEM | PROJECT_HIDE; project(0, 0, y, x, 0, GF_KILL_DOOR, flg, -1); } var_set_bool(res, TRUE); break; } default: default_spell(cmd, res); break; } }
/* * Determine if the given location is "between" two walls, * and "next to" two corridor spaces. XXX XXX XXX * * Assumes "in_bounds(y, x)" */ static bool possible_doorway(int y, int x) { /* Count the adjacent corridors */ if (next_to_corr(y, x) >= 2) { /* Check Vertical */ if (cave_have_flag_bold(y - 1, x, FF_WALL) && cave_have_flag_bold(y + 1, x, FF_WALL)) { return (TRUE); } /* Check Horizontal */ if (cave_have_flag_bold(y, x - 1, FF_WALL) && cave_have_flag_bold(y, x + 1, FF_WALL)) { return (TRUE); } } /* No doorway */ return (FALSE); }
/* * Places door at y, x position if at least 2 walls found */ static void try_door(int y, int x) { /* Paranoia */ if (!in_bounds(y, x)) return; /* Ignore walls */ if (cave_have_flag_bold(y, x, FF_WALL)) return; /* Ignore room grids */ if (cave[y][x].info & (CAVE_ROOM)) return; /* Occasional door (if allowed) */ if ((randint0(100) < dun_tun_jct) && possible_doorway(y, x) && !(d_info[dungeon_type].flags1 & DF1_NO_DOORS)) { /* Place a door */ place_random_door(y, x, FALSE); } }
static bool _elemental_travel(int flag) { int rng = p_ptr->lev / 2 + 10; int x, y; if (!tgt_pt(&x, &y, rng)) return FALSE; if (!in_bounds(y, x)) return FALSE; if (!cave_have_flag_bold(y, x, flag)) { msg_print("Failed! You are out of your element!"); teleport_player((p_ptr->lev + 2) * 2, TELEPORT_PASSIVE); } else if (one_in_(7)) { msg_print("You failed to travel correctly!"); teleport_player((p_ptr->lev + 2) * 2, TELEPORT_PASSIVE); } else teleport_player_to(y, x, 0); return TRUE; }
/*! * @brief モンスターが特殊能力の目標地点を決める処理 / * Get the actual center point of ball spells (rad > 1) (originally from TOband) * @param sy 始点のY座標 * @param sx 始点のX座標 * @param ty 目標Y座標を返す参照ポインタ * @param tx 目標X座標を返す参照ポインタ * @param flg 判定のフラグ配列 * @return なし */ void get_project_point(int sy, int sx, int *ty, int *tx, int flg) { u16b path_g[128]; int path_n, i; path_n = project_path(path_g, MAX_RANGE, sy, sx, *ty, *tx, flg); *ty = sy; *tx = sx; /* Project along the path */ for (i = 0; i < path_n; i++) { sy = GRID_Y(path_g[i]); sx = GRID_X(path_g[i]); /* Hack -- Balls explode before reaching walls */ if (!cave_have_flag_bold(sy, sx, FF_PROJECT)) break; *ty = sy; *tx = sx; } }
static void _stone_smash_spell(int cmd, variant *res) { switch (cmd) { case SPELL_NAME: var_set_string(res, "Stone Smash"); break; case SPELL_DESC: var_set_string(res, "Destroys adjacent targeted wall."); break; case SPELL_CAST: { int y, x, dir; var_set_bool(res, FALSE); if (!get_rep_dir2(&dir)) return; if (dir == 5) return; y = py + ddy[dir]; x = px + ddx[dir]; if (!in_bounds(y, x)) return; if (cave_have_flag_bold(y, x, FF_HURT_ROCK)) { cave_alter_feat(y, x, FF_HURT_ROCK); p_ptr->update |= PU_FLOW; } var_set_bool(res, TRUE); break; } default: default_spell(cmd, res); break; } }
/* A special fetch(), that places item in player's inventory */ static bool _whip_fetch(int dir, int rng) { int ty, tx; cave_type *c_ptr; object_type *o_ptr; char o_name[MAX_NLEN]; /* Use a target */ if (dir == 5 && target_okay()) { tx = target_col; ty = target_row; if (distance(py, px, ty, tx) > rng) { msg_print("You can't fetch something that far away!"); return FALSE; } c_ptr = &cave[ty][tx]; /* We need an item to fetch */ if (!c_ptr->o_idx) { msg_print("There is no object at this place."); return TRUE; /* didn't work, but charge the player energy anyway */ } /* Fetching from a vault is OK */ /* Line of sight is required */ if (!player_has_los_bold(ty, tx)) { msg_print("You have no direct line of sight to that location."); return FALSE; } else if (!projectable(py, px, ty, tx)) { msg_print("You have no direct line of sight to that location."); return FALSE; } } else { /* Use a direction */ ty = py; /* Where to drop the item */ tx = px; do { ty += ddy[dir]; tx += ddx[dir]; c_ptr = &cave[ty][tx]; if ((distance(py, px, ty, tx) > MAX_RANGE) || !in_bounds(ty, tx) || !cave_have_flag_bold(ty, tx, FF_PROJECT)) { return TRUE; /* didn't work, but charge the player energy anyway */ } } while (!c_ptr->o_idx); } o_ptr = &o_list[c_ptr->o_idx]; if (o_ptr->weight > p_ptr->lev * 15) { msg_print("The object is too heavy."); return TRUE; /* didn't work, but charge the player energy anyway */ } object_desc(o_name, o_ptr, OD_NAME_ONLY); /* Get the object */ if (!inven_carry_okay(o_ptr)) { cmsg_format(TERM_VIOLET, "You fail to fetch %^s since your pack is full.", o_name); /* Leave the object where it is */ } else { msg_format("You skillfully crack your whip and fetch %^s.", o_name); py_pickup_aux(c_ptr->o_idx); } return TRUE; }
static void _double_crack_spell(int cmd, variant *res) { switch (cmd) { case SPELL_NAME: var_set_string(res, "Double Crack"); break; case SPELL_DESC: var_set_string(res, "Attack a monster normally with your whip, and then randomly attack an adjacent monster."); break; case SPELL_CAST: if (_whip_check()) { int dir = 5; bool b = FALSE; if ( get_rep_dir2(&dir) && dir != 5 ) { int x, y; int num = 1; int attempts = 0; /* First we attack where the player selected */ y = py + ddy[dir]; x = px + ddx[dir]; if (in_bounds(y, x) && cave[y][x].m_idx) py_attack(y, x, 0); else msg_print("Your whip cracks in empty air."); /* Now the whip cracks randomly! Note that we favor fighting in hallways, or with ones back up against the wall. */ while (num > 0) { if (attempts > 3 * num) { while (num > 0) { msg_print("Your whip cracks in empty air."); num--; } break; } /* random direction, but we don't penalize for choosing the player (5) */ dir = randint0(9); if (dir == 5) continue; attempts++; y = py + ddy[dir]; x = px + ddx[dir]; if ( !in_bounds(y, x) || cave_have_flag_bold(y, x, FF_WALL) || cave_have_flag_bold(y, x, FF_TREE) || cave_have_flag_bold(y, x, FF_CAN_DIG) ) { continue; } if (cave[y][x].m_idx) py_attack(y, x, 0); else msg_print("Your whip cracks in empty air."); num--; } b = TRUE; } var_set_bool(res, b); } else { msg_print("Whip techniques can only be used if you are fighting with whips."); var_set_bool(res, FALSE); } break; default: default_spell(cmd, res); break; } }
static void _greater_whirlwind_attack_spell(int cmd, variant *res) { switch (cmd) { case SPELL_NAME: var_set_string(res, "Greater Ambush"); break; case SPELL_DESC: var_set_string(res, "Perform a massive ambush on nearby monsters."); break; case SPELL_CAST: { int i, x, y; cave_type *c_ptr; monster_type *m_ptr; /* cba d218l e3@7k f456j ghi */ typedef struct _offset_t { int dx; int dy; } _offset; static _offset offsets[] = { { 0, -1}, {-1, -1}, {-1, 0}, {-1, 1}, { 0, 1}, { 1, 1}, { 1, 0}, { 1, -1}, { 1, -2}, { 0, -2}, {-1, -2}, {-2, -1}, {-2, 0}, {-2, 1}, {-1, 2}, { 0, 2}, { 1, 2}, { 2, 1}, { 2, 0}, { 2, -1}, { 0, 0}, /* sentinel */ }; for (i = 0;; i++) { _offset offset = offsets[i]; if (offset.dx == 0 && offset.dy == 0) break; y = py + offset.dy; x = px + offset.dx; if (!in_bounds(y, x)) continue; if (!projectable(py, px, y, x)) continue; c_ptr = &cave[y][x]; if (!c_ptr->m_idx) continue; m_ptr = &m_list[c_ptr->m_idx]; if (m_ptr->ml || cave_have_flag_bold(y, x, FF_PROJECT)) { int msec = delay_factor * delay_factor * delay_factor; if (panel_contains(y, x) && player_can_see_bold(y, x)) { char c = 0x30; byte a = TERM_WHITE; print_rel(c, a, y, x); move_cursor_relative(y, x); Term_fresh(); Term_xtra(TERM_XTRA_DELAY, msec); lite_spot(y, x); Term_fresh(); } else Term_xtra(TERM_XTRA_DELAY, msec); py_attack(y, x, 0); } } var_set_bool(res, TRUE); break; } default: default_spell(cmd, res); break; } }
/*! * @brief モンスターが敵対モンスターに直接ブレスを当てることが可能かを判定する / * Determine if a breath will hit the target. * @param y1 始点のY座標 * @param x1 始点のX座標 * @param y2 目標のY座標 * @param x2 目標のX座標 * @param rad 半径 * @param typ 効果属性ID * @param is_friend TRUEならば、プレイヤーを巻き込む時にブレスの判定をFALSEにする。 * @return ブレスを直接当てられるならばTRUEを返す */ static bool breath_direct(int y1, int x1, int y2, int x2, int rad, int typ, bool is_friend) { /* Must be the same as projectable() */ int i; /* Initial grid */ int y = y1; int x = x1; int grid_n = 0; u16b grid_g[512]; int grids = 0; byte gx[1024], gy[1024]; byte gm[32]; int gm_rad = rad; bool hit2 = FALSE; bool hityou = FALSE; int flg; switch (typ) { case GF_LITE: case GF_LITE_WEAK: flg = PROJECT_LOS; break; case GF_DISINTEGRATE: flg = PROJECT_DISI; break; default: flg = 0; break; } /* Check the projection path */ grid_n = project_path(grid_g, MAX_RANGE, y1, x1, y2, x2, flg); /* Project along the path */ for (i = 0; i < grid_n; ++i) { int ny = GRID_Y(grid_g[i]); int nx = GRID_X(grid_g[i]); if (flg & PROJECT_DISI) { /* Hack -- Balls explode before reaching walls */ if (cave_stop_disintegration(ny, nx)) break; } else if (flg & PROJECT_LOS) { /* Hack -- Balls explode before reaching walls */ if (!cave_los_bold(ny, nx)) break; } else { /* Hack -- Balls explode before reaching walls */ if (!cave_have_flag_bold(ny, nx, FF_PROJECT)) break; } /* Save the "blast epicenter" */ y = ny; x = nx; } grid_n = i; if (!grid_n) { if (flg & PROJECT_DISI) { if (in_disintegration_range(y1, x1, y2, x2) && (distance(y1, x1, y2, x2) <= rad)) hit2 = TRUE; if (in_disintegration_range(y1, x1, p_ptr->y, p_ptr->x) && (distance(y1, x1, p_ptr->y, p_ptr->x) <= rad)) hityou = TRUE; } else if (flg & PROJECT_LOS) { if (los(y1, x1, y2, x2) && (distance(y1, x1, y2, x2) <= rad)) hit2 = TRUE; if (los(y1, x1, p_ptr->y, p_ptr->x) && (distance(y1, x1, p_ptr->y, p_ptr->x) <= rad)) hityou = TRUE; } else { if (projectable(y1, x1, y2, x2) && (distance(y1, x1, y2, x2) <= rad)) hit2 = TRUE; if (projectable(y1, x1, p_ptr->y, p_ptr->x) && (distance(y1, x1, p_ptr->y, p_ptr->x) <= rad)) hityou = TRUE; } } else { breath_shape(grid_g, grid_n, &grids, gx, gy, gm, &gm_rad, rad, y1, x1, y, x, typ); for (i = 0; i < grids; i++) { /* Extract the location */ y = gy[i]; x = gx[i]; if ((y == y2) && (x == x2)) hit2 = TRUE; if (player_bold(y, x)) hityou = TRUE; } } if (!hit2) return FALSE; if (is_friend && hityou) return FALSE; return TRUE; }