- Add Dossier/Saga tabs, Design A panel, and hover preview with read-pause - Persist observed saga facts across roster churn; pin subject without stale fallback - Restore Saga after Open Lore; hide redundant Kind · Climax spine under matching tips - Densify dossier header/chips and keep the cast rail as stable top chrome - Extend harness coverage for hover restore, empty pick, Evidence, and Lore return
135 lines
3.9 KiB
C#
135 lines
3.9 KiB
C#
using System.Collections.Generic;
|
|
|
|
namespace IdleSpectator;
|
|
|
|
/// <summary>
|
|
/// Compatibility façade over <see cref="LifeSagaPresentation"/>.
|
|
/// Prefer <see cref="LifeSagaPresentation.Build"/> for new UI.
|
|
/// </summary>
|
|
public static class LifeSagaOverview
|
|
{
|
|
public static LifeSagaSnapshot BuildSnapshot(LifeSagaSlot slot)
|
|
{
|
|
var snapshot = new LifeSagaSnapshot();
|
|
if (slot == null || slot.UnitId == 0)
|
|
{
|
|
return snapshot;
|
|
}
|
|
|
|
LifeSagaViewModel model = LifeSagaPresentation.Build(slot.UnitId);
|
|
snapshot.UnitId = model.UnitId;
|
|
snapshot.Header = model.Name;
|
|
snapshot.Subtitle = model.Title;
|
|
if (!string.IsNullOrEmpty(model.StakeLine))
|
|
{
|
|
snapshot.Rows.Add(new LifeSagaSnapshotRow
|
|
{
|
|
Kind = LifeSagaSnapshotRowKind.Headline,
|
|
Text = model.StakeLine
|
|
});
|
|
}
|
|
|
|
if (model.Cast.Count > 0)
|
|
{
|
|
var parts = new List<string>(model.Cast.Count);
|
|
for (int i = 0; i < model.Cast.Count; i++)
|
|
{
|
|
parts.Add(model.Cast[i].Relation + " " + model.Cast[i].Name);
|
|
}
|
|
|
|
snapshot.Rows.Add(new LifeSagaSnapshotRow
|
|
{
|
|
Kind = LifeSagaSnapshotRowKind.Circle,
|
|
Text = string.Join(" · ", parts)
|
|
});
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(model.EvidenceLine))
|
|
{
|
|
snapshot.Rows.Add(new LifeSagaSnapshotRow
|
|
{
|
|
Kind = LifeSagaSnapshotRowKind.Current,
|
|
Text = model.EvidenceTitle + ": " + model.EvidenceLine
|
|
});
|
|
}
|
|
|
|
for (int i = 0; i < model.Legacy.Count; i++)
|
|
{
|
|
snapshot.Rows.Add(new LifeSagaSnapshotRow
|
|
{
|
|
Kind = LifeSagaSnapshotRowKind.Chapter,
|
|
ChapterKind = ToChapterKind(model.Legacy[i].Kind),
|
|
Text = model.Legacy[i].Line
|
|
});
|
|
}
|
|
|
|
return snapshot;
|
|
}
|
|
|
|
public static string Build(LifeSagaSlot slot)
|
|
{
|
|
return LifeSagaPresentation.BuildPlainText(slot);
|
|
}
|
|
|
|
public static float StandoutTraitScore(Actor actor)
|
|
{
|
|
return UnitDossier.ReadStandoutTraitNames(actor, 1).Count > 0 ? 100f : 0f;
|
|
}
|
|
|
|
private static LifeSagaChapterKind ToChapterKind(LifeSagaFactKind kind)
|
|
{
|
|
switch (kind)
|
|
{
|
|
case LifeSagaFactKind.Kill:
|
|
case LifeSagaFactKind.RivalEarned:
|
|
case LifeSagaFactKind.HardArcCombat:
|
|
return LifeSagaChapterKind.Combat;
|
|
case LifeSagaFactKind.WarJoin:
|
|
case LifeSagaFactKind.WarEnd:
|
|
case LifeSagaFactKind.HardArcWar:
|
|
return LifeSagaChapterKind.War;
|
|
case LifeSagaFactKind.PlotJoin:
|
|
case LifeSagaFactKind.PlotEnd:
|
|
case LifeSagaFactKind.HardArcPlot:
|
|
return LifeSagaChapterKind.Plot;
|
|
case LifeSagaFactKind.BondFormed:
|
|
case LifeSagaFactKind.HardArcLove:
|
|
return LifeSagaChapterKind.Love;
|
|
case LifeSagaFactKind.BondBroken:
|
|
case LifeSagaFactKind.Death:
|
|
case LifeSagaFactKind.HardArcGrief:
|
|
return LifeSagaChapterKind.Grief;
|
|
default:
|
|
return LifeSagaChapterKind.Unknown;
|
|
}
|
|
}
|
|
}
|
|
|
|
public enum LifeSagaSnapshotRowKind
|
|
{
|
|
Headline,
|
|
Current,
|
|
Circle,
|
|
Qualities,
|
|
Chapter
|
|
}
|
|
|
|
public sealed class LifeSagaSnapshotRow
|
|
{
|
|
public LifeSagaSnapshotRowKind Kind;
|
|
public LifeSagaChapterKind ChapterKind;
|
|
public string Text = "";
|
|
}
|
|
|
|
public sealed class LifeSagaSnapshot
|
|
{
|
|
public long UnitId;
|
|
public string Header = "";
|
|
public string Subtitle = "";
|
|
public readonly List<LifeSagaSnapshotRow> Rows = new List<LifeSagaSnapshotRow>();
|
|
|
|
public string ToPlainText()
|
|
{
|
|
return LifeSagaPresentation.BuildPlainText(UnitId);
|
|
}
|
|
}
|