shrink_glob bug when when glob is totally gone

When a wielded glob shrank away to nothing, an impossible warning:
"obfree: deleting worn obj" would be issued.

If a glob is quivered or wielded or set up as swap weapon when it
shrinks away to nothing, clear the relevant weapon slot before
destroying the glob.

Won't happen for monsters since they never wield globs.  Also won't
happen for migrating objects (which overload obj->owornmask) because
they have to have arrived somewhere in order to have their shrink
timer execute.
This commit is contained in:
PatR
2021-12-10 20:16:30 -08:00
parent 8aa90bdbac
commit ba255875cd
3 changed files with 25 additions and 17 deletions

View File

@@ -923,6 +923,8 @@ if 'showrace' was On and invisible hero couldn't see invisible so didn't see
in wizard mode, a poly'd priest/priestess attempting to polymorph into priest
or priestess in order to rehumanize became a new man or woman instead
because "priest" matched "aligned cleric" rather than the role monster
if a glob which has just shrunk away to nothing was wielded or quivered,
unwield it before destroying it
curses: 'msg_window' option wasn't functional for curses unless the binary
also included tty support

View File

@@ -1996,19 +1996,13 @@ rot_corpse(anything *arg, long timeout)
Your("%s%s %s away%c", obj == uwep ? "wielded " : "", cname,
otense(obj, "rot"), obj == uwep ? '!' : '.');
}
if (obj == uwep) {
uwepgone(); /* now bare handed */
stop_occupation();
} else if (obj == uswapwep) {
uswapwepgone();
stop_occupation();
} else if (obj == uquiver) {
uqwepgone();
if (obj->owornmask) {
remove_worn_item(obj, TRUE);
stop_occupation();
}
} else if (obj->where == OBJ_MINVENT && obj->owornmask) {
if (obj == MON_WEP(obj->ocarry))
setmnotwielded(obj->ocarry, obj);
} else if (obj->where == OBJ_MINVENT) {
if (obj->owornmask && obj == MON_WEP(obj->ocarry))
setmnotwielded(obj->ocarry, obj); /* clears owornmask */
} else if (obj->where == OBJ_MIGRATING) {
/* clear destination flag so that obfree()'s check for
freeing a worn object doesn't get a false hit */

View File

@@ -1368,7 +1368,8 @@ shrink_glob(
if (delta >= (long) obj->owt) {
/* gone; no newsym() or message here--forthcoming map update for
level arrival is all that's needed */
level arrival is all that's needed; no owornmask handling is
necessary (obj is not in invent, monsters never wield globs) */
obj_extract_self(obj); /* if contained, also updates container's
* weight (recursively when nested) */
obfree(obj, (struct obj *) 0);
@@ -1486,11 +1487,22 @@ shrink_glob(
&& get_obj_location(obj, &ox, &oy, 0)
&& cansee(ox, oy));
/* weight has been reduced to 0 so destroy the glob; if it was
contained, it has already been removed from its container above */
if (obj->where != OBJ_FREE)
obj_extract_self(obj);
obfree(obj, (struct obj *) 0);
/* weight has been reduced to 0 so destroy the glob */
if (ininv) {
if (obj->owornmask) {
remove_worn_item(obj, FALSE);
stop_occupation();
}
useupall(obj); /* freeinv()+obfree() */
} else {
/* no owornmask handling necessary (when not in hero's invent,
can't be worn: monsters don't wield globs and shrink timer
can't fire for migrating objects); if glob was contained, it
has already been removed from its container and is now free */
if (obj->where != OBJ_FREE)
obj_extract_self(obj);
obfree(obj, (struct obj *) 0);
}
if (seeit) {
newsym(ox, oy);