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....
This commit is contained in:
PatR
2020-02-18 03:14:22 -08:00
parent f177675cbc
commit 814adb41b8
4 changed files with 146 additions and 13 deletions
+2 -1
View File
@@ -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 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 now that stone could be mapped to an entirely different symbol
added several new status conditions all of which are opt-in except added several new status conditions all of which are opt-in except
the new cond_grab and cond_lava which are opt-out 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 Platform- and/or Interface-Specific New Features
+2 -1
View File
@@ -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. */ /* Copyright (c) Steve Creps, 1988. */
/* NetHack may be freely redistributed. See license for details. */ /* 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(whimper, (struct monst *));
E void FDECL(beg, (struct monst *)); E void FDECL(beg, (struct monst *));
E int NDECL(dotalk); E int NDECL(dotalk);
E int NDECL(tiphat);
#ifdef USER_SOUNDS #ifdef USER_SOUNDS
E int FDECL(add_sound_mapping, (const char *)); E int FDECL(add_sound_mapping, (const char *));
E void FDECL(play_sound_for_message, (const char *)); E void FDECL(play_sound_for_message, (const char *));
+3 -1
View File
@@ -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) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -3171,6 +3171,8 @@ dotip()
/* anything not covered yet */ /* anything not covered yet */
if (cobj->oclass == POTION_CLASS) /* can't pour potions... */ if (cobj->oclass == POTION_CLASS) /* can't pour potions... */
pline_The("%s %s securely sealed.", xname(cobj), otense(cobj, "are")); pline_The("%s %s securely sealed.", xname(cobj), otense(cobj, "are"));
else if (uarmh && cobj == uarmh)
return tiphat();
else if (cobj->otyp == STATUE) else if (cobj->otyp == STATUE)
pline("Nothing interesting happens."); pline("Nothing interesting happens.");
else else
+139 -10
View File
@@ -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 */ /* Copyright (c) 1989 Janet Walz, Mike Threepoint */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -7,6 +7,7 @@
static boolean FDECL(mon_is_gecko, (struct monst *)); static boolean FDECL(mon_is_gecko, (struct monst *));
static int FDECL(domonnoise, (struct monst *)); static int FDECL(domonnoise, (struct monst *));
static int NDECL(dochat); static int NDECL(dochat);
static struct monst *FDECL(responsive_mon_at, (int, int));
static int FDECL(mon_in_room, (struct monst *, int)); static int FDECL(mon_in_room, (struct monst *, int));
/* this easily could be a macro, but it might overtax dumb compilers */ /* this easily could be a macro, but it might overtax dumb compilers */
@@ -926,15 +927,14 @@ register struct monst *mtmp;
break; break;
case MS_SOLDIER: { case MS_SOLDIER: {
static const char static const char
*const soldier_foe_msg[3] = *const soldier_foe_msg[3] = {
{ "Resistance is useless!", "You're dog meat!", "Surrender!",
"Resistance is useless!", "You're dog meat!", "Surrender!", },
}, *const soldier_pax_msg[3] = {
*const soldier_pax_msg[3] = { "What lousy pay we're getting here!",
"What lousy pay we're getting here!", "The food's not fit for Orcs!",
"The food's not fit for Orcs!", "My feet hurt, I've been on them all day!",
"My feet hurt, I've been on them all day!", };
};
verbl_msg = mtmp->mpeaceful ? soldier_pax_msg[rn2(3)] verbl_msg = mtmp->mpeaceful ? soldier_pax_msg[rn2(3)]
: soldier_foe_msg[rn2(3)]; : soldier_foe_msg[rn2(3)];
break; break;
@@ -1115,6 +1115,135 @@ dochat()
return domonnoise(mtmp); return domonnoise(mtmp);
} }
/* is there a monster at <x,y> 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 #ifdef USER_SOUNDS
extern void FDECL(play_usersound, (const char *, int)); extern void FDECL(play_usersound, (const char *, int));