/** * Front-end command which fires at the nearest target with default ammo. */ void textui_cmd_fire_at_nearest(void) { /* the direction '5' means 'use the target' */ int i, dir = 5, item = -1; /* Require a usable launcher */ if (!p_ptr->inventory[INVEN_BOW].tval || !p_ptr->state.ammo_tval) { msg("You have nothing to fire with."); return; } /* Find first eligible ammo in the quiver */ for (i = QUIVER_START; i < QUIVER_END; i++) { if (p_ptr->inventory[i].tval != p_ptr->state.ammo_tval) continue; item = i; break; } /* Require usable ammo */ if (item < 0) { msg("You have no ammunition in the quiver to fire"); return; } /* Require foe */ if (!target_set_closest(TARGET_KILL | TARGET_QUIET)) return; /* Fire! */ cmd_insert(CMD_FIRE); cmd_set_arg_item(cmd_get_top(), 0, item); cmd_set_arg_target(cmd_get_top(), 1, dir); }
/** * Front-end command which fires at the nearest target with default ammo. */ void do_cmd_fire_at_nearest(void) { int i, dir = DIR_TARGET; struct object *ammo = NULL; struct object *bow = equipped_item_by_slot_name(player, "shooting"); /* Require a usable launcher */ if (!bow || !player->state.ammo_tval) { msg("You have nothing to fire with."); return; } /* Find first eligible ammo in the quiver */ for (i = 0; i < z_info->quiver_size; i++) { if (!player->upkeep->quiver[i]) continue; if (player->upkeep->quiver[i]->tval != player->state.ammo_tval) continue; ammo = player->upkeep->quiver[i]; break; } /* Require usable ammo */ if (!ammo) { msg("You have no ammunition in the quiver to fire."); return; } /* Require foe */ if (!target_set_closest(TARGET_KILL | TARGET_QUIET)) return; /* Fire! */ cmdq_push(CMD_FIRE); cmd_set_arg_item(cmdq_peek(), "item", ammo); cmd_set_arg_target(cmdq_peek(), "target", dir); }
/** * Target closest monster. * * XXX: Move to using CMD_TARGET_CLOSEST at some point instead of invoking * target_set_closest() directly. */ void textui_target_closest(void) { if (target_set_closest(TARGET_KILL)) { bool visibility; int x, y; target_get(&x, &y); /* Visual cue */ Term_fresh(); Term_get_cursor(&visibility); (void)Term_set_cursor(TRUE); move_cursor_relative(y, x); Term_redraw_section(x, y, x, y); /* TODO: what's an appropriate amount of time to spend highlighting */ Term_xtra(TERM_XTRA_DELAY, 150); (void)Term_set_cursor(visibility); } }
/* * Get an "aiming direction" (1,2,3,4,6,7,8,9 or 5) from the user. * * Return TRUE if a direction was chosen, otherwise return FALSE. * * The direction "5" is special, and means "use current target". * * This function tracks and uses the "global direction", and uses * that as the "desired direction", if it is set. * * Note that "Force Target", if set, will pre-empt user interaction, * if there is a usable target already set. * * Currently this function applies confusion directly. */ bool get_aim_dir(int *dp) { /* Global direction */ int dir = 0; ui_event_data ke; cptr p; /* Initialize */ (*dp) = 0; /* Hack -- auto-target if requested */ if (OPT(use_old_target) && target_okay() && !dir) dir = 5; /* Ask until satisfied */ while (!dir) { /* Choose a prompt */ if (!target_okay()) p = "Direction ('*' or <click> to target, \"'\" for closest, Escape to cancel)? "; else p = "Direction ('5' for target, '*' or <click> to re-target, Escape to cancel)? "; /* Get a command (or Cancel) */ if (!get_com_ex(p, &ke)) break; if (ke.type == EVT_MOUSE) { if (target_set_interactive (TARGET_KILL, KEY_GRID_X(ke), KEY_GRID_Y(ke))) dir = 5; } else if (ke.type == EVT_KBRD) { if (ke.key == '*') { /* Set new target, use target if legal */ if (target_set_interactive(TARGET_KILL, -1, -1)) dir = 5; } else if (ke.key == '\'') { /* Set to closest target */ if (target_set_closest(TARGET_KILL)) dir = 5; } else if (ke.key == 't' || ke.key == '5' || ke.key == '0' || ke.key == '.') { if (target_okay()) dir = 5; } else { /* Possible direction */ int keypresses_handled = 0; while (ke.key != 0) { int this_dir; /* XXX Ideally show and move the cursor here to indicate * the currently "Pending" direction. XXX */ this_dir = target_dir(ke.key); if (this_dir) dir = dir_transitions[dir][this_dir]; else break; if (lazymove_delay == 0 || ++keypresses_handled > 1) break; /* See if there's a second keypress within the defined * period of time. */ inkey_scan = lazymove_delay; ke = inkey_ex(); } } } /* Error */ if (!dir) bell("Illegal aim direction!"); } /* No direction */ if (!dir) return (FALSE); /* Save direction */ (*dp) = dir; /* Check for confusion */ if (p_ptr->timed[TMD_CONFUSED]) { /* Random direction */ dir = ddd[randint0(8)]; } /* Notice confusion */ if ((*dp) != dir) { /* Warn the user */ msg_print("You are confused."); } /* Save direction */ (*dp) = dir; /* A "valid" direction was entered */ return (TRUE); }
// Repeat the previous command // Assumes the command and args were properly saved void do_cmd_repeat(void) { if (!character_dungeon) return; if (!p_ptr->command_previous) return; // repeat the previous command command_type *command_ptr = &command_info[p_ptr->command_previous]; // Make sure we are dealing with the same item if (command_ptr->cmd_needs & (ARG_ITEM)) { object_type *o_ptr = object_from_item_idx(p_ptr->command_previous_args.item); if (o_ptr->k_idx != p_ptr->command_previous_args.k_idx) { pop_up_message_box("Unable to repeat command.<br>Item has been moved or changed."); p_ptr->player_previous_command_wipe(); return; } } if (p_ptr->command_previous == CMD_CAST) { if (!spell_needs_aim(cp_ptr->spell_book, p_ptr->command_previous_args.number)) p_ptr->command_previous_args.direction = DIR_UNKNOWN; else if (p_ptr->command_previous_args.direction == DIR_CLOSEST) { int mode = TARGET_QUIET; if (!is_trap_spell(cp_ptr->spell_book, p_ptr->command_previous_args.number)) mode |= TARGET_KILL; else mode |= TARGET_TRAP; if (!target_set_closest(mode)) p_ptr->command_previous_args.direction = DIR_UNKNOWN; } } else if (p_ptr->command_previous == CMD_ITEM_USE) { object_type *o_ptr = object_from_item_idx(p_ptr->command_previous_args.item); if (!obj_needs_aim(o_ptr)) p_ptr->command_previous_args.direction = DIR_UNKNOWN; else if (p_ptr->command_previous_args.direction == DIR_CLOSEST) { int mode = TARGET_QUIET; if (!k_info[o_ptr->k_idx].is_trap_object_kind()) mode |= TARGET_KILL; else mode |= TARGET_TRAP; if (!target_set_closest(mode)) p_ptr->command_previous_args.direction = DIR_UNKNOWN; } } else if (!command_ptr->keep_direction()) { p_ptr->command_previous_args.direction = DIR_UNKNOWN; } // Get the direction, if necessary if (command_ptr->needs_direction()) { if (!get_aim_dir(&p_ptr->command_previous_args.direction, FALSE)) return; } command_ptr->command_function(p_ptr->command_previous_args); }
void commands_angband_keyset(int key_press, bool shift_key, bool alt_key, bool ctrl_key, bool meta_key) { bool using_mods = FALSE; if (shift_key || alt_key || ctrl_key || meta_key) using_mods = TRUE; // Normal mode switch (key_press) { // ESCAPE case Qt::Key_Escape: { ui_center(p_ptr->py, p_ptr->px); break; } // Move down case Qt::Key_2: case Qt::Key_Down: { process_move_key(2, shift_key, alt_key, ctrl_key, meta_key); break; } // Move up case Qt::Key_8: case Qt::Key_Up: { process_move_key(8, shift_key, alt_key, ctrl_key, meta_key); break; } // Move left case Qt::Key_4: case Qt::Key_Left: { process_move_key(4, shift_key, alt_key, ctrl_key, meta_key); break; } // Move right case Qt::Key_6: case Qt::Key_Right: { process_move_key(6, shift_key, alt_key, ctrl_key, meta_key); break; } // Move diagonally left and up case Qt::Key_7: case Qt::Key_Home: { process_move_key(7, shift_key, alt_key, ctrl_key, meta_key); break; } // Move diagonally right and up case Qt::Key_9: case Qt::Key_PageUp: { process_move_key(9, shift_key, alt_key, ctrl_key, meta_key); break; } // Move diagonally left and down case Qt::Key_1: case Qt::Key_End: { process_move_key(1, shift_key, alt_key, ctrl_key, meta_key); break; } // Move diagonally right and down case Qt::Key_3: case Qt::Key_PageDown: { process_move_key(3, shift_key, alt_key, ctrl_key, meta_key); break; } case Qt::Key_5: case Qt::Key_Clear: { do_cmd_hold(); break; } case Qt::Key_A: { if (alt_key) do_cmd_wizard_mode(); else if (shift_key) do_cmd_activate(); else if (!using_mods) do_cmd_aim_wand(); break; } case Qt::Key_B: { if (shift_key) do_cmd_bash(DIR_UNKNOWN); else if (!using_mods) do_cmd_browse(-1); break; } case Qt::Key_C: { if (shift_key && alt_key) save_character_file(); else if (shift_key) do_cmd_character_screen(); else if (!using_mods) do_cmd_close(DIR_UNKNOWN); break; } case Qt::Key_D: { if (shift_key) do_cmd_disarm(DIR_UNKNOWN); else if (!using_mods) do_cmd_drop(); break; } case Qt::Key_E: { if (shift_key) do_cmd_eat_food(); else if (!using_mods) do_cmd_all_objects(TAB_EQUIP); break; } case Qt::Key_F: { if (ctrl_key) do_cmd_feeling(); else if (shift_key) do_cmd_refuel(); else if (!using_mods) do_cmd_fire(); break; } case Qt::Key_G: { if (shift_key) do_cmd_study(-1); else if (!using_mods) do_cmd_pickup_from_pile(FALSE, TRUE); break; } case Qt::Key_H: { if (!using_mods) do_cmd_fire_at_nearest(); break; } case Qt::Key_I: { if (shift_key) do_cmd_examine(); else if (!using_mods) do_cmd_all_objects(TAB_INVEN); break; } case Qt::Key_J: { if (!using_mods) do_cmd_spike(DIR_UNKNOWN); break; } case Qt::Key_K: { if (!using_mods) do_cmd_destroy(); break; } case Qt::Key_L: { if (shift_key) ui_center(p_ptr->py, p_ptr->px); else if (!using_mods) do_cmd_look(); break; } case Qt::Key_M: { if (shift_key) break; // TODO - MAP else if (!using_mods) do_cmd_cast(-1); break; } case Qt::Key_N: case Qt::Key_0: case Qt::Key_Insert: { if (!using_mods) do_cmd_repeat(); break; } case Qt::Key_O: { if (shift_key) do_cmd_make_trap(DIR_UNKNOWN); else if (!using_mods) do_cmd_open(DIR_UNKNOWN); break; } case Qt::Key_P: { if (ctrl_key) display_message_log(); else if (!using_mods) do_cmd_cast(-1); break; } case Qt::Key_Q: { if (alt_key) do_cmd_quest_desc(); else if (shift_key) do_cmd_suicide(); else if (!using_mods) do_cmd_quaff_potion(); break; } case Qt::Key_R: { if (ctrl_key) ui_redraw_all(); else if (shift_key) do_cmd_rest(); else if (!using_mods) do_cmd_read_scroll(); break; } case Qt::Key_S: { if (shift_key) do_cmd_toggle_search(); else if (!using_mods) do_cmd_search(); break; } case Qt::Key_T: { if (shift_key) do_cmd_tunnel(DIR_UNKNOWN); else if (!using_mods) do_cmd_takeoff(); break; } case Qt::Key_U: { if (!using_mods) do_cmd_use_staff(); break; } case Qt::Key_V: { if (!using_mods) do_cmd_throw(); break; } case Qt::Key_W: { if (!using_mods) do_cmd_wield(); break; } case Qt::Key_X: { if (!using_mods) do_cmd_swap_weapon(); break; } case Qt::Key_Y: { break; } case Qt::Key_Z: { if (!using_mods) do_cmd_zap_rod(); break; } case Qt::Key_Apostrophe: case Qt::Key_Asterisk: { target_set_closest(TARGET_KILL); break; } case Qt::Key_BraceLeft: { do_cmd_inscribe(); break; } case Qt::Key_BraceRight: { do_cmd_uninscribe(); break; } case Qt::Key_Greater: { do_cmd_go_down(); break; } case Qt::Key_Less: { do_cmd_go_up(); break; } case Qt::Key_Period: { do_cmd_run(DIR_UNKNOWN); break; } case Qt::Key_Plus: { do_cmd_alter(DIR_UNKNOWN); break; } case Qt::Key_Minus: { do_cmd_walk(DIR_UNKNOWN, TRUE); break; } case Qt::Key_Underscore: case Qt::Key_Comma: { do_cmd_hold(); break; } case Qt::Key_Semicolon: { do_cmd_walk(DIR_UNKNOWN, FALSE); break; } case Qt::Key_Colon: { do_cmd_write_note(); break; } case Qt::Key_ParenRight: { save_screenshot(FALSE); break; } case Qt::Key_ParenLeft: { save_screenshot(TRUE); break; } case Qt::Key_AsciiTilde: { do_cmd_knowledge_screens(); break; } default: { break; } } }
/* * Handle "target" and "look". * * Note that this code can be called from "get_aim_dir()". * * Currently, when "flag" is true, that is, when * "interesting" grids are being used, and a directional key is used, we * only scroll by a single panel, in the direction requested, and check * for any interesting grids on that panel. The "correct" solution would * actually involve scanning a larger set of grids, including ones in * panels which are adjacent to the one currently scanned, but this is * overkill for this function. XXX XXX * * Hack -- targeting/observing an "outer border grid" may induce * problems, so this is not currently allowed. * * The player can use the direction keys to move among "interesting" * grids in a heuristic manner, or the "space", "+", and "-" keys to * move through the "interesting" grids in a sequential manner, or * can enter "location" mode, and use the direction keys to move one * grid at a time in any direction. The "t" (set target) command will * only target a monster (as opposed to a location) if the monster is * target_able and the "interesting" mode is being used. * * The current grid is described using the "look" method above, and * a new command may be entered at any time, but note that if the * "TARGET_LOOK" bit flag is set (or if we are in "location" mode, * where "space" has no obvious meaning) then "space" will scan * through the description of the current grid until done, instead * of immediately jumping to the next "interesting" grid. This * allows the "target" command to retain its old semantics. * * The "*", "+", and "-" keys may always be used to jump immediately * to the next (or previous) interesting grid, in the proper mode. * * The "return" key may always be used to scan through a complete * grid description (forever). * * This command will cancel any old target, even if used from * inside the "look" command. * * 'mode' is one of TARGET_LOOK or TARGET_KILL. * 'x' and 'y' are the initial position of the target to be highlighted, * or -1 if no location is specified. * Returns TRUE if a target has been successfully set, FALSE otherwise. */ bool target_set_interactive(int mode, int x, int y) { int py = p_ptr->py; int px = p_ptr->px; int i, d, target_count; bool done = FALSE; bool interactive = TRUE; u16b path_n; u16b path_g[PATH_SIZE]; u16b path_gx[PATH_SIZE]; /* Cancel target */ target_set_monster(0, FALSE); /* All grids are selectable */ if (mode & (TARGET_GRID)) { /* Disable other modes */ mode &= ~(TARGET_LOOK | TARGET_KILL | TARGET_TRAP); /* Disable interesting grids */ interactive = FALSE; } /* Prepare the "temp" array */ target_set_interactive_prepare(mode); /* If we haven't been given an initial location, start on the player. */ if ((x == -1 || y == -1) && target_grids.size()) { x = p_ptr->px; y = p_ptr->py; ui_targeting_show(MODE_TARGETING_INTERACTIVE); ui_update_message_label(color_string("Interactive Target Mode", TERM_L_RED)); } /* * If we /have/ been given an initial location, make sure we * honour it by going into "free targeting" mode. */ else { if (x == -1 || y == -1) { x = p_ptr->px; y = p_ptr->py; } interactive = FALSE; ui_targeting_show(MODE_TARGETING_MANUAL); ui_update_message_label(color_string("Manual Target Mode", TERM_L_RED)); } /* Start near the player */ target_count = 0; /* Interact */ while (!done) { /* Interesting grids */ if (interactive && target_grids.size()) { bool path_drawn = FALSE; int yy, xx; y = target_grids[target_count].y; x = target_grids[target_count].x; /* Dummy pointers to send to project_path */ yy = y; xx = x; /* Adjust panel if needed */ ui_ensure(y, x); /* Find the path. */ path_n = project_path(path_g, path_gx, MAX_RANGE, py, px, &yy, &xx, PROJECT_THRU); /* Draw the path in "target" mode. If there is one */ if ((mode & (TARGET_KILL)) && (dungeon_info[y][x].projectable())) { path_drawn = ui_draw_path(path_n, path_g, y, x); } ui_show_cursor(y, x); /* Describe and Prompt */ describe_grid_brief(y, x); UserInput input = ui_get_input(); /* Remove the path */ if (path_drawn) ui_destroy_path(); ui_show_cursor(-1, -1); /* Assume no "direction" */ d = 0; // Use the mouse wheel to go through targets if (input.mode == INPUT_MODE_MOUSE_WHEEL) { if (input.key == Qt::Key_Plus) { if (++target_count == target_grids.size()) target_count = 0; } else if (input.key == Qt::Key_Minus) { if (target_count-- == 0) target_count = target_grids.size() - 1; } continue; } // double-click - automatically target if appropriate if (input.mode == INPUT_MODE_MOUSE_DOUBLE_CLICK) { if (!set_selected_target(mode, y, x)) { target_set_location(y, x); } done = TRUE; continue; } /* * If we click, move the target location to the click and * switch to "free targeting" mode by unsetting 'flag'. * This means we get some info about wherever we've picked. */ if (input.mode == INPUT_MODE_MOUSE_SINGLE_CLICK) { // If clicking twice on the same square, accept if (input.x == x && input.y == y) { if (set_selected_target(mode, y, x)) done = TRUE; continue; } x = input.x; y = input.y; ui_update_message_label(color_string("Interactive Target Mode", TERM_L_RED)); ui_targeting_show(MODE_TARGETING_MANUAL); interactive = FALSE; continue; } /* Analyze */ switch (input.key) { case Qt::Key_Escape: case Qt::Key_X: { done = TRUE; break; } case Qt::Key_C: case Qt::Key_Comma: { /* Set to closest target */ if (target_set_closest(TARGET_KILL)) done = TRUE; break; } case Qt::Key_Space: case Qt::Key_Plus: { if (++target_count == target_grids.size()) target_count = 0; break; } case Qt::Key_Minus: { if (target_count-- == 0) target_count = target_grids.size() - 1; break; } case Qt::Key_Exclam: case Qt::Key_L: { GridDialog(y, x); break; } case Qt::Key_Asterisk: case Qt::Key_M: { ui_update_message_label(color_string("Manual Target Mode", TERM_L_RED)); ui_targeting_show(MODE_TARGETING_MANUAL); interactive = FALSE; break; } case Qt::Key_Question: { do_cmd_list_targeting_commands(); break; } case Qt::Key_H: case Qt::Key_5: case Qt::Key_Period: case Qt::Key_Clear: { if (set_selected_target(mode, y, x)) done = TRUE; break; } default: { /* Extract direction */ d = target_dir(input); /* Oops */ if (!d) message("Illegal command for target mode!"); break; } } /* Hack -- move around */ if (d) { int old_y = target_grids[target_count].y; int old_x = target_grids[target_count].x; /* Find a new monster */ i = target_pick(old_y, old_x, ddy[d], ddx[d]); /* Scroll to find interesting grid */ if (i < 0) { QRect vis = visible_dungeon(); int old_wy = vis.y(); int old_wx = vis.x(); /* Change if legal */ if (ui_change_panel(d)) { /* Recalculate interesting grids */ target_set_interactive_prepare(mode); /* Find a new monster */ i = target_pick(old_y, old_x, ddy[d], ddx[d]); /* Restore panel if needed */ if ((i < 0) && ui_modify_panel(old_wy, old_wx)) { /* Recalculate interesting grids */ target_set_interactive_prepare(mode); } } } /* Use interesting grid if found */ if (i >= 0) target_count = i; } } /* Arbitrary grids */ else { bool path_drawn = FALSE; /* Dummy pointers to send to project_path */ int yy = y; int xx = x; /* Find the path. */ path_n = project_path(path_g, path_gx, MAX_RANGE, py, px, &yy, &xx, PROJECT_THRU); /* Draw the path in "target" mode. If there is one */ if ((mode & (TARGET_KILL)) && (dungeon_info[y][x].projectable())) { /* Save target info */ path_drawn = ui_draw_path(path_n, path_g, y, x); } describe_grid_brief(y, x); ui_show_cursor(y, x); UserInput input = ui_get_input(); /* Remove the path */ if (path_drawn) ui_destroy_path(); ui_show_cursor(y, x); /* Assume no direction */ d = 0; if (input.mode == INPUT_MODE_MOUSE_WHEEL) continue; // double-click - automatically target if appropriate if (input.mode == INPUT_MODE_MOUSE_DOUBLE_CLICK) { if (set_selected_target(mode, y, x)) done = TRUE; else { message(QString("Illegal target!")); } break; } if (input.mode == INPUT_MODE_MOUSE_SINGLE_CLICK) { /* We only target if we click somewhere where the cursor is already (i.e. a double-click without a time limit) */ if (input.x == x && input.y == y) { target_set_location(y, x); done = TRUE; } else { /* Just move the cursor for now - another click will target. */ x = input.x; y = input.y; } continue; } /* Analyze the keypress */ switch (input.key) { case Qt::Key_Escape: case Qt::Key_X: { done = TRUE; continue; } case Qt::Key_Asterisk: case Qt::Key_M: { if (((mode & (TARGET_GRID)) != TARGET_GRID) && target_grids.size()) { ui_update_message_label(color_string("Interactive Target Mode", TERM_L_RED)); ui_targeting_show(MODE_TARGETING_INTERACTIVE); interactive = TRUE; } break; } case Qt::Key_copyright: case Qt::Key_C: case Qt::Key_Comma: { /* Set to closest target */ if (target_set_closest(TARGET_KILL)) done = TRUE; break; } case Qt::Key_Exclam: case Qt::Key_L: { GridDialog(y, x); break; } case Qt::Key_Ampersand: case Qt::Key_P: { /* Recenter around player */ ui_center(py, px); y = py; x = px; break; } case Qt::Key_H: case Qt::Key_5: case Qt::Key_Period: case Qt::Key_Clear: { target_set_location(y, x); done = TRUE; break; } case Qt::Key_Question: { do_cmd_list_targeting_commands(); break; } default: { /* Extract a direction */ d = target_dir(input); /* Oops */ if (!d) message("Illegal command for target mode!"); break; } } /* Handle "direction" */ if (d) { int dungeon_hgt = p_ptr->cur_map_hgt; int dungeon_wid = p_ptr->cur_map_wid; /* Move */ x += ddx[d]; y += ddy[d]; /* Slide into legality */ if (x >= dungeon_wid - 1) x--; else if (x <= 0) x++; /* Slide into legality */ if (y >= dungeon_hgt - 1) y--; else if (y <= 0) y++; /* Adjust panel if needed */ if (ui_adjust_panel(y, x)) { /* Recalculate interesting grids */ target_set_interactive_prepare(mode); } } } } /* Forget */ target_grids.clear(); ui_targeting_hide(); /* Recenter around player */ ui_ensure(py, px); /* Failure to set target */ if (!p_ptr->target_set) return (FALSE); /* Success */ return (TRUE); }
/* * Get an "aiming direction" (1,2,3,4,6,7,8,9 or 5) from the user. * * Return TRUE if a direction was chosen, otherwise return FALSE. * * The direction "5" is special, and means "use current target". Also DIR_TARGET * * This function tracks and uses the "global direction", and uses * that as the "desired direction", if it is set. * * Note that "Force Target", if set, will pre-empt user interaction, * if there is a usable target already set. * * Currently this function applies confusion directly. */ bool get_aim_dir(int *dp, bool target_trap) { /* Global direction */ int dir = 0; int old_dir; bool done = FALSE; int mode = TARGET_QUIET; if (target_trap) mode |= TARGET_TRAP; else mode |= TARGET_KILL; if (*dp == DIR_CLOSEST) { if (target_set_closest(mode)) { return(TRUE); } } /* Initialize */ (*dp) = 0; /* Hack -- auto-target if requested */ if (use_old_target && target_okay() && !dir) dir = DIR_TARGET; else ui_update_message_label(color_string("Please select a target.", TERM_L_RED)); ui_targeting_show(MODE_TARGETING_AIMING); /* Ask until satisfied */ while (!dir && !done) { ui_show_cursor(p_ptr->py, p_ptr->px); /* Get a command (or Cancel) */ UserInput input = ui_get_input(); // Paranoia if (input.mode == INPUT_MODE_NONE) break; if ((input.key == Qt::Key_Escape) || (input.key == Qt::Key_X)) { break; } // Do nothing if (input.mode == INPUT_MODE_MOUSE_WHEEL) { continue; } // Skip interactive mode and directly choose target. if (input.mode == INPUT_MODE_MOUSE_DOUBLE_CLICK) { if (set_selected_target(mode, input.y, input.x)) dir = DIR_TARGET; else if (set_selected_target(TARGET_GRID, input.y, input.x)) dir = DIR_TARGET; continue; } if (input.mode == INPUT_MODE_MOUSE_SINGLE_CLICK) { /* Calculate approximate angle */ if (target_set_interactive(mode, input.x, input.y)) dir = DIR_TARGET; else done = TRUE; continue; } /* Analyze */ switch (input.key) { case Qt::Key_M: case Qt::Key_Asterisk: { /* Set new target, use target if legal */ int mode = TARGET_KILL; if (target_trap) mode |= TARGET_TRAP; if (target_set_interactive(mode, -1, -1)) dir = DIR_TARGET; else done = TRUE; continue; } case Qt::Key_C: case Qt::Key_Comma: { /* Set to closest target */ if (target_set_closest(TARGET_KILL)) { dir = DIR_CLOSEST; continue; } break; } case Qt::Key_Question: { do_cmd_list_targeting_commands(); continue; } case Qt::Key_H: case Qt::Key_5: case Qt::Key_Period: case Qt::Key_Clear: { /* Use current target, if set and legal */ if (target_okay()) dir = DIR_TARGET; break; } default: { /* Possible direction */ dir = target_dir(input); break; } } /* Error */ if (!dir) color_message("Illegal aim direction!", TERM_ORANGE); } ui_targeting_hide(); ui_show_cursor(-1, -1); ui_clear_message_label(); /* No direction */ if (!dir) return (FALSE); /* Save the direction */ old_dir = dir; /* Check for confusion */ if (p_ptr->timed[TMD_CONFUSED]) { /* Random direction */ dir = ddd[randint0(8)]; } /* Notice confusion */ if (old_dir != dir) { /* Warn the user */ message(QString("You are confused.")); } /* Save direction */ (*dp) = dir; /* A "valid" direction was entered */ return (TRUE); }
/** * Get an "aiming direction" (1,2,3,4,6,7,8,9 or 5) from the user. * * Return true if a direction was chosen, otherwise return false. * * The direction "5" is special, and means "use current target". * * This function tracks and uses the "global direction", and uses * that as the "desired direction", if it is set. * * Note that "Force Target", if set, will pre-empt user interaction, * if there is a usable target already set. */ bool textui_get_aim_dir(int *dp) { /* Global direction */ int dir = 0; ui_event ke; const char *p; /* Initialize */ (*dp) = 0; /* Hack -- auto-target if requested */ if (OPT(use_old_target) && target_okay() && !dir) dir = 5; /* Ask until satisfied */ while (!dir) { /* Choose a prompt */ if (!target_okay()) p = "Direction ('*' or <click> to target, \"'\" for closest, Escape to cancel)? "; else p = "Direction ('5' for target, '*' or <click> to re-target, Escape to cancel)? "; /* Get a command (or Cancel) */ if (!get_com_ex(p, &ke)) break; if (ke.type == EVT_MOUSE) { if (ke.mouse.button == 1) { if (target_set_interactive(TARGET_KILL, KEY_GRID_X(ke), KEY_GRID_Y(ke))) dir = 5; } else if (ke.mouse.button == 2) { break; } } else if (ke.type == EVT_KBRD) { if (ke.key.code == '*') { /* Set new target, use target if legal */ if (target_set_interactive(TARGET_KILL, -1, -1)) dir = 5; } else if (ke.key.code == '\'') { /* Set to closest target */ if (target_set_closest(TARGET_KILL)) dir = 5; } else if (ke.key.code == 't' || ke.key.code == '5' || ke.key.code == '0' || ke.key.code == '.') { if (target_okay()) dir = 5; } else { /* Possible direction */ int keypresses_handled = 0; while (ke.key.code != 0) { int this_dir; /* XXX Ideally show and move the cursor here to indicate * the currently "Pending" direction. XXX */ this_dir = target_dir(ke.key); if (this_dir) dir = dir_transitions[dir][this_dir]; else break; if (op_ptr->lazymove_delay == 0 || ++keypresses_handled > 1) break; /* See if there's a second keypress within the defined * period of time. */ inkey_scan = op_ptr->lazymove_delay; ke = inkey_ex(); } } } /* Error */ if (!dir) bell("Illegal aim direction!"); } /* No direction */ if (!dir) return (false); /* Save direction */ (*dp) = dir; /* A "valid" direction was entered */ return (true); }
void do_cmd_target_closest(void) { target_set_closest(TARGET_KILL); }