vampires now shapeshift [trunk only]

- can shift into fog clouds, vampire bats, and vampire lords into wolves
- after being "killed" in shifted form, they transform back rather than get
  destroyed, and you must take them on in vampire form to defeat them
- can deliberately shift into fog clouds to pass under closed doors
This commit is contained in:
nethack.allison
2004-06-15 11:52:04 +00:00
parent c8ef9338f0
commit 9b3521e503
27 changed files with 270 additions and 83 deletions

View File

@@ -18,7 +18,6 @@ STATIC_DCL long FDECL(mm_aggression, (struct monst *,struct monst *));
STATIC_DCL long FDECL(mm_displacement, (struct monst *,struct monst *));
#endif
STATIC_DCL int NDECL(pick_animal);
STATIC_DCL int FDECL(select_newcham_form, (struct monst *));
STATIC_DCL void FDECL(kill_eggs, (struct obj *));
#ifdef REINCARNATION
@@ -530,8 +529,12 @@ mcalcdistress()
mon_regen(mtmp, FALSE);
/* possibly polymorph shapechangers and lycanthropes */
if (mtmp->cham && !rn2(6))
(void) newcham(mtmp, (struct permonst *)0, FALSE, FALSE);
if (mtmp->cham != CHAM_ORDINARY) {
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);
}
were_change(mtmp);
/* gradually time out temporary problems */
@@ -917,7 +920,6 @@ max_mon_load(mtmp)
register struct monst *mtmp;
{
register long maxload;
/* Base monster carrying capacity is equal to human maximum
* carrying capacity, or half human maximum if not strong.
* (for a polymorphed player, the value used would be the
@@ -956,7 +958,7 @@ struct obj *otmp;
return FALSE;
if (otyp == CORPSE && is_rider(&mons[otmp->corpsenm]))
return FALSE;
if (objects[otyp].oc_material == SILVER && hates_silver(mdat) &&
if (objects[otyp].oc_material == SILVER && mon_hates_silver(mtmp) &&
(otyp != BELL_OF_OPENING || !is_covetous(mdat)))
return FALSE;
@@ -1049,7 +1051,8 @@ nexttry: /* eels prefer the water, but if there is no water nearby,
!((IS_TREE(ntyp) ? treeok : rockok) && may_dig(nx,ny))) continue;
/* KMH -- Added iron bars */
if (ntyp == IRONBARS && !(flag & ALLOW_BARS)) continue;
if(IS_DOOR(ntyp) && !amorphous(mdat) &&
if(IS_DOOR(ntyp) &&
!(amorphous(mdat) || (!amorphous(mdat) && can_fog(mon))) &&
((levl[nx][ny].doormask & D_CLOSED && !(flag & OPENDOOR)) ||
(levl[nx][ny].doormask & D_LOCKED && !(flag & UNLOCKDOOR))) &&
!thrudoor) continue;
@@ -1373,7 +1376,7 @@ struct obj *
mlifesaver(mon)
struct monst *mon;
{
if (!nonliving(mon->data)) {
if (!nonliving(mon->data) || is_vampshifter(mon)) {
struct obj *otmp = which_armor(mon, W_AMUL);
if (otmp && otmp->otyp == AMULET_OF_LIFE_SAVING)
@@ -1441,6 +1444,52 @@ register struct monst *mtmp;
lifesaved_monster(mtmp);
if (mtmp->mhp > 0) return;
if (is_vampshifter(mtmp)) {
int mndx = mtmp->cham;
int x = mtmp->mx, y = mtmp->my;
/* this only happens if shapeshifted */
if (mndx != CHAM_ORDINARY && mndx != monsndx(mtmp->data)) {
char buf[BUFSZ];
boolean in_door = amorphous(mtmp->data) &&
closed_door(mtmp->mx,mtmp->my);
Sprintf(buf,
"The %s%s suddenly %s and rises as %%s!",
(nonliving(mtmp->data) ||
noncorporeal(mtmp->data) ||
amorphous(mtmp->data)) ? "" : "seemingly dead ",
x_monnam(mtmp, ARTICLE_NONE, (char *)0,
SUPPRESS_SADDLE | SUPPRESS_HALLUCINATION |
SUPPRESS_INVISIBLE | SUPPRESS_IT, FALSE),
(nonliving(mtmp->data) ||
noncorporeal(mtmp->data) ||
amorphous(mtmp->data)) ?
"reconstitutes" : "transforms");
mtmp->mcanmove = 1;
mtmp->mfrozen = 0;
if (mtmp->mhpmax <= 0) mtmp->mhpmax = 10;
mtmp->mhp = mtmp->mhpmax;
/* this can happen if previously a fog cloud */
if (u.uswallow && (mtmp == u.ustuck))
expels(mtmp, mtmp->data, FALSE);
if (in_door) {
coord new_xy;
if (enexto(&new_xy,
mtmp->mx, mtmp->my, &mons[mndx])) {
rloc_to(mtmp, new_xy.x, new_xy.y);
}
}
newcham(mtmp, &mons[mndx], FALSE, FALSE);
if (mtmp->data == &mons[mndx])
mtmp->cham = CHAM_ORDINARY;
else
mtmp->cham = mndx;
if ((!Blind && canseemon(mtmp)) || sensemon(mtmp))
pline(buf, a_monnam(mtmp));
newsym(x,y);
return;
}
}
#ifdef STEED
/* Player is thrown from his steed when it dies */
if (mtmp == u.usteed)
@@ -2306,6 +2355,31 @@ pick_animal()
return animal_list[rn2(animal_list_count)];
}
void
decide_to_shapeshift(mon, shiftflags)
struct monst *mon;
int shiftflags;
{
boolean msg = FALSE;
if ((shiftflags & SHIFT_MSG) ||
((shiftflags & SHIFT_SEENMSG) && sensemon(mon))) msg = TRUE;
if (is_vampshifter(mon)) {
/* 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))
(void) newcham(mon, &mons[mon->cham], FALSE, msg);
} else if (mon->data->mlet == S_VAMPIRE && mon->cham == CHAM_ORDINARY
&& !rn2(6) && (mon->mhp > mon->mhpmax - ((mon->mhpmax / 10) + 1))) {
(void) newcham(mon, (struct permonst *)0, FALSE, msg);
}
}
int
select_newcham_form(mon)
struct monst *mon;