fix #H7157 - cancel self as clay golem

The report was "doesn't kill even if unchanging", but it does cause
rehumanize() when not Unchanging, the same thing that happens when
you die due to loss of hit points.  But losing the activating word(s)
and then having Unchanging retain the clay golem shape does seem
wrong, so make losing the word(s) while being unable to revert to
normal form be fatal.

Poly'd hero (without Unchanging) reverts to normal when cancelled,
so make monsters behave that way.  Previously, only werecritters in
beast form were forced to human form.  This changes cancellation to
make shapechangers and hiding mimics take on normal form too.

Cancelled shapechangers now behave as if the hero has the
Protection_from_shape_changes attribute and will be unable to change
their shape (after having been forced into normal form).  Getting
polymorphed in any fashion uncancels them prior to giving new shape.
[There may be some newcham() situations that should be disallowed
when cancelled rather proceeding and consequently uncancelling.]
This commit is contained in:
PatR
2018-09-15 19:23:29 -07:00
parent e031800880
commit 89237fc96d
3 changed files with 44 additions and 11 deletions

View File

@@ -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

View File

@@ -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) {

View File

@@ -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);