Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Author Handoff Point in WolvenKit

This walkthrough expands the supplied Lab 4 start checkpoint into the exact 12-node parent and 10-node child. The start project already contains every world, journal, localization, registration, and phase resource so the work can focus on the native composition boundary.

RecordValue
Structural validation date2026-08-09
Runtime test dateNot yet recorded

Required environment

ComponentExact version
Cyberpunk 2077 for Windows (GOG)2.31a (public patch 2.31)
WolvenKit8.19.0
ArchiveXL1.27.0
RED4ext1.30.0
redscript0.5.31

Use an untouched save created before any Lab 4 candidate was installed for runtime testing. A manually edited _Start project is useful for learning and comparison, but only the unmodified completed checkpoint is the canonical acceptance candidate.

1. Open and isolate the checkpoint

  1. Download and extract the start ZIP.
  2. Open CQA_Lab04_HandoffPoint_Start.cpmodproj with File > Open Project.
  3. Make an untouched backup of the extracted directory.
  4. Confirm source\archive and source\raw each contain the seven depot resources listed in the overview.
  5. Confirm CQA_Lab04_HandoffPoint_Start.archive.xl is under source\resources.
  6. Do not install the start and completed checkpoints together.

The start parent is [0] Input -> [13] Phase -> [1] Output. The start child is [0] Input -> [1] Output. Both output nodes use socketName: Out1 and type: Terminating.

2. Audit registration before graph work

Open the ArchiveXL file and retain these four sections:

quest:
  phases:
  - path: mod\cqa\cqa004\phases\cqa004.questphase
    parent: base\quest\cyberpunk2077.quest

journal:
- mod\cqa\cqa004\journal\cqa004.journal

localization:
  onscreens:
    en-us:
    - mod\cqa\cqa004\localization\en-us\onscreens\cqa004.json

streaming:
  blocks:
  - mod\cqa\cqa004\world\cqa004_handoff.streamingblock

Do not add cqa004_boundary.questphase to quest.phases. It is an archived child resolved by the parent, not a second root. Do not add the two sectors to a guessed top-level registration list; the block descriptors reach them.

3. Audit all seven native resources

Before changing either graph, identify each supplied owner:

ResourceCheck
cqa004.questphaseRegistered root, one phasePrefabs entry, external phase node
cqa004_boundary.questphaseUnregistered external child, empty phasePrefabs
cqa004.journalQuest, phase, reach, leave, confirmation, and map-pin entries
cqa004.jsonFive exact secondary keys and English strings
cqa004_handoff.streamingblockQuest-sector and AlwaysLoaded-sector descriptors
cqa004_handoff.streamingsectorTwo trigger nodes, placements, refs, and outlines
cqa004_always_loaded.streamingsectorStatic marker, placement, and marker ref

The checkpoint includes cooked resources for direct WolvenKit editing and raw CR2W-JSON for focused review. Do not edit the JSON as the tutorial workflow.

4. Audit journal and localization ownership

Open cqa004.journal and confirm this typed tree:

gameJournalRootFolderEntry
└── quests                         gameJournalPrimaryFolderEntry
    └── minor_quest                gameJournalFolderEntry
        └── cqa004                 gameJournalQuest
            └── cqa004_01          gameJournalQuestPhase
                ├── cqa004_01_obj_reach
                │   └── cqa004_01_qmp_handoff
                ├── cqa004_01_obj_leave
                └── cqa004_01_obj_confirm

The map pin’s reference is #cqa004_mp_handoff. Open the localization resource and confirm:

Secondary keyEnglish value
cqa_cqa004_titleHandoff Point
cqa_cqa004_objective_reachReach the handoff point.
cqa_cqa004_objective_leaveClear the handoff area.
cqa_cqa004_objective_confirmWait for handoff confirmation.
cqa_cqa004_mappin_handoffHandoff Point

The child later changes reach, pin, and leave state. The parent later changes quest, phase, and confirmation state. Neither phase owns the strings.

5. Audit prefab scope and world resources

Open the root phase’s top-level phasePrefabs and retain exactly one questQuestPrefabEntry:

#cqa004_pr_handoff

Open the child and confirm phasePrefabs: []. Open parent phase node 13 and confirm phaseInstancePrefabs: []. Do not duplicate the root into either empty list.

The streaming block’s Quest descriptor uses full root:

$/mod/cqa/cqa004/#cqa004_pr_handoff

The two sector resources supply these full child refs:

