Enhance AgentHarness and Chronicle functionality to support detailed jump tracking. Added LastJumpDetail and LastJumpPosition properties for improved state management during jumps. Updated HUD interactions to reflect jump outcomes and integrated new test scenarios for world event navigation.

This commit is contained in:
DazedAnon 2026-07-14 22:03:50 -05:00
parent 94b356c9c8
commit 7876321391
5 changed files with 143 additions and 8 deletions

View file

@ -702,7 +702,50 @@ public static class AgentHarness
_cmdFail++;
}
Emit(cmd, ok, detail: $"jumped={ok} focus={MoveCamera.hasFocusUnit()}");
Emit(
cmd,
ok,
detail:
$"jumped={ok} detail={Chronicle.LastJumpDetail} focus={MoveCamera.hasFocusUnit()} pos={Chronicle.LastJumpPosition}");
break;
}
case "lore_jump_world":
{
Chronicle.ShowHud();
ChronicleHud.SetTab(ChronicleHud.LoreTab.World);
ChronicleEntry target = null;
IReadOnlyList<ChronicleEntry> snap = Chronicle.SnapshotMemory();
for (int i = snap.Count - 1; i >= 0; i--)
{
ChronicleEntry e = snap[i];
if (e == null || e.Kind == ChronicleKind.AgeChapter)
{
continue;
}
if (e.Kind == ChronicleKind.World || e.IsLegend)
{
target = e;
break;
}
}
bool ok = target != null && Chronicle.JumpTo(target);
if (ok)
{
_cmdOk++;
}
else
{
_cmdFail++;
}
Emit(
cmd,
ok,
detail:
$"jumped={ok} detail={Chronicle.LastJumpDetail} focus={MoveCamera.hasFocusUnit()} line={(target != null ? target.Line : "")}");
break;
}
@ -1700,6 +1743,15 @@ public static class AgentHarness
$"fallenFocus={Chronicle.LastFallenFocusDetail} hasFocus={MoveCamera.hasFocusUnit()} pos={Chronicle.LastFallenFocusPosition}";
break;
}
case "world_jump_place":
{
pass = Chronicle.LastJumpDetail == "place"
&& !MoveCamera.hasFocusUnit()
&& Chronicle.LastJumpPosition.sqrMagnitude > 0.0001f;
detail =
$"jump={Chronicle.LastJumpDetail} hasFocus={MoveCamera.hasFocusUnit()} pos={Chronicle.LastJumpPosition}";
break;
}
case "fallen_killer_camera":
{
Actor focus = MoveCamera.hasFocusUnit() ? MoveCamera._focus_unit : null;

View file

@ -449,6 +449,12 @@ public static class Chronicle
ChronicleHud.SetVisible(false);
}
/// <summary>Harness: how the last JumpTo resolved (unit:id | place | none).</summary>
public static string LastJumpDetail { get; private set; } = "";
/// <summary>Harness: world position used by the last place-style JumpTo.</summary>
public static Vector3 LastJumpPosition { get; private set; } = Vector3.zero;
public static bool JumpToLatest()
{
// Prefer a Memory landmark when it can resolve a unit/position; else focus history.
@ -463,15 +469,37 @@ public static class Chronicle
public static bool JumpTo(ChronicleEntry entry)
{
LastJumpDetail = "none";
LastJumpPosition = Vector3.zero;
if (entry == null || entry.Kind == ChronicleKind.AgeChapter)
{
return false;
}
// World Memory landmarks: always go to the recorded place when we have one,
// even if the related unit is gone or has moved on.
bool memoryPlaceFirst = entry.Kind == ChronicleKind.World || entry.IsLegend;
if (memoryPlaceFirst && EntryHasWorldPosition(entry))
{
CameraDirector.ClearFollow();
CameraDirector.PanTo(entry.Position);
LastJumpDetail = "place";
LastJumpPosition = entry.Position;
LogService.LogInfo(
$"[IdleSpectator][MEMORY] jump place pos={entry.Position} line={entry.DisplayLine}");
return true;
}
Actor unit = FindUnitById(entry.SubjectId);
if (unit != null && unit.isAlive())
{
return FocusSubject(unit);
bool ok = FocusSubject(unit);
if (ok)
{
LastJumpDetail = "unit:" + entry.SubjectId;
}
return ok;
}
if (entry.OtherId != 0)
@ -479,13 +507,24 @@ public static class Chronicle
Actor other = FindUnitById(entry.OtherId);
if (other != null && other.isAlive())
{
return FocusSubject(other);
bool ok = FocusSubject(other);
if (ok)
{
LastJumpDetail = "unit:" + entry.OtherId;
}
return ok;
}
}
if (entry.Position != Vector3.zero)
if (EntryHasWorldPosition(entry))
{
CameraDirector.ClearFollow();
CameraDirector.PanTo(entry.Position);
LastJumpDetail = "place";
LastJumpPosition = entry.Position;
LogService.LogInfo(
$"[IdleSpectator][MEMORY] jump place pos={entry.Position} line={entry.DisplayLine}");
return true;
}
@ -1180,13 +1219,37 @@ public static class Chronicle
return false;
}
Vector3 pos = Vector3.zero;
if (MoveCamera.hasFocusUnit() && MoveCamera._focus_unit != null)
{
try
{
pos = MoveCamera._focus_unit.current_position;
}
catch
{
pos = Vector3.zero;
}
}
if (pos.sqrMagnitude < 0.0001f && MoveCamera.instance != null)
{
pos = MoveCamera.instance.transform.position;
pos.z = 0f;
}
if (pos.sqrMagnitude < 0.0001f)
{
pos = new Vector3(48f, 48f, 0f);
}
AppendLandmark(
ChronicleKind.World,
null,
null,
label,
LoreProse.Rewrite(ChronicleKind.World, label),
Vector3.zero,
pos,
"harness",
isLegend: false);
return true;

