if a branch has only one level (Fort Ludios), prevent creation of any level
teleporters there (level definition doesn't have any but wizard mode
wishing could attempt to place one)
+opening/unlocking magic zapped at monster holding the hero will release hold
+ (zap at engulfer already expels hero); zapping at self has same effect
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
extern void learnwand(struct obj *);
extern int bhitm(struct monst *, struct obj *);
+extern void release_hold(void);
extern void probe_monster(struct monst *);
extern boolean get_obj_location(struct obj *, xchar *, xchar *, int);
extern boolean get_mon_location(struct monst *, xchar *, xchar *, int);
affects_objects = FALSE;
switch (obj->otyp) {
+ case WAN_OPENING:
+ if (u.ustuck) {
+ release_hold();
+ if (obj->dknown)
+ makeknown(WAN_OPENING);
+ goto discard_broken_wand;
+ }
+ /*FALLTHRU*/
case WAN_WISHING:
case WAN_NOTHING:
case WAN_LOCKING:
case WAN_PROBING:
case WAN_ENLIGHTENMENT:
- case WAN_OPENING:
case WAN_SECRET_DOOR_DETECTION:
pline(nothing_else_happens);
goto discard_broken_wand;
dmg *= 2;
/*FALLTHRU*/
case WAN_MAGIC_MISSILE:
- wanexpl:
+ wanexpl:
explode(u.ux, u.uy, -(obj->otyp), dmg, WAND_CLASS, expltype);
makeknown(obj->otyp); /* explode describes the effect */
goto discard_broken_wand;
if (obj->otyp == WAN_LIGHT)
litroom(TRUE, obj); /* only needs to be done once */
-discard_broken_wand:
+ discard_broken_wand:
obj = g.current_wand; /* [see dozap() and destroy_item()] */
g.current_wand = 0;
if (obj)
/* note: 3d9 is slightly higher than previous 4d6 */
}
- } else if (attk->aatyp == AT_ENGL && magr->mspec_used) {
- /* can't re-engulf yet; switch to simpler attack */
+ /* holders/engulfers who release the hero have mspec_used set to rnd(2)
+ and can't re-hold/re-engulf until it has been decremented to zero */
+ } else if (magr->mspec_used && (attk->aatyp == AT_ENGL
+ || attk->aatyp == AT_HUGS
+ || attk->adtyp == AD_STCK)) {
+ boolean wimpy = (attk->damd == 0); /* lichen, violet fungus */
+
+ /* can't re-engulf or re-grab yet; switch to simpler attack */
*alt_attk_buf = *attk;
attk = alt_attk_buf;
if (attk->adtyp == AD_ACID || attk->adtyp == AD_ELEC
}
attk->damn = 1; /* relatively weak: 1d6 */
attk->damd = 6;
+ if (wimpy && attk->aatyp == AT_CLAW) {
+ attk->aatyp = AT_TUCH;
+ attk->damn = attk->damd = 0;
+ }
/* barrow wight, Nazgul, erinys have weapon attack for non-physical
damage; force physical damage if attacker has been cancelled or
unstuck(struct monst* mtmp)
{
if (u.ustuck == mtmp) {
+ struct permonst *ptr = mtmp->data;
+
/* do this first so that docrt()'s botl update is accurate;
safe to do as long as u.uswallow is also cleared before docrt() */
set_ustuck((struct monst *) 0);
placebc();
g.vision_full_recalc = 1;
docrt();
- /* prevent swallower (mtmp might have just poly'd into something
- without an engulf attack) from immediately re-engulfing */
- if (attacktype(mtmp->data, AT_ENGL) && !mtmp->mspec_used)
- mtmp->mspec_used = rnd(2);
}
+
+ /* prevent holder/engulfer from immediately re-holding/re-engulfing
+ [note: this call to unstuck() might be because u.ustuck has just
+ changed shape and doesn't have a holding attack any more, hence
+ don't set mspec_used uncondtionally] */
+ if (!mtmp->mspec_used && (dmgtype(ptr, AD_STCK)
+ || attacktype(ptr, AT_ENGL)
+ || attacktype(ptr, AT_HUGS)))
+ mtmp->mspec_used = rnd(2);
}
}
boolean negated = !(rn2(10) >= 3 * armpro);
if (!negated && !sticks(pd) && distu(mdef->mx, mdef->my) <= 2)
- u.ustuck = mdef; /* it's now stuck to you */
+ set_ustuck(mdef); /* it's now stuck to you */
} else if (mdef == &g.youmonst) {
/* mhitu */
int armpro = magic_negation(mdef);
case WAN_OPENING:
case SPE_KNOCK:
wake = FALSE; /* don't want immediate counterattack */
- if (u.uswallow && mtmp == u.ustuck) {
- if (is_animal(mtmp->data)) {
- if (Blind)
- You_feel("a sudden rush of air!");
- else
- pline("%s opens its mouth!", Monnam(mtmp));
- }
- expels(mtmp, mtmp->data, TRUE);
- /* zap which hits steed will only release saddle if it
- doesn't hit a holding or falling trap; playability
- here overrides the more logical target ordering */
+ if (mtmp == u.ustuck) {
+ /* zapping either holder/holdee or self [zapyourself()] will
+ release hero from holder's grasp or holdee from hero's grasp */
+ release_hold();
+ learn_it = TRUE;
+
+ /* zap which hits steed will only release saddle if it
+ doesn't hit a holding or falling trap; playability
+ here overrides the more logical target ordering */
} else if (openholdingtrap(mtmp, &learn_it)) {
break;
} else if (openfallingtrap(mtmp, TRUE, &learn_it)) {
return 0;
}
+/* hero is held by a monster or engulfed or holding a monster and has zapped
+ opening/unlocking magic at holder/engulfer/holdee or at self */
+void
+release_hold()
+{
+ struct monst *mtmp = u.ustuck;
+
+ if (!mtmp) {
+ impossible("release_hold when not held?");
+ } else if (sticks(g.youmonst.data)) {
+ /* order matters if 'holding' status condition is enabled;
+ set_ustuck() will set flag for botl update, You() pline will
+ trigger a status update with "UHold" removed */
+ set_ustuck((struct monst *) 0);
+ You("release %s.", mon_nam(mtmp));
+ } else if (u.uswallow) {
+ if (is_animal(mtmp->data)) {
+ if (!Blind)
+ pline("%s opens its mouth!", Monnam(mtmp));
+ else
+ You_feel("a sudden rush of air!");
+ }
+ /* gives "you get regurgitated" or "you get expelled from <mon>" */
+ expels(mtmp, mtmp->data, TRUE);
+ } else { /* held but not swallowed */
+ char relbuf[BUFSZ];
+
+ unstuck(u.ustuck);
+ if (!nohands(mtmp->data))
+ Sprintf(relbuf, "from %s grasp", s_suffix(mon_nam(mtmp)));
+ else
+ Sprintf(relbuf, "by %s", mon_nam(mtmp));
+ You("are released %s.", relbuf);
+ }
+}
+
void
probe_monster(struct monst *mtmp)
{
break;
case WAN_OPENING:
case SPE_KNOCK:
+ if (u.ustuck) {
+ /* zapping either self or holder/holdee [bhitm()] will release
+ holder's grasp from the hero or hero's grasp from holdee */
+ release_hold();
+ learn_it = TRUE;
+ }
if (Punished) {
learn_it = TRUE;
unpunish();