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

868 lines
28 KiB
C#

using System;
using System.Collections.Generic;
namespace IdleSpectator;
/// <summary>
/// Live AssetManager library event dials (powers, genes, …).
/// Strengths/labels from <c>event-catalog.json</c> <c>libraries</c>; signal predicates stay in C#.
/// </summary>
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<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(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<string> signals = d.SignalIds.Count > 0
? d.SignalIds
: new HashSet<string>(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);
}
/// <summary>
/// Spectacle casts own the camera; brief FX / utility (silence, shield, cure, grass) stay B.
/// </summary>
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<string> 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<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(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();
// God-tool editors / drip brushes stay B.
if (s.Contains("_edit")
|| s.Contains("traits_")
|| s.Contains("equipment_rain")
|| s.EndsWith("_brush", StringComparison.Ordinal)
|| s.Contains("draw_")
|| s.Contains("paint"))
{
return false;
}
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("blood_rain")
|| s.Contains("hell")
|| s.Contains("lightning")
|| s.Contains("storm")
|| s.Contains("acid")
|| s.Contains("fire")
|| s.Contains("disaster")
|| s.Contains("dragon")
|| s.Contains("demon")
|| s.Contains("plague")
|| s.Contains("zombie")
|| s.Contains("crabzilla")
|| s == "ufo"
|| s.Contains("god_finger")
|| s.Contains("cold_one")
|| s.Contains("heatray")
|| s.Contains("curse")
|| s.Contains("lava")
|| s.Contains("ash")
|| s.Contains("golden_brain")
|| s.Contains("corrupted_brain")
|| s.Contains("infection");
}
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<string> 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<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(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();
// High / mid-spectacle materials from live items library plus named relics.
// Leather/wood/copper/iron stay ambient B.
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")
|| s.Contains("silver")
|| s.Contains("steel")
|| s.Contains("_bone")
|| s.StartsWith("bone_", StringComparison.Ordinal)
|| s.EndsWith("_bone", StringComparison.Ordinal);
}
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<string> 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<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(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")
|| s.Contains("mutation")
|| s.Contains("death")
|| s.Contains("blood")
|| s.Contains("horror")
|| s.Contains("tentacle");
}
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<string> 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<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(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;
// Gene gain/remove is catalog noise - no Signal predicate, all B (like phenotypes).
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,
ambientCreatesInterest: d.AmbientCreatesInterest);
}
public static IEnumerable<string> 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<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(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<string> 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<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(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")
|| s.Contains("cursed")
|| s.Contains("forever_")
|| s.Contains("tumor")
|| s.Contains("mutant")
|| s.Contains("evolution")
|| s.Contains("old_age")
|| s.Contains("kingdom_expansion")
|| s.Contains("border_steal")
|| s.Contains("civ_army")
|| s.Contains("exploding");
}
public static IEnumerable<string> 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<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(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<string> 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")
|| s.Contains("conscript")
|| s.Contains("join_or_die")
|| s.Contains("necro")
|| s.Contains("evil")
|| s.Contains("shattered")
|| s.Contains("titan")
|| s.Contains("ethno")
|| s.Contains("flame")
|| s.Contains("ice_weapon")
|| s.Contains("shotgun")
|| s.Contains("blaster");
}
public static class CultureTrait
{
private static readonly Dictionary<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(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<string> 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<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(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<string> 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<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(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<string> 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<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(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<string> 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);
}
}
}