From ba255875cd0da63dc7ade8395b73231af6b77755 Mon Sep 17 00:00:00 2001 From: PatR Date: Fri, 10 Dec 2021 20:16:30 -0800 Subject: [PATCH] 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. --- doc/fixes37.0 | 2 ++ src/dig.c | 16 +++++----------- src/mkobj.c | 24 ++++++++++++++++++------ 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 175c0ee9b..4e37125ae 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -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 diff --git a/src/dig.c b/src/dig.c index 1ed57b428..8cb34e237 100644 --- a/src/dig.c +++ b/src/dig.c @@ -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 */ diff --git a/src/mkobj.c b/src/mkobj.c index afd757acf..86be3b0e6 100644 --- a/src/mkobj.c +++ b/src/mkobj.c @@ -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);