- Keep LifeSagaSession across Clear; wipe on map load/clear with bind key - Soft-bias Prefer/cross-MC/cast and prefer roster MCs in aftermath/recover/park - Resolve war/plot principals plus discrete/WorldLog labels from live libraries - Amortize roster world scans, gate Relayout, and add hitch probe/save-slot helpers
893 lines
29 KiB
C#
893 lines
29 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,
|
|
libraryKind: "spell");
|
|
}
|
|
|
|
/// <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, libraryKind: "spell");
|
|
}
|
|
}
|
|
|
|
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")
|
|
|| s.StartsWith("boat_", StringComparison.Ordinal))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Creature drop powers that match live spectacle actors (evil_mage, necromancer, …).
|
|
if (WorldActivityScanner.IsSpectacleAssetId(s))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
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")
|
|
|| s.Contains("mage")
|
|
|| s.Contains("necromancer")
|
|
|| s.Contains("druid");
|
|
}
|
|
|
|
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,
|
|
libraryKind: "power");
|
|
}
|
|
|
|
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, libraryKind: "power");
|
|
}
|
|
}
|
|
|
|
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();
|
|
// Only top-tier materials own the camera. Steel/silver/bone gear is soak noise.
|
|
return s.Contains("mythril") || s.Contains("adamantine");
|
|
}
|
|
|
|
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,
|
|
libraryKind: "item");
|
|
}
|
|
|
|
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, libraryKind: "item");
|
|
}
|
|
}
|
|
|
|
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,
|
|
libraryKind: "subspecies_trait");
|
|
}
|
|
|
|
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, libraryKind: "subspecies_trait");
|
|
}
|
|
}
|
|
|
|
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,
|
|
libraryKind: "gene");
|
|
}
|
|
|
|
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, libraryKind: "gene");
|
|
}
|
|
}
|
|
|
|
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,
|
|
libraryKind: "phenotype");
|
|
}
|
|
|
|
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, libraryKind: "phenotype");
|
|
}
|
|
}
|
|
|
|
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,
|
|
libraryKind: "worldlaw");
|
|
}
|
|
|
|
private static bool IsDramaticWorldLaw(string id)
|
|
{
|
|
if (string.IsNullOrEmpty(id))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
string s = id.ToLowerInvariant();
|
|
// God-law toggles are mostly UI spam. Keep era-defining / crisis switches only.
|
|
return s.Contains("cursed")
|
|
|| s.Contains("forever_")
|
|
|| s.Contains("disaster")
|
|
|| s.Contains("rebell");
|
|
}
|
|
|
|
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, libraryKind: "worldlaw");
|
|
}
|
|
}
|
|
|
|
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,
|
|
libraryKind: "biome");
|
|
}
|
|
|
|
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, libraryKind: "biome");
|
|
}
|
|
}
|
|
|
|
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");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Culture camera: hard politics only. Lovers / layouts / craft skins are soak noise.
|
|
/// </summary>
|
|
private static bool IsDramaticCultureTrait(string id)
|
|
{
|
|
if (string.IsNullOrEmpty(id))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
string s = id.ToLowerInvariant();
|
|
if (s.Contains("lover")
|
|
|| s.Contains("city_layout")
|
|
|| s.StartsWith("craft_", StringComparison.Ordinal)
|
|
|| s.Contains("ethno")
|
|
|| s.Contains("reading")
|
|
|| s.Contains("statue")
|
|
|| s.Contains("tower")
|
|
|| s.Contains("gossip"))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return s.Contains("conscript")
|
|
|| s.Contains("xenophob")
|
|
|| s.Contains("expans")
|
|
|| s.Contains("join_or_die")
|
|
|| s.Contains("happiness_from_war")
|
|
|| s.Contains("warriors_ascension")
|
|
|| s.Contains("shattered_crown");
|
|
}
|
|
|
|
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: IsDramaticCultureTrait,
|
|
ambientCreatesInterest: d.AmbientCreatesInterest,
|
|
libraryKind: "culture_trait");
|
|
}
|
|
|
|
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, libraryKind: "culture_trait");
|
|
}
|
|
}
|
|
|
|
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,
|
|
libraryKind: "religion_trait");
|
|
}
|
|
|
|
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, libraryKind: "religion_trait");
|
|
}
|
|
}
|
|
|
|
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;
|
|
// Clan blood / vein traits are gene-like soak noise - all B.
|
|
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,
|
|
ambientCreatesInterest: d.AmbientCreatesInterest,
|
|
libraryKind: "clan_trait");
|
|
}
|
|
|
|
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, libraryKind: "clan_trait");
|
|
}
|
|
}
|
|
|
|
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;
|
|
// Language flavor traits never own the camera.
|
|
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,
|
|
ambientCreatesInterest: d.AmbientCreatesInterest,
|
|
libraryKind: "language_trait");
|
|
}
|
|
|
|
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, libraryKind: "language_trait");
|
|
}
|
|
}
|
|
}
|