$/mod/cqa/cqa004/#cqa004_pr_handoff/#cqa004_tr_reach
$/mod/cqa/cqa004/#cqa004_pr_handoff/#cqa004_tr_leave
$/mod/cqa/cqa004/#cqa004_pr_handoff/#cqa004_mp_handoff

The trigger geometry and marker placement intentionally match Lab 3. Confirm their values against the Lab 4 overview instead of changing location and phase ownership in the same experiment.

6. Audit the existing external phase node

Open cqa004.questphase, select node 13, and inspect its serialized properties:

PropertyExact value
RED typequestPhaseNodeDefinition
phaseGraphnull
phaseInstancePrefabsempty
phaseResource.DepotPathmod\cqa\cqa004\phases\cqa004_boundary.questphase
phaseResource.FlagsSoft
saveLock0
unfreezingTriggerNodeRefzero NodeRef
interface socketsinput In1, output Out1
interruption socketCutDestination, unwired

Open the child and confirm input node 0 exposes socketName: In1, output node 1 exposes socketName: Out1, and output type is Terminating.

The figure shows both interface layers and the present-but-unwired CutDestination. Do not connect cut to the terminating output as a shortcut.

7. Add and number parent nodes

Keep parent nodes 0, 1, and 13. Add these nine nodes:

Target IDAdd Node labelRED type
10ConditionquestConditionNodeDefinition
11JournalquestJournalNodeDefinition
12JournalquestJournalNodeDefinition
14JournalquestJournalNodeDefinition
15PauseConditionquestPauseConditionNodeDefinition
16JournalquestJournalNodeDefinition
17JournalquestJournalNodeDefinition
18FactsDBManagerquestFactsDBManagerNodeDefinition
19JournalquestJournalNodeDefinition

WolvenKit may assign lower automatic IDs. Renumber safely in two passes: move new nodes to temporary IDs 100–108, then move them to the targets. Never overwrite an ID still owned by another node. Save, close, reopen, and confirm the inventory before wiring.

8. Configure the parent guard and fact write

At parent ID 10, add questFactsDBCondition, then questVarComparison_ConditionType:

PropertyValue
factNamecqa004_completed
comparisonTypeEqual
value0

At parent ID 18, choose questSetVar_NodeType:

PropertyValue
factNamecqa004_completed
setExactValue1
value1

The exact write occurs only after child return and confirmation. Do not add a second fact to the child.

9. Configure parent journal operations

For parent Journal nodes, add questJournalQuestEntry_NodeType and a typed gameJournalPath. Keep these common values:

PropertyValue
optional0
sendNotification1
trackQuest1
versionInitial
path.editorPathempty
path.fileEntryIndex2
IDsclassNamerealPathConnected state
11, 19gameJournalQuestquests/minor_quest/cqa00411.Active, 19.Succeeded
12, 17gameJournalQuestPhasequests/minor_quest/cqa004/cqa004_0112.Active, 17.Succeeded
14, 16gameJournalQuestObjectivequests/minor_quest/cqa004/cqa004_01/cqa004_01_obj_confirm14.Active, 16.Succeeded

Incoming state sockets choose the requested journal state. The repeated path does not make the nodes redundant.

10. Configure the parent confirmation delay

At parent ID 15, add questTimeCondition, then questRealtimeDelay_ConditionType:

PropertyValue
hours0
minutes0
seconds30
miliseconds0

The 30-second realtime window makes the returned parent owner observable and provides a dedicated post-return reload case. It is not child cleanup.

11. Wire the exact parent graph

Right-click nodes and use Show Unused Sockets, then create these twelve ordinary edges:

SourceDestination
0.Out10.In
10.False1.In
10.True11.Active
11.Out12.Active
12.Out13.In1
13.Out114.Active
14.Out15.In
15.Out16.Succeeded
16.Out17.Succeeded
17.Out18.In
18.Out19.Succeeded
19.Out1.In

The decisive handoff edge is 13.Out1 -> 14.Active. Leave every CutDestination unwired.

Save, close, reopen, then compare against the exact parent graph. Canvas position and handle IDs are not behavior.

12. Add and number child nodes

Open cqa004_boundary.questphase. Keep nodes 0 and 1, then add:

Target IDAdd Node labelRED type
10JournalquestJournalNodeDefinition
11MappinManagerquestMappinManagerNodeDefinition
12PauseConditionquestPauseConditionNodeDefinition
13MappinManagerquestMappinManagerNodeDefinition
14JournalquestJournalNodeDefinition
15JournalquestJournalNodeDefinition
16PauseConditionquestPauseConditionNodeDefinition
17JournalquestJournalNodeDefinition

