aklys fixes

track which locations had updates that could be seen in tmp_at()
to aid in cleanup.

ensure that nothing is shown for places that the hero can't see
(internal buglist entry 3161).

adjust several aklys messages to better reflect the tethering
aspect.
This commit is contained in:
nhmall
2026-06-04 15:36:12 -04:00
parent ecfa78f974
commit 2edf27f0f0
2 changed files with 125 additions and 42 deletions
+59 -18
View File
@@ -1164,6 +1164,7 @@ tether_glyph(coordxy x, coordxy y)
static struct tmp_glyph {
coord saved[TMP_AT_MAX_GLYPHS]; /* previously updated positions */
boolean shown_on_map[TMP_AT_MAX_GLYPHS];
int sidx; /* index of next unused slot in saved[] */
int style; /* either DISP_BEAM or DISP_FLASH or DISP_ALWAYS */
int glyph; /* glyph to use when printing */
@@ -1175,6 +1176,7 @@ tmp_at(coordxy x, coordxy y)
{
static struct tmp_glyph *tglyph = (struct tmp_glyph *) 0;
struct tmp_glyph *tmp;
boolean suppress_show = FALSE;
switch (x) {
case DISP_BEAM:
@@ -1220,27 +1222,42 @@ tmp_at(coordxy x, coordxy y)
int i;
/* Erase (reset) from source to end */
for (i = 0; i < tglyph->sidx; i++)
for (i = 0; i < tglyph->sidx; i++) {
newsym(tglyph->saved[i].x, tglyph->saved[i].y);
tglyph->shown_on_map[i] = FALSE;
}
} else if (tglyph->style == DISP_TETHER) {
int i;
if (y == BACKTRACK && tglyph->sidx > 1) {
/* backtrack */
for (i = tglyph->sidx - 1; i > 0; i--) {
newsym(tglyph->saved[i].x, tglyph->saved[i].y);
show_glyph(tglyph->saved[i - 1].x,
tglyph->saved[i - 1].y, tglyph->glyph);
flush_screen(0); /* make sure it shows up */
nh_delay_output();
if (tglyph->shown_on_map[i]) {
newsym(tglyph->saved[i].x, tglyph->saved[i].y);
tglyph->shown_on_map[i] = FALSE;
}
if (cansee(tglyph->saved[i - 1].x,
tglyph->saved[i - 1].y)) {
tglyph->shown_on_map[i - 1] = TRUE;
show_glyph(tglyph->saved[i - 1].x,
tglyph->saved[i - 1].y, tglyph->glyph);
flush_screen(0); /* make sure it shows up */
nh_delay_output();
}
}
tglyph->sidx = 1;
}
for (i = 0; i < tglyph->sidx; i++)
newsym(tglyph->saved[i].x, tglyph->saved[i].y);
for (i = 0; i < tglyph->sidx; i++) {
if (tglyph->shown_on_map[i])
newsym(tglyph->saved[i].x, tglyph->saved[i].y);
}
} else { /* DISP_FLASH or DISP_ALWAYS */
if (tglyph->sidx) /* been called at least once */
newsym(tglyph->saved[0].x, tglyph->saved[0].y);
if (tglyph->sidx) { /* been called at least once */
if (tglyph->shown_on_map[0]) {
newsym(tglyph->saved[0].x, tglyph->saved[0].y);
tglyph->shown_on_map[0] = FALSE;
}
}
}
/* tglyph->sidx = 0; -- about to be freed, so not necessary */
tmp = tglyph->prev;
@@ -1253,10 +1270,13 @@ tmp_at(coordxy x, coordxy y)
if (!isok(x, y))
break;
if (tglyph->style == DISP_BEAM || tglyph->style == DISP_ALL) {
if (tglyph->style != DISP_ALL && !cansee(x, y))
break;
if (tglyph->sidx >= TMP_AT_MAX_GLYPHS)
break; /* too many locations */
if (tglyph->style != DISP_ALL && !cansee(x, y)) {
tglyph->shown_on_map[tglyph->sidx] = FALSE;
suppress_show = TRUE;
break;
}
/* save pos for later erasing */
tglyph->saved[tglyph->sidx].x = x;
tglyph->saved[tglyph->sidx].y = y;
@@ -1269,27 +1289,48 @@ tmp_at(coordxy x, coordxy y)
px = tglyph->saved[tglyph->sidx - 1].x;
py = tglyph->saved[tglyph->sidx - 1].y;
show_glyph(px, py, tether_glyph(px, py));
if (cansee(px, py)) {
tglyph->shown_on_map[tglyph->sidx - 1] = TRUE;
show_glyph(px, py, tether_glyph(px, py));
} else {
tglyph->shown_on_map[tglyph->sidx - 1] = FALSE;
suppress_show = TRUE;
}
}
/* save pos for later use or erasure */
tglyph->saved[tglyph->sidx].x = x;
tglyph->saved[tglyph->sidx].y = y;
if (!cansee(x, y)) {
tglyph->shown_on_map[tglyph->sidx] = FALSE;
suppress_show = TRUE;
} else {
/* happens at end of this default case */
tglyph->shown_on_map[tglyph->sidx] = TRUE;
}
tglyph->sidx += 1;
} else { /* DISP_FLASH/ALWAYS */
if (tglyph
->sidx) { /* not first call, so reset previous pos */
if (tglyph->sidx) { /* not first call, so reset previous pos */
newsym(tglyph->saved[0].x, tglyph->saved[0].y);
tglyph->shown_on_map[0] = FALSE;
tglyph->sidx = 0; /* display is presently up to date */
}
if (!cansee(x, y) && tglyph->style != DISP_ALWAYS)
if (!cansee(x, y) && tglyph->style != DISP_ALWAYS) {
suppress_show = TRUE;
tglyph->shown_on_map[0] = FALSE;
break;
} else {
/* happens at end of this default case */
tglyph->shown_on_map[0] = TRUE;
}
tglyph->saved[0].x = x;
tglyph->saved[0].y = y;
tglyph->sidx = 1;
}
show_glyph(x, y, tglyph->glyph); /* show it */
flush_screen(0); /* make sure it shows up */
if (!suppress_show) {
show_glyph(x, y, tglyph->glyph); /* show it */
flush_screen(0); /* make sure it shows up */
}
break;
} /* end switch */
}
+66 -24
View File
@@ -1729,46 +1729,88 @@ throwit(
} else {
int dmg = rn2(2);
if (tethered_weapon) {
/* It's tethered, so it usually returns to your
* inventory, despite impairment */
obj = addinv_before(obj, oldslot);
encumber_msg();
/* addinv autoquivers an aklys if quiver is empty;
if obj is quivered, remove it before wielding */
if (obj->owornmask & W_QUIVER)
setuqwep((struct obj *) 0);
#if 0
setuwep(obj);
set_twoweap(twoweap); /* u.twoweap = twoweap */
#endif
if (cansee(gb.bhitpos.x, gb.bhitpos.y))
newsym(gb.bhitpos.x, gb.bhitpos.y);
}
if (!dmg) {
pline(Blind ? "%s lands %s your %s."
: "%s back to you, landing %s your %s.",
Blind ? Something : Tobjnam(obj, "return"),
Levitation ? "beneath" : "at",
makeplural(body_part(FOOT)));
if (tethered_weapon) {
pline(Blind ? "%s%s back and is left"
" dangling from your %s."
: "%s is left dangling from your %s.",
Blind ? "Your tethered weapon" : Tobjnam(obj, "return"),
Blind ? " snaps" : "",
body_part(ARM));
} else {
pline(Blind
? "%s lands %s your %s."
: "%s back to you, landing %s your %s.",
Blind ? Something : Tobjnam(obj, "return"),
Levitation ? "beneath" : "at",
makeplural(body_part(FOOT)));
}
} else {
dmg += rnd(3);
pline(Blind ? "%s your %s!"
if (tethered_weapon) {
Your("tethered %s your %s!",
Blind ? "weapon returns and hits" : Tobjnam(obj, "hit"),
body_part(ARM));
} else {
pline(
Blind
? "%s your %s!"
: "%s back toward you, hitting your %s!",
Tobjnam(obj, Blind ? "hit" : "fly"),
body_part(ARM));
Tobjnam(obj, Blind ? "hit" : "fly"),
body_part(ARM));
}
if (obj->oartifact)
(void) artifact_hit((struct monst *) 0,
&gy.youmonst, obj, &dmg, 0);
losehp(Maybe_Half_Phys(dmg), killer_xname(obj),
KILLED_BY);
}
if (u.uswallow) {
swallowit(obj);
return;
if (!tethered_weapon) {
if (u.uswallow) {
swallowit(obj);
return;
}
if (!ship_object(obj, u.ux, u.uy, FALSE))
dropy(obj);
} else {
pline_The("%s tether releases from your %s!",
s_suffix(simpleonames(obj)), body_part(ARM));
}
if (!ship_object(obj, u.ux, u.uy, FALSE))
dropy(obj);
}
throwit_return(TRUE);
return;
} else {
if (tethered_weapon)
if (tethered_weapon) {
tmp_at(DISP_END, 0);
/* when this location is stepped on, the weapon will be
auto-picked up due to 'obj->how_lost' of LOST_THROWN;
addinv() prevents thrown Mjollnir from being placed
into the quiver slot, but an aklys will end up there if
that slot is empty at the time; since hero will need to
explicitly rewield the weapon to get throw-and-return
capability back anyway, quivered or not shouldn't matter */
pline("%s to return!", Tobjnam(obj, "fail"));
/* when this location is stepped on, the weapon will be
auto-picked up due to 'obj->how_lost' of LOST_THROWN;
addinv() prevents thrown Mjollnir from being placed
into the quiver slot, but an aklys will end up there if
that slot is empty at the time; since hero will need to
explicitly rewield the weapon to get throw-and-return
capability back anyway, quivered or not shouldn't
matter */
pline("The tether snaps off your %s!",
body_part(ARM));
} else {
pline("%s to return!", Tobjnam(obj, "fail"));
}
if (u.uswallow) {
swallowit(obj);
return;