using NeoModLoader.services; using UnityEngine; namespace IdleSpectator; /// /// Persistent "who am I watching" caption while Idle Spectator is active. /// public static class WatchCaption { private const float RefreshSeconds = 4.5f; private static float _lastShownAt = -999f; private static UnitDossier _current; public static UnitDossier Current => _current; public static string LastHeadline { get; private set; } = ""; public static string LastDetail { get; private set; } = ""; public static string LastCaptionText { get; private set; } = ""; public static void Clear() { _current = null; LastHeadline = ""; LastDetail = ""; LastCaptionText = ""; _lastShownAt = -999f; try { WorldTip.hideNow(); } catch { // ignore } } public static void SetFromInterest(InterestEvent interest) { Actor unit = interest != null && interest.HasFollowUnit ? interest.FollowUnit : (MoveCamera.hasFocusUnit() ? MoveCamera._focus_unit : null); if (unit == null || !unit.isAlive()) { if (interest != null) { LastHeadline = CameraDirector.FormatWatchTip(interest); LastDetail = ""; LastCaptionText = LastHeadline; _current = null; ShowNow(LastCaptionText, force: true); } return; } SetFromActor(unit, interest?.Tier, interest?.Label); } public static void SetFromActor(Actor actor, InterestTier? tier = null, string label = null) { UnitDossier dossier = UnitDossier.FromActor(actor, tier, label); _current = dossier; LastHeadline = dossier.Headline ?? ""; LastDetail = dossier.DetailLine ?? ""; LastCaptionText = dossier.CaptionText ?? ""; ShowNow(LastCaptionText, force: true); LogService.LogInfo("[IdleSpectator][CAPTION] " + LastCaptionText.Replace("\n", " | ")); } public static void Update() { if (!SpectatorMode.Active || !ModSettings.ShowDossierCaption) { return; } if (string.IsNullOrEmpty(LastCaptionText)) { return; } if (Time.unscaledTime - _lastShownAt < RefreshSeconds) { return; } // Refresh so the tip does not fade away during long AFK watches. ShowNow(LastCaptionText, force: false); } private static void ShowNow(string text, bool force) { if (!ModSettings.ShowDossierCaption || string.IsNullOrEmpty(text)) { return; } if (!force && Time.unscaledTime - _lastShownAt < 1f) { return; } WorldTip.showNow(text, pTranslate: false, pPosition: "top", pTime: RefreshSeconds + 2f); _lastShownAt = Time.unscaledTime; } }