- Open war/disaster/outbreak crisis overlays with epilogue_crisis closers - Keep Duel pairs hot only on owned cast; park sleep/freeze; drop ambient scrap pins - Require a fallen theater partner for survivor aftermath; let king_killed cut mid-fight - Gate crisis, combat cold, king cut-in, and living-partner aftermath in harness
142 lines
4.9 KiB
C#
142 lines
4.9 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)
|
|
{
|
|
// Spectacle 1vN scraps share one scene so attack_target hops merge instead of
|
|
// spawning combat:pair:owner:victimN keys that thrash Duel tips.
|
|
if (follow != null && WorldActivityScanner.IsSpectaclePublic(follow))
|
|
{
|
|
long sid = EventFeedUtil.SafeId(follow);
|
|
if (sid != 0)
|
|
{
|
|
return "combat:spectacle:" + sid;
|
|
}
|
|
}
|
|
|
|
if (related != null && WorldActivityScanner.IsSpectaclePublic(related))
|
|
{
|
|
long sid = EventFeedUtil.SafeId(related);
|
|
if (sid != 0)
|
|
{
|
|
return "combat:spectacle:" + sid;
|
|
}
|
|
}
|
|
|
|
long a = EventFeedUtil.SafeId(follow);
|
|
long b = EventFeedUtil.SafeId(related);
|
|
return b != 0 ? PairKey(a, b) : Key(a);
|
|
}
|
|
}
|
|
}
|