Skip to content

Quest graph editor and runtime system (replaces the FTUE tutorial flow) - #571

Open
Shombith03 wants to merge 70 commits into
bleeding-edgefrom
claude/ftue-editor-tool-69acq5
Open

Quest graph editor and runtime system (replaces the FTUE tutorial flow)#571
Shombith03 wants to merge 70 commits into
bleeding-edgefrom
claude/ftue-editor-tool-69acq5

Conversation

@Shombith03

@Shombith03 Shombith03 commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

Replaces the flat TutorialSequenceSet FTUE flow with a quest system: a quest is an ordered list of phase graphs, and each phase is a node graph of ScriptableObject nodes connected by named ports. Adds a three-panel graph editor, 22 node types across 7 categories, cloud-persisted progress, and retires both the tutorial-era code and the previous quest/user-journey systems.

Naming: the types were renamed FTUE*Quest* during this branch's life, and this description has been brought in line with the tree. The code still lives under Assets/FTUE/, but there is no FTUEGraphSO / FTUENodeSO / FTUEGraphRunner — search for Quest… instead.

Scope: 268 files — 134 added, 77 deleted, 38 modified, 19 renamed (+15,798 / −2,585). 174 are under Assets/FTUE/.

Editor tooling — Assets/FTUE/Editor/

Tool Role
QuestGraphEditorWindow Three-panel IMGUI editor: quest/phase list, draggable node canvas with edge drawing, typed inspector + validation
QuestGraphLayout Canonical canvas arrangement: flow reads left→right along a row, and a new row starts at every context switch between app shell (menus, arcade, profile) and gameplay (freestyle, a launched match) — boundaries come from QuestNodeSO.Venue, which is what QuestVenue exists for
QuestDefaultContentBuilder Generates the canonical quest content
QuestRunnerSetup Auto-wires QuestGraphRunner from the open scene and project assets
QuestPhase0UIWirer One-click wiring of the hand-built Phase 0 UI in Menu_Main: InGameInstructionSetQuestInstructionView as keyed panels in flight-school order; DialogueSetUIQuestDialoguePanelView, plugged into DialogueViewResolver's MainMenu override slot

All five are #if !LINUX_BUILD; runtime code is platform-agnostic.

Core graph — Assets/FTUE/Scripts/Graph/

  • QuestSO — the quest: questId (stable persistence/analytics key), questEnabled master switch, designerNotes, and an ordered List<QuestPhaseGraphSO> phases. Index 0 runs first; a Phase End node advances.
  • QuestPhaseGraphSO — one phase: graphId, phaseName, phaseEnabled, entryNode, and nodes stored as sub-assets, plus editor-only canvas scroll/zoom.
  • QuestNodeSO — polymorphic base; carries QuestNodeCategory and QuestVenue, typed fields, an Execute() coroutine, and Validate().
  • QuestEdge — directed connection from a named output port to a target node by stable ID, not index.
  • QuestPorts — canonical port names. There are exactly two: next and onTimeout.
  • QuestRuntimeContext (+ QuestButtonEntry) — live scene systems and SOAP assets handed to every node.

Node types (22)

Category Nodes
Gate (9) WaitForInput, WaitForSkim, WaitForDrift, WaitForIntensity, WaitForGameLaunch, WaitForGamePlayed, WaitForUserAction, WaitForModeUnlocked, ExitFreestyle
Gameplay (6) Navigate, LockModes, LockNavigation, EnterFreestyle, SetArcadeConstraints, SetButtonInteractable
Presentation (2) ShowInstruction, Dialogue
Terminal (2) PhaseEnd, End
Flow (1) Wait
Guidance (1) HighlightCTA
Progression (1) UnlockMode

(All are Quest…Node; the prefix is dropped above for width.)

Runtime — Assets/FTUE/Scripts/Graph/Runtime/

QuestGraphRunner — waits for the menu autopilot vessel via GameData.OnClientReady (so force-enter-freestyle and input steps have a live vessel), gates on QuestProgressStore.IsCompleted, resumes at the saved phase + node (every completed node is persisted to UGS), then executes from the entry node and follows the edge for the port each node advances on. Honours questEnabled / phaseEnabled master switches and carries debugForceRun / debugPhaseOverride test hooks. Alongside it: QuestProgressStore, QuestArcadeConstraints, QuestPlayRecorder.

UIQuestInstructionView (+ InstructionPanel), QuestDialoguePanelView, QuestRewardRevealView, QuestToastNotifier.

Cloud persistence

QuestProgressCloudData + QuestProgressRepository, keyed on UGSKeys.QuestGraph = "QUEST_GRAPH_PROGRESS", exposed as UGSDataService.QuestGraph (reader) and QuestGraphRepo.

Cloud is the source of truth, synced across devices, with a PlayerPrefs mirror so first-run gating works offline; node completions are debounce-saved to UGS. ProgressionBackendGate.CloudEnabled turns the cloud half off — the store then runs PlayerPrefs-only and every cloud write is a no-op, which is the local-only testing path.

Authored content

MainQuest.asset plus MainQuest_Phase0MainQuest_Phase5.

Progression & unlocks

New SO_UnlockData, SO_UnlockList, and ProgressionBackendGate (the switch that decides whether progression talks to the backend at all); modified GameModeProgressionService, SO_ProgressionConfig, VesselUnlockSystem, CallToActionSystem/CallToActionTarget, UserActionTrigger. ProgressionConfig.asset drops mode 36 from alwaysUnlockedModes and raises defaultMaxIntensity to 3.

What this retires

25 tutorial-era files (TutorialSequenceSet, TutorialStep/Section/Phase/Payload/StepType, TutorialFlowController, FTUEIntroAnimator + adapters, the four step handlers, seven ITutorial*/IFlowController/IAnimator/IOutroHandler interfaces, TutorialUIView, InGameTutorialFlowView) and the previous quest stack: SO_GameModeQuestData, SO_GameModeQuestList, SO_QuestChain, Quest.cs, QuestSystem.cs, UserJourneySystem.cs.

