From b73d45fd66270fcadc2832bc5af894689f92063b Mon Sep 17 00:00:00 2001 From: PatR Date: Mon, 26 Feb 2018 11:18:29 -0800 Subject: [PATCH] throw-and-return for aklys The comment I added to data.base--to explain that despite what the short description says, an aklys wouldn't return to sender after being thrown--was bugging me, so I've made aklyses behave like Mjollnir. If thrown when wielded as primary weapon, it will usually return and usually be re-wielded. I also added a new message when either thrown Mjollnir or thrown aklys is expected to return and fails to do so. Most of the diff to dothrow.c is a change in indentation level. The amount of code needed was quite small. Autopickup for thrown Mjollnir which had failed to return was putting it into the quiver slot if that was empty. Note quite an outright bug, but it started wielded and can't be thrown if quivered, so exclude it from the stuff that will auto-fill the quiver slot when added to invent (post-3.6.0 issue). --- dat/data.base | 2 - doc/fixes36.1 | 5 +++ src/dothrow.c | 101 ++++++++++++++++++++++++++++++-------------------- src/invent.c | 7 +++- 4 files changed, 71 insertions(+), 44 deletions(-) diff --git a/dat/data.base b/dat/data.base index 2cef03af0..848f3112a 100644 --- a/dat/data.base +++ b/dat/data.base @@ -59,8 +59,6 @@ thonged club it to be drawn back to the wielder after having been thrown. It should not be confused with the atlatl, which is a device used to throw spears for longer distances. - - (NetHack's "aklys" is just a club and won't return if thrown.) ~agate ring agate* Translucent, cryptocrystalline variety of quartz and a subvariety diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 5a85f7f7a..62dcedaeb 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -595,6 +595,8 @@ unix: fix for freeing MAIL also introduced a memory leak whenever new mail when clairvoyance lets you move the cursor to examine the map (if it occurs when engulfed or underwater or when blessed clairvoyance finds a monster), the "for instructions type '?'" prompt could be confusing +prevent Mjollnir from being auto-quivered if it's been thrown without return + and then picked back up while quiver slot is empty Platform- and/or Interface-Specific Fixes @@ -785,6 +787,9 @@ change #adjust's behavior when collecting compatible stacks; that used to a prayer result which results in uncursing some or all of the hero's items won't uncurse a worn helm of opposite alignment since that would facilitate the hero switching to another god by taking it off +wielded aklys behaves like Mjollnir when thrown--it usually returns; unlike + Mjollnir, it isn't limited to Valkyries or need gauntlets of power + (so far, hero-only; an aklys won't return if thrown by a monster) Platform- and/or Interface-Specific New Features diff --git a/src/dothrow.c b/src/dothrow.c index 0b1539454..0c72002ee 100644 --- a/src/dothrow.c +++ b/src/dothrow.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 dothrow.c $NHDT-Date: 1502243899 2017/08/09 01:58:19 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.125 $ */ +/* NetHack 3.6 dothrow.c $NHDT-Date: 1519672703 2018/02/26 19:18:23 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.130 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1068,8 +1068,7 @@ void throwit(obj, wep_mask, twoweap) struct obj *obj; long wep_mask; /* used to re-equip returning boomerang */ -boolean - twoweap; /* used to restore twoweapon mode if wielded weapon returns */ +boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */ { register struct monst *mon; register int range, urange; @@ -1120,7 +1119,11 @@ boolean bhitpos.x = mon->mx; bhitpos.y = mon->my; } else if (u.dz) { - if (u.dz < 0 && Role_if(PM_VALKYRIE) && obj->oartifact == ART_MJOLLNIR + if (u.dz < 0 + /* Mjnollnir must we wielded to be thrown--caller verifies this; + aklys must we wielded as primary to return when thrown */ + && ((Role_if(PM_VALKYRIE) && obj->oartifact == ART_MJOLLNIR) + || (obj->otyp == AKLYS && (wep_mask & W_WEP) != 0)) && !impaired) { pline("%s the %s and returns to your hand!", Tobjnam(obj, "hit"), ceiling(u.ux, u.uy)); @@ -1253,47 +1256,63 @@ boolean (void) mpickobj(u.ustuck, obj); thrownobj = (struct obj *) 0; } else { - /* the code following might become part of dropy() */ - if (obj->oartifact == ART_MJOLLNIR && Role_if(PM_VALKYRIE) - && rn2(100)) { - /* we must be wearing Gauntlets of Power to get here */ - sho_obj_return_to_u(obj); /* display its flight */ + /* Mjnollnir must we wielded to be thrown--caller verifies this; + aklys must we wielded as primary to return when thrown */ + if ((obj->oartifact == ART_MJOLLNIR && Role_if(PM_VALKYRIE)) + || (obj->otyp == AKLYS && (wep_mask & W_WEP) != 0)) { + if (rn2(100)) { + sho_obj_return_to_u(obj); /* display its flight */ - if (!impaired && rn2(100)) { - pline("%s to your hand!", Tobjnam(obj, "return")); - obj = addinv(obj); - (void) encumber_msg(); - setuwep(obj); - u.twoweap = twoweap; - if (cansee(bhitpos.x, bhitpos.y)) - newsym(bhitpos.x, bhitpos.y); - } else { - int dmg = rn2(2); - if (!dmg) { - pline(Blind ? "%s lands %s your %s." - : "%s back to you, landing %s your %s.", - Blind ? Something : Tobjnam(obj, "return"), - Levitation ? "beneath" : "at", - makeplural(body_part(FOOT))); + if (!impaired && rn2(100)) { + pline("%s to your hand!", Tobjnam(obj, "return")); + obj = addinv(obj); + (void) encumber_msg(); + setuwep(obj); + u.twoweap = twoweap; + if (cansee(bhitpos.x, bhitpos.y)) + newsym(bhitpos.x, bhitpos.y); } else { - dmg += rnd(3); - pline(Blind ? "%s your %s!" - : "%s back toward you, hitting your %s!", - Tobjnam(obj, Blind ? "hit" : "fly"), - body_part(ARM)); - (void) artifact_hit((struct monst *) 0, &youmonst, obj, - &dmg, 0); - losehp(Maybe_Half_Phys(dmg), killer_xname(obj), - KILLED_BY); + int dmg = rn2(2); + + if (!dmg) { + pline(Blind ? "%s lands %s your %s." + : "%s back to you, landing %s your %s.", + Blind ? Something : Tobjnam(obj, "return"), + Levitation ? "beneath" : "at", + makeplural(body_part(FOOT))); + } else { + dmg += rnd(3); + pline(Blind ? "%s your %s!" + : "%s back toward you, hitting your %s!", + Tobjnam(obj, Blind ? "hit" : "fly"), + body_part(ARM)); + if (obj->oartifact) + (void) artifact_hit((struct monst *) 0, &youmonst, + obj, &dmg, 0); + losehp(Maybe_Half_Phys(dmg), killer_xname(obj), + KILLED_BY); + } + if (ship_object(obj, u.ux, u.uy, FALSE)) { + thrownobj = (struct obj *) 0; + return; + } + dropy(obj); } - if (ship_object(obj, u.ux, u.uy, FALSE)) { - thrownobj = (struct obj *) 0; - return; - } - dropy(obj); + thrownobj = (struct obj *) 0; + return; + } else { + /* when this location is stepped on, the weapon will be + auto-picked up due to 'obj->was_thrown' of 1; + addinv() prevents thrown Mjollnir from being placed + into the quiver slot, but an aklys will end up there if + that slot is empty at the time; since hero will need to + explicitly rewield the weapon to get throw-and-return + capability back anyway, quivered or not shouldn't matter */ + pline("%s fails to return!", + upstart(obj->oartifact ? ONAME(obj) + : thesimpleoname(obj))); + /* continue with placing 'obj' at target location */ } - thrownobj = (struct obj *) 0; - return; } if (!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ) && breaktest(obj)) { diff --git a/src/invent.c b/src/invent.c index 828a947df..1cd0cdd1a 100644 --- a/src/invent.c +++ b/src/invent.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 invent.c $NHDT-Date: 1518053384 2018/02/08 01:29:44 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.224 $ */ +/* NetHack 3.6 invent.c $NHDT-Date: 1519672703 2018/02/26 19:18:23 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.225 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -598,6 +598,11 @@ struct obj *obj; /* fill empty quiver if obj was thrown */ if (flags.pickup_thrown && !uquiver && obj_was_thrown + /* if Mjollnir is thrown and fails to return, we want to + auto-pick it when we move to its spot, but not into quiver; + aklyses behave like Mjollnir when thrown while wielded, but + we lack sufficient information here make them exceptions */ + && obj->oartifact != ART_MJOLLNIR && (throwing_weapon(obj) || is_ammo(obj))) setuqwep(obj); added: