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:
@@ -763,7 +763,7 @@ struct obj *obj;
|
||||
if (vis)
|
||||
pline("%s can't see anything right now.", Monnam(mtmp));
|
||||
/* some monsters do special things */
|
||||
} else if (mlet == S_VAMPIRE || mlet == S_GHOST) {
|
||||
} else if (mlet == S_VAMPIRE || mlet == S_GHOST || is_vampshifter(mtmp)) {
|
||||
if (vis)
|
||||
pline ("%s doesn't have a reflection.", Monnam(mtmp));
|
||||
} else if(!mtmp->mcan && !mtmp->minvis &&
|
||||
|
||||
@@ -464,7 +464,8 @@ domonability()
|
||||
if(u.uburied)
|
||||
pline("Unfortunately sound does not carry well through rock.");
|
||||
else aggravate();
|
||||
} else if (Upolyd)
|
||||
} else if (youmonst.data->mlet == S_VAMPIRE) return dopoly();
|
||||
else if (Upolyd)
|
||||
pline("Any special ability you may have is purely reflexive.");
|
||||
else You("don't have a special ability in your normal form!");
|
||||
return 0;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* SCCS Id: @(#)dog.c 3.4 2002/09/08 */
|
||||
/* SCCS Id: @(#)dog.c 3.4 2004/06/12 */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -689,7 +689,7 @@ register struct obj *obj;
|
||||
return (herbi ? CADAVER : MANFOOD);
|
||||
else return (carni ? CADAVER : MANFOOD);
|
||||
case CLOVE_OF_GARLIC:
|
||||
return (is_undead(mon->data) ? TABU :
|
||||
return ((is_undead(mon->data) || is_vampshifter(mon)) ? TABU :
|
||||
((herbi || starving) ? ACCFOOD : MANFOOD));
|
||||
case TIN:
|
||||
return (metallivorous(mon->data) ? ACCFOOD : MANFOOD);
|
||||
@@ -709,7 +709,7 @@ register struct obj *obj;
|
||||
if (obj->otyp == AMULET_OF_STRANGULATION ||
|
||||
obj->otyp == RIN_SLOW_DIGESTION)
|
||||
return TABU;
|
||||
if (hates_silver(mon->data) &&
|
||||
if (mon_hates_silver(mon) &&
|
||||
objects[obj->otyp].oc_material == SILVER)
|
||||
return(TABU);
|
||||
if (mon->data == &mons[PM_GELATINOUS_CUBE] && is_organic(obj))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* SCCS Id: @(#)dokick.c 3.4 2003/12/04 */
|
||||
/* SCCS Id: @(#)dokick.c 3.4 2004/06/12 */
|
||||
/* Copyright (c) Izchak Miller, Mike Stephenson, Steve Linhart, 1989. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -49,8 +49,8 @@ register boolean clumsy;
|
||||
if (mon->data == &mons[PM_SHADE])
|
||||
dmg = 0;
|
||||
|
||||
if ((is_undead(mon->data) || is_demon(mon->data)) && uarmf &&
|
||||
uarmf->blessed)
|
||||
if ((is_undead(mon->data) || is_demon(mon->data) || is_vampshifter(mon))
|
||||
&& uarmf && uarmf->blessed)
|
||||
blessed_foot_damage = 1;
|
||||
|
||||
if (mon->data == &mons[PM_SHADE] && !blessed_foot_damage) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* SCCS Id: @(#)explode.c 3.4 2003/10/21 */
|
||||
/* SCCS Id: @(#)explode.c 3.4 2004/06/12 */
|
||||
/* Copyright (C) 1990 by Ken Arromdee */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -157,7 +157,7 @@ int expltype;
|
||||
break;
|
||||
case AD_DISN:
|
||||
explmask[i][j] |= (olet == WAND_CLASS) ?
|
||||
(nonliving(mtmp->data) || is_demon(mtmp->data)) :
|
||||
(nonliving(mtmp->data) || is_demon(mtmp->data) || is_vampshifter(mtmp)) :
|
||||
resists_disint(mtmp);
|
||||
break;
|
||||
case AD_ELEC:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* SCCS Id: @(#)makemon.c 3.4 2004/05/21 */
|
||||
/* SCCS Id: @(#)makemon.c 3.4 2004/06/12 */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -1001,18 +1001,28 @@ register int mmflags;
|
||||
LS_MONSTER, (genericptr_t)mtmp);
|
||||
mitem = 0; /* extra inventory item for this monster */
|
||||
|
||||
if (mndx == PM_VLAD_THE_IMPALER)
|
||||
mitem = CANDELABRUM_OF_INVOCATION;
|
||||
mtmp->cham = CHAM_ORDINARY; /* default is "not a shapechanger" */
|
||||
if ((mcham = pm_to_cham(mndx)) != CHAM_ORDINARY) {
|
||||
/* this is a shapechanger after all */
|
||||
if (Protection_from_shape_changers) {
|
||||
; /* stuck in its natural form (CHAM_ORDINARY) */
|
||||
} else {
|
||||
/* new shapechanger starts out with random form
|
||||
/* General shapechangers start out with random form
|
||||
(this explicitly picks something from the normal
|
||||
selection for current difficulty level rather
|
||||
than from among shapechanger's preferred forms) */
|
||||
than from among shapechanger's preferred forms).
|
||||
Vampires are the exception. */
|
||||
struct permonst *tmpcham = rndmonst();
|
||||
mtmp->cham = mcham;
|
||||
(void) newcham(mtmp, rndmonst(), FALSE, FALSE);
|
||||
if (is_vampshifter(mtmp)){
|
||||
int chamidx = select_newcham_form(mtmp);
|
||||
if (chamidx != NON_PM)
|
||||
tmpcham = &mons[chamidx];
|
||||
}
|
||||
if (mtmp->cham != PM_VLAD_THE_IMPALER)
|
||||
(void) newcham(mtmp,tmpcham,FALSE, FALSE);
|
||||
}
|
||||
} else if (mndx == PM_WIZARD_OF_YENDOR) {
|
||||
mtmp->iswiz = TRUE;
|
||||
@@ -1021,8 +1031,6 @@ register int mmflags;
|
||||
mitem = SPE_DIG;
|
||||
} else if (mndx == PM_GHOST && !(mmflags & MM_NONAME)) {
|
||||
mtmp = christen_monst(mtmp, rndghostname());
|
||||
} else if (mndx == PM_VLAD_THE_IMPALER) {
|
||||
mitem = CANDELABRUM_OF_INVOCATION;
|
||||
} else if (mndx == PM_CROESUS) {
|
||||
mitem = TWO_HANDED_SWORD;
|
||||
} else if (ptr->msound == MS_NEMESIS) {
|
||||
|
||||
@@ -890,7 +890,7 @@ hitmu(mtmp, mattk)
|
||||
|
||||
/* First determine the base damage done */
|
||||
dmg = d((int)mattk->damn, (int)mattk->damd);
|
||||
if(is_undead(mdat) && midnight())
|
||||
if((is_undead(mdat) || is_vampshifter(mtmp)) && midnight())
|
||||
dmg += d((int)mattk->damn, (int)mattk->damd); /* extra damage */
|
||||
|
||||
/* Next a cancellation factor */
|
||||
@@ -1550,7 +1550,8 @@ dopois:
|
||||
if (Half_physical_damage
|
||||
/* Mitre of Holiness */
|
||||
|| (Role_if(PM_PRIEST) && uarmh && is_quest_artifact(uarmh) &&
|
||||
(is_undead(mtmp->data) || is_demon(mtmp->data))))
|
||||
(is_undead(mtmp->data) ||
|
||||
is_demon(mtmp->data) || is_vampshifter(mtmp))))
|
||||
dmg = (dmg+1) / 2;
|
||||
|
||||
if (permdmg) { /* Death's life force drain */
|
||||
|
||||
88
src/mon.c
88
src/mon.c
@@ -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;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* SCCS Id: @(#)mondata.c 3.4 2003/06/02 */
|
||||
/* SCCS Id: @(#)mondata.c 3.4 2004/06/12 */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -63,7 +63,7 @@ struct monst *mon;
|
||||
struct obj *wep = ((mon == &youmonst) ? uwep : MON_WEP(mon));
|
||||
|
||||
return (boolean)(is_undead(ptr) || is_demon(ptr) || is_were(ptr) ||
|
||||
ptr == &mons[PM_DEATH] ||
|
||||
ptr == &mons[PM_DEATH] || is_vampshifter(mon) ||
|
||||
(wep && wep->oartifact && defends(AD_DRLI, wep)));
|
||||
}
|
||||
|
||||
@@ -226,6 +226,13 @@ struct permonst *ptr;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
boolean
|
||||
mon_hates_silver(mon)
|
||||
struct monst *mon;
|
||||
{
|
||||
return (is_vampshifter(mon) || hates_silver(mon->data));
|
||||
}
|
||||
|
||||
boolean
|
||||
hates_silver(ptr)
|
||||
register struct permonst *ptr;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* SCCS Id: @(#)monmove.c 3.4 2002/04/06 */
|
||||
/* SCCS Id: @(#)monmove.c 3.4 2004/06/12 */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -13,6 +13,9 @@ STATIC_DCL int FDECL(disturb,(struct monst *));
|
||||
STATIC_DCL void FDECL(distfleeck,(struct monst *,int *,int *,int *));
|
||||
STATIC_DCL int FDECL(m_arrival, (struct monst *));
|
||||
STATIC_DCL void FDECL(watch_on_duty,(struct monst *));
|
||||
STATIC_DCL boolean FDECL(stuff_prevents_passage, (struct monst *));
|
||||
STATIC_OVL int FDECL(vamp_shift, (struct monst *,struct permonst *));
|
||||
|
||||
|
||||
boolean /* TRUE : mtmp died */
|
||||
mb_trapped(mtmp)
|
||||
@@ -936,6 +939,7 @@ not_special:
|
||||
if (can_tunnel) 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)) flag |= NOGARLIC;
|
||||
if (throws_rocks(ptr)) flag |= ALLOW_ROCK;
|
||||
if (can_open) flag |= OPENDOOR;
|
||||
if (can_unlock) flag |= UNLOCKDOOR;
|
||||
@@ -1118,7 +1122,9 @@ postmov:
|
||||
struct rm *here = &levl[mtmp->mx][mtmp->my];
|
||||
boolean btrapped = (here->doormask & D_TRAPPED);
|
||||
|
||||
if(here->doormask & (D_LOCKED|D_CLOSED) && amorphous(ptr)) {
|
||||
if(here->doormask & (D_LOCKED|D_CLOSED) &&
|
||||
(amorphous(ptr) || (!amorphous(ptr) && can_fog(mtmp) &&
|
||||
vamp_shift(mtmp, &mons[PM_FOG_CLOUD])))) {
|
||||
if (flags.verbose && canseemon(mtmp))
|
||||
pline("%s %s under the door.", Monnam(mtmp),
|
||||
(ptr == &mons[PM_FOG_CLOUD] ||
|
||||
@@ -1346,7 +1352,8 @@ register struct monst *mtmp;
|
||||
|| ((mx != u.ux || my != u.uy) &&
|
||||
!passes_walls(mtmp->data) &&
|
||||
(!ACCESSIBLE(levl[mx][my].typ) ||
|
||||
(closed_door(mx, my) && !can_ooze(mtmp))))
|
||||
(closed_door(mx, my) &&
|
||||
!(can_ooze(mtmp) || can_fog(mtmp)))))
|
||||
|| !couldsee(mx, my));
|
||||
} else {
|
||||
found_you:
|
||||
@@ -1392,21 +1399,24 @@ xchar x,y;
|
||||
}
|
||||
#endif /* BARGETHROUGH */
|
||||
|
||||
boolean
|
||||
can_ooze(mtmp)
|
||||
/*
|
||||
* Inventory prevents passage under door.
|
||||
* Used by can_ooze() and can_fog().
|
||||
*/
|
||||
STATIC_OVL boolean
|
||||
stuff_prevents_passage(mtmp)
|
||||
struct monst *mtmp;
|
||||
{
|
||||
struct obj *chain, *obj;
|
||||
|
||||
if (!amorphous(mtmp->data)) return FALSE;
|
||||
if (mtmp == &youmonst) {
|
||||
#ifndef GOLDOBJ
|
||||
if (u.ugold > 100L) return FALSE;
|
||||
if (u.ugold > 100L) return TRUE;
|
||||
#endif
|
||||
chain = invent;
|
||||
} else {
|
||||
#ifndef GOLDOBJ
|
||||
if (mtmp->mgold > 100L) return FALSE;
|
||||
if (mtmp->mgold > 100L) return TRUE;
|
||||
#endif
|
||||
chain = mtmp->minvent;
|
||||
}
|
||||
@@ -1414,7 +1424,7 @@ struct monst *mtmp;
|
||||
int typ = obj->otyp;
|
||||
|
||||
#ifdef GOLDOBJ
|
||||
if (typ == COIN_CLASS && obj->quan > 100L) return FALSE;
|
||||
if (typ == COIN_CLASS && obj->quan > 100L) return TRUE;
|
||||
#endif
|
||||
if (obj->oclass != GEM_CLASS &&
|
||||
!(typ >= ARROW && typ <= BOOMERANG) &&
|
||||
@@ -1441,11 +1451,47 @@ struct monst *mtmp;
|
||||
typ != TIN_WHISTLE && typ != MAGIC_WHISTLE &&
|
||||
typ != MAGIC_MARKER && typ != TIN_OPENER &&
|
||||
typ != SKELETON_KEY && typ != LOCK_PICK
|
||||
) return FALSE;
|
||||
if (Is_container(obj) && obj->cobj) return FALSE;
|
||||
|
||||
) return TRUE;
|
||||
if (Is_container(obj) && obj->cobj) return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
boolean
|
||||
can_ooze(mtmp)
|
||||
struct monst *mtmp;
|
||||
{
|
||||
if (!amorphous(mtmp->data) ||
|
||||
stuff_prevents_passage(mtmp))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* monster can change form into a fog if necessary */
|
||||
boolean
|
||||
can_fog(mtmp)
|
||||
struct monst *mtmp;
|
||||
{
|
||||
if ((is_vampshifter(mtmp) || mtmp->data->mlet == S_VAMPIRE) &&
|
||||
!Protection_from_shape_changers && !stuff_prevents_passage(mtmp))
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
STATIC_OVL int
|
||||
vamp_shift(mon,ptr)
|
||||
struct monst *mon;
|
||||
struct permonst *ptr;
|
||||
{
|
||||
int reslt = 0;
|
||||
if (mon->cham != CHAM_ORDINARY) {
|
||||
if (ptr == &mons[mon->cham])
|
||||
mon->cham = CHAM_ORDINARY;
|
||||
reslt = newcham(mon, ptr, FALSE, FALSE);
|
||||
} else if (mon->cham == CHAM_ORDINARY && ptr != mon->data) {
|
||||
mon->cham = monsndx(mon->data);
|
||||
reslt = newcham(mon, ptr, FALSE, FALSE);
|
||||
}
|
||||
return reslt;
|
||||
}
|
||||
/*monmove.c*/
|
||||
|
||||
12
src/monst.c
12
src/monst.c
@@ -1997,16 +1997,16 @@ struct permonst _mons2[] = {
|
||||
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
|
||||
SIZ(WT_HUMAN, 400, 0, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP|MR_POISON, 0,
|
||||
M1_FLY|M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN,
|
||||
M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_STRONG|M2_NASTY, M3_INFRAVISIBLE,
|
||||
CLR_RED),
|
||||
M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_STRONG|M2_NASTY|M2_SHAPESHIFTER,
|
||||
M3_INFRAVISIBLE, CLR_RED),
|
||||
MON("vampire lord", S_VAMPIRE,
|
||||
LVL(12, 14, 0, 50, -9), (G_GENO|G_NOCORPSE|1),
|
||||
A(ATTK(AT_CLAW, AD_PHYS, 1, 8), ATTK(AT_BITE, AD_DRLI, 1, 8),
|
||||
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
|
||||
SIZ(WT_HUMAN, 400, 0, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP|MR_POISON, 0,
|
||||
M1_FLY|M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN,
|
||||
M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_STRONG|M2_NASTY|M2_LORD|M2_MALE,
|
||||
M3_INFRAVISIBLE, CLR_BLUE),
|
||||
M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_STRONG|M2_NASTY|M2_LORD|M2_MALE|
|
||||
M2_SHAPESHIFTER, M3_INFRAVISIBLE, CLR_BLUE),
|
||||
#if 0 /* DEFERRED */
|
||||
MON("vampire mage", S_VAMPIRE,
|
||||
LVL(20, 14, -4, 50, -9), (G_GENO|G_NOCORPSE|1),
|
||||
@@ -2015,7 +2015,7 @@ struct permonst _mons2[] = {
|
||||
SIZ(WT_HUMAN, 400, 0, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP|MR_POISON, 0,
|
||||
M1_FLY|M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN,
|
||||
M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_STRONG|M2_NASTY|M2_LORD|M2_MALE|
|
||||
M2_MAGIC, M3_INFRAVISIBLE, HI_ZAP),
|
||||
M2_MAGIC|M2_SHAPESHIFTER, M3_INFRAVISIBLE, HI_ZAP),
|
||||
#endif
|
||||
MON("Vlad the Impaler", S_VAMPIRE,
|
||||
LVL(14, 18, -3, 80, -10), (G_NOGEN|G_NOCORPSE|G_UNIQ),
|
||||
@@ -2024,7 +2024,7 @@ struct permonst _mons2[] = {
|
||||
SIZ(WT_HUMAN, 400, 0, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP|MR_POISON, 0,
|
||||
M1_FLY|M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN,
|
||||
M2_NOPOLY|M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_PNAME|M2_STRONG|
|
||||
M2_NASTY|M2_PRINCE|M2_MALE,
|
||||
M2_NASTY|M2_PRINCE|M2_MALE|M2_SHAPESHIFTER,
|
||||
M3_WAITFORU|M3_WANTSCAND|M3_INFRAVISIBLE, HI_LORD),
|
||||
/*
|
||||
* Wraiths
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* SCCS Id: @(#)mthrowu.c 3.4 2003/11/26 */
|
||||
/* SCCS Id: @(#)mthrowu.c 3.4 2004/06/12 */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -182,7 +182,7 @@ boolean verbose; /* give message(s) even when you can't see what happened */
|
||||
}
|
||||
}
|
||||
if (objects[otmp->otyp].oc_material == SILVER &&
|
||||
hates_silver(mtmp->data)) {
|
||||
mon_hates_silver(mtmp)) {
|
||||
if (vis) pline_The("silver sears %s flesh!",
|
||||
s_suffix(mon_nam(mtmp)));
|
||||
else if (verbose) pline("Its flesh is seared!");
|
||||
@@ -201,7 +201,8 @@ boolean verbose; /* give message(s) even when you can't see what happened */
|
||||
if (mtmp->mhp < 1) {
|
||||
if (vis || verbose)
|
||||
pline("%s is %s!", Monnam(mtmp),
|
||||
(nonliving(mtmp->data) || !canspotmon(mtmp))
|
||||
(nonliving(mtmp->data) ||
|
||||
is_vampshifter(mtmp) || !canspotmon(mtmp))
|
||||
? "destroyed" : "killed");
|
||||
/* don't blame hero for unknown rolling boulder trap */
|
||||
if (!context.mon_moving &&
|
||||
|
||||
@@ -1848,7 +1848,7 @@ skipmsg:
|
||||
if (!where_to) {
|
||||
pline_The("whip slips free."); /* not `The_whip' */
|
||||
return 1;
|
||||
} else if (where_to == 3 && hates_silver(mtmp->data) &&
|
||||
} else if (where_to == 3 && mon_hates_silver(mtmp) &&
|
||||
objects[obj->otyp].oc_material == SILVER) {
|
||||
/* this monster won't want to catch a silver
|
||||
weapon; drop it at hero's feet instead */
|
||||
@@ -1929,7 +1929,8 @@ struct monst *mtmp;
|
||||
if (difficulty < 6 && !rn2(30))
|
||||
return rn2(6) ? POT_POLYMORPH : WAN_POLYMORPH;
|
||||
|
||||
if (!rn2(40) && !nonliving(pm)) return AMULET_OF_LIFE_SAVING;
|
||||
if (!rn2(40) && !nonliving(pm) && !is_vampshifter(mtmp))
|
||||
return AMULET_OF_LIFE_SAVING;
|
||||
|
||||
switch (rn2(3)) {
|
||||
case 0:
|
||||
@@ -1997,7 +1998,7 @@ struct obj *obj;
|
||||
break;
|
||||
case AMULET_CLASS:
|
||||
if (typ == AMULET_OF_LIFE_SAVING)
|
||||
return (boolean)(!nonliving(mon->data));
|
||||
return (boolean)(!(nonliving(mon->data) || is_vampshifter(mon)));
|
||||
if (typ == AMULET_OF_REFLECTION)
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
@@ -233,11 +233,12 @@ int psflags;
|
||||
int mntmp = NON_PM;
|
||||
int tries=0;
|
||||
boolean forcecontrol = (psflags == 1);
|
||||
boolean monsterpoly = (psflags == 2);
|
||||
boolean draconian = (uarm &&
|
||||
uarm->otyp >= GRAY_DRAGON_SCALE_MAIL &&
|
||||
uarm->otyp <= YELLOW_DRAGON_SCALES);
|
||||
boolean iswere = (u.ulycn >= LOW_PM || is_were(youmonst.data));
|
||||
boolean isvamp = (youmonst.data->mlet == S_VAMPIRE || u.umonnum == PM_VAMPIRE_BAT);
|
||||
boolean isvamp = (youmonst.data->mlet == S_VAMPIRE);
|
||||
boolean was_floating = (Levitation || Flying);
|
||||
|
||||
if(!Polymorph_control && !forcecontrol && !draconian && !iswere && !isvamp) {
|
||||
@@ -250,7 +251,7 @@ int psflags;
|
||||
}
|
||||
old_light = Upolyd ? emits_light(youmonst.data) : 0;
|
||||
|
||||
if (Polymorph_control || forcecontrol) {
|
||||
if ((Polymorph_control || forcecontrol) && !monsterpoly) {
|
||||
do {
|
||||
getlin("Become what kind of monster? [type the name]",
|
||||
buf);
|
||||
@@ -288,10 +289,21 @@ int psflags;
|
||||
else
|
||||
mntmp = u.ulycn;
|
||||
} else {
|
||||
if (youmonst.data->mlet == S_VAMPIRE)
|
||||
mntmp = PM_VAMPIRE_BAT;
|
||||
else
|
||||
mntmp = PM_VAMPIRE;
|
||||
if (youmonst.data->mlet == S_VAMPIRE) {
|
||||
mntmp = (youmonst.data != &mons[PM_VAMPIRE] &&
|
||||
!rn2(10)) ? PM_WOLF :
|
||||
!rn2(4) ? PM_FOG_CLOUD : PM_VAMPIRE_BAT;
|
||||
if (Polymorph_control) {
|
||||
char buf[BUFSZ];
|
||||
Sprintf(buf, "Become %s?",
|
||||
an(mons[mntmp].mname));
|
||||
if (yn(buf) != 'y') return;
|
||||
}
|
||||
if (Unchanging) {
|
||||
pline("You fail to transform!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* if polymon fails, "you feel" message has been given
|
||||
so don't follow up with another polymon or newman */
|
||||
@@ -1077,6 +1089,21 @@ dohide()
|
||||
return(1);
|
||||
}
|
||||
|
||||
int
|
||||
dopoly()
|
||||
{
|
||||
boolean isvampire = youmonst.data->mlet == S_VAMPIRE;
|
||||
struct permonst *savedat = youmonst.data;
|
||||
if (isvampire) {
|
||||
polyself(2);
|
||||
if (savedat != youmonst.data) {
|
||||
You("transform into %s.", an(youmonst.data->mname));
|
||||
newsym(u.ux,u.uy);
|
||||
}
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
int
|
||||
domindblast()
|
||||
{
|
||||
|
||||
@@ -1211,7 +1211,7 @@ boolean your_fault;
|
||||
break;
|
||||
case POT_WATER:
|
||||
if (is_undead(mon->data) || is_demon(mon->data) ||
|
||||
is_were(mon->data)) {
|
||||
is_were(mon->data) || is_vampshifter(mon)) {
|
||||
if (obj->blessed) {
|
||||
pline("%s %s in pain!", Monnam(mon),
|
||||
is_silent(mon->data) ? "writhes" : "shrieks");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* SCCS Id: @(#)pray.c 3.4 2003/10/26 */
|
||||
/* SCCS Id: @(#)pray.c 3.4 2004/06/12 */
|
||||
/* Copyright (c) Benson I. Margulies, Mike Stephenson, Steve Linhart, 1989. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -1697,6 +1697,7 @@ doturn()
|
||||
distu(mtmp->mx,mtmp->my) > range) continue;
|
||||
|
||||
if (!mtmp->mpeaceful && (is_undead(mtmp->data) ||
|
||||
is_vampshifter(mtmp) ||
|
||||
(is_demon(mtmp->data) && (u.ulevel > (MAXULEV/2))))) {
|
||||
|
||||
mtmp->msleeping = 0;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* SCCS Id: @(#)region.c 3.4 2002/10/15 */
|
||||
/* SCCS Id: @(#)region.c 3.4 2004/06/12 */
|
||||
/* Copyright (c) 1996 by Jean-Christophe Collet */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -922,7 +922,8 @@ genericptr_t p2;
|
||||
mtmp = (struct monst *) p2;
|
||||
|
||||
/* Non living and non breathing monsters are not concerned */
|
||||
if (!nonliving(mtmp->data) && !breathless(mtmp->data)) {
|
||||
if (!(nonliving(mtmp->data) || is_vampshifter(mtmp))
|
||||
&& !breathless(mtmp->data)) {
|
||||
if (cansee(mtmp->mx, mtmp->my))
|
||||
pline("%s coughs!", Monnam(mtmp));
|
||||
if (heros_fault(reg)) setmangry(mtmp);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* SCCS Id: @(#)sounds.c 3.4 2002/05/06 */
|
||||
/* SCCS Id: @(#)sounds.c 3.4 2004/06/12 */
|
||||
/* Copyright (c) 1989 Janet Walz, Mike Threepoint */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -157,7 +157,7 @@ dosounds()
|
||||
if (level.flags.has_morgue && !rn2(200)) {
|
||||
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
|
||||
if (DEADMONSTER(mtmp)) continue;
|
||||
if (is_undead(mtmp->data) &&
|
||||
if ((is_undead(mtmp->data) || is_vampshifter(mtmp)) &&
|
||||
mon_in_room(mtmp, MORGUE)) {
|
||||
switch (rn2(2)+hallu) {
|
||||
case 0:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* SCCS Id: @(#)spell.c 3.4 2003/01/17 */
|
||||
/* SCCS Id: @(#)spell.c 3.4 2004/06/12 */
|
||||
/* Copyright (c) M. Stephenson 1988 */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -284,7 +284,8 @@ raise_dead:
|
||||
mtmp2 = mtmp->nmon; /* tamedog() changes chain */
|
||||
if (DEADMONSTER(mtmp)) continue;
|
||||
|
||||
if (is_undead(mtmp->data) && cansee(mtmp->mx, mtmp->my)) {
|
||||
if ((is_undead(mtmp->data) || is_vampshifter(mtmp)) &&
|
||||
cansee(mtmp->mx, mtmp->my)) {
|
||||
mtmp->mpeaceful = TRUE;
|
||||
if(sgn(mtmp->data->maligntyp) == sgn(u.ualign.type)
|
||||
&& distu(mtmp->mx, mtmp->my) < 4)
|
||||
|
||||
@@ -472,7 +472,8 @@ int *fail_reason;
|
||||
else mon->mundetected = FALSE;
|
||||
|
||||
if ((x == u.ux && y == u.uy) || cause == ANIMATE_SPELL) {
|
||||
const char *comes_to_life = nonliving(mon->data) ?
|
||||
const char *comes_to_life = (nonliving(mon->data) ||
|
||||
is_vampshifter(mon)) ?
|
||||
"moves" : "comes to life";
|
||||
if (cause == ANIMATE_SPELL)
|
||||
pline("%s %s!", upstart(statuename),
|
||||
|
||||
17
src/uhitm.c
17
src/uhitm.c
@@ -1,4 +1,4 @@
|
||||
/* SCCS Id: @(#)uhitm.c 3.4 2003/03/14 */
|
||||
/* SCCS Id: @(#)uhitm.c 3.4 2004/06/12 */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -570,7 +570,8 @@ int thrown;
|
||||
tmp = rnd(2);
|
||||
valid_weapon_attack = (tmp > 1);
|
||||
/* blessed gloves give bonuses when fighting 'bare-handed' */
|
||||
if (uarmg && uarmg->blessed && (is_undead(mdat) || is_demon(mdat)))
|
||||
if (uarmg && uarmg->blessed &&
|
||||
(is_undead(mdat) || is_demon(mdat) || is_vampshifter(mon)))
|
||||
tmp += rnd(4);
|
||||
/* So do silver rings. Note: rings are worn under gloves, so you
|
||||
* don't get both bonuses.
|
||||
@@ -580,7 +581,7 @@ int thrown;
|
||||
barehand_silver_rings++;
|
||||
if (uright && objects[uright->otyp].oc_material == SILVER)
|
||||
barehand_silver_rings++;
|
||||
if (barehand_silver_rings && hates_silver(mdat)) {
|
||||
if (barehand_silver_rings && mon_hates_silver(mon)) {
|
||||
tmp += rnd(20);
|
||||
silvermsg = TRUE;
|
||||
}
|
||||
@@ -609,7 +610,7 @@ int thrown;
|
||||
else
|
||||
tmp = rnd(2);
|
||||
if (objects[obj->otyp].oc_material == SILVER
|
||||
&& hates_silver(mdat)) {
|
||||
&& mon_hates_silver(mon)) {
|
||||
silvermsg = TRUE; silverobj = TRUE;
|
||||
/* if it will already inflict dmg, make it worse */
|
||||
tmp += rnd((tmp) ? 20 : 10);
|
||||
@@ -676,7 +677,7 @@ int thrown;
|
||||
hittxt = TRUE;
|
||||
}
|
||||
if (objects[obj->otyp].oc_material == SILVER
|
||||
&& hates_silver(mdat)) {
|
||||
&& mon_hates_silver(mon)) {
|
||||
silvermsg = TRUE; silverobj = TRUE;
|
||||
}
|
||||
#ifdef STEED
|
||||
@@ -833,7 +834,7 @@ int thrown;
|
||||
#undef useup_eggs
|
||||
}
|
||||
case CLOVE_OF_GARLIC: /* no effect against demons */
|
||||
if (is_undead(mdat)) {
|
||||
if (is_undead(mdat) || is_vampshifter(mon)) {
|
||||
monflee(mon, d(2, 4), FALSE, TRUE);
|
||||
}
|
||||
tmp = 1;
|
||||
@@ -905,7 +906,7 @@ int thrown;
|
||||
* so we need another silver check.
|
||||
*/
|
||||
if (objects[obj->otyp].oc_material == SILVER
|
||||
&& hates_silver(mdat)) {
|
||||
&& mon_hates_silver(mon)) {
|
||||
tmp += rnd(20);
|
||||
silvermsg = TRUE; silverobj = TRUE;
|
||||
}
|
||||
@@ -1067,7 +1068,7 @@ int thrown;
|
||||
fmt = "%s is seared!";
|
||||
}
|
||||
/* note: s_suffix returns a modifiable buffer */
|
||||
if (!noncorporeal(mdat))
|
||||
if (!noncorporeal(mdat) && !amorphous(mdat))
|
||||
whom = strcat(s_suffix(whom), " flesh");
|
||||
pline(fmt, whom);
|
||||
}
|
||||
|
||||
13
src/weapon.c
13
src/weapon.c
@@ -1,4 +1,4 @@
|
||||
/* SCCS Id: @(#)weapon.c 3.4 2002/11/07 */
|
||||
/* SCCS Id: @(#)weapon.c 3.4 2004/06/12 */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -124,7 +124,7 @@ struct monst *mon;
|
||||
|
||||
/* Blessed weapons used against undead or demons */
|
||||
if (Is_weapon && otmp->blessed &&
|
||||
(is_demon(ptr) || is_undead(ptr))) tmp += 2;
|
||||
(is_demon(ptr) || is_undead(ptr) || is_vampshifter(mon))) tmp += 2;
|
||||
|
||||
if (is_spear(otmp) &&
|
||||
index(kebabable, ptr->mlet)) tmp += 2;
|
||||
@@ -270,11 +270,12 @@ struct monst *mon;
|
||||
otmp->oclass == BALL_CLASS || otmp->oclass == CHAIN_CLASS) {
|
||||
int bonus = 0;
|
||||
|
||||
if (otmp->blessed && (is_undead(ptr) || is_demon(ptr)))
|
||||
if (otmp->blessed &&
|
||||
(is_undead(ptr) || is_demon(ptr) || is_vampshifter(mon)))
|
||||
bonus += rnd(4);
|
||||
if (is_axe(otmp) && is_wooden(ptr))
|
||||
bonus += rnd(4);
|
||||
if (objects[otyp].oc_material == SILVER && hates_silver(ptr))
|
||||
if (objects[otyp].oc_material == SILVER && mon_hates_silver(mon))
|
||||
bonus += rnd(20);
|
||||
|
||||
/* if the weapon is going to get a double damage bonus, adjust
|
||||
@@ -370,7 +371,7 @@ register struct monst *mtmp;
|
||||
if (((strongmonst(mtmp->data) && (mtmp->misc_worn_check & W_ARMS) == 0)
|
||||
|| !objects[pwep[i]].oc_bimanual) &&
|
||||
(objects[pwep[i]].oc_material != SILVER
|
||||
|| !hates_silver(mtmp->data))) {
|
||||
|| !mon_hates_silver(mtmp))) {
|
||||
if ((otmp = oselect(mtmp, pwep[i])) != 0) {
|
||||
propellor = otmp; /* force the monster to wield it */
|
||||
return otmp;
|
||||
@@ -492,7 +493,7 @@ register struct monst *mtmp;
|
||||
if (((strong && !wearing_shield)
|
||||
|| !objects[hwep[i]].oc_bimanual) &&
|
||||
(objects[hwep[i]].oc_material != SILVER
|
||||
|| !hates_silver(mtmp->data)))
|
||||
|| !mon_hates_silver(mtmp)))
|
||||
Oselect(hwep[i]);
|
||||
}
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ struct obj *otmp;
|
||||
case SPE_TURN_UNDEAD:
|
||||
wake = FALSE;
|
||||
if (unturn_dead(mtmp)) wake = TRUE;
|
||||
if (is_undead(mtmp->data)) {
|
||||
if (is_undead(mtmp->data) || is_vampshifter(mtmp)) {
|
||||
reveal_invis = TRUE;
|
||||
wake = TRUE;
|
||||
dmg = rnd(8);
|
||||
@@ -3034,7 +3034,8 @@ struct obj **ootmp; /* to return worn armor for caller to disintegrate */
|
||||
break;
|
||||
}
|
||||
if (nonliving(mon->data) || is_demon(mon->data) ||
|
||||
resists_magm(mon)) { /* similar to player */
|
||||
is_vampshifter(mon) || resists_magm(mon)) {
|
||||
/* similar to player */
|
||||
sho_shieldeff = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user