diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 835d4f18a..ccb4a09c9 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -194,6 +194,9 @@ if normal game save file is restored via `nethack -X', restore in normal mode--with save file deletion--and require confirmation ala 'X' command to make deferred switch into explore mode stethoscope applied to hiding mimic will bring it out of hiding +rephrase " evades your grasp" message if artifact is already held +artifacts which subsequently evade your grasp/control after already being + worn or wielded become unworn/unwielded Platform- and/or Interface-Specific Fixes diff --git a/include/extern.h b/include/extern.h index 6c1964002..99357a47d 100644 --- a/include/extern.h +++ b/include/extern.h @@ -84,6 +84,7 @@ E boolean FDECL(artifact_has_invprop, (struct obj *,UCHAR_P)); E long FDECL(arti_cost, (struct obj *)); E struct obj *FDECL(what_gives, (long *)); E void FDECL(Sting_effects, (int)); +E int FDECL(retouch_object, (struct obj **,BOOLEAN_P)); /* ### attrib.c ### */ diff --git a/src/apply.c b/src/apply.c index b899937f7..3bb57f08c 100644 --- a/src/apply.c +++ b/src/apply.c @@ -2974,7 +2974,7 @@ doapply() obj = getobj(class_list, "use or apply"); if(!obj) return 0; - if (obj->oartifact && !touch_artifact(obj, &youmonst)) + if (!retouch_object(&obj, FALSE)) return 1; /* evading your grasp costs a turn; just be grateful that you don't drop it as well */ diff --git a/src/artifact.c b/src/artifact.c index b0d3d610e..c38098f80 100644 --- a/src/artifact.c +++ b/src/artifact.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)artifact.c 3.5 2006/06/08 */ +/* SCCS Id: @(#)artifact.c 3.5 2007/03/05 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -559,7 +559,12 @@ touch_artifact(obj,mon) /* can pick it up unless you're totally non-synch'd with the artifact */ if (badclass && badalign && self_willed) { - if (yours) pline("%s your grasp!", Tobjnam(obj, "evade")); + if (yours) { + if (obj->where != OBJ_INVENT) + pline("%s your grasp!", Tobjnam(obj, "evade")); + else + pline("%s beyond your control!", Tobjnam(obj, "are")); + } return 0; } @@ -1200,11 +1205,11 @@ static NEARDATA const char invoke_types[] = { ALL_CLASSES, 0 }; int doinvoke() { - register struct obj *obj; + struct obj *obj; obj = getobj(invoke_types, "invoke"); if (!obj) return 0; - if (obj->oartifact && !touch_artifact(obj, &youmonst)) return 1; + if (!retouch_object(&obj, FALSE)) return 1; return arti_invoke(obj); } @@ -1596,4 +1601,52 @@ int orc_count; } } +/* called when hero is wielding/applying/invoking a carried item, or + after undergoing a transformation (alignment change, lycanthropy) + which might affect item access */ +int +retouch_object(objp, loseit) +struct obj **objp; /* might be destroyed or unintentionally dropped */ +boolean loseit; /* whether to drop it if hero can longer touch it */ +{ + struct obj *obj = *objp; + + if (touch_artifact(obj, &youmonst)) { + /* nothing to do if hero can successfully handle this object */ + if (!(objects[obj->otyp].oc_material == SILVER && + (u.ulycn >= LOW_PM || hates_silver(youmonst.data)))) + return 1; + /* we didn't get " evades your grasp" message; give alt message */ + You_cant("handle %s anymore!", thesimpleoname(obj)); + } + + /* removing a worn item might result in loss of levitation, + dropping the hero onto a polymorph trap or into water or + lava and potentially dropping or destroying the item */ + if (obj->owornmask) { + struct obj *otmp; + + remove_worn_item(obj, FALSE); + for (otmp = invent; otmp; otmp = otmp->nobj) + if (otmp == obj) break; + if (!otmp) *objp = obj = 0; + } + + /* if we still have it and caller wants us to drop it, do so now */ + if (loseit && obj) { + if (Levitation) { + freeinv(obj); + hitfloor(obj); + } else { + /* dropx gives a message iff item lands on an altar */ + if (!IS_ALTAR(levl[u.ux][u.uy].typ)) + pline("%s to the %s.", + Tobjnam(obj, "drop"), surface(u.ux, u.uy)); + dropx(obj); + } + *objp = obj = 0; /* no longer in inventory */ + } + return 0; +} + /*artifact.c*/ diff --git a/src/eat.c b/src/eat.c index 781f028dc..d67cf1da8 100644 --- a/src/eat.c +++ b/src/eat.c @@ -1152,11 +1152,9 @@ register int pm; break; } - if (catch_lycanthropy && defends(AD_WERE, uwep)) { - if (!touch_artifact(uwep, &youmonst)) { - dropx(uwep); - uwepgone(); - } + if (catch_lycanthropy) { + if (u.twoweap) (void)retouch_object(&uswapwep, TRUE); + if (uwep) (void)retouch_object(&uwep, TRUE); } return; @@ -2250,7 +2248,7 @@ struct obj *otmp; int doeat() /* generic "eat" command funtion (see cmd.c) */ { - register struct obj *otmp; + struct obj *otmp; int basenutrit; /* nutrition of full item */ boolean dont_start = FALSE, nodelicious = FALSE; @@ -2276,7 +2274,8 @@ doeat() /* generic "eat" command funtion (see cmd.c) */ * mails, players who polymorph back to human in the middle of their * metallic meal, etc.... */ - if (otmp->oartifact && !touch_artifact(otmp, &youmonst)) { + if (!(carried(otmp) ? retouch_object(&otmp, FALSE) : + touch_artifact(otmp, &youmonst))) { return 1; } else if (!is_edible(otmp)) { You("cannot eat that!"); diff --git a/src/mhitu.c b/src/mhitu.c index 29dc2b101..96eed6609 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mhitu.c 3.5 2006/08/07 */ +/* SCCS Id: @(#)mhitu.c 3.5 2007/03/09 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1230,6 +1230,8 @@ dopois: You_feel("feverish."); exercise(A_CON, FALSE); u.ulycn = monsndx(mdat); + if (u.twoweap) (void)retouch_object(&uswapwep, TRUE); + if (uwep) (void)retouch_object(&uwep, TRUE); } break; case AD_SGLD: diff --git a/src/wield.c b/src/wield.c index c0ac03192..0c5f9708f 100644 --- a/src/wield.c +++ b/src/wield.c @@ -150,11 +150,11 @@ struct obj *wep; } else if (wep->otyp == CORPSE && cant_wield_corpse(wep)) { /* hero must have been life-saved to get here; use a turn */ res++; /* corpse won't be wielded */ - } else if (uarms && bimanual(wep)) + } else if (uarms && bimanual(wep)) { You("cannot wield a two-handed %s while wearing a shield.", is_sword(wep) ? "sword" : wep->otyp == BATTLE_AXE ? "axe" : "weapon"); - else if (wep->oartifact && !touch_artifact(wep, &youmonst)) { + } else if (!retouch_object(&wep, FALSE)) { res++; /* takes a turn even though it doesn't get wielded */ } else { /* Weapon WILL be wielded after this point */