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

Lab 1: author First Signal

This walkthrough builds the complete First Signal checkpoint from the empty Lab 1 WolvenKit project. You will create three mod-owned CR2W resources, wire the quest graph, add the ArchiveXL registration, install the project, and run a save-aware acceptance pass.

RecordValue
Runtime test dateNot yet recorded

The supplied checkpoint passes WolvenKit 8.19.0 structural checks. Follow the test procedure after authoring so you can compare the expected route with what actually happens in your game.

Use this exact baseline:

  • Cyberpunk 2077 2.31a;
  • WolvenKit 8.19.0;
  • ArchiveXL 1.27.0;
  • RED4ext 1.30.0;
  • redscript 0.5.31 (ArchiveXL 1.27.0 requires 0.5.31 or newer).

Complete the pinned toolchain setup, review the project and resource structure, and read Lab 1’s design before starting. Keep the completed checkpoint extracted in a separate directory for comparison.

Editor boundary used in this guide

WolvenKit 8.19.0 exposes these named commands in the tested editor:

  • File > New File for an empty CR2W or ArchiveXL file;
  • Add Node on an empty part of a quest graph;
  • Show Unused Sockets on a graph node;
  • Node Properties beside the quest graph;
  • Project > Scan for broken file references, Scan for broken files, and Run File Validation on the entire project;
  • Build > Install.

The nested CR2W type chooser is contextual: its placement and visible rows depend on the selected property. Where that makes a click label ambiguous, this guide gives a RED property path instead. At that path, use the plus control whose tooltip is Add Handle for a null handle or Add New Element for an array, then choose the exact RED type named here. This is still an in-editor workflow. Do not edit the serialized files under source\raw.

1. Open the start checkpoint

  1. Extract the start checkpoint to a writable working directory outside the game directory.

  2. In WolvenKit, choose File > Open Project and open CQA_Lab01_OneShot_Start.cpmodproj.

  3. Save a separate backup of that freshly extracted directory. WolvenKit’s quest editor has no general undo/redo safety net for this graph workflow.

  4. In the Project Explorer, open the source\archive directory in Windows Explorer and create this directory tree:

    mod\cqa\cqa001\
    ├── journal\
    ├── localization\en-us\onscreens\
    └── phases\
    

The start checkpoint’s project ModName ends in _Start, so its packed archive will be named CQA_Lab01_OneShot_Start.archive. That external archive name can differ from the completed checkpoint’s archive name; the depot paths inside it must match exactly.

2. Create the three CR2W resources

Create each file through File > New File. Choose the CR2W Files category, select the listed root type, replace the proposed name with the relative path below, and select Create.

Root type shown in New FileNameResult beneath source\archive
questQuestPhaseResourcemod\cqa\cqa001\phases\cqa001.questphaseRoot questphase
gameJournalResourcemod\cqa\cqa001\journal\cqa001.journalJournal tree
JsonResource with the .json descriptionmod\cqa\cqa001\localization\en-us\onscreens\cqa001.jsonOnscreen localization

The last file has a .json depot extension but is a binary CR2W JsonResource. It is not the plain-text review file whose name ends in .json.json in the completed checkpoint.

Press Ctrl+S after creating each file. The empty questphase should already contain a non-null questGraphDefinition; this is the scratch-file behavior of WolvenKit 8.19.0.

3. Author the journal tree

Open cqa001.journal. Work in the CR2W property tree and build this handle chain:

RootChunk                                      gameJournalResource
└── entry                                      gameJournalRootFolderEntry
    └── entries[0]                             gameJournalPrimaryFolderEntry
        └── entries[0]                         gameJournalFolderEntry
            └── entries[0]                     gameJournalQuest
                └── entries[0]                 gameJournalQuestPhase
                    └── entries[0]             gameJournalQuestObjective

At RootChunk.entry, add a handle of type gameJournalRootFolderEntry. At every following entries array, add one element and select the type shown above. Do not add an extra wrapper folder.

Set these properties. Paths use RED property names and array indexes, not CR2W-JSON HandleId wrappers.

