From 99790cbb8924641903ee447e7319c5bf0291d82e Mon Sep 17 00:00:00 2001 From: kinther Date: Thu, 2 Oct 2025 13:39:00 -0700 Subject: [PATCH] Add view command for shops and remove identify --- src/interpreter.c | 2 +- src/shop.c | 204 ++++++++++++++++++++-------------------------- 2 files changed, 88 insertions(+), 118 deletions(-) diff --git a/src/interpreter.c b/src/interpreter.c index 8762d44..bffa33e 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -174,7 +174,6 @@ cpp_extern const struct command_info cmd_info[] = { { "house" , "house" , POS_RESTING , do_house , 0, 0 }, { "inventory", "i" , POS_DEAD , do_inventory, 0, 0 }, - { "identify" , "id" , POS_STANDING, do_not_here , 1, 0 }, { "idea" , "ide" , POS_DEAD , do_ibt , 0, SCMD_IDEA }, { "imotd" , "imo" , POS_DEAD , do_gen_ps , LVL_IMMORT, SCMD_IMOTD }, { "immlist" , "imm" , POS_DEAD , do_gen_ps , 0, SCMD_IMMLIST }, @@ -320,6 +319,7 @@ cpp_extern const struct command_info cmd_info[] = { { "value" , "val" , POS_STANDING, do_not_here , 0, 0 }, { "version" , "ver" , POS_DEAD , do_gen_ps , 0, SCMD_VERSION }, + { "view" , "vie" , POS_STANDING, do_not_here , 0, 0 }, { "visible" , "vis" , POS_RESTING , do_visible , 1, 0 }, { "vnum" , "vnum" , POS_DEAD , do_vnum , LVL_IMMORT, 0 }, { "vstat" , "vstat" , POS_DEAD , do_vstat , LVL_IMMORT, 0 }, diff --git a/src/shop.c b/src/shop.c index a9093e8..2221c22 100644 --- a/src/shop.c +++ b/src/shop.c @@ -61,7 +61,6 @@ static char *read_shop_message(int mnum, room_vnum shr, FILE *shop_f, const char static int read_type_list(FILE *shop_f, struct shop_buy_data *list, int new_format, int max); static int read_list(FILE *shop_f, struct shop_buy_data *list, int new_format, int max, int type); static void shopping_list(char *arg, struct char_data *ch, struct char_data *keeper, int shop_nr); -static bool shopping_identify(char *arg, struct char_data *ch, struct char_data *keeper, int shop_nr); static void shopping_value(char *arg, struct char_data *ch, struct char_data *keeper, int shop_nr); static void shopping_sell(char *arg, struct char_data *ch, struct char_data *keeper, int shop_nr); static struct obj_data *get_selling_obj(struct char_data *ch, char *name, struct char_data *keeper, int shop_nr, int msg); @@ -996,9 +995,93 @@ SPECIAL(shop_keeper) } else if (CMD_IS("list")) { shopping_list(argument, ch, keeper, shop_nr); return (TRUE); - } else if (CMD_IS("identify")) { - return (shopping_identify(argument, ch, keeper, shop_nr)); - } + } else if (CMD_IS("view")) { + /* view #N */ + char tok[MAX_INPUT_LENGTH]; + struct obj_data *obj = NULL, *last_obj = NULL, *cur; + int index, lindex = 0, cnt = 0; + + one_argument(argument, tok); + + if (!*tok || tok[0] != '#') { + send_to_char(ch, "Usage: view #\r\n"); + return (TRUE); + } + index = atoi(tok + 1); + if (index <= 0) { + send_to_char(ch, "That item number looks off. Try: view #1\r\n"); + return (TRUE); + } + + /* Mirror shopping_list() gates and ordering */ + if (!is_ok(keeper, ch, shop_nr)) + return (TRUE); + + if (SHOP_SORT(shop_nr) < IS_CARRYING_N(keeper)) + sort_keeper_objs(keeper, shop_nr); + + /* Group identical items with same_obj() and count groups to match list numbering */ + for (cur = keeper->carrying; cur; cur = cur->next_content) { + if (!(CAN_SEE_OBJ(ch, cur) && GET_OBJ_COST(cur) > 0)) + continue; + + if (!last_obj) { + last_obj = cur; + cnt = 1; + continue; + } + + if (same_obj(last_obj, cur)) { + cnt++; + continue; + } + + /* Completed a group: bump list index */ + lindex++; + if (lindex == index) { + obj = last_obj; + break; + } + + /* Start next group */ + last_obj = cur; + cnt = 1; + } + + /* Handle tail group if needed */ + if (!obj && last_obj) { + lindex++; + if (lindex == index) + obj = last_obj; + } + + if (!obj) { + send_to_char(ch, "There is no item #%d in the shop list.\r\n", index); + return (TRUE); + } + + /* Show main description and weight */ + { + const char *mdesc = NULL; +#ifdef GET_OBJ_MAIN_DESC + if (GET_OBJ_MAIN_DESC(obj) && *GET_OBJ_MAIN_DESC(obj)) + mdesc = GET_OBJ_MAIN_DESC(obj); +#endif + if (!mdesc) { + if (obj->description && *obj->description) + mdesc = obj->description; + else if (obj->short_description && *obj->short_description) + mdesc = obj->short_description; + else + mdesc = "You see nothing remarkable about it."; + } + + send_to_char(ch, "%s\r\n", mdesc); + send_to_char(ch, "Weight: %d\r\n", GET_OBJ_WEIGHT(obj)); + } + + return (TRUE); + } return (FALSE); } @@ -1565,116 +1648,3 @@ void destroy_shops(void) top_shop = -1; } -bool shopping_identify(char *arg, struct char_data *ch, struct char_data *keeper, int shop_nr) -{ - char buf[MAX_STRING_LENGTH]; - struct obj_data *obj; - int i, found; - - if (!is_ok(keeper, ch, shop_nr)) - return FALSE; - - if (SHOP_SORT(shop_nr) < IS_CARRYING_N(keeper)) - sort_keeper_objs(keeper, shop_nr); - - if (!*arg) { - snprintf(buf, sizeof(buf), "%s What do you want to identify??", GET_NAME(ch)); - do_tell(keeper, buf, cmd_tell, 0); - return TRUE; - } - if (!(obj = get_purchase_obj(ch, arg, keeper, shop_nr, TRUE))) - return FALSE; - - send_to_char(ch, "Name: %s\r\n", (obj->short_description) ? obj->short_description : ""); - sprinttype(GET_OBJ_TYPE(obj), item_types, buf, sizeof(buf)); - send_to_char(ch, "Type: %s\r\n", buf); - send_to_char(ch, "Weight: %d, Cost to Sell: %s%d%s, Cost to Buy: %s%d%s\r\n", - GET_OBJ_WEIGHT(obj), - QYEL, sell_price(obj, shop_nr, keeper, ch), QNRM, - QYEL, buy_price(obj, shop_nr, keeper, ch), QNRM); - - sprintbitarray(GET_OBJ_WEAR(obj), wear_bits, TW_ARRAY_MAX, buf); - send_to_char(ch, "Can be worn on: %s\r\n", buf); - - switch (GET_OBJ_TYPE(obj)) { - case ITEM_LIGHT: - if (GET_OBJ_VAL(obj, 2) == -1) - send_to_char(ch, "Hours Remaining: (Infinite)\r\n"); - else if (GET_OBJ_VAL(obj, 2) == 0) - send_to_char(ch, "Hours Remaining: None!\r\n"); - else - send_to_char(ch, "Hours Remaining: %d\r\n", GET_OBJ_VAL(obj, 2)); - break; - case ITEM_SCROLL: - case ITEM_POTION: - send_to_char(ch, "Spells: %s, %s, %s\r\n", - skill_name(GET_OBJ_VAL(obj, 1)), - skill_name(GET_OBJ_VAL(obj, 2)), - skill_name(GET_OBJ_VAL(obj, 3))); - break; - case ITEM_WAND: - case ITEM_STAFF: - send_to_char(ch, "Spell: %s\r\n", skill_name(GET_OBJ_VAL(obj, 3))); - send_to_char(ch, "Charges: %d/%d\r\n", GET_OBJ_VAL(obj, 2), GET_OBJ_VAL(obj, 1)); - break; - case ITEM_WEAPON: - send_to_char(ch, "Damage Dice is '%dD%d' for an average per-round damage of %.1f.\r\n", - GET_OBJ_VAL(obj, 1), GET_OBJ_VAL(obj, 2), - ((GET_OBJ_VAL(obj, 2) + 1) / 2.0) * GET_OBJ_VAL(obj, 1)); - break; - case ITEM_ARMOR: - if(GET_OBJ_VAL(obj,1) == 0) - { - send_to_char(ch, "AC-apply: [%d]\r\n", GET_OBJ_VAL(obj, 0)); - } - else - { - send_to_char(ch, "AC-apply: [%d] - This item has magical affects.\r\n", GET_OBJ_VAL(obj, 0)); - } - break; - case ITEM_CONTAINER: - send_to_char(ch, "Capacity: %d/%d\r\n", GET_OBJ_WEIGHT(obj), GET_OBJ_VAL(obj, 0)); - break; - case ITEM_DRINKCON: - case ITEM_FOUNTAIN: - send_to_char(ch, "Drinks: %d/%d\r\n", GET_OBJ_VAL(obj, 1), GET_OBJ_VAL(obj, 0)); - break; - case ITEM_NOTE: - send_to_char(ch, "\r\n"); - break; - case ITEM_KEY: - send_to_char(ch, "\r\n"); - break; - case ITEM_FOOD: - send_to_char(ch, "\r\n"); - break; - case ITEM_MONEY: - send_to_char(ch, "\r\n"); - break; - case ITEM_WORN: - if(GET_OBJ_VAL(obj,1) > 0) - send_to_char(ch, "This item has magical affects.\r\n"); - else - send_to_char(ch, "\r\n"); - break; - default: - send_to_char(ch, "\r\n"); - break; - } - - found = 0; - send_to_char(ch, "Affections:"); - for (i = 0; i < MAX_OBJ_AFFECT; i++) - if (obj->affected[i].modifier) { - sprinttype(obj->affected[i].location, apply_types, buf, sizeof(buf)); - send_to_char(ch, "%s %+d to %s", found++ ? "," : "", obj->affected[i].modifier, buf); - } - if (!found) - send_to_char(ch, " None"); - - send_to_char(ch, "\r\nExtra Flags: "); - sprintbitarray(GET_OBJ_EXTRA(obj), extra_bits, EF_ARRAY_MAX, buf); - send_to_char(ch, "%s\r\n", buf); - - return TRUE; -}