/* * Request a game command from the uI and carry out whatever actions * go along with it. */ void process_command(cmd_context ctx, bool no_request) { int idx; game_command cmd; /* If we've got a command to process, do it. */ if (cmd_get(ctx, &cmd, !no_request) == 0) { idx = cmd_idx(cmd.command); if (idx == -1) return; /* Do some sanity checking on those arguments that might have been declared as "unknown", such as directions and targets. */ switch (cmd.command) { case CMD_WALK: case CMD_RUN: case CMD_JUMP: case CMD_OPEN: case CMD_CLOSE: case CMD_TUNNEL: case CMD_DISARM: case CMD_BASH: case CMD_ALTER: case CMD_JAM: case CMD_MAKE_TRAP: { /* Direction hasn't been specified, so we ask for one. */ if (cmd.args[0].direction == DIR_UNKNOWN) { if (!get_rep_dir(&cmd.args[0].direction)) return; } break; } /* * These take an item number and a "target" as arguments, * though a target isn't always actually needed, so we'll * only prompt for it via callback if the item being used needs it. */ case CMD_USE_WAND: case CMD_USE_ROD: case CMD_QUAFF: case CMD_ACTIVATE: case CMD_READ_SCROLL: case CMD_FIRE: case CMD_THROW: case CMD_STEAL: { bool get_target = FALSE; if (cmd.command == CMD_FIRE || cmd.command == CMD_THROW || obj_needs_aim(object_from_item_idx(cmd.args[0].choice))) { if (cmd.args[1].direction == DIR_UNKNOWN) get_target = TRUE; if (cmd.args[1].direction == DIR_TARGET && !target_okay()) get_target = TRUE; } if (get_target && !get_aim_dir(&cmd.args[1].direction, FALSE)) return; break; } /* This takes a choice and a direction. */ case CMD_CAST: { bool get_target = FALSE; if (spell_needs_aim(cp_ptr->spell_book, cmd.args[0].choice)) { if (cmd.args[1].direction == DIR_UNKNOWN) get_target = TRUE; if (cmd.args[1].direction == DIR_TARGET && !target_okay()) get_target = TRUE; } if (get_target && !get_aim_dir(&cmd.args[1].direction, FALSE)) return; break; } default: { /* I can see the point of the compiler warning, but still... */ break; } } /* Command repetition */ if (game_cmds[idx].repeat_allowed) { /* Auto-repeat */ if (game_cmds[idx].auto_repeat_n > 0 && p_ptr->command_arg == 0 && p_ptr->command_rep == 0) p_ptr->command_arg = game_cmds[idx].auto_repeat_n; allow_repeated_command(); } repeat_prev_allowed = TRUE; if (game_cmds[idx].fn) game_cmds[idx].fn(cmd.command, cmd.args); } }
// 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); }