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
+4
View File
@@ -109,6 +109,10 @@ health-food store that stocks monk-appropriate foods in mine town when monk
give more information about your attributes in debug mode give more information about your attributes in debug mode
polywarn to give intrinsic monster detection of limited species while polymorphed polywarn to give intrinsic monster detection of limited species while polymorphed
rocks can skip on the water sometimes allowing them to pass over water creatures rocks can skip on the water sometimes allowing them to pass over water creatures
vampires can now shapeshift into bats and fog clouds; the latter can be done at
will to slip through locked doors
shapeshifted vampire will transform back to vampire form after you defeat it and
continue to fight in its native form
Platform- and/or Interface-Specific New Features Platform- and/or Interface-Specific New Features
+4
View File
@@ -1196,6 +1196,7 @@ E void NDECL(kill_genocided_monsters);
E void FDECL(golemeffects, (struct monst *,int,int)); E void FDECL(golemeffects, (struct monst *,int,int));
E boolean FDECL(angry_guards, (BOOLEAN_P)); E boolean FDECL(angry_guards, (BOOLEAN_P));
E void NDECL(pacify_guards); E void NDECL(pacify_guards);
E void FDECL(decide_to_shapeshift, (struct monst *,int));
/* ### mondata.c ### */ /* ### mondata.c ### */
@@ -1209,6 +1210,7 @@ E boolean FDECL(resists_blnd, (struct monst *));
E boolean FDECL(can_blnd, (struct monst *,struct monst *,UCHAR_P,struct obj *)); E boolean FDECL(can_blnd, (struct monst *,struct monst *,UCHAR_P,struct obj *));
E boolean FDECL(ranged_attk, (struct permonst *)); E boolean FDECL(ranged_attk, (struct permonst *));
E boolean FDECL(hates_silver, (struct permonst *)); E boolean FDECL(hates_silver, (struct permonst *));
E boolean FDECL(mon_hates_silver, (struct monst *));
E boolean FDECL(passes_bars, (struct permonst *)); E boolean FDECL(passes_bars, (struct permonst *));
E boolean FDECL(can_blow, (struct monst *)); E boolean FDECL(can_blow, (struct monst *));
E boolean FDECL(can_track, (struct permonst *)); E boolean FDECL(can_track, (struct permonst *));
@@ -1247,6 +1249,7 @@ E boolean FDECL(closed_door, (int,int));
E boolean FDECL(accessible, (int,int)); E boolean FDECL(accessible, (int,int));
E void FDECL(set_apparxy, (struct monst *)); E void FDECL(set_apparxy, (struct monst *));
E boolean FDECL(can_ooze, (struct monst *)); E boolean FDECL(can_ooze, (struct monst *));
E boolean FDECL(can_fog, (struct monst *));
#ifdef BARGETHROUGH #ifdef BARGETHROUGH
E boolean FDECL(should_displace, (struct monst *,coord *,long *,int, E boolean FDECL(should_displace, (struct monst *,coord *,long *,int,
XCHAR_P,XCHAR_P)); XCHAR_P,XCHAR_P));
@@ -1591,6 +1594,7 @@ E int NDECL(dospinweb);
E int NDECL(dosummon); E int NDECL(dosummon);
E int NDECL(dogaze); E int NDECL(dogaze);
E int NDECL(dohide); E int NDECL(dohide);
E int NDECL(dopoly);
E int NDECL(domindblast); E int NDECL(domindblast);
E void FDECL(skinback, (BOOLEAN_P)); E void FDECL(skinback, (BOOLEAN_P));
E const char *FDECL(mbodypart, (struct monst *,int)); E const char *FDECL(mbodypart, (struct monst *,int));
+4
View File
@@ -153,6 +153,10 @@ NEARDATA extern coord bhitpos; /* place where throw or zap hits or stops */
#define CORPSTAT_INIT 0x01 /* pass init flag to mkcorpstat */ #define CORPSTAT_INIT 0x01 /* pass init flag to mkcorpstat */
#define CORPSTAT_BURIED 0x02 /* bury the corpse or statue */ #define CORPSTAT_BURIED 0x02 /* bury the corpse or statue */
/* flags for decide_to_shift() */
#define SHIFT_SEENMSG 0x01 /* put out a message if in sight */
#define SHIFT_MSG 0x02 /* always put out a message */
/* special mhpmax value when loading bones monster to flag as extinct or genocided */ /* special mhpmax value when loading bones monster to flag as extinct or genocided */
#define DEFUNCT_MONSTER (-100) #define DEFUNCT_MONSTER (-100)
+3 -1
View File
@@ -176,5 +176,7 @@ struct monst {
#define DEADMONSTER(mon) ((mon)->mhp < 1) #define DEADMONSTER(mon) ((mon)->mhp < 1)
#define is_starting_pet(mon) ((mon)->m_id == context.startingpet_mid) #define is_starting_pet(mon) ((mon)->m_id == context.startingpet_mid)
#define is_vampshifter(mon) ((mon)->cham == PM_VAMPIRE || \
(mon)->cham == PM_VAMPIRE_LORD || \
(mon)->cham == PM_VLAD_THE_IMPALER)
#endif /* MONST_H */ #endif /* MONST_H */
+1 -1
View File
@@ -763,7 +763,7 @@ struct obj *obj;
if (vis) if (vis)
pline("%s can't see anything right now.", Monnam(mtmp)); pline("%s can't see anything right now.", Monnam(mtmp));
/* some monsters do special things */ /* 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) if (vis)
pline ("%s doesn't have a reflection.", Monnam(mtmp)); pline ("%s doesn't have a reflection.", Monnam(mtmp));
} else if(!mtmp->mcan && !mtmp->minvis && } else if(!mtmp->mcan && !mtmp->minvis &&
+2 -1
View File
@@ -464,7 +464,8 @@ domonability()
if(u.uburied) if(u.uburied)
pline("Unfortunately sound does not carry well through rock."); pline("Unfortunately sound does not carry well through rock.");
else aggravate(); 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."); pline("Any special ability you may have is purely reflexive.");
else You("don't have a special ability in your normal form!"); else You("don't have a special ability in your normal form!");
return 0; return 0;
+3 -3
View File
@@ -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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -689,7 +689,7 @@ register struct obj *obj;
return (herbi ? CADAVER : MANFOOD); return (herbi ? CADAVER : MANFOOD);
else return (carni ? CADAVER : MANFOOD); else return (carni ? CADAVER : MANFOOD);
case CLOVE_OF_GARLIC: case CLOVE_OF_GARLIC:
return (is_undead(mon->data) ? TABU : return ((is_undead(mon->data) || is_vampshifter(mon)) ? TABU :
((herbi || starving) ? ACCFOOD : MANFOOD)); ((herbi || starving) ? ACCFOOD : MANFOOD));
case TIN: case TIN:
return (metallivorous(mon->data) ? ACCFOOD : MANFOOD); return (metallivorous(mon->data) ? ACCFOOD : MANFOOD);
@@ -709,7 +709,7 @@ register struct obj *obj;
if (obj->otyp == AMULET_OF_STRANGULATION || if (obj->otyp == AMULET_OF_STRANGULATION ||
obj->otyp == RIN_SLOW_DIGESTION) obj->otyp == RIN_SLOW_DIGESTION)
return TABU; return TABU;
if (hates_silver(mon->data) && if (mon_hates_silver(mon) &&
objects[obj->otyp].oc_material == SILVER) objects[obj->otyp].oc_material == SILVER)
return(TABU); return(TABU);
if (mon->data == &mons[PM_GELATINOUS_CUBE] && is_organic(obj)) if (mon->data == &mons[PM_GELATINOUS_CUBE] && is_organic(obj))
+3 -3
View File
@@ -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. */ /* Copyright (c) Izchak Miller, Mike Stephenson, Steve Linhart, 1989. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -49,8 +49,8 @@ register boolean clumsy;
if (mon->data == &mons[PM_SHADE]) if (mon->data == &mons[PM_SHADE])
dmg = 0; dmg = 0;
if ((is_undead(mon->data) || is_demon(mon->data)) && uarmf && if ((is_undead(mon->data) || is_demon(mon->data) || is_vampshifter(mon))
uarmf->blessed) && uarmf && uarmf->blessed)
blessed_foot_damage = 1; blessed_foot_damage = 1;
if (mon->data == &mons[PM_SHADE] && !blessed_foot_damage) { if (mon->data == &mons[PM_SHADE] && !blessed_foot_damage) {
+2 -2
View File
@@ -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 */ /* Copyright (C) 1990 by Ken Arromdee */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -157,7 +157,7 @@ int expltype;
break; break;
case AD_DISN: case AD_DISN:
explmask[i][j] |= (olet == WAND_CLASS) ? 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); resists_disint(mtmp);
break; break;
case AD_ELEC: case AD_ELEC:
+14 -6
View File
@@ -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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -1001,18 +1001,28 @@ register int mmflags;
LS_MONSTER, (genericptr_t)mtmp); LS_MONSTER, (genericptr_t)mtmp);
mitem = 0; /* extra inventory item for this monster */ 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" */ mtmp->cham = CHAM_ORDINARY; /* default is "not a shapechanger" */
if ((mcham = pm_to_cham(mndx)) != CHAM_ORDINARY) { if ((mcham = pm_to_cham(mndx)) != CHAM_ORDINARY) {
/* this is a shapechanger after all */ /* this is a shapechanger after all */
if (Protection_from_shape_changers) { if (Protection_from_shape_changers) {
; /* stuck in its natural form (CHAM_ORDINARY) */ ; /* stuck in its natural form (CHAM_ORDINARY) */
} else { } else {
/* new shapechanger starts out with random form /* General shapechangers start out with random form
(this explicitly picks something from the normal (this explicitly picks something from the normal
selection for current difficulty level rather 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; 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) { } else if (mndx == PM_WIZARD_OF_YENDOR) {
mtmp->iswiz = TRUE; mtmp->iswiz = TRUE;
@@ -1021,8 +1031,6 @@ register int mmflags;
mitem = SPE_DIG; mitem = SPE_DIG;
} else if (mndx == PM_GHOST && !(mmflags & MM_NONAME)) { } else if (mndx == PM_GHOST && !(mmflags & MM_NONAME)) {
mtmp = christen_monst(mtmp, rndghostname()); mtmp = christen_monst(mtmp, rndghostname());
} else if (mndx == PM_VLAD_THE_IMPALER) {
mitem = CANDELABRUM_OF_INVOCATION;
} else if (mndx == PM_CROESUS) { } else if (mndx == PM_CROESUS) {
mitem = TWO_HANDED_SWORD; mitem = TWO_HANDED_SWORD;
} else if (ptr->msound == MS_NEMESIS) { } else if (ptr->msound == MS_NEMESIS) {
+3 -2
View File
@@ -890,7 +890,7 @@ hitmu(mtmp, mattk)
/* First determine the base damage done */ /* First determine the base damage done */
dmg = d((int)mattk->damn, (int)mattk->damd); 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 */ dmg += d((int)mattk->damn, (int)mattk->damd); /* extra damage */
/* Next a cancellation factor */ /* Next a cancellation factor */
@@ -1550,7 +1550,8 @@ dopois:
if (Half_physical_damage if (Half_physical_damage
/* Mitre of Holiness */ /* Mitre of Holiness */
|| (Role_if(PM_PRIEST) && uarmh && is_quest_artifact(uarmh) && || (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; dmg = (dmg+1) / 2;
if (permdmg) { /* Death's life force drain */ if (permdmg) { /* Death's life force drain */
+81 -7
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 *)); STATIC_DCL long FDECL(mm_displacement, (struct monst *,struct monst *));
#endif #endif
STATIC_DCL int NDECL(pick_animal); STATIC_DCL int NDECL(pick_animal);
STATIC_DCL int FDECL(select_newcham_form, (struct monst *));
STATIC_DCL void FDECL(kill_eggs, (struct obj *)); STATIC_DCL void FDECL(kill_eggs, (struct obj *));
#ifdef REINCARNATION #ifdef REINCARNATION
@@ -530,8 +529,12 @@ mcalcdistress()
mon_regen(mtmp, FALSE); mon_regen(mtmp, FALSE);
/* possibly polymorph shapechangers and lycanthropes */ /* possibly polymorph shapechangers and lycanthropes */
if (mtmp->cham && !rn2(6)) if (mtmp->cham != CHAM_ORDINARY) {
(void) newcham(mtmp, (struct permonst *)0, FALSE, FALSE); 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); were_change(mtmp);
/* gradually time out temporary problems */ /* gradually time out temporary problems */
@@ -917,7 +920,6 @@ max_mon_load(mtmp)
register struct monst *mtmp; register struct monst *mtmp;
{ {
register long maxload; register long maxload;
/* Base monster carrying capacity is equal to human maximum /* Base monster carrying capacity is equal to human maximum
* carrying capacity, or half human maximum if not strong. * carrying capacity, or half human maximum if not strong.
* (for a polymorphed player, the value used would be the * (for a polymorphed player, the value used would be the
@@ -956,7 +958,7 @@ struct obj *otmp;
return FALSE; return FALSE;
if (otyp == CORPSE && is_rider(&mons[otmp->corpsenm])) if (otyp == CORPSE && is_rider(&mons[otmp->corpsenm]))
return FALSE; 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))) (otyp != BELL_OF_OPENING || !is_covetous(mdat)))
return FALSE; 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; !((IS_TREE(ntyp) ? treeok : rockok) && may_dig(nx,ny))) continue;
/* KMH -- Added iron bars */ /* KMH -- Added iron bars */
if (ntyp == IRONBARS && !(flag & ALLOW_BARS)) continue; 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_CLOSED && !(flag & OPENDOOR)) ||
(levl[nx][ny].doormask & D_LOCKED && !(flag & UNLOCKDOOR))) && (levl[nx][ny].doormask & D_LOCKED && !(flag & UNLOCKDOOR))) &&
!thrudoor) continue; !thrudoor) continue;
@@ -1373,7 +1376,7 @@ struct obj *
mlifesaver(mon) mlifesaver(mon)
struct monst *mon; struct monst *mon;
{ {
if (!nonliving(mon->data)) { if (!nonliving(mon->data) || is_vampshifter(mon)) {
struct obj *otmp = which_armor(mon, W_AMUL); struct obj *otmp = which_armor(mon, W_AMUL);
if (otmp && otmp->otyp == AMULET_OF_LIFE_SAVING) if (otmp && otmp->otyp == AMULET_OF_LIFE_SAVING)
@@ -1441,6 +1444,52 @@ register struct monst *mtmp;
lifesaved_monster(mtmp); lifesaved_monster(mtmp);
if (mtmp->mhp > 0) return; 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 #ifdef STEED
/* Player is thrown from his steed when it dies */ /* Player is thrown from his steed when it dies */
if (mtmp == u.usteed) if (mtmp == u.usteed)
@@ -2306,6 +2355,31 @@ pick_animal()
return animal_list[rn2(animal_list_count)]; 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 int
select_newcham_form(mon) select_newcham_form(mon)
struct monst *mon; struct monst *mon;
+9 -2
View File
@@ -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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* 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)); struct obj *wep = ((mon == &youmonst) ? uwep : MON_WEP(mon));
return (boolean)(is_undead(ptr) || is_demon(ptr) || is_were(ptr) || 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))); (wep && wep->oartifact && defends(AD_DRLI, wep)));
} }
@@ -226,6 +226,13 @@ struct permonst *ptr;
return FALSE; return FALSE;
} }
boolean
mon_hates_silver(mon)
struct monst *mon;
{
return (is_vampshifter(mon) || hates_silver(mon->data));
}
boolean boolean
hates_silver(ptr) hates_silver(ptr)
register struct permonst *ptr; register struct permonst *ptr;
+58 -12
View File
@@ -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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* 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 void FDECL(distfleeck,(struct monst *,int *,int *,int *));
STATIC_DCL int FDECL(m_arrival, (struct monst *)); STATIC_DCL int FDECL(m_arrival, (struct monst *));
STATIC_DCL void FDECL(watch_on_duty,(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 */ boolean /* TRUE : mtmp died */
mb_trapped(mtmp) mb_trapped(mtmp)
@@ -936,6 +939,7 @@ not_special:
if (can_tunnel) flag |= ALLOW_DIG; if (can_tunnel) flag |= ALLOW_DIG;
if (is_human(ptr) || ptr == &mons[PM_MINOTAUR]) flag |= ALLOW_SSM; if (is_human(ptr) || ptr == &mons[PM_MINOTAUR]) flag |= ALLOW_SSM;
if (is_undead(ptr) && ptr->mlet != S_GHOST) flag |= NOGARLIC; if (is_undead(ptr) && ptr->mlet != S_GHOST) flag |= NOGARLIC;
if (is_vampshifter(mtmp)) flag |= NOGARLIC;
if (throws_rocks(ptr)) flag |= ALLOW_ROCK; if (throws_rocks(ptr)) flag |= ALLOW_ROCK;
if (can_open) flag |= OPENDOOR; if (can_open) flag |= OPENDOOR;
if (can_unlock) flag |= UNLOCKDOOR; if (can_unlock) flag |= UNLOCKDOOR;
@@ -1118,7 +1122,9 @@ postmov:
struct rm *here = &levl[mtmp->mx][mtmp->my]; struct rm *here = &levl[mtmp->mx][mtmp->my];
boolean btrapped = (here->doormask & D_TRAPPED); 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)) if (flags.verbose && canseemon(mtmp))
pline("%s %s under the door.", Monnam(mtmp), pline("%s %s under the door.", Monnam(mtmp),
(ptr == &mons[PM_FOG_CLOUD] || (ptr == &mons[PM_FOG_CLOUD] ||
@@ -1346,7 +1352,8 @@ register struct monst *mtmp;
|| ((mx != u.ux || my != u.uy) && || ((mx != u.ux || my != u.uy) &&
!passes_walls(mtmp->data) && !passes_walls(mtmp->data) &&
(!ACCESSIBLE(levl[mx][my].typ) || (!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)); || !couldsee(mx, my));
} else { } else {
found_you: found_you:
@@ -1392,21 +1399,24 @@ xchar x,y;
} }
#endif /* BARGETHROUGH */ #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 monst *mtmp;
{ {
struct obj *chain, *obj; struct obj *chain, *obj;
if (!amorphous(mtmp->data)) return FALSE;
if (mtmp == &youmonst) { if (mtmp == &youmonst) {
#ifndef GOLDOBJ #ifndef GOLDOBJ
if (u.ugold > 100L) return FALSE; if (u.ugold > 100L) return TRUE;
#endif #endif
chain = invent; chain = invent;
} else { } else {
#ifndef GOLDOBJ #ifndef GOLDOBJ
if (mtmp->mgold > 100L) return FALSE; if (mtmp->mgold > 100L) return TRUE;
#endif #endif
chain = mtmp->minvent; chain = mtmp->minvent;
} }
@@ -1414,7 +1424,7 @@ struct monst *mtmp;
int typ = obj->otyp; int typ = obj->otyp;
#ifdef GOLDOBJ #ifdef GOLDOBJ
if (typ == COIN_CLASS && obj->quan > 100L) return FALSE; if (typ == COIN_CLASS && obj->quan > 100L) return TRUE;
#endif #endif
if (obj->oclass != GEM_CLASS && if (obj->oclass != GEM_CLASS &&
!(typ >= ARROW && typ <= BOOMERANG) && !(typ >= ARROW && typ <= BOOMERANG) &&
@@ -1441,11 +1451,47 @@ struct monst *mtmp;
typ != TIN_WHISTLE && typ != MAGIC_WHISTLE && typ != TIN_WHISTLE && typ != MAGIC_WHISTLE &&
typ != MAGIC_MARKER && typ != TIN_OPENER && typ != MAGIC_MARKER && typ != TIN_OPENER &&
typ != SKELETON_KEY && typ != LOCK_PICK typ != SKELETON_KEY && typ != LOCK_PICK
) return FALSE; ) return TRUE;
if (Is_container(obj) && obj->cobj) return FALSE; 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; 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*/ /*monmove.c*/
+6 -6
View File
@@ -1997,16 +1997,16 @@ struct permonst _mons2[] = {
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(WT_HUMAN, 400, 0, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP|MR_POISON, 0, SIZ(WT_HUMAN, 400, 0, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP|MR_POISON, 0,
M1_FLY|M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN, M1_FLY|M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN,
M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_STRONG|M2_NASTY, M3_INFRAVISIBLE, M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_STRONG|M2_NASTY|M2_SHAPESHIFTER,
CLR_RED), M3_INFRAVISIBLE, CLR_RED),
MON("vampire lord", S_VAMPIRE, MON("vampire lord", S_VAMPIRE,
LVL(12, 14, 0, 50, -9), (G_GENO|G_NOCORPSE|1), 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), A(ATTK(AT_CLAW, AD_PHYS, 1, 8), ATTK(AT_BITE, AD_DRLI, 1, 8),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(WT_HUMAN, 400, 0, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP|MR_POISON, 0, SIZ(WT_HUMAN, 400, 0, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP|MR_POISON, 0,
M1_FLY|M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN, 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_UNDEAD|M2_STALK|M2_HOSTILE|M2_STRONG|M2_NASTY|M2_LORD|M2_MALE|
M3_INFRAVISIBLE, CLR_BLUE), M2_SHAPESHIFTER, M3_INFRAVISIBLE, CLR_BLUE),
#if 0 /* DEFERRED */ #if 0 /* DEFERRED */
MON("vampire mage", S_VAMPIRE, MON("vampire mage", S_VAMPIRE,
LVL(20, 14, -4, 50, -9), (G_GENO|G_NOCORPSE|1), 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, SIZ(WT_HUMAN, 400, 0, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP|MR_POISON, 0,
M1_FLY|M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN, 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_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 #endif
MON("Vlad the Impaler", S_VAMPIRE, MON("Vlad the Impaler", S_VAMPIRE,
LVL(14, 18, -3, 80, -10), (G_NOGEN|G_NOCORPSE|G_UNIQ), 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, SIZ(WT_HUMAN, 400, 0, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP|MR_POISON, 0,
M1_FLY|M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN, M1_FLY|M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN,
M2_NOPOLY|M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_PNAME|M2_STRONG| 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), M3_WAITFORU|M3_WANTSCAND|M3_INFRAVISIBLE, HI_LORD),
/* /*
* Wraiths * Wraiths
+4 -3
View File
@@ -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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* 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 && if (objects[otmp->otyp].oc_material == SILVER &&
hates_silver(mtmp->data)) { mon_hates_silver(mtmp)) {
if (vis) pline_The("silver sears %s flesh!", if (vis) pline_The("silver sears %s flesh!",
s_suffix(mon_nam(mtmp))); s_suffix(mon_nam(mtmp)));
else if (verbose) pline("Its flesh is seared!"); 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 (mtmp->mhp < 1) {
if (vis || verbose) if (vis || verbose)
pline("%s is %s!", Monnam(mtmp), pline("%s is %s!", Monnam(mtmp),
(nonliving(mtmp->data) || !canspotmon(mtmp)) (nonliving(mtmp->data) ||
is_vampshifter(mtmp) || !canspotmon(mtmp))
? "destroyed" : "killed"); ? "destroyed" : "killed");
/* don't blame hero for unknown rolling boulder trap */ /* don't blame hero for unknown rolling boulder trap */
if (!context.mon_moving && if (!context.mon_moving &&
+4 -3
View File
@@ -1848,7 +1848,7 @@ skipmsg:
if (!where_to) { if (!where_to) {
pline_The("whip slips free."); /* not `The_whip' */ pline_The("whip slips free."); /* not `The_whip' */
return 1; 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) { objects[obj->otyp].oc_material == SILVER) {
/* this monster won't want to catch a silver /* this monster won't want to catch a silver
weapon; drop it at hero's feet instead */ weapon; drop it at hero's feet instead */
@@ -1929,7 +1929,8 @@ struct monst *mtmp;
if (difficulty < 6 && !rn2(30)) if (difficulty < 6 && !rn2(30))
return rn2(6) ? POT_POLYMORPH : WAN_POLYMORPH; 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)) { switch (rn2(3)) {
case 0: case 0:
@@ -1997,7 +1998,7 @@ struct obj *obj;
break; break;
case AMULET_CLASS: case AMULET_CLASS:
if (typ == AMULET_OF_LIFE_SAVING) if (typ == AMULET_OF_LIFE_SAVING)
return (boolean)(!nonliving(mon->data)); return (boolean)(!(nonliving(mon->data) || is_vampshifter(mon)));
if (typ == AMULET_OF_REFLECTION) if (typ == AMULET_OF_REFLECTION)
return TRUE; return TRUE;
break; break;
+33 -6
View File
@@ -233,11 +233,12 @@ int psflags;
int mntmp = NON_PM; int mntmp = NON_PM;
int tries=0; int tries=0;
boolean forcecontrol = (psflags == 1); boolean forcecontrol = (psflags == 1);
boolean monsterpoly = (psflags == 2);
boolean draconian = (uarm && boolean draconian = (uarm &&
uarm->otyp >= GRAY_DRAGON_SCALE_MAIL && uarm->otyp >= GRAY_DRAGON_SCALE_MAIL &&
uarm->otyp <= YELLOW_DRAGON_SCALES); uarm->otyp <= YELLOW_DRAGON_SCALES);
boolean iswere = (u.ulycn >= LOW_PM || is_were(youmonst.data)); 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); boolean was_floating = (Levitation || Flying);
if(!Polymorph_control && !forcecontrol && !draconian && !iswere && !isvamp) { if(!Polymorph_control && !forcecontrol && !draconian && !iswere && !isvamp) {
@@ -250,7 +251,7 @@ int psflags;
} }
old_light = Upolyd ? emits_light(youmonst.data) : 0; old_light = Upolyd ? emits_light(youmonst.data) : 0;
if (Polymorph_control || forcecontrol) { if ((Polymorph_control || forcecontrol) && !monsterpoly) {
do { do {
getlin("Become what kind of monster? [type the name]", getlin("Become what kind of monster? [type the name]",
buf); buf);
@@ -288,10 +289,21 @@ int psflags;
else else
mntmp = u.ulycn; mntmp = u.ulycn;
} else { } else {
if (youmonst.data->mlet == S_VAMPIRE) if (youmonst.data->mlet == S_VAMPIRE) {
mntmp = PM_VAMPIRE_BAT; mntmp = (youmonst.data != &mons[PM_VAMPIRE] &&
else !rn2(10)) ? PM_WOLF :
mntmp = PM_VAMPIRE; !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 /* if polymon fails, "you feel" message has been given
so don't follow up with another polymon or newman */ so don't follow up with another polymon or newman */
@@ -1077,6 +1089,21 @@ dohide()
return(1); 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 int
domindblast() domindblast()
{ {
+1 -1
View File
@@ -1211,7 +1211,7 @@ boolean your_fault;
break; break;
case POT_WATER: case POT_WATER:
if (is_undead(mon->data) || is_demon(mon->data) || if (is_undead(mon->data) || is_demon(mon->data) ||
is_were(mon->data)) { is_were(mon->data) || is_vampshifter(mon)) {
if (obj->blessed) { if (obj->blessed) {
pline("%s %s in pain!", Monnam(mon), pline("%s %s in pain!", Monnam(mon),
is_silent(mon->data) ? "writhes" : "shrieks"); is_silent(mon->data) ? "writhes" : "shrieks");
+2 -1
View File
@@ -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. */ /* Copyright (c) Benson I. Margulies, Mike Stephenson, Steve Linhart, 1989. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -1697,6 +1697,7 @@ doturn()
distu(mtmp->mx,mtmp->my) > range) continue; distu(mtmp->mx,mtmp->my) > range) continue;
if (!mtmp->mpeaceful && (is_undead(mtmp->data) || if (!mtmp->mpeaceful && (is_undead(mtmp->data) ||
is_vampshifter(mtmp) ||
(is_demon(mtmp->data) && (u.ulevel > (MAXULEV/2))))) { (is_demon(mtmp->data) && (u.ulevel > (MAXULEV/2))))) {
mtmp->msleeping = 0; mtmp->msleeping = 0;
+3 -2
View File
@@ -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 */ /* Copyright (c) 1996 by Jean-Christophe Collet */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -922,7 +922,8 @@ genericptr_t p2;
mtmp = (struct monst *) p2; mtmp = (struct monst *) p2;
/* Non living and non breathing monsters are not concerned */ /* 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)) if (cansee(mtmp->mx, mtmp->my))
pline("%s coughs!", Monnam(mtmp)); pline("%s coughs!", Monnam(mtmp));
if (heros_fault(reg)) setmangry(mtmp); if (heros_fault(reg)) setmangry(mtmp);
+2 -2
View File
@@ -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 */ /* Copyright (c) 1989 Janet Walz, Mike Threepoint */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -157,7 +157,7 @@ dosounds()
if (level.flags.has_morgue && !rn2(200)) { if (level.flags.has_morgue && !rn2(200)) {
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp)) continue; if (DEADMONSTER(mtmp)) continue;
if (is_undead(mtmp->data) && if ((is_undead(mtmp->data) || is_vampshifter(mtmp)) &&
mon_in_room(mtmp, MORGUE)) { mon_in_room(mtmp, MORGUE)) {
switch (rn2(2)+hallu) { switch (rn2(2)+hallu) {
case 0: case 0:
+3 -2
View File
@@ -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 */ /* Copyright (c) M. Stephenson 1988 */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -284,7 +284,8 @@ raise_dead:
mtmp2 = mtmp->nmon; /* tamedog() changes chain */ mtmp2 = mtmp->nmon; /* tamedog() changes chain */
if (DEADMONSTER(mtmp)) continue; 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; mtmp->mpeaceful = TRUE;
if(sgn(mtmp->data->maligntyp) == sgn(u.ualign.type) if(sgn(mtmp->data->maligntyp) == sgn(u.ualign.type)
&& distu(mtmp->mx, mtmp->my) < 4) && distu(mtmp->mx, mtmp->my) < 4)
+2 -1
View File
@@ -472,7 +472,8 @@ int *fail_reason;
else mon->mundetected = FALSE; else mon->mundetected = FALSE;
if ((x == u.ux && y == u.uy) || cause == ANIMATE_SPELL) { 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"; "moves" : "comes to life";
if (cause == ANIMATE_SPELL) if (cause == ANIMATE_SPELL)
pline("%s %s!", upstart(statuename), pline("%s %s!", upstart(statuename),
+9 -8
View File
@@ -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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -570,7 +570,8 @@ int thrown;
tmp = rnd(2); tmp = rnd(2);
valid_weapon_attack = (tmp > 1); valid_weapon_attack = (tmp > 1);
/* blessed gloves give bonuses when fighting 'bare-handed' */ /* 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); tmp += rnd(4);
/* So do silver rings. Note: rings are worn under gloves, so you /* So do silver rings. Note: rings are worn under gloves, so you
* don't get both bonuses. * don't get both bonuses.
@@ -580,7 +581,7 @@ int thrown;
barehand_silver_rings++; barehand_silver_rings++;
if (uright && objects[uright->otyp].oc_material == SILVER) if (uright && objects[uright->otyp].oc_material == SILVER)
barehand_silver_rings++; barehand_silver_rings++;
if (barehand_silver_rings && hates_silver(mdat)) { if (barehand_silver_rings && mon_hates_silver(mon)) {
tmp += rnd(20); tmp += rnd(20);
silvermsg = TRUE; silvermsg = TRUE;
} }
@@ -609,7 +610,7 @@ int thrown;
else else
tmp = rnd(2); tmp = rnd(2);
if (objects[obj->otyp].oc_material == SILVER if (objects[obj->otyp].oc_material == SILVER
&& hates_silver(mdat)) { && mon_hates_silver(mon)) {
silvermsg = TRUE; silverobj = TRUE; silvermsg = TRUE; silverobj = TRUE;
/* if it will already inflict dmg, make it worse */ /* if it will already inflict dmg, make it worse */
tmp += rnd((tmp) ? 20 : 10); tmp += rnd((tmp) ? 20 : 10);
@@ -676,7 +677,7 @@ int thrown;
hittxt = TRUE; hittxt = TRUE;
} }
if (objects[obj->otyp].oc_material == SILVER if (objects[obj->otyp].oc_material == SILVER
&& hates_silver(mdat)) { && mon_hates_silver(mon)) {
silvermsg = TRUE; silverobj = TRUE; silvermsg = TRUE; silverobj = TRUE;
} }
#ifdef STEED #ifdef STEED
@@ -833,7 +834,7 @@ int thrown;
#undef useup_eggs #undef useup_eggs
} }
case CLOVE_OF_GARLIC: /* no effect against demons */ 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); monflee(mon, d(2, 4), FALSE, TRUE);
} }
tmp = 1; tmp = 1;
@@ -905,7 +906,7 @@ int thrown;
* so we need another silver check. * so we need another silver check.
*/ */
if (objects[obj->otyp].oc_material == SILVER if (objects[obj->otyp].oc_material == SILVER
&& hates_silver(mdat)) { && mon_hates_silver(mon)) {
tmp += rnd(20); tmp += rnd(20);
silvermsg = TRUE; silverobj = TRUE; silvermsg = TRUE; silverobj = TRUE;
} }
@@ -1067,7 +1068,7 @@ int thrown;
fmt = "%s is seared!"; fmt = "%s is seared!";
} }
/* note: s_suffix returns a modifiable buffer */ /* note: s_suffix returns a modifiable buffer */
if (!noncorporeal(mdat)) if (!noncorporeal(mdat) && !amorphous(mdat))
whom = strcat(s_suffix(whom), " flesh"); whom = strcat(s_suffix(whom), " flesh");
pline(fmt, whom); pline(fmt, whom);
} }
+7 -6
View File
@@ -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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -124,7 +124,7 @@ struct monst *mon;
/* Blessed weapons used against undead or demons */ /* Blessed weapons used against undead or demons */
if (Is_weapon && otmp->blessed && 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) && if (is_spear(otmp) &&
index(kebabable, ptr->mlet)) tmp += 2; index(kebabable, ptr->mlet)) tmp += 2;
@@ -270,11 +270,12 @@ struct monst *mon;
otmp->oclass == BALL_CLASS || otmp->oclass == CHAIN_CLASS) { otmp->oclass == BALL_CLASS || otmp->oclass == CHAIN_CLASS) {
int bonus = 0; 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); bonus += rnd(4);
if (is_axe(otmp) && is_wooden(ptr)) if (is_axe(otmp) && is_wooden(ptr))
bonus += rnd(4); 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); bonus += rnd(20);
/* if the weapon is going to get a double damage bonus, adjust /* 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) if (((strongmonst(mtmp->data) && (mtmp->misc_worn_check & W_ARMS) == 0)
|| !objects[pwep[i]].oc_bimanual) && || !objects[pwep[i]].oc_bimanual) &&
(objects[pwep[i]].oc_material != SILVER (objects[pwep[i]].oc_material != SILVER
|| !hates_silver(mtmp->data))) { || !mon_hates_silver(mtmp))) {
if ((otmp = oselect(mtmp, pwep[i])) != 0) { if ((otmp = oselect(mtmp, pwep[i])) != 0) {
propellor = otmp; /* force the monster to wield it */ propellor = otmp; /* force the monster to wield it */
return otmp; return otmp;
@@ -492,7 +493,7 @@ register struct monst *mtmp;
if (((strong && !wearing_shield) if (((strong && !wearing_shield)
|| !objects[hwep[i]].oc_bimanual) && || !objects[hwep[i]].oc_bimanual) &&
(objects[hwep[i]].oc_material != SILVER (objects[hwep[i]].oc_material != SILVER
|| !hates_silver(mtmp->data))) || !mon_hates_silver(mtmp)))
Oselect(hwep[i]); Oselect(hwep[i]);
} }
+3 -2
View File
@@ -153,7 +153,7 @@ struct obj *otmp;
case SPE_TURN_UNDEAD: case SPE_TURN_UNDEAD:
wake = FALSE; wake = FALSE;
if (unturn_dead(mtmp)) wake = TRUE; if (unturn_dead(mtmp)) wake = TRUE;
if (is_undead(mtmp->data)) { if (is_undead(mtmp->data) || is_vampshifter(mtmp)) {
reveal_invis = TRUE; reveal_invis = TRUE;
wake = TRUE; wake = TRUE;
dmg = rnd(8); dmg = rnd(8);
@@ -3034,7 +3034,8 @@ struct obj **ootmp; /* to return worn armor for caller to disintegrate */
break; break;
} }
if (nonliving(mon->data) || is_demon(mon->data) || 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; sho_shieldeff = TRUE;
break; break;
} }