int context_menu_cave(struct cave *c, int y, int x, int adjacent, int mx, int my) { menu_type *m; region r; int selected; char *labels; bool allowed = TRUE; int mode = OPT(rogue_like_commands) ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG; unsigned char cmdkey; m = menu_dynamic_new(); if (!m) { return 0; } labels = string_make(lower_case); m->selections = labels; /* Looking has different keys, but we don't have a way to look them up (see cmd-process.c). */ cmdkey = (mode == KEYMAP_MODE_ORIG) ? 'l' : 'x'; menu_dynamic_add_label(m, "Look At", cmdkey, MENU_VALUE_LOOK, labels); if (c->m_idx[y][x]) { /* '/' is used for recall in both keymaps. */ menu_dynamic_add_label(m, "Recall Info", '/', MENU_VALUE_RECALL, labels); } ADD_LABEL("Use Item On", CMD_USE_ANY, MN_ROW_VALID); if (player_can_cast(p_ptr, FALSE)) { ADD_LABEL("Cast On", CMD_CAST, MN_ROW_VALID); } if (adjacent) { ADD_LABEL((c->m_idx[y][x]) ? "Attack" : "Alter", CMD_ALTER, MN_ROW_VALID); if (c->o_idx[y][x]) { s16b o_idx = chest_check(y,x, CHEST_ANY); if (o_idx) { object_type *o_ptr = object_byid(o_idx); if (!squelch_item_ok(o_ptr)) { if (object_is_known(o_ptr)) { if (is_locked_chest(o_ptr)) { ADD_LABEL("Disarm Chest", CMD_DISARM, MN_ROW_VALID); ADD_LABEL("Open Chest", CMD_OPEN, MN_ROW_VALID); } else { ADD_LABEL("Open Disarmed Chest", CMD_OPEN, MN_ROW_VALID); } } else { ADD_LABEL("Open Chest", CMD_OPEN, MN_ROW_VALID); } } } } if (cave_istrap(c, y, x)) { ADD_LABEL("Disarm", CMD_DISARM, MN_ROW_VALID); ADD_LABEL("Jump Onto", CMD_JUMP, MN_ROW_VALID); } if (cave_isopendoor(c, y, x)) { ADD_LABEL("Close", CMD_CLOSE, MN_ROW_VALID); } else if (cave_iscloseddoor(c, y, x)) { ADD_LABEL("Open", CMD_OPEN, MN_ROW_VALID); ADD_LABEL("Lock", CMD_DISARM, MN_ROW_VALID); } else if (cave_isdiggable(c, y, x)) { ADD_LABEL("Tunnel", CMD_TUNNEL, MN_ROW_VALID); } ADD_LABEL("Search", CMD_SEARCH, MN_ROW_VALID); ADD_LABEL("Walk Towards", CMD_WALK, MN_ROW_VALID); } else { /* ',' is used for squelch in rogue keymap, so we'll just swap letters. */ cmdkey = (mode == KEYMAP_MODE_ORIG) ? ',' : '.'; menu_dynamic_add_label(m, "Pathfind To", cmdkey, CMD_PATHFIND, labels); ADD_LABEL("Walk Towards", CMD_WALK, MN_ROW_VALID); ADD_LABEL("Run Towards", CMD_RUN, MN_ROW_VALID); } if (player_can_fire(p_ptr, FALSE)) { ADD_LABEL("Fire On", CMD_FIRE, MN_ROW_VALID); } ADD_LABEL("Throw To", CMD_THROW, MN_ROW_VALID); /* work out display region */ r.width = (int)menu_dynamic_longest_entry(m) + 3 + 2; /* +3 for tag, 2 for pad */ if (mx > Term->wid - r.width - 1) { r.col = Term->wid - r.width - 1; } else { r.col = mx + 1; } r.page_rows = m->count; if (my > Term->hgt - r.page_rows - 1) { if (my - r.page_rows - 1 <= 0) { /* menu has too many items, so put in upper right corner */ r.row = 1; r.col = Term->wid - r.width - 1; } else { r.row = Term->hgt - r.page_rows - 1; } } else { r.row = my + 1; } /* Hack -- no flush needed */ msg_flag = FALSE; screen_save(); menu_layout(m, &r); region_erase_bordered(&r); if (p_ptr->timed[TMD_IMAGE]) { prt("(Enter to select command, ESC to cancel) You see something strange:", 0, 0); } else if (c->m_idx[y][x]) { char m_name[80]; monster_type *m_ptr = cave_monster_at(c, y, x); /* Get the monster name ("a kobold") */ monster_desc(m_name, sizeof(m_name), m_ptr, MDESC_IND_VIS); prt(format("(Enter to select command, ESC to cancel) You see %s:", m_name), 0, 0); } else if (c->o_idx[y][x] && !squelch_item_ok(object_byid(c->o_idx[y][x]))) { char o_name[80]; /* Get the single object in the list */ object_type *o_ptr = object_byid(c->o_idx[y][x]); /* Obtain an object description */ object_desc(o_name, sizeof (o_name), o_ptr, ODESC_PREFIX | ODESC_FULL); prt(format("(Enter to select command, ESC to cancel) You see %s:", o_name), 0, 0); } else { /* Feature (apply mimic) */ const char *name = cave_apparent_name(c, p_ptr, y, x); /* Hack -- special introduction for store doors */ if (cave_isshop(cave, y, x)) { prt(format("(Enter to select command, ESC to cancel) You see the entrance to the %s:", name), 0, 0); } else { prt(format("(Enter to select command, ESC to cancel) You see %s %s:", (is_a_vowel(name[0])) ? "an" : "a", name), 0, 0); } } selected = menu_dynamic_select(m); menu_dynamic_free(m); string_free(labels); screen_load(); cmdkey = cmd_lookup_key(selected, mode); /* Check the command to see if it is allowed. */ switch (selected) { case -1: /* User cancelled the menu. */ return 3; case MENU_VALUE_LOOK: case MENU_VALUE_RECALL: case CMD_PATHFIND: allowed = TRUE; break; case CMD_SEARCH: case CMD_ALTER: case CMD_DISARM: case CMD_JUMP: case CMD_CLOSE: case CMD_OPEN: case CMD_TUNNEL: case CMD_WALK: case CMD_RUN: case CMD_CAST: case CMD_FIRE: case CMD_THROW: case CMD_USE_ANY: /* Only check for ^ inscriptions, since we don't have an object selected (if we need one). */ allowed = key_confirm_command(cmdkey); break; default: /* Invalid command; prevent anything from happening. */ bell("Invalid context menu command."); allowed = FALSE; break; } if (!allowed) return 1; /* Perform the command. */ switch (selected) { case MENU_VALUE_LOOK: /* look at the spot */ if (target_set_interactive(TARGET_LOOK, x, y)) { msg("Target Selected."); } break; case MENU_VALUE_RECALL: { /* recall monster Info */ monster_type *m_ptr = cave_monster_at(c, y, x); if (m_ptr) { monster_lore *lore = get_lore(m_ptr->race); lore_show_interactive(m_ptr->race, lore); } } break; case CMD_SEARCH: cmd_insert(selected); break; case CMD_PATHFIND: cmd_insert(selected); cmd_set_arg_point(cmd_get_top(), 0, x, y); break; case CMD_ALTER: case CMD_DISARM: case CMD_JUMP: case CMD_CLOSE: case CMD_OPEN: case CMD_TUNNEL: case CMD_WALK: case CMD_RUN: cmd_insert(selected); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(y,x)); break; case CMD_CAST: if (textui_obj_cast_ret() >= 0) { cmd_set_arg_target(cmd_get_top(), 1, DIR_TARGET); } break; case CMD_FIRE: case CMD_THROW: case CMD_USE_ANY: cmd_insert(selected); cmd_set_arg_target(cmd_get_top(), 1, DIR_TARGET); break; default: break; } return 1; }
/** * Handle a textui mouseclick. */ static void textui_process_click(ui_event e) { int x, y; if (!OPT(mouse_movement)) return; y = KEY_GRID_Y(e); x = KEY_GRID_X(e); /* Check for a valid location */ if (!cave_in_bounds_fully(cave, y, x)) return; /* XXX show context menu here */ if ((p_ptr->py == y) && (p_ptr->px == x)) { if (e.mouse.mods & KC_MOD_SHIFT) { /* shift-click - cast magic */ if (e.mouse.button == 1) { textui_obj_cast(); } else if (e.mouse.button == 2) { Term_keypress('i',0); } } else if (e.mouse.mods & KC_MOD_CONTROL) { /* ctrl-click - use feature / use inventory item */ /* switch with default */ if (e.mouse.button == 1) { if (cave_isupstairs(cave, p_ptr->py, p_ptr->px)) cmd_insert(CMD_GO_UP); else if (cave_isdownstairs(cave, p_ptr->py, p_ptr->px)) cmd_insert(CMD_GO_DOWN); } else if (e.mouse.button == 2) { cmd_insert(CMD_USE_UNAIMED); } } else if (e.mouse.mods & KC_MOD_ALT) { /* alt-click - Search or show char screen */ /* XXX call a platform specific hook */ if (e.mouse.button == 1) { cmd_insert(CMD_SEARCH); } else if (e.mouse.button == 2) { Term_keypress('C',0); } } else { if (e.mouse.button == 1) { if (cave->o_idx[y][x]) { cmd_insert(CMD_PICKUP); } else { cmd_insert(CMD_HOLD); } } else if (e.mouse.button == 2) { // show a context menu context_menu_player(e.mouse.x, e.mouse.y); } } } else if (e.mouse.button == 1) { if (p_ptr->timed[TMD_CONFUSED]) { cmd_insert(CMD_WALK); } else { if (e.mouse.mods & KC_MOD_SHIFT) { /* shift-click - run */ cmd_insert(CMD_RUN); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(y,x)); /*if ((y-p_ptr->py >= -1) && (y-p_ptr->py <= 1) && (x-p_ptr->px >= -1) && (x-p_ptr->px <= 1)) { cmd_insert(CMD_JUMP); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(y,x)); } else { cmd_insert(CMD_RUN); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(y,x)); }*/ } else if (e.mouse.mods & KC_MOD_CONTROL) { /* control-click - alter */ cmd_insert(CMD_ALTER); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(y,x)); } else if (e.mouse.mods & KC_MOD_ALT) { /* alt-click - look */ if (target_set_interactive(TARGET_LOOK, x, y)) { msg("Target Selected."); } //cmd_insert(CMD_LOOK); //cmd_set_arg_point(cmd_get_top(), 0, y, x); } else { /* pathfind does not work well on trap detection borders, * so if the click is next to the player, force a walk step */ if ((y-p_ptr->py >= -1) && (y-p_ptr->py <= 1) && (x-p_ptr->px >= -1) && (x-p_ptr->px <= 1)) { cmd_insert(CMD_WALK); cmd_set_arg_direction(cmd_get_top(), 0, coords_to_dir(y,x)); } else { cmd_insert(CMD_PATHFIND); cmd_set_arg_point(cmd_get_top(), 0, y, x); } } } } else if (e.mouse.button == 2) { struct monster *m = cave_monster_at(cave, y, x); if (m && target_able(m)) { /* Set up target information */ monster_race_track(m->race); health_track(p_ptr, m); target_set_monster(m); } else { target_set_location(y,x); } if (e.mouse.mods & KC_MOD_SHIFT) { /* shift-click - cast spell at target */ if (textui_obj_cast_ret() >= 0) { cmd_set_arg_target(cmd_get_top(), 1, DIR_TARGET); } } else if (e.mouse.mods & KC_MOD_CONTROL) { /* control-click - fire at target */ cmd_insert(CMD_USE_AIMED); cmd_set_arg_target(cmd_get_top(), 1, DIR_TARGET); } else if (e.mouse.mods & KC_MOD_ALT) { /* alt-click - throw at target */ cmd_insert(CMD_THROW); cmd_set_arg_target(cmd_get_top(), 1, DIR_TARGET); } else { //msg("Target set."); /* see if the click was adjacent to the player */ if ((y-p_ptr->py >= -1) && (y-p_ptr->py <= 1) && (x-p_ptr->px >= -1) && (x-p_ptr->px <= 1)) { context_menu_cave(cave,y,x,1,e.mouse.x, e.mouse.y); } else { context_menu_cave(cave,y,x,0,e.mouse.x, e.mouse.y); } } } }