197 lines
6 KiB
C#
197 lines
6 KiB
C#
using NeoModLoader.General;
|
|
using NeoModLoader.services;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
namespace IdleSpectator;
|
|
|
|
/// <summary>
|
|
/// Persistent compact dossier card (top-left) while Idle Spectator is active.
|
|
/// Replaces WorldTip for dossier text so AFK watching does not spam giant orange toasts.
|
|
/// </summary>
|
|
public static class WatchCaption
|
|
{
|
|
private const float PanelWidth = 260f;
|
|
private const float PanelHeight = 72f;
|
|
|
|
private static GameObject _root;
|
|
private static Text _nameText;
|
|
private static Text _reasonText;
|
|
private static Text _metaText;
|
|
private static UnitDossier _current;
|
|
private static bool _visible;
|
|
|
|
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 = "";
|
|
SetVisible(false);
|
|
}
|
|
|
|
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;
|
|
EnsureBuilt();
|
|
ApplyLines(LastHeadline, "", "");
|
|
SetVisible(ModSettings.ShowDossierCaption && SpectatorMode.Active);
|
|
}
|
|
|
|
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 ?? "";
|
|
EnsureBuilt();
|
|
ApplyLines(dossier.Headline, dossier.ReasonLine, dossier.DetailLine);
|
|
SetVisible(ModSettings.ShowDossierCaption && SpectatorMode.Active);
|
|
LogService.LogInfo("[IdleSpectator][CAPTION] " + LastCaptionText.Replace("\n", " | "));
|
|
}
|
|
|
|
public static void Update()
|
|
{
|
|
if (!SpectatorMode.Active || !ModSettings.ShowDossierCaption)
|
|
{
|
|
if (_visible)
|
|
{
|
|
SetVisible(false);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (_root == null && !string.IsNullOrEmpty(LastCaptionText))
|
|
{
|
|
EnsureBuilt();
|
|
if (_current != null)
|
|
{
|
|
ApplyLines(_current.Headline, _current.ReasonLine, _current.DetailLine);
|
|
}
|
|
else
|
|
{
|
|
ApplyLines(LastHeadline, "", LastDetail);
|
|
}
|
|
|
|
SetVisible(true);
|
|
}
|
|
}
|
|
|
|
private static void ApplyLines(string name, string reason, string meta)
|
|
{
|
|
if (_nameText != null)
|
|
{
|
|
_nameText.text = string.IsNullOrEmpty(name) ? "" : name;
|
|
}
|
|
|
|
if (_reasonText != null)
|
|
{
|
|
_reasonText.text = string.IsNullOrEmpty(reason) ? "" : reason;
|
|
}
|
|
|
|
if (_metaText != null)
|
|
{
|
|
_metaText.text = string.IsNullOrEmpty(meta) ? "" : meta;
|
|
}
|
|
}
|
|
|
|
private static void SetVisible(bool visible)
|
|
{
|
|
EnsureBuilt();
|
|
if (_root == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_visible = visible;
|
|
_root.SetActive(visible);
|
|
}
|
|
|
|
private static void EnsureBuilt()
|
|
{
|
|
if (_root != null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Canvas canvas = HudCanvas.Resolve();
|
|
if (canvas == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_root = new GameObject("IdleSpectatorDossierHud", typeof(RectTransform), typeof(Image), typeof(CanvasGroup));
|
|
_root.transform.SetParent(canvas.transform, false);
|
|
|
|
RectTransform rt = _root.GetComponent<RectTransform>();
|
|
rt.anchorMin = new Vector2(0f, 1f);
|
|
rt.anchorMax = new Vector2(0f, 1f);
|
|
rt.pivot = new Vector2(0f, 1f);
|
|
rt.sizeDelta = new Vector2(PanelWidth, PanelHeight);
|
|
rt.anchoredPosition = new Vector2(12f, -12f);
|
|
|
|
Image bg = _root.GetComponent<Image>();
|
|
bg.color = new Color(0.05f, 0.06f, 0.08f, 0.72f);
|
|
bg.raycastTarget = false;
|
|
|
|
CanvasGroup group = _root.GetComponent<CanvasGroup>();
|
|
group.blocksRaycasts = false;
|
|
group.interactable = false;
|
|
|
|
_nameText = HudCanvas.MakeText(_root.transform, "Name", "", 12);
|
|
PlaceLine(_nameText.GetComponent<RectTransform>(), -6f, 22f);
|
|
_nameText.fontStyle = FontStyle.Bold;
|
|
_nameText.color = new Color(0.95f, 0.93f, 0.88f, 1f);
|
|
_nameText.alignment = TextAnchor.MiddleLeft;
|
|
|
|
_reasonText = HudCanvas.MakeText(_root.transform, "Reason", "", 10);
|
|
PlaceLine(_reasonText.GetComponent<RectTransform>(), -28f, 18f);
|
|
_reasonText.color = new Color(0.95f, 0.72f, 0.38f, 1f);
|
|
_reasonText.alignment = TextAnchor.MiddleLeft;
|
|
|
|
_metaText = HudCanvas.MakeText(_root.transform, "Meta", "", 9);
|
|
PlaceLine(_metaText.GetComponent<RectTransform>(), -46f, 18f);
|
|
_metaText.color = new Color(0.72f, 0.75f, 0.78f, 1f);
|
|
_metaText.alignment = TextAnchor.MiddleLeft;
|
|
|
|
_root.SetActive(false);
|
|
_visible = false;
|
|
LogService.LogInfo("[IdleSpectator] Dossier HUD ready (top-left card)");
|
|
}
|
|
|
|
private static void PlaceLine(RectTransform lineRt, float yFromTop, float height)
|
|
{
|
|
lineRt.anchorMin = new Vector2(0f, 1f);
|
|
lineRt.anchorMax = new Vector2(1f, 1f);
|
|
lineRt.pivot = new Vector2(0.5f, 1f);
|
|
lineRt.sizeDelta = new Vector2(-16f, height);
|
|
lineRt.anchoredPosition = new Vector2(0f, yFromTop);
|
|
}
|
|
}
|