breaking wielded fragile item against iron bars
Reported by entrez, wielding something fragile (potion of acid perhaps), and using F to smash it against iron bars called breaktest() directly, then a second time indirectly through hero_breaks() via hit_bars(). There is a random chance to resist breaking (99% for artifacts, 1% for other items) so breaktest() might say that something will break on the first call and that it will not break on the second call, or vice versa. That could remove uwep from inventory then leave it in limbo without destroying it, or destroy uwep without removing it from inventory first triggering impossible "obfree: deleting worn obj".
This commit is contained in:
@@ -550,7 +550,7 @@ hitfloor(struct obj *obj,
|
||||
pline("%s %s the %s.", Doname2(obj), otense(obj, "hit"), surf);
|
||||
}
|
||||
|
||||
if (hero_breaks(obj, u.ux, u.uy, TRUE))
|
||||
if (hero_breaks(obj, u.ux, u.uy, BRK_FROM_INV))
|
||||
return;
|
||||
if (ship_object(obj, u.ux, u.uy, FALSE))
|
||||
return;
|
||||
@@ -2053,13 +2053,20 @@ gem_accept(register struct monst *mon, register struct obj *obj)
|
||||
int
|
||||
hero_breaks(struct obj *obj,
|
||||
xchar x, xchar y, /* object location (ox, oy may not be right) */
|
||||
boolean from_invent) /* thrown or dropped by player;
|
||||
maybe on shop bill */
|
||||
unsigned breakflags)
|
||||
{
|
||||
boolean in_view = Blind ? FALSE : (from_invent || cansee(x, y));
|
||||
/* from_invent: thrown or dropped by player; maybe on shop bill;
|
||||
by-hero is implicit so callers don't need to specify BRK_BY_HERO */
|
||||
boolean from_invent = (breakflags & BRK_FROM_INV) != 0,
|
||||
in_view = Blind ? FALSE : (from_invent || cansee(x, y));
|
||||
unsigned brk = (breakflags & BRK_KNOWN_OUTCOME);
|
||||
|
||||
if (!breaktest(obj))
|
||||
/* only call breaktest if caller hasn't already specified the outcome */
|
||||
if (!brk)
|
||||
brk = breaktest(obj) ? BRK_KNOWN2BREAK : BRK_KNOWN2NOTBREAK;
|
||||
if (brk == BRK_KNOWN2NOTBREAK)
|
||||
return 0;
|
||||
|
||||
breakmsg(obj, in_view);
|
||||
breakobj(obj, x, y, TRUE, from_invent);
|
||||
return 1;
|
||||
|
||||
Reference in New Issue
Block a user