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 5: First Contact

Lab 5 combines the systems from the first four labs into one small contact encounter. A registered root calls an external child. The child activates a one-entry community, waits for the actor and player to become ready, starts a one-line scene through its named entry, consumes the named scene exit, and delays cleanup until V has left the outer area.

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

Implementation status: both supplied checkpoints contain eleven mod-owned CR2W resources plus one WEM. The CR2W pairs are Structurally validated with WolvenKit 8.19.0; the WEM’s container, format, duration, path, and hash are checked separately. Mounting, actor materialization, scene playback, subtitle and VO lookup, named return, stream-away/return, post-contact_done reload, completed reload, pre-scene save loads, and cleanup are covered by the Lab 5 test procedure.

What the lab demonstrates

registered root -> cqa005_completed == 0?
  False -> terminate
  True  -> activate First Contact
        -> enter external child through In1
             activate meet objective and map pin
             Activate contact/default
             wait CharacterSpawned > 0 for the whole community
             wait until V is inside the broad setup area
             create checkpoint
             enter scene through start
             contact says one externally localized line
             scene exits through contact_done
             succeed meet; retire pin; activate leave
             wait until V is outside the cleanup area
             Deactivate the whole community
             succeed leave; return through Out1
        <- succeed quest; set cqa005_completed = 1; terminate

The two waits before the scene solve different races. CharacterSpawned observes the community, while IsInside #cqa005_tr_setup controls player placement. Neither is a substitute for the other. The outer cleanup wait keeps the actor alive after the named scene exit and avoids removing the contact in front of the player.

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

Other versions may serialize different wrappers or produce different runtime behavior.

Prerequisites and downloads

Complete Lab 4, then read:

Do not install both checkpoints. They register and pack the same depot paths. For frozen runtime acceptance, establish the two documented untouched manual originals, each of which has never loaded any CQA Lab 1–5 candidate. Case 1 then creates the exact pre-scene, post-contact, and completed manual seeds under the unchanged canonical candidate; later cases use byte-identical full-slot clones. Labs 3 and 4 share this site, and removing their files does not erase their saved state. A console reset of cqa005_completed likewise does not remove save-backed quest, journal, scene, community, actor, or streamed-world state. See the test chapter for the five capture IDs and fan-out.

Twelve runtime artifacts

#ArtifactDepot pathOwner or purpose
1Root questphasemod\cqa\cqa005\phases\cqa005.questphaseRegistration, one-shot guard, root prefab, child call, quest completion
2Contact child questphasemod\cqa\cqa005\phases\cqa005_contact.questphaseMeet, readiness, scene handoff, leave, and cleanup lifecycle
3Scenemod\cqa\cqa005\scenes\cqa005_first_contact.sceneActors, screenplay item, line event, graph, entry, and named exit
4Journalmod\cqa\cqa005\journal\cqa005.journalQuest, phase, two objectives, and contact map pin
5Onscreen localizationmod\cqa\cqa005\localization\en-us\onscreens\cqa005_onscreens.jsonQuest, objective, and map-pin text
6Subtitle mapmod\cqa\cqa005\localization\en-us\subtitles\cqa005_subtitles_map.jsonRegistered route to the subtitle entries resource
7Subtitle entriesmod\cqa\cqa005\localization\en-us\subtitles\cqa005_subtitles.jsonMale and female text for locstring 9638591835734011695
8VO mapmod\cqa\cqa005\localization\en-us\vo\cqa005_vo.jsonMale and female audio lookup for the same locstring
9WEMmod\cqa\cqa005\localization\en-us\vo\contact_i_85c3283507e7ef2f.wemPrebuilt synthetic spoken audio
10Streaming blockmod\cqa\cqa005\world\cqa005_first_contact.streamingblockQuest and AlwaysLoaded sector descriptors
11Quest sectormod\cqa\cqa005\world\cqa005_first_contact.streamingsectorSetup/cleanup triggers, AI spot, and compiled community area
12AlwaysLoaded sectormod\cqa\cqa005\world\cqa005_always_loaded.streamingsectorScene marker, map marker, and community registry

The WEM is not a CR2W file and has no CR2W-JSON counterpart. Each checkpoint therefore contains eleven raw/cooked CR2W pairs and one archived WEM. Its source WAV and production record live outside the WolvenKit source tree so they cannot be packed accidentally.

