FolioTier 3

locations

Navigable named places. Imported from Ren'Py screen blocks; author scripts navigate them with `goto` and pop with `return-to-map`.

What Locations does

A location is a named place with art, optional time-of-day variants, and optional clickable hotspots over the art. Together the locations in a project form a navigable world — the surface Tier 3+ Ren'Py games approximate by writing custom screen-language map screens.

Two facts to internalize before writing anything:

  1. Locations are declared by the importer, not by author scripts. When you upload a Ren'Py project, every location screen the importer recognizes lands as an entry in canonicalProject.subsystems.locations. Your scenes navigate between them via goto and return-to-map; they don't create locations.
  2. Hotspots are a sub-shape inside Locations, not a parallel subsystem. Schema slot: CanonicalLocation.hotspots. Per G6.5.

The Studio's Locations + Time rail (Script tab) lists every declared location and every goto <name> site in the open buffer — that's your authoring surface, not a hand-written location: block.

The two hotspot positioning shapes

The schema carries both forms because the corpus uses both. The audit doc has the full reasoning.

| Form | Source pattern | Hit-test | |---|---|---| | Alignment-anchored | Ren'Py imagebutton with xalign / yalign — Eternum's house style (88 sites) | Anchor at (canvasW × xalign, canvasH × yalign), dimension from the idle PNG's natural size. | | Pixel rectangle | Ren'Py imagemap hotspot (x, y, w, h) calls — STS / MilfyCity's house style | Direct screen-coordinate rectangle. |

Both forms carry width / height. The runtime always computes an absolute hit area; the form distinction matters at authoring time + for re-export, not at hit-test time.

Hover affordance — both shapes ship

| Shape | When it applies | |---|---| | Explicit hover swaphoverAssetId is set | Eternum's house style. The renderer swaps idlehover on pointer-enter. | | Default-glow filteridleAssetId is set, hoverAssetId is null | STS / MilfyCity's house style. The renderer applies a theme-skinnable filter on hover (no second PNG). |

G6.5 decided this. The importer collapses imagebutton idle X hover HoverImage(X) (same PNG, filtered) to hoverAssetId: null; different hover args land both ids.

Navigation verbs

| Verb | Page | |---|---| | goto <name> | /docs/folio/goto | | return-to-map | /docs/folio/return-to-map |

Hotspot action shapes (importer output)

Ren'Py imagebutton actions reduce to four shapes in the canonical hotspot's action chain:

| Ren'Py source | Canonical | |---|---| | action Jump('label') | { kind: "jump-label", targetSceneId: "label" } | | action [Play("sound", "x"), Jump('label')] | [{ play-sound }, { jump-label }] (source order) | | action ShowMenu('point') | Manual lane — sub-menu pattern out of v1 | | hovered [Play("sound", "x")] | hoverSoundAssetId set on the hotspot |

Importer translation — Eternum's shape (Tier 3 ship target)

screen hallways:
    imagebutton:
        idle "hallway1"
        hover "hallway1b"
        xalign 0.26
        yalign 0.38
        action Jump('corridorl')

Lowers to a CanonicalHotspot with:

  • position: { kind: "align", xalign: 0.26, yalign: 0.38, width, height }
  • idleAssetId, hoverAssetId resolved against canonicalProject.assets
  • actions: [{ kind: "jump-label", targetSceneId: "corridorl" }]

The screen-to-label binding (call screen <name> from a label body) becomes a CanonicalLocation keyed on the screen name.

See also

  • goto — navigate to a declared location
  • return-to-map — pop the location stack
  • time — paired subsystem; time.period gates and at period art variants
  • stats — sister subsystem; both ship as typed engine slots