diff --git a/include/extern.h b/include/extern.h index 2f36c3d74..abf3e410c 100644 --- a/include/extern.h +++ b/include/extern.h @@ -417,6 +417,7 @@ E void FDECL(off_msg, (struct obj *)); E void FDECL(set_wear, (struct obj *)); E boolean FDECL(donning, (struct obj *)); E void NDECL(cancel_don); +E int FDECL(stop_donning, (struct obj *)); E int NDECL(Armor_off); E int NDECL(Armor_gone); E int NDECL(Helmet_off); diff --git a/src/do_wear.c b/src/do_wear.c index 0607b0190..def059815 100644 --- a/src/do_wear.c +++ b/src/do_wear.c @@ -1203,6 +1203,46 @@ cancel_don() context.takeoff.what = 0L; } +/* called by steal() during theft from hero; interrupt donning/doffing */ +int +stop_donning(stolenobj) +struct obj *stolenobj; /* no message if stolenobj is already being doffing */ +{ + char buf[BUFSZ]; + struct obj *otmp; + boolean putting_on; + int result; + + for (otmp = invent; otmp; otmp = otmp->nobj) + if ((otmp->owornmask & W_ARMOR) && donning(otmp)) break; + /* at most one item will pass donning() test at any given time */ + if (!otmp) return 0; + + result = -multi; /* remember this before calling unmul() */ + /* donning() returns True when doffing too */ + putting_on = !(context.takeoff.mask & otmp->owornmask); + /* cancel_don() looks at afternmv; it also serves as cancel_doff() */ + cancel_don(); + /* don't want _on() or _off() being called + by unmul() since the on or off action isn't completing */ + afternmv = 0; + if (putting_on || otmp != stolenobj) + Sprintf(buf, "You stop %s %s.", + putting_on ? "putting on" : "taking off", + thesimpleoname(otmp)); + else + buf[0] = '\0'; /* silently stop doffing stolenobj */ + unmul(buf); + /* while putting on, item becomes worn immediately but side-effects are + deferred until the delay expires; when interrupted, make it unworn + (while taking off, item stays worn until the delay expires; when + interrupted, leave it worn) */ + if (putting_on) + remove_worn_item(otmp, FALSE); + + return result; +} + static NEARDATA const char clothes[] = {ARMOR_CLASS, 0}; static NEARDATA const char accessories[] = {RING_CLASS, AMULET_CLASS, TOOL_CLASS, FOOD_CLASS, 0}; diff --git a/src/mhitu.c b/src/mhitu.c index d36d1eb07..1f379388b 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -2261,6 +2261,9 @@ register struct monst *mon; if (Blind) pline("It caresses you..."); else You_feel("very attracted to %s.", mon_nam(mon)); + /* if in the process of putting armor on or taking armor off, + interrupt that activity now */ + stop_donning((struct obj *)0); /* don't try to take off gloves if cursed weapon blocks them */ if (welded(uwep)) tried_gloves = 1; diff --git a/src/steal.c b/src/steal.c index 64b8deb7b..6016e41a9 100644 --- a/src/steal.c +++ b/src/steal.c @@ -271,7 +271,7 @@ struct monst *mtmp; char *objnambuf; { struct obj *otmp; - int tmp, could_petrify, named = 0, armordelay, retrycnt = 0; + int tmp, could_petrify, armordelay, olddelay, named = 0, retrycnt = 0; boolean monkey_business; /* true iff an animal is doing the thievery */ if (objnambuf) *objnambuf = '\0'; @@ -391,6 +391,9 @@ gotobj: o_unleash(otmp); } + /* stop donning/doffing now so that afternmv won't be clobbered + below; stop_occupation doesn't handle donning/doffing */ + olddelay = stop_donning(otmp); /* you're going to notice the theft... */ stop_occupation(); @@ -404,14 +407,13 @@ gotobj: break; case ARMOR_CLASS: armordelay = objects[otmp->otyp].oc_delay; - /* Stop putting on armor which has been stolen. */ - if (donning(otmp)) { - remove_worn_item(otmp, TRUE); - break; - } else if (monkey_business) { + if (olddelay > 0 && olddelay < armordelay) + armordelay = olddelay; + if (monkey_business) { /* animals usually don't have enough patience to take off items which require extra time */ - if (armordelay >= 1 && rn2(10)) goto cant_take; + if (armordelay >= 1 && !olddelay && rn2(10)) + goto cant_take; remove_worn_item(otmp, TRUE); break; } else {