Property path below RootChunkValue
cookingPlatformPLATFORM_PC
entry.descriptor.DepotPathbase\journal\descriptor.journaldesc
entry.descriptor.FlagsSoft
entry.entries[0].idquests
entry.entries[0].entries[0].idminor_quest
entry.entries[0].entries[0].entries[0].idcqa001
...cqa001.title.unk10
...cqa001.title.valuecqa_cqa001_title
...cqa001.typeMinorQuest
...cqa001.entries[0].idcqa001_01
...cqa001_01.entries[0].idcqa001_01_obj_wait
...cqa001_01_obj_wait.description.unk10
...cqa001_01_obj_wait.description.valuecqa_cqa001_objective_wait
...cqa001_01_obj_wait.counter0
...cqa001_01_obj_wait.optional0

In the abbreviated paths, ...cqa001 means entry.entries[0].entries[0].entries[0]; each later name identifies its one child entry.

base\journal\descriptor.journaldesc is the game-owned journal descriptor that supplies the standard hierarchy contract. It is a reference only: do not extract it into, rename it for, or redistribute it with the tutorial project.

Leave every entry’s journalEntryOverrideDataList empty. Leave the quest’s districtID empty and recommendedLevelID at zero. Leave the phase’s locationPrefabRef at zero. Leave the objective’s districtID empty and its itemID and locationPrefabRef at zero. These values are deliberate: Lab 1 has no district, item, marker, or world reference.

Press Ctrl+S, close the tab, and reopen it. Confirm that the six-entry chain and both localization keys survived serialization.

4. Author the onscreen localization

Open the CR2W cqa001.json under source\archive. At RootChunk.root, add a handle of type localizationPersistenceOnScreenEntries. Add two elements to its entries array; both elements are localizationPersistenceOnScreenEntry.

Set the resource and entries exactly:

Property path below RootChunkValue
cookingPlatformPLATFORM_PC
root.entries[0].primaryKey0
root.entries[0].secondaryKeycqa_cqa001_title
root.entries[0].femaleVariantFirst Signal
root.entries[0].maleVariantempty string
root.entries[1].primaryKey0
root.entries[1].secondaryKeycqa_cqa001_objective_wait
root.entries[1].femaleVariantWait for the signal.
root.entries[1].maleVariantempty string

This reproduces the structurally validated checkpoint shape. Runtime fallback and presentation for this new arrangement remain part of the Lab 1 Experimental acceptance run.

Save, close, and reopen the resource. Confirm the secondary keys exactly match the journal’s title.value and description.value strings.

5. Add the quest nodes

Open cqa001.questphase. Its Phase Resources view should show empty inplacePhases and phasePrefabs arrays. Leave both empty.

On an empty area of the graph, right-click and choose Add Node, then add the following nodes in order. The menu uses the short editor label; the second column records the serialized RED type.

Add Node labelRED typeTarget graph ID
InputquestInputNodeDefinition0
OutputquestOutputNodeDefinition1
ConditionquestConditionNodeDefinition10
JournalquestJournalNodeDefinition11
JournalquestJournalNodeDefinition12
PauseConditionquestPauseConditionNodeDefinition13
JournalquestJournalNodeDefinition14
FactsDBManagerquestFactsDBManagerNodeDefinition15
JournalquestJournalNodeDefinition16

WolvenKit assigns fresh IDs as nodes are created. Select each node and use Node Properties to set its id to the target value. If you created all nine first, change them in the table’s order: moving the initial input from 1 to 0 frees 1 for the output, and the remaining IDs move to the unused 10–16 range.

Set the interface fields:

NodePropertyValue
ID 0socketNameIn1
ID 1socketNameOut1
ID 1typeTerminating

socketName is the phase interface. It is different from the input node’s internal Out socket and the output node’s internal In socket.

Press Ctrl+S, close the questphase tab, and reopen it now. WolvenKit’s canvas can retain the wrappers’ original display IDs after an in-place id edit. Before following the ID-addressed steps below, verify that the graph now shows exactly [0], [1], and [10] through [16]. Reopening also rebinds the connector owners to the serialized IDs.

6. Configure the node payloads

ID 10: one-shot guard

At the node’s condition property, add a questFactsDBCondition handle. At condition.type, add a questVarComparison_ConditionType handle, then set:

Property pathValue
condition.type.factNamecqa001_completed
condition.type.comparisonTypeEqual
condition.type.value0