View file

@ -1549,8 +1549,19 @@ public static class ChronicleHud
ChronicleEntry captured = entry;
button.onClick.AddListener(new UnityAction(() =>
{
if (SpectatorMode.Active)
{
SpectatorMode.SetActive(false, quiet: true);
WatchCaption.PinWhilePaused();
WatchCaption.ShowStatusBanner(
captured.Kind == ChronicleKind.World || captured.IsLegend
? "Paused (viewing world)"
: "Paused (viewing landmark)");
}
bool ok = Chronicle.JumpTo(captured);
LogService.LogInfo($"[IdleSpectator][MEMORY] jump ok={ok} line={captured.DisplayLine}");
LogService.LogInfo(
$"[IdleSpectator][MEMORY] jump ok={ok} detail={Chronicle.LastJumpDetail} line={captured.DisplayLine}");
}));
return go;

View file

@ -447,6 +447,15 @@ internal static class HarnessScenarios
Step("ch17c", "assert", expect: "world_memory_contains", value: "harness_alpha"),
Step("ch17d", "assert", expect: "chronicle_latest_contains", value: "Burned"),
Step("ch17e", "assert", expect: "world_memory_age"),
// Selecting a world event pans to its recorded place (even with no unit there).
Step("ch17j", "lore_jump_world"),
Step("ch17k", "wait", wait: 0.2f),
Step("ch17l", "assert", expect: "world_jump_place"),
Step("ch17m", "assert", expect: "focus", value: "false"),
// Restore a living focus for the rest of the scenario.
Step("ch17n", "focus", asset: "auto"),
Step("ch17o", "wait", wait: 0.2f),
Step("ch17p", "assert", expect: "focus", value: "true"),
// World Memory panel + dossier controls
Step("ch18", "chronicle_open"),

View file

@ -1,7 +1,7 @@
{
"name": "IdleSpectator",
"author": "dazed",
"version": "0.12.14",
"description": "AFK Idle Spectator (I) + Lore (L). Tabs: World / Living / Fallen (newest first).",
"version": "0.12.16",
"description": "AFK Idle Spectator (I) + Lore (L). World events pan to location; Living/Fallen tabs.",
"GUID": "com.dazed.idlespectator"
}