From: PatR Date: Tue, 18 Feb 2020 11:14:22 +0000 (-0800) Subject: fix #K376 - tipping cap X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=814adb41b8a80a29702620ed321ec89272a381d9;p=nethack fix #K376 - tipping cap Allow #tip to do something if you pick your worn helmet instead of a container. It's mostly just a variation of #chat but probably adds several new bugs.... --- diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 95f64cd44..ad4974740 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.102 $ $NHDT-Date: 1581810078 2020/02/15 23:41:18 $ +$NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.103 $ $NHDT-Date: 1582020640 2020/02/18 10:10:40 $ General Fixes and Modified Features ----------------------------------- @@ -160,6 +160,7 @@ new glyph GLYPH_NOTHING was added so !dark_room has something to be set to now that stone could be mapped to an entirely different symbol added several new status conditions all of which are opt-in except the new cond_grab and cond_lava which are opt-out +tipping your cap might get a response Platform- and/or Interface-Specific New Features diff --git a/include/extern.h b/include/extern.h index 6a344c9fd..7fdfeb039 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1581886855 2020/02/16 21:00:55 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.797 $ */ +/* NetHack 3.6 extern.h $NHDT-Date: 1581985538 2020/02/18 00:25:38 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.798 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2449,6 +2449,7 @@ E void FDECL(yelp, (struct monst *)); E void FDECL(whimper, (struct monst *)); E void FDECL(beg, (struct monst *)); E int NDECL(dotalk); +E int NDECL(tiphat); #ifdef USER_SOUNDS E int FDECL(add_sound_mapping, (const char *)); E void FDECL(play_sound_for_message, (const char *)); diff --git a/src/pickup.c b/src/pickup.c index 8cb4f68de..e86ec2d77 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 pickup.c $NHDT-Date: 1578297247 2020/01/06 07:54:07 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.258 $ */ +/* NetHack 3.6 pickup.c $NHDT-Date: 1581985559 2020/02/18 00:25:59 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.261 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -3171,6 +3171,8 @@ dotip() /* anything not covered yet */ if (cobj->oclass == POTION_CLASS) /* can't pour potions... */ pline_The("%s %s securely sealed.", xname(cobj), otense(cobj, "are")); + else if (uarmh && cobj == uarmh) + return tiphat(); else if (cobj->otyp == STATUE) pline("Nothing interesting happens."); else diff --git a/src/sounds.c b/src/sounds.c index b72003440..0e3b7df89 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 sounds.c $NHDT-Date: 1570844005 2019/10/12 01:33:25 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.83 $ */ +/* NetHack 3.6 sounds.c $NHDT-Date: 1582024315 2020/02/18 11:11:55 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.95 $ */ /* Copyright (c) 1989 Janet Walz, Mike Threepoint */ /* NetHack may be freely redistributed. See license for details. */ @@ -7,6 +7,7 @@ static boolean FDECL(mon_is_gecko, (struct monst *)); static int FDECL(domonnoise, (struct monst *)); static int NDECL(dochat); +static struct monst *FDECL(responsive_mon_at, (int, int)); static int FDECL(mon_in_room, (struct monst *, int)); /* this easily could be a macro, but it might overtax dumb compilers */ @@ -926,15 +927,14 @@ register struct monst *mtmp; break; case MS_SOLDIER: { static const char - *const soldier_foe_msg[3] = - { - "Resistance is useless!", "You're dog meat!", "Surrender!", - }, - *const soldier_pax_msg[3] = { - "What lousy pay we're getting here!", - "The food's not fit for Orcs!", - "My feet hurt, I've been on them all day!", - }; + *const soldier_foe_msg[3] = { + "Resistance is useless!", "You're dog meat!", "Surrender!", + }, + *const soldier_pax_msg[3] = { + "What lousy pay we're getting here!", + "The food's not fit for Orcs!", + "My feet hurt, I've been on them all day!", + }; verbl_msg = mtmp->mpeaceful ? soldier_pax_msg[rn2(3)] : soldier_foe_msg[rn2(3)]; break; @@ -1115,6 +1115,135 @@ dochat() return domonnoise(mtmp); } +/* is there a monster at that can see the hero and react? */ +static struct monst * +responsive_mon_at(x, y) +int x, y; +{ + struct monst *mtmp = isok(x, y) ? m_at(x, y) : 0; + + if (mtmp && (!mtmp->mcanmove || mtmp->msleeping /* immobilized monst */ + || !mtmp->mcansee || !haseyes(mtmp->data) /* blind monst */ + || (Invis && !perceives(mtmp->data)) /* unseen hero */ + || (x != mtmp->mx || y != mtmp->my))) /* worm tail */ + mtmp = (struct monst *) 0; + return mtmp; +} + +/* player chose 'uarmh' for #tip (pickup.c); visual #chat, sort of... */ +int +tiphat() +{ + struct monst *mtmp; + struct obj *otmp; + int x, y, range, glyph, vismon, unseen, statue, res; + + if (!uarmh) /* can't get here from there */ + return 0; + + res = uarmh->bknown ? 0 : 1; + if (cursed(uarmh)) /* "You can't. It is cursed." */ + return res; /* if learned of curse, use a move */ + + /* might choose a position, but dealing with direct lines is simpler */ + if (!getdir("At whom? (in what direction)")) /* bail on ESC */ + return res; /* iffy; now know it's not cursed for sure (since we got + * past prior test) but might have already known that */ + res = 1; /* physical action is going to take place */ + + /* most helmets have a short wear/take-off delay and we could set + 'multi' to account for that, but we'll pretend that no extra time + beyond the current move is necessary */ + You("briefly doff your %s.", helm_simple_name(uarmh)); + + if (!u.dx && !u.dy) { + if (u.usteed && u.dz > 0) { + if (!u.usteed->mcanmove || u.usteed->msleeping) + pline("%s doesn't notice.", Monnam(u.usteed)); + else + (void) domonnoise(u.usteed); + } else if (u.dz) { + pline("There's no one %s there.", (u.dz < 0) ? "up" : "down"); + } else { + pline_The("lout here doesn't acknowledge you..."); + } + return res; + } + + mtmp = (struct monst *) 0; + vismon = unseen = statue = 0, glyph = GLYPH_MON_OFF; + x = u.ux, y = u.uy; + for (range = 1; range <= BOLT_LIM + 1; ++range) { + x += u.dx, y += u.dy; + if (!isok(x, y) || (range > 1 && !couldsee(x, y))) { + /* switch back to coordinates for previous interation's 'mtmp' */ + x -= u.dx, y -= u.dy; + break; + } + mtmp = m_at(x, y); + vismon = (mtmp && canseemon(mtmp)); + glyph = glyph_at(x, y); + unseen = glyph_is_invisible(glyph); + statue = (glyph_is_statue(glyph) /* mimic or hallucinatory statue */ + || (!vismon && !unseen && (otmp = vobj_at(x, y)) != 0 + && otmp->otyp == STATUE)); /* or actual statue */ + if (vismon && (M_AP_TYPE(mtmp) == M_AP_FURNITURE + || M_AP_TYPE(mtmp) == M_AP_OBJECT)) + vismon = 0, mtmp = (struct monst *) 0; + if (vismon || unseen || (statue && Hallucination) + /* unseen adjacent monster will respond if able */ + || (range == 1 && mtmp && responsive_mon_at(x, y) + && mtmp->data->msound != MS_SILENT) + /* we check accessible() after m_at() in case there's a + visible monster phazing through a wall here */ + || !(accessible(x, y) || levl[x][y].typ == IRONBARS)) + break; + } + + if (unseen || (statue && Hallucination)) { + pline("That %screature is ignoring you!", unseen ? "unseen " : ""); + } else if (!mtmp || !responsive_mon_at(x, y)) { + if (vismon) /* 'vismon' is only True when 'mtmp' is non-Null */ + pline("%s seems not to notice you.", Monnam(mtmp)); + else + goto nada; + } else { /* 'mtmp' is guaranteed to be non-Null if we get here */ + /* if this monster is waiting for something, prod it into action */ + mtmp->mstrategy &= ~STRAT_WAITMASK; + + if (vismon && mtmp->mpeaceful && humanoid(mtmp->data)) { + if ((otmp = which_armor(mtmp, W_ARMH)) == 0) { + pline("%s waves.", Monnam(mtmp)); + } else if (otmp->cursed) { + pline("%s grasps %s %s but can't remove it.", Monnam(mtmp), + mhis(mtmp), helm_simple_name(otmp)); + otmp->bknown = 1; + } else { + pline("%s tips %s %s in response.", Monnam(mtmp), + mhis(mtmp), helm_simple_name(otmp)); + } + } else if (vismon && humanoid(mtmp->data)) { + static const char *const reaction[3] = { + "curses", "gestures rudely", "gestures offensively", + }; + int which = !Deaf ? rn2(3) : rn1(2, 1), + twice = (Deaf || which > 0 || rn2(3)) ? 0 : rn1(2, 1); + + pline("%s %s%s%s at you...", Monnam(mtmp), reaction[which], + twice ? " and " : "", twice ? reaction[twice] : ""); + } else if (distu(x, y) <= 2 && !Deaf && domonnoise(mtmp)) { + if (!vismon) + map_invisible(x, y); + } else if (vismon) { + pline("%s doesn't respond.", Monnam(mtmp)); + } else { + nada: + pline("%s", nothing_happens); + } + } + return res; +} + #ifdef USER_SOUNDS extern void FDECL(play_usersound, (const char *, int));