diff --git a/doc/fixes36.2 b/doc/fixes36.2 index 3454dda9e..8fb98475e 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -120,6 +120,11 @@ handle monsters inside the invocation area give monsters who have had a worn item stolen or who have been life-saved (used up amulet) a chance to wear replacement gear on next move instead of having to wait until they pick something up +Unchanging hero in clay golem form will be killed when cancelled +poly'd shapechanger and hiding mimic will revert to normal when cancelled, + like werecreature in beast form and non-Unchanging hero +cancelled shapeshifter is no longer able to change shape +cancelled shapeshifter hit by polymorph magic will become uncancelled Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository diff --git a/src/mon.c b/src/mon.c index cbdde81ba..9cdf9b6d9 100644 --- a/src/mon.c +++ b/src/mon.c @@ -2900,7 +2900,8 @@ restartcham() for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { if (DEADMONSTER(mtmp)) continue; - mtmp->cham = pm_to_cham(monsndx(mtmp->data)); + if (!mtmp->mcan) + mtmp->cham = pm_to_cham(monsndx(mtmp->data)); if (mtmp->data->mlet == S_MIMIC && mtmp->msleeping && cansee(mtmp->mx, mtmp->my)) { set_mimic_sym(mtmp); @@ -3417,6 +3418,13 @@ boolean msg; /* "The oldmon turns into a newmon!" */ anomalous extinction feedback during final disclsoure */ if (mbirth_limit(monsndx(olddata)) < MAXMONNO) return 0; + /* cancelled shapechangers become uncancelled prior + to being given a new shape */ + if (mtmp->mcan && !Protection_from_shape_changers) { + mtmp->cham = pm_to_cham(monsndx(mtmp->data)); + if (mtmp->cham != NON_PM) + mtmp->mcan = 0; + } } if (msg) { diff --git a/src/zap.c b/src/zap.c index 14b47902a..37b38e8ab 100644 --- a/src/zap.c +++ b/src/zap.c @@ -2306,7 +2306,7 @@ boolean ordinary; case WAN_CANCELLATION: case SPE_CANCELLATION: - (void) cancel_monst(&youmonst, obj, TRUE, FALSE, TRUE); + (void) cancel_monst(&youmonst, obj, TRUE, TRUE, TRUE); break; case SPE_DRAIN_LIFE: @@ -2675,25 +2675,45 @@ boolean youattack, allow_cancel_kill, self_cancel; /* now handle special cases */ if (youdefend) { - if (Upolyd) { - if ((u.umonnum == PM_CLAY_GOLEM) && !Blind) - pline(writing_vanishes, your); - - if (Unchanging) + if (Upolyd) { /* includes lycanthrope in creature form */ + /* + * Return to normal form unless Unchanging. + * Hero in clay golem form dies if Unchanging. + * Does not cure lycanthropy or stop timed random polymorph. + */ + if (u.umonnum == PM_CLAY_GOLEM) { + if (!Blind) + pline(writing_vanishes, your); + else /* note: "dark" rather than "heavy" is intentional... */ + You_feel("%s headed.", Hallucination ? "dark" : "light"); + u.mh = 0; /* fatal; death handled by rehumanize() */ + } + if (Unchanging && u.mh > 0) Your("amulet grows hot for a moment, then cools."); else rehumanize(); } } else { - mdef->mcan = TRUE; - - if (is_were(mdef->data) && mdef->data->mlet != S_HUMAN) + mdef->mcan = 1; + /* force shapeshifter into its base form */ + if (mdef->m_ap_type != M_AP_NOTHING) + seemimic(mdef); + /* [not 'else if'; chameleon might have been hiding as a mimic] */ + if (mdef->cham >= LOW_PM) { + /* note: newcham() uncancels shapechangers (resets m->mcan + to 0), but only for shapechangers whose m->cham is already + NON_PM and we just verified that it's LOW_PM or higher */ + newcham(mdef, &mons[mdef->cham], FALSE, FALSE); + mdef->cham = NON_PM; /* cancelled shapeshifter can't shift */ + } + if (is_were(mdef->data) && !is_human(mdef->data)) were_change(mdef); if (mdef->data == &mons[PM_CLAY_GOLEM]) { if (canseemon(mdef)) pline(writing_vanishes, s_suffix(mon_nam(mdef))); - + /* !allow_cancel_kill is for Magicbane, where clay golem + will be killed somewhere back up the call/return chain... */ if (allow_cancel_kill) { if (youattack) killed(mdef);