event catalog

This commit is contained in:
DazedAnon 2026-07-16 00:40:53 -05:00
parent ff824c76a1
commit 63ba0ca3d1
51 changed files with 272 additions and 170 deletions

View file

@ -30,7 +30,7 @@ public static class ActivityHappinessHarness
{ {
List<string> liveIds = ActivityAssetCatalog.EnumerateLiveHappinessIds(); List<string> liveIds = ActivityAssetCatalog.EnumerateLiveHappinessIds();
var authored = new HashSet<string>(StringComparer.OrdinalIgnoreCase); var authored = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (string id in HappinessEventCatalog.AuthoredIds) foreach (string id in EventCatalog.Happiness.AuthoredIds)
{ {
authored.Add(id); authored.Add(id);
} }
@ -53,8 +53,8 @@ public static class ActivityHappinessHarness
string id = liveIds[i]; string id = liveIds[i];
liveSet.Add(id); liveSet.Add(id);
HappinessAsset asset = ActivityAssetCatalog.TryGetHappinessAsset(id); HappinessAsset asset = ActivityAssetCatalog.TryGetHappinessAsset(id);
bool hasAuthored = HappinessEventCatalog.HasAuthored(id); bool hasAuthored = EventCatalog.Happiness.HasAuthored(id);
HappinessCatalogEntry entry = HappinessEventCatalog.GetOrFallback(id); HappinessCatalogEntry entry = EventCatalog.Happiness.GetOrFallback(id);
if (!hasAuthored || entry.IsFallback) if (!hasAuthored || entry.IsFallback)
{ {
missingAuthored++; missingAuthored++;

View file

@ -36,7 +36,7 @@ public static class ActivityHappinessProse
out bool authored) out bool authored)
{ {
usedRelated = false; usedRelated = false;
authored = entry != null && !entry.IsFallback && HappinessEventCatalog.HasAuthored(entry.Id); authored = entry != null && !entry.IsFallback && EventCatalog.Happiness.HasAuthored(entry.Id);
if (entry == null) if (entry == null)
{ {
return "feels a change in happiness"; return "feels a change in happiness";

View file

@ -750,7 +750,7 @@ public static class ActivityLog
if (published != null && !string.IsNullOrEmpty(relatedName)) if (published != null && !string.IsNullOrEmpty(relatedName))
{ {
published.RelatedName = relatedName; published.RelatedName = relatedName;
HappinessCatalogEntry entry = HappinessEventCatalog.GetOrFallback(effectId); HappinessCatalogEntry entry = EventCatalog.Happiness.GetOrFallback(effectId);
string clause = ActivityHappinessProse.Clause(entry, relatedName, out bool usedRelated, out _); string clause = ActivityHappinessProse.Clause(entry, relatedName, out bool usedRelated, out _);
published.PlainClause = clause; published.PlainClause = clause;
published.RichClause = usedRelated published.RichClause = usedRelated
@ -770,7 +770,7 @@ public static class ActivityLog
return published != null; return published != null;
} }
HappinessCatalogEntry fallbackEntry = HappinessEventCatalog.GetOrFallback(effectId); HappinessCatalogEntry fallbackEntry = EventCatalog.Happiness.GetOrFallback(effectId);
string fallbackClause = ActivityHappinessProse.Clause( string fallbackClause = ActivityHappinessProse.Clause(
fallbackEntry, relatedName, out bool usedRel, out _); fallbackEntry, relatedName, out bool usedRel, out _);
string rich = usedRel && !string.IsNullOrEmpty(relatedName) string rich = usedRel && !string.IsNullOrEmpty(relatedName)

View file

@ -47,7 +47,7 @@ public static class ActivityStatusHarness
var liveSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase); var liveSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var interestAuthored = new HashSet<string>(StringComparer.OrdinalIgnoreCase); var interestAuthored = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (string id in StatusInterestCatalog.AuthoredIds) foreach (string id in EventCatalog.Status.AuthoredIds)
{ {
interestAuthored.Add(id); interestAuthored.Add(id);
} }
@ -65,8 +65,8 @@ public static class ActivityStatusHarness
missingAuthored++; missingAuthored++;
} }
StatusInterestEntry interest = StatusInterestCatalog.GetOrFallback(id); StatusInterestEntry interest = EventCatalog.Status.GetOrFallback(id);
bool hasInterest = StatusInterestCatalog.HasAuthored(id) && !interest.IsFallback; bool hasInterest = EventCatalog.Status.HasAuthored(id) && !interest.IsFallback;
if (!hasInterest) if (!hasInterest)
{ {
missingInterest++; missingInterest++;

View file

@ -2486,14 +2486,14 @@ public static class AgentHarness
assetId = "disaster_tornado"; assetId = "disaster_tornado";
} }
if (!WorldLogEventCatalog.HasAuthored(assetId)) if (!EventCatalog.WorldLog.HasAuthored(assetId))
{ {
_cmdFail++; _cmdFail++;
Emit(cmd, ok: false, detail: "not_authored:" + assetId); Emit(cmd, ok: false, detail: "not_authored:" + assetId);
return; return;
} }
WorldLogEventEntry entry = WorldLogEventCatalog.GetOrFallback(assetId); WorldLogEventEntry entry = EventCatalog.WorldLog.GetOrFallback(assetId);
Actor follow = ResolveUnit(null) ?? WorldActivityScanner.FindNearestAliveUnit(CameraPos(), 200f); Actor follow = ResolveUnit(null) ?? WorldActivityScanner.FindNearestAliveUnit(CameraPos(), 200f);
if (follow == null && entry.CreatesInterest) if (follow == null && entry.CreatesInterest)
{ {
@ -2581,7 +2581,7 @@ public static class AgentHarness
id = "set_lover"; id = "set_lover";
} }
entry = RelationshipEventCatalog.GetOrFallback(id); entry = EventCatalog.Relationship.GetOrFallback(id);
Actor related = ActorRelation.ResolvePackRelated(unit) Actor related = ActorRelation.ResolvePackRelated(unit)
?? WorldActivityScanner.FindNearestAliveUnit(unit.current_position, 40f); ?? WorldActivityScanner.FindNearestAliveUnit(unit.current_position, 40f);
if (related == unit) if (related == unit)
@ -2623,7 +2623,7 @@ public static class AgentHarness
id = "new_war"; id = "new_war";
} }
entry = PlotInterestCatalog.GetOrFallback(id); entry = EventCatalog.Plot.GetOrFallback(id);
key = "plot:" + entry.Id + ":new:" + EventFeedUtil.SafeId(unit); key = "plot:" + entry.Id + ":new:" + EventFeedUtil.SafeId(unit);
label = entry.MakeLabel(EventFeedUtil.SafeName(unit), "new"); label = entry.MakeLabel(EventFeedUtil.SafeName(unit), "new");
strength = entry.EventStrength; strength = entry.EventStrength;
@ -2636,7 +2636,7 @@ public static class AgentHarness
id = "age_chaos"; id = "age_chaos";
} }
entry = EraInterestCatalog.GetOrFallback(id); entry = EventCatalog.Era.GetOrFallback(id);
key = "era:" + entry.Id; key = "era:" + entry.Id;
label = entry.MakeLabel("", ""); label = entry.MakeLabel("", "");
strength = entry.EventStrength; strength = entry.EventStrength;
@ -2673,7 +2673,7 @@ public static class AgentHarness
id = "history_book"; id = "history_book";
} }
entry = BookInterestCatalog.GetOrFallback(id); entry = EventCatalog.Book.GetOrFallback(id);
key = "book:" + entry.Id + ":new:" + EventFeedUtil.SafeId(unit); key = "book:" + entry.Id + ":new:" + EventFeedUtil.SafeId(unit);
label = entry.MakeLabel(EventFeedUtil.SafeName(unit), "new"); label = entry.MakeLabel(EventFeedUtil.SafeName(unit), "new");
strength = entry.EventStrength; strength = entry.EventStrength;
@ -2686,7 +2686,7 @@ public static class AgentHarness
id = "immortal"; id = "immortal";
} }
entry = TraitInterestCatalog.GetOrFallback(id); entry = EventCatalog.Trait.GetOrFallback(id);
key = "trait:" + entry.Id + ":gains:" + EventFeedUtil.SafeId(unit); key = "trait:" + entry.Id + ":gains:" + EventFeedUtil.SafeId(unit);
label = EventFeedUtil.SafeName(unit) + " gains " + entry.Id; label = EventFeedUtil.SafeName(unit) + " gains " + entry.Id;
strength = entry.EventStrength; strength = entry.EventStrength;
@ -2728,7 +2728,7 @@ public static class AgentHarness
} }
{ {
DiscreteEventEntry spellEntry = SpellInterestCatalog.GetOrFallback(id); DiscreteEventEntry spellEntry = EventCatalog.Spell.GetOrFallback(id);
key = "spell:" + spellEntry.Id + ":" + EventFeedUtil.SafeId(unit); key = "spell:" + spellEntry.Id + ":" + EventFeedUtil.SafeId(unit);
label = spellEntry.MakeLabel(EventFeedUtil.SafeName(unit), ""); label = spellEntry.MakeLabel(EventFeedUtil.SafeName(unit), "");
strength = spellEntry.EventStrength; strength = spellEntry.EventStrength;
@ -2745,7 +2745,7 @@ public static class AgentHarness
} }
{ {
DiscreteEventEntry itemEntry = ItemInterestCatalog.GetOrFallback(id); DiscreteEventEntry itemEntry = EventCatalog.Item.GetOrFallback(id);
key = "item:" + itemEntry.Id + ":" + EventFeedUtil.SafeId(unit); key = "item:" + itemEntry.Id + ":" + EventFeedUtil.SafeId(unit);
label = itemEntry.MakeLabel(EventFeedUtil.SafeName(unit), ""); label = itemEntry.MakeLabel(EventFeedUtil.SafeName(unit), "");
strength = itemEntry.EventStrength; strength = itemEntry.EventStrength;
@ -2762,7 +2762,7 @@ public static class AgentHarness
} }
{ {
DiscreteEventEntry decEntry = DecisionInterestCatalog.GetOrFallback(id); DiscreteEventEntry decEntry = EventCatalog.Decision.GetOrFallback(id);
key = "decision:" + decEntry.Id + ":" + EventFeedUtil.SafeId(unit); key = "decision:" + decEntry.Id + ":" + EventFeedUtil.SafeId(unit);
label = decEntry.MakeLabel(EventFeedUtil.SafeName(unit), ""); label = decEntry.MakeLabel(EventFeedUtil.SafeName(unit), "");
strength = decEntry.EventStrength; strength = decEntry.EventStrength;
@ -2779,7 +2779,7 @@ public static class AgentHarness
} }
{ {
DiscreteEventEntry powEntry = PowerInterestCatalog.GetOrFallback(id); DiscreteEventEntry powEntry = EventCatalog.Power.GetOrFallback(id);
key = "power:" + powEntry.Id + ":" + EventFeedUtil.SafeId(unit); key = "power:" + powEntry.Id + ":" + EventFeedUtil.SafeId(unit);
label = powEntry.MakeLabel(EventFeedUtil.SafeName(unit), ""); label = powEntry.MakeLabel(EventFeedUtil.SafeName(unit), "");
strength = powEntry.EventStrength; strength = powEntry.EventStrength;
@ -2797,7 +2797,7 @@ public static class AgentHarness
} }
{ {
DiscreteEventEntry stEntry = SubspeciesTraitInterestCatalog.GetOrFallback(id); DiscreteEventEntry stEntry = EventCatalog.SubspeciesTrait.GetOrFallback(id);
key = "subspecies_trait:" + stEntry.Id + ":" + EventFeedUtil.SafeId(unit); key = "subspecies_trait:" + stEntry.Id + ":" + EventFeedUtil.SafeId(unit);
label = stEntry.MakeLabel(EventFeedUtil.SafeName(unit), ""); label = stEntry.MakeLabel(EventFeedUtil.SafeName(unit), "");
strength = stEntry.EventStrength; strength = stEntry.EventStrength;
@ -2814,7 +2814,7 @@ public static class AgentHarness
} }
{ {
DiscreteEventEntry geneEntry = GeneInterestCatalog.GetOrFallback(id); DiscreteEventEntry geneEntry = EventCatalog.Gene.GetOrFallback(id);
key = "gene:" + geneEntry.Id + ":" + EventFeedUtil.SafeId(unit); key = "gene:" + geneEntry.Id + ":" + EventFeedUtil.SafeId(unit);
label = geneEntry.MakeLabel(EventFeedUtil.SafeName(unit), ""); label = geneEntry.MakeLabel(EventFeedUtil.SafeName(unit), "");
strength = geneEntry.EventStrength; strength = geneEntry.EventStrength;

View file

@ -119,103 +119,103 @@ public static class DomainEventHarness
CatalogCoverageDiff plots = CatalogCoverageAudit.Diff( CatalogCoverageDiff plots = CatalogCoverageAudit.Diff(
"plots", "plots",
ActivityAssetCatalog.EnumerateLivePlotIds(), ActivityAssetCatalog.EnumerateLivePlotIds(),
PlotInterestCatalog.AuthoredIds); EventCatalog.Plot.AuthoredIds);
AppendLibraryDomain(tsv, "plots", ActivityAssetCatalog.EnumerateLivePlotIds(), plots, PlotInterestCatalog.GetOrFallback); AppendLibraryDomain(tsv, "plots", ActivityAssetCatalog.EnumerateLivePlotIds(), plots, EventCatalog.Plot.GetOrFallback);
CatalogCoverageDiff eras = CatalogCoverageAudit.Diff( CatalogCoverageDiff eras = CatalogCoverageAudit.Diff(
"eras", "eras",
ActivityAssetCatalog.EnumerateLiveEraIds(), ActivityAssetCatalog.EnumerateLiveEraIds(),
EraInterestCatalog.AuthoredIds); EventCatalog.Era.AuthoredIds);
AppendLibraryDomain(tsv, "eras", ActivityAssetCatalog.EnumerateLiveEraIds(), eras, EraInterestCatalog.GetOrFallback); AppendLibraryDomain(tsv, "eras", ActivityAssetCatalog.EnumerateLiveEraIds(), eras, EventCatalog.Era.GetOrFallback);
CatalogCoverageDiff books = CatalogCoverageAudit.Diff( CatalogCoverageDiff books = CatalogCoverageAudit.Diff(
"books", "books",
ActivityAssetCatalog.EnumerateLiveBookTypeIds(), ActivityAssetCatalog.EnumerateLiveBookTypeIds(),
BookInterestCatalog.AuthoredIds); EventCatalog.Book.AuthoredIds);
AppendLibraryDomain(tsv, "books", ActivityAssetCatalog.EnumerateLiveBookTypeIds(), books, BookInterestCatalog.GetOrFallback); AppendLibraryDomain(tsv, "books", ActivityAssetCatalog.EnumerateLiveBookTypeIds(), books, EventCatalog.Book.GetOrFallback);
CatalogCoverageDiff traits = CatalogCoverageAudit.Diff( CatalogCoverageDiff traits = CatalogCoverageAudit.Diff(
"traits", "traits",
ActivityAssetCatalog.EnumerateLiveTraitIds(), ActivityAssetCatalog.EnumerateLiveTraitIds(),
TraitInterestCatalog.AuthoredIds); EventCatalog.Trait.AuthoredIds);
AppendLibraryDomain(tsv, "traits", ActivityAssetCatalog.EnumerateLiveTraitIds(), traits, TraitInterestCatalog.GetOrFallback); AppendLibraryDomain(tsv, "traits", ActivityAssetCatalog.EnumerateLiveTraitIds(), traits, EventCatalog.Trait.GetOrFallback);
CatalogCoverageDiff spells = CatalogCoverageAudit.Diff( CatalogCoverageDiff spells = CatalogCoverageAudit.Diff(
"spells", "spells",
ActivityAssetCatalog.EnumerateLiveSpellIds(), ActivityAssetCatalog.EnumerateLiveSpellIds(),
SpellInterestCatalog.AuthoredIds); EventCatalog.Spell.AuthoredIds);
AppendLibraryDomain(tsv, "spells", ActivityAssetCatalog.EnumerateLiveSpellIds(), spells, SpellInterestCatalog.GetOrFallback); AppendLibraryDomain(tsv, "spells", ActivityAssetCatalog.EnumerateLiveSpellIds(), spells, EventCatalog.Spell.GetOrFallback);
CatalogCoverageDiff powers = CatalogCoverageAudit.Diff( CatalogCoverageDiff powers = CatalogCoverageAudit.Diff(
"powers", "powers",
ActivityAssetCatalog.EnumerateLivePowerIds(), ActivityAssetCatalog.EnumerateLivePowerIds(),
PowerInterestCatalog.AuthoredIds); EventCatalog.Power.AuthoredIds);
AppendLibraryDomain(tsv, "powers", ActivityAssetCatalog.EnumerateLivePowerIds(), powers, PowerInterestCatalog.GetOrFallback); AppendLibraryDomain(tsv, "powers", ActivityAssetCatalog.EnumerateLivePowerIds(), powers, EventCatalog.Power.GetOrFallback);
CatalogCoverageDiff decisions = CatalogCoverageAudit.Diff( CatalogCoverageDiff decisions = CatalogCoverageAudit.Diff(
"decisions", "decisions",
ActivityAssetCatalog.EnumerateLiveDecisionIds(), ActivityAssetCatalog.EnumerateLiveDecisionIds(),
DecisionInterestCatalog.AuthoredIds); EventCatalog.Decision.AuthoredIds);
AppendLibraryDomain(tsv, "decisions", ActivityAssetCatalog.EnumerateLiveDecisionIds(), decisions, DecisionInterestCatalog.GetOrFallback); AppendLibraryDomain(tsv, "decisions", ActivityAssetCatalog.EnumerateLiveDecisionIds(), decisions, EventCatalog.Decision.GetOrFallback);
CatalogCoverageDiff items = CatalogCoverageAudit.Diff( CatalogCoverageDiff items = CatalogCoverageAudit.Diff(
"items", "items",
ActivityAssetCatalog.EnumerateLiveItemIds(), ActivityAssetCatalog.EnumerateLiveItemIds(),
ItemInterestCatalog.AuthoredIds); EventCatalog.Item.AuthoredIds);
AppendLibraryDomain(tsv, "items", ActivityAssetCatalog.EnumerateLiveItemIds(), items, ItemInterestCatalog.GetOrFallback); AppendLibraryDomain(tsv, "items", ActivityAssetCatalog.EnumerateLiveItemIds(), items, EventCatalog.Item.GetOrFallback);
CatalogCoverageDiff subspTraits = CatalogCoverageAudit.Diff( CatalogCoverageDiff subspTraits = CatalogCoverageAudit.Diff(
"subspecies_traits", "subspecies_traits",
ActivityAssetCatalog.EnumerateLiveSubspeciesTraitIds(), ActivityAssetCatalog.EnumerateLiveSubspeciesTraitIds(),
SubspeciesTraitInterestCatalog.AuthoredIds); EventCatalog.SubspeciesTrait.AuthoredIds);
AppendLibraryDomain( AppendLibraryDomain(
tsv, tsv,
"subspecies_traits", "subspecies_traits",
ActivityAssetCatalog.EnumerateLiveSubspeciesTraitIds(), ActivityAssetCatalog.EnumerateLiveSubspeciesTraitIds(),
subspTraits, subspTraits,
SubspeciesTraitInterestCatalog.GetOrFallback); EventCatalog.SubspeciesTrait.GetOrFallback);
CatalogCoverageDiff genes = CatalogCoverageAudit.Diff( CatalogCoverageDiff genes = CatalogCoverageAudit.Diff(
"genes", "genes",
ActivityAssetCatalog.EnumerateLiveGeneIds(), ActivityAssetCatalog.EnumerateLiveGeneIds(),
GeneInterestCatalog.AuthoredIds); EventCatalog.Gene.AuthoredIds);
AppendLibraryDomain(tsv, "genes", ActivityAssetCatalog.EnumerateLiveGeneIds(), genes, GeneInterestCatalog.GetOrFallback); AppendLibraryDomain(tsv, "genes", ActivityAssetCatalog.EnumerateLiveGeneIds(), genes, EventCatalog.Gene.GetOrFallback);
CatalogCoverageDiff phenotypes = CatalogCoverageAudit.Diff( CatalogCoverageDiff phenotypes = CatalogCoverageAudit.Diff(
"phenotypes", "phenotypes",
ActivityAssetCatalog.EnumerateLivePhenotypeIds(), ActivityAssetCatalog.EnumerateLivePhenotypeIds(),
PhenotypeInterestCatalog.AuthoredIds); EventCatalog.Phenotype.AuthoredIds);
AppendLibraryDomain( AppendLibraryDomain(
tsv, tsv,
"phenotypes", "phenotypes",
ActivityAssetCatalog.EnumerateLivePhenotypeIds(), ActivityAssetCatalog.EnumerateLivePhenotypeIds(),
phenotypes, phenotypes,
PhenotypeInterestCatalog.GetOrFallback); EventCatalog.Phenotype.GetOrFallback);
CatalogCoverageDiff worldLaws = CatalogCoverageAudit.Diff( CatalogCoverageDiff worldLaws = CatalogCoverageAudit.Diff(
"world_laws", "world_laws",
ActivityAssetCatalog.EnumerateLiveWorldLawIds(), ActivityAssetCatalog.EnumerateLiveWorldLawIds(),
WorldLawInterestCatalog.AuthoredIds); EventCatalog.WorldLaw.AuthoredIds);
AppendLibraryDomain( AppendLibraryDomain(
tsv, tsv,
"world_laws", "world_laws",
ActivityAssetCatalog.EnumerateLiveWorldLawIds(), ActivityAssetCatalog.EnumerateLiveWorldLawIds(),
worldLaws, worldLaws,
WorldLawInterestCatalog.GetOrFallback); EventCatalog.WorldLaw.GetOrFallback);
CatalogCoverageDiff biomes = CatalogCoverageAudit.Diff( CatalogCoverageDiff biomes = CatalogCoverageAudit.Diff(
"biomes", "biomes",
ActivityAssetCatalog.EnumerateLiveBiomeIds(), ActivityAssetCatalog.EnumerateLiveBiomeIds(),
BiomeInterestCatalog.AuthoredIds); EventCatalog.Biome.AuthoredIds);
AppendLibraryDomain(tsv, "biomes", ActivityAssetCatalog.EnumerateLiveBiomeIds(), biomes, BiomeInterestCatalog.GetOrFallback); AppendLibraryDomain(tsv, "biomes", ActivityAssetCatalog.EnumerateLiveBiomeIds(), biomes, EventCatalog.Biome.GetOrFallback);
int relMissing = 0; int relMissing = 0;
int relTotal = 0; int relTotal = 0;
foreach (string id in RelationshipEventCatalog.AuthoredIds) foreach (string id in EventCatalog.Relationship.AuthoredIds)
{ {
relTotal++; relTotal++;
DiscreteEventEntry entry = RelationshipEventCatalog.GetOrFallback(id); DiscreteEventEntry entry = EventCatalog.Relationship.GetOrFallback(id);
bool ok = RelationshipEventCatalog.HasAuthored(id) && !entry.IsFallback; bool ok = EventCatalog.Relationship.HasAuthored(id) && !entry.IsFallback;
if (!ok) if (!ok)
{ {
relMissing++; relMissing++;

View file

@ -26,13 +26,13 @@ public static class DisasterWarHarness
List<string> warTypes = ActivityAssetCatalog.EnumerateLiveWarTypeIds(); List<string> warTypes = ActivityAssetCatalog.EnumerateLiveWarTypeIds();
var authoredDisasters = new HashSet<string>(StringComparer.OrdinalIgnoreCase); var authoredDisasters = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (string id in DisasterInterestCatalog.AuthoredIds) foreach (string id in EventCatalog.Disaster.AuthoredIds)
{ {
authoredDisasters.Add(id); authoredDisasters.Add(id);
} }
var authoredWars = new HashSet<string>(StringComparer.OrdinalIgnoreCase); var authoredWars = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (string id in WarTypeInterestCatalog.AuthoredIds) foreach (string id in EventCatalog.WarType.AuthoredIds)
{ {
authoredWars.Add(id); authoredWars.Add(id);
} }
@ -49,8 +49,8 @@ public static class DisasterWarHarness
{ {
string id = disasters[i]; string id = disasters[i];
liveDisasters.Add(id); liveDisasters.Add(id);
DisasterInterestEntry entry = DisasterInterestCatalog.GetOrFallback(id); DisasterInterestEntry entry = EventCatalog.Disaster.GetOrFallback(id);
bool has = DisasterInterestCatalog.HasAuthored(id) && !entry.IsFallback; bool has = EventCatalog.Disaster.HasAuthored(id) && !entry.IsFallback;
if (!has) if (!has)
{ {
missingDisaster++; missingDisaster++;
@ -77,8 +77,8 @@ public static class DisasterWarHarness
{ {
string id = warTypes[i]; string id = warTypes[i];
liveWars.Add(id); liveWars.Add(id);
WarTypeInterestEntry entry = WarTypeInterestCatalog.GetOrFallback(id); WarTypeInterestEntry entry = EventCatalog.WarType.GetOrFallback(id);
bool has = WarTypeInterestCatalog.HasAuthored(id) && !entry.IsFallback; bool has = EventCatalog.WarType.HasAuthored(id) && !entry.IsFallback;
if (!has) if (!has)
{ {
missingWarType++; missingWarType++;

View file

@ -4,12 +4,14 @@ using System.Collections.Generic;
namespace IdleSpectator; namespace IdleSpectator;
/// <summary>Authored interest overlay for every live book_types asset.</summary> /// <summary>Authored interest overlay for every live book_types asset.</summary>
public static class BookInterestCatalog public static partial class EventCatalog
{
public static class Book
{ {
private static readonly Dictionary<string, DiscreteEventEntry> Entries = private static readonly Dictionary<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase); new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase);
static BookInterestCatalog() static Book()
{ {
Add("family_story", 52f, "Culture", "{a} writes a family story"); Add("family_story", 52f, "Culture", "{a} writes a family story");
Add("love_story", 58f, "Culture", "{a} writes a love story"); Add("love_story", 58f, "Culture", "{a} writes a love story");
@ -64,3 +66,4 @@ public static class BookInterestCatalog
}; };
} }
} }
}

View file

@ -14,12 +14,14 @@ public sealed class DisasterInterestEntry
} }
/// <summary>Authored interest overlay for every live disasters library asset.</summary> /// <summary>Authored interest overlay for every live disasters library asset.</summary>
public static class DisasterInterestCatalog public static partial class EventCatalog
{
public static class Disaster
{ {
private static readonly Dictionary<string, DisasterInterestEntry> Entries = private static readonly Dictionary<string, DisasterInterestEntry> Entries =
new Dictionary<string, DisasterInterestEntry>(StringComparer.OrdinalIgnoreCase); new Dictionary<string, DisasterInterestEntry>(StringComparer.OrdinalIgnoreCase);
static DisasterInterestCatalog() static Disaster()
{ {
Add("tornado", 95f, "disaster_tornado"); Add("tornado", 95f, "disaster_tornado");
Add("heatwave", 88f, "disaster_heatwave"); Add("heatwave", 88f, "disaster_heatwave");
@ -89,3 +91,4 @@ public static class DisasterInterestCatalog
}; };
} }
} }
}

View file

@ -4,12 +4,14 @@ using System.Collections.Generic;
namespace IdleSpectator; namespace IdleSpectator;
/// <summary>Authored interest overlay for every live era_library asset.</summary> /// <summary>Authored interest overlay for every live era_library asset.</summary>
public static class EraInterestCatalog public static partial class EventCatalog
{
public static class Era
{ {
private static readonly Dictionary<string, DiscreteEventEntry> Entries = private static readonly Dictionary<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase); new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase);
static EraInterestCatalog() static Era()
{ {
Add("age_hope", 78f, "World", "Age of Hope"); Add("age_hope", 78f, "World", "Age of Hope");
Add("age_sun", 80f, "World", "Age of Sun"); Add("age_sun", 80f, "World", "Age of Sun");
@ -63,3 +65,4 @@ public static class EraInterestCatalog
}; };
} }
} }
}

View file

@ -4,7 +4,9 @@ using System.Collections.Generic;
namespace IdleSpectator; namespace IdleSpectator;
/// <summary>Authored policy + prose for every live happiness effect.</summary> /// <summary>Authored policy + prose for every live happiness effect.</summary>
public static class HappinessEventCatalog public static partial class EventCatalog
{
public static class Happiness
{ {
private static readonly Dictionary<string, HappinessCatalogEntry> Entries = private static readonly Dictionary<string, HappinessCatalogEntry> Entries =
new Dictionary<string, HappinessCatalogEntry>(StringComparer.OrdinalIgnoreCase) new Dictionary<string, HappinessCatalogEntry>(StringComparer.OrdinalIgnoreCase)
@ -944,4 +946,4 @@ public static class HappinessEventCatalog
}; };
} }
} }
}

