static void _charge_spell(int cmd, variant *res) { switch (cmd) { case SPELL_NAME: var_set_string(res, "Charge"); break; case SPELL_DESC: var_set_string(res, "Attacks monster with your weapons normally, then move through counter side of the monster."); break; case SPELL_CAST: { int dir, x, y; var_set_bool(res, FALSE); if (p_ptr->riding) { msg_print("You cannot do it when riding."); return; } if (!get_rep_dir2(&dir)) return; if (dir == 5) return; y = py + ddy[dir]; x = px + ddx[dir]; if (!cave[y][x].m_idx) { msg_print("There is no monster there."); return; } py_attack(y, x, 0); if (player_can_enter(cave[y][x].feat, 0) && !is_trap(cave[y][x].feat)) { y += ddy[dir]; x += ddx[dir]; if (player_can_enter(cave[y][x].feat, 0) && !is_trap(cave[y][x].feat) && !cave[y][x].m_idx) { msg_print(NULL); move_player_effect(y, x, MPE_FORGET_FLOW | MPE_HANDLE_STUFF | MPE_DONT_PICKUP); } } var_set_bool(res, TRUE); break; } default: default_spell(cmd, res); break; } }
/* * Returns random co-ordinates for player/monster/object */ bool new_player_spot(void) { int y = 0, x = 0; int max_attempts = 10000; cave_type *c_ptr; feature_type *f_ptr; /* Place the player */ while (max_attempts--) { /* Pick a legal spot */ y = rand_range(1, cur_hgt - 2); x = rand_range(1, cur_wid - 2); c_ptr = &cave[y][x]; /* Must be a "naked" floor grid */ if (c_ptr->m_idx) continue; if (dun_level) { f_ptr = &f_info[c_ptr->feat]; if (max_attempts > 5000) /* Rule 1 */ { if (!have_flag(f_ptr->flags, FF_FLOOR)) continue; } else /* Rule 2 */ { if (!have_flag(f_ptr->flags, FF_MOVE)) continue; if (have_flag(f_ptr->flags, FF_HIT_TRAP)) continue; } /* Refuse to start on anti-teleport grids in dungeon */ if (!have_flag(f_ptr->flags, FF_TELEPORTABLE)) continue; } if (!player_can_enter(c_ptr->feat, 0)) continue; if (!in_bounds(y, x)) continue; /* Refuse to start on anti-teleport grids */ if (c_ptr->info & (CAVE_ICKY)) continue; /* Done */ break; } if (max_attempts < 1) /* Should be -1, actually if we failed... */ return FALSE; /* Save the new player grid */ py = y; px = x; return TRUE; }
_rush_result _rush_attack(int rng, _rush_type type) { _rush_result result = _rush_cancelled; int tx, ty; int tm_idx = 0; u16b path_g[32]; int path_n, i; bool moved = FALSE; int flg = 0; int dis = 0; if (type == _rush_normal) flg = PROJECT_STOP | PROJECT_KILL; else if (type == _rush_acrobatic) flg = PROJECT_THRU | PROJECT_KILL; else flg = PROJECT_DISI | PROJECT_THRU; if (!p_ptr->duelist_target_idx) { msg_print("You need to select a foe first (Mark Target)."); return result; } tm_idx = p_ptr->duelist_target_idx; tx = m_list[tm_idx].fx; ty = m_list[tm_idx].fy; dis = distance(ty, tx, py, px); /* Foe must be visible. For all charges except the phase charge, the foe must also be in your line of sight */ if (!m_list[p_ptr->duelist_target_idx].ml || (type != _rush_phase && !los(ty, tx, py, px))) { msg_format("%^s is not in your line of sight.", duelist_current_challenge()); return result; } if (dis > rng) { msg_format("Your foe is out of range (%d vs %d).", dis, rng); if (!get_check("Charge anyway? ")) return result; } project_length = rng; path_n = project_path(path_g, project_length, py, px, ty, tx, flg); project_length = 0; if (!path_n) return result; result = _rush_failed; /* Use ty and tx as to-move point */ ty = py; tx = px; /* Scrolling the cave would invalidate our path! */ if (!dun_level && !p_ptr->wild_mode && !p_ptr->inside_arena && !p_ptr->inside_battle) wilderness_scroll_lock = TRUE; /* Project along the path */ for (i = 0; i < path_n; i++) { monster_type *m_ptr; cave_type *c_ptr; bool can_enter = FALSE; bool old_pass_wall = p_ptr->pass_wall; int ny = GRID_Y(path_g[i]); int nx = GRID_X(path_g[i]); c_ptr = &cave[ny][nx]; switch (type) { case _rush_normal: can_enter = cave_empty_bold(ny, nx) && player_can_enter(c_ptr->feat, 0); break; case _rush_acrobatic: can_enter = !c_ptr->m_idx && player_can_enter(c_ptr->feat, 0); break; case _rush_phase: p_ptr->pass_wall = TRUE; can_enter = !c_ptr->m_idx && player_can_enter(c_ptr->feat, 0); p_ptr->pass_wall = old_pass_wall; break; } if (can_enter) { ty = ny; tx = nx; continue; } if (!c_ptr->m_idx) { msg_print("Failed!"); break; } /* Move player before updating the monster */ if (!player_bold(ty, tx)) move_player_effect(ty, tx, MPE_FORGET_FLOW | MPE_HANDLE_STUFF | MPE_DONT_PICKUP); moved = TRUE; /* Update the monster */ update_mon(c_ptr->m_idx, TRUE); /* Found a monster */ m_ptr = &m_list[c_ptr->m_idx]; /* But it is not the monster we seek! */ if (tm_idx != c_ptr->m_idx) { /* Acrobatic Charge attempts to displace monsters on route */ if (type == _rush_acrobatic) { /* Swap position of player and monster */ set_monster_csleep(c_ptr->m_idx, 0); move_player_effect(ny, nx, MPE_FORGET_FLOW | MPE_HANDLE_STUFF | MPE_DONT_PICKUP); ty = ny; tx = nx; continue; } /* Normal Charge just attacks first monster on route */ else msg_format("There is %s in the way!", m_ptr->ml ? (tm_idx ? "another monster" : "a monster") : "someone"); } /* Attack the monster */ if (tm_idx == p_ptr->duelist_target_idx) result = _rush_succeeded; py_attack(ny, nx, 0); break; } if (!moved && !player_bold(ty, tx)) move_player_effect(ty, tx, MPE_FORGET_FLOW | MPE_HANDLE_STUFF | MPE_DONT_PICKUP); if (!dun_level && !p_ptr->wild_mode && !p_ptr->inside_arena && !p_ptr->inside_battle) { wilderness_scroll_lock = FALSE; wilderness_move_player(px, py); } return result; }