FolioTier 3
time
Discrete-period clock + day counter — the time-passes machinery for sandbox VNs. Ships paired with Locations.
What Time does
Time is two coupled state machines — a discrete-period clock (morning / noon / evening / night) and a day counter — that the runtime advances on author-controlled boundaries. Games gate content on "what time of day" and "what day of the week" without manual scalar bookkeeping.
Like Stats, Time exists because Ren'Py has no
time primitive — every sandbox game builds its own scaffolding in
init python: blocks. Shipping it as an engine subsystem replaces
that scaffolding with declarative verbs and a typed slot in the
canonical project that saves carry.
Verbs
| Verb | Page |
|---|---|
| set time period=<id> day=<id> | /docs/folio/set-time |
| advance-time periods=<expr> | /docs/folio/advance-time |
Expression accessors
| Accessor | Returns |
|---|---|
| time.period | The current period identifier (or null when no clock state). |
| time.day | The current day identifier (or null when no clock state). |
Both round-trip through the bounded expression grammar — use them
inside any if, gate when:, hotspot when:, etc.
if time.period == "evening" -> events-evening else -> events-day
Default period / day enums
| Periods (default) | Days (default) |
|---|---|
| morning, noon, evening, night | monday, tuesday, wednesday, thursday, friday, saturday, sunday |
Imported projects can override either set via the time config schema;
the runtime gates set time writes against the declared lists
(silently drops unknown identifiers). Your project's actual enum lives
in canonicalProject.subsystems.time.periods / .days — the Studio's
Locations + Time rail shows them.
Trenchcoat split — linear-time vs. calendar-with-schedules
v1 ships the linear-time half completely:
- Linear-time (Eternum) — period + day count, no per-character
schedules. Authors use
at period <X>art variants andif time.period == "<X>"gates directly. Eternum has zero calendar machinery — period strings are textual narration in the dialogue prose, not runtime state. The runtime no-ops cleanly onadvance-timewheninitialPeriod/initialDayare null. - Calendar-with-schedules (AWAM, Lab Rats 2) — characters have
declared schedules; the runtime resolves "who is at this location
right now" from the clock + schedule table. Out of v1. The
schema reserves
time.schedules: nullfor the post-v1 expansion; authors who need character schedules in v1 fall through to manual lane via the migration report.
"No clock state" projects (Eternum case)
When initialPeriod / initialDay are null:
set time/advance-timeare silently no-ops at runtime.time.period/time.dayreturnnullfrom expression accessors.if time.period == "evening"resolves false (null is never equal to a string).
Authors of Eternum-shaped projects use period strings narratively
("It's getting late") rather than as state. The Time runtime exists
to support Locations art time-of-day
variants and to hold the slot for post-v1 calendar expansion.
Importer translation
Ren'Py's time machinery is pure scaffolding — bare variables with
helper functions in init python::
default current_period = "morning"
default current_day = "monday"
default day_index = 0
init python:
def advance_period():
global period_index, day_index
period_index = (period_index + 1) % 4
if period_index == 0:
day_index += 1
The pattern pass (Track B § B.3) detects this scaffolding shape
(variable triplet + modulo arithmetic on period index) and lowers it
to advance-time periods=1 calls. Conditions on
current_period == "<period>" lower to if time.period == "<period>".
Custom period names, non-standard rollover, hour-granularity counters land in the migration report's manual lane. AWAM-style per-character schedules flow there too in v1.
See also
set time— initialize the clockadvance-time— move the clock forwardlocations— paired subsystemif—time.period/time.dayin conditional routingstats— sister subsystem