View file

@ -3,8 +3,10 @@ using System.Collections.Generic;
namespace IdleSpectator; namespace IdleSpectator;
/// <summary>Live spells library interest overlay (Signal when cast resolves to a unit).</summary> /// <summary>Live AssetManager library event dials (powers, genes, …).</summary>
public static class SpellInterestCatalog public static partial class EventCatalog
{
public static class Spell
{ {
private static readonly Dictionary<string, DiscreteEventEntry> Entries = private static readonly Dictionary<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase); new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase);
@ -43,7 +45,7 @@ public static class SpellInterestCatalog
} }
/// <summary>God powers library - mostly Ambient; Signal for disaster/spectacle ids.</summary> /// <summary>God powers library - mostly Ambient; Signal for disaster/spectacle ids.</summary>
public static class PowerInterestCatalog public static class Power
{ {
private static readonly Dictionary<string, DiscreteEventEntry> Entries = private static readonly Dictionary<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase); new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase);
@ -100,7 +102,7 @@ public static class PowerInterestCatalog
} }
/// <summary>AI decisions - Signal for war/rebellion/kingdom-affecting; Ambient otherwise.</summary> /// <summary>AI decisions - Signal for war/rebellion/kingdom-affecting; Ambient otherwise.</summary>
public static class DecisionInterestCatalog public static class Decision
{ {
private static readonly Dictionary<string, DiscreteEventEntry> Entries = private static readonly Dictionary<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase); new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase);
@ -169,7 +171,7 @@ public static class DecisionInterestCatalog
} }
/// <summary>Items library - Signal for legendary/wonder subset.</summary> /// <summary>Items library - Signal for legendary/wonder subset.</summary>
public static class ItemInterestCatalog public static class Item
{ {
private static readonly Dictionary<string, DiscreteEventEntry> Entries = private static readonly Dictionary<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase); new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase);
@ -223,7 +225,7 @@ public static class ItemInterestCatalog
} }
/// <summary>Subspecies traits - Signal for dramatic; Ambient fill-capped.</summary> /// <summary>Subspecies traits - Signal for dramatic; Ambient fill-capped.</summary>
public static class SubspeciesTraitInterestCatalog public static class SubspeciesTrait
{ {
private static readonly Dictionary<string, DiscreteEventEntry> Entries = private static readonly Dictionary<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase); new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase);
@ -280,7 +282,7 @@ public static class SubspeciesTraitInterestCatalog
} }
/// <summary>Genes - Ambient default.</summary> /// <summary>Genes - Ambient default.</summary>
public static class GeneInterestCatalog public static class Gene
{ {
private static readonly Dictionary<string, DiscreteEventEntry> Entries = private static readonly Dictionary<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase); new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase);
@ -314,7 +316,7 @@ public static class GeneInterestCatalog
} }
/// <summary>Phenotypes - Ambient default.</summary> /// <summary>Phenotypes - Ambient default.</summary>
public static class PhenotypeInterestCatalog public static class Phenotype
{ {
private static readonly Dictionary<string, DiscreteEventEntry> Entries = private static readonly Dictionary<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase); new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase);
@ -347,7 +349,7 @@ public static class PhenotypeInterestCatalog
} }
/// <summary>World laws - Ambient / location-only style.</summary> /// <summary>World laws - Ambient / location-only style.</summary>
public static class WorldLawInterestCatalog public static class WorldLaw
{ {
private static readonly Dictionary<string, DiscreteEventEntry> Entries = private static readonly Dictionary<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase); new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase);
@ -381,7 +383,7 @@ public static class WorldLawInterestCatalog
} }
/// <summary>Biomes - Ambient.</summary> /// <summary>Biomes - Ambient.</summary>
public static class BiomeInterestCatalog public static class Biome
{ {
private static readonly Dictionary<string, DiscreteEventEntry> Entries = private static readonly Dictionary<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase); new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase);
@ -412,3 +414,5 @@ public static class BiomeInterestCatalog
return LiveLibraryInterest.Lookup(Entries, id, "Biome", "Biome shifts: {id}", 26f); return LiveLibraryInterest.Lookup(Entries, id, "Biome", "Biome shifts: {id}", 26f);
} }
} }
}

