diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index c2683835e..d92d0a25e 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -1811,6 +1811,11 @@ autopickup while levitating shares code with 'mention_decor'; after being told about ice covered by an object, moving over some other object later when mention_decor is Off could give "you are back on solid ground" long after leaving the ice +duration of temporary stoning resistance would be extended while eating a + cockatrice corpse, as intended, but not while eating Medusa's corpse + so if it timed out during the meal, player got the message about hero + no longer being protected against stoning but was able to finish the + meal safely Fixes to 3.7.0-x Platform and/or Interface Problems Exposed Via git Repository diff --git a/include/extern.h b/include/extern.h index 49664ca9f..5538d1a86 100644 --- a/include/extern.h +++ b/include/extern.h @@ -863,8 +863,10 @@ extern int eaten_stat(int, struct obj *) NONNULLARG2; extern void food_disappears(struct obj *) NONNULLARG1; extern void food_substitution(struct obj *, struct obj *) NONNULLPTRS; extern long temp_resist(int); +extern boolean eating_dangerous_corpse(int); extern void eating_conducts(struct permonst *) NONNULLARG1; -extern int eat_brains(struct monst *, struct monst *, boolean, int *) NONNULLARG12; +extern int eat_brains(struct monst *, struct monst *, boolean, + int *) NONNULLARG12; extern void fix_petrification(void); extern int intrinsic_possible(int, struct permonst *) NONNULLARG2; extern boolean should_givit(int, struct permonst *) NONNULLARG2; diff --git a/src/eat.c b/src/eat.c index 8587b0338..b9b686961 100644 --- a/src/eat.c +++ b/src/eat.c @@ -16,7 +16,6 @@ static void choke(struct obj *); static void recalc_wt(void); static struct obj *touchfood(struct obj *) NONNULL; static void do_reset_eat(void); -static void maybe_extend_timed_resist(int); static void done_eating(boolean); static void cprefx(int); static boolean temp_givit(int, struct permonst *); @@ -428,7 +427,7 @@ do_reset_eat(void) /* if 'prop' is only set because of a timed value (so not an intrinsic attribute or because of polymorph shape or worn or carried gear), return - its timeout, otherwise return 0 */ + its timeout, otherwise return 0; used by enlightenment */ long temp_resist(int prop) { @@ -448,6 +447,33 @@ temp_resist(int prop) return 0L; } +/* if temporary acid or stoning resistance is timing out while eating + something which that resistance is protecting against, caller will + extend resistance's duration so that it times out after meal finishes */ +boolean +eating_dangerous_corpse(int res) +{ + struct obj *food; + int mnum; + + if (go.occupation == eatfood + && (food = gc.context.victual.piece) != 0 + && food->otyp == CORPSE + && (mnum = food->corpsenm) >= LOW_PM + && (carried(food) || obj_here(food, u.ux, u.uy))) { + + if (res == ACID_RES && acidic(&mons[mnum])) + return TRUE; + /* flesh_petrifies() includes Medusa as well as touch_petrifies() */ + if (res == STONE_RES && flesh_petrifies(&mons[mnum])) + return TRUE; + } + return FALSE; +} + +#if 0 /* no longer used */ +static void maybe_extend_timed_resist(int); + /* if temp resist against 'prop' is about to timeout, extend it slightly */ static void maybe_extend_timed_resist(int prop) @@ -465,6 +491,7 @@ maybe_extend_timed_resist(int prop) set_itimeout(&u.uprops[prop].intrinsic, 2L); } } +#endif /* called each move during eating process */ static int @@ -482,25 +509,6 @@ eatfood(void) if (!gc.context.victual.eating) return 0; - /* - * We don't want temporary acid resistance to timeout while eating - * an acidic corpse or temporary stoning resistance to do that while - * eating a cockatrice corpse. Protection is checked at the start - * of the meal and having it go away mid-meal with a message about - * increased vulnerability but no consequences is too obviously wrong, - * but also too nit-picky to deal with. - * - * (Tins aren't handled by eatfood() and wouldn't need this anyway - * because they're finished in one turn once they've been opened. - * Come to think of it, eggs are probably eaten in one turn too.) - */ - if ((food->otyp == CORPSE || food->otyp == EGG) - && food->corpsenm >= LOW_PM && acidic(&mons[food->corpsenm])) - maybe_extend_timed_resist(ACID_RES); - if ((food->otyp == CORPSE || food->otyp == EGG) - && food->corpsenm >= LOW_PM && touch_petrifies(&mons[food->corpsenm])) - maybe_extend_timed_resist(STONE_RES); - if (++gc.context.victual.usedtime <= gc.context.victual.reqtime) { if (bite()) return 0; diff --git a/src/timeout.c b/src/timeout.c index 1ae644098..7d8204dc7 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -775,15 +775,33 @@ nh_timeout(void) } break; case ACID_RES: - if (!Acid_resistance && !Unaware) - You("no longer feel safe from acid."); + if (!Acid_resistance) { + if (eating_dangerous_corpse(ACID_RES)) { + /* extend temporary acid resistance if in midst + of eating an acidic corpse; this will repeat + until eating is finished or interrupted */ + set_itimeout(&u.uprops[ACID_RES].intrinsic, 1L); + break; + } + if (!Unaware) + You("no longer feel safe from acid."); + } break; case STONE_RES: if (!Stone_resistance) { + if (eating_dangerous_corpse(STONE_RES)) { + /* extend temporary stoning resistance if in midst + of eating a stoning corpse; this will repeat + until eating is finished or interrupted */ + set_itimeout(&u.uprops[STONE_RES].intrinsic, 1L); + break; + } if (!Unaware) You("no longer feel secure from petrification."); /* no-op if not wielding a cockatrice corpse; - uswapwep case is always a no-op (see Gloves_off()) */ + uswapwep case is always a no-op because two-weapon + combat is only possible with two one-handed weapons + or weapon tools, not corpses */ wielding_corpse(uwep, (struct obj *) 0, FALSE); wielding_corpse(uswapwep, (struct obj *) 0, FALSE); }