Heart of Ahriman hack (trunk only)

From a four year old news posting:  hero was levitating via #invoke
on the Heart of Ahriman, then dropping that artifact yielded:
  You drop a gray stone named The Heart of Ahriman.
  You float gently to the floor.
  A gray stone named The Heart of Ahriman hits the floor.
That might be strictly correct, assuming that both hero and stone fall at
the same speed; if the stone was dropped from perhaps waist height then
the hero's feet would touch first.  But it looks strange, like a cartoon
where something hangs in midair until someone notices that it should fall.

     Removing the artifact from inventory causes the #invoke property to
toggle off.  Unfortunately it has to be done here before the object can
be placed at its destination.  Modifying message order seemed unviable;
this fix fiddles with the Levitation property in order to defer hero's
descent until after object handling is finished.  Now same setup gives:
  You drop a gray stone named The Heart of Ahriman.
  A gray stone named The Heart of Ahriman hits the floor.
  You float gently to the floor.
  You see here a gray stone named The Heart of Ahriman.
This commit is contained in:
nethack.rankin
2007-06-03 01:05:43 +00:00
parent 9abdff361b
commit 66f95ef37c
4 changed files with 36 additions and 0 deletions

View File

@@ -1475,6 +1475,33 @@ nothing_special:
return 1;
}
/* will freeing this object from inventory cause levitation to end? */
boolean
finesse_ahriman(obj)
struct obj *obj;
{
const struct artifact *oart;
struct prop save_Lev;
boolean result;
/* if we aren't levitating or this isn't an artifact which confers
levitation via #invoke then freeinv() won't toggle levitation */
if (!Levitation || (oart = get_artifact(obj)) == 0 ||
oart->inv_prop != LEVITATION || !(ELevitation & W_ARTI))
return FALSE;
/* arti_invoke(off) -> float_down() clears I_SPECIAL|TIMEOUT & W_ARTI;
probe ahead to see whether that actually results in floating down;
(this assumes that there aren't two simultaneously invoked artifacts
both conferring levitation--safe, since if there were two of them,
invoking the 2nd would negate the 1st rather than stack with it) */
save_Lev = u.uprops[LEVITATION];
HLevitation &= ~(I_SPECIAL|TIMEOUT);
ELevitation &= ~W_ARTI;
result = (boolean)!Levitation;
u.uprops[LEVITATION] = save_Lev;
return result;
}
/* WAC return TRUE if artifact is always lit */
boolean

View File

@@ -484,6 +484,12 @@ register struct obj *obj;
}
#endif
if (!can_reach_floor(TRUE)) {
/* we might be levitating due to #invoke Heart of Ahriman;
if so, levitation would end during call to freeinv()
and we want hitfloor() to happen before float_down() */
boolean levhack = finesse_ahriman(obj);
if (levhack) ELevitation = W_ART; /* other than W_ARTI */
if(flags.verbose) You("drop %s.", doname(obj));
#ifndef GOLDOBJ
if (obj->oclass != COIN_CLASS || obj == invent) freeinv(obj);
@@ -493,6 +499,7 @@ register struct obj *obj;
freeinv(obj);
#endif
hitfloor(obj);
if (levhack) float_down(I_SPECIAL|TIMEOUT, W_ARTI|W_ART);
return(1);
}
if (!IS_ALTAR(levl[u.ux][u.uy].typ) && flags.verbose)