using System; using System.Collections.Generic; namespace IdleSpectator; /// Live spells library interest overlay (Signal when cast resolves to a unit). public static class SpellInterestCatalog { private static readonly Dictionary Entries = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly HashSet SignalIds = new HashSet(StringComparer.OrdinalIgnoreCase) { "summon_lightning", "summon_tornado", "cast_curse", "cast_fire", "cast_blood_rain", "summon_meteor", "teleport" }; private static void Ensure() => LiveLibraryInterest.EnsureSeeded( Entries, ActivityAssetCatalog.EnumerateLiveSpellIds, "Spectacle", "{a} casts {id}", ambientStrength: 48f, SignalIds, signalStrength: 88f, ambientCreatesInterest: false); public static IEnumerable AuthoredIds { get { Ensure(); return Entries.Keys; } } public static DiscreteEventEntry GetOrFallback(string id) { Ensure(); return LiveLibraryInterest.Lookup(Entries, id, "Spectacle", "{a} casts {id}", 55f); } } /// God powers library - mostly Ambient; Signal for disaster/spectacle ids. public static class PowerInterestCatalog { private static readonly Dictionary Entries = new Dictionary(StringComparer.OrdinalIgnoreCase); private static bool IsSpectaclePower(string id) { if (string.IsNullOrEmpty(id)) { return false; } string s = id.ToLowerInvariant(); return s.Contains("meteor") || s.Contains("earthquake") || s.Contains("tornado") || s.Contains("volcano") || s.Contains("nuke") || s.Contains("bomb") || s.Contains("rain_blood") || s.Contains("hell") || s.Contains("lightning") || s.Contains("storm") || s.Contains("acid") || s.Contains("fire") || s.Contains("disaster"); } private static void Ensure() => LiveLibraryInterest.EnsureSeeded( Entries, ActivityAssetCatalog.EnumerateLivePowerIds, "Spectacle", "God power: {id}", ambientStrength: 28f, signalIds: null, signalStrength: 92f, signalPredicate: IsSpectaclePower, ambientCreatesInterest: false); public static IEnumerable AuthoredIds { get { Ensure(); return Entries.Keys; } } public static DiscreteEventEntry GetOrFallback(string id) { Ensure(); return LiveLibraryInterest.Lookup(Entries, id, "Spectacle", "God power: {id}", 30f); } } /// AI decisions - Signal for war/rebellion/kingdom-affecting; Ambient otherwise. public static class DecisionInterestCatalog { private static readonly Dictionary Entries = new Dictionary(StringComparer.OrdinalIgnoreCase); private static bool IsKingdomDecision(string id) { if (string.IsNullOrEmpty(id)) { return false; } string s = id.ToLowerInvariant(); // Routine AI ticks often include "king" in the name - those are not camera events. if (s.Contains("idle") || s.Contains("walking") || s.Contains("check") || s.Contains("wait") || s.Contains("sleep")) { return false; } return s.Contains("war") || s.Contains("rebellion") || s.Contains("revolt") || s.Contains("alliance") || s.Contains("coup") || s.Contains("betray") || s.Contains("declare") || s.Contains("invade") || s.Contains("siege") || s.Contains("found") || s.Contains("city_foundation") || (s.Contains("king") && (s.Contains("war") || s.Contains("city") || s.Contains("rebellion"))); } /// True when a decision id should be allowed to own the idle camera. public static bool IsCameraWorthy(string id) => IsKingdomDecision(id); private static void Ensure() => LiveLibraryInterest.EnsureSeeded( Entries, ActivityAssetCatalog.EnumerateLiveDecisionIds, "Politics", "{a} decides {id}", ambientStrength: 32f, signalIds: null, signalStrength: 86f, signalPredicate: IsKingdomDecision, ambientCreatesInterest: false); public static IEnumerable AuthoredIds { get { Ensure(); return Entries.Keys; } } public static DiscreteEventEntry GetOrFallback(string id) { Ensure(); return LiveLibraryInterest.Lookup(Entries, id, "Politics", "{a} decides {id}", 35f); } } /// Items library - Signal for legendary/wonder subset. public static class ItemInterestCatalog { private static readonly Dictionary Entries = new Dictionary(StringComparer.OrdinalIgnoreCase); private static bool IsLegendaryItem(string id) { if (string.IsNullOrEmpty(id)) { return false; } string s = id.ToLowerInvariant(); return s.Contains("legendary") || s.Contains("mythic") || s.Contains("artifact") || s.Contains("relic") || s.Contains("divine") || s.Contains("demon") || s.Contains("dragon") || s.Contains("nuke") || s.Contains("excalibur") || s.Contains("wonder"); } private static void Ensure() => LiveLibraryInterest.EnsureSeeded( Entries, ActivityAssetCatalog.EnumerateLiveItemIds, "Item", "{a} forges {id}", ambientStrength: 36f, signalIds: null, signalStrength: 80f, signalPredicate: IsLegendaryItem, ambientCreatesInterest: false); public static IEnumerable AuthoredIds { get { Ensure(); return Entries.Keys; } } public static DiscreteEventEntry GetOrFallback(string id) { Ensure(); return LiveLibraryInterest.Lookup(Entries, id, "Item", "{a} forges {id}", 40f); } } /// Subspecies traits - Signal for dramatic; Ambient fill-capped. public static class SubspeciesTraitInterestCatalog { private static readonly Dictionary Entries = new Dictionary(StringComparer.OrdinalIgnoreCase); private static bool IsDramatic(string id) { if (string.IsNullOrEmpty(id)) { return false; } string s = id.ToLowerInvariant(); return s.Contains("immortal") || s.Contains("giant") || s.Contains("tiny") || s.Contains("fire") || s.Contains("frost") || s.Contains("poison") || s.Contains("plague") || s.Contains("magic") || s.Contains("divine") || s.Contains("demon") || s.Contains("undead") || s.Contains("dragon") || s.Contains("evolve") || s.Contains("mutate"); } private static void Ensure() => LiveLibraryInterest.EnsureSeeded( Entries, ActivityAssetCatalog.EnumerateLiveSubspeciesTraitIds, "Evolution", "{a} evolves {id}", ambientStrength: 34f, signalIds: null, signalStrength: 78f, signalPredicate: IsDramatic); public static IEnumerable AuthoredIds { get { Ensure(); return Entries.Keys; } } public static DiscreteEventEntry GetOrFallback(string id) { Ensure(); return LiveLibraryInterest.Lookup(Entries, id, "Evolution", "{a} evolves {id}", 36f); } } /// Genes - Ambient default. public static class GeneInterestCatalog { private static readonly Dictionary Entries = new Dictionary(StringComparer.OrdinalIgnoreCase); private static void Ensure() => LiveLibraryInterest.EnsureSeeded( Entries, ActivityAssetCatalog.EnumerateLiveGeneIds, "Genetics", "{a} gains gene {id}", ambientStrength: 30f, signalIds: null, signalStrength: 70f, signalPredicate: id => id != null && (id.Contains("warfare") || id.Contains("magic") || id.Contains("mutation")), ambientCreatesInterest: false); public static IEnumerable AuthoredIds { get { Ensure(); return Entries.Keys; } } public static DiscreteEventEntry GetOrFallback(string id) { Ensure(); return LiveLibraryInterest.Lookup(Entries, id, "Genetics", "{a} gains gene {id}", 30f); } } /// Phenotypes - Ambient default. public static class PhenotypeInterestCatalog { private static readonly Dictionary Entries = new Dictionary(StringComparer.OrdinalIgnoreCase); private static void Ensure() => LiveLibraryInterest.EnsureSeeded( Entries, ActivityAssetCatalog.EnumerateLivePhenotypeIds, "Genetics", "{a} shows {id}", ambientStrength: 28f, signalIds: null, signalStrength: 60f); public static IEnumerable AuthoredIds { get { Ensure(); return Entries.Keys; } } public static DiscreteEventEntry GetOrFallback(string id) { Ensure(); return LiveLibraryInterest.Lookup(Entries, id, "Genetics", "{a} shows {id}", 28f); } } /// World laws - Ambient / location-only style. public static class WorldLawInterestCatalog { private static readonly Dictionary Entries = new Dictionary(StringComparer.OrdinalIgnoreCase); private static void Ensure() => LiveLibraryInterest.EnsureSeeded( Entries, ActivityAssetCatalog.EnumerateLiveWorldLawIds, "WorldLaw", "Law changed: {id}", ambientStrength: 40f, signalIds: null, signalStrength: 70f, signalPredicate: id => id != null && (id.Contains("war") || id.Contains("death") || id.Contains("plague")), ambientCreatesInterest: false); public static IEnumerable AuthoredIds { get { Ensure(); return Entries.Keys; } } public static DiscreteEventEntry GetOrFallback(string id) { Ensure(); return LiveLibraryInterest.Lookup(Entries, id, "WorldLaw", "Law changed: {id}", 40f); } } /// Biomes - Ambient. public static class BiomeInterestCatalog { private static readonly Dictionary Entries = new Dictionary(StringComparer.OrdinalIgnoreCase); private static void Ensure() => LiveLibraryInterest.EnsureSeeded( Entries, ActivityAssetCatalog.EnumerateLiveBiomeIds, "Biome", "Biome shifts: {id}", ambientStrength: 26f, signalIds: null, signalStrength: 50f, ambientCreatesInterest: false); public static IEnumerable AuthoredIds { get { Ensure(); return Entries.Keys; } } public static DiscreteEventEntry GetOrFallback(string id) { Ensure(); return LiveLibraryInterest.Lookup(Entries, id, "Biome", "Biome shifts: {id}", 26f); } }