Maturity: Draft. How a mod spawns or chooses an NPC, makes it walk, turn and follow through the game's AI commands, makes it speak (its own voice or text), gives it a face, a gaze and a gesture, offers V dialogue choices and receives the answer, and cleans up so nothing reaches a save. Consolidated on 30 September 2026 from the decompiled 2.31 script bundle (redscript-cli 0.5.31, final.redscripts SHA-256 2119046f…ee86), the game's REDmod TweakDB sources, Codeware (v1.20.4, 613a1cb8), TweakXL (v1.11.4), ArchiveXL (v1.27.3), the Modding Docs at a54b0873, and installed mods read in place (Appearance Menu Mod 2.12.5 with its GitHub clone 5427235, Native Interactions Framework f1.05b with its clone 041f17e, keanuWheeze's InteractionUI module inside Immersive V Dialogue Expanded 1.1.0.0, Dark Future 2.0.3, Audioware 1.8.0, Immersive Food Vendors 1.2.2). Nothing on this page has runtime evidence yet. Grades follow the knowledge rules. The bridge design built on it, with provenance, commands, a first scenario and a test card, is NPC direction design. Crowd reactions, voicesets and overhead barks are on NPC reactions.
Game-script citations are paths inside the decompiled bundle; installed-mod citations are paths inside the mod's folder in the mod manager (mods/).
1. The short answers
| Question | Answer | Grade |
|---|---|---|
| Can a mod spawn an NPC that never reaches a save? | Yes: Codeware's DynamicEntitySystem with persistState and persistSpawn off writes nothing at save time and clears everything at world detach | source |
| Can it make an NPC walk somewhere? | Yes: AIMoveToCommand through the NPC's AI component, with Walk, Run or Sprint, a stop distance and a facing target | source; AMM ships it |
| Can it make an NPC say something? | In the NPC's own voice, only a line its voiceset has for a generic trigger; any text as a subtitle or overhead line | source |
| Can it offer V dialogue choices and learn the answer? | Yes, without a scene: add a hub to the game's own dialogue widget and read the player's choice keys; or author a .scene with a choice node | source (a shipping CET module); wiki |
| Can it play a gesture? | A facial reaction yes; a body gesture through a workspot carrier entity | source |
| Do crowd NPCs obey commands? | Unknown; crowd NPCs are driven by the crowd system and change AI role only once, per AMM | hypothesis |
2. Spawning and choosing
Arrows
- DynamicEntitySpec: record or template, appearance, position, flags, tags arrow to DynamicEntitySystem.CreateEntity
- DynamicEntitySystem.CreateEntity arrow to Entity stub + population system (streams by distance)
- Entity stub + population system (streams by distance) arrow to Spawned event: GetEntity(id)
- Save arrow to Codeware persistent state ("only persistState or persistSpawn specs")
- World detach (load, quit) arrow to All states, tags and listeners cleared
Mermaid source
flowchart LR
A["DynamicEntitySpec: record or template, appearance, position, flags, tags"] --> B["DynamicEntitySystem.CreateEntity"]
B --> C["Entity stub + population system (streams by distance)"]
C --> D["Spawned event: GetEntity(id)"]
E["Save"] -->|"only persistState or persistSpawn specs"| F["Codeware persistent state"]
G["World detach (load, quit)"] --> H["All states, tags and listeners cleared"]
- Spec and system:
DynamicEntitySpec { recordID | templatePath, appearanceName, position, orientation, persistState, persistSpawn, alwaysSpawned, spawnInView, active, tags };CreateEntity,DeleteEntity,IsSpawned,GetEntity,GetTagged,DeleteTagged, and tag listeners receivingCreated,Deleted,Spawned,Despawned,Deadsource Codewarescripts/,World/ DynamicEntitySpec.reds DynamicEntitySystem.reds,DynamicEntityEvent.reds. - Streaming: a record spawn registers an entity stub with the population system, honouring
spawnInViewandalwaysSpawnedsourcesrc/.App/ World/ DynamicEntitySystem.cpp:247-280 - Persistence is opt-in: save writes only specs with either persist flag; load respawns only
persistSpawn; world detach clears all; a non-persistent spec gets a transient entity id sourceDynamicEntitySystem.cpp:24-100, 282-325. - Records: crowd citizens derive from
Crowd_(NPC_ Base isCrowd = true, civilian attitude group,ReactionPresets.Civilian_, senses off at start); 122 records derive from it, several on Phantom Liberty templates resource REDmodNeutral characters/,bases/ base_ records.tweak:42-68 characters/. A TweakXL clone (npcs/ records/ crowds/ communities.tweak $base) can change such flags without touching the vanilla record source TweakXLYamlReader.cpp:8. Changing a vanilla record's flats at run time (as AMM does to arm its spawns) changes every NPC of that record for the session source AMMModules/.spawn.lua:588-594 - Friendly and unhurt:
GetAttitudeAgent().SetAttitudeTowards(player, AIA_;Friendly) GodModeSystem.AddGodMode(id, Immortal, n"Default")source AMMModules/,director.lua:1426-1427 Modules/.util.lua:906-916 - Choosing an existing NPC:
GameObject.GetNPCsAroundObject(range)sourcecore/. Protection checks onentity/ gameObject.script:715-731 ScriptedPuppetsourcecyberpunk/:puppet/ scriptedPuppet.script IsQuest()(3000),IsPlayerCompanion()(1693),IsBoss()(1299),IsVendor()(1336),IsCharacterPolice()(1398),IsCharacterChildren()(1414),IsCrowd()(1425),IsOnAutonomousAI()(1603, false when the AI story tier isCinematic); plusSceneSystemInterface.IsEntityInScene/IsEntityInDialoguesourceorphans.script:32250-32252andWorkspotGameSystem.IsActorInWorkspot. On objects of unknown type use only entity-level natives (the bridge 0.7 world-object rule, after a session-7 crash; game crashes). - Crowd NPCs walk traffic lanes owned by the crowd system (
CrowdMemberComponent:IsInCrowd,TryStopTrafficMovement,ChangeMoveType,AllowWorkspotsUsage) sourceorphans.script:24142-24175; AMM respawns a crowd NPC rather than change its role a second time sourceModules/.util.lua:871-893
3. AI commands
| Command | Key fields | Grade |
|---|---|---|
AIMoveToCommand | movementTarget / facingTarget (AIPositionSpec: an entity or a world position), movementType (Walk, Run, Sprint), desiredDistanceFromTarget, finishWhenDestinationReached, ignoreNavigation, useStart, useStop, rotateEntityTowardsFacingTarget | source orphans.script:44519-44540, 29704-29720, 2-6 |
AIFollowTargetCommand | target, desiredDistance, tolerance, stopWhenDestinationReached, movementType, lookAtTarget, matchSpeed, teleport | source orphans.script:47171-47188 |
AIRotateToCommand | target, angleTolerance, angleOffset, speed | source :47141-47150 |
AIHoldPositionCommand | duration | source :28790-28793 |
AITeleportCommand | position, rotation, doNavTest | source :47349-47356 |
AIUseWorkspotCommand | a placed workspot's workspotNode (node ref), jumpToEntry, entryId, moveToWorkspot, forceEntryAnimName, movementType | source :47358-47376 |
AIEquipCommand, AIUnequipCommand, AIJoinCrowdCommand | slot and item; none | source :47378-47394, 47190 |
- All derive from
AICommand { id, state }; moves addremoveAfterCombat,ignoreInCombat,alwaysUseStealthsource:25056-25066, 28774-28781. There is no voice-over AI command; speech is an event on the NPC source. - Send, track, cancel:
AIComponent.SendCommand,GetCommandState(NotExecuting, Enqueued, Executing, Cancelled, Interrupted, Success, Failure),IsCommandExecuting/IsCommandWaitingby class,StopExecutingCommand(cmd, success),CancelCommand(cmd),CancelCommandById,CancelOrInterruptCommand;AIHumanComponent.GetActiveCommandID(class)sourcecore/,components/ aiComponent.script:14-34, 977-983 orphans.script:276-284. The game's ForceMoveInCombat effector sends a move and, on cleanup, stops it if executing or cancels it if waiting sourcecore/.gameplay/ effectors/ quickhackEffectors.script:883-925 - AMM's Director chains teleport, move, arrival by distance (< 1 m), look-at, voice trigger, facial reaction, pose and a hold per node source AMM
Modules/. Arrival by distance suggests command state alone may not signal arrival hypothesis.director.lua:1151-1377
4. Speech
- Own voice:
GameObject.PlayVoiceOver(npc, trigger, …)queuesSoundPlayVo { voContext }; the voice's voiceset scene plays a random line for that trigger with audio, subtitle and lip sync sourcecore/(NPC reactions §3). AMM's Director offers 26 triggers source AMMentity/ gameObject.script:743-770 init.lua:2792-2830. - Text:
scnDialogLineDataonUIGameData.ShowDialogLine, typesRegular(bottom subtitle with the speaker's name),OverHead,OverHeadAlwaysVisible,Holocall,Narrator, …; hidden by id sourceorphans.script:7396-7410, 44905-44926(NPC reactions §4). No audio means no lip sync hypothesis. - Custom audio: Audioware's
AudioSystemExt.Play(event, entityID, emitter, lineType, settings)and emitters source Audiowarer6/; needs a consenting voice.scripts/ Audioware/ Ext.reds:11-36 - Holocalls are phone machinery plus an ordinary scene over it, started from a quest phase; the answer comes back as a fact wiki
modding-guides/(quest/ custom-video-holocalls.md holocall-phase-3-answer-wait.png).
5. Dialogue choices
Arrows
- Mod builds ListChoiceHubData (title, choices) arrow to Wrap InteractionUIBase.OnDialogsData: append hub
- Wrap InteractionUIBase.OnDialogsData: append hub arrow to Game's dialogue widget draws it
- Player: ChoiceScrollUp / Down, ChoiceApply arrow to Mod's input handler moves ActiveChoiceHubID / SelectedIndex, consumes the input
- Mod's input handler moves ActiveChoiceHubID / SelectedIndex, consumes the input arrow to Callback with the chosen index
Mermaid source
flowchart LR
A["Mod builds ListChoiceHubData (title, choices)"] --> B["Wrap InteractionUIBase.OnDialogsData: append hub"]
B --> C["Game's dialogue widget draws it"]
D["Player: ChoiceScrollUp / Down, ChoiceApply"] --> E["Mod's input handler moves ActiveChoiceHubID / SelectedIndex, consumes the input"]
E --> F["Callback with the chosen index"]
- Data:
UIInteractions.DialogChoiceHubs→ListChoiceHubData { id, activityState, flags, isPhoneLockActive, title, choices, timeProvider }→ListChoiceData { localizedName, type, inputActionName, captionParts, timeProvider };ActiveChoiceHubID,SelectedIndexsourceorphans.script:42023-42026, 54489-54517. Codeware addshubPrioritysource Codewarescripts/.Base/ Addons/ ListChoiceHubData.reds InteractionUIBaselistens withOnDialogsData,OnDialogsActivateHub,OnDialogsSelectIndex,OnInteractionDatasourcecyberpunk/.UI/ interactions/ interactionUIBase.script:32-89 - Runtime hubs (no scene): keanuWheeze's InteractionUI module overrides
OnDialogsDatato append its hub, handles the three choice actions fromPlayerPuppet.OnAction, sets the active hub and index on the blackboard, consumes what it handles, and guardsOnDialogsSelectIndex,OnInteractionDataanddialogWidgetGameController.OnDialogsActivateHubsource…/. Six installed CET mods ship it.ImmersiveVDialogueExpanded/ modules/ interactionUI.lua:117-413 - In redscript:
GameObject.RegisterInputListener(listener, n"ChoiceApply")is how the tutorial popup hears the apply key;ListenerAction.GetName/,GetType ListenerActionConsumer.ConsumesourcegameObject.script:152,cyberpunk/,UI/ popups/ tutorialGameController.script:105-108 orphans.script:31981-32023. Whether a listener sees the scroll actions and whether consuming stops the native handling is hypothesis. - Reading any pick:
UIInteractions.LastAttemptedChoice(InteractionAttemptedChoice), as Dark Future does sourceDFInteractionSystem.reds:405-408, 1088-1101. - Scene choices:
scnChoiceNodeoptions, one output socket each, text fromscreenplayStore.options[].locstringId, optional actor reminders wikimodding-guides/(Choice Nodes; its example image shows the ordinary widget). Mods start scenes from an ArchiveXL-injected phase through facts and hear the end through anquest/ scene-node-definitions.md ActionEventon the player; NIF patches scenes at load to shift choice-node ids, retarget node refs and swap option text source NIFmodules/,utils/ resourceHelper.lua:47-146, 199-349 modules/. Custom scene text is registered with ArchiveXLclasses/ interaction.lua:88-142 localization: subtitles:source ArchiveXLLocalization/; resource Immersive Food Vendors.Config.cpp:8-36 - Runtime hub versus scene: a runtime hub needs no authoring and touches no save; a scene adds the conversation state and camera, timed choices and reminders, voiced lines with lip sync and timeline animations, at the cost of authoring, an injected phase and facts in saves (quests and story §2).
6. Face, gaze and gestures
- Face:
AnimFeature_applied asFacialReaction { category, idle } FacialReactionsourceorphans.script:32382-32387; AMM's labelled pairs (joy 3/5, smile 3/6, sad 3/3, surprise 3/8, anger 3/1, disgust 3/7, fear 3/11, interested 1/3, neutral 2/2) source AMMinit.lua:2832-2857. - Gaze:
LookAtAddEvent.SetEntityTarget(target, n"pla_, style, limits, head and chest parts; removed withdefault_ tgt", offset) LookAtRemoveEvent.QueueRemoveLookatEvent(owner, event)sourcereactionComponent.script:3539-3600,core/; AMMevents/ lookAtEvents.script:2-10 Modules/.util.lua:762-804 - Gestures:
WorkspotGameSystem.PlayInDeviceSimple(carrier, npc, …)thenSendJumpToAnimEnt(npc, clip, instant);StopInDevice,SendFastExitSignalsourceorphans.script:18381-18420. AMM spawns its own carrier entity and catalogues 43,963 clips per rig source AMMModules/; resource itsanims.lua:328-400 db.sqlite3.
7. Safety and clean-up
- Refuse in tier-3+ scenes, dialogue, combat, vehicles and busy states; never direct protected NPCs (§2).
- Non-persistent spawns never reach a save and vanish at a load source (§2); a save lock covers the rest.
- Release: cancel or stop commands, hide lines, withdraw a hub, remove look-ats, reset faces, stop workspots, delete by tag (AMM teleports its actors behind V first) source AMM
Modules/.director.lua:1051-1091 - No facts or quest phases are needed for any of the runtime routes; the scene route adds both.
Open questions
- Does a TweakXL clone of a crowd record with
isCrowd: falsetake commands like a named NPC? - Is
AICommandState.Successreported on arrival? - Does a redscript input listener see and consume the choice actions while a dialogue hub is shown?
- Which reaction preset keeps a spawned actor calm and quiet to crime but still expressive?
- Does a spawned actor's own proximity reaction fight a mod's look-at and lines?
- Does the
Holocallsubtitle style render with no call in progress? - Which workspot clips play on every rig, and what is the smallest carrier resource that plays them?
Related pages
NPC reactions · Quests and story · Player control · Lip sync · Facial expressions · World and streaming · Runtime access · NPC direction design </content> </invoke>