Use temporary IDs 100–107 before assigning final IDs. Save and reopen the child before adding connections.

13. Configure child journal operations

Use the same common journal values as the parent. Configure:

IDsclassNamerealPathConnected state
10, 14gameJournalQuestObjectivequests/minor_quest/cqa004/cqa004_01/cqa004_01_obj_reach10.Active, 14.Succeeded
15, 17gameJournalQuestObjectivequests/minor_quest/cqa004/cqa004_01/cqa004_01_obj_leave15.Active, 17.Succeeded

Child node 17 succeeds its local objective before the terminating output. It does not succeed the parent phase or root quest.

14. Configure child map-pin operations

Both Mappin Manager nodes use:

PropertyValue
path.classNamegameJournalQuestMapPin
path.realPathquests/minor_quest/cqa004/cqa004_01/cqa004_01_obj_reach/cqa004_01_qmp_handoff
path.fileEntryIndex2
path.editorPathempty
disablePreviousMappins0

Node 11 receives Active; node 13 receives Inactive. They address the same journal map pin. This isolated lab has no deliberate prior route to replace.

15. Configure child trigger waits

At each Pause Condition, add questTriggerCondition:

IDcondition.typetriggerAreaRef
12IsInside#cqa004_tr_reach
16IsOutside#cqa004_tr_leave

Set isPlayerActivator: 1. Leave activatorRef as the ordinary empty gameEntityReference. These are state-shaped waits, not Entered/Exited transition events.

The refs are local to #cqa004_pr_handoff, which is declared by the parent root. Keep child phasePrefabs empty for this lab.

16. Wire the exact child graph

Use Show Unused Sockets, then create these nine ordinary edges:

SourceDestination
0.Out10.Active
10.Out11.Active
11.Out12.In
12.Out13.Inactive
13.Out14.Succeeded
14.Out15.Active
15.Out16.In
16.Out17.Succeeded
17.Out1.In

Leave every CutDestination unwired. Save, close, reopen, and compare with the exact child graph.

17. Review the two resources together

Confirm all of the following before building:

  1. parent node 13.In1 matches child input socketName: In1;
  2. child output socketName: Out1 is terminating;
  3. parent node 13.Out1 connects only to parent 14.Active;
  4. phaseResource is soft and matches the archived child path exactly;
  5. phaseGraph is null;
  6. parent phase-node instance prefabs and child root prefabs are empty;
  7. only the root declares #cqa004_pr_handoff;
  8. no edge uses CutDestination;
  9. the child is absent from ArchiveXL quest.phases.

The exact contract figure should now match the resources:

18. Validate, build, and install

With every tab saved:

  1. run Project > Scan for broken file references;
  2. run Project > Scan for broken files;
  3. run Project > Run File Validation on the entire project;
  4. resolve all project-owned errors;
  5. close Cyberpunk 2077;
  6. choose Build > Install and wait for packing and installation;
  7. inspect WolvenKit’s Log panel and both installed files.

Use the normal ArchiveXL project install, not Install as REDmod. A packed archive without its loose .archive.xl cannot attach the root, merge the journal/localization, or register the world block.

The authored start project installs _Start-named files. To test the supplied completed project, open CQA_Lab04_HandoffPoint.cpmodproj, remove the start project’s installed files, and install the following pair:

archive\pc\mod\CQA_Lab04_HandoffPoint.archive
archive\pc\mod\CQA_Lab04_HandoffPoint.archive.xl

Common authoring failures

SymptomCheck
Parent activates but child does notExact soft depot path, packed child, null phaseGraph, matching In1, and logs
Child finishes but confirmation does not startChild output reachability, terminating Out1, and 13.Out1 -> 14.Active
Trigger refs fail after the splitParent root prefab entry, empty child/instance lists, world full root, and exact child refs
Both phases start independentlyRemove the child from ArchiveXL quest.phases; only the root is registered
Completion bypass runs too earlyConfirm guard is Equal 0 and fact write occurs at parent ID 18
Cut seems to terminate normallyRemove the guessed cut edge; Lab 4 leaves every cut socket unwired
Graph changes after reopenRenumber through temporary IDs, save/reopen before wiring, then compare semantics
Canonical hashes do not matchUse the unmodified completed checkpoint; a manually expanded _Start build is not byte-identical evidence

Lab sequence: All labs · Previous: Lab 4: Handoff Point · Next: Test Handoff Point.