From 56d5bf50e56cb82522764a80479bddb9632b88fb Mon Sep 17 00:00:00 2001 From: Michael Meyer Date: Thu, 16 Nov 2023 22:48:31 -0500 Subject: [PATCH] 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). --- src/do.c | 14 ++++++-------- src/pickup.c | 17 ++++++++++------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/do.c b/src/do.c index 7a20e1d1c..9a998309c 100644 --- a/src/do.c +++ b/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 diff --git a/src/pickup.c b/src/pickup.c index 6474c9973..79c84554d 100644 --- a/src/pickup.c +++ b/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;