using System; using System.Collections.Generic; namespace IdleSpectator; /// /// Live AssetManager library event dials (powers, genes, …). /// Strengths/labels from event-catalog.json libraries; signal predicates stay in C#. /// public static partial class EventCatalog { private static LibraryCatalogDefaults LibOr( string key, float ambient, float signal, string category, string label, bool ambientCreatesInterest) { if (EventCatalogConfig.TryGetLibraryDefaults(key, out LibraryCatalogDefaults d) && d != null) { return d; } return new LibraryCatalogDefaults { AmbientStrength = ambient, SignalStrength = signal, Category = category, Label = label, AmbientCreatesInterest = ambientCreatesInterest }; } public static class Spell { private static readonly Dictionary Entries = new Dictionary(StringComparer.OrdinalIgnoreCase); private static int _appliedGeneration = -1; public static void InvalidateOverlays() { Entries.Clear(); _appliedGeneration = -1; } private static void Ensure() { if (_appliedGeneration == EventCatalogConfig.Generation && Entries.Count > 0) { return; } Entries.Clear(); _appliedGeneration = EventCatalogConfig.Generation; LibraryCatalogDefaults d = LibOr("spell", 48f, 88f, "Spectacle", "{a} casts {id}", false); HashSet signals = d.SignalIds.Count > 0 ? d.SignalIds : new HashSet(StringComparer.OrdinalIgnoreCase) { "summon_lightning", "summon_tornado", "cast_curse", "cast_fire", "cast_blood_rain", "summon_meteor", "teleport" }; LiveLibraryInterest.EnsureSeeded( Entries, ActivityAssetCatalog.EnumerateLiveSpellIds, d.Category, d.Label, d.AmbientStrength, signals, d.SignalStrength, signalPredicate: IsSpectacleSpell, ambientCreatesInterest: d.AmbientCreatesInterest); } /// /// Spectacle casts own the camera; brief FX / utility (silence, shield, cure, grass) stay B. /// private static bool IsSpectacleSpell(string id) { if (string.IsNullOrEmpty(id)) { return false; } string s = id.ToLowerInvariant(); if (s.Contains("silence") || s.Contains("shield") || s.Contains("cure") || s.Contains("grass") || s.Contains("vegetation") || s.Contains("skeleton")) { return false; } return s.StartsWith("summon_", StringComparison.Ordinal) || s.Contains("meteor") || s.Contains("tornado") || s.Contains("lightning") || s.Contains("teleport") || s.Contains("curse") || s.Contains("blood_rain") || s.Contains("cast_fire"); } public static IEnumerable AuthoredIds { get { Ensure(); return Entries.Keys; } } public static DiscreteEventEntry GetOrFallback(string id) { Ensure(); LibraryCatalogDefaults d = LibOr("spell", 48f, 88f, "Spectacle", "{a} casts {id}", false); return LiveLibraryInterest.Lookup(Entries, id, d.Category, d.Label, 55f); } } public static class Power { private static readonly Dictionary Entries = new Dictionary(StringComparer.OrdinalIgnoreCase); private static int _appliedGeneration = -1; public static void InvalidateOverlays() { Entries.Clear(); _appliedGeneration = -1; } 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() { if (_appliedGeneration == EventCatalogConfig.Generation && Entries.Count > 0) { return; } Entries.Clear(); _appliedGeneration = EventCatalogConfig.Generation; LibraryCatalogDefaults d = LibOr("power", 28f, 92f, "Spectacle", "God power: {id}", false); LiveLibraryInterest.EnsureSeeded( Entries, ActivityAssetCatalog.EnumerateLivePowerIds, d.Category, d.Label, d.AmbientStrength, signalIds: null, d.SignalStrength, signalPredicate: IsSpectaclePower, ambientCreatesInterest: d.AmbientCreatesInterest); } public static IEnumerable AuthoredIds { get { Ensure(); return Entries.Keys; } } public static DiscreteEventEntry GetOrFallback(string id) { Ensure(); LibraryCatalogDefaults d = LibOr("power", 28f, 92f, "Spectacle", "God power: {id}", false); return LiveLibraryInterest.Lookup(Entries, id, d.Category, d.Label, 30f); } } public static class Item { private static readonly Dictionary Entries = new Dictionary(StringComparer.OrdinalIgnoreCase); private static int _appliedGeneration = -1; public static void InvalidateOverlays() { Entries.Clear(); _appliedGeneration = -1; } private static bool IsLegendaryItem(string id) { if (string.IsNullOrEmpty(id)) { return false; } string s = id.ToLowerInvariant(); // Top-tier materials from live items library (mythril/adamantine) plus named relics. return s.Contains("legendary") || s.Contains("mythic") || s.Contains("mythril") || s.Contains("adamantine") || 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() { if (_appliedGeneration == EventCatalogConfig.Generation && Entries.Count > 0) { return; } Entries.Clear(); _appliedGeneration = EventCatalogConfig.Generation; LibraryCatalogDefaults d = LibOr("item", 36f, 80f, "Item", "{a} gains {id}", false); LiveLibraryInterest.EnsureSeeded( Entries, ActivityAssetCatalog.EnumerateLiveItemIds, d.Category, d.Label, d.AmbientStrength, signalIds: null, d.SignalStrength, signalPredicate: IsLegendaryItem, ambientCreatesInterest: d.AmbientCreatesInterest); } public static IEnumerable AuthoredIds { get { Ensure(); return Entries.Keys; } } public static DiscreteEventEntry GetOrFallback(string id) { Ensure(); LibraryCatalogDefaults d = LibOr("item", 36f, 80f, "Item", "{a} gains {id}", false); return LiveLibraryInterest.Lookup(Entries, id, d.Category, d.Label, 40f); } } public static class SubspeciesTrait { private static readonly Dictionary Entries = new Dictionary(StringComparer.OrdinalIgnoreCase); private static int _appliedGeneration = -1; public static void InvalidateOverlays() { Entries.Clear(); _appliedGeneration = -1; } 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() { if (_appliedGeneration == EventCatalogConfig.Generation && Entries.Count > 0) { return; } Entries.Clear(); _appliedGeneration = EventCatalogConfig.Generation; LibraryCatalogDefaults d = LibOr("subspeciesTrait", 34f, 78f, "Evolution", "{a} evolves {id}", false); LiveLibraryInterest.EnsureSeeded( Entries, ActivityAssetCatalog.EnumerateLiveSubspeciesTraitIds, d.Category, d.Label, d.AmbientStrength, signalIds: null, d.SignalStrength, signalPredicate: IsDramatic, ambientCreatesInterest: d.AmbientCreatesInterest); } public static IEnumerable AuthoredIds { get { Ensure(); return Entries.Keys; } } public static DiscreteEventEntry GetOrFallback(string id) { Ensure(); LibraryCatalogDefaults d = LibOr("subspeciesTrait", 34f, 78f, "Evolution", "{a} evolves {id}", false); return LiveLibraryInterest.Lookup(Entries, id, d.Category, d.Label, 36f); } } public static class Gene { private static readonly Dictionary Entries = new Dictionary(StringComparer.OrdinalIgnoreCase); private static int _appliedGeneration = -1; public static void InvalidateOverlays() { Entries.Clear(); _appliedGeneration = -1; } private static void Ensure() { if (_appliedGeneration == EventCatalogConfig.Generation && Entries.Count > 0) { return; } Entries.Clear(); _appliedGeneration = EventCatalogConfig.Generation; LibraryCatalogDefaults d = LibOr("gene", 30f, 70f, "Genetics", "{a} gains gene {id}", false); LiveLibraryInterest.EnsureSeeded( Entries, ActivityAssetCatalog.EnumerateLiveGeneIds, d.Category, d.Label, d.AmbientStrength, signalIds: null, d.SignalStrength, signalPredicate: id => id != null && (id.Contains("warfare") || id.Contains("magic") || id.Contains("mutation")), ambientCreatesInterest: d.AmbientCreatesInterest); } public static IEnumerable AuthoredIds { get { Ensure(); return Entries.Keys; } } public static DiscreteEventEntry GetOrFallback(string id) { Ensure(); LibraryCatalogDefaults d = LibOr("gene", 30f, 70f, "Genetics", "{a} gains gene {id}", false); return LiveLibraryInterest.Lookup(Entries, id, d.Category, d.Label, 30f); } } public static class Phenotype { private static readonly Dictionary Entries = new Dictionary(StringComparer.OrdinalIgnoreCase); private static int _appliedGeneration = -1; public static void InvalidateOverlays() { Entries.Clear(); _appliedGeneration = -1; } private static void Ensure() { if (_appliedGeneration == EventCatalogConfig.Generation && Entries.Count > 0) { return; } Entries.Clear(); _appliedGeneration = EventCatalogConfig.Generation; // Skin/shade phenotypes are ambient noise - no Signal predicate, all B. LibraryCatalogDefaults d = LibOr("phenotype", 28f, 60f, "Genetics", "{a} shows {id}", false); LiveLibraryInterest.EnsureSeeded( Entries, ActivityAssetCatalog.EnumerateLivePhenotypeIds, d.Category, d.Label, d.AmbientStrength, signalIds: null, d.SignalStrength, ambientCreatesInterest: d.AmbientCreatesInterest); } public static IEnumerable AuthoredIds { get { Ensure(); return Entries.Keys; } } public static DiscreteEventEntry GetOrFallback(string id) { Ensure(); LibraryCatalogDefaults d = LibOr("phenotype", 28f, 60f, "Genetics", "{a} shows {id}", false); return LiveLibraryInterest.Lookup(Entries, id, d.Category, d.Label, 28f); } } public static class WorldLaw { private static readonly Dictionary Entries = new Dictionary(StringComparer.OrdinalIgnoreCase); private static int _appliedGeneration = -1; public static void InvalidateOverlays() { Entries.Clear(); _appliedGeneration = -1; } private static void Ensure() { if (_appliedGeneration == EventCatalogConfig.Generation && Entries.Count > 0) { return; } Entries.Clear(); _appliedGeneration = EventCatalogConfig.Generation; LibraryCatalogDefaults d = LibOr("worldLaw", 40f, 70f, "WorldLaw", "Law changed: {id}", false); LiveLibraryInterest.EnsureSeeded( Entries, ActivityAssetCatalog.EnumerateLiveWorldLawIds, d.Category, d.Label, d.AmbientStrength, signalIds: null, d.SignalStrength, signalPredicate: IsDramaticWorldLaw, ambientCreatesInterest: d.AmbientCreatesInterest); } private static bool IsDramaticWorldLaw(string id) { if (string.IsNullOrEmpty(id)) { return false; } string s = id.ToLowerInvariant(); return s.Contains("war") || s.Contains("death") || s.Contains("plague") || s.Contains("hunger") || s.Contains("rebell") || s.Contains("disaster") || s.Contains("angry"); } public static IEnumerable AuthoredIds { get { Ensure(); return Entries.Keys; } } public static DiscreteEventEntry GetOrFallback(string id) { Ensure(); LibraryCatalogDefaults d = LibOr("worldLaw", 40f, 70f, "WorldLaw", "Law changed: {id}", false); return LiveLibraryInterest.Lookup(Entries, id, d.Category, d.Label, 40f); } } public static class Biome { private static readonly Dictionary Entries = new Dictionary(StringComparer.OrdinalIgnoreCase); private static int _appliedGeneration = -1; public static void InvalidateOverlays() { Entries.Clear(); _appliedGeneration = -1; } private static void Ensure() { if (_appliedGeneration == EventCatalogConfig.Generation && Entries.Count > 0) { return; } Entries.Clear(); _appliedGeneration = EventCatalogConfig.Generation; LibraryCatalogDefaults d = LibOr("biome", 26f, 50f, "Biome", "Biome shifts: {id}", false); LiveLibraryInterest.EnsureSeeded( Entries, ActivityAssetCatalog.EnumerateLiveBiomeIds, d.Category, d.Label, d.AmbientStrength, signalIds: null, d.SignalStrength, ambientCreatesInterest: d.AmbientCreatesInterest); } public static IEnumerable AuthoredIds { get { Ensure(); return Entries.Keys; } } public static DiscreteEventEntry GetOrFallback(string id) { Ensure(); LibraryCatalogDefaults d = LibOr("biome", 26f, 50f, "Biome", "Biome shifts: {id}", false); return LiveLibraryInterest.Lookup(Entries, id, d.Category, d.Label, 26f); } } private static bool IsDramaticMetaTrait(string id) { if (string.IsNullOrEmpty(id)) { return false; } string s = id.ToLowerInvariant(); return s.Contains("war") || s.Contains("blood") || s.Contains("death") || s.Contains("fire") || s.Contains("magic") || s.Contains("divine") || s.Contains("demon") || s.Contains("hate") || s.Contains("love") || s.Contains("xenophob") || s.Contains("expans") || s.Contains("conquest") || s.Contains("slave") || s.Contains("zealot") || s.Contains("fanatic") || s.Contains("schism") || s.Contains("royal"); } public static class CultureTrait { private static readonly Dictionary Entries = new Dictionary(StringComparer.OrdinalIgnoreCase); private static int _appliedGeneration = -1; public static void InvalidateOverlays() { Entries.Clear(); _appliedGeneration = -1; } private static void Ensure() { if (_appliedGeneration == EventCatalogConfig.Generation && Entries.Count > 0) { return; } Entries.Clear(); _appliedGeneration = EventCatalogConfig.Generation; LibraryCatalogDefaults d = LibOr("cultureTrait", 34f, 74f, "Culture", "{a} culture gains {id}", false); LiveLibraryInterest.EnsureSeeded( Entries, ActivityAssetCatalog.EnumerateLiveCultureTraitIds, d.Category, d.Label, d.AmbientStrength, signalIds: null, d.SignalStrength, signalPredicate: IsDramaticMetaTrait, ambientCreatesInterest: d.AmbientCreatesInterest); } public static IEnumerable AuthoredIds { get { Ensure(); return Entries.Keys; } } public static DiscreteEventEntry GetOrFallback(string id) { Ensure(); LibraryCatalogDefaults d = LibOr("cultureTrait", 34f, 74f, "Culture", "{a} culture gains {id}", false); return LiveLibraryInterest.Lookup(Entries, id, d.Category, d.Label, 34f); } } public static class ReligionTrait { private static readonly Dictionary Entries = new Dictionary(StringComparer.OrdinalIgnoreCase); private static int _appliedGeneration = -1; public static void InvalidateOverlays() { Entries.Clear(); _appliedGeneration = -1; } private static void Ensure() { if (_appliedGeneration == EventCatalogConfig.Generation && Entries.Count > 0) { return; } Entries.Clear(); _appliedGeneration = EventCatalogConfig.Generation; LibraryCatalogDefaults d = LibOr("religionTrait", 34f, 74f, "Religion", "{a} faith gains {id}", false); LiveLibraryInterest.EnsureSeeded( Entries, ActivityAssetCatalog.EnumerateLiveReligionTraitIds, d.Category, d.Label, d.AmbientStrength, signalIds: null, d.SignalStrength, signalPredicate: IsDramaticMetaTrait, ambientCreatesInterest: d.AmbientCreatesInterest); } public static IEnumerable AuthoredIds { get { Ensure(); return Entries.Keys; } } public static DiscreteEventEntry GetOrFallback(string id) { Ensure(); LibraryCatalogDefaults d = LibOr("religionTrait", 34f, 74f, "Religion", "{a} faith gains {id}", false); return LiveLibraryInterest.Lookup(Entries, id, d.Category, d.Label, 34f); } } public static class ClanTrait { private static readonly Dictionary Entries = new Dictionary(StringComparer.OrdinalIgnoreCase); private static int _appliedGeneration = -1; public static void InvalidateOverlays() { Entries.Clear(); _appliedGeneration = -1; } private static void Ensure() { if (_appliedGeneration == EventCatalogConfig.Generation && Entries.Count > 0) { return; } Entries.Clear(); _appliedGeneration = EventCatalogConfig.Generation; LibraryCatalogDefaults d = LibOr("clanTrait", 32f, 72f, "Clan", "{a} clan gains {id}", false); LiveLibraryInterest.EnsureSeeded( Entries, ActivityAssetCatalog.EnumerateLiveClanTraitIds, d.Category, d.Label, d.AmbientStrength, signalIds: null, d.SignalStrength, signalPredicate: IsDramaticMetaTrait, ambientCreatesInterest: d.AmbientCreatesInterest); } public static IEnumerable AuthoredIds { get { Ensure(); return Entries.Keys; } } public static DiscreteEventEntry GetOrFallback(string id) { Ensure(); LibraryCatalogDefaults d = LibOr("clanTrait", 32f, 72f, "Clan", "{a} clan gains {id}", false); return LiveLibraryInterest.Lookup(Entries, id, d.Category, d.Label, 32f); } } public static class LanguageTrait { private static readonly Dictionary Entries = new Dictionary(StringComparer.OrdinalIgnoreCase); private static int _appliedGeneration = -1; public static void InvalidateOverlays() { Entries.Clear(); _appliedGeneration = -1; } private static void Ensure() { if (_appliedGeneration == EventCatalogConfig.Generation && Entries.Count > 0) { return; } Entries.Clear(); _appliedGeneration = EventCatalogConfig.Generation; LibraryCatalogDefaults d = LibOr("languageTrait", 30f, 68f, "Language", "{a} tongue gains {id}", false); LiveLibraryInterest.EnsureSeeded( Entries, ActivityAssetCatalog.EnumerateLiveLanguageTraitIds, d.Category, d.Label, d.AmbientStrength, signalIds: null, d.SignalStrength, signalPredicate: IsDramaticMetaTrait, ambientCreatesInterest: d.AmbientCreatesInterest); } public static IEnumerable AuthoredIds { get { Ensure(); return Entries.Keys; } } public static DiscreteEventEntry GetOrFallback(string id) { Ensure(); LibraryCatalogDefaults d = LibOr("languageTrait", 30f, 68f, "Language", "{a} tongue gains {id}", false); return LiveLibraryInterest.Lookup(Entries, id, d.Category, d.Label, 30f); } } }