From 163fb7613fa646ba6cb92cbfcab4f842aac88359 Mon Sep 17 00:00:00 2001 From: PatR Date: Mon, 5 Feb 2024 12:57:13 -0800 Subject: [PATCH] fix theft of uball Yesterday's commit to add a " takes off " during theft of a worn item used uchain instead of uball when the item was uball. That works as intended when uball is just carried, but if it is also wielded, alt-wielded, or quivered then the pointers for those weapon slots weren't updated (because uchain doesn't have the corresponding owornmask bits set when removal performs unpunish()). Check for that and call remove_worn_item() again if necessary. Also, the subsequent " stole " message was inserting "removed the chain and" before "stole" when item is uball, but that isn't needed anymore since the preface message " takes off the iron chain (attached to you)" will have just been given. --- src/steal.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/steal.c b/src/steal.c index ee4cde9e5..029a8bbbd 100644 --- a/src/steal.c +++ b/src/steal.c @@ -329,7 +329,10 @@ worn_item_removal( : 0; if (strip_art) { /* convert "a/an/the " to "your object" */ copynchars(article, objbuf, strip_art); - (void) strsubst(objbuf, article, "your "); + /* when removing attached iron ball, caller passes 'uchain'; + when formatted, it will be "an iron chain (attached to you)"; + change "an" to "the" rather than to "your" in that situation */ + (void) strsubst(objbuf, article, (obj == uchain) ? "the " : "your "); } /* these ought to be guarded against matching user-supplied name */ (void) strsubst(objbuf, " (being worn)", ""); @@ -579,6 +582,14 @@ steal(struct monst* mtmp, char* objnambuf) if (otmp == uball && uchain != NULL) item = uchain; /* yields a more accurate 'takes off' message */ worn_item_removal(mtmp, item); + /* if we switched from uball to uchain for the preface message, + then unpunish() took place and both those pointers are now Null, + with 'item' a stale pointer to freed chain; the ball is still + present though and 'otmp' is still valid; if uball was also + wielded or quivered, the corresponding weapon pointer hasn't + been cleared yet; do that, with no preface message this time */ + if ((otmp->owornmask & W_WEAPONS) != 0L) + remove_worn_item(otmp, FALSE); } /* do this before removing it from inventory */ @@ -599,9 +610,7 @@ steal(struct monst* mtmp, char* objnambuf) if (iflags.last_msg == PLNMSG_MON_TAKES_OFF_ITEM && mtmp->data->mlet == S_NYMPH) ++named; - urgent_pline("%s%s stole %s.", named ? "She" : Monnambuf, - (was_punished && !Punished) ? " removed your chain and" : "", - doname(otmp)); + urgent_pline("%s stole %s.", named ? "She" : Monnambuf, doname(otmp)); (void) encumber_msg(); could_petrify = (otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm]));