The Chronicle — World History
The Chronicle records significant events from the Living World simulation: species extinctions, city foundings, war declarations, resource exhaustion, faction defeats. It is the historical record of the shared world and a content source your game can read to generate contextual lore, quest triggers, and NPC dialogue.
What The Chronicle records
Events are written by other subsystems when a threshold is crossed:
| Event type | Produced by | Example |
|---|---|---|
SpeciesEndangered | The Wild | Rabbit population in zone_north_forest dropped below 10% |
SpeciesExtinct | The Wild | Aurochs went extinct in zone_grasslands |
SpeciesRecovered | The Wild | Wolf population recovered above 50% in zone_highlands |
ResourceExhausted | The Flow | Iron vein 1 in zone_eastern_mines fully depleted |
ResourceRestored | The Flow | Berry bushes in zone_north_forest restored to 80% |
SettlementFounded | The Age | Ironwarden Guild founded a hamlet in zone_eastern_mines |
SettlementRazed | The Age | River Commune’s village in zone_plains was destroyed |
SettlementUpgraded | The Age | Ironwarden Guild’s town upgraded to city tier |
WarDeclared | The Age | Ironwarden Guild declared war on River Commune |
PeaceReached | The Age | Ironwarden Guild and River Commune signed a truce |
ResourceScarcityGlobal | The Flow | Berries were scarce across all forest zones for 30 game-days |
StormEvent | The Veil | A major storm system crossed 5 zones over 3 game-days |
Chronicles events include: a timestamp (world-time), a zone ID, the producing subsystem, a type enum, a dictionary of typed detail fields, and an optional player attribution (for events triggered by Echo).
Querying history
using Softfire.Engine.Worldweave.Chronicle;
var chronicle = Services.Get<ChronicleService>();
// Query for war declarations affecting a specific zone in the last 90 game-daysvar query = new ChronicleQuery{ EventTypes = new[] { ChronicleEventType.WarDeclared, ChronicleEventType.PeaceReached }, ZoneIds = new[] { currentZoneId }, SinceTime = WorldTime.Now.MinusDays(90), MaxResults = 20,};
IReadOnlyList<ChronicleEvent> events = await chronicle.QueryAsync(query);
foreach (var e in events){ string aggressor = e.Details.Get<string>("aggressorFactionId"); string defender = e.Details.Get<string>("defenderFactionId"); Logger.Info($"[{e.OccurredAt}] {aggressor} vs {defender}: {e.Type}");}Additional filter options on ChronicleQuery:
| Filter | Type | Description |
|---|---|---|
ActorId | string | Filter by faction, species, or player canonical ID |
SinceTime | WorldTime | Events on or after this world-time |
BeforeTime | WorldTime | Events before this world-time |
MaxResults | int | Limit result set |
OrderBy | ChronicleOrder | Newest (default) or Oldest |
Lore generation
The LoreGenerator service takes a list of Chronicle events and produces procedural prose — a block of text written in a configurable tone that reads like in-world history.
var lore = Services.Get<LoreGenerator>();
string passage = lore.GeneratePassage( events: chronicleEvents, tone: LoreTone.EpicChronicle, maxLength: 400);
// Display in an in-game book or scrolling lore panelUiSystem.ShowLorePanel(passage);Available tones: EpicChronicle, FieldNotes, GossipRumour, OfficialDecree, AncientFragment. Each tone produces text in a different register — GossipRumour reads like an NPC overheard at a tavern; AncientFragment produces fragmented, archaic prose.
Lore generation is template-based, not AI-generated: a set of sentence templates is populated with Chronicle event data. This means lore output is deterministic for a given set of events and tone, and does not require any network call.
Using Chronicle in dialogue and quests
A common pattern is to query Chronicle on scene load and store results as context variables for your dialogue tree:
// On entering a zonevar query = new ChronicleQuery{ ZoneIds = new[] { enteredZoneId }, SinceTime = WorldTime.Now.MinusDays(60), MaxResults = 5,};
var recentEvents = await chronicle.QueryAsync(query);DialogueContext.Set("recentChronicleEvents", recentEvents);DialogueContext.Set("zoneIsAtWar", recentEvents.Any(e => e.Type == ChronicleEventType.WarDeclared));Your dialogue tree then branches on zoneIsAtWar to serve contextually appropriate NPC responses — without any developer having written specific war-related story content in advance. The Chronicle provides the facts; your dialogue tree provides the framing.
Retention and aggregation
Chronicle events are retained in full for 1 in-game year (using the Pulse’s world calendar). Events older than 1 year are summarised to aggregates — individual war declarations become a “3 wars occurred in zone X over the decade” aggregate record. Aggregates are kept indefinitely.
Full event details are available for the trailing year. Aggregate records are available for all prior history. You can query both via ChronicleService — the result set transparently mixes full events and aggregate records based on the date range you query.