Enable hero to wash hands in fountains and pools

Dipping hands (with '-') or currently-worn gloves in a fountain or pool
will cause the hero to wash her hands, washing away any oil and clearing
the Glib intrinsic timeout.  This does mean bare hands can be used to
fish for fountain effects, without having to pick up a stray arrow and
carry it around as a dipping item, but having your hands be the only
thing that does not activate those effects felt weird.  If that would be
too unbalancing this could be scrapped.
This commit is contained in:
Michael Meyer
2023-10-24 18:02:30 -04:00
committed by PatR
parent 33034ebaba
commit 5af1fad398
3 changed files with 58 additions and 13 deletions

View File

@@ -972,6 +972,7 @@ extern void dogushforth(int);
extern void dryup(coordxy, coordxy, boolean);
extern void drinkfountain(void);
extern void dipfountain(struct obj *);
extern int wash_hands(void);
extern void breaksink(coordxy, coordxy);
extern void drinksink(void);

View File

@@ -389,6 +389,7 @@ void
dipfountain(register struct obj *obj)
{
int er = ER_NOTHING;
boolean is_hands = (obj == &cg.zeroobj);
if (Levitation) {
floating_above("fountain");
@@ -437,17 +438,19 @@ dipfountain(register struct obj *obj)
if (in_town(u.ux, u.uy))
(void) angry_guards(FALSE);
return;
} else if (is_hands || obj == uarmg) {
er = wash_hands();
} else {
er = water_damage(obj, NULL, TRUE);
}
if (er == ER_DESTROYED || (er != ER_NOTHING && !rn2(2))) {
return; /* no further effect */
}
if (er == ER_DESTROYED || (er != ER_NOTHING && !rn2(2))) {
return; /* no further effect */
}
switch (rnd(30)) {
case 16: /* Curse the item */
if (obj->oclass != COIN_CLASS && !obj->cursed) {
if (!is_hands && obj->oclass != COIN_CLASS && !obj->cursed) {
curse(obj);
}
break;
@@ -455,7 +458,7 @@ dipfountain(register struct obj *obj)
case 18:
case 19:
case 20: /* Uncurse the item */
if (obj->cursed) {
if (!is_hands && obj->cursed) {
if (!Blind)
pline_The("%s glows for a moment.", hliquid("water"));
uncurse(obj);
@@ -539,6 +542,27 @@ dipfountain(register struct obj *obj)
dryup(u.ux, u.uy, TRUE);
}
int
wash_hands(void)
{
const char *hands = makeplural(body_part(HAND));
int res = ER_NOTHING;
You("wash your %s%s in the %s.", uarmg ? "gloved " : "", hands,
hliquid("water"));
if (Glib) {
make_glib(0);
Your("%s are no longer slippery.",
uarmg ? gloves_simple_name(uarmg) : hands);
/* not what ER_GREASED is for, but the checks in dipfountain just
compare the result to ER_DESTROYED and ER_NOTHING, so it works */
res = ER_GREASED;
} else if (uarmg) {
res = water_damage(uarmg, (const char *) 0, TRUE);
}
return res;
}
void
breaksink(coordxy x, coordxy y)
{

View File

@@ -2177,8 +2177,10 @@ mixtype(struct obj *o1, struct obj *o2)
static int
dip_ok(struct obj *obj)
{
/* dipping hands and gold isn't currently implemented */
if (!obj || obj->oclass == COIN_CLASS)
if (!obj)
return GETOBJ_DOWNPLAY;
/* dipping gold isn't currently implemented */
if (obj->oclass == COIN_CLASS)
return GETOBJ_EXCLUDE;
if (inaccessible_equipment(obj, (const char *) 0, FALSE))
@@ -2218,14 +2220,16 @@ dodip(void)
uchar here;
char qbuf[QBUFSZ], obuf[QBUFSZ];
const char *shortestname; /* last resort obj name for prompt */
boolean is_hands;
if (!(obj = getobj("dip", dip_ok, GETOBJ_PROMPT)))
return ECMD_CANCEL;
if (inaccessible_equipment(obj, "dip", FALSE))
return ECMD_OK;
shortestname = (is_plural(obj) || pair_of(obj)) ? "them" : "it";
is_hands = (obj == &cg.zeroobj);
shortestname = (is_hands || is_plural(obj) || pair_of(obj)) ? "them"
: "it";
drink_ok_extra = 0;
/* preceding #dip with 'm' skips the possibility of dipping into
fountains and pools plus the prompting which those entail */
@@ -2239,10 +2243,16 @@ dodip(void)
* supplied type name.
* getobj: "What do you want to dip <the object> into? [xyz or ?*] "
*/
Strcpy(obuf, short_oname(obj, doname, thesimpleoname,
/* 128 - (24 + 54 + 1) leaves 49 for <object> */
QBUFSZ - sizeof "What do you want to dip \
if (is_hands) {
Snprintf(obuf, sizeof(obuf), "your %s",
makeplural(body_part(HAND)));
} else {
Strcpy(obuf, short_oname(obj, doname, thesimpleoname,
/* 128 - (24 + 54 + 1) leaves 49 for
<object> */
QBUFSZ - sizeof "What do you want to dip\
into? [abdeghjkmnpqstvwyzBCEFHIKLNOQRTUWXZ#-# or ?*] "));
}
here = levl[u.ux][u.uy].typ;
/* Is there a fountain to dip into here? */
@@ -2253,7 +2263,8 @@ dodip(void)
flags.verbose ? obuf : shortestname);
/* "Dip <the object> into the fountain?" */
if (y_n(qbuf) == 'y') {
obj->pickup_prev = 0;
if (!is_hands)
obj->pickup_prev = 0;
dipfountain(obj);
return ECMD_TIME;
}
@@ -2270,6 +2281,10 @@ dodip(void)
} else if (u.usteed && !is_swimmer(u.usteed->data)
&& P_SKILL(P_RIDING) < P_BASIC) {
rider_cant_reach(); /* not skilled enough to reach */
} else if (is_hands || obj == uarmg) {
if (!is_hands)
obj->pickup_prev = 0;
(void) wash_hands();
} else {
obj->pickup_prev = 0;
if (obj->otyp == POT_ACID)
@@ -2338,6 +2353,11 @@ potion_dip(struct obj *obj, struct obj *potion)
pline("That is a potion bottle, not a Klein bottle!");
return ECMD_OK;
}
if (obj == &cg.zeroobj) {
You("can't fit your %s into the mouth of the bottle!",
body_part(HAND));
return ECMD_OK;
}
obj->pickup_prev = 0; /* no longer 'recently picked up' */
potion->in_use = TRUE; /* assume it will be used up */