From: PatR Date: Sun, 10 Apr 2022 19:22:21 +0000 (-0700) Subject: context-sensitive inventory X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4195722df68adf4107f2f5410c886c024c5343ce;p=nethack context-sensitive inventory Add '-' choice if player picks wielded weapon. 'w-' is effectively the unwield command but a normal inventory list doesn't present '-' as something that can be picked, so there's no context menu entry that can suggest wielding it. Make 't' clearer. Don't offer it as a choice when selected item is worn, distinguish between throwing and shooting, and introduce a bit of plural handling. Since we aren't using a magic 'A' command to "equip" and "unequip", make the uses of P/R/T/W match up with how they normally operate so that player can learn them while using item menus. Do something similar for offer vs sacrifice. --- diff --git a/src/invent.c b/src/invent.c index 847f8419e..447fb3ba6 100644 --- a/src/invent.c +++ b/src/invent.c @@ -2515,6 +2515,7 @@ enum item_action_actions { IA_SWAPWEAPON, IA_ZAP_OBJ, IA_SACRIFICE, + IA_UNWIELD }; static void @@ -2543,6 +2544,17 @@ itemactions(struct obj *otmp) win = create_nhwindow(NHW_MENU); start_menu(win, MENU_BEHAVE_STANDARD); + /* -: unwield; picking current weapon offers an opportunity for 'w-' + to wield bare/gloved hands */ + if (otmp == uwep) { + /* TODO: if uwep is ammo, tell player that to shoot instead of toss, + * the corresponding launcher must be wielded */ + Sprintf(buf, "Wield '-' to unwield this %s", + (otmp->oclass == WEAPON_CLASS || is_weptool(otmp)) ? "weapon" + : "item"); + ia_addmenu(win, IA_UNWIELD, '-', buf); + } + /* a: apply */ if (otmp->otyp == CREAM_PIE) ia_addmenu(win, IA_APPLY_OBJ, 'a', "Hit yourself with this cream pie"); @@ -2622,7 +2634,8 @@ itemactions(struct obj *otmp) /* e: eat item */ if (otmp->otyp == TIN && uwep && uwep->otyp == TIN_OPENER) - ia_addmenu(win, IA_EAT_OBJ, 'e', "Open and eat this tin with your tin opener"); + ia_addmenu(win, IA_EAT_OBJ, 'e', + "Open and eat this tin with your tin opener"); else if (otmp->otyp == TIN) ia_addmenu(win, IA_EAT_OBJ, 'e', "Open and eat this tin"); else if (is_edible(otmp)) @@ -2635,24 +2648,40 @@ itemactions(struct obj *otmp) ia_addmenu(win, IA_ENGRAVE_OBJ, 'E', "Scribble graffiti on the floor"); else if (otmp->oclass == WEAPON_CLASS || otmp->oclass == WAND_CLASS || otmp->oclass == GEM_CLASS || otmp->oclass == RING_CLASS) - ia_addmenu(win, IA_ENGRAVE_OBJ, 'E', "Write on the floor with this object"); + ia_addmenu(win, IA_ENGRAVE_OBJ, 'E', + "Write on the floor with this object"); /* p: pay for unpaid utems */ if ((mtmp = shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE))) && inhishop(mtmp) && otmp->unpaid) ia_addmenu(win, IA_BUY_OBJ, 'p', "Buy this unpaid item"); + /* P: put on accessory */ + if (!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL))) { + if (otmp->oclass == RING_CLASS || otmp->otyp == MEAT_RING) + ia_addmenu(win, IA_WEAR_OBJ, 'P', "Put this ring on"); + else if (otmp->oclass == AMULET_CLASS) + ia_addmenu(win, IA_WEAR_OBJ, 'P', "Put this amulet on"); + else if (otmp->otyp == TOWEL || otmp->otyp == BLINDFOLD) + ia_addmenu(win, IA_WEAR_OBJ, 'P', + "Use this to blindfold yourself"); + else if (otmp->otyp == LENSES) + ia_addmenu(win, IA_WEAR_OBJ, 'P', "Put these lenses on"); + } + /* q: drink item */ if (otmp->oclass == POTION_CLASS) ia_addmenu(win, IA_QUAFF_OBJ, 'q', "Quaff this potion"); /* Q: quiver throwable item */ if (otmp->oclass == GEM_CLASS || otmp->oclass == WEAPON_CLASS) - ia_addmenu(win, IA_QUIVER_OBJ, 'Q', "Quiver this item for easy throwing"); + ia_addmenu(win, IA_QUIVER_OBJ, 'Q', + "Quiver this item for easy throwing"); /* r: read item */ if (otmp->otyp == FORTUNE_COOKIE) - ia_addmenu(win, IA_READ_OBJ, 'r', "Read the message inside this cookie"); + ia_addmenu(win, IA_READ_OBJ, 'r', + "Read the message inside this cookie"); else if (otmp->otyp == T_SHIRT) ia_addmenu(win, IA_READ_OBJ, 'r', "Read the slogan on the shirt"); else if (otmp->otyp == ALCHEMY_SMOCK) @@ -2664,7 +2693,9 @@ itemactions(struct obj *otmp) else if (otmp->oclass == SPBOOK_CLASS) ia_addmenu(win, IA_READ_OBJ, 'r', "Study this spellbook"); - /* R: rub item */ + /* R: remove accessory or rub item */ + if (otmp->owornmask & (W_RING | W_AMUL | W_TOOL)) + ia_addmenu(win, IA_TAKEOFF_OBJ, 'R', "Remove this accessory"); if (otmp->otyp == OIL_LAMP || otmp->otyp == MAGIC_LAMP || otmp->otyp == BRASS_LANTERN) { Sprintf(buf, "Rub this %s", simpleonames(otmp)); @@ -2673,11 +2704,27 @@ itemactions(struct obj *otmp) ia_addmenu(win, IA_RUB_OBJ, 'R', "Rub something on this stone"); /* t: throw item */ - ia_addmenu(win, IA_THROW_OBJ, 't', "Throw this item"); + if (!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL))) { + const char *verb = ammo_and_launcher(otmp, uwep) ? "Shoot" : "Throw"; - /* T: take off, unequip worn item */ - if ((otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL))) - ia_addmenu(win, IA_TAKEOFF_OBJ, 'T', "Unequip this equipment"); + /* + * FIXME: + * 'one of these' should be changed to 'some of these' when there + * is the possibility of a multi-shot volley but we don't have + * any way to determine that except by actually calculating the + * volley count and that could randomly yield 1 here and 2..N + * while throwing or vice versa. + */ + Sprintf(buf, "%s %s", verb, + (otmp->quan == 1L) ? "this item" + : (otmp->otyp == GOLD_PIECE) ? "them" + : "one of these"); + ia_addmenu(win, IA_THROW_OBJ, 't', buf); + } + + /* T: take off armor */ + if (otmp->owornmask & W_ARMOR) + ia_addmenu(win, IA_TAKEOFF_OBJ, 'T', "Take off this armor"); /* V: invoke */ if ((otmp->otyp == FAKE_AMULET_OF_YENDOR && !otmp->known) || @@ -2687,27 +2734,22 @@ itemactions(struct obj *otmp) /* w: wield, hold in hands, works on everything but with different advice text; not mentioned for things that are already wielded */ - if (otmp == uwep) { /* nothing here */ } - else if (otmp->oclass == WEAPON_CLASS || otmp->otyp == PICK_AXE - || otmp->otyp == UNICORN_HORN) + if (otmp == uwep) + ; + else if (otmp->oclass == WEAPON_CLASS || is_weptool(otmp) + || is_wet_towel(otmp)) ia_addmenu(win, IA_WIELD_OBJ, 'w', "Wield this as your weapon"); else if (otmp->otyp == TIN_OPENER) ia_addmenu(win, IA_WIELD_OBJ, 'w', "Hold the tin opener to open tins"); else + /* FIXME: there's no concept of "holding an item" that's any + different from having it in inventory; 'w' means wield as weapon */ ia_addmenu(win, IA_WIELD_OBJ, 'w', "Hold this item in your hands"); - /* W: Equip this item */ + /* W: wear armor */ if (!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL))) { if (otmp->oclass == ARMOR_CLASS) ia_addmenu(win, IA_WEAR_OBJ, 'W', "Wear this armor"); - else if (otmp->oclass == RING_CLASS || otmp->otyp == MEAT_RING) - ia_addmenu(win, IA_WEAR_OBJ, 'W', "Put this ring on"); - else if (otmp->oclass == AMULET_CLASS) - ia_addmenu(win, IA_WEAR_OBJ, 'W', "Put this amulet on"); - else if (otmp->otyp == TOWEL || otmp->otyp == BLINDFOLD) - ia_addmenu(win, IA_WEAR_OBJ, 'W', "Use this to blindfold yourself"); - else if (otmp->otyp == LENSES) - ia_addmenu(win, IA_WEAR_OBJ, 'W', "Put these lenses on"); } /* x: Swap main and readied weapon */ @@ -2724,10 +2766,12 @@ itemactions(struct obj *otmp) if (IS_ALTAR(levl[u.ux][u.uy].typ) && !u.uswallow) { if (otmp->otyp == CORPSE) - ia_addmenu(win, IA_SACRIFICE, 'S', "Sacrifice this corpse at this altar"); + ia_addmenu(win, IA_SACRIFICE, 'O', + "Offer this corpse as a sacrifice at this altar"); else if (otmp->otyp == AMULET_OF_YENDOR || otmp->otyp == FAKE_AMULET_OF_YENDOR) - ia_addmenu(win, IA_SACRIFICE, 'S', "Sacrifice this amulet at this altar"); + ia_addmenu(win, IA_SACRIFICE, 'O', + "Offer this amulet as a sacrifice at this altar"); } Sprintf(buf, "Do what with %s?", the(cxname(otmp))); @@ -2742,7 +2786,8 @@ itemactions(struct obj *otmp) switch (act) { default: impossible("Unknown item action"); - case IA_NONE: break; + case IA_NONE: + break; case IA_APPLY_OBJ: cmdq_add_ec(doapply); cmdq_add_key(otmp->invlet); @@ -2816,6 +2861,10 @@ itemactions(struct obj *otmp) cmdq_add_ec(dosacrifice); cmdq_add_key(otmp->invlet); break; + case IA_UNWIELD: + cmdq_add_ec(dowield); + cmdq_add_key('-'); + break; } } else ret = !n ? ECMD_CANCEL : ECMD_OK; /* cancelled */