/** * Describe an item's origin */ static bool describe_origin(textblock *tb, const struct object *obj, bool terse) { char loot_spot[80]; char name[80]; int origin; const char *dropper = NULL; const char *article; bool unique = false; /* Only give this info in chardumps if wieldable */ if (terse && !obj_can_wear(obj)) return false; /* Set the origin - care needed for mimics */ if ((obj->origin == ORIGIN_DROP_MIMIC) && (obj->mimicking_m_idx != 0)) origin = ORIGIN_FLOOR; else origin = obj->origin; /* Name the place of origin */ if (obj->origin_depth) strnfmt(loot_spot, sizeof(loot_spot), "at %d feet (level %d)", obj->origin_depth * 50, obj->origin_depth); else my_strcpy(loot_spot, "in town", sizeof(loot_spot)); /* Name the monster of origin */ if (obj->origin_race) { dropper = obj->origin_race->name; if (rf_has(obj->origin_race->flags, RF_UNIQUE)) { unique = true; } } else { dropper = "monster lost to history"; } article = is_a_vowel(dropper[0]) ? "an " : "a "; if (unique) my_strcpy(name, dropper, sizeof(name)); else { my_strcpy(name, article, sizeof(name)); my_strcat(name, dropper, sizeof(name)); } /* Print an appropriate description */ switch (origins[origin].args) { case -1: return false; case 0: textblock_append(tb, origins[origin].desc); break; case 1: textblock_append(tb, origins[origin].desc, loot_spot); break; case 2: textblock_append(tb, origins[origin].desc, name, loot_spot); break; } textblock_append(tb, "\n\n"); return true; }
/** * Describe an item's origin */ static bool describe_origin(textblock *tb, const struct object *obj, bool terse) { char loot_spot[80]; char name[80]; const char *droppee; const char *article; /* Only give this info in chardumps if wieldable */ if (terse && !obj_can_wear(obj)) return FALSE; /* Name the place of origin */ if (obj->origin_depth) strnfmt(loot_spot, sizeof(loot_spot), "at %d feet (level %d)", obj->origin_depth * 50, obj->origin_depth); else my_strcpy(loot_spot, "in town", sizeof(loot_spot)); /* Name the monster of origin */ if (r_info[obj->origin_xtra].ridx) droppee = r_info[obj->origin_xtra].name; else droppee = "monster lost to history"; article = is_a_vowel(droppee[0]) ? "an " : "a "; if (rf_has(r_info[obj->origin_xtra].flags, RF_UNIQUE)) my_strcpy(name, droppee, sizeof(name)); else { my_strcpy(name, article, sizeof(name)); my_strcat(name, droppee, sizeof(name)); } /* Print an appropriate description */ switch (origins[obj->origin].args) { case -1: return FALSE; case 0: textblock_append(tb, origins[obj->origin].desc); break; case 1: textblock_append(tb, origins[obj->origin].desc, loot_spot); break; case 2: textblock_append(tb, origins[obj->origin].desc, name, loot_spot); break; } textblock_append(tb, "\n\n"); return TRUE; }
/* pick the context menu options appropiate for the item */ int context_menu_object(const object_type *o_ptr, const int slot) { menu_type *m; region r; int selected; char *labels; char header[120]; textblock *tb; region area = { 0, 0, 0, 0 }; bool allowed = TRUE; int mode = OPT(rogue_like_commands) ? KEYMAP_MODE_ROGUE : KEYMAP_MODE_ORIG; unsigned char cmdkey; m = menu_dynamic_new(); if (!m || !o_ptr) { return 0; } object_desc(header, sizeof(header), o_ptr, ODESC_PREFIX | ODESC_BASE); labels = string_make(lower_case); m->selections = labels; /* 'I' is used for inspect in both keymaps. */ menu_dynamic_add_label(m, "Inspect", 'I', MENU_VALUE_INSPECT, labels); if (obj_can_browse(o_ptr)) { if (obj_can_cast_from(o_ptr) && player_can_cast(p_ptr, FALSE)) { ADD_LABEL("Cast", CMD_CAST, MN_ROW_VALID); } if (obj_can_study(o_ptr) && player_can_study(p_ptr, FALSE)) { cmd_code study_cmd = player_has(PF_CHOOSE_SPELLS) ? CMD_STUDY_SPELL : CMD_STUDY_BOOK; /* Hack - Use the STUDY_BOOK command key so that we get the correct command key. */ cmdkey = cmd_lookup_key_unktrl(CMD_STUDY_BOOK, mode); menu_dynamic_add_label(m, "Study", cmdkey, study_cmd, labels); } if (player_can_read(p_ptr, FALSE)) { ADD_LABEL("Browse", CMD_BROWSE_SPELL, MN_ROW_VALID); } } else if (obj_is_useable(o_ptr)) { if (obj_is_wand(o_ptr)) { menu_row_validity_t valid = (obj_has_charges(o_ptr)) ? MN_ROW_VALID : MN_ROW_INVALID; ADD_LABEL("Aim", CMD_USE_WAND, valid); } else if (obj_is_rod(o_ptr)) { menu_row_validity_t valid = (obj_can_zap(o_ptr)) ? MN_ROW_VALID : MN_ROW_INVALID; ADD_LABEL("Zap", CMD_USE_ROD, valid); } else if (obj_is_staff(o_ptr)) { menu_row_validity_t valid = (obj_has_charges(o_ptr)) ? MN_ROW_VALID : MN_ROW_INVALID; ADD_LABEL("Use", CMD_USE_STAFF, valid); } else if (obj_is_scroll(o_ptr)) { menu_row_validity_t valid = (player_can_read(p_ptr, FALSE)) ? MN_ROW_VALID : MN_ROW_INVALID; ADD_LABEL("Read", CMD_READ_SCROLL, valid); } else if (obj_is_potion(o_ptr)) { ADD_LABEL("Quaff", CMD_QUAFF, MN_ROW_VALID); } else if (obj_is_food(o_ptr)) { ADD_LABEL("Eat", CMD_EAT, MN_ROW_VALID); } else if (obj_is_activatable(o_ptr)) { menu_row_validity_t valid = (slot >= INVEN_WIELD && obj_can_activate(o_ptr)) ? MN_ROW_VALID : MN_ROW_INVALID; ADD_LABEL("Activate", CMD_ACTIVATE, valid); } else if (obj_can_fire(o_ptr)) { ADD_LABEL("Fire", CMD_FIRE, MN_ROW_VALID); } else { ADD_LABEL("Use", CMD_USE_ANY, MN_ROW_VALID); } } if (obj_can_refill(o_ptr)) { ADD_LABEL("Refill", CMD_REFILL, MN_ROW_VALID); } if (slot >= INVEN_WIELD && obj_can_takeoff(o_ptr)) { ADD_LABEL("Take off", CMD_TAKEOFF, MN_ROW_VALID); } else if (slot < INVEN_WIELD && obj_can_wear(o_ptr)) { //if (obj_is_armor(o_ptr)) { // menu_dynamic_add(m, "Wear", 2); //} else { // menu_dynamic_add(m, "Wield", 2); //} ADD_LABEL("Equip", CMD_WIELD, MN_ROW_VALID); } if (slot >= 0) { if (!store_in_store || cave_shopnum(cave, p_ptr->py, p_ptr->px) == STORE_HOME) { ADD_LABEL("Drop", CMD_DROP, MN_ROW_VALID); if (o_ptr->number > 1) { /* 'D' is used for squelch in rogue keymap, so we'll just swap letters. */ cmdkey = (mode == KEYMAP_MODE_ORIG) ? 'D' : 'k'; menu_dynamic_add_label(m, "Drop All", cmdkey, MENU_VALUE_DROP_ALL, labels); } } } else { menu_row_validity_t valid = (inven_carry_okay(o_ptr)) ? MN_ROW_VALID : MN_ROW_INVALID; ADD_LABEL("Pick up", CMD_PICKUP, valid); } ADD_LABEL("Throw", CMD_THROW, MN_ROW_VALID); ADD_LABEL("Inscribe", CMD_INSCRIBE, MN_ROW_VALID); if (obj_has_inscrip(o_ptr)) { ADD_LABEL("Uninscribe", CMD_UNINSCRIBE, MN_ROW_VALID); } ADD_LABEL( (object_is_squelched(o_ptr) ? "Unignore" : "Ignore"), CMD_DESTROY, MN_ROW_VALID); /* work out display region */ r.width = (int)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; area.width = -(r.width + 2); /* Hack -- no flush needed */ msg_flag = FALSE; screen_save(); /* Display info */ tb = object_info(o_ptr, OINFO_NONE); object_desc(header, sizeof(header), o_ptr, ODESC_PREFIX | ODESC_FULL); textui_textblock_place(tb, area, format("%s", header)); textblock_free(tb); menu_layout(m, &r); region_erase_bordered(&r); prt(format("(Enter to select, ESC) Command for %s:", header), 0, 0); selected = menu_dynamic_select(m); menu_dynamic_free(m); string_free(labels); screen_load(); cmdkey = cmd_lookup_key(selected, mode); switch (selected) { case -1: /* User cancelled the menu. */ return 3; case MENU_VALUE_INSPECT: /* copied from textui_obj_examine */ /* Display info */ tb = object_info(o_ptr, OINFO_NONE); object_desc(header, sizeof(header), o_ptr, ODESC_PREFIX | ODESC_FULL); textui_textblock_show(tb, area, format("%s", header)); textblock_free(tb); return 2; case MENU_VALUE_DROP_ALL: /* Drop entire stack with confirmation. */ if (get_check(format("Drop %s? ", header))) { cmd_insert(store_in_store ? CMD_STASH : CMD_DROP); cmd_set_arg_item(cmd_get_top(), 0, slot); cmd_set_arg_number(cmd_get_top(), 1, o_ptr->number); } return 1; case CMD_STUDY_SPELL: /* Hack - Use the STUDY_BOOK command key so that get_item_allow() works properly. */ cmdkey = cmd_lookup_key(CMD_STUDY_BOOK, mode); /* Fall through. */ case CMD_BROWSE_SPELL: case CMD_STUDY_BOOK: case CMD_CAST: case CMD_DESTROY: case CMD_WIELD: case CMD_TAKEOFF: case CMD_INSCRIBE: case CMD_UNINSCRIBE: case CMD_PICKUP: case CMD_DROP: case CMD_REFILL: case CMD_THROW: case CMD_USE_WAND: case CMD_USE_ROD: case CMD_USE_STAFF: case CMD_READ_SCROLL: case CMD_QUAFF: case CMD_EAT: case CMD_ACTIVATE: case CMD_FIRE: case CMD_USE_ANY: /* Check for inscriptions that trigger confirmation. */ allowed = key_confirm_command(cmdkey) && get_item_allow(slot, cmdkey, selected, FALSE); break; default: /* Invalid command; prevent anything from happening. */ bell("Invalid context menu command."); allowed = FALSE; break; } if (!allowed) return 1; if (selected == CMD_DESTROY) { /* squelch or unsquelch the item */ textui_cmd_destroy_menu(slot); } else if (selected == CMD_BROWSE_SPELL) { /* browse a spellbook */ /* copied from textui_spell_browse */ textui_book_browse(o_ptr); return 2; } else if (selected == CMD_STUDY_SPELL) { /* study a spell book */ /* copied from textui_obj_study */ int spell = get_spell(o_ptr, "study", spell_okay_to_study); if (spell >= 0) { cmd_insert(CMD_STUDY_SPELL); cmd_set_arg_choice(cmd_get_top(), 0, spell); } } else if (selected == CMD_CAST) { if (obj_can_browse(o_ptr)) { /* copied from textui_obj_cast */ const char *verb = ((p_ptr->class->spell_book == TV_MAGIC_BOOK) ? "cast" : "recite"); int spell = get_spell(o_ptr, verb, spell_okay_to_cast); if (spell >= 0) { cmd_insert(CMD_CAST); cmd_set_arg_choice(cmd_get_top(), 0, spell); } } } else {