From cbc93a05556e863972bcf3f8e368a3d59e745ed5 Mon Sep 17 00:00:00 2001 From: PatR Date: Thu, 28 Nov 2024 11:33:26 -0800 Subject: [PATCH] github issue #1312 - prot from shape changers Issue reported by youkan700: shape change anomalies. Shapechangers could change shape despite active protection-from-shape-changers if hero wore two rings of protection from shape changers and took one off. Shapechangers who migrated to a not-yet-visited level that eventually got visited with protection from shape changers in effect would be stuck in their current shape, even if the PfSC attribute got toggled off and back on. The issue included suggested fixes and those are what I've used. I noticed a third case that only applies to wizard mode: if player used #wizintrinsic to set a timed value for PfSC, monsters wouldn't resume changing shape after it timed out, unless/until it got toggled on and back off via a PfSC ring or hero left the level and returned. Fixes #1312 --- src/do_wear.c | 9 +++++---- src/dog.c | 6 ++++++ src/mon.c | 2 +- src/timeout.c | 6 ++++++ 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/do_wear.c b/src/do_wear.c index 72ecfd75d..e7cc1be64 100644 --- a/src/do_wear.c +++ b/src/do_wear.c @@ -1410,10 +1410,11 @@ Ring_off_or_gone(struct obj *obj, boolean gone) find_ac(); /* updates botl */ break; case RIN_PROTECTION_FROM_SHAPE_CHAN: - /* If you're no longer protected, let the chameleons - * change shape again -dgk - */ - restartcham(); + /* if you're no longer protected, let the chameleons change + shape again; however, might still be protected if wearing + 2nd ring of this type (or via #wizintrinsic) */ + if (!Protection_from_shape_changers) + restartcham(); break; } } diff --git a/src/dog.c b/src/dog.c index deade5f5e..9c4f85560 100644 --- a/src/dog.c +++ b/src/dog.c @@ -417,6 +417,12 @@ mon_arrive(struct monst *mtmp, int when) fromdlev.dnum = mtmp->mtrack[2].x; fromdlev.dlevel = mtmp->mtrack[2].y; mon_track_clear(mtmp); + /* in case Protection_from_shape_changers is different now from when + 'mtmp' went onto the migrating monsters list; that's handled in + getlev() when returning to a previously visited level and by the + special level code for monsters specified in the level, but needed + here for monsters migrating to a newly created level */ + restore_cham(mtmp); if (mtmp == u.usteed) return; /* don't place steed on the map */ diff --git a/src/mon.c b/src/mon.c index bbfe06f4a..1c2ecad07 100644 --- a/src/mon.c +++ b/src/mon.c @@ -4465,7 +4465,7 @@ get_iter_mons_xy( /* force all chameleons and mimics to become themselves and werecreatures to revert to human form; called when Protection_from_shape_changers gets - activated via wearing or eating ring or wizintrinsics */ + activated via wearing or eating ring or via #wizintrinsic */ void rescham(void) { diff --git a/src/timeout.c b/src/timeout.c index 8553320bb..cb9800994 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -930,6 +930,12 @@ nh_timeout(void) case GLIB: make_glib(0); /* might update persistent inventory */ break; + case PROT_FROM_SHAPE_CHANGERS: + /* timed Protection_from_shape_changers is via + #wizintrinsic only */ + if (!Protection_from_shape_changers) + restartcham(); + break; } }