This node evaluates once on entry. It does not wait for the fact to change.

IDs 11, 12, 14, and 16: journal operations

For each journal node, add a questJournalQuestEntry_NodeType handle at type. Then select type.path, choose Add Handle, and create a gameJournalPath handle. New journal nodes do not create that nested path for you. Set the common fields on all four nodes:

Property pathValue
type.optional0
type.sendNotification1
type.trackQuest1
type.versionInitial
type.path.editorPathempty string
type.path.fileEntryIndex2

Then set each typed path:

IDtype.path.classNametype.path.realPath
11gameJournalQuestquests/minor_quest/cqa001
12gameJournalQuestObjectivequests/minor_quest/cqa001/cqa001_01/cqa001_01_obj_wait
14gameJournalQuestObjectivequests/minor_quest/cqa001/cqa001_01/cqa001_01_obj_wait
16gameJournalQuestquests/minor_quest/cqa001

IDs 12 and 14 address the same entry. Their incoming sockets will request different states.

ID 13: ten-second realtime gate

At condition, add a questTimeCondition handle. At condition.type, add a questRealtimeDelay_ConditionType handle and set:

Property pathValue
condition.type.hours0
condition.type.minutes0
condition.type.seconds10
condition.type.miliseconds0

miliseconds is the RED property spelling. This pause condition holds its path until the realtime delay becomes true.

ID 15: persistent fact write

WolvenKit initializes a new FactsDBManager node with a questSetVar_NodeType. Verify and set:

Property pathValue
type.factNamecqa001_completed
type.setExactValue1
type.value1

This writes exactly 1; it does not increment the existing value.

7. Expose and connect every socket

Right-click each node and choose Show Unused Sockets. Drag from each source output to the destination input in this table:

SourceDestinationMeaning
0.Out10.InEnter the one-shot guard
10.True11.ActiveFirst run: activate and track the quest
10.False1.InAlready complete: terminate immediately
11.Out12.ActiveActivate and track the objective
12.Out13.InBegin the realtime wait
13.Out14.SucceededSucceed the objective after the wait
14.Out15.InContinue to the completion fact write
15.Out16.SucceededSucceed the quest after the fact write
16.Out1.InTerminate the successful route

Socket inventory matters even when a socket is unused:

Node IDsSupplied socketsLab 1 use
0CutDestination, OutOut is connected; cut is unwired
1CutDestination, Inboth normal routes enter In; cut is unwired
10CutDestination, In, False, Trueall except cut are connected
11, 12, 14, 16CutDestination, Active, Inactive, Succeeded, Failed, Outthe connected state input differs by node; Out continues; all other state inputs and cut are unwired
13CutDestination, In, Outnormal wait path is connected; cut is unwired
15CutDestination, In, Outnormal fact-write path is connected; cut is unwired

For ID 11, Active is connected. For ID 12, Active is connected. For IDs 14 and 16, Succeeded is connected. An edge entering a journal node’s ordinary-looking but wrong state socket changes the requested journal state.

The unused CutDestination sockets are visible lifecycle obligations, not missing normal-flow edges. Lab 1 does not claim cut-safe behavior. Do not wire them to the terminating output as a guess.

Press Ctrl+S, close the questphase, and reopen it. Compare the graph against the exact generated figure. Node placement may differ; IDs, types, sockets, payloads, and edges must not.

8. Register the resources with ArchiveXL

Choose File > New File, select the ArchiveXL category and ArchiveXL file, name it CQA_Lab01_OneShot.archive.xl, and select Create. WolvenKit places it under source\resources.

Enter this YAML exactly:

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

journal:
- mod\cqa\cqa001\journal\cqa001.journal

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

Save the file. The three entries have separate jobs: attach the executable phase beneath the vanilla quest root, merge the journal, and register the English onscreen strings. The parent path is a reference; do not extract or add base\quest\cyberpunk2077.quest to the project.

Your authored source tree should now contain:

source\
├── archive\mod\cqa\cqa001\
│   ├── journal\cqa001.journal
│   ├── localization\en-us\onscreens\cqa001.json
│   └── phases\cqa001.questphase
└── resources\CQA_Lab01_OneShot.archive.xl