Registration versus indirect dependencies

ArchiveXL registers six roots:

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

journal:
- mod\cqa\cqa005\journal\cqa005.journal

localization:
  onscreens:
    en-us:
    - mod\cqa\cqa005\localization\en-us\onscreens\cqa005_onscreens.json
  subtitles:
    en-us:
    - mod\cqa\cqa005\localization\en-us\subtitles\cqa005_subtitles_map.json
  vomaps:
    en-us:
    - mod\cqa\cqa005\localization\en-us\vo\cqa005_vo.json

streaming:
  blocks:
  - mod\cqa\cqa005\world\cqa005_first_contact.streamingblock

The child phase, scene, subtitle entries, WEM, and two sectors are archived dependencies. They are reached respectively by phaseResource, sceneFile, the subtitle map, the VO map, and the streaming-block descriptors. Registering those indirect resources as additional roots changes the ownership model and is rejected by the supplied validator.

Root and child ownership

The registered root declares one prefab:

#cqa005_pr_first_contact

The child has phasePrefabs: [], and the external phase node has phaseInstancePrefabs: []. The root’s world-side expansion is:

$/mod/cqa/cqa005/#cqa005_pr_first_contact
  #cqa005_tr_setup
  #cqa005_tr_cleanup
  #cqa005_spot_contact
  #cqa005_com_contact
  #cqa005_sm_contact
  #cqa005_mp_contact

The two marker nodes and registry live in the AlwaysLoaded sector. The two triggers, AI spot, and compiled area live in the finite Quest sector. Root ownership does not make every nested node AlwaysLoaded; the block descriptors still decide sector lifetime.

Exact root graph

IDRED node typeDecisive payload
0questInputNodeDefinitionRoot In1 interface
1questOutputNodeDefinitionTerminating Out1
10questConditionNodeDefinitioncqa005_completed Equal 0
11questJournalNodeDefinitionSet First Contact quest Active
12questPhaseNodeDefinitionSoft cqa005_contact.questphase; null inline graph; empty instance prefabs
13questJournalNodeDefinitionSet First Contact quest Succeeded
14questFactsDBManagerNodeDefinitionSet cqa005_completed = 1 exactly

Its seven edges are:

0.Out -> 10.In
10.False -> 1.In
10.True -> 11.Active
11.Out -> 12.In1
12.Out1 -> 13.Succeeded
13.Out -> 14.In
14.Out -> 1.In

The completion fact is deliberately written only after the child returns and the quest reaches succeeded state. This is the candidate’s exact policy, not a universal ordering rule.

Exact contact child

IDRED node typePurpose
0questInputNodeDefinitionReceive In1
1questOutputNodeDefinitionReturn terminating Out1
10questJournalNodeDefinitionActivate meet objective
11questMappinManagerNodeDefinitionActivate contact pin
12questSpawnManagerNodeDefinitionActivate contact/default
13questPauseConditionNodeDefinitionWait CharacterSpawned Greater 0, entireCommunity: 1
14questPauseConditionNodeDefinitionWait player IsInside #cqa005_tr_setup
15questCheckpointNodeDefinitionCreate the pre-scene checkpoint
16questSceneNodeDefinitionEnter start; continue only from contact_done
17questJournalNodeDefinitionSucceed meet objective
18questMappinManagerNodeDefinitionInactivate contact pin
19questJournalNodeDefinitionActivate leave objective
20questPauseConditionNodeDefinitionWait player IsOutside #cqa005_tr_cleanup
21questSpawnManagerNodeDefinitionDeactivate with entry/phase None for the whole community
22questJournalNodeDefinitionSucceed leave objective

The fourteen edges form one ordered chain from 0.Out to 1.In. Node 16 has exactly five sockets: CutDestination, input start, output contact_done, and the unconnected Default INT and Default RET outputs. There is no invented end output. The child continues only from the exit name actually published by the scene.

Community and world identity contract

The canonical contact is a generic Tyger Claws record, not a unique story-managed actor:

characterRecordId:
  Character.jpn_tyger_claws_biker2_ranged2_copperhead_wa
appearance: default
entry: contact
phase: default
workspot:
  base\workspots\common\ground\
  generic__stand_ground_cigarette__smoke__01.workspot

