struct obj *otmp;
boolean self;
{
+ if (otmp->spe < 1) {
+ impossible("Mon zapping wand with %d charges?", otmp->spe);
+ return;
+ }
if (!canseemon(mtmp)) {
int range = couldsee(mtmp->mx, mtmp->my) /* 9 or 5 */
? (BOLT_LIM + 1) : (BOLT_LIM - 3);
#define MUSE_UNICORN_HORN 17
#define MUSE_POT_FULL_HEALING 18
#define MUSE_LIZARD_CORPSE 19
+#define MUSE_WAN_UNDEAD_TURNING 20
/*
#define MUSE_INNATE_TPT 9999
* We cannot use this. Since monsters get unlimited teleportation, if they
{
register struct obj *obj = 0;
struct trap *t;
- int x = mtmp->mx, y = mtmp->my;
- boolean stuck = (mtmp == u.ustuck);
- boolean immobile = (mtmp->data->mmove == 0);
- int fraction;
+ int fraction, x = mtmp->mx, y = mtmp->my;
+ boolean stuck = (mtmp == u.ustuck),
+ immobile = (mtmp->data->mmove == 0);
if (is_animal(mtmp->data) || mindless(mtmp->data))
return FALSE;
return TRUE;
}
+ /* monsters aren't given wands of undead turning but if they
+ happen to have picked one up, use it against corpse wielder;
+ when applicable, use it now even if 'mtmp' isn't wounded */
+ if (!mtmp->mpeaceful && !nohands(mtmp->data)
+ && uwep && uwep->otyp == CORPSE
+ && touch_petrifies(&mons[uwep->corpsenm])
+ && !poly_when_stoned(mtmp->data) && !resists_ston(mtmp)
+ && lined_up(mtmp)) { /* only lines up if distu range is within 5*5 */
+ /* could use m_carrying(), then nxtobj() when matching wand
+ is empty, but direct traversal is actually simpler here */
+ for (obj = mtmp->minvent; obj; obj = obj->nobj)
+ if (obj->otyp == WAN_UNDEAD_TURNING && obj->spe > 0) {
+ g.m.defensive = obj;
+ g.m.has_defense = MUSE_WAN_UNDEAD_TURNING;
+ return TRUE;
+ }
+ }
+
fraction = u.ulevel < 10 ? 5 : u.ulevel < 14 ? 4 : 3;
if (mtmp->mhp >= mtmp->mhpmax
|| (mtmp->mhp >= 10 && mtmp->mhp * fraction >= mtmp->mhpmax))
(coord *) 0);
return 2;
}
+ case MUSE_WAN_UNDEAD_TURNING:
+ g.zap_oseen = oseen;
+ mzapwand(mtmp, otmp, FALSE);
+ g.m_using = TRUE;
+ mbhit(mtmp, rn1(8, 6), mbhitm, bhito, otmp);
+ g.m_using = FALSE;
+ return 2;
case MUSE_WAN_CREATE_MONSTER: {
coord cc;
- /* pm: 0 => random, eel => aquatic, croc => amphibious */
- struct permonst *pm =
- !is_pool(mtmp->mx, mtmp->my)
- ? 0
- : &mons[u.uinwater ? PM_GIANT_EEL : PM_CROCODILE];
struct monst *mon;
+ /* pm: 0 => random, eel => aquatic, croc => amphibious */
+ struct permonst *pm = !is_pool(mtmp->mx, mtmp->my) ? 0
+ : &mons[u.uinwater ? PM_GIANT_EEL : PM_CROCODILE];
if (!enexto(&cc, mtmp->mx, mtmp->my, pm))
return 0;
register struct obj *otmp;
{
int tmp;
- boolean reveal_invis = FALSE;
+ boolean reveal_invis = FALSE, hits_you = (mtmp == &g.youmonst);
- if (mtmp != &g.youmonst) {
+ if (!hits_you && otmp->otyp != WAN_UNDEAD_TURNING) {
mtmp->msleeping = 0;
if (mtmp->m_ap_type)
seemimic(mtmp);
switch (otmp->otyp) {
case WAN_STRIKING:
reveal_invis = TRUE;
- if (mtmp == &g.youmonst) {
- if (g.zap_oseen)
- makeknown(WAN_STRIKING);
+ if (hits_you) {
if (Antimagic) {
shieldeff(u.ux, u.uy);
pline("Boing!");
break;
#if 0 /* disabled because find_offensive() never picks WAN_TELEPORTATION */
case WAN_TELEPORTATION:
- if (mtmp == &g.youmonst) {
+ if (hits_you) {
+ tele();
if (g.zap_oseen)
makeknown(WAN_TELEPORTATION);
- tele();
} else {
/* for consistency with zap.c, don't identify */
if (mtmp->ispriest && *in_rooms(mtmp->mx, mtmp->my, TEMPLE)) {
case SPE_CANCELLATION:
(void) cancel_monst(mtmp, otmp, FALSE, TRUE, FALSE);
break;
+ case WAN_UNDEAD_TURNING: {
+ boolean learnit = FALSE;
+
+ if (hits_you) {
+ unturn_you();
+ learnit = g.zap_oseen;
+ } else {
+ boolean wake = FALSE;
+
+ if (unturn_dead(mtmp)) /* affects mtmp's invent, not mtmp */
+ wake = TRUE;
+ if (is_undead(mtmp->data) || is_vampshifter(mtmp)) {
+ wake = reveal_invis = TRUE;
+ /* context.bypasses=True: if resist() happens to be fatal,
+ make_corpse() will set obj->bypass on the new corpse
+ so that mbhito() will skip it instead of reviving it */
+ g.context.bypasses = TRUE; /* for make_corpse() */
+ (void) resist(mtmp, WAND_CLASS, rnd(8), NOTELL);
+ }
+ if (wake) {
+ if (!DEADMONSTER(mtmp))
+ wakeup(mtmp, FALSE);
+ learnit = g.zap_oseen;
+ }
+ }
+ if (learnit)
+ makeknown(WAN_UNDEAD_TURNING);
+ break;
}
- if (reveal_invis) {
- if (!DEADMONSTER(mtmp) && cansee(g.bhitpos.x, g.bhitpos.y)
- && !canspotmon(mtmp))
- map_invisible(g.bhitpos.x, g.bhitpos.y);
+ default:
+ break;
}
+ if (reveal_invis && !DEADMONSTER(mtmp)
+ && cansee(g.bhitpos.x, g.bhitpos.y) && !canspotmon(mtmp))
+ map_invisible(g.bhitpos.x, g.bhitpos.y);
+
return 0;
}
int typ = obj->otyp;
/* don't let monsters interact with protected items on the floor */
- if ((obj->where == OBJ_FLOOR)
- && (obj->ox == mon->mx) && (obj->oy == mon->my)
+ if (obj->where == OBJ_FLOOR
+ && (obj->ox == mon->mx && obj->oy == mon->my)
&& onscary(obj->ox, obj->oy, mon)) {
return FALSE;
}
if (objects[typ].oc_dir == RAY || typ == WAN_STRIKING
|| typ == WAN_TELEPORTATION || typ == WAN_CREATE_MONSTER)
return TRUE;
+ if (typ == WAN_UNDEAD_TURNING)
+ return carrying(CORPSE) || (Upolyd && is_undead(g.youmonst.data));
break;
case POTION_CLASS:
if (typ == POT_HEALING || typ == POT_EXTRA_HEALING
return res;
}
+void
+unturn_you()
+{
+ (void) unturn_dead(&g.youmonst); /* hit carried corpses and eggs */
+
+ if (is_undead(g.youmonst.data)) {
+ You_feel("frightened and %sstunned.", Stunned ? "even more " : "");
+ make_stunned((HStun & TIMEOUT) + (long) rnd(30), FALSE);
+ } else {
+ You("shudder in dread.");
+ }
+}
+
/* cancel obj, possibly carried by you or a monster */
void
cancel_item(obj)
} else if (obj->otyp == CORPSE) {
struct monst *mtmp;
xchar ox, oy;
+ boolean by_u = !g.context.mon_moving;
int corpsenm = corpse_revive_type(obj);
char *corpsname = cxname_singular(obj);
if (canspotmon(mtmp)) {
pline("%s is resurrected!",
upstart(noname_monnam(mtmp, ARTICLE_THE)));
- learn_it = TRUE;
+ learn_it = by_u ? TRUE : g.zap_oseen;
} else {
/* saw corpse but don't see monster: maybe
mtmp is invisible, or has been placed at
You_hear("%s reviving.", corpsname);
else
You_hear("a defibrillator.");
- learn_it = TRUE;
+ learn_it = by_u ? TRUE : g.zap_oseen;
}
if (canspotmon(mtmp))
/* didn't see corpse but do see monster: it
case WAN_UNDEAD_TURNING:
case SPE_TURN_UNDEAD:
learn_it = TRUE;
- (void) unturn_dead(&g.youmonst);
- if (is_undead(g.youmonst.data)) {
- You_feel("frightened and %sstunned.",
- Stunned ? "even more " : "");
- make_stunned((HStun & TIMEOUT) + (long) rnd(30), FALSE);
- } else
- You("shudder in dread.");
+ unturn_you();
break;
case SPE_HEALING:
case SPE_EXTRA_HEALING: