From: PatR Date: Thu, 21 Jan 2016 10:12:47 +0000 (-0800) Subject: fix #H4204 - shapeshifter taking vampire form X-Git-Tag: NetHack-3.6.1_RC01~997 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=885de116e1e93faa8ad5dc2685d16a9f553c50ed;p=nethack fix #H4204 - shapeshifter taking vampire form When a chameleon/doppelganger/sandestin took vampire or vampire lord shape, it stopped taking on new shapes. Vampire shapeshifting was being applied to all vampires rather than just to is_vampshifter(). When is_vampshifter() is false, the vampire is some other shapeshifter or Protection_from_shape_changers is in effect, so vampire shifting doesn't apply. While testing, I noticed that vampires/lords only turned into bats/ wolves during initial creation. They did turn into fog clouds in order to pass closed doors but the other alternate forms were ignored. That's fixed too. --- diff --git a/doc/fixes36.1 b/doc/fixes36.1 index a719cdd0e..bb35edd09 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -120,6 +120,7 @@ fix floor descriptions on the Planes when levitating fix warning glyph description when monster symbol coincided the warning symbol allow the same color names for status hilites and menucolors override MSGTYPE=norep while executing the ':' command +if a chameleon took vampire form, it would stop periodically changing shape Platform- and/or Interface-Specific Fixes diff --git a/src/mon.c b/src/mon.c index 802d20bff..8080fd044 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mon.c $NHDT-Date: 1451664800 2016/01/01 16:13:20 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.203 $ */ +/* NetHack 3.6 mon.c $NHDT-Date: 1453371163 2016/01/21 10:12:43 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.208 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -588,12 +588,10 @@ mcalcdistress() mon_regen(mtmp, FALSE); /* possibly polymorph shapechangers and lycanthropes */ - if (mtmp->cham >= LOW_PM) { - if (is_vampshifter(mtmp) || mtmp->data->mlet == S_VAMPIRE) - decide_to_shapeshift(mtmp, 0); - else if (!rn2(6)) - (void) newcham(mtmp, (struct permonst *) 0, FALSE, FALSE); - } + if (mtmp->cham >= LOW_PM) + decide_to_shapeshift(mtmp, (canspotmon(mtmp) + || (u.uswallow && mtmp == u.ustuck)) + ? SHIFT_MSG : 0); were_change(mtmp); /* gradually time out temporary problems */ @@ -2859,30 +2857,39 @@ int shiftflags; || ((shiftflags & SHIFT_SEENMSG) && sensemon(mon))) msg = TRUE; - if (is_vampshifter(mon)) { + if (!is_vampshifter(mon)) { + /* regular shapeshifter */ + if (!rn2(6)) + (void) newcham(mon, (struct permonst *) 0, FALSE, msg); + } else { /* The vampire has to be in good health (mhp) to maintain * its shifted form. - * + * * If we're shifted and getting low on hp, maybe shift back. * If we're not already shifted and in good health, maybe shift. */ - if ((mon->mhp <= mon->mhpmax / 6) && rn2(4) && (mon->cham >= LOW_PM)) - (void) newcham(mon, &mons[mon->cham], FALSE, msg); - } else if (mon->data->mlet == S_VAMPIRE && mon->cham == NON_PM && !rn2(6) - && (mon->mhp > mon->mhpmax - ((mon->mhpmax / 10) + 1))) { - (void) newcham(mon, (struct permonst *) 0, FALSE, msg); + if (mon->data->mlet != S_VAMPIRE) { + if ((mon->mhp <= (mon->mhpmax + 5) / 6) && rn2(4) + && mon->cham >= LOW_PM) + (void) newcham(mon, &mons[mon->cham], FALSE, msg); + } else { + if (mon->mhp >= 9 * mon->mhpmax / 10 && !rn2(6) + && (!canseemon(mon) + || distu(mon->mx, mon->my) > BOLT_LIM * BOLT_LIM)) + (void) newcham(mon, (struct permonst *) 0, FALSE, msg); + } + /* override the 10% chance for sex change */ + ptr = mon->data; + if (!is_male(ptr) && !is_female(ptr) && !is_neuter(ptr)) + mon->female = was_female; } - /* override the 10% chance for sex change */ - ptr = mon->data; - if (!is_male(ptr) && !is_female(ptr) && !is_neuter(ptr)) - mon->female = was_female; } STATIC_OVL int pickvampshape(mon) struct monst *mon; { - int mndx = mon->cham; + int mndx = mon->cham, wolfchance = 10; /* avoid picking monsters with lowercase display symbols ('d' for wolf and 'v' for fog cloud) on rogue level*/ boolean uppercase_only = Is_rogue_level(&u.uz); @@ -2892,9 +2899,10 @@ struct monst *mon; /* ensure Vlad can keep carrying the Candelabrum */ if (mon_has_special(mon)) break; /* leave mndx as is */ + wolfchance = 3; /*FALLTHRU*/ case PM_VAMPIRE_LORD: /* vampire lord or Vlad can become wolf */ - if (!rn2(10) && !uppercase_only) { + if (!rn2(wolfchance) && !uppercase_only) { mndx = PM_WOLF; break; } @@ -3045,13 +3053,17 @@ struct monst *mon; } break; } + /* for debugging: allow control of polymorphed monster */ if (wizard && iflags.mon_polycontrol) { char pprompt[BUFSZ], buf[BUFSZ]; int monclass; - Sprintf(pprompt, "Change %s @ <%d,%d> into what kind of monster?", - noit_mon_nam(mon), (int) mon->mx, (int) mon->my); + Sprintf(pprompt, "Change %s @ %s into what kind of monster?", + noit_mon_nam(mon), + coord_desc((int) mon->mx, (int) mon->my, buf, + (iflags.getpos_coords != GPCOORDS_NONE) + ? iflags.getpos_coords : GPCOORDS_MAP)); tryct = 5; do { monclass = 0; @@ -3274,9 +3286,10 @@ boolean msg; /* "The oldmon turns into a newmon!" */ /* Do this even if msg is FALSE */ You("%s %s%s!", - (amorphous(olddata) || is_whirly(olddata)) ? - "emerge from" : "break out of", + (amorphous(olddata) || is_whirly(olddata)) + ? "emerge from" : "break out of", l_oldname, msgtrail); + msg = FALSE; /* message has been given */ mtmp->mhp = 1; /* almost dead */ } expels(mtmp, olddata, FALSE); diff --git a/src/monmove.c b/src/monmove.c index 86432a6c5..558927164 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 monmove.c $NHDT-Date: 1451866935 2016/01/04 00:22:15 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.80 $ */ +/* NetHack 3.6 monmove.c $NHDT-Date: 1453371163 2016/01/21 10:12:43 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.83 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1023,9 +1023,7 @@ not_special: flag |= ALLOW_DIG; if (is_human(ptr) || ptr == &mons[PM_MINOTAUR]) flag |= ALLOW_SSM; - if (is_undead(ptr) && ptr->mlet != S_GHOST) - flag |= NOGARLIC; - if (is_vampshifter(mtmp)) + if ((is_undead(ptr) && ptr->mlet != S_GHOST) || is_vampshifter(mtmp)) flag |= NOGARLIC; if (throws_rocks(ptr)) flag |= ALLOW_ROCK; @@ -1215,10 +1213,11 @@ postmov: boolean btrapped = (here->doormask & D_TRAPPED), observeit = canseeit && canspotmon(mtmp); - if (here->doormask & (D_LOCKED | D_CLOSED) + if ((here->doormask & (D_LOCKED | D_CLOSED)) != 0 && (amorphous(ptr) - || (!amorphous(ptr) && can_fog(mtmp) - && vamp_shift(mtmp, &mons[PM_FOG_CLOUD],canspotmon(mtmp))))) { + || (can_fog(mtmp) + && vamp_shift(mtmp, &mons[PM_FOG_CLOUD], + canspotmon(mtmp))))) { if (flags.verbose && canseemon(mtmp)) pline("%s %s under the door.", Monnam(mtmp), (ptr == &mons[PM_FOG_CLOUD] @@ -1581,7 +1580,7 @@ boolean can_fog(mtmp) struct monst *mtmp; { - if ((is_vampshifter(mtmp) || mtmp->data->mlet == S_VAMPIRE) + if (!(mvitals[PM_FOG_CLOUD].mvflags & G_GENOD) && is_vampshifter(mtmp) && !Protection_from_shape_changers && !stuff_prevents_passage(mtmp)) return TRUE; return FALSE; @@ -1601,12 +1600,11 @@ boolean domsg; sensemon(mon) ? "now detect" : "observe", an(m_monnam(mon))); } - if (mon->cham >= LOW_PM) { - if (ptr == &mons[mon->cham]) - mon->cham = NON_PM; - reslt = newcham(mon, ptr, FALSE, FALSE); - } else if (mon->cham == NON_PM && ptr != mon->data) { - mon->cham = monsndx(mon->data); + if (mon->data == ptr) { + /* already right shape */ + reslt = 1; + domsg = FALSE; + } else if (is_vampshifter(mon)) { reslt = newcham(mon, ptr, FALSE, FALSE); } if (reslt && domsg) {