9. Compare with the completed checkpoint

Open the completed .cpmodproj in a second WolvenKit instance, or close the start project and open the completed project after saving. Compare semantic structure, not binary bytes or CR2W handle numbers.

Check all of the following:

  1. the three depot paths and ArchiveXL filename match;
  2. the journal has the six exact types and IDs in one chain;
  3. both journal localization keys resolve to the two secondary keys;
  4. the questphase has IDs 0, 1, and 10–16, with no extra nodes;
  5. the nine connections match the socket table above;
  6. both outer questphase arrays are empty;
  7. the condition, delay, fact-write, journal path, notification, and tracking values match the property tables;
  8. the ArchiveXL YAML matches by registration meaning and depot path.

If you need a text diff, Project Explorer can export a mod-owned CR2W file to JSON under the mirrored source\raw path. Use that export only as a review artifact. Do not repair the lab by editing raw JSON, and do not compare HandleId allocation as if it were graph identity.

10. Validate, install, and inspect the install

With all tabs 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 every validation error owned by this project before continuing;
  5. close Cyberpunk 2077;
  6. choose Build > Install and wait for packing and installation to finish;
  7. read WolvenKit’s Log panel rather than treating the button press as proof.

Use the normal Install command for this ArchiveXL project. Do not choose Install as REDmod or a hot-reload command. The full install, launch, log, and test procedure is collected in Install, test, and reset.

The vanilla journal descriptor and root parent are deliberate references; they need not be copied into the project. Treat any other unresolved reference or validation error as a stop condition, even if it does not spell out one of the three mod depot paths.

For the start checkpoint, verify these exact installed files beneath the game directory:

archive\pc\mod\CQA_Lab01_OneShot_Start.archive
archive\pc\mod\CQA_Lab01_OneShot.archive.xl

If you install the completed checkpoint instead, the archive is named CQA_Lab01_OneShot.archive. The loose .archive.xl must be present beside the archive in either case. A packed archive alone cannot register the root, journal, or localization resources.

After launching the game once, inspect:

red4ext\plugins\ArchiveXL\ArchiveXL.log
red4ext\logs\red4ext.log
red4ext\logs\game.log
r6\logs\redscript_rCURRENT.log

Search the ArchiveXL log for CQA_Lab01_OneShot.archive.xl, cqa001, or an error naming one of the registered depot paths. Confirm that RED4ext loaded ArchiveXL and that redscript did not report a new dependency/load error. Registration without errors is evidence about registration, not proof that the quest route executed.

11. Test and reset

Continue with Install, test, and reset. Use the archive built from your start project, CQA_Lab01_OneShot_Start.archive, and the shared CQA_Lab01_OneShot.archive.xl registration file.

That guide covers the first load, mid-flow reload, completed reload, reinstallation, clean replay, logs, and removal. Begin from a manual save made before any version of cqa001 was installed. Changing its completion fact alone does not reset the journal or saved graph state.

The intended first run activates First Signal and Wait for the signal., then succeeds after about ten real-time seconds. This behavior remains Experimental until tested. The terminating output has no separate visible indicator; infer it from the graph, successful journal state, and absence of reactivation.

To compare your build with the supplied completed checkpoint, close the game, remove the _Start archive, install the completed project, and repeat from the same untouched baseline. Keep only one checkpoint’s archive installed.

Failure routing

SymptomInspect first
No quest activationInstalled .archive.xl, its quest.phases path, ArchiveXL log, and the save’s completion fact
Quest title or objective text is blankJournal localization key versus onscreen secondaryKey
Objective stays activeID 13.Out to ID 14.Succeeded, not 14.Active
Quest finishes but repeatsID 15 exact fact write and the fact value on the reloaded save
First run works; replay looks inconsistentJournal state and other save-backed data left by the earlier run
WolvenKit graph looks different after reopenCompare IDs, node types, sockets, and edges; ignore layout and handle allocation

Serialization, validation, packing, ArchiveXL registration, and runtime behavior are different evidence steps. Keep the Experimental label until the clean-save matrix—not merely the successful build—has been retained.

Lab sequence: All labs · Previous: Lab 1: First Signal · Next: Install, test, and reset.