View file

@ -4,12 +4,14 @@ using System.Collections.Generic;
namespace IdleSpectator; namespace IdleSpectator;
/// <summary>Authored interest overlay for every live plots_library asset.</summary> /// <summary>Authored interest overlay for every live plots_library asset.</summary>
public static class PlotInterestCatalog public static partial class EventCatalog
{
public static class Plot
{ {
private static readonly Dictionary<string, DiscreteEventEntry> Entries = private static readonly Dictionary<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase); new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase);
static PlotInterestCatalog() static Plot()
{ {
Add("rebellion", 92f, "Politics", "{a} is plotting a rebellion"); Add("rebellion", 92f, "Politics", "{a} is plotting a rebellion");
Add("new_war", 94f, "Politics", "{a} is plotting a war"); Add("new_war", 94f, "Politics", "{a} is plotting a war");
@ -80,3 +82,4 @@ public static class PlotInterestCatalog
}; };
} }
} }
}

View file

@ -3,37 +3,15 @@ using System.Collections.Generic;
namespace IdleSpectator; namespace IdleSpectator;
public sealed class DiscreteEventEntry
{
public string Id = "";
public float EventStrength = 50f;
public string Category = "Event";
public bool CreatesInterest = true;
public string LabelTemplate = "{a}";
public bool IsFallback;
public string MakeLabel(Actor a, Actor b = null)
{
return EventReason.Apply(LabelTemplate, a, b, Id);
}
public string MakeLabel(string a, string b)
{
string template = string.IsNullOrEmpty(LabelTemplate) ? "{id}" : LabelTemplate;
return template
.Replace("{id}", Id ?? "")
.Replace("{a}", a ?? "")
.Replace("{b}", b ?? "");
}
}
/// <summary>Authored discrete relationship lifecycle events (not a live asset library).</summary> /// <summary>Authored discrete relationship lifecycle events (not a live asset library).</summary>
public static class RelationshipEventCatalog public static partial class EventCatalog
{
public static class Relationship
{ {
private static readonly Dictionary<string, DiscreteEventEntry> Entries = private static readonly Dictionary<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase); new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase);
static RelationshipEventCatalog() static Relationship()
{ {
Add("set_lover", 72f, "Relationship", "{a} became lovers with {b}"); Add("set_lover", 72f, "Relationship", "{a} became lovers with {b}");
Add("clear_lover", 55f, "Relationship", "{a} parted from a lover"); Add("clear_lover", 55f, "Relationship", "{a} parted from a lover");
@ -83,7 +61,9 @@ public static class RelationshipEventCatalog
EventStrength = 40f, EventStrength = 40f,
Category = "Relationship", Category = "Relationship",
LabelTemplate = "{a} · {id}", LabelTemplate = "{a} · {id}",
CreatesInterest = false,
IsFallback = true IsFallback = true
}; };
} }
} }
}

