Skip to content

Memory palace

The hub the player teleports to via memory orbs. Holds a permanent home slot for every rune they've discovered, plus a per-rune definition. Orbs handle the in/out fade.

AMemoryPalace

Level-placed actor. One per palace level.

Components:

  • PalaceRoot — root scene component.

Auth fields:

  • PalaceSlots (TArray<ARuneSlot*>) — slot inventory. Designers either drop slots in via this array, or set bAutoCreateSlots to have the actor spawn them.
  • NumSlots (default 50) — auto-create count.
  • CircleRadius (default 1000), NumRings (default 3), RingSpacing (default 300), SlotHeightOffset (default 50) — auto-layout knobs.
  • SlotClass — what to spawn (typically AMemoryPalaceSlot).
  • SlotDefinitionWidgetClass — widget assigned to auto-generated slots.
  • RuneHeightAboveSlot (default 200) — vertical offset of the rune above the slot.
  • bAutoCreateSlots — toggle.

State:

  • PlayerKnowledge (UPlayerRuneKnowledge*) — handle to the save game.
  • SlotIndexToRuneMap — quick lookup, slot index to rune data.

API:

  • OnPlayerEnter(Player) — refresh slots, spawn newly discovered runes.
  • AssignNewRunesToSlots() — assign pending runes to next empty slots, persist to save.
  • RefreshAllSlots() — wipe and respawn all assigned runes.
  • FindNextEmptySlot() — first slot index without a rune.
  • CreateSlots() — auto-layout in concentric rings.
  • SpawnRune(RuneData) — spawn an ARune from a data asset.
  • GetPlayerKnowledge() — load or create the save game on demand.
  • ReturnRuneToSlot(RuneData) — used when the player borrows a palace rune and then takes a different one elsewhere; the original goes home.

AMemoryOrb

Teleporter actor. Two flavors gated by bIsInPalace:

  • World orb (bIsInPalace = false): teleports the player to the palace. Stores PalaceSpawnTransform for entry, captures ReturnTransform from the player at teleport time so the palace orb can send them back.
  • Palace orb (bIsInPalace = true): teleports the player back to the world. Looks up the most recent world orb at runtime via FindWorldOrb().

Components: OrbMesh (visible), implements IInteractableInterface.

Auth fields:

  • MemoryPalace — the palace this orb is paired with.
  • FadeDuration (default 1), FadeColor (default Black) — transition.
  • NormalMaterial / NearbyMaterial + SwapMaterialIndex — material swap when player approaches.
  • bShouldRotate + RotationSpeed — visual flair.

Interaction flow (OnInteractTeleportToPalace / TeleportToWorld):

  1. Player presses interact while overlapping.
  2. Orb begins fade-out via PlayFadeTransition(Player, true).
  3. UpdateFade ticks the alpha each frame.
  4. On fade complete, OnFadeComplete runs the actual teleport (set actor location/rotation), then fades back in.

The fade is camera-managed (alpha applied via ApplyFadeToCamera), not a UI overlay, so it works regardless of HUD state.

UPlayerRuneKnowledge (USaveGame)

The player's discovery and palace progress. Persists across sessions. This is the only actively-used save game class today.

State (all SaveGame flagged):

  • DiscoveredRunes (TSet<URuneDataAsset*>) — every rune the player has encountered.
  • RuneToSlotMap — permanent palace slot assignment.
  • bHasVisitedPalace — first-visit gate.
  • bHasUsedWorldOrb — gates palace orb interaction (don't let the player palace-out before they've palace-in'd from the world).
  • PendingPalaceRunes — discovered since last palace visit; not persisted (rebuilt on entry).

Static slot/index:

static const FString SaveSlotName;
static const int32 UserIndex;

API:

  • DiscoverRune(Rune) — adds to discovered set and pending set; returns true on first discovery (caller plays the discovery VFX).
  • IsRuneDiscovered(Rune), ShouldShowInPalace(Rune).
  • AssignRuneToSlot(Rune, SlotIndex) / GetSlotForRune(Rune).
  • ClearPendingRunes() — called after the palace has consumed them.
  • GetPendingRunes() — array view.
  • SaveKnowledge() / LoadKnowledge() (static) — disk I/O.
  • ResetKnowledge() — for new game / debug.

AMemoryPalace::GetPlayerKnowledge calls LoadKnowledge lazily and persists with SaveKnowledge after assignment changes.

How discovery flows

  1. Player interacts with a slot containing a never-seen rune.
  2. ARuneSlot (or the rune itself) calls DiscoverRune on the knowledge save game.
  3. Knowledge: adds to DiscoveredRunes, adds to PendingPalaceRunes, persists.
  4. Slot fires Rune::PlayDiscoveryVFX.
  5. Next time the player enters the palace, OnPlayerEnter triggers AssignNewRunesToSlots, which pulls pending runes, assigns each to FindNextEmptySlot, and persists.
  6. RefreshAllSlots populates every assigned slot with a runtime ARune.

Source files

  • Source/Rephrased_Demo/MemoryPalace.h
  • Source/Rephrased_Demo/MemoryOrb.h
  • Source/Rephrased_Demo/PlayerRuneKnowledge.h
  • Source/Rephrased_Demo/MemoryPalaceSlot.h (the per-slot subclass; documented in Rune actors and placement)

Known constraints

  • The palace is referenced by name from the TDD as "WIP for rework." The current implementation works but the visual layout (concentric rings) is a placeholder — designers will iterate on the topology before Gate 4.
  • PendingPalaceRunes is rebuilt at entry by diffing DiscoveredRunes against RuneToSlotMap. This works as long as the diff is cheap (set count is bounded by total rune count).
  • No multi-save-slot support today. SaveSlotName is a single string. New game wipes the existing save.
  • No autosave timer. Save fires explicitly on knowledge mutation.

Change history

  • 2026-05-08 — Gabriel Li — Added baseline change history section for weekly wiki maintenance.