worldbox-observer-mod/IdleSpectator/WatchCaption.cs
2026-07-14 15:55:22 -05:00

111 lines
2.9 KiB
C#

using NeoModLoader.services;
using UnityEngine;
namespace IdleSpectator;
/// <summary>
/// Persistent "who am I watching" caption while Idle Spectator is active.
/// </summary>
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;
}
}