View file

@ -16,12 +16,14 @@ public sealed class StatusInterestEntry
/// <summary> /// <summary>
/// Authored interest policy for every live status asset. Prose stays in ActivityStatusProse. /// Authored interest policy for every live status asset. Prose stays in ActivityStatusProse.
/// </summary> /// </summary>
public static class StatusInterestCatalog public static partial class EventCatalog
{
public static class Status
{ {
private static readonly Dictionary<string, StatusInterestEntry> Entries = private static readonly Dictionary<string, StatusInterestEntry> Entries =
new Dictionary<string, StatusInterestEntry>(StringComparer.OrdinalIgnoreCase); new Dictionary<string, StatusInterestEntry>(StringComparer.OrdinalIgnoreCase);
static StatusInterestCatalog() static Status()
{ {
// Spectacle / camera-worthy transformations // Spectacle / camera-worthy transformations
Add("burning", 70f, "StatusTransformation", true); Add("burning", 70f, "StatusTransformation", true);
@ -146,3 +148,4 @@ public static class StatusInterestCatalog
}; };
} }
} }
}

View file

@ -4,12 +4,14 @@ using System.Collections.Generic;
namespace IdleSpectator; namespace IdleSpectator;
/// <summary>Authored interest overlay for every live traits library asset.</summary> /// <summary>Authored interest overlay for every live traits library asset.</summary>
public static class TraitInterestCatalog public static partial class EventCatalog
{
public static class Trait
{ {
private static readonly Dictionary<string, DiscreteEventEntry> Entries = private static readonly Dictionary<string, DiscreteEventEntry> Entries =
new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase); new Dictionary<string, DiscreteEventEntry>(StringComparer.OrdinalIgnoreCase);
static TraitInterestCatalog() static Trait()
{ {
Add("zombie", 82f); Add("zombie", 82f);
Add("wise", 42f); Add("wise", 42f);
@ -164,3 +166,4 @@ public static class TraitInterestCatalog
}; };
} }
} }
}

