ReadonlyappsThe apps namespace tree (sohl.apps.foundry.CalendarSettingsMenu, …). Bound at init.
ReadonlycoreThe core namespace tree (sohl.core.logic.SohlSystem, …). Bound at init.
ReadonlydocumentThe document namespace tree — sohl.document.effect.foundry.SohlActiveEffect,
etc. Bound to the barrel namespace at init (in sohl.ts); the type is
declared here without a runtime import so the binding stays cycle-free.
ReadonlyentityThe sohl.entity surface — the constructable entity-class registry (the
outside-SoHL surface for macros and variant modules to new, subclass, or
override via sohl.entity.X / sohl.entity.register(...); each class is a
getter, so a register() override is picked up at every construction
site) merged with the entity sub-namespaces for addressing
(sohl.entity.modifier.ValueModifier, …). Bound at init in sohl.ts; the
type is declared via typeof import(...) so the binding stays cycle-free.
ReadonlyeventsIn-memory trigger/event dispatcher (sohl.events).
Readonlyi18nLocalization helper (sohl.i18n).
ReadonlylogSystem logger (sohl.log).
ReadonlyrandomThe process-wide pseudo-random generator (sohl.random) — the shared,
ambient sohl.entity.random.Rng stream backing
sohl.entity.roll.SimpleRoll, hit-location selection, and the
rand() expression helper when no generator is injected. Seeded from
entropy at construction; present from that point on (its own readiness
signal). It is one shared stream — safe for atomic synchronous draws but
not isolated; a flow needing isolation injects its own createRng
instance. e2e re-seeds it through the window for reproducibility
(win.sohl.random.seed(...)).
Never seed this with a fixed value in a play path — predictable dice ruin play, and a shared deterministic stream desyncs across clients anyway. Fixed seeds are strictly a test/e2e affordance.
ReadonlyutilsThe utils namespace (sohl.utils) — the Foundry-free utility superset:
the sohl.utils.romanize-style helpers and the constants (ACTOR_KIND, …)
re-exported at its top level, plus the nested collection sub-namespace
(sohl.utils.collection.SohlMap). Bound to the barrel namespace at init
(in sohl.ts); the type is declared here without a runtime import so the
binding stays cycle-free. The curated constants alias
(sohl.constants) is kept alongside it.
Static ReadonlyconstantsThe constants module (static access).
StaticreadySet true once the system has finished its ready-hook setup.
The actor-kind → base Logic-class map (sohl.actorLogicClasses). Exposes
the SoHL base classes so a variant module can subclass one before
registering the override. Reads reflect any registered override.
The logic instance of every world actor — a direct entry point into the
actor logic layer (sohl.actorLogics), instead of going through
game.actors and reading each .logic.
One SohlActorLogic per world actor.
The currently active world calendar. May be a SohlCalendarData or any CalendarData subclass installed by another module — code that consumes this must use only the base CalendarData API.
The SoHL system configuration (sohl.CONFIG) — the document, sheet,
DataModel, modifier, and result registries merged into Foundry's CONFIG
at init. See SOHLCONFIG.
The constants module (sohl.constants).
The sohl.document.combatant.logic.SohlCombatantLogic of every combatant in the active combat — a
direct entry point into the combatant logic layer
(sohl.currentCombatCombatantLogics). Empty when no combat is active.
One sohl.document.combatant.logic.SohlCombatantLogic per combatant in game.combat.
The item-kind → base Logic-class map (sohl.itemLogicClasses). Exposes the
SoHL base classes for subclassing. Reads reflect any registered override.
The logic instance of every world (non-embedded) item — a direct entry
point into the item logic layer (sohl.itemLogics), instead of going
through game.items and reading each .logic.
One SohlItemLogic per world item.
StaticcalendarsAll registered calendars.
Attach a Foundry Macro to doc as a SCRIPT action —
sohl.addScriptAction. The clean programmatic sibling of the sheet's
"create action" control and of sohl.schedule / sohl.worldHost
(issue #588, deliverable §7): a module or macro hands a minimal spec
({ name, executor } plus optional overrides) and gets a persisted,
runnable action back — without knowing the full actionDefs shape.
spec.name becomes both the action's shortcode (what
schedule and the [Perform] reminder address) and its default
title; spec.executor is a Foundry Macro UUID (a reference, never
inline code). Re-attaching the same name replaces the entry rather than
duplicating it, so an init hook can run on every reload safely.
Works on any document that carries system.actionDefs — an actor
(including the _sohlworld host) or an item. Because SCRIPT entries
are GM-authored, this is a no-op returning undefined for a non-GM (the
same gate SohlActor/SohlItem._preUpdate enforce at the persist
boundary); the caller must also be an owner of doc (a document write).
The document to attach the action to.
The Script Action spec (name + executor required).
The persisted action def, or undefined when the current user is
not a GM.
Register an actor Logic class for a kind, overriding the SoHL default.
Call from a module's init/setup hook — before the first .logic for
that kind is constructed. No construction-site changes are needed: the
resolution path (SohlDataModel.create) reads this map, so every document
of that kind built afterward uses the registered class.
The actor kind whose Logic class to override.
The replacement Logic class (a SohlActorLogic subclass).
Register an item Logic class for a kind, overriding the SoHL default. See registerActorLogic for the calling contract.
The item kind whose Logic class to override.
The replacement Logic class (a SohlItemLogic subclass).
Schedule a recurring action on a document (issue #588) — sohl.schedule.
Persists the schedule to the document's system.scheduledActions (the
durable record, anchored at the current world time) and arms the event
queue (the live entry), so when it comes due the queue offers it as a
[Perform] reminder. Re-call it (e.g. from the action after it performs) to
reschedule the next occurrence.
Works on any document whose data model extends the base SohlDataModel
and so carries a system.scheduledActions field — an actor (including
the _sohlworld host) or an item (a wound, an affliction). Scenes and
active effects extend TypeDataModel directly and cannot host a schedule.
Must run as an owner of doc (a document write). Both halves derive the
fire time from the same anchor + interval, so they cannot drift.
A schedule may be scene-bound (issue #590): pass sceneUuid and the
[Perform] reminder is offered only while that scene is the active scene —
a bandit check at a hideout does not fire while the party is elsewhere, and
a check that came due while away surfaces when they return. Omit sceneUuid
(or pass undefined) for a world-wide schedule that fires regardless of
the active scene.
The document to schedule on (its logic hosts actionName).
The action shortcode to run when due.
Seconds until the next fire.
Optionalpayload: Record<string, unknown>Opaque scope handed to the action on [Perform].
OptionalsceneUuid: stringThe scene the schedule is bound to, or undefined for a
world-wide schedule.
OptionaltriggerName: stringThe lifecycle trigger to bind to (issue #622). Omitted
or "updateWorldTime" ⇒ a time-based schedule fired at now + interval
(the default); any other value ("turnEnd", "combatStart", …) ⇒ an
event-driven schedule (interval is then unused).
Optionalpredicate: stringOptional sohl.entity.expr.SafeExpression source
gating an event-driven schedule (issue #569; subscriberUuid is bound to
doc). Ignored for a time schedule.
Optionalanchor: numberWorld time the recurrence is measured from, defaulting to
now. A recurring *Test passes the due time of the occurrence it just
performed, not the moment the player pressed the button, so a check
answered late does not push the whole cadence later (issue #1181). The
resulting fire time may therefore already be in the past, in which case
the schedule is armed due and its *Check fires at the next dispatch.
A promise that resolves once the schedule is persisted and armed.
Remove a recurring schedule for actionName on doc — sohl.unschedule.
Clears the persisted system.scheduledActions entry and unsubscribes it
from the event queue.
The document to unschedule on.
The schedule to remove.
A promise that resolves once the schedule is removed.
Find (or, for a GM, create) the singleton world host actor —
sohl.worldHost(). It is the document world-scoped scheduled actions and
events hang off of (issue #588): an Actor, so it already has the execution
surface (onChatCardButton + an actions collection) that a scheduled
action's [Perform] needs.
Identified by the reserved shortcode WORLD_HOST_SHORTCODE. Created
with ownership default NONE, so only the GM ever sees it. If it has been
deleted, a GM call recreates it (its stored schedule is lost and must be
re-registered). A non-GM who cannot see it gets undefined.
The world-host actor, or undefined (non-GM, not visible).
StaticapplyStaticgetGet a registered calendar by ID.
The identifier of the calendar to retrieve.
The matching calendar registration, or undefined if none.
StaticgetReturn the singleton instance, creating it on first call.
The shared SohlSystem instance.
StaticregisterRegister a calendar configuration. Overwrites any existing registration with the same ID.
The unique identifier for the calendar.
The calendar registration to store.
Staticunregister
The central runtime object for Song of Heroic Lands — and what the global
sohlvariable points at.A single
SohlSysteminstance is created during Foundry'sinithook (via getInstance) and installed asglobalThis.sohl, so it is reachable frominitonward — beforeready(SohlSystem.ready flips totrueonceready-hook setup finishes). Macros, modules, and Script Actions reach SoHL's system-wide services through it. This is the canonical reference for thatsohlsurface; the members below are the full list.For working with one specific actor or item, prefer that document's
.logic(the "document surface") over walking these collections — see the The SoHL API how-to guide for the two-surface model. Whatsohloffers, by category:sohl.utils.romanize()) and constants (ACTOR_KIND,ITEM_KIND, …).CONFIGat init) and the active calendar.