polymorphing worn items (trunk only)
From a bug report. That's hard to fix in the general case because armor and tools might not fit back into the same equipment slot, but most other types of worn items can be re-worn after being transformed. This makes any transformed worn item stay worn if it is wearable in the same slot.
This commit is contained in:
@@ -172,6 +172,7 @@ shops now claim ownership of items created by using an unpaid horn of plenty
|
||||
shopkeepers shouldn't refer to non-male character as "cad"
|
||||
tweak levitation timeout if trap is being triggered on same turn it is to end
|
||||
if Rider corpse revival fails, usually try again later instead of rotting away
|
||||
worn item transformed by polymorph remains worn if feasible
|
||||
|
||||
|
||||
Platform- and/or Interface-Specific Fixes
|
||||
|
||||
@@ -393,7 +393,7 @@ E int FDECL(select_off, (struct obj *));
|
||||
E int NDECL(take_off);
|
||||
#endif
|
||||
E void FDECL(off_msg, (struct obj *));
|
||||
E void NDECL(set_wear);
|
||||
E void FDECL(set_wear, (struct obj *));
|
||||
E boolean FDECL(donning, (struct obj *));
|
||||
E void NDECL(cancel_don);
|
||||
E int NDECL(Armor_off);
|
||||
@@ -2538,6 +2538,7 @@ E boolean FDECL(worm_known, (struct monst *));
|
||||
|
||||
E void FDECL(setworn, (struct obj *,long));
|
||||
E void FDECL(setnotworn, (struct obj *));
|
||||
E long FDECL(wearslot, (struct obj *));
|
||||
E void FDECL(mon_set_minvis, (struct monst *));
|
||||
E void FDECL(mon_adjust_speed, (struct monst *,int,struct obj *));
|
||||
E void FDECL(update_mon_intrinsics,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* SCCS Id: @(#)allmain.c 3.5 2006/04/01 */
|
||||
/* SCCS Id: @(#)allmain.c 3.5 2006/11/27 */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -53,9 +53,9 @@ boolean resuming;
|
||||
|
||||
if (!resuming) { /* new game */
|
||||
context.rndencode = rnd(9000);
|
||||
set_wear(); /* handle side-effects of worn starting gear */
|
||||
set_wear((struct obj *)0); /* for side-effects of worn starting gear */
|
||||
(void) pickup(1); /* autopickup at initial location */
|
||||
} else {
|
||||
} else { /* restore old game */
|
||||
update_inventory(); /* for perm_invent */
|
||||
read_engr_at(u.ux, u.uy); /* subset of pickup() */
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* SCCS Id: @(#)do_wear.c 3.5 2006/06/25 */
|
||||
/* SCCS Id: @(#)do_wear.c 3.5 2006/11/27 */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -982,19 +982,26 @@ register struct obj *otmp;
|
||||
}
|
||||
}
|
||||
|
||||
/* called in main to set intrinsics of worn start-up items */
|
||||
/* called in moveloop()'s prologue to set side-effects of worn start-up items;
|
||||
also used by poly_obj() when a worn item gets transformed */
|
||||
void
|
||||
set_wear()
|
||||
set_wear(obj)
|
||||
struct obj *obj; /* if null, do all worn items; otherwise just obj itself */
|
||||
{
|
||||
if (!obj ? ublindf != 0 : (obj == ublindf)) (void) Blindf_on(ublindf);
|
||||
if (!obj ? uright != 0 : (obj == uright)) (void) Ring_on(uright);
|
||||
if (!obj ? uleft != 0 : (obj == uleft)) (void) Ring_on(uleft);
|
||||
if (!obj ? uamul != 0 : (obj == uamul)) (void) Amulet_on();
|
||||
|
||||
#ifdef TOURIST
|
||||
if (uarmu) (void) Shirt_on();
|
||||
if (!obj ? uarmu != 0 : (obj == uarmu)) (void) Shirt_on();
|
||||
#endif
|
||||
if (uarm) (void) Armor_on();
|
||||
if (uarmc) (void) Cloak_on();
|
||||
if (uarmf) (void) Boots_on();
|
||||
if (uarmg) (void) Gloves_on();
|
||||
if (uarmh) (void) Helmet_on();
|
||||
if (uarms) (void) Shield_on();
|
||||
if (!obj ? uarm != 0 : (obj == uarm)) (void) Armor_on();
|
||||
if (!obj ? uarmc != 0 : (obj == uarmc)) (void) Cloak_on();
|
||||
if (!obj ? uarmf != 0 : (obj == uarmf)) (void) Boots_on();
|
||||
if (!obj ? uarmg != 0 : (obj == uarmg)) (void) Gloves_on();
|
||||
if (!obj ? uarmh != 0 : (obj == uarmh)) (void) Helmet_on();
|
||||
if (!obj ? uarms != 0 : (obj == uarms)) (void) Shield_on();
|
||||
}
|
||||
|
||||
/* check whether the target object is currently being put on (or taken off) */
|
||||
|
||||
64
src/worn.c
64
src/worn.c
@@ -1,4 +1,4 @@
|
||||
/* SCCS Id: @(#)worn.c 3.5 2005/04/06 */
|
||||
/* SCCS Id: @(#)worn.c 3.5 2005/11/27 */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -128,6 +128,68 @@ register struct obj *obj;
|
||||
update_inventory();
|
||||
}
|
||||
|
||||
/* return a bitmask of the equipment slot(s) a given item might be worn in */
|
||||
long
|
||||
wearslot(obj)
|
||||
struct obj *obj;
|
||||
{
|
||||
int otyp = obj->otyp;
|
||||
/* practically any item can be wielded or quivered; it's up to
|
||||
our caller to handle such things--we assume "normal" usage */
|
||||
long res = 0L; /* default: can't be worn anywhere */
|
||||
|
||||
switch (obj->oclass) {
|
||||
case AMULET_CLASS:
|
||||
res = W_AMUL; /* WORN_AMUL */
|
||||
break;
|
||||
case RING_CLASS:
|
||||
res = W_RINGL|W_RINGR; /* W_RING, BOTH_SIDES */
|
||||
break;
|
||||
case ARMOR_CLASS:
|
||||
switch (objects[otyp].oc_armcat) {
|
||||
case ARM_SUIT: res = W_ARM; break; /* WORN_ARMOR */
|
||||
case ARM_SHIELD: res = W_ARMS; break; /* WORN_SHIELD */
|
||||
case ARM_HELM: res = W_ARMH; break; /* WORN_HELMET */
|
||||
case ARM_GLOVES: res = W_ARMG; break; /* WORN_GLOVES */
|
||||
case ARM_BOOTS: res = W_ARMF; break; /* WORN_BOOTS */
|
||||
case ARM_CLOAK: res = W_ARMC; break; /* WORN_CLOAK */
|
||||
#ifdef TOURIST
|
||||
case ARM_SHIRT: res = W_ARMU; break; /* WORN_SHIRT */
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case WEAPON_CLASS:
|
||||
res = W_WEP|W_SWAPWEP;
|
||||
if (objects[otyp].oc_merge) res |= W_QUIVER;
|
||||
break;
|
||||
case TOOL_CLASS:
|
||||
if (otyp == BLINDFOLD || otyp == TOWEL || otyp == LENSES)
|
||||
res = W_TOOL; /* WORN_BLINDF */
|
||||
else if (is_weptool(obj) || otyp == TIN_OPENER)
|
||||
res = W_WEP|W_SWAPWEP;
|
||||
#ifdef STEED
|
||||
else if (otyp == SADDLE)
|
||||
res = W_SADDLE;
|
||||
#endif
|
||||
break;
|
||||
case FOOD_CLASS:
|
||||
if (obj->otyp == MEAT_RING) res = W_RINGL|W_RINGR;
|
||||
break;
|
||||
case GEM_CLASS:
|
||||
res = W_QUIVER;
|
||||
break;
|
||||
case BALL_CLASS:
|
||||
res = W_BALL;
|
||||
break;
|
||||
case CHAIN_CLASS:
|
||||
res = W_CHAIN;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
mon_set_minvis(mon)
|
||||
struct monst *mon;
|
||||
|
||||
59
src/zap.c
59
src/zap.c
@@ -1,4 +1,4 @@
|
||||
/* SCCS Id: @(#)zap.c 3.5 2006/05/09 */
|
||||
/* SCCS Id: @(#)zap.c 3.5 2006/11/27 */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -1434,37 +1434,38 @@ poly_obj(obj, id)
|
||||
/* update the weight */
|
||||
otmp->owt = weight(otmp);
|
||||
|
||||
/* for now, take off worn items being polymorphed */
|
||||
if (obj_location == OBJ_INVENT) {
|
||||
if (id == STRANGE_OBJECT)
|
||||
remove_worn_item(obj, TRUE);
|
||||
else {
|
||||
/* This is called only for stone to flesh. It's a lot simpler
|
||||
* than it otherwise might be. We don't need to check for
|
||||
* special effects when putting them on (no meat objects have
|
||||
* any) and only three worn masks are possible.
|
||||
*/
|
||||
otmp->owornmask = obj->owornmask;
|
||||
remove_worn_item(obj, TRUE);
|
||||
setworn(otmp, otmp->owornmask);
|
||||
if (otmp->owornmask & LEFT_RING)
|
||||
uleft = otmp;
|
||||
if (otmp->owornmask & RIGHT_RING)
|
||||
uright = otmp;
|
||||
if (otmp->owornmask & W_WEP)
|
||||
uwep = otmp;
|
||||
if (otmp->owornmask & W_SWAPWEP)
|
||||
uswapwep = otmp;
|
||||
if (otmp->owornmask & W_QUIVER)
|
||||
uquiver = otmp;
|
||||
goto no_unwear;
|
||||
/* handle polymorph of worn item: stone-to-flesh cast on self can
|
||||
affect multiple objects at once, but their new forms won't
|
||||
produce any side-effects; a single worn item dipped into potion
|
||||
of polymorph can produce side-effects but those won't yield out
|
||||
of sequence messages because current polymorph is finished */
|
||||
if (obj_location == OBJ_INVENT && obj->owornmask) {
|
||||
long old_wornmask = obj->owornmask & ~(W_ART|W_ARTI),
|
||||
new_wornmask = wearslot(otmp);
|
||||
boolean was_twohanded = bimanual(obj),
|
||||
was_twoweap = u.twoweap;
|
||||
|
||||
remove_worn_item(obj, TRUE);
|
||||
/* if the new form can be worn in the same slot, make it so
|
||||
[possible extension: if it could be worn in some other
|
||||
slot which is currently unfilled, wear it there instead] */
|
||||
if ((old_wornmask & W_QUIVER) != 0L) {
|
||||
setuqwep(otmp);
|
||||
} else if ((old_wornmask & W_SWAPWEP) != 0L) {
|
||||
if (was_twohanded || !bimanual(otmp))
|
||||
setuswapwep(otmp);
|
||||
if (was_twoweap && uswapwep) u.twoweap = TRUE;
|
||||
} else if ((old_wornmask & W_WEP) != 0L) {
|
||||
if (was_twohanded || !bimanual(otmp) || !uarms)
|
||||
setuwep(otmp);
|
||||
if (was_twoweap && uwep && !bimanual(uwep)) u.twoweap = TRUE;
|
||||
} else if ((old_wornmask & new_wornmask) != 0L) {
|
||||
new_wornmask &= old_wornmask;
|
||||
setworn(otmp, new_wornmask);
|
||||
set_wear(otmp); /* Armor_on() for side-effects */
|
||||
}
|
||||
}
|
||||
|
||||
/* preserve the mask in case being used by something else */
|
||||
otmp->owornmask = obj->owornmask;
|
||||
no_unwear:
|
||||
|
||||
/* ** we are now done adjusting the object ** */
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user