/* pick the context menu options appropiate for the item */ int context_menu_object(const object_type *o_ptr) { menu_type *m; rect_region r; int selected; int location = 0; char *labels; char header[120]; s16b *list; m = menu_dynamic_new(); if (!m || !o_ptr) { return 0; } object_desc(header, o_ptr, TRUE, 2, sizeof(header)); list = look_up_list((object_type*)o_ptr); if (list) { if (list == &(p_ptr->inventory)) { location = USE_INVEN; } else if (list == &(area(p_ptr->px, p_ptr->py)->o_idx)) { location = USE_FLOOR; } else { /* check if in a container */ location = USE_INVEN; } } else if (GET_ARRAY_INDEX(p_ptr->equipment, o_ptr) >= EQUIP_WIELD) { location = USE_EQUIP; } labels = (char*)string_make(lower_case); m->selections = labels; menu_dynamic_add_label(m, "Inspect", 'I', 1, labels); if (item_tester_hook_is_book(o_ptr)) { if (player_can_cast_from(o_ptr)) { if (player_can_cast()) { menu_dynamic_add_label(m, "Cast", 'm', 8, labels); } else { menu_dynamic_add_label(m, "$Cast", 'm', 8, labels); } if (player_can_study()) { menu_dynamic_add_label(m, "Study", 'G', 10, labels); } else { menu_dynamic_add_label(m, "$Study", 'G', 10, labels); } } if (player_is_caster() && player_can_read()) { menu_dynamic_add_label(m, "Browse", 'b', 9, labels); } } else if (item_tester_hook_useable(o_ptr)) { if (obj_is_wand(o_ptr)) { if (obj_has_charges(o_ptr)) { menu_dynamic_add_label(m, "Aim", 'a', 8, labels); } else { menu_dynamic_add_label(m, "$Aim", 'a', 8, labels); } } else if (obj_is_rod(o_ptr)) { if (obj_can_zap(o_ptr)) { menu_dynamic_add_label(m, "Zap", 'z', 8, labels); } else { menu_dynamic_add_label(m, "$Zap", 'z', 8, labels); } } else if (obj_is_staff(o_ptr)) { if (obj_has_charges(o_ptr)) { menu_dynamic_add_label(m, "Use", 'u', 8, labels); } else { menu_dynamic_add_label(m, "$Use", 'u', 8, labels); } } else if (obj_is_scroll(o_ptr)) { if (player_can_read()) { menu_dynamic_add_label(m, "Read", 'r', 8, labels); } else { menu_dynamic_add_label(m, "$Read", 'r', 8, labels); } } else if (obj_is_potion(o_ptr)) { menu_dynamic_add_label(m, "Quaff", 'q', 8, labels); } else if (obj_is_food(o_ptr)) { menu_dynamic_add_label(m, "Eat", 'E', 8, labels); } else if (item_tester_hook_activate(o_ptr)) { if (obj_is_activatable(o_ptr)) { menu_dynamic_add_label(m, "Activate", 'A', 8, labels); } else { menu_dynamic_add_label(m, "$Activate", 'A', 8, labels); } } else { menu_dynamic_add_label(m, "Use", 'U', 8, labels); } } else if (item_tester_hook_ammo(o_ptr)) { if (obj_can_fire(o_ptr)) { menu_dynamic_add_label(m, "Fire", 'f', 15, labels); } else { menu_dynamic_add_label(m, "$Fire", 'f', 15, labels); } } if (obj_can_refill(o_ptr)) { menu_dynamic_add_label(m, "Refill", 'F', 11, labels); } if (item_tester_hook_wear(o_ptr)) { if (location == USE_EQUIP) { menu_dynamic_add_label(m, "Take off", 't', 3, labels); } else if (location == USE_INVEN) { if (item_tester_hook_armour(o_ptr)) { menu_dynamic_add_label(m, "Wear", 'w', 2, labels); } else { menu_dynamic_add_label(m, "Wield", 'w', 2, labels); } /*menu_dynamic_add_label(m, "Equip", 'w', 2, labels);*/ } } if ((location == USE_INVEN) || (location == USE_EQUIP)) { menu_dynamic_add_label(m, "Drop", 'd', 6, labels); if (o_ptr->number > 1) { menu_dynamic_add_label(m, "Drop All", 'd', 13, labels); } } else if (location == USE_FLOOR) { if (inven_carry_okay(o_ptr)) { menu_dynamic_add_label(m, "Pickup", 'g', 7, labels); } else { menu_dynamic_add_label(m, "$Pickup", 'g', 7, labels); } } menu_dynamic_add_label(m, "Throw", 'v', 12, labels); /*if (obj_has_inscrip(o_ptr)) {*/ if (o_ptr->inscription) { menu_dynamic_add_label(m, "Uninscribe", '}', 5, labels); } else { menu_dynamic_add_label(m, "Inscribe", '{', 4, labels); } menu_dynamic_add_label(m, "Destroy", 'k', 14, labels); #if 0 if (object_is_squelched(o_ptr)) { menu_dynamic_add_label(m, "Unignore", 'k', 14, labels); } else { menu_dynamic_add_label(m, "Ignore", 'k', 14, labels); } #endif /* work out display region */ r.width = menu_dynamic_longest_entry(m) + 3 + 2; /* +3 for tag, 2 for pad */ r.col = Term->wid - r.width - 1; r.row = 1; r.page_rows = m->count; /* Hack -- no flush needed */ msg_flag = FALSE; screen_save(); button_backup_all(TRUE); /* Recall object */ roff_set_width(r.col); roff_obj_aux(o_ptr); roff_set_width(0); menu_layout(m, &r); rect_region_erase_bordered(&r); prtf(0, 0, "($UEnter to select$Y\n$V, $UESC$Y%c$V) Command for %s:", ESCAPE, header); selected = menu_dynamic_select(m); menu_dynamic_free(m); string_free(labels); button_restore(); screen_load(); if (selected == 1) { /* inspect it */ identify_fully_aux(o_ptr); return 2; } else if (selected == 2) { /* wield the item */ set_get_item_object(o_ptr); p_ptr->cmd.cmd = 'w'; do_cmd_wield(); /*cmd_insert(CMD_WIELD); cmd_set_arg_item(cmd_get_top(), 0, slot);*/ } else if (selected == 3) { /* take the item off */ set_get_item_object(o_ptr); p_ptr->cmd.cmd = 't'; do_cmd_takeoff(); /*cmd_insert(CMD_TAKEOFF); cmd_set_arg_item(cmd_get_top(), 0, slot);*/ } else if (selected == 4) { /* inscribe the item */ set_get_item_object(o_ptr); p_ptr->cmd.cmd = '{'; do_cmd_inscribe(); /*cmd_insert(CMD_INSCRIBE); cmd_set_arg_item(cmd_get_top(), 0, slot);*/ } else if (selected == 5) { /* uninscribe the item */ set_get_item_object(o_ptr); p_ptr->cmd.cmd = '}'; do_cmd_uninscribe(); /*cmd_insert(CMD_UNINSCRIBE); cmd_set_arg_item(cmd_get_top(), 0, slot);*/ } else if (selected == 6) { /* drop the item */ set_get_item_object(o_ptr); p_ptr->cmd.cmd = 'd'; do_cmd_drop(); /*cmd_insert(CMD_DROP); cmd_set_arg_item(cmd_get_top(), 0, slot);*/ } else if (selected == 7) { /* pick the item up */ p_ptr->cmd.cmd = 'g'; if (inven_carry_okay(o_ptr)) { py_pickup_aux((object_type*)o_ptr); } else { carry(TRUE); } /*cmd_insert(CMD_PICKUP); cmd_set_arg_item(cmd_get_top(), 0, slot);*/ } else if (selected == 8) { /* use the item */ bool full = item_tester_full; item_tester_full = FALSE; if (player_can_cast_from(o_ptr)) { set_get_item_object(o_ptr); p_ptr->cmd.cmd = 'm'; do_cmd_cast(); } else { set_get_item_object(o_ptr); p_ptr->cmd.cmd = 'u'; repeat_check(); do_cmd_use(); /*cmd_insert(CMD_USE_ANY); cmd_set_arg_item(cmd_get_top(), 0, slot);*/ } item_tester_full = full; } else if (selected == 9) { /* browse a spellbook */ p_ptr->cmd.cmd = 'b'; do_cmd_browse_aux(o_ptr); /* copied from textui_spell_browse */ /*textui_book_browse(o_ptr);*/ return 2; } else if (selected == 10) { /* study a spell book */ p_ptr->cmd.cmd = 'G'; do_cmd_study(FALSE, (object_type*)o_ptr); } else if (selected == 11) { /* use the item to refill a light source */ set_get_item_object(o_ptr); p_ptr->cmd.cmd = 'F'; do_cmd_refill(); /*cmd_insert(CMD_REFILL); cmd_set_arg_item(cmd_get_top(), 0, slot);*/ } else if (selected == 12) { /* throw the item */ set_get_item_object(o_ptr); p_ptr->cmd.cmd = 'v'; repeat_check(); do_cmd_throw(); /*cmd_insert(CMD_THROW); cmd_set_arg_item(cmd_get_top(), 0, slot);*/ } else if (selected == 13) { /* drop all of the item stack */ if (get_check(format("Drop %s? ", header))) { set_get_item_object(o_ptr); p_ptr->cmd.arg = o_ptr->number; p_ptr->cmd.cmd = 'd'; do_cmd_drop(); /*cmd_insert(CMD_DROP); cmd_set_arg_item(cmd_get_top(), 0, slot); cmd_set_arg_number(cmd_get_top(), 1, o_ptr->number);*/ } } else if (selected == 14) { /* squelch or unsquelch the item */ set_get_item_object(o_ptr); p_ptr->cmd.cmd = 'k'; do_cmd_destroy(); /*textui_cmd_destroy_menu(slot);*/ } else if (selected == 15) { /* fire some ammo */ set_get_item_object(o_ptr); p_ptr->cmd.cmd = 'f'; repeat_check(); do_cmd_fire(); } else if (selected == -1) { /* this menu was canceled, tell whatever called us to display its menu again */ return 3; } return 1; }
/* * Pick up objects and treasure on the floor. -LM- * * Called with pickup: * 0 to act according to the player's settings * 1 to quickly pickup single objects or present a menu for more * 2 to force a menu for any number of objects * * Scan the list of objects in that floor grid. Pick up gold automatically. * Pick up objects automatically until backpack space is full if * auto-pickup option is on, Otherwise, store objects on * floor in an array, and tally both how many there are and can be picked up. * * If not picking up anything, indicate objects on the floor. Show more * details if the "OPT(pickup_detail)" option is set. Do the same thing if we * don't have room for anything. * * [This paragraph is not true, intentional?] * If we are picking up objects automatically, and have room for at least * one, allow the "OPT(pickup_detail)" option to display information about objects * and prompt the player. Otherwise, automatically pick up a single object * or use a menu for more than one. * * Pick up multiple objects using Tim Baker's menu system. Recursively * call this function (forcing menus for any number of objects) until * objects are gone, backpack is full, or player is satisfied. * * We keep track of number of objects picked up to calculate time spent. * This tally is incremented even for automatic pickup, so we are careful * (in "dungeon.c" and elsewhere) to handle pickup as either a separate * automated move or a no-cost part of the stay still or 'g'et command. * * Note the lack of chance for the character to be disturbed by unmarked * objects. They are truly "unknown". */ byte py_pickup(int pickup) { int py = p_ptr->py; int px = p_ptr->px; s16b this_o_idx = 0; size_t floor_num = 0; int floor_list[MAX_FLOOR_STACK + 1]; size_t i; int can_pickup = 0; bool call_function_again = FALSE; bool domsg = TRUE; /* Objects picked up. Used to determine time cost of command. */ byte objs_picked_up = 0; /* Nothing else to pick up -- return */ if (!cave->o_idx[py][px]) return objs_picked_up; /* Tally objects that can be picked up.*/ floor_num = scan_floor(floor_list, N_ELEMENTS(floor_list), py, px, 0x03); for (i = 0; i < floor_num; i++) { can_pickup += inven_carry_okay(object_byid(floor_list[i])); } if (!can_pickup) { /* Can't pick up, but probably want to know what's there. */ event_signal(EVENT_SEEFLOOR); return objs_picked_up; } /* Use a menu interface for multiple objects, or pickup single objects */ if (pickup == 1) { if (floor_num > 1) pickup = 2; else this_o_idx = floor_list[0]; } /* Display a list if requested. */ if (pickup == 2) { const char *q, *s; int item; /* Restrict the choices */ item_tester_hook = inven_carry_okay; /* Get an object or exit. */ q = "Get which item?"; s = "You see nothing there."; if (!get_item(&item, q, s, CMD_PICKUP, USE_FLOOR)) return (objs_picked_up); this_o_idx = 0 - item; call_function_again = TRUE; /* With a list, we do not need explicit pickup messages */ domsg = FALSE; } /* Pick up object, if legal */ if (this_o_idx) { /* Pick up the object */ py_pickup_aux(this_o_idx, domsg); /* Indicate an object picked up. */ objs_picked_up = 1; } /* * If requested, call this function recursively. Count objects picked * up. Force the display of a menu in all cases. */ if (call_function_again) objs_picked_up += py_pickup(2); /* Indicate how many objects have been picked up. */ return (objs_picked_up); }
/* 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; }
int do_autopickup(void) { int py = p_ptr->py; int px = p_ptr->px; s16b this_o_idx, next_o_idx = 0; object_type *o_ptr; /* Objects picked up. Used to determine time cost of command. */ byte objs_picked_up = 0; size_t floor_num = 0; int floor_list[MAX_FLOOR_STACK + 1]; /* Nothing to pick up -- return */ if (!cave->o_idx[py][px]) return (0); /* Always pickup gold, effortlessly */ py_pickup_gold(); /* Scan the remaining objects */ for (this_o_idx = cave->o_idx[py][px]; this_o_idx; this_o_idx = next_o_idx) { /* Get the object and the next object */ o_ptr = object_byid(this_o_idx); next_o_idx = o_ptr->next_o_idx; /* Ignore all hidden objects and non-objects */ if (squelch_item_ok(o_ptr) || !o_ptr->kind) continue; /* XXX Hack -- Enforce limit */ if (floor_num >= N_ELEMENTS(floor_list)) break; /* Hack -- disturb */ disturb(p_ptr, 0, 0); /* Automatically pick up items into the backpack */ if (auto_pickup_okay(o_ptr)) { /* Pick up the object with message */ py_pickup_aux(this_o_idx, TRUE); objs_picked_up++; continue; } /* Tally objects and store them in an array. */ /* Remember this object index */ floor_list[floor_num] = this_o_idx; /* Count non-gold objects that remain on the floor. */ floor_num++; } return objs_picked_up; }
/** * Pick up objects and treasure on the floor, now also used for telekinesis. * * Called with pickup: * 0 to grab gold and describe non-gold objects. * 1 to pick up objects either with or without displaying a menu. * 2 to pick up objects, forcing a menu for multiple objects. * 3 to pick up objects, forcing a menu for any number of objects. * * Scan the list of objects in that floor grid. Pick up gold automatically. * Pick up objects automatically until pile or backpack space is full if * auto-pickup option is on, carry_query_floor option is not, and menus are * not forced (which the "get" command does). Otherwise, store objects on * floor in an array, and tally both how many there are and can be picked up. * * If the player is not picking up objects, describe a single object or * indicate the presence of a floor stack. If player is picking up objects, * name a single object, or indicate a stack of objects, that cannot go in * the backpack. * * Pick up a single object without menus, unless menus for single items are * forced. Confirm pickup if that option is on. * * Pick up multiple objects (unless using autopickup, no confirm) using Tim * Baker's menu system. Recursively call this function (forcing menus for any * number of objects) until objects are gone, backpack is full, or player is * satisfied. * * Keep track of number of objects picked up (to calculate time spent). */ byte py_pickup(int pickup, int y, int x) { s16b this_o_idx, next_o_idx = 0; char o_name[120]; object_type *o_ptr; /* Objects picked up. Used to determine time cost of command. */ byte objs_picked_up = 0; size_t floor_num = 0; int floor_list[MAX_FLOOR_STACK + 1], floor_o_idx = 0; int can_pickup = 0; bool call_function_again = FALSE; bool blind = ((p_ptr->timed[TMD_BLIND]) || (no_light())); bool msg = TRUE; bool telekinesis = (!(y == p_ptr->py) || !(x == p_ptr->px)); /* Nothing to pick up -- return */ if (!cave_o_idx[y][x]) return (0); /* Always pickup gold, effortlessly */ if (!telekinesis) py_pickup_gold(); /* Scan the pile of objects */ for (this_o_idx = cave_o_idx[y][x]; this_o_idx; this_o_idx = next_o_idx) { /* Access the object */ o_ptr = &o_list[this_o_idx]; /* Access the next object */ next_o_idx = o_ptr->next_o_idx; /* Ordinary pickup */ if (!telekinesis) { /* Ignore all hidden objects and non-objects */ if (squelch_hide_item(o_ptr) || !o_ptr->k_idx) continue; /* Hack -- disturb */ disturb(0, 0); /* Automatically pick up some items */ if (auto_pickup_okay(o_ptr)) { /* Pick up the object */ py_pickup_aux(this_o_idx, TRUE); objs_picked_up++; /* Check the next object */ continue; } } /* Tally objects and store them in an array. */ /* Remember this object index */ floor_list[floor_num] = this_o_idx; /* Count non-gold objects that remain on the floor. */ floor_num++; /* Tally objects that can be picked up.*/ if (inven_carry_okay(o_ptr)) can_pickup++; } /* There are no non-gold objects */ if (!floor_num) return (objs_picked_up); /* Get hold of the last floor index */ floor_o_idx = floor_list[floor_num - 1]; /* Mention the objects if player is not picking them up. */ if (pickup == 0 || !(can_pickup || telekinesis)) { const char *p = "see"; /* One object */ if (floor_num == 1) { if (!can_pickup) p = "have no room for"; else if (blind) p = "feel"; /* Get the object */ o_ptr = &o_list[floor_o_idx]; /* Describe the object. Less detail if blind. */ if (blind) object_desc(o_name, sizeof(o_name), o_ptr, ODESC_PREFIX | ODESC_BASE); else object_desc(o_name, sizeof(o_name), o_ptr, ODESC_PREFIX | ODESC_FULL); /* Message */ message_flush(); msg_format("You %s %s.", p, o_name); } else { /* Optionally, display more information about floor items */ if (OPT(pickup_detail)) { ui_event_data e; if (!can_pickup) p = "have no room for the following objects"; else if (blind) p = "feel something on the floor"; /* Scan all marked objects in the grid */ floor_num = scan_floor(floor_list, N_ELEMENTS(floor_list), y, x, 0x03); /* Save screen */ screen_save(); /* Display objects on the floor */ show_floor(floor_list, floor_num, (OLIST_WEIGHT)); /* Display prompt */ prt(format("You %s: ", p), 0, 0); /* Move cursor back to character, if needed */ if (OPT(highlight_player)) move_cursor_relative(p_ptr->py, p_ptr->px); /* Wait for it. Use key as next command. */ e = inkey_ex(); Term_event_push(&e); /* Restore screen */ screen_load(); } /* Show less detail */ else { message_flush(); if (!can_pickup) msg_print("You have no room for any of the items on the floor."); else msg_format("You %s a pile of %d items.", (blind ? "feel" : "see"), floor_num); } } /* Done */ return (objs_picked_up); } /* We can pick up objects. Menus are not requested (yet). */ if (pickup == 1) { /* Scan floor (again) */ floor_num = scan_floor(floor_list, N_ELEMENTS(floor_list), y, x, 0x03); /* Use a menu interface for multiple objects, or get single objects */ if (floor_num > 1) pickup = 2; else this_o_idx = floor_o_idx; } /* Display a list if requested. */ if (pickup == 2) { cptr q, s; int item; /* Get an object or exit. */ q = "Get which item?"; s = "You see nothing there."; /* Telekinesis */ if (telekinesis) { item_tester_hook = inven_carry_okay; if (!get_item(&item, q, s, CMD_PICKUP, USE_TARGET)) return (objs_picked_up); this_o_idx = 0 - item; } else { /* Restrict the choices */ item_tester_hook = inven_carry_okay; if (!get_item(&item, q, s, CMD_PICKUP, USE_FLOOR)) return (objs_picked_up); this_o_idx = 0 - item; call_function_again = TRUE; } /* With a list, we do not need explicit pickup messages */ msg = FALSE; } /* Pick up object, if legal */ if (this_o_idx) { /* Regular pickup or telekinesis with pack not full */ if (can_pickup) { /* Pick up the object */ py_pickup_aux(this_o_idx, msg); } /* Telekinesis with pack full */ else { /* Access the object */ o_ptr = &o_list[this_o_idx]; /* Drop it */ drop_near(o_ptr, -1, p_ptr->py, p_ptr->px, TRUE); /* Delete the old object */ delete_object_idx(this_o_idx); } } /* Indicate an object picked up. */ objs_picked_up = 1; /* If requested, call this function recursively. Count objects picked up. * Force the display of a menu in all cases. */ if (call_function_again) objs_picked_up += py_pickup(3, y, x); /* Indicate how many objects have been picked up. */ return (objs_picked_up); }