Ignore loot/multidrop 'A' if no filter specified

The 'A' option in the #loot or 'D'rop menu selecting every selectable
item when used on its own has been the cause of many bag of holding
explosions and other typo-related frustration.  Now that it operates on
other filters rather than overriding them, actually require some other
filter be selected for it to have any effect.  This means that 'A' on
its own will do nothing, but 'A'+'a' will still act like 'A' alone
previously did.  I think this will reduce the rate of serious typo
accidents in games, without being intrusive and while still maintaining
'A' as a useful option (which I think it is, in it's 3.7 incarnation --
I use it all the time in combination with other filters, especially
justpicked).
This commit is contained in:
Michael Meyer
2023-11-16 22:48:31 -05:00
committed by PatR
parent c2fd027669
commit 56d5bf50e5
2 changed files with 16 additions and 15 deletions

View File

@@ -955,7 +955,7 @@ menu_drop(int retry)
int n, i, n_dropped = 0;
struct obj *otmp, *otmp2;
menu_item *pick_list;
boolean all_categories = TRUE, drop_everything = FALSE, autopick = FALSE;
boolean all_categories = TRUE, autopick = FALSE;
boolean drop_justpicked = FALSE;
long justpicked_quan = 0;
@@ -968,21 +968,19 @@ menu_drop(int retry)
| BUC_BLESSED | BUC_CURSED | BUC_UNCURSED
| BUC_UNKNOWN | JUSTPICKED | INCLUDE_VENOM),
&pick_list, PICK_ANY);
if (!n)
goto drop_done;
if (!n || (n == 1 && pick_list[0].item.a_int == 'A'))
goto drop_done; /* no non-autopick category filters specified */
for (i = 0; i < n; i++) {
if (pick_list[i].item.a_int == ALL_TYPES_SELECTED) {
all_categories = TRUE;
} else if (pick_list[i].item.a_int == 'A') {
drop_everything = autopick = TRUE;
autopick = TRUE;
} else if (pick_list[i].item.a_int == 'P') {
justpicked_quan = max(0, pick_list[i].count);
drop_justpicked = TRUE;
drop_everything = FALSE;
add_valid_menu_class(pick_list[i].item.a_int);
} else {
add_valid_menu_class(pick_list[i].item.a_int);
drop_everything = FALSE;
}
}
free((genericptr_t) pick_list);
@@ -1021,7 +1019,7 @@ menu_drop(int retry)
*/
bypass_objlist(gi.invent, FALSE); /* clear bypass bit for invent */
while ((otmp = nxt_unbypassed_obj(gi.invent)) != 0) {
if (drop_everything || all_categories || allow_category(otmp))
if (all_categories || allow_category(otmp))
n_dropped += ((drop(otmp) & ECMD_TIME) != 0) ? 1 : 0;
}
/* we might not have dropped everything (worn armor, welded weapon,
@@ -1043,7 +1041,7 @@ menu_drop(int retry)
/*
* picklist[] contains a set of pointers into inventory, but
* as soon as something gets dropped, they might become stale
* (see the drop_everything code above for an explanation).
* (see the autopick code above for an explanation).
* Just checking to see whether one is still in the gi.invent
* chain is not sufficient validation since destroyed items
* will be freed and items we've split here might have already

View File

@@ -504,6 +504,11 @@ allow_all(struct obj *obj UNUSED)
boolean
allow_category(struct obj *obj)
{
/* If no filters are active, nothing will match. */
if (!gc.class_filter && !gs.shop_filter && !gb.bucx_filter
&& !gp.picked_filter)
return FALSE;
/* For coins, if any class filter is specified, accept if coins
* are included regardless of whether either unpaid or BUC-status
* is also specified since player has explicitly requested coins.
@@ -3166,7 +3171,7 @@ static int
menu_loot(int retry, boolean put_in)
{
int n, i, n_looted = 0;
boolean all_categories = TRUE, loot_everything = FALSE, autopick = FALSE;
boolean all_categories = TRUE, autopick = FALSE;
char buf[BUFSZ];
boolean loot_justpicked = FALSE;
const char *action = put_in ? "Put in" : "Take out";
@@ -3187,21 +3192,19 @@ menu_loot(int retry, boolean put_in)
n = query_category(buf,
put_in ? gi.invent : gc.current_container->cobj,
mflags, &pick_list, PICK_ANY);
if (!n)
return ECMD_OK;
if (!n || (n == 1 && pick_list[0].item.a_int == 'A'))
return ECMD_OK; /* no non-autopick category filters specified */
for (i = 0; i < n; i++) {
if (pick_list[i].item.a_int == 'A') {
loot_everything = autopick = TRUE;
autopick = TRUE;
} else if (put_in && pick_list[i].item.a_int == 'P') {
loot_justpicked = TRUE;
count = max(0, pick_list[i].count);
add_valid_menu_class(pick_list[i].item.a_int);
loot_everything = FALSE;
} else if (pick_list[i].item.a_int == ALL_TYPES_SELECTED) {
all_categories = TRUE;
} else {
add_valid_menu_class(pick_list[i].item.a_int);
loot_everything = FALSE;
}
}
free((genericptr_t) pick_list);
@@ -3228,7 +3231,7 @@ menu_loot(int retry, boolean put_in)
*/
for (otmp = firstobj; otmp && gc.current_container; otmp = otmp2) {
otmp2 = otmp->nobj;
if (loot_everything || all_categories || allow_category(otmp)) {
if (all_categories || allow_category(otmp)) {
res = (*inout_func)(otmp);
if (res < 0)
break;