View file

@ -14,12 +14,14 @@ public sealed class WarTypeInterestEntry
} }
/// <summary>Authored interest overlay for every live war_types_library asset.</summary> /// <summary>Authored interest overlay for every live war_types_library asset.</summary>
public static class WarTypeInterestCatalog public static partial class EventCatalog
{
public static class WarType
{ {
private static readonly Dictionary<string, WarTypeInterestEntry> Entries = private static readonly Dictionary<string, WarTypeInterestEntry> Entries =
new Dictionary<string, WarTypeInterestEntry>(StringComparer.OrdinalIgnoreCase); new Dictionary<string, WarTypeInterestEntry>(StringComparer.OrdinalIgnoreCase);
static WarTypeInterestCatalog() static WarType()
{ {
Add("normal", 90f, "War: {a}"); Add("normal", 90f, "War: {a}");
Add("spite", 88f, "Spite war: {a}"); Add("spite", 88f, "Spite war: {a}");
@ -90,3 +92,4 @@ public static class WarTypeInterestCatalog
.Replace("{a}", special1 ?? ""); .Replace("{a}", special1 ?? "");
} }
} }
}

View file

@ -42,12 +42,14 @@ public sealed class WorldLogEventEntry
/// <summary> /// <summary>
/// Authored policy for every live WorldLog asset. Game library is inventory; this is presentation/scoring only. /// Authored policy for every live WorldLog asset. Game library is inventory; this is presentation/scoring only.
/// </summary> /// </summary>
public static class WorldLogEventCatalog public static partial class EventCatalog
{
public static class WorldLog
{ {
private static readonly Dictionary<string, WorldLogEventEntry> Entries = private static readonly Dictionary<string, WorldLogEventEntry> Entries =
new Dictionary<string, WorldLogEventEntry>(StringComparer.OrdinalIgnoreCase); new Dictionary<string, WorldLogEventEntry>(StringComparer.OrdinalIgnoreCase);
static WorldLogEventCatalog() static WorldLog()
{ {
// Kings // Kings
Add("king_new", 78f, "Politics", true, "New king: {b} ({a})", 6f, 28f); Add("king_new", 78f, "Politics", true, "New king: {b} ({a})", 6f, 28f);
@ -188,3 +190,4 @@ public static class WorldLogEventCatalog
return GetOrFallback(message.asset_id).MakeLabel(message); return GetOrFallback(message.asset_id).MakeLabel(message);
} }
} }
}

View file

@ -61,7 +61,8 @@ public static class LiveLibraryInterest
string id, string id,
string category, string category,
string labelTemplate, string labelTemplate,
float fallbackStrength = 40f) float fallbackStrength = 40f,
bool fallbackCreatesInterest = false)
{ {
if (!string.IsNullOrEmpty(id) && entries != null && entries.TryGetValue(id.Trim(), out DiscreteEventEntry entry)) if (!string.IsNullOrEmpty(id) && entries != null && entries.TryGetValue(id.Trim(), out DiscreteEventEntry entry))
{ {
@ -75,6 +76,7 @@ public static class LiveLibraryInterest
EventStrength = fallbackStrength, EventStrength = fallbackStrength,
Category = category, Category = category,
LabelTemplate = labelTemplate, LabelTemplate = labelTemplate,
CreatesInterest = fallbackCreatesInterest,
IsFallback = true IsFallback = true
}; };
} }

View file

@ -0,0 +1,29 @@
namespace IdleSpectator;
/// <summary>
/// Shared catalog row for discrete / library-backed spectator events.
/// Lives in <c>Events/</c> with <see cref="EventReason"/> - catalogs own dials; director only ranks.
/// </summary>
public sealed class DiscreteEventEntry
{
public string Id = "";
public float EventStrength = 50f;
public string Category = "Event";
public bool CreatesInterest = true;
public string LabelTemplate = "{a}";
public bool IsFallback;
public string MakeLabel(Actor a, Actor b = null)
{
return EventReason.Apply(LabelTemplate, a, b, Id);
}
public string MakeLabel(string a, string b)
{
string template = string.IsNullOrEmpty(LabelTemplate) ? "{id}" : LabelTemplate;
return template
.Replace("{id}", Id ?? "")
.Replace("{a}", a ?? "")
.Replace("{b}", b ?? "");
}
}

View file

@ -0,0 +1,36 @@
namespace IdleSpectator;
/// <summary>
/// IdleSpectator event inventory (one type, split across partial files).
/// Call sites: EventCatalog.Status / .Happiness / .Combat / …
/// Director only ranks; feeds register from these dials.
///
/// 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 (Spell, Power, Decision, Item, SubspeciesTrait, Gene, Phenotype, WorldLaw, Biome)
/// Combat policy lives in this file.
/// </summary>
public static partial class EventCatalog
{
/// <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;
}
}

View file

