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:
14
src/do.c
14
src/do.c
@@ -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
|
||||
|
||||
17
src/pickup.c
17
src/pickup.c
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user