fix issue #1455 - fully thrown quiver stack won't

autoquiver when picked back up

Issue reported by ars3niy:  empty quiver used to be refilled when
picking a thrown item or stack up.  Bug introduced by a previous fix
(commit 593a93d254) dealing with the
post-3.6 obj->how_lost field.

As with the last time I dealt with this, there was a lot of trial
and error involved.  This fixes the quiver issue without bringing
the earlier problem back.  This time the problem was that how_lost
got cleared before it was used to check whether an item being picked
up had been thrown.

Dropping part of a stack and throwing another part of the same stack
may behave oddly if a monster picks both up.  I am not going to try
to figure that out.

Fixes #1466
This commit is contained in:
PatR
2025-12-24 22:11:16 -08:00
parent aae7778d66
commit 5bda026acb
3 changed files with 22 additions and 16 deletions

View File

@@ -2177,6 +2177,8 @@ livelog/#chronicle for saving-grace: if saving-grace prevents hero's death,
naming a type of item, unnaming it (with name of <space>), naming it again
(new name or re-use of old one), then unnaming it again would issue
impossible: "named object not in disco"
throwing entire quiver and then picking the stack back up was not putting it
back into quiver
Fixes to 3.7.0-x Platform and/or Interface Problems Exposed Via git Repository

View File

@@ -1063,8 +1063,9 @@ addinv_core2(struct obj *obj)
* Adjust hero attributes as necessary.
*/
staticfn struct obj *
addinv_core0(struct obj *obj, struct obj *other_obj,
boolean update_perm_invent)
addinv_core0(
struct obj *obj, struct obj *other_obj,
boolean update_perm_invent)
{
struct obj *otmp, *prev;
int saved_otyp = (int) obj->otyp; /* for panic */
@@ -1072,6 +1073,9 @@ addinv_core0(struct obj *obj, struct obj *other_obj,
if (obj->where != OBJ_FREE)
panic("addinv: obj not free");
if (obj->how_lost == LOST_EXPLODING)
return (struct obj *) NULL;
/* normally addtobill() clears no_charge when items in a shop are
picked up, but won't do so if the shop has become untended */
obj->no_charge = 0; /* should not be set in hero's invent */
@@ -1146,6 +1150,7 @@ addinv_core0(struct obj *obj, struct obj *other_obj,
setuqwep(obj);
added:
obj->pickup_prev = 1;
obj->how_lost = 0;
addinv_core2(obj); /* handle extrinsics conferred by carrying obj */
carry_obj_effects(obj); /* carrying affects the obj */
if (update_perm_invent)
@@ -1163,7 +1168,8 @@ addinv(struct obj *obj)
/* add obj to the hero's inventory by inserting in front of a specific item;
used for throw-and-return in case '!fixinv' is in effect */
struct obj *
addinv_before(struct obj *obj, struct obj *other_obj)
addinv_before(
struct obj *obj, struct obj *other_obj)
{
/* if 'other_obj' is present this will implicitly be 'nomerge' */
return addinv_core0(obj, other_obj, TRUE);
@@ -5094,7 +5100,12 @@ mergable(
if (obj->cursed != otmp->cursed || obj->blessed != otmp->blessed)
return FALSE;
if ((obj->how_lost & ~LOSTOVERRIDEMASK) != 0)
if (obj->how_lost == LOST_EXPLODING
|| otmp->how_lost == LOST_EXPLODING)
return FALSE;
if ((obj->how_lost & ~LOSTOVERRIDEMASK)
!= (otmp->how_lost & ~LOSTOVERRIDEMASK))
return FALSE;
#if 0 /* don't require 'bypass' to match; that results in items dropped
* via 'D' not stacking with compatible items already on the floor;
@@ -5111,8 +5122,7 @@ mergable(
if (obj->unpaid != otmp->unpaid || obj->spe != otmp->spe
|| obj->no_charge != otmp->no_charge || obj->obroken != otmp->obroken
|| obj->otrapped != otmp->otrapped || obj->lamplit != otmp->lamplit
|| obj->how_lost != otmp->how_lost)
|| obj->otrapped != otmp->otrapped || obj->lamplit != otmp->lamplit)
return FALSE;
if (obj->oclass == FOOD_CLASS

View File

@@ -1805,7 +1805,6 @@ pickup_object(
long count, /* if non-zero, pick up a subset of this amount */
boolean telekinesis) /* not picking it up directly by hand */
{
unsigned save_how_lost;
int res;
if (obj->quan < count) {
@@ -1862,16 +1861,12 @@ pickup_object(
}
}
save_how_lost = obj->how_lost;
/* obj has either already passed autopick_testobj or we are explicitly
picking it off the floor, so override obj->how_lost; otherwise we
couldn't pick up a thrown, stolen, or dropped item that was split
off from a carried stack even while still carrying the rest of the
stack unless we have at least one free slot available */
obj->how_lost &= ~LOSTOVERRIDEMASK; /* affects merge_choice() */
picking it off the floor, so addinv() will override obj->how_lost;
otherwise we couldn't pick up a thrown, stolen, or dropped item that
was split off from a carried stack even while still carrying the
rest of the stack unless we have at least one free slot available */
res = lift_object(obj, (struct obj *) 0, &count, telekinesis);
obj->how_lost = save_how_lost; /* even when res > 0,
* in case we call splitobj() below */
if (res <= 0)
return res;
@@ -1881,7 +1876,6 @@ pickup_object(
if (obj->quan != count && obj->otyp != LOADSTONE)
obj = splitobj(obj, count);
obj->how_lost &= ~LOSTOVERRIDEMASK;
obj = pick_obj(obj);
if (uwep && uwep == obj)