fix #H6925 - being trapped vs Levitation/Flying

Make being trapped in/on/over floor block Levitation and Flying, the
way that being inside solid rock already does, and the way levitating
blocks flight.

Blocked levitation still provides enhanced carrying capacity since
magic is attempting to make the hero's body be bouyant.  I think that
that is appropriate but am not completely convinced.

One thing that almost certainly needs fixing is digging a hole when
trapped in the floor or tethered to a buried iron ball, where the
first part of digactualhole() releases the hero from being trapped.
If being released re-enables blocked levitation, the further stages
of digging might not make sense in some circumstances.

I recently realized that being held by a grabbing monster is similar
to being trapped so should also interfere with levitation and flying.
Nothing here attempts to address that.

Save files change, but in a compatible fashion unless trapped at the
time of saving.  If someone saves while trapped prior to this patch,
then applies it and restores, the game will behave as if the patch
wasn't in place--until escape from trap is achieved.  (Not verified.)
This commit is contained in:
PatR
2018-09-30 01:06:59 -07:00
parent 00dfed5b3a
commit 3e19858edd
20 changed files with 330 additions and 149 deletions

View File

@@ -539,11 +539,17 @@ dosinkfall()
int dmg;
boolean lev_boots = (uarmf && uarmf->otyp == LEVITATION_BOOTS),
innate_lev = ((HLevitation & (FROMOUTSIDE | FROMFORM)) != 0L),
ufall = (!innate_lev && !(HFlying || EFlying)); /* BFlying */
/* to handle being chained to buried iron ball, trying to
levitate but being blocked, then moving onto adjacent sink;
no need to worry about being blocked by terrain because we
couldn't be over a sink at the same time */
blockd_lev = (BLevitation == I_SPECIAL),
ufall = (!innate_lev && !blockd_lev
&& !(HFlying || EFlying)); /* BFlying */
if (!ufall) {
You(innate_lev ? "wobble unsteadily for a moment."
: "gain control of your flight.");
You((innate_lev || blockd_lev) ? "wobble unsteadily for a moment."
: "gain control of your flight.");
} else {
long save_ELev = ELevitation, save_HLev = HLevitation;
@@ -1179,6 +1185,10 @@ struct trap *desttrap; /* nonnull if another trap at <x,y> */
if (!u.utrap)
return TRUE; /* sanity check */
/*
* Note: caller should call reset_utrap() when we set u.utrap to 0.
*/
switch (u.utraptype) {
case TT_BEARTRAP:
if (flags.verbose) {
@@ -1203,7 +1213,6 @@ struct trap *desttrap; /* nonnull if another trap at <x,y> */
break;
case TT_WEB:
if (uwep && uwep->oartifact == ART_STING) {
u.utrap = 0;
pline("Sting cuts through the web!");
break; /* escape trap but don't move */
}
@@ -1656,7 +1665,12 @@ domove()
return;
if (u.utrap) {
if (!trapmove(x, y, trap))
boolean moved = trapmove(x, y, trap);
if (!u.utrap)
reset_utrap(TRUE); /* might resume levitation or flight */
/* might not have escaped, or did escape but remain in same spot */
if (!moved)
return;
}
@@ -1927,13 +1941,15 @@ switch_terrain()
|| (Is_waterlevel(&u.uz) && lev->typ == WATER));
if (blocklev) {
/* called from spoteffects(), skip float_down() */
/* called from spoteffects(), stop levitating but skip float_down() */
if (Levitation)
You_cant("levitate in here.");
BLevitation |= FROMOUTSIDE;
} else if (BLevitation) {
BLevitation &= ~FROMOUTSIDE;
if (Levitation)
/* we're probably levitating now; if not, we must be chained
to a buried iron ball so get float_up() feedback for that */
if (Levitation || BLevitation)
float_up();
}
/* the same terrain that blocks levitation also blocks flight */
@@ -2058,7 +2074,7 @@ boolean pick;
spotterrain = levl[u.ux][u.uy].typ;
spotloc.x = u.ux, spotloc.y = u.uy;
/* moving onto different terrain might cause Levitation to toggle */
/* moving onto different terrain might cause Lev or Fly to toggle */
if (spotterrain != levl[u.ux0][u.uy0].typ || !on_level(&u.uz, &u.uz0))
switch_terrain();
@@ -2890,7 +2906,7 @@ boolean k_format;
int
weight_cap()
{
long carrcap, save_ELev = ELevitation;
long carrcap, save_ELev = ELevitation, save_BLev = BLevitation;
/* boots take multiple turns to wear but any properties they
confer are enabled at the start rather than the end; that
@@ -2900,6 +2916,9 @@ weight_cap()
ELevitation &= ~W_ARMF;
float_vs_flight(); /* in case Levitation is blocking Flying */
}
/* levitation is blocked by being trapped in the floor, but it still
functions enough in that situation to enhance carrying capacity */
BLevitation &= ~I_SPECIAL;
carrcap = 25 * (ACURRSTR + ACURR(A_CON)) + 50;
if (Upolyd) {
@@ -2930,8 +2949,9 @@ weight_cap()
carrcap = 0;
}
if (ELevitation != save_ELev) {
if (ELevitation != save_ELev || BLevitation != save_BLev) {
ELevitation = save_ELev;
BLevitation = save_BLev;
float_vs_flight();
}