fix #K4006 - 'null obj after quiver merge' panic

Using apply to unlight a lit potion of oil makes it unlit, removes
it from inventory, and then re-adds it to try to force it to merge
with other potions of oil.  If it was wielded and the other potions
were quivered, the game would panic.  When merging, they get forced
into the weapon slot in preference to the quiver slot.

Unwearing it before freeinv+addinv would solve this but also leave
the hero with nothing wielded, even if it didn't merge with another
stack.  Instead, don't try to merge if the potion being unlit happens
to be worn.

3.6.x was subject to this too and the fix is small+isolated but the
situation is so uncommon that I haven't bothered backporting it.

Applying a lump of royal jelly and then not picking anything to rub
it on had a similar problem.  It also panicked if the applied lump
was wielded and other lumps were quivered.  The fix is different
because the stack it gets split from during apply is known.  This one
doesn't impact 3.6.x; applying jelly to eggs wasn't implemented yet.
This commit is contained in:
PatR
2023-09-19 07:16:00 -07:00
parent 44a649b0b4
commit 3fdcd5f4e0
3 changed files with 29 additions and 9 deletions

View File

@@ -1237,6 +1237,9 @@ ring of hunger prevents choking on your food
paranoid_confirm:pray can be changed to require yes/no response instead of y/n
by also setting paranoid_confirm:Confirm
wand of probing reveals map locations in the ray path
applying a wielded, lit potion of oil to unlight it while other unlit
potion(s) of oil were quivered would trigger panic
"addinv: null obj after quiver merge otyp=N" where N is POT_OIL
Fixes to 3.7.0-x General Problems Exposed Via git Repository
@@ -1676,6 +1679,9 @@ using wizard mode #wizkill outside the endgame followed by m^V to enter the
dwarf/elf/orc/gnome hero killed by zombie would rise as human zombie for bones
paranoid_confirm:Autoall for menustyle:full has the test handling backward and
was treating 'yes' as no and 'n' or ESC as 'y'
applying a wielded lump of royal jelly but not picking something to rub it on
while other lumps of jelly were quivered would trigger a panic,
"addinv: null obj after quiver merge" (like applying lit potion of oil)
Fixes to 3.7.0-x Platform and/or Interface Problems Exposed Via git Repository

View File

@@ -1684,10 +1684,14 @@ light_cocktail(struct obj **optr)
/*
* Free & add to re-merge potion. This will average the
* age of the potions. Not exactly the best solution,
* but its easy.
* but its easy. Don't do that unless obj is not worn (uwep,
* uswapwep, or uquiver) because if wielded and other oil is
* quivered a "null obj after quiver merge" panic will occur.
*/
freeinv(obj);
*optr = addinv(obj);
if (!obj->owornmask) {
freeinv(obj);
*optr = addinv(obj);
}
return;
} else if (Underwater) {
There("is not enough oxygen to sustain a fire.");
@@ -1702,7 +1706,8 @@ light_cocktail(struct obj **optr)
Blind ? "" : " It gives off a dim light.");
if (obj->unpaid && costly_spot(u.ux, u.uy)) {
struct monst *shkp VOICEONLY = shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE));
struct monst *shkp VOICEONLY = shop_keeper(*in_rooms(u.ux, u.uy,
SHOPBASE));
/* Normally, we shouldn't both partially and fully charge
* for an item, but (Yendorian Fuel) Taxes are inevitable...
@@ -3477,10 +3482,10 @@ use_royal_jelly(struct obj **optr)
{
int oldcorpsenm;
unsigned was_timed;
struct obj *obj = *optr;
struct obj *eobj;
struct obj *eobj, *obj = *optr;
boolean splitit = (obj->quan > 1L);
if (obj->quan > 1L)
if (splitit)
obj = splitobj(obj, 1L);
/* remove from inventory so that it won't be offered as a choice
to rub on itself */
@@ -3489,8 +3494,15 @@ use_royal_jelly(struct obj **optr)
/* right now you can rub one royal jelly on an entire stack of eggs */
eobj = getobj("rub the royal jelly on", jelly_ok, GETOBJ_PROMPT);
if (!eobj) {
addinv(obj); /* put the unused lump back; if it came from
* a split, it should merge back */
if (splitit) {
(void) unsplitobj(obj);
update_inventory(); /* freeinv() updated perminv w/ obj omitted */
} else {
/* this lump was already separate; pervent merge */
obj->nomerge = 1;
addinv(obj); /* put the unused lump back; updates perminv */
obj->nomerge = 0;
}
return ECMD_CANCEL;
}

View File

@@ -1583,7 +1583,9 @@ nhl_gamestate(lua_State *L)
wornmask = otmp->owornmask;
otmp->owornmask = 0L;
extract_nobj(otmp, &gmst_invent);
otmp->nomerge = 1;
addinv(otmp);
otmp->nomerge = 0;
if (wornmask)
setworn(otmp, wornmask);
}