Skip to content

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 typeProduced byExample
SpeciesEndangeredThe WildRabbit population in zone_north_forest dropped below 10%
SpeciesExtinctThe WildAurochs went extinct in zone_grasslands
SpeciesRecoveredThe WildWolf population recovered above 50% in zone_highlands
ResourceExhaustedThe FlowIron vein 1 in zone_eastern_mines fully depleted
ResourceRestoredThe FlowBerry bushes in zone_north_forest restored to 80%
SettlementFoundedThe AgeIronwarden Guild founded a hamlet in zone_eastern_mines
SettlementRazedThe AgeRiver Commune’s village in zone_plains was destroyed
SettlementUpgradedThe AgeIronwarden Guild’s town upgraded to city tier
WarDeclaredThe AgeIronwarden Guild declared war on River Commune
PeaceReachedThe AgeIronwarden Guild and River Commune signed a truce
ResourceScarcityGlobalThe FlowBerries were scarce across all forest zones for 30 game-days
StormEventThe VeilA 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-days
var 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:

FilterTypeDescription
ActorIdstringFilter by faction, species, or player canonical ID
SinceTimeWorldTimeEvents on or after this world-time
BeforeTimeWorldTimeEvents before this world-time
MaxResultsintLimit result set
OrderByChronicleOrderNewest (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 panel
UiSystem.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 zone
var 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.