@ -6,7 +6,8 @@ namespace IdleSpectator;
/// <summary> /// <summary>
/// Sole factory for interest Labels shown as the orange dossier reason. /// Sole factory for interest Labels shown as the orange dossier reason.
/// Feeds must call these helpers (or Apply) instead of concatenating crumbs. /// Part of the <c>Events/</c> module with catalogs - feeds call these helpers (or Apply)
/// instead of concatenating crumbs. Director never authors reasons.
/// </summary> /// </summary>
public static class EventReason public static class EventReason
{ {

View file

@ -12,7 +12,7 @@ public static class BookInterestFeed
return; return;
} }
DiscreteEventEntry entry = BookInterestCatalog.GetOrFallback(bookTypeId); DiscreteEventEntry entry = EventCatalog.Book.GetOrFallback(bookTypeId);
if (!entry.CreatesInterest) if (!entry.CreatesInterest)
{ {
return; return;

View file

@ -11,7 +11,7 @@ public static class DeferredInterestFeed
"spell", "spell",
spellId, spellId,
caster, caster,
SpellInterestCatalog.GetOrFallback, EventCatalog.Spell.GetOrFallback,
related: null, related: null,
locationOnly: false); locationOnly: false);
} }
@ -22,7 +22,7 @@ public static class DeferredInterestFeed
"item", "item",
itemId, itemId,
craftsman, craftsman,
ItemInterestCatalog.GetOrFallback, EventCatalog.Item.GetOrFallback,
related: null, related: null,
locationOnly: false); locationOnly: false);
} }
@ -33,14 +33,14 @@ public static class DeferredInterestFeed
"decision", "decision",
decisionId, decisionId,
actor, actor,
DecisionInterestCatalog.GetOrFallback, EventCatalog.Decision.GetOrFallback,
related: null, related: null,
locationOnly: false); locationOnly: false);
} }
public static void EmitPower(string powerId, Vector3 position, Actor nearUnit) public static void EmitPower(string powerId, Vector3 position, Actor nearUnit)
{ {
DiscreteEventEntry entry = PowerInterestCatalog.GetOrFallback(powerId); DiscreteEventEntry entry = EventCatalog.Power.GetOrFallback(powerId);
if (!entry.CreatesInterest || AgentHarness.Busy) if (!entry.CreatesInterest || AgentHarness.Busy)
{ {
return; return;
@ -48,7 +48,7 @@ public static class DeferredInterestFeed
if (nearUnit != null && nearUnit.isAlive()) if (nearUnit != null && nearUnit.isAlive())
{ {
EmitFromCatalog("power", powerId, nearUnit, PowerInterestCatalog.GetOrFallback, null, false); EmitFromCatalog("power", powerId, nearUnit, EventCatalog.Power.GetOrFallback, null, false);
return; return;
} }
@ -75,7 +75,7 @@ public static class DeferredInterestFeed
"subspecies_trait", "subspecies_trait",
traitId, traitId,
anchor, anchor,
SubspeciesTraitInterestCatalog.GetOrFallback, EventCatalog.SubspeciesTrait.GetOrFallback,
related: null, related: null,
locationOnly: false); locationOnly: false);
} }
@ -86,7 +86,7 @@ public static class DeferredInterestFeed
"gene", "gene",
geneId, geneId,
actor, actor,
GeneInterestCatalog.GetOrFallback, EventCatalog.Gene.GetOrFallback,
related: null, related: null,
locationOnly: false); locationOnly: false);
} }
@ -97,7 +97,7 @@ public static class DeferredInterestFeed
"phenotype", "phenotype",
phenotypeId, phenotypeId,
actor, actor,
PhenotypeInterestCatalog.GetOrFallback, EventCatalog.Phenotype.GetOrFallback,
related: null, related: null,
locationOnly: false); locationOnly: false);
} }
@ -109,7 +109,7 @@ public static class DeferredInterestFeed
return; return;
} }
DiscreteEventEntry entry = WorldLawInterestCatalog.GetOrFallback(lawId); DiscreteEventEntry entry = EventCatalog.WorldLaw.GetOrFallback(lawId);
if (!entry.CreatesInterest) if (!entry.CreatesInterest)
{ {
return; return;
@ -134,7 +134,7 @@ public static class DeferredInterestFeed
return; return;
} }
DiscreteEventEntry entry = BiomeInterestCatalog.GetOrFallback(biomeId); DiscreteEventEntry entry = EventCatalog.Biome.GetOrFallback(biomeId);
if (!entry.CreatesInterest) if (!entry.CreatesInterest)
{ {
return; return;

View file

@ -93,7 +93,7 @@ public static class InterestFeeds
return; return;
} }
WorldLogEventEntry entry = WorldLogEventCatalog.GetOrFallback(message.asset_id); WorldLogEventEntry entry = EventCatalog.WorldLog.GetOrFallback(message.asset_id);
if (!entry.CreatesInterest) if (!entry.CreatesInterest)
{ {
return; return;
@ -325,15 +325,14 @@ public static class InterestFeeds
} }
string verb = taskOrBeat ?? "fighting"; string verb = taskOrBeat ?? "fighting";
// One combat key per fighter so activity + scanner merge instead of thrashing. string key = EventCatalog.Combat.Key(id);
string key = "combat:" + id;
var candidate = new InterestCandidate var candidate = new InterestCandidate
{ {
Key = key, Key = key,
LeadKind = InterestLeadKind.EventLed, LeadKind = InterestLeadKind.EventLed,
Category = "Combat", Category = "Combat",
Source = "activity", Source = "activity",
EventStrength = 88f, EventStrength = EventCatalog.Combat.ActivityStrength,
VisualConfidence = 0.8f, VisualConfidence = 0.8f,
Position = actor.current_position, Position = actor.current_position,
FollowUnit = actor, FollowUnit = actor,
@ -348,9 +347,9 @@ public static class InterestFeeds
KingdomKey = actor.kingdom != null ? (actor.kingdom.name ?? "") : "", KingdomKey = actor.kingdom != null ? (actor.kingdom.name ?? "") : "",
CreatedAt = Time.unscaledTime, CreatedAt = Time.unscaledTime,
LastSeenAt = Time.unscaledTime, LastSeenAt = Time.unscaledTime,
ExpiresAt = Time.unscaledTime + 20f, ExpiresAt = Time.unscaledTime + EventCatalog.Combat.ActivityTtl,
MinWatch = 4f, MinWatch = EventCatalog.Combat.MinWatch,
MaxWatch = 60f, MaxWatch = EventCatalog.Combat.MaxWatch,
Completion = InterestCompletionKind.CombatActive Completion = InterestCompletionKind.CombatActive
}; };
candidate.ParticipantIds.Add(id); candidate.ParticipantIds.Add(id);
@ -370,7 +369,7 @@ public static class InterestFeeds
return; return;
} }
StatusInterestEntry entry = StatusInterestCatalog.GetOrFallback(statusId); StatusInterestEntry entry = EventCatalog.Status.GetOrFallback(statusId);
if (!entry.CreatesInterest) if (!entry.CreatesInterest)
{ {
return; return;

View file

@ -12,7 +12,7 @@ public static class MetaInterestFeed
return; return;
} }
DiscreteEventEntry entry = EraInterestCatalog.GetOrFallback(eraId); DiscreteEventEntry entry = EventCatalog.Era.GetOrFallback(eraId);
if (!entry.CreatesInterest) if (!entry.CreatesInterest)
{ {
return; return;

View file

@ -14,7 +14,7 @@ public static class PlotInterestFeed
return; return;
} }
DiscreteEventEntry entry = PlotInterestCatalog.GetOrFallback(plotAssetId); DiscreteEventEntry entry = EventCatalog.Plot.GetOrFallback(plotAssetId);
if (!entry.CreatesInterest) if (!entry.CreatesInterest)
{ {
return; return;

View file

@ -12,7 +12,7 @@ public static class RelationshipInterestFeed
return; return;
} }
DiscreteEventEntry entry = RelationshipEventCatalog.GetOrFallback(eventId); DiscreteEventEntry entry = EventCatalog.Relationship.GetOrFallback(eventId);
if (!entry.CreatesInterest) if (!entry.CreatesInterest)
{ {
return; return;
@ -69,7 +69,7 @@ public static class RelationshipInterestFeed
return; return;
} }
DiscreteEventEntry entry = RelationshipEventCatalog.GetOrFallback(eventId); DiscreteEventEntry entry = EventCatalog.Relationship.GetOrFallback(eventId);
Actor follow = anchor != null && anchor.isAlive() ? anchor : null; Actor follow = anchor != null && anchor.isAlive() ? anchor : null;
if (follow == null) if (follow == null)
{ {
@ -122,7 +122,7 @@ public static class RelationshipInterestFeed
return EventReason.FamilyPack(subject, related, "leave"); return EventReason.FamilyPack(subject, related, "leave");
default: default:
return EventReason.Apply( return EventReason.Apply(
RelationshipEventCatalog.GetOrFallback(eventId).LabelTemplate, EventCatalog.Relationship.GetOrFallback(eventId).LabelTemplate,
subject, subject,
related, related,
eventId); eventId);

View file

@ -59,7 +59,7 @@ public static class WarInterestFeed
private static bool TryRegisterWar(object war, string phase) private static bool TryRegisterWar(object war, string phase)
{ {
string warTypeId = ReadWarTypeId(war); string warTypeId = ReadWarTypeId(war);
WarTypeInterestEntry entry = WarTypeInterestCatalog.GetOrFallback(warTypeId); WarTypeInterestEntry entry = EventCatalog.WarType.GetOrFallback(warTypeId);
if (!entry.CreatesInterest) if (!entry.CreatesInterest)
{ {
return false; return false;
@ -86,7 +86,7 @@ public static class WarInterestFeed
string phaseKey = string.IsNullOrEmpty(phase) ? "active" : phase; string phaseKey = string.IsNullOrEmpty(phase) ? "active" : phase;
string key = "war:" + phaseKey + ":" + (ReadString(war, "id") ?? labelPair) + ":" + (warTypeId ?? "normal"); string key = "war:" + phaseKey + ":" + (ReadString(war, "id") ?? labelPair) + ":" + (warTypeId ?? "normal");
string label = WarTypeInterestCatalog.MakeLabel(entry, labelPair); string label = EventCatalog.WarType.MakeLabel(entry, labelPair);
if (phaseKey == "new") if (phaseKey == "new")
{ {
label = "War begins: " + labelPair; label = "War begins: " + labelPair;

View file

@ -287,7 +287,7 @@ public static class DeferredEventPatches
} }
// High-frequency hook: only kingdom-affecting decisions, never idle AI ticks. // High-frequency hook: only kingdom-affecting decisions, never idle AI ticks.
if (!DecisionInterestCatalog.IsCameraWorthy(id)) if (!EventCatalog.Decision.IsCameraWorthy(id))
{ {
return; return;
} }
@ -304,7 +304,7 @@ public static class DeferredEventPatches
return; return;
} }
string id = "phenotype"; string id = "";
try try
{ {
object data = __instance.data; object data = __instance.data;
@ -312,12 +312,19 @@ public static class DeferredEventPatches
?? data?.GetType().GetProperty("phenotype")?.GetValue(data, null); ?? data?.GetType().GetProperty("phenotype")?.GetValue(data, null);
if (ph != null) if (ph != null)
{ {
id = ph.ToString(); id = ph.ToString() ?? "";
} }
} }
catch catch
{ {
// ignore id = "";
}
// Placeholder / empty ids are not camera events (catalog ambient is CreatesInterest=false).
if (string.IsNullOrEmpty(id)
|| string.Equals(id, "phenotype", StringComparison.OrdinalIgnoreCase))
{
return;
} }
DeferredInterestFeed.EmitPhenotype(id, __instance); DeferredInterestFeed.EmitPhenotype(id, __instance);

View file

@ -112,7 +112,7 @@ public static class TraitEventPatches
return; return;
} }
DiscreteEventEntry entry = TraitInterestCatalog.GetOrFallback(traitId); DiscreteEventEntry entry = EventCatalog.Trait.GetOrFallback(traitId);
if (!entry.CreatesInterest) if (!entry.CreatesInterest)
{ {
return; return;

View file

@ -14,7 +14,7 @@ public static class WorldLogMessageAddPatch
return; return;
} }
WorldLogEventEntry entry = WorldLogEventCatalog.GetOrFallback(pMessage.asset_id); WorldLogEventEntry entry = EventCatalog.WorldLog.GetOrFallback(pMessage.asset_id);
// Chronicle notable world events only (authored ChronicleEligible / story-strength+). // Chronicle notable world events only (authored ChronicleEligible / story-strength+).
if (!entry.ChronicleEligible) if (!entry.ChronicleEligible)
{ {

View file

@ -214,7 +214,7 @@ public static class HappinessEventRouter
FlushStaleAggregates(); FlushStaleAggregates();
HappinessCatalogEntry entry = HappinessEventCatalog.GetOrFallback(effectId); HappinessCatalogEntry entry = EventCatalog.Happiness.GetOrFallback(effectId);
if (related == null if (related == null
&& HappinessContextBag.TryGetRelated(subject, out Actor bagRelated, out HappinessRelationRole bagRole)) && HappinessContextBag.TryGetRelated(subject, out Actor bagRelated, out HappinessRelationRole bagRole))
{ {
@ -407,7 +407,7 @@ public static class HappinessEventRouter
continue; continue;
} }
HappinessCatalogEntry entry = HappinessEventCatalog.GetOrFallback(bucket.EffectId); HappinessCatalogEntry entry = EventCatalog.Happiness.GetOrFallback(bucket.EffectId);
HappinessOccurrence summary = BuildOccurrence( HappinessOccurrence summary = BuildOccurrence(
subject, subject,
bucket.EffectId, bucket.EffectId,
@ -450,7 +450,7 @@ public static class HappinessEventRouter
bool applied, bool applied,
bool suppressedByPsychopath) bool suppressedByPsychopath)
{ {
HappinessCatalogEntry entry = HappinessEventCatalog.GetOrFallback(effectId); HappinessCatalogEntry entry = EventCatalog.Happiness.GetOrFallback(effectId);
long subjectId = 0; long subjectId = 0;
string subjectName = "Someone"; string subjectName = "Someone";
string species = ""; string species = "";

View file

@ -39,12 +39,12 @@ public static class InterestScoring
public static float EventStrengthForHappiness(string effectId) public static float EventStrengthForHappiness(string effectId)
{ {
return HappinessEventCatalog.GetOrFallback(effectId).EventStrength; return EventCatalog.Happiness.GetOrFallback(effectId).EventStrength;
} }
public static float EventStrengthForWorldLog(string assetId) public static float EventStrengthForWorldLog(string assetId)
{ {
return WorldLogEventCatalog.GetOrFallback(assetId).EventStrength; return EventCatalog.WorldLog.GetOrFallback(assetId).EventStrength;
} }
public static bool IsFillScore(float totalScore) public static bool IsFillScore(float totalScore)

View file

@ -126,11 +126,11 @@ public static class WorldActivityScanner
string label = EventReason.Fight(actor, foe); string label = EventReason.Fight(actor, foe);
var candidate = new InterestCandidate var candidate = new InterestCandidate
{ {
Key = "combat:" + id, Key = EventCatalog.Combat.Key(id),
LeadKind = InterestLeadKind.EventLed, LeadKind = InterestLeadKind.EventLed,
Category = "Combat", Category = "Combat",
Source = "scanner", Source = "scanner",
EventStrength = Mathf.Max(actionScore, 80f), EventStrength = Mathf.Max(actionScore, EventCatalog.Combat.ScannerStrengthFloor),
CharacterSignificance = charScore, CharacterSignificance = charScore,
VisualConfidence = 0.7f, VisualConfidence = 0.7f,
Position = actor.current_position, Position = actor.current_position,
@ -148,9 +148,9 @@ public static class WorldActivityScanner
NotableParticipantCount = notables, NotableParticipantCount = notables,
CreatedAt = Time.unscaledTime, CreatedAt = Time.unscaledTime,
LastSeenAt = Time.unscaledTime, LastSeenAt = Time.unscaledTime,
ExpiresAt = Time.unscaledTime + 18f, ExpiresAt = Time.unscaledTime + EventCatalog.Combat.ScannerTtl,
MinWatch = 4f, MinWatch = EventCatalog.Combat.MinWatch,
MaxWatch = 60f, MaxWatch = EventCatalog.Combat.MaxWatch,
Completion = InterestCompletionKind.CombatActive Completion = InterestCompletionKind.CombatActive
}; };
InterestScoring.ScoreCheap(candidate); InterestScoring.ScoreCheap(candidate);

View file

@ -26,7 +26,7 @@ public static class WorldLogEventHarness
{ {
List<string> liveIds = ActivityAssetCatalog.EnumerateLiveWorldLogIds(); List<string> liveIds = ActivityAssetCatalog.EnumerateLiveWorldLogIds();
var authored = new HashSet<string>(StringComparer.OrdinalIgnoreCase); var authored = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (string id in WorldLogEventCatalog.AuthoredIds) foreach (string id in EventCatalog.WorldLog.AuthoredIds)
{ {
authored.Add(id); authored.Add(id);
} }
@ -44,8 +44,8 @@ public static class WorldLogEventHarness
string id = liveIds[i]; string id = liveIds[i];
liveSet.Add(id); liveSet.Add(id);
WorldLogAsset asset = ActivityAssetCatalog.TryGetWorldLogAsset(id); WorldLogAsset asset = ActivityAssetCatalog.TryGetWorldLogAsset(id);
bool hasAuthored = WorldLogEventCatalog.HasAuthored(id); bool hasAuthored = EventCatalog.WorldLog.HasAuthored(id);
WorldLogEventEntry entry = WorldLogEventCatalog.GetOrFallback(id); WorldLogEventEntry entry = EventCatalog.WorldLog.GetOrFallback(id);
if (!hasAuthored || entry.IsFallback) if (!hasAuthored || entry.IsFallback)
{ {
missingAuthored++; missingAuthored++;

View file

@ -3,19 +3,19 @@ using System.Collections.Generic;
namespace IdleSpectator; namespace IdleSpectator;
/// <summary> /// <summary>
/// Compatibility facade over <see cref="WorldLogEventCatalog"/>. Prefer the catalog directly. /// Compatibility facade over <see cref="EventCatalog.WorldLog"/>. Prefer the catalog directly.
/// </summary> /// </summary>
public static class WorldLogInterestTable public static class WorldLogInterestTable
{ {
public static bool TryGetEventStrength(string assetId, out float eventStrength) public static bool TryGetEventStrength(string assetId, out float eventStrength)
{ {
return WorldLogEventCatalog.TryGetEventStrength(assetId, out eventStrength); return EventCatalog.WorldLog.TryGetEventStrength(assetId, out eventStrength);
} }
public static string MakeLabel(WorldLogMessage message) public static string MakeLabel(WorldLogMessage message)
{ {
return WorldLogEventCatalog.MakeLabel(message); return EventCatalog.WorldLog.MakeLabel(message);
} }
public static IEnumerable<string> AuthoredIds => WorldLogEventCatalog.AuthoredIds; public static IEnumerable<string> AuthoredIds => EventCatalog.WorldLog.AuthoredIds;
} }

View file

@ -1,7 +1,7 @@
{ {
"name": "IdleSpectator", "name": "IdleSpectator",
"author": "dazed", "author": "dazed",
"version": "0.20.12", "version": "0.21.1",
"description": "AFK Idle Spectator (I) + Lore (L). Event-centered scene director + happiness Activity/Life logging.", "description": "AFK Idle Spectator (I) + Lore (L). Event-centered scene director + happiness Activity/Life logging.",
"GUID": "com.dazed.idlespectator" "GUID": "com.dazed.idlespectator"
} }

View file

@ -95,7 +95,7 @@
"IdleSpectator/WorldActivityScanner.cs", "IdleSpectator/WorldActivityScanner.cs",
"IdleSpectator/InterestDirector.cs", "IdleSpectator/InterestDirector.cs",
"IdleSpectator/InterestVariety.cs", "IdleSpectator/InterestVariety.cs",
"IdleSpectator/InterestFeeds.cs" "IdleSpectator/Events/Feeds/InterestFeeds.cs"
], ],
"designIntent": [ "designIntent": [
"Actions matter much more than characters.", "Actions matter much more than characters.",

View file

@ -3,6 +3,10 @@
Inventory policy after the full gap expand. Inventory policy after the full gap expand.
Camera interrupt is score-margin only (`cutInMargin`); no Signal/Ambient ownership gate. Camera interrupt is score-margin only (`cutInMargin`); no Signal/Ambient ownership gate.
**Single inventory:** [`EventCatalog`](../IdleSpectator/Events/EventCatalog.cs) (partials under `Events/Catalogs/`).
Nested domains: `Status`, `Happiness`, `WorldLog`, `Trait`, `Combat`, `Spell`, …
Feeds/patches register from those dials; `InterestDirector` only ranks candidates.
## Dials ## Dials
| Dial | Role | | Dial | Role |
@ -30,17 +34,17 @@ Ambient / Character fill is exempt - events may take the camera immediately.
| Source | Primary owner | Reason factory | Notes | | Source | Primary owner | Reason factory | Notes |
|--------|---------------|----------------|-------| |--------|---------------|----------------|-------|
| WorldLog | `InterestFeeds.OnWorldLogMessage` | catalog / EventReason | Strength from WorldLogEventCatalog | | WorldLog | `InterestFeeds.OnWorldLogMessage` | catalog / EventReason | Strength from `EventCatalog.WorldLog` |
| Happiness | `IngestHappiness` | HappinessEventCatalog + EventReason | Birth/hatch freshness; grief sticky | | Happiness | `IngestHappiness` | `EventCatalog.Happiness` + EventReason | Birth/hatch freshness; grief sticky |
| Status | `OnStatusChange` | EventReason.Status | `drowning` CreatesInterest=true, strength ~50; notable via CharacterSignificance | | Status | `OnStatusChange` | EventReason.Status | `drowning` CreatesInterest=true, strength ~50; notable via CharacterSignificance |
| Scanner combat | WorldActivityScanner | EventReason.Fight / Battle | Completion CombatActive | | Scanner combat | WorldActivityScanner | EventReason.Fight / Battle | Completion CombatActive; dials `EventCatalog.Combat` |
| War | WarEventPatches + WarInterestFeed.Tick | war type labels | | | War | WarEventPatches + WarInterestFeed.Tick | war type labels | |
| Plot | PlotEventPatches + PlotInterestFeed.Tick | PlotInterestCatalog | | | Plot | PlotEventPatches + PlotInterestFeed.Tick | `EventCatalog.Plot` | |
| Relationship | RelationshipEventPatches + happiness lovers | EventReason.* | | | Relationship | RelationshipEventPatches + happiness lovers | EventReason.* | |
| Trait | TraitEventPatches | EventReason.Trait | Spawn window filters routine traits | | Trait | TraitEventPatches | EventReason.Trait | Spawn window filters routine traits |
| Building | BuildingEventPatches | EventReason.Building* | Eat/damage/falls | | Building | BuildingEventPatches | EventReason.Building* | Eat/damage/falls |
| Boat | BoatEventPatches | EventReason.Boat | | | Boat | BoatEventPatches | EventReason.Boat | |
| Book | BookEventPatches | BookInterestCatalog sentences | | | Book | BookEventPatches | `EventCatalog.Book` sentences | |
| Era / Meta | MetaEventPatches | EventReason.MetaNew / era labels | | | Era / Meta | MetaEventPatches | EventReason.MetaNew / era labels | |
| Spell | CombatActionLibrary.tryToCastSpell | EventReason.Library | Ambient CreatesInterest=false except spectacle ids | | Spell | CombatActionLibrary.tryToCastSpell | EventReason.Library | Ambient CreatesInterest=false except spectacle ids |
| Power | PlayerControl.clickedFinal | EventReason.HumanizeId | Spectacle ids create interest | | Power | PlayerControl.clickedFinal | EventReason.HumanizeId | Spectacle ids create interest |

View file

@ -11,9 +11,23 @@ Quiet grace / inactive dwell clears the reason even if focus has not switched ye
## EventReason ## EventReason
[`IdleSpectator/EventReason.cs`](../IdleSpectator/EventReason.cs) is the sole Label factory for camera candidates. [`IdleSpectator/Events/EventReason.cs`](../IdleSpectator/Events/EventReason.cs) is the sole Label factory for camera candidates.
It lives in the Events module with catalogs (not in the director).
Feeds call typed helpers (`Fight`, `BuildingEat`, `SeekingLover`, …) or `Apply(template, a, b, id)`. Feeds call typed helpers (`Fight`, `BuildingEat`, `SeekingLover`, …) or `Apply(template, a, b, id)`.
## Events module layout
| Path | Role |
|------|------|
| `Events/EventCatalog.cs` (+ `Catalogs/EventCatalog.*.cs`) | **One inventory** - nested domains (`Status`, `Combat`, …) |
| `Events/Feeds/` | Build + register candidates from catalog dials |
| `Events/Patches/` | Harmony hooks → feeds |
| `Events/EventReason.cs` | Orange reason sentences |
| `Events/EventFeedUtil.cs` | Shared Register path |
| `Events/DiscreteEventEntry.cs` | Shared catalog row shape |
`InterestDirector` only ranks registered candidates for the camera - it does not author event inventory.
Rules: Rules:
- Sentence form with names: `{a} is fighting {b}`, `{a} is eating a beehive`, `{a} is seeking a lover`. - Sentence form with names: `{a} is fighting {b}`, `{a} is eating a beehive`, `{a} is seeking a lover`.