V5 is one open world worn five ways — Urban Crime, Period Drama, Frontier, Monster Hunter, Sci-Fi — and two of its subsystems exist precisely to bind those cells back together rather than let them drift into five disconnected games. The creator suite is the in-editor tooling that lets a designer (or, through Workshop, a player) author a playable detective case — clues placed in a world, an interrogation tree, a publish package — without writing engine code, and have that case validated by the same rules the runtime will judge it under. The Mind Palace is the cross-cell deduction layer: a graph of evidence orbs and authored deduction threads, a volumetric "memory room" to manipulate them, and an accusation system that resolves a case into a branching outcome. It is V5's signature, the one screen where a clue picked up in the 1940s Period cell can be dragged against a clue from the Sci-Fi cell and — if the player has earned the Bureau XP to unlock it — snap into a cross-era deduction. The two systems are a matched pair: the creator suite authors the cases, the Mind Palace is where they are solved. This page is the deep companion to ../V5_ARCHITECTURE.md; the monolith's "Creator Suite Architecture" and "Mind Palace Deduction Architecture" sections carry the data-contract tables this expands on.
What ships, honestly#
The C++ logic, the JSON content catalogs, and the automation tests are real,
committed, and compiled; the 3-D art those systems point at is the
manifest-referenced surface that, per the V5 posture, is not checked in as
binary .uasset. Four honest layers:
- Real, built, and tested.
V5CaseAuthor,V5MindPalace, andV5DetectiveMindPalaceare genuine UE5 C++ modules that compile to committed Linux editor binaries (V5/ue/Binaries/Linux/libUnrealEditor-V5CaseAuthor.so,…-V5MindPalace.so,…-V5DetectiveMindPalace.so, built as theueagentuser). Each shipsIMPLEMENT_SIMPLE_AUTOMATION_TESTsuites that assert specific authored counts and computed verdicts — not truthiness. The Mind Palace deduction graph, the weak-edge derivation, the breadth-first hypothesis walk, the evidence-chain accusation gate, the Bureau-XP cross-era gate, the daily-puzzle rotation math, and the leaderboard scoring are all real domain-specific algorithms. - Authored content is JSON, validated on load. The 110 authored deduction
pairs and 15 accusation outcomes are committed data
(
V5/ue/Content/V5MindPalace/Data/), parsed and schema-checked at load, not hard-coded. The case-author templates and Mind-Palace mode counts are likewise committed manifests with aschemaVersiongate. - Honest fail-loud seams. Workshop publish and Mind-Palace cloud-sync build
real requests (a real
FHttpModulePOST for cloud-sync) but their backends are the seam: an unhealthy service returns503and queues offline, a missing JWT returns401, and the live round-trip test is gated onV5_ONLINE_LIVE=1. These refuse to fabricate a success they didn't get. - Art referenced, not committed. Preview worlds
(
/Game/V5/Editor/CaseAuthor/L_HomicideCasePreview), the 100 examinable 3-D evidence assets the Mind Palace mode validates the count of, and the MetaHuman interrogation faces are asset paths named by manifest. They are the UE-art surface V5 keeps out of git; the logic that consumes them is here, the binary art is not.
The creator suite: authoring inside the editor#
The monolith lists nine creator tools (Mission Editor, Heist Author, Case
Author, Contract Author, Ship Loadout, Bestiary, Cinematic Director, Replay
Editor, Workshop Publisher), each emitting "a typed data file (USTRUCT-based)
that the runtime loads." The committed, deeply-implemented one — and the one
that ties the suite to the Mind Palace — is Case Author, the V5CaseAuthor
module. Its Build.cs is the tell: it depends on V5Investigation,
V5Interrogation, and V5OnlineServices alongside Slate/SlateCore, so the
editor tool is built on the very runtime types a played case uses, not a
parallel authoring model.
A typed authoring model, not a blob#
V5CaseAuthorTypes.h defines the whole authoring surface as USTRUCTs. An
FV5CaseAuthorTemplate carries a CaseId, a BaseInterrogationSceneId, an
EV5Cell, a PreviewWorldPath, a WorkshopCategoryTag, and floor requirements
(RequiredClueCount = 4, RequiredInterrogationQuestionCount = 3). An
FV5CaseAuthorDraft is the editable document: a CaseId, an array of
FV5CaseAuthorCluePlacement (each wrapping a real
FV5InvestigationClueDefinition plus a world transform and interaction radius),
the FV5InterrogationSceneDefinitions, and an array of
FV5CaseAuthorInterrogationBranch mapping a source question to an
EV5InterrogationChoice, a required-evidence id, and success/failure
next-question ids. The FV5CaseAuthorCatalog ships three launch templates —
case.vice.homicide.001, case.vice.narcotics.001, case.vice.corruption.001
(V5CaseAuthorSystems.cpp:254) — the "Vice-Squad-style case authoring" the
monolith names.
Build-from-template wires real interrogation primitives#
BuildDraftFromTemplate (V5CaseAuthorSystems.cpp:309) is where the tool earns
trust. It loads the template's interrogation scene through the runtime's own
UV5_Interrogation_TellLibrary::FindScene, falling back to a fully-formed
FallbackScene if none is authored yet. It then synthesizes clue placements
from the scene's required-evidence ids and a rotating set of extra clues
(scene_photo, timeline_note, witness_pin, lab_report) until the
template's RequiredClueCount is met, each clue stamped with four
FV5InvestigationDetailSpots (powder residue, maker mark, transfer stain,
hidden note). Finally BuildBranches walks the scene's questions and, for each
one, derives the correct authored choice from the question's truth-state:
CorrectChoiceForQuestion maps Truthful→Truth, Withholding→Doubt,
Lying→Lie (:63). The draft a designer starts from is therefore already a
self-consistent, runtime-shaped case.
Validation is the contract, and it's domain-specific#
ValidateDraft (V5CaseAuthorSystems.cpp:324) is the heart of the tool, and it
is not a shape check. It runs three graded sub-passes that set
bCluePlacementValid / bInterrogationValid / bBranchValid independently:
- Clues — at least four placements, ids unique, each clue belonging to the active case, each carrying a scene id, at least three detail spots, and a positive interaction radius.
- Interrogation — every scene belongs to the case; at least three questions;
and the load-bearing rule — a
Lyingquestion must be answerable with placed evidence, checked by calling the runtime'sUV5_Interrogation_EvidenceBackedLie::CanChallengeWithLie(Question, EvidenceInventory)(:357-360) against an inventory built from the draft's own clue placements. A lie the player can't catch with a planted clue fails authoring. - Branches — every branch maps to a source question that exists, and that
branch's
(question, expected-choice, has-evidence)triple mustResolveInputtobCorrectthroughUV5_Interrogation_TruthDoubtLie::ResolveInput(:376); every question needs a branch and every branch needs a success path.
Because both checks call the same V5Interrogation resolvers the runtime
uses, a case that passes the editor is guaranteed solvable under the live rules.
That is the difference between authoring tooling and a CRUD form: the validator
is the game's own logic, run at edit time.
Publish: a real request with a fail-loud seam#
BuildWorkshopPublishPlan (V5CaseAuthorSystems.cpp:454) assembles an
FV5OnlineServiceRequest via UV5_Online_WorkshopClient::BuildPublishRequest,
targets /v5/workshop/case-author/publish, and serializes a payload carrying
the clue/scene/branch counts, the valid flag, and
moderationState: "pending". bReadyToPublish is true only when the draft is
valid and an account id and JWT are present. PublishToWorkshop (:477)
hands the request to UV5_Online_ServiceCatalog::ExecuteRequest, whose
automation test (V5CaseAuthorTests.cpp:141) pins the honest seam: 202 on a
healthy service, 503 + bQueuedOffline on an outage, 401 when the JWT is
empty. The Workshop service is elsewhere; the editor's job is a correct, gated
request and it does exactly that.
The visible tool is SV5CaseAuthorPanel (SV5CaseAuthorPanel.cpp), a real
Slate widget: an SBorder over a four-column SHorizontalBox (Clues /
Interrogation / Branches / Validation+Workshop) inside SScrollBoxes, with
Validate, Preview, and Publish SButtons whose IsEnabled is wired to
bSupportsCluePlacement && bSupportsInterrogationTree and
WorkshopPlan.bReadyToPublish. The committed case_author_manifest.json
mirrors the module's content counts and system flags under schemaVersion: 1.
The Mind Palace: a cross-cell deduction graph#
The Mind Palace is "a graph database + a UI shell," and conceptually a
side-car to all five cells: each cell's investigation gameplay pushes
evidence into it through one interface. IV5_Investigation_MindPalacePush
(V5InvestigationMindPalacePush.h) declares a single
EmitEvidenceNodeEvent(FV5InvestigationEvidenceNodeEvent); the graph implements
it (V5MindPalaceGraph.cpp:21), translating an in-cell evidence event into an
FV5MindPalaceEvidenceNode tagged to the MindPalace cell. That is how a clue
examined in any cell becomes an orb in the shared room.
The data model#
V5MindPalaceTypes.h defines the graph. An FV5MindPalaceEvidenceNode is the
monolith's V5_Evidence_Node — NodeId, CaseId, source cell, location,
TimestampInFiction, Tags, Description, an Image soft path, examined
details, and a bFalseLead flag. An FV5MindPalaceDeductionEdge is the
V5_Deduction_Edge — a from/to node pair with their cells, DeductionText,
a Confidence float, a Kind (Authored or Weak), bCrossEra, a
RequiredBureauTier, and an UnlockFlag. An FV5MindPalaceAccusationOutcome
(V5_Accusation_Outcome) carries the EvidenceChain, the RequiredEdgeIds it
demands, a Rating (Brilliant/Good/Doubtful/Wrong) and an
OutcomeBranch (TruthRevealed/PlausibleConviction/PoliticalCoverup/
Unproven). The FV5MindPalaceState is the V5_MindPalace_State: nodes,
edges, accusations, and unlock flags.
The deduction mechanic is authored-first with a weak fallback#
AttemptDeduction(NodeA, NodeB, BureauLedger) (V5MindPalaceGraph.cpp:78) is
the "drag two orbs onto the pedestal" action, and its logic is specific. After
rejecting same-node or non-existent pairs, it looks up an authored edge for
the unordered pair via FindAuthoredEdge. If none exists it calls
BuildWeakEdge (:271), which only succeeds when the two nodes share a
tag: it mints a weak.<a>.<b> edge at Confidence 0.35, Kind = Weak,
marked bCrossEra when the cells differ and given RequiredBureauTier 5 +
UnlockFlag MindPalace.CrossEraPairs in that case. So a pairing is either a
known authored insight or an honest "weak thematic connection… needs stronger
corroboration" — never a fabricated certainty. The candidate then passes through
the cross-era gate before being committed to State.Edges; the result reports
bSuccess, bGateBlocked, a FailureReason, and the resolved Edge.
The gate itself is UV5_MindPalace_CrossEraGate::CanUnlockDeduction
(V5MindPalaceCrossEraGate.cpp): a non-cross-era edge is always allowed; a
cross-era edge requires BureauLedger.CurrentTier >= max(1, RequiredBureauTier)
or that the ledger's Unlocks already contains the edge's UnlockFlag.
This is the spine connecting the Mind Palace to progression — the cross-cell
"aha" moments are earned through Bureau XP, the same ledger detailed in the
Hunter, Period & Bureau spine.
Hypothesis chains and the accusation gate#
BuildHypothesisChain(start, maxDepth) (V5MindPalaceGraph.cpp:112) is a real
breadth-first traversal over the committed edges: a frontier expands outward
(depth clamped to 1–12), collecting reachable node and edge ids and accumulating
an AverageConfidence. It is the "UI helper for visualizing" a line of
reasoning, and the test asserts an authored chain carries
AverageConfidence >= 0.80 (V5MindPalaceTests.cpp:99).
MakeAccusation(case, accused, chain) (:165) defaults to the worst outcome —
Wrong / Unproven — then searches the authored catalog for a matching
(case, accused) outcome. The match only "sticks" with its authored Rating
and OutcomeBranch if the player's EvidenceChain contains every
RequiredEdgeId; a chain missing a required link collapses back to
Wrong/Unproven with "lacked the required evidence chain." This is a real
proof-of-work gate, not a coin flip: the end-to-end test
(V5MindPalaceTests.cpp:161) completes each of the 15 authored outcomes'
required deductions and asserts the accusation resolves the expected branch,
covering three distinct branches across the arc.
The volumetric memory room#
UV5_MindPalace_View_Volumetric::BuildViewState
(V5MindPalaceViewVolumetric.cpp:33) renders the monolith's "circular memory
room with evidence orbs in concentric rings by cell of origin." It first filters
the node set through the filter rail, then places each surviving node on a ring
whose radius is a function of its cell (RingForCell = 220 + cell·70), at an
angle evenly distributed around the circle, lifted in z by index. The selected
orb scales up (1.35) and glows; each orb takes a per-cell accent color
(ColorForCell). Deduction threads are drawn only between two visible orbs;
an authored thread's intensity tracks its confidence while cross-era threads are
gold. UV5_MindPalace_FilterRail::FilterNodes (V5MindPalaceFilterRail.cpp:19)
is the left rail: filter by cell, by case, by an in-fiction timestamp range, and
by required tags (all must be present). The test drives this end-to-end —
filtering to one node by cell+tag, then building a view with "two evidence orbs"
and "one thread."
Authored content is data, validated on load#
The 110 deduction pairs and 15 accusation outcomes are not hard-coded.
UV5_MindPalace_Catalog::LoadDeductionPairs (V5MindPalaceCatalog.cpp:121)
reads V5/ue/Content/V5MindPalace/Data/deduction_pairs.json and validates it: a
schemaVersion of 1, required string/number fields, no duplicate edge ids, no
self-loops, positive confidence. The JSON is a compact generator spec —
pairGroups whose counts sum to exactly 110 (one cross-era group of 30
spanning all five cells at requiredBureauTier 5, plus five per-cell groups of
16 = 80) — matching the test's Deductions.Num() == 110, CrossEraCount == 30,
PerCellCount == 80 (V5MindPalaceTests.cpp:57). accusation_outcomes.json
holds 15 outcomes — five anchor cases × three authored branches, an even
PlausibleConviction / PoliticalCoverup / TruthRevealed split.
Cloud sync and the companion app#
V5MindPalaceCloudSyncHttp::BuildHttpRequest (exercised at
V5MindPalaceTests.cpp:248) is a genuine FHttpModule POST to
@v5/service-mindpalace-cloud-sync at /v5/mindpalace-cloud-sync/graph-diff on
port :4220, a Bearer JWT header, application/json, and a body carrying a
CRDT-style version-vector graph diff; ParseResult maps 2xx→success,
503→failure. A second, latent test (V5_ONLINE_LIVE=1) does a real round-trip
against the running service and asserts the response acknowledges the merged
diff. The companion-app path (V5MindPalaceCompanionAppRead) builds a read-only
snapshot for the AR overlay and an editable snapshot exposing add-clue /
annotate-clue, queuing append-only edit drafts for cloud-sync — the Year-1
Companion-App Mind Palace Editor.
The Detective Mind Palace mode: dailies, crossovers, scoring#
V5DetectiveMindPalace is the runtime mode plugin built on the graph. Its
ValidateCatalog (V5DetectiveMindPalaceSystems.cpp:589) enforces the shape of
the main arc — ten one-hour beats totalling ten hours, covering all 30 cross-era
deductions, 80 per-cell deductions, and 100 examinable 3-D evidence assets
(count validated; the assets themselves are the referenced art surface). On top
sit two live-service systems:
- Daily puzzles.
BuildDailyPuzzleForDate(:541) is deterministic: it takes the floor of days since the rotation start (2027-06-07Z), wraps it modulo 365 (with a correct negative-safe((d % n) + n) % n), and indexes the 365 authored puzzles — so day 0 → puzzle 001, day 1 → 002, day 365 wraps back to 001, exactly as the test pins (V5DetectiveMindPalaceTests.cpp:115).EvaluateDailyPuzzleSolve(:550) computes a leaderboard score —50000 + tier·1500 + timeBonus − hintPenalty, floored at 1 — but only when the solve is clean:bSolved && bAntiCheatClean && positive time. A dirty solve scores zero and is leaderboard-ineligible. Scores submit through the shared leaderboards service. - Crossover pack. A Year-1 "Black Archive" six-hour, six-beat arc adding 12 new cross-era deductions, each validated as authored, cross-era, Bureau-gated, and referenced by exactly the beats that need it.
ScoreConnection (:705) grades a single thread: Confidence·100 clamped to
0–100, Strong only when the edge is authored and ≥70 and the cross-era
gate is unlocked, and bCanSupportAccusation follows from Strong + unlocked.
The five automation tests (Catalog, DailyPuzzleRotation,
Year1CrossoverPackExpansion, ConnectionScoring,
CrossEraUnlockMultiAccusation) assert these computed values directly.
Edge cases & connections#
- A pairing with no authored edge and no shared tag yields "No meaningful
connection found" (
V5MindPalaceGraph.cpp:91) — the system refuses to invent a deduction. Shared-tag pairings produce only a low-confidence weak edge, never a confident one. - A cross-era deduction below the Bureau tier returns
bGateBlockedwith the candidate edge attached but not committed to state — the gate fails loud and leaves the graph unchanged until the player earns the unlock. - An accusation with an incomplete chain can never reach an authored
conviction branch; the missing-link path is the explicit
Wrong/Unprovencollapse, so the outcome is always backed by the evidence the player actually assembled. - Authoring a lie with no catchable evidence fails
ValidateDraftvia the runtime's evidence-backed-lie resolver — the creator suite will not let a designer ship an unsolvable interrogation. - Offline / unhealthy backends surface as
503 + queued-offline(Workshop publish, cloud-sync) or401(missing JWT); the live cloud-sync round-trip is opt-in behindV5_ONLINE_LIVE, so the default test run never depends on a service being up. - Where the cases get played and judged. The interrogation rig the Case Author validates against — MotionScan tells, the Truth/Doubt/Lie call, scoring — and the Heist Author that shares the Mission Editor are detailed in Interrogation, Dialogue & Heist.
- Platform substrate. The shared online services these systems target (Workshop, leaderboards, the Mind-Palace cloud-sync domain) and the Bureau-XP ledger they gate against are catalogued in Oshun Domain Libraries.
Together the creator suite and the Mind Palace are V5's answer to the open-world anthology problem: a tool that authors a detective case under the runtime's own rules, and a deduction layer that lets evidence cross cell boundaries — real in logic, honest about the art they reach for.