The registry sets entryActiveOnStart: 0, one quantity, and a non-sequence time period. Quest logic activates it explicitly.

Three 64-bit identity domains stay distinct:

  1. the compiled area’s sourceObjectId equals the registry item’s communityId;
  2. the registry node placement has a different numeric world identity;
  3. the AI spot’s global ID is repeated by the compiled area’s spotNodeIds and registry workspotsPersistentData.

All three are derived from full NodeRef-aware source strings. They are not plain FNV hashes of debug labels, and the # alias marker has RED4-specific hash behavior. The registry’s numeric placement identity is also not an ordinary string entry in the sector’s nodeRefs array.

Check the contact for spawn, passivity, scene acquisition, cleanup, and visible workspot animation at the supplied location.

Exact scene contract

The completed scene graph has four nodes and three edges:

[1] Start -- output 0/0 --> [2] Section input 0/0
          \-- same output --> [4] PuppetAI input 0/1
[2] Section -- output 0/0 --> [3] End (Terminating)
[4] PuppetAI -- output 0/0 --> no destination

The PuppetAI branch places the contact in the Cinematic AI tier and is fire-and-forget. It does not delay the named exit. Section output stamp 1/0 is the deliberately unconnected cancel route. startNodes contains node 1, endNodes contains node 3, entry start targets node 1, and exit contact_done targets node 3.

Actor 0, contact, uses community acquisition for entry contact. Player actor 1, V, uses findInContext with Character.Player_Puppet_Base. Their performer IDs are 1 and 257; both select lipsync slot 0. The scene retains one vanilla lipsync animation-set reference by depot path without redistributing that resource.

The screenplay store contains one scnscreenplayDialogLine spoken by actor 0 to actor 1, with gender mask 3. One scnDialogLineEvent points to that item. The line is:

All clear. Keep moving.

Its unsigned locstring ID is 9638591835734011695. The section lasts the audio duration plus 400 ms. The embedded locStore remains typed and empty: spoken text and sound come from external localization resources.

The start checkpoint retains the same actors, lipsync reference, entry, exit, debug scaffold, and typed empty stores, but its graph is only Start 1 to terminating End 3. Neither start phase graph invokes that scene shell.

Spoken-line lookup

scene line locstring 9638591835734011695
  -> registered subtitle map
       -> archived subtitle entries
            femaleVariant = maleVariant = "All clear. Keep moving."
  -> registered VO map
       -> archived WEM for femaleResPath and maleResPath

The checkpoint includes a synthetic WAV and its prebuilt WEM. Use the supplied WEM for the lab; see External VO, WEM, and lipsync when preparing your own audio.

Geometry and delayed cleanup

The example reuses the checked Allen Street center from Labs 3 and 4:

OwnerCenterGeometry
Setup trigger(-1000.02, 1497.2208, 2.3)25 m circumradius, 16 points, 12 m high
Cleanup trigger(-1000.02, 1497.2208, 0.3)110 m circumradius, 20 points, 16 m high
Contact AI spot(-1000.02, 1497.2208, 6.957)cigarette workspot, yaw 88.6 degrees
Scene and map markers(-1000.02, 1497.2208, 8.3)yaw 88.6 degrees

The broad setup area makes a fast arrival less likely to outrun actor readiness. The much larger cleanup area keeps the contact present while V can still see the meeting point. These dimensions are a candidate design choice, not a universal safe radius.

Common failure modes

SymptomCheck first
Quest never appearsRoot registration, archive pair, ArchiveXL and RED4ext logs, clean starting save
Objective appears but contact does notQuest-sector streaming, community/source join, entry and phase names, spot ID joins, CharacterSpawned payload
Contact spawns hostileGeneric character record, AI state, absence of unrelated combat stimuli, exact installed build
Contact exists but scene does not startSetup trigger, scene marker, actor acquisition reference, named start socket
Mouth moves but there is no subtitle or soundLocstring equality across scene, subtitle entries, and VO map; registered map paths; archived WEM path
Line plays but quest stallsScene exit contact_done, End 3, quest scene-node output name, unconnected default outputs
Contact disappears in viewCleanup IsOutside radius and deactivation order
Completed save starts againcqa005_completed, write order, exact installed candidate, and original save history

Lab sequence: All labs · Next: Author First Contact in WolvenKit.