Documentation

Adds Assets/FTUE/QUEST_GRAPH_TOOL.md and QUEST_GRAPH_EDITOR_TOOL.md, Docs/QUEST_TRACK_AND_BREADCRUMB.md, Docs/QuestMap/QUEST_MAP.html; updates Docs/Analytics/DATA_INVENTORY.md and Docs/MENU_PROGRESSION_AND_IAP.md.

Also touched

R_VesselActionHandler gains SetInputSuppressed/ClearSuppressedInputs — an untimed on/off gate (distinct from the timed MuteInput) so the flight school can disable action buttons while only sticks and triggers are being taught. Plus ScreenSwitcher, GameCanvas, Scoreboard, ArcadeGameConfigureModal, QuestTrackView, QuestItemCard, ArcadeExploreView, HangarVesselDetailView, DialogueManager, DialogueViewResolver, SceneLoader, EndGameSequencer, TurnMonitorController, Menu_Main.unity, and additive enum members in CallToActionTargetType / UserActionType.

Verification status

  • Verified in the Unity editor (2026-08-27): the Quest graph assets open and read correctly.
  • CI does not compile this project. On the current head the unity job is skipped; only resolve and conditional-compilation run (both pass). Do not read a green check as a successful build.
  • Not exercised, and a human must run these:
    • A full first-run playthrough of MainQuest phases 0–5. The runner gates on stored progress, so a profile that has already completed the quest silently skips everything and the run looks like a pass — use a fresh profile, or tick debugForceRun on QuestGraphRunner (and debugPhaseOverride to jump to one phase).
    • The cloud round-trip under QUEST_GRAPH_PROGRESS — write, sign out, sign back in, confirm resume lands on the right phase. Offline first-run relies on the PlayerPrefs mirror; if mirror and cloud disagree the symptom is a quest that restarts or skips rather than an error. Note IsCompleted short-circuits on the local mirror before consulting cloud, so a stale local flag wins.
    • Removal of the old quest stack (QuestSystem, UserJourneySystem, SO_QuestChain) against a built player, not just the editor. These were referenced from prefabs and Menu_Main; a missed reference surfaces as a null script on a scene object, which the editor tolerates more quietly than a player does.
    • SetInputSuppressed release: suppression has no timer and the caller owns the release, so a phase that exits early while a button is suppressed leaves that ability dead for the session.

Base is synced to bleeding-edge as of df80aab1 (PRs #762#811).

🤖 Generated with Claude Code

https://claude.ai/code/session_01MEapXRwbzTHRHeFukGugdt

claude and others added 30 commits June 30, 2026 18:36
…e breadcrumb

Recreate the XP/Quest progression system per the Quest Track + Breadcrumb design.
Quest completion is now the only progression currency and the progression spine is
the single driver of the Call-to-Action breadcrumb.

C1 — Remove XP entirely:
- Delete ParticipationXpAwarder, XPTrackView, SO_XPTrackData, SO_XPTrackReward
  (+ assets) and the ParticipationXpAwarder component in Bootstrap.unity.
- Strip GetXP/AddXP/OnXPChanged from PlayerDataService; drop participationXpPerGame
  from SO_ProgressionConfig. The cloud PlayerProfileData.xp field is left dormant.

Retire the old quest stack:
- Delete Quest, QuestSystem, UserJourneySystem, SO_QuestChain (+ assets) and remove
  the SO_QuestChain field from SO_TrainingGame.

Generalize the unlock model:
- Rename SO_GameModeQuestData -> SO_UnlockData and SO_GameModeQuestList -> SO_UnlockList
  (script GUIDs + field names preserved so authored assets keep their data). Add a
  FeatureKind enum (GameMode/Vessel/IntensityTier/Screen/Captain/Episode/UIElement),
  FeatureRef, UnlockKey, and the breadcrumb fields CallToActionTargetID /
  CompletionUserAction / DependencyTargetIDs + BuildCallToAction().

KEY WIRE — progression drives the breadcrumb (C2):
- GameModeProgressionService funnels every change through RaiseProgressionChanged,
  which recomputes the active frontier and lights its authored CallToAction,
  retracting the previous one (single guidance channel).
- CallToActionSystem gains RemoveCallToAction, guards double-activation, and keeps
  dismissed callbacks so a target can re-light.

C3 — continuity law:
- CallToActionTarget blooms (scale + fade in) on activate and withers on dismiss via
  DOTween instead of instant SetActive.

Author breadcrumb data on the 6 unlock assets (the 4 game modes point at their
PlayGame* card via ArcadeMenu; the Vessel Hangar Screen node points at HangarMenu).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FpNEL7iHc7bCKFTFvV3Byc
…breadcrumb design

Review follow-up.

- Fix IsVesselHangarUnlocked: test the persistent done signal (IsUnlockObjectiveDone —
  a completed quest stays at max intensity) instead of the transient CompletedQuests set,
  which ClaimQuestAndUnlockNext empties on claim. The old conjunction was unsatisfiable, so
  the hangar (and its new breadcrumb, and the hangar feature gate) never unlocked.
- Document the intentional CompletionUserAction=None on game-mode frontier breadcrumbs:
  multi-play quests stay lit until the objective is met (progression-owned), not dismissed
  after a single play via fragile event ordering.
- Add Docs/QUEST_TRACK_AND_BREADCRUMB.md (architecture, content chain, in-editor wiring
  checklist, v1 boundaries); update MENU_PROGRESSION_AND_IAP.md and Analytics/DATA_INVENTORY.md
  to drop the removed XP track and rename SO_GameModeQuestData/List -> SO_UnlockData/List.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FpNEL7iHc7bCKFTFvV3Byc
Drop GameModeQuest_WildlifeBlitz from SO_UnlockList and delete the asset; the chain
is now CrystalCapture -> HexRace -> Joust -> PartyGame(placeholder) -> VesselHangar.
Update the doc chain tables to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FpNEL7iHc7bCKFTFvV3Byc
Set defaultMaxIntensity 2 -> 3 (config asset + SO default). Intensities 1, 2 and 3
are now playable the moment a mode unlocks; completing the intensity-3 goal unlocks
intensity 4 and finishes the quest. The intensity-2->3 branch in RecordIntensityPlay
is now inert (never fires while the floor is 3). Docs updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FpNEL7iHc7bCKFTFvV3Byc
Add Assets/_Graphics/UI/CTA_Glow_Outline_Cyan.png (the breadcrumb ActiveIndicator —
9-slice neon border, spriteBorder 88) and Card_Frame_Cyan.png (sci-fi frame for the
game-mode card, spriteBorder 74). Both import as Sprite (Single) with 9-slice borders
preset via their .meta, so they stretch to any element size.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FpNEL7iHc7bCKFTFvV3Byc
- Replace the cyan CTA highlight with CTA_Glow_Outline_Green.png (neon green, 9-slice
  rectangular outline glow, spriteBorder 66).
- CallToActionTarget now runs a continuous glow pulse while active (alpha yoyo, or a
  subtle scale yoyo when the ActiveIndicator has no CanvasGroup), tunable + toggleable,
  on top of the existing bloom-in / wither-out. Resumes on menu re-entry.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FpNEL7iHc7bCKFTFvV3Byc
Card_Frame_Cyan.png now fills its interior with an opaque dark-navy vertical gradient
(was a transparent-center outline) and uses a much subtler glow. Same file/GUID/9-slice
meta, so existing wiring is unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FpNEL7iHc7bCKFTFvV3Byc
Adds a ScriptableObject node-graph system for authoring the First-Time-User-
Experience as a branching flowchart, an IMGUI editor to build it, a runtime
runner that executes it against existing systems, cloud-synced completion
persistence, and a generator for the canonical onboarding flow.

Extends the existing Assets/FTUE scaffold (reuses TutorialUIView / FTUEIntroAnimator /
FTUEEventManager) and replaces the flat, non-branching TutorialSequenceSet with a graph.

- Graph model: FTUEGraphSO + polymorphic FTUENodeSO (+ FTUEEdge/FTUEPorts/FTUERuntimeContext)
  with 15 node types: PlayIntro/Outro, ShowInstruction, Dialogue, EnterFreestyle,
  ExitFreestyle, WaitForInput, HighlightCTA, LockModes, Navigate, WaitForGameLaunch,
  WaitForGamePlayed, Wait, SetPhase, End — each mapped to a real runtime system.
- FTUEGraphRunner: first-run gated on GameData.OnClientReady + cloud completion, edge-based
  advancement, per-node SOAP subscription cleanup (no leaked delegates).
- Editor: FTUE Graph window (node canvas, port wiring, per-node inspector, live validation),
  Create Default FTUE Graph generator (authors the described flow end-to-end), and a
  Setup Runner In Scene helper that auto-resolves references.
- Cloud persistence: FTUECloudData + FTUEProgressRepository wired into UGSDataService
  (key FTUE_PROGRESS) with a PlayerPrefs mirror via FTUECompletionStore.
- DialogueManager.OnDialogueFinished event so dialogue nodes advance without polling.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
…h tool

Renames the FTUE graph system to Quest Graph (GUID-preserving) and rebuilds it
around the design plan: a QuestSO holds ordered phase graphs; the graph is the
source of truth driving CTA breadcrumbs, GameModeProgressionService, dialogue,
and per-node UGS persistence.

- Phase model: QuestSO (ordered QuestPhaseGraphSO phases with designer notes);
  QuestPhaseEndNode advances phases, QuestEndNode completes the quest.
- New nodes: WaitForIntensity (tier gate), WaitForModeUnlocked (claim gate),
  UnlockMode (direct progression write), WaitForUserAction (generic gate);
  WaitForGamePlayed gains mode + min-intensity filters. Node categories,
  tooltips, and live field summaries on every node.
- Runner v2: runs a quest across phases with exact mid-phase resume from UGS,
  records every completed node (QuestProgressCloudData, key QUEST_GRAPH_PROGRESS),
  and owns guidance while running via GameModeProgressionService.BreadcrumbSuppressed.
- Progression service: public UnlockMode(mode) + breadcrumb suppression window.
- Enums/hooks: CallToActionTargetType ProfileMenu/EpisodeMenu/PlayGameMaelstrom;
  UserActionType ViewProfileMenu/ViewEpisodeMenu/UnlockVessel; ScreenSwitcher
  fires ViewProfileMenu on Profile navigation.
- Quest Graph Editor (FrogletTools ▸ Quest Graph Editor): cached asset lists +
  validation (no per-frame AssetDatabase hits), cursor-anchored wheel zoom,
  middle/alt-drag pan, content-sized node cards, category colors + legend,
  hover tooltips, drag-to-connect with spawn-and-connect, quest/phase panel
  with reorder, default asset locations (no file dialogs), F-frame/Delete keys.
- Generator: FrogletTools ▸ Quest Graph ▸ Create Main Quest builds the full
  6-phase FTUE plan (onboarding/CC → HexRace → Joust → Maelstrom → vessel tour
  → episodes finale) with notes baked in.
- Docs: QUEST_GRAPH_TOOL.md; shareable/editable progression map at
  Docs/QuestMap/QUEST_MAP.html (data embedded via Save-as-HTML).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
- Enable/disable switches at every level (test harness): QuestSO.questEnabled
  (runner never starts a disabled quest), QuestPhaseGraphSO.phaseEnabled
  (runner skips disabled phases), QuestNodeSO.nodeEnabled (runner passes
  straight through disabled nodes via their next edge). Toggles in the left
  panel rows, node card headers, right-panel inspectors, and node context
  menu, with dimmed/OFF visuals and an entry-node-disabled validation warning.
- Quest inspector gains Rename Asset and Reset Local Progress (PlayerPrefs
  mirror) controls.
- Removed the Standalone Graphs section and the standalone graph creation
  button — phase graphs now exist only as quest phases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
Code contracts for the five designer-built UIs, wired into the graph:

- QuestInstructionView — lightweight control-teaching overlay (plain text +
  NiceVibrations haptic pulse, CanvasGroup fade). ShowInstruction nodes now
  drive it (new fields: haptic preset, minDisplaySeconds, hideOnAdvance;
  next-press removed) with the legacy TutorialUIView as fallback; runner
  hides it at phase/quest boundaries.
- QuestDialoguePanelView — IDialogueView with captain portrait, typewriter
  body, Next (complete-then-advance) and Skip (fast-forward set); slots into
  DialogueViewResolver's MainMenu channel for Dialogue nodes.
- QuestRewardRevealView — IDialogueView for the Reward channel: profile-screen
  panel populated from the set's RewardData, Continue steps lines and closes.
- QuestToastNotifier — achievement toasts through ToastNotificationAPI: mode
  unlocked, intensity tier, quest-track objective met, quest-graph phase and
  quest completion (templates + toggles serialized).
- FTUEEventManager gains OnQuestPhaseCompleted / OnQuestCompleted, raised by
  the runner at phase/quest boundaries.
- UserActionTrigger gains optional triggerOnEnable so panels (e.g. the episode
  panel inside profile) fire their UserActionType on open.
- Runner/setup expose + auto-resolve the instruction view; default-content
  generator updated for the new ShowInstruction fields.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
…nels, control icons

Redesigns the Phase 0 in-flight tutorial to the new control curriculum:
sticks-outward speed up, sticks-inward slow down, movement-stick look-around,
LT+RT drift, skim 10 prisms (live counter), and press-B exit — the player is
never forced out of freestyle except by their own B press.

- QuestInstructionView: keyed CanvasGroup panels (designer-built instruction
  sets with icons, cross-toggled by ShowInstruction's new panelKey) + a
  progress counter ("3 / 10") for counting gates.
- New gates: QuestWaitForDriftNode (IVesselStatus.IsDrifting sustained) and
  QuestWaitForSkimNode (rides the shared skim-boost SOAP channel, filtered to
  the local vessel and to boost INCREASES so per-frame decay raises don't
  count; drives the live counter).
- Success haptics: WaitForInput/WaitForDrift/WaitForSkim pulse a configurable
  HapticType when the player performs the correct action (per-skim pulse
  separate, default off — the skimmer's own haptics effect covers it).
- QuestExitFreestyleNode gains forceExit (+retry/timeout): pairs with a
  WaitForInput(Button3/B) gate so the exit fires exactly on B.
- Runner/context/setup expose the skim-boost event asset.
- Control icon sprite set (white, tintable, animatable parts) at
  Assets/_Graphics/UI/ControlIcons: thumbstick base/cap, chevron arrow,
  composed outward/inward pulls, look-around stick, LT/RT triggers, B button.
- Generator Phase 0 rewritten to the new sequence (panel keys authored);
  design map (Docs/QuestMap/QUEST_MAP.html) updated with the flight school
  and embedded as the file's data revision.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
- QuestPhase0UIWirer (FrogletTools ▸ Quest Graph ▸ Wire Phase 0 UI): wires the
  hand-built Menu_Main UI in place — InGameInstructionSet/Container children
  become keyed instruction panels (flight-school order, mapping logged), a
  starter skim ProgressText is created if missing, DialogueSetUI gets
  QuestDialoguePanelView with captain/body/next resolved by heuristics and is
  plugged into the dialogue resolver, QuestToastNotifier lands on the runner,
  then the standard runner setup re-resolves references.
- DialogueViewResolver: optional per-channel override slots (any IDialogueView
  MonoBehaviour) so the new panels take over MainMenu/Reward channels without
  replacing the existing concrete views; validated in OnValidate.
- QuestExitFreestyleNode hides the instruction overlay when the flight ends
  (all completion paths) so the exit prompt can't linger over the menu.
- QuestInstructionView only auto-grabs a fallback TMP in plain-text mode —
  with keyed panels the first child TMP belongs to a panel.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
… dialogue system retired from the quest path

Per design: the Main Quest no longer uses DialogueManager/DialogueSet assets.
QuestDialogueNode now carries its own lines (speaker + optional portrait
override + [TextArea] lines) and drives the DialogueSetUI panel directly.

- QuestDialoguePanelView: new PlayLines(speaker, portrait, lines, onComplete)
  self-driving sequence (typewriter, Next steps, Skip fast-forwards, hides and
  calls back after the last line), CancelIfPlaying for clean teardown, default
  captain portrait preserved across per-beat overrides. IDialogueView impl kept
  for optional legacy use.
- QuestRuntimeContext: DialoguePanel scene ref + prefab/parent fallback with
  lazy instantiation (GetOrCreateDialoguePanel); DialogueManager removed.
- Runner/setup wire the panel (auto-resolved); Phase 0 UI wirer no longer
  touches the dialogue resolver.
- Generator: every dialogue beat now ships with authored placeholder lines
  (maps tour, profile explainer, per-mode reward reveals, hangar tour, finale)
  — the MainQuest runs end-to-end with zero DialogueSet assets.
- Docs + design map updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
The FTUE's first beat is now the EnterFreestyle node itself: as soon as the
menu initializes (OnClientReady + start delay), the camera blends from the
menu orbit to the player vessel — the same transition as entering freestyle
manually — and the first instruction only appears after the blend completes.
The intro-cinematic node is removed from the default graph's front (the
PlayIntro node type remains available for authoring).

Generator, docs, and the design map updated to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
…skim counter

- QuestToastNotifier: logInsteadOfToast (default on) routes all achievement
  messages through CSDebug.Log with a [Quest][TOAST] prefix — untick once the
  toast UI exists in the scene.
- Phase 0 UI wirer no longer auto-creates a ProgressText: the skim counter is
  opt-in (assign any TMP to the instruction view's Progress Text to enable the
  live readout; the skim gate works without it).
- Runner setup stops warning about the legacy TutorialUIView / FTUEIntroAnimator
  fallbacks — they're optional now that instructions use QuestInstructionView
  and the default graph has no intro cinematic.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
…ter appends to the active set's text

Legacy FTUE tutorial system deleted — the Quest Graph replaced it entirely:
- Scripts: TutorialFlowController, TutorialSequenceSet/Step/StepType/Payload/
  Section/Phase, FTUEProgress, FTUEIntroAnimator, TutorialUIView,
  InGameTutorialFlowView, all adapters/handlers/interfaces.
- Assets: legacy step/sequence/progress SOs and the Captain_VO_FTUE prefab.
- Quest nodes PlayIntro/PlayOutro removed (drove the deleted animator).
- Runner/context/setup drop the TutorialUI + IntroAnimator legacy slots;
  ShowInstruction no longer has a legacy fallback.
- FTUEEventManager trimmed to what is actually raised: OnCTAClicked (GameCard),
  InitializeFTUE, and the quest phase/completion events.

Skim counter: no separate ProgressText — the "n / target" count is appended to
the ACTIVE instruction set's own TMP text (base text cached on activation and
restored when the gate completes).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
…, training HUD hide

- QuestEdge gains per-edge delaySeconds; runner waits (realtime) before
  running the next node. Editable in the tool: a "Delay (s)" field under
  each connection in the side panel plus a live label on the canvas edge.
- Editor gets "Reset Player Progress (Local + Cloud)" — clears the local
  PlayerPrefs mirror always, and in Play mode also removes the quest's
  cloud record (QuestProgressStore.ResetCloud) and resets
  GameModeProgressionService progression.
- QuestWaitForDriftNode now requires drifting BOTH directions (LT-led and
  RT-led, trigger-dominance detection with hold time) before advancing;
  shows a 0/2 progress counter and pulses haptics per completed direction.
- Flight training hides gameplay HUD: runner's hideDuringFlightTraining
  CanvasGroups are zeroed when EnterFreestyle completes; the Phase 0 wirer
  auto-assigns the "Game UI" group.
- Instruction panels: the node's authored text now OVERWRITES the panel's
  scene TMP text (scene text is a placeholder only) — also fixes the
  doubled skim counter, since the counter appends to the node text base.
- Default MainQuest generator authors sensible delays (1.5s menu->vessel
  camera entry, 0.8-1s between training beats) and the two-direction
  drift prompt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
…k, arcade funnel, full reset

- Flight training now hides the vessel HUD through its own controller
  (VesselHUDController.HideHUD — same channel MenuMiniGameHUD uses) instead
  of zeroing the Game UI group, which raced the freestyle fade AND hid the
  volume button. Extra authored hide-groups are enforced every LateUpdate
  while training is active so a late fade can't re-show them.
- R_VesselActionHandler gains SetInputSuppressed/ClearSuppressedInputs (no
  timer, caller-owned). During flight school the quest gates A/X/B/flip at
  press and release — only the taught sticks and triggers do anything.
- Exit is now the volume/pause button (it already calls ToggleTransition):
  the last instruction says to tap it and a passive ExitFreestyle node waits
  for the menu blend. Never forced; B is suppressed like the other buttons.
- New QuestLockNavigationNode + runner nav wiring: after exit the footer nav
  locks to the Arcade button and a captain dialogue points at it; nav is
  unlocked after the first Crystal Capture run and always on quest teardown.
- New QuestArcadeConstraints (static, survives Menu->game->Menu reloads) +
  QuestSetArcadeConstraintsNode: locks every game card except the tutorial
  mode, disables every intensity except the forced one, defaults player
  count to max and domain count to 3. Consumed by ArcadeExploreView and
  ArcadeGameConfigureModal. P0 authors intensity-2 funnel, then intensity-3,
  then clears it.
- WaitForGamePlayed now consults GameModeProgressionService play counts on
  resume — the OnMiniGameEnd raise happens in the game scene while the
  runner lives in Menu_Main, so a fresh menu load advances the gate from
  the recorded play instead of hanging.
- Reset button is now a FULL gameplay wipe (QuestProgressStore.
  ResetAllGameplayProgress): quest local+cloud, mode/intensity progression,
  all vessel unlocks (hangar cloud record flushed), and arcade constraints.
  The Froglet Toolbox reads this state live and can still re-unlock manually.
- Phase 0 wirer: removes the legacy 'Game UI' hide entry and auto-wires the
  nav buttons from ScreenSwitcher's OnClick*Nav persistent handlers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
…l UX, constraint refresh

Backend (local-only testing mode):
- New ProgressionBackendGate (CloudEnabled=false, TEMP): with the gate
  closed, quest progress lives only in the PlayerPrefs mirror, game-mode
  progression neither loads from nor saves to GAME_MODE_PROGRESSION (fresh
  every session), and vessel unlocks are not persisted NOR resurrected from
  the stale hangar cloud record (SyncHangarToVessels gated symmetrically
  with the write paths). Reset button works instantly, edit or play mode,
  and the quest inspector shows a LOCAL-ONLY banner.

Dialogue (the FTUE hang after flight school):
- QuestDialoguePanelView now lazy-initializes and activates its own
  GameObject before playing — the hand-built DialogueSetUI is saved
  inactive, so Awake had never run: PlayLines threw on the null CanvasGroup
  / inactive-object StartCoroutine and the quest silently hung, which is
  why nothing after the dialogue (constraints, card locks, intensity locks,
  max players) ever applied. If a parent is still inactive it now fails
  OPEN (logs + completes) so the quest can never stall on a dialogue beat.
- QuestRunnerSetup clears the Dialogue Panel Prefab slot when it holds the
  scene panel (the hand-wired duplicate reference).

Arcade constraints:
- QuestArcadeConstraints.OnChanged event; ArcadeExploreView repopulates on
  it (and retries its progression subscription in Start), so card locks
  apply even if the constraints node fires while the arcade is open.

Editor tool:
- Left/right sidebars are resizable (drag the inner edge) and hideable
  (toolbar toggles), widths/visibility persisted in EditorPrefs; canvas
  shrinks panels proportionally on small windows and drag clamps guard
  against inversion (review findings).
- Designer-notes fields use a real scroll view with a draggable scrollbar
  (raw IMGUI TextAreas only caret-scroll); scrollbar drags no longer trip
  the change check and dirty the asset. Node [TextArea] fields grew to 8
  lines.
- "Legend" is now a persisted "Node Colors" show/hide toggle.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
…st-game 1/2/2, place progression service

- Editor checkpoint view: the canvas now overlays the player's LOCAL
  progress — ✓ on every completed node, an amber "▶ NEXT" banner on the
  node the quest resumes at, a ▶ marker on the current phase row, and a
  PLAYER PROGRESS readout in the quest inspector. Polls the local mirror
  and repaints live during Play mode, so you can always see the last
  checkpoint you completed while testing.
- QuestProgressStore records every completed node id locally (DoneNodes
  CSV) alongside the cursor; ResetLocal clears it and also clears the
  arcade constraints so a cursor wipe can't strand a locked arcade.
- QuestArcadeConstraints now PERSIST in PlayerPrefs with the quest cursor:
  the resume point lands past the SetArcadeConstraints node, so statics
  alone meant any play-session restart silently unlocked the whole arcade
  (the "gamemodes are unlocked again" inconsistency).
- First-game funnel is now authored as intensity 1, player count 2, domain
  count 2 (ForcedPlayerCount replaces force-max-players; the played gate
  accepts intensity >= 1). Second CC run stays intensity 3 with 2/2.
- Phase 0 wirer creates + wires GameModeProgressionService in Menu_Main if
  missing — the only prefab carrying it sits unplaced in MIgration_Prefabs
  (DELETE LATER), so Instance was NULL in every run: no progression card
  locks, no play-count tracking, and played-game gates could never resume
  after the Menu->game->Menu round-trip.
- QuestGraphRunner auto-heals the dialogue prefab slot (OnValidate + at
  context build): a scene object wired into the prefab slot is cleared —
  it must be a prefab asset, the scene panel drives dialogue.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
…silent stuck-at-end

Adversarial trace of the solo game-over path found the whole pipeline runs
synchronously inside ONE latched SOAP raise with zero exception isolation:
TurnMonitorController latches _isRunning=false, raises OnMiniGameTurnEnd,
and that single raise nests winner calc → score sync → reveal → scoreboard.
Any subscriber exception anywhere kills everything downstream permanently —
no winner, no scoreboard, no menu button: exactly "game over then stuck".

- TurnMonitorController: catch + LogException around the raise with a loud
  pointer at the culprit subscriber (the latch means it never retries).
- EndGameSequencer.RunReveal: flourish wrapped fail-open (and AudioSystem
  null-guarded) so InvokeShowGameEndScreen is ALWAYS reached; the reveal
  hold is now unscaled so a zero timescale can't freeze it forever.
- Scoreboard.ShowScoreboard: population wrapped fail-open so the panel
  (with its Main Menu / Play Again buttons) appears even if a stats step
  throws — the player always has a way home.
- SceneLoader: ClearPlayerVesselReferences wrapped fail-open (the fade is
  already black at that point), and the ignored Netcode LoadScene status
  now falls back to a local load when the scene event is refused.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
claude and others added 29 commits July 14, 2026 22:13
…ttern (Joust, Maelstrom)

Mirrors the hand-authored HexRace phase in the generator's unlock-phase
template so every unlock phase (HexRace, Joust, Maelstrom) gets it:
profile CTA + explainer, then a WaitForUserAction(ViewProfileMenu) hold so
the claim-hint dialogue ("Tap the <previous mode> card on your quest track
to collect your reward!") only plays once the player is actually ON the
profile, then claim → reward → play CTA → played. Dialogue lines use
player-facing mode names (Crystal Capture / Hex Race / Joust / Maelstrom)
instead of enum names.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
…ton shows unsaved state

Flipping a quest/phase/node enable toggle only marked the asset dirty in
memory — the .asset file (what git sees) changed only on an explicit save,
so a disabled phase pushed with no diff. The five toggle sites (left-panel
quest + phase, node card checkbox, right-panel node toggle, node context
menu) now call AssetDatabase.SaveAssets() on the spot: the tool's harness
state always lands in version control the moment it's flipped. Other edits
(text, node positions, wiring) still batch behind the Save button, which
now reads "Save*" with a tooltip while in-memory edits are pending.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
… Maelstrom phase ASSETS

Hand-edited MainQuest_Phase2/Phase3 directly (the live graphs the runner
uses — no regeneration): after the Profile Explainer, a new
WaitForUserAction(ViewProfileMenu) node holds until the player actually
opens the profile, then a new claim-hint dialogue points at the previous
mode's card ("Tap the HEX RACE / JOUST card on your quest track to collect
your reward!") before the claim gate — mirroring the hand-authored
HexRace phase. Fresh sub-asset ids, explainer edge retargeted, nodes
registered on each graph; edge/reference integrity verified.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
… state panel for testing

The stale phase-0 funnel (Allowed Mode=CC, Forced Intensity=1) was leaking
into phase 1: the newly claimed mode's card sat LOCKED under a glowing CTA,
its button was unpressable, and the configure modal blocked intensities
2-4 even after force-advance had genuinely unlocked tier 4 in progression.
Three-layer fix:

- Phase scope: QuestPhaseEndNode now CLEARS the arcade funnel at every
  phase boundary — the funnel is a within-phase tool; a phase that wants
  one re-applies it. No authored graph can strand a stale funnel anymore.
- Reward exemption: IsModeBlocked never blocks a mode the progression
  chain has explicitly unlocked — the funnel focuses onboarding, it can't
  lock the quest's own reward.
- Correct scope: forced intensity / player count / domain count apply only
  to the tutorial (allowed) mode itself, never to other games' modals
  (IsIntensityBlocked now takes the mode; all modal call sites updated).

Testing affordance: the quest inspector gains a play-mode LIVE STATE box
showing the current funnel constraints and every unlocked mode with its
max tier, plus a "Clear Arcade Funnel Now" escape hatch — so "why is this
locked?" is answered at a glance instead of by replaying.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
…r gate + toast NRE

- New QuestSetButtonInteractableNode: flips a runner-registered scene Button's
  interactable state by key. Phase 5 now ENTERS through 'Enable Episodes Button'
  (key 'episodes') so the authored non-interactable Episodes button becomes
  clickable right before its CTA — the ViewEpisodeMenu gate is satisfiable.
- QuestGraphRunner gains a Quest Buttons list (key + Button); context exposes
  SetQuestButtonInteractable. Phase 0 wirer auto-registers the first Button whose
  name contains 'episode' under key 'episodes'.
- MainQuest_Phase5.asset patched in place (new entry node -> CTA: Episodes);
  generator emits the same chain on future regens.
- GameModeProgressionService.IsUnlockObjectiveDone: full-intensity modes
  (Maelstrom/Tournament) have no intensity ladder, so the raw persisted-intensity
  check could never pass and the Vessel Hangar gate was permanently locked. They
  now count as done once the chain unlocks them.
- ToastNotificationItem.Show: lazy-resolve CanvasGroup/RectTransform — Show can
  arrive before Awake on an inactive item (NRE on vessel unlock tap).
- HangarVesselDetailView: hangar-locked feedback via CSDebug.Log for now.
- Quest editor inspector: backend hint removed; Force-Advance / Reset / Clear
  Funnel buttons are centered and fitted instead of stretched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
…inale dialogue

Match the authored MainQuest_Phase5 order (dialogue names the Episodes screen,
THEN the button becomes interactable, then its CTA) so a regenerated quest keeps
the CTA gate satisfiable the moment it lights up.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
QUEST_GRAPH_EDITOR_TOOL.md — hands-on guide for the FrogletTools Quest Graph
Editor: window tour + canvas controls, graph editing (edges, delays, entry node,
enable toggles, saving), full node reference, the play-mode testing workflow
(checkpoint view, Force-Advance, LIVE STATE, reset), persistence notes, common
recipes, and troubleshooting. Cross-linked from the architecture reference.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
…editor-tool-69acq5

# Conflicts:
#	Assets/_Prefabs/UI Elements/Main Menu Screens/QuestItemPrefab.prefab
#	Assets/_SO_Assets/GameModeQuest/ProgressionConfig.asset
#	Assets/_Scenes/Menu_Main.unity
#	Assets/_Scripts/Controller/Arcade/TurnMonitorController.cs
#	Assets/_Scripts/ScriptableObjects/SO_GameModeQuestData.cs
#	Assets/_Scripts/ScriptableObjects/SO_ProgressionConfig.cs
#	Assets/_Scripts/System/Progression/GameModeProgressionService.cs
#	Assets/_Scripts/UI/Scoreboard.cs
#	Assets/_Scripts/Utility/DataContainers/EndGameSequencer.cs
…editor-tool-69acq5

# Conflicts:
#	Assets/_Scenes/Bootstrap.unity
…editor-tool-69acq5

# Conflicts:
#	Assets/_Scenes/Bootstrap.unity
… targets, gate readout

- ExtractStatForIntensityGoal / ExtractStatForQuest: CrystalsCollected goals now read
  the dedicated RoundStats.CrystalsCollected counter instead of Score (mode-defined:
  golf finish time in races, points elsewhere) — crystal goals silently never counted.
- GameModeQuest_CrystalCapture: intensity 3/4 stat targets 30/25 -> 10. The match ends
  when a domain totals 20 crystals, so a personal 25 was structurally impossible — the
  SCURRY tier-4 gate could never advance no matter how well the player played.
- RecordIntensityPlay logs the shortfall when a deciding-intensity game misses its goal
  (stat seen vs needed, or plays so far), so "played I3, nothing advanced" is
  diagnosable from the console.
- Quest Graph tool: when the resume node is a tier gate, PLAYER PROGRESS now spells out
  the unlock requirement — stat threshold or play count, the mode's current tier, plays
  recorded, and the race caveat (finish time counts only on the winning domain).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
…est cards open the arcade

- All three chain modes now unlock tier 4 (and complete their quest) by WINNING an
  intensity-3 game: Scurry/Crystal Capture, Hex Race, and Joust all switch to the
  WinMatch stat with target 1 ("Rank first ..." goal text on each quest asset).
- WinMatch extraction rewired to the authoritative winner state (WinnerDomain vs the
  local player's domain, with the per-domain stats fallback) — the old check read
  RoundStatsList[0], which is roster order, not rank, so wins were misdetected.
- Quest Graph tool: gate readout words the WinMatch goal plainly ("WIN the match").
- Quest track (profile): tapping a card now acts by state — an unlocked or claimed
  mode jumps straight to the arcade (ScreenSwitcher.OnClickArcadeNav, which also
  satisfies arcade CTA gates), a ready-to-claim card claims with the whole card as
  the hit target, locked cards ignore the tap. QuestItemCard grows a BindCardAction
  root-Button binding; the child claim button still consumes its own clicks first.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QkxbbeGixf58FkVYRk4Moz
…editor-tool-69acq5

# Conflicts:
#	Assets/_Scripts/System/VesselUnlock/VesselUnlockSystem.cs
#	Assets/_Scripts/UI/Views/PlayerDataService.cs
#	Assets/_Scripts/UI/Views/XPTrackView.cs
The Quest Graph Editor laid every phase out in columns of 5 (a snaking
cursor), which said nothing about the track. Graphs now read left→right
along a ROW, with a new row wherever the beat moves the player between the
app shell (menus, arcade, profile) and gameplay (freestyle flight, a
launched match) — so each row is one place the player is standing and each
break is a real context switch.

- QuestNodeSO: new QuestVenue (Inherit/AppShell/Gameplay) + Venue /
  VenueAfter virtuals. Only the transition nodes override them —
  EnterFreestyle, ExitFreestyle, WaitForGameLaunch, and the away trips
  WaitForGamePlayed / WaitForIntensity (gameplay while they run, app shell
  after) — everything else inherits, so rows never break on a beat that
  didn't move the player.
- QuestGraphLayout (editor): DFS flow order from the entry node, one row per
  venue; unreachable nodes appended rather than left stacked at the origin.
  Geometry constants live here.
- Editor window: "Layout Rows" toolbar button (undoable, frames after).
- FrogletTools ▸ Quest Graph ▸ Layout All Phases (Rows) for the whole quest.
- QuestDefaultContentBuilder: drops the column cursor and runs the shared
  layout, so generated graphs open already arranged.
- All six MainQuest phase assets re-laid out (positions only).
- Docs: QUEST_GRAPH_TOOL.md gains a "Canvas layout — venue rows" section;
  QUEST_GRAPH_EDITOR_TOOL.md gains the toolbar/menu entries and a designer
  walkthrough of the row paradigm.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G9U9w56EkngSuv4ix1vzmX
Long rows never wrap (Phase 0's flight-school row can't fit a framed
canvas), and CLAUDE.md's FTUE section still predates the Quest Graph
system entirely. Both logged in QUEST_GRAPH_TOOL.md so they have a doc
home rather than living in a PR comment.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G9U9w56EkngSuv4ix1vzmX
…rows-or6y6j

feat(ftue): arrange quest graphs in venue rows instead of columns
…editor-tool-69acq5

# Conflicts:
#	Assets/FTUE/DataContainer/FTUEGraph_Default.asset.meta
#	Assets/FTUE/DataContainer/Phases/MainQuest_Phase0.asset.meta
#	Assets/FTUE/DataContainer/Phases/MainQuest_Phase1.asset.meta
#	Assets/FTUE/DataContainer/Phases/MainQuest_Phase2.asset.meta
#	Assets/Resources/PrismOcclusionConfig.asset.meta
#	Assets/_SO_Assets/Cell Configs/Blob Cell/Blob Cell Spawn Profile.asset
#	Assets/_SO_Assets/Cell Configs/Blob Cell/Blob Fauna Config Data.asset
#	Assets/_SO_Assets/Cell Configs/Geode Cell/Geode Cell Config.asset.meta
#	Assets/_SO_Assets/Cell Configs/Orrery Cell/Orrery Cell Config.asset.meta
#	Assets/_SO_Assets/Cell Configs/Scurry Cell/Scurry Cell Config.asset.meta
#	Assets/_SO_Assets/Songs/Charles 3.asset
#	Assets/_SO_Assets/Songs/Charles 4.asset
#	Assets/_SO_Assets/VesselActions/Rhino/RhinoSwordSwingKinematicsConfig.asset
#	Assets/_SO_Assets/XP/XPTrackData.asset.meta
#	Assets/_SO_Assets/XP/XPTrackReward_1.asset.meta
#	Assets/_SO_Assets/XP/XPTrackReward_2.asset.meta
#	Assets/_SO_Assets/XP/XPTrackReward_3.asset.meta
#	Assets/_Scenes/Menu_Main.unity
#	Assets/_Scripts/ScriptableObjects/SO_ProgressionConfig.cs
#	Assets/_Scripts/UI/Scoreboard.cs
#	Assets/_Scripts/UI/Views/PlayerDataService.cs
#	Docs/Analytics/DATA_INVENTORY.md
#	Docs/MENU_PROGRESSION_AND_IAP.md
…editor-tool-69acq5

# Conflicts:
#	Assets/_Scenes/Menu_Main.unity
#	Assets/_Scripts/Controller/Arcade/TurnMonitorController.cs
…pstream

Merges origin/bleeding-edge (df80aab, PRs #762-#811) into the Quest Graph
branch, which last synced at #761 on Aug 20.

Upstream and this branch overlap on only three files; every other conflict
(77 of 81) was criss-cross collateral from this branch's repeated upstream
merges, on paths this branch never modified. Those are resolved to upstream
exactly -- verified file-by-file that each is byte-identical between the old
merge base and this branch's HEAD, so no branch change is discarded.

Resolutions:

- 73 paths taken from upstream verbatim (ecology level-retirement assets,
  prism-clock shader/HLSL, docs, CLAUDE.md, skills, CI workflow).
- 4 paths removed: present in neither side, left behind by the recursive
  merge's virtual base (tests upstream moved to Tests/Editor/).
- 4 .cs.meta kept at this branch's GUIDs. Git's rename detection paired the
  branch's new Quest metas with unrelated new upstream metas -- default
  MonoImporter boilerplate differing only in GUID. Both files now exist with
  their own GUIDs; all nine involved GUIDs verified distinct.

The two genuine content overlaps auto-merged correctly and were checked by
hand rather than assumed:

- Blob Fauna Config Data: keeps this branch's PopulationSize 9 /
  MaxLivePopulation 15 AND upstream's retirement of FeedsPerLevel,
  InitialLevel, BodyScalePerLevel and LevelGrowSeconds (#810,
  "retire lifeform levels"). No retired field survives.
- ProgressionConfig: keeps this branch's removal of mode 36 from
  alwaysUnlockedModes and defaultMaxIntensity 3, plus upstream's mode 44.

R_VesselActionHandler.cs carried both sides: this branch's SetInputSuppressed
gate and upstream's InputDeviceType.MouseKeyboard override row.

The Quest/FTUE work is not superseded -- upstream touched no FTUE or Quest
file. All 268 PR files, 22 quest nodes and 5 editor tools are intact.

Tools/Build/check_conditional_compilation.py: OK (1804 files).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MEapXRwbzTHRHeFukGugdt
@FenrysUnchained FenrysUnchained changed the title Add FTUE graph editor and runtime system Quest graph editor and runtime system (replaces the FTUE tutorial flow) Aug 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants