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

@@ -241,6 +241,7 @@ engulfer under influence of conflict or confusion could swallow monster at
unicorn horn restoration no longer overrides sustain ability characteristic
hider monster revived from corpse would start out hidden (even if own corpse
was only object around to hide under)
fix sequencing issues with dropping #invoked Heart of Ahriman
Platform- and/or Interface-Specific Fixes

View File

@@ -78,6 +78,7 @@ E int FDECL(disp_artifact_discoveries, (winid));
E boolean FDECL(artifact_hit, (struct monst *,struct monst *,
struct obj *,int *,int));
E int NDECL(doinvoke);
E boolean FDECL(finesse_ahriman, (struct obj *));
E void FDECL(arti_speak, (struct obj *));
E boolean FDECL(artifact_light, (struct obj *));
E long FDECL(spec_m2, (struct obj *));

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)