diff --git a/include/extern.h b/include/extern.h index 5c84a82a5..ff3b74503 100644 --- a/include/extern.h +++ b/include/extern.h @@ -3101,6 +3101,8 @@ extern void bypass_objlist(struct obj *, boolean); extern struct obj *nxt_unbypassed_obj(struct obj *); extern struct obj *nxt_unbypassed_loot(Loot *, struct obj *); extern int racial_exception(struct monst *, struct obj *); +extern void extract_from_minvent(struct monst *, struct obj *, boolean, + boolean); /* ### write.c ### */ diff --git a/src/mkobj.c b/src/mkobj.c index e57d7b40e..9cae22145 100644 --- a/src/mkobj.c +++ b/src/mkobj.c @@ -1878,21 +1878,11 @@ remove_object(struct obj* otmp) void discard_minvent(struct monst* mtmp, boolean uncreate_artifacts) { - struct obj *otmp, *mwep = MON_WEP(mtmp); - boolean keeping_mon = !DEADMONSTER(mtmp); + struct obj *otmp; while ((otmp = mtmp->minvent) != 0) { /* this has now become very similar to m_useupall()... */ - obj_extract_self(otmp); - if (otmp->owornmask) { - if (keeping_mon) { - if (otmp == mwep) - mwepgone(mtmp), mwep = 0; - mtmp->misc_worn_check &= ~otmp->owornmask; - update_mon_intrinsics(mtmp, otmp, FALSE, TRUE); - } - otmp->owornmask = 0L; /* obfree() expects this */ - } + extract_from_minvent(mtmp, otmp, TRUE, TRUE); if (uncreate_artifacts && otmp->oartifact) artifact_exists(otmp, safe_oname(otmp), FALSE); obfree(otmp, (struct obj *) 0); /* dealloc_obj() isn't sufficient */ diff --git a/src/mon.c b/src/mon.c index 9932594bd..782d68a7d 100644 --- a/src/mon.c +++ b/src/mon.c @@ -2597,13 +2597,7 @@ monstone(struct monst* mdef) oldminvent = 0; /* some objects may end up outside the statue */ while ((obj = mdef->minvent) != 0) { - obj_extract_self(obj); - if (obj->owornmask) - update_mon_intrinsics(mdef, obj, FALSE, TRUE); - obj_no_longer_held(obj); - if (obj->owornmask & W_WEP) - setmnotwielded(mdef, obj); - obj->owornmask = 0L; + extract_from_minvent(mdef, obj, TRUE, TRUE); if (obj->otyp == BOULDER #if 0 /* monsters don't carry statues */ || (obj->otyp == STATUE diff --git a/src/mthrowu.c b/src/mthrowu.c index 8dd7be626..a4507f4e6 100644 --- a/src/mthrowu.c +++ b/src/mthrowu.c @@ -842,20 +842,11 @@ breamm(struct monst* mtmp, struct attack* mattk, struct monst* mtarg) return MM_HIT; } - - /* remove an entire item from a monster's inventory; destroy that item */ void m_useupall(struct monst* mon, struct obj* obj) { - obj_extract_self(obj); - if (obj->owornmask) { - if (obj == MON_WEP(mon)) - mwepgone(mon); - mon->misc_worn_check &= ~obj->owornmask; - update_mon_intrinsics(mon, obj, FALSE, FALSE); - obj->owornmask = 0L; - } + extract_from_minvent(mon, obj, TRUE, FALSE); obfree(obj, (struct obj *) 0); } diff --git a/src/pickup.c b/src/pickup.c index 6db657dd7..25a860671 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -2104,8 +2104,6 @@ loot_mon(struct monst *mtmp, int *passed_info, boolean *prev_loot) * *prev_loot is set to TRUE if something was actually acquired in here. */ if (mtmp && mtmp != u.usteed && (otmp = which_armor(mtmp, W_SADDLE))) { - long unwornmask; - if (passed_info) *passed_info = 1; Sprintf(qbuf, "Do you want to remove the saddle from %s?", @@ -2123,12 +2121,7 @@ loot_mon(struct monst *mtmp, int *passed_info, boolean *prev_loot) /* the attempt costs you time */ return 1; } - obj_extract_self(otmp); - if ((unwornmask = otmp->owornmask) != 0L) { - mtmp->misc_worn_check &= ~unwornmask; - otmp->owornmask = 0L; - update_mon_intrinsics(mtmp, otmp, FALSE, FALSE); - } + extract_from_minvent(mtmp, otmp, TRUE, FALSE); otmp = hold_another_object(otmp, "You drop %s!", doname(otmp), (const char *) 0); nhUse(otmp); diff --git a/src/steal.c b/src/steal.c index cfd3fcfdf..b5e40329d 100644 --- a/src/steal.c +++ b/src/steal.c @@ -671,27 +671,16 @@ mdrop_obj( boolean verbosely) { int omx = mon->mx, omy = mon->my; - boolean update_mon = FALSE; + boolean unwornmask = obj->owornmask; - if (obj->owornmask) { - /* perform worn item handling if the monster is still alive */ - if (!DEADMONSTER(mon)) { - mon->misc_worn_check &= ~obj->owornmask; - update_mon = TRUE; - - /* don't charge for an owned saddle on dead steed (provided - that the hero is within the same shop at the time) */ - } else if (mon->mtame && (obj->owornmask & W_SADDLE) != 0L - && !obj->unpaid && costly_spot(omx, omy) - /* being at costly_spot guarantees lev->roomno is not 0 */ - && index(in_rooms(u.ux, u.uy, SHOPBASE), - levl[omx][omy].roomno)) { - obj->no_charge = 1; - } - /* this should be done even if the monster has died */ - if (obj->owornmask & W_WEP) - setmnotwielded(mon, obj); - obj->owornmask = 0L; + extract_from_minvent(mon, obj, FALSE, TRUE); + /* don't charge for an owned saddle on dead steed (provided + that the hero is within the same shop at the time) */ + if (unwornmask && mon->mtame && (unwornmask & W_SADDLE) != 0L + && !obj->unpaid && costly_spot(omx, omy) + /* being at costly_spot guarantees lev->roomno is not 0 */ + && index(in_rooms(u.ux, u.uy, SHOPBASE), levl[omx][omy].roomno)) { + obj->no_charge = 1; } /* obj_no_longer_held(obj); -- done by place_object */ if (verbosely && cansee(omx, omy)) @@ -701,8 +690,9 @@ mdrop_obj( stackobj(obj); } /* do this last, after placing obj on floor; removing steed's saddle - throws rider, possibly inflicting fatal damage and producing bones */ - if (update_mon) + throws rider, possibly inflicting fatal damage and producing bones; this + is why we had to call extract_from_minvent() with do_intrinsics=FALSE */ + if (!DEADMONSTER(mon) && unwornmask) update_mon_intrinsics(mon, obj, FALSE, TRUE); } @@ -721,16 +711,10 @@ mdrop_special_objs(struct monst* mon) current role's quest artifact is rescued too--quest artifacts for the other roles are not */ if (obj_resists(obj, 0, 0) || is_quest_artifact(obj)) { - obj_extract_self(obj); if (mon->mx) { mdrop_obj(mon, obj, FALSE); } else { /* migrating monster not on map */ - if (obj->owornmask) { - mon->misc_worn_check &= ~obj->owornmask; - if (obj->owornmask & W_WEP) - setmnotwielded(mon, obj); - obj->owornmask = 0L; - } + extract_from_minvent(mon, obj, TRUE, TRUE); rloco(obj); } } @@ -757,7 +741,6 @@ relobj( } /* isgd && has gold */ while ((otmp = (is_pet ? droppables(mtmp) : mtmp->minvent)) != 0) { - obj_extract_self(otmp); mdrop_obj(mtmp, otmp, is_pet && flags.verbose); } diff --git a/src/uhitm.c b/src/uhitm.c index 3456259f2..756929f24 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -1626,22 +1626,14 @@ steal_it(struct monst *mdef, struct attack *mattk) mpickobj(mdef, gold), gold = 0; if (!Upolyd) break; /* no longer have ability to steal */ + unwornmask = otmp->owornmask; /* take the object away from the monster */ - obj_extract_self(otmp); - if ((unwornmask = otmp->owornmask) != 0L) { - mdef->misc_worn_check &= ~unwornmask; - if (otmp->owornmask & W_WEP) - setmnotwielded(mdef, otmp); - otmp->owornmask = 0L; - update_mon_intrinsics(mdef, otmp, FALSE, FALSE); - /* give monster a chance to wear other equipment on its next - move instead of waiting until it picks something up */ - mdef->misc_worn_check |= I_SPECIAL; - - if (otmp == ustealo) /* special message for final item */ - pline("%s finishes taking off %s suit.", Monnam(mdef), - mhis(mdef)); - } + extract_from_minvent(mdef, otmp, TRUE, FALSE); + /* special message for final item; no need to check owornmask because + * ustealo is only set on objects with (owornmask & W_ARM) */ + if (otmp == ustealo) + pline("%s finishes taking off %s suit.", Monnam(mdef), + mhis(mdef)); /* give the object to the character */ otmp = hold_another_object(otmp, "You snatched but dropped %s.", doname(otmp), "You steal: "); @@ -3917,17 +3909,7 @@ mhitm_ad_sedu(struct monst *magr, struct attack *mattk, struct monst *mdef, if (u.usteed == mdef && obj == which_armor(mdef, W_SADDLE)) /* "You can no longer ride ." */ dismount_steed(DISMOUNT_POLY); - obj_extract_self(obj); - if (obj->owornmask) { - mdef->misc_worn_check &= ~obj->owornmask; - if (obj->owornmask & W_WEP) - mwepgone(mdef); - obj->owornmask = 0L; - update_mon_intrinsics(mdef, obj, FALSE, FALSE); - /* give monster a chance to wear other equipment on its next - move instead of waiting until it picks something up */ - mdef->misc_worn_check |= I_SPECIAL; - } + extract_from_minvent(mdef, obj, TRUE, FALSE); /* add_to_minv() might free 'obj' [if it merges] */ if (g.vis) Strcpy(onambuf, doname(obj)); diff --git a/src/worn.c b/src/worn.c index 0b35ad492..53c9b951c 100644 --- a/src/worn.c +++ b/src/worn.c @@ -709,12 +709,7 @@ which_armor(struct monst *mon, long flag) static void m_lose_armor(struct monst *mon, struct obj *obj) { - mon->misc_worn_check &= ~obj->owornmask; - if (obj->owornmask) - update_mon_intrinsics(mon, obj, FALSE, FALSE); - obj->owornmask = 0L; - - obj_extract_self(obj); + extract_from_minvent(mon, obj, TRUE, FALSE); place_object(obj, mon->mx, mon->my); /* call stackobj() if we ever drop anything that can merge */ newsym(mon->mx, mon->my); @@ -1039,4 +1034,39 @@ racial_exception(struct monst *mon, struct obj *obj) return 0; } + +/* Remove an object from a monster's inventory. + * At its core this is just obj_extract_self(), but it also handles any updates + * that needs to happen if the gear is equipped or in some other sort of state + * that needs handling. + * Note that like obj_extract_self(), this leaves obj free. */ +void +extract_from_minvent(struct monst *mon, struct obj *obj, + boolean do_intrinsics, /* whether to call + update_mon_intrinsics */ + boolean silently) /* doesn't affect all possible messages, + just update_mon_intrinsics's */ +{ + long unwornmask = obj->owornmask; + + if (obj->where != OBJ_MINVENT) { + impossible("extract_from_minvent called on object not in minvent"); + return; + } + obj_extract_self(obj); + obj->owornmask = 0L; + if (unwornmask) { + if (!DEADMONSTER(mon) && do_intrinsics) { + update_mon_intrinsics(mon, obj, FALSE, silently); + } + mon->misc_worn_check &= ~unwornmask; + /* give monster a chance to wear other equipment on its next + move instead of waiting until it picks something up */ + mon->misc_worn_check |= I_SPECIAL; + } + obj_no_longer_held(obj); + if (unwornmask & W_WEP) { + mwepgone(mon); /* unwields and sets weapon_check to NEED_WEAPON */ + } +} /*worn.c*/ diff --git a/src/zap.c b/src/zap.c index 67de59d3b..3b210789d 100644 --- a/src/zap.c +++ b/src/zap.c @@ -347,7 +347,6 @@ bhitm(struct monst *mtmp, struct obj *otmp) } else if (canspotmon(mtmp)) { pline("%s falls off.", buf); } - obj_extract_self(obj); mdrop_obj(mtmp, obj, FALSE); } break; @@ -4052,16 +4051,7 @@ disintegrate_mon(struct monst *mon, for (otmp = mon->minvent; otmp; otmp = otmp2) { otmp2 = otmp->nobj; if (!oresist_disintegration(otmp)) { - if (otmp->owornmask) { - /* in case monster's life gets saved */ - mon->misc_worn_check &= ~otmp->owornmask; - if (otmp->owornmask & W_WEP) - setmnotwielded(mon, otmp); - /* also dismounts hero if this object is steed's saddle */ - update_mon_intrinsics(mon, otmp, FALSE, TRUE); - otmp->owornmask = 0L; - } - obj_extract_self(otmp); + extract_from_minvent(mon, otmp, TRUE, TRUE); obfree(otmp, (struct obj *) 0); } }