worldbox-observer-mod/IdleSpectator/Events/EventCatalog.cs
2026-07-21 13:35:07 -05:00

122 lines
4.2 KiB
C#

namespace IdleSpectator;
/// <summary>
/// IdleSpectator event inventory (one type, split across partial files).
///
/// Layer B (ticker): Activity / Life prose for live ids - completeness.
/// Layer A (story camera): only CameraWorthy beats register interest and cut the camera.
///
/// Call sites: EventCatalog.Status / .Happiness / .Combat / …
/// Director only ranks A candidates; it does not author inventory.
///
/// Domain files under Events/Catalogs/:
/// EventCatalog.Status.cs
/// EventCatalog.Happiness.cs
/// EventCatalog.WorldLog.cs
/// EventCatalog.Trait.cs
/// EventCatalog.Book.cs
/// EventCatalog.Era.cs
/// EventCatalog.Plot.cs
/// EventCatalog.Relationship.cs
/// EventCatalog.Disaster.cs
/// EventCatalog.WarType.cs
/// EventCatalog.Libraries.cs
/// Combat policy lives in this file.
/// </summary>
public static partial class EventCatalog
{
/// <summary>Drop cached catalog rows so the next Ensure reloads from event-catalog.json.</summary>
public static void InvalidateAllOverlays()
{
Decision.InvalidateOverlays();
Happiness.InvalidateOverlays();
Status.InvalidateOverlays();
WorldLog.InvalidateOverlays();
Plot.InvalidateOverlays();
Relationship.InvalidateOverlays();
Story.InvalidateOverlays();
Trait.InvalidateOverlays();
Book.InvalidateOverlays();
Era.InvalidateOverlays();
Disaster.InvalidateOverlays();
WarType.InvalidateOverlays();
Spell.InvalidateOverlays();
Power.InvalidateOverlays();
Item.InvalidateOverlays();
Gene.InvalidateOverlays();
Phenotype.InvalidateOverlays();
WorldLaw.InvalidateOverlays();
SubspeciesTrait.InvalidateOverlays();
Biome.InvalidateOverlays();
CultureTrait.InvalidateOverlays();
ReligionTrait.InvalidateOverlays();
ClanTrait.InvalidateOverlays();
LanguageTrait.InvalidateOverlays();
}
/// <summary>
/// Layer A gate for happiness: Signal may own the camera; Ambient/Aggregate are B-only.
/// </summary>
public static bool IsCameraWorthy(HappinessPresentationTier presentation) =>
presentation == HappinessPresentationTier.Signal;
/// <summary>Layer A gate for discrete / status / worldlog rows.</summary>
public static bool IsCameraWorthy(bool createsInterest) => createsInterest;
public static bool IsCameraWorthy(DiscreteEventEntry entry) =>
entry != null && entry.CreatesInterest && !entry.IsFallback;
public static bool IsCameraWorthy(StatusInterestEntry entry) =>
entry != null && entry.CreatesInterest && !entry.IsFallback;
public static bool IsCameraWorthy(WorldLogEventEntry entry) =>
entry != null && entry.CreatesInterest && !entry.IsFallback;
public static bool IsCameraWorthy(HappinessCatalogEntry entry) =>
entry != null && IsCameraWorthy(entry.Presentation);
/// <summary>Combat camera policy (activity + scanner share one key / dials).</summary>
public static class Combat
{
public const float ActivityStrength = 88f;
public const float ScannerStrengthFloor = 80f;
public const float MinWatch = 4f;
public const float MaxWatch = 60f;
public const float ActivityTtl = 20f;
public const float ScannerTtl = 18f;
public static string Key(long subjectId) => "combat:" + subjectId;
/// <summary>
/// Unordered pair key so A-vs-B and B-vs-A collapse to one durable combat scene.
/// </summary>
public static string PairKey(long a, long b)
{
if (a == 0 && b == 0)
{
return "combat:0";
}
if (a == 0)
{
return Key(b);
}
if (b == 0 || a == b)
{
return Key(a);
}
long lo = a < b ? a : b;
long hi = a < b ? b : a;
return "combat:pair:" + lo + ":" + hi;
}
public static string KeyFor(Actor follow, Actor related)
{
long a = EventFeedUtil.SafeId(follow);
long b = EventFeedUtil.SafeId(related);
return b != 0 ? PairKey(a, b) : Key(a);
}
}
}