diff --git a/doc/fixes35.0 b/doc/fixes35.0 index 5b5df3ded..964392143 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -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 diff --git a/include/extern.h b/include/extern.h index d31578afe..2989822d6 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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 *)); diff --git a/src/artifact.c b/src/artifact.c index aa3355f4c..9097daa74 100644 --- a/src/artifact.c +++ b/src/artifact.c @@ -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 diff --git a/src/do.c b/src/do.c index 1253f506d..5a856b3e0 100644 --- a/src/do.c +++ b/src/do.c @@ -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)