Scene Node Definitions

✂️Cut Control

scnCutControlNode

What it does

The scnCutControlNode is a fundamental logic gate in the scene system. Its one and only function is to act as a simple, high-speed Result-Router. It's a signal splitter.

The node itself is "dumb," stateless, and contains no internal logic or data fields. Its power comes from its interaction with the signals it receives. Signals can be tagged with a SUCCESS or FAILURE state by a "smart" node that sent it.

If you're familiar with programming, a Cut Control is basically an if-else statement that operates the check on the signal.

The CutControlNode's job is to inspect this tag on the incoming signal and route the execution flow down one of its two dedicated paths. This provides designers with a clean, reusable component to create conditional branches based on the outcome of a gameplay action or check.

Why the Name "CutControl"?

The name can be confusing. It does not mean it can only "cut" as in interrupt a node. Think of it like using scissors on a wire - the Cut Control node literally cuts the signal into two: the true signal via Out0 and the false signal via Out1.

Sockets

Inputs

Socket Name (ID)
Type
Description

In (0,0)

Input

The single entry point. It receives a signal that has been tagged with a SUCCESS or FAILURE state by an upstream node.

Outputs

Socket Name (ID)
Recommended Editor Label
Description

Out0 (0, 1)

Success / True

The path taken when the incoming signal is tagged with SUCCESS.

Out1 (1, 0)

Failure / False

The path taken when the incoming signal is tagged with FAILURE.

The Source of the Logic: "Smart" Nodes

The conditional check does not happen inside the CutControlNode. It happens in an upstream "smart" node that then generates the tagged signal. The most common state producers are:

  1. scnChoiceNode: A specific dialogue option can have a condition (like a stat check or payment) attached to it as a property. When the player selects that option, the ChoiceNode performs the check and tags its output signal with the result.

  2. scnQuestNode -> Condition node: sometimes a Condition node is set upstream and at a later point, the signals are converged into a single output (via a Hub) - which then again at a later point is split into the true/false signals via CutControlNode

Examples

Example 1: Narrative Branching (The Lifepath Check)

This is the clearest example of the node's primary purpose. Scene: base/open_world/street_stories/watson/kabuki/sts_wat_kab_04/scenes/sts_wat_kab_04_receptionist.scene

  • The Goal: Show a different version of a conversation based on V's Lifepath.

  • The Mechanism:

    1. The player makes a dialogue choice. A questConditionNode upstream checks the player's lifepath and fires a signal tagged SUCCESS for Corpo or FAILURE for others.

    2. The CutControlNode [84] receives this tagged signal.

    3. It routes the flow:

      • Out0 (Success) leads to Section [15], the professional "Corpo" dialogue.

      • Out1 (Failure) leads to Section [28], the rougher "Streetkid" dialogue.

Example 2: Looping Dialogue State (The Braindance Dealer)

This shows how the node is used to control a looping conversation. Scene: base/quest/main_quests/part1/q105/scenes/q105_04c_braindance_dealer.scene

  • The Goal: Keep the player in a conversation until they successfully purchase the required item.

  • The Mechanism:

    1. After the player makes a choice, a linked questConditionNode checks if the objective is complete.

    2. It sends a SUCCESS or FAILURE tagged signal to the CutControlNode [1437].

    3. The CutControl routes the flow:

      • Out0 (Success) breaks the loop and ends the conversation.

      • Out1 (Failure) routes the flow back to the start of the idle/choice loop, preventing the conversation from ending prematurely.


🔀Flow Control

scnFlowControlNode and questFlowControlNodeDefinition

A compact gating tool that counts how many signals arrive while it is open and how many arrive while it is closed. It is a very stateful node. It is not dumb.

You steer it in two ways:

  • Window parametersopensAt / closesAt – an automatic first-N / next-M limiter.

  • Control pinsOpen / Close / Switch – instant manual override.

Because the node exists in both the Scene player and the Quest system, its counters live in different places, but the behaviour you see as a modder is identical.

What it does:

It maintains three state variables (or facts)

  • A count of signals received while the gate is open (let's call this internal counter: openCounter)

  • A count of signals received while the gate is closed (let's call this internal counter closedCounter)

  • The current open/closed state (this is stored in the node property: isOpen)

Every time a signals hits In the node of a Flow Control:

It checks the isOpen property. One of the following things happen:

  1. If it is set to true (i.e. it's opened) then the openCounter is incremented.

    1. Then a simple range check is done: has the openCounter we just incremented reached the closesAt yet?

  2. If it is set to false (i.e. it's closed) then the closeCounter is incremented

    1. Then a simple range check is done, has the closeCounter we just incremented reached the opensAtyet?

If the answer is “No” to either question → the gate forwards the signal and keeps its current isOpen state.

If the answer is “Yes” → the gate flips its isOpen state first and then re-checks:

  • if the currrent final flipped state = open → it forwards the signal via it's output socket

  • or if the final state is closed → it swallows/does not forward the signal

What do the sockets do then? They are overrides. You can just not use opensAt and closesAt params, and use Flow Control as a simple 'latch' with the sockets alone.

The Sockets always win

  • Opensets state = open.

  • Close sets state = closed.

  • Toggletoggles the state.

Scope:

  • Scene runtime stores the counters in the scene resource and are reset outside the scene

  • Quest runtime stores them in a fact scoped to the Phase that owns the node

If you know how to code, you can also understand the Flow Control with this Python snippet:

class FlowControl:
    def __init__(self, opens_at: int = 0, closes_at: int = 0,
                 start_open: bool = False):
        self.opensAt      = opens_at
        self.closesAt     = closes_at
        self.isOpen       = start_open          # latch flag
        self.openCounter  = 0                   # signals while open
        self.closedCounter = 0                  # signals while closed
        self._override    = None                # None / True / False

    # ─ pin handlers ────────────────────────────────────────────────
    def pinOpen(self):
        self._override = True                   # force state for THIS frame

    def pinClose(self):
        self._override = False

    def pinSwitch(self):
        self._override = not self.isOpen

    # ─ main entry: returns True if signal forwarded ─────────────────
    def signal(self) -> bool:
        # 1) apply any override that came in earlier this frame
        if self._override is not None:
            self.isOpen = self._override
        self._override = None                   # override lasts one frame

        # 2) bump the appropriate counter
        if self.isOpen:
            self.openCounter += 1
            # 3) test open-side limit
            if self.openCounter >= self.closesAt and self.closesAt != 0:
                self.isOpen = False             # flip latch
        else:
            self.closedCounter += 1
            # 3) test closed-side limit
            if self.closedCounter >= self.opensAt:
                self.isOpen = True              # flip latch

        # 4) forward or swallow
        return self.isOpen

Sockets

Socket
Scene flavour
Quest flavour
Notes

In

Signal you want to gate

Out

Forwarded signal (if gate passes)

Open

should work¹

Signal → state = open

Close

should work¹

Signal → state = closed

Switch

should work¹

Signal → state toggles

CutDestination

Standard interrupt used when you want to interrupt/bypass the entire check

should work¹ : This is untested but it should work. Existing scene files never never uses the sockets on a scene Flow Control node. But it should be easy to verify! If you do, please update this part of the guide or let us know in #quest-and-scenes in the Cyberpunk discord.

Key properties

Name
Meaning
Typical values

opensAt

Lower limit checked while gate is closed

0 (let the very first pulse open)

closesAt

Upper limit checked while gate is open

1 (one-shot), 2 (two-shot), 0 (infinite)

isOpen

Cached flag (true / false) saved with the scene/phase

You can pre-set to open or closed

Examples & Use-cases

Use-case
Scene setting
Quest setting
Wiring sketch

One-shot VO – play once, never again

opensAt 0 / closesAt 1

same

Trigger → FlowCtrl → Section VO

Dual-shot – play twice, then stop

0 / 2

same

Distance Pause → FlowCtrl → animation

Auto-cap at N, but re-arm later

0 / N, sockets optional

same + QuestEvent → Open

Timer loop → FlowCtrl → bark Section

Toggle every signal

numbers default, wire same signal to In & Switch

Event → (split) → Switch & In

Scene “bump” two-shot

0 / 2

n/a

Distance ≤ 2 m → 100 ms Pause → FlowCtrl → bump VO + anim

Scene capped bark loop

Two gates: [0-2) and [2-3)

n/a

Randomizer → Hub → GateA / GateB → Pause → loop-back

Phase-scoped call-cap

n/a

opensAt 0 / closesAt 2 (no sockets)

PhaseOut → FlowCtrl → Output call

Manual latch

sockets only, numbers 0/0

QuestEvent.On → Open, QuestEvent.Off → Close

Choosing between numbers and sockets

Want
Easiest choice

“Fire a fixed N times, then never again.”

Just set opensAt / closesAt and ignore sockets.

“Enable/disable it on command.”

Leave numbers at 0 / 0 and wire Open / Close sockets.

“Cap at N but allow re-arm.”

Window [0-N), plus Open pin to re-arm trigger.

Checklist

  1. Scene logic – drop Flow Control where you need “play this node only the first N times.”

  2. Quest logic – use it as a lightweight latch; sockets give you full control, numbers give you auto-limits.

  3. Remember: the counters are scoped within a scene instance (for scenes) or the Phase node (for quests) ends.


🌐Hub

What it does

The Hub node is one of the simplest but most essential tools for organizing scene graphs. Its sole function is to be a signal merger or funnel. It takes any number of incoming execution paths and combines them into a single, unified output path.

Like the CutControlNode, the Hub is a "dumb," stateless node. It contains no internal logic. It doesn't care which input socket received a signal or how many signals it has received; it simply fires a signal from its Out socket every time any of its In sockets are triggered.

While the Hub's main job is to merge inputs, it's important to remember that its single Out socket can be connected to multiple downstream nodes. This allows a Hub to also act as a signal distributor, broadcasting a unified signal to several paths at once. This is often used to trigger multiple parallel events after a set of preceding conditions have been met and merged.

Sockets

Pin
Direction
Type
Description

In, In1, …

In

Execution

Any number of dynamically created input sockets. When you drag a connection to a Hub, a new input socket is automatically created.

Out

Out

Execution

A single output socket that fires whenever any input is triggered.

Examples & Use-cases

Example 1: Converging Logic Branches (The "Collector")

This is the most common use case: cleaning up the graph after several different logic branches have concluded.

  • The Goal: Ensure that multiple, mutually exclusive outcomes all lead to the same final step.

  • The Mechanism: As seen in the example image, a scene might have several FactsDBManager nodes that set different game states (holo_setup_active, holo_setup_started, holo_setup_ended). Each of these represents the end of a small logic branch. Instead of drawing a messy "spider web" of connections from all these nodes to a single End node, a Hub ([289]) is used as a collector. Each FactsDBManager connects to one of the Hub's input sockets. The Hub then provides a single, clean output connection to the final End node ([235]).

Hub example

Example 2: Re-joining after a Condition

  • The Goal: After splitting the execution flow with a CutControlNode (e.g., for a lifepath-specific dialogue line), you often need to bring the paths back together to continue with actions that are common to all outcomes.

  • The Mechanism:

    1. A CutControlNode splits the flow: Out0 (Success) goes to a "Corpo" dialogue Section, and Out1 (Failure) goes to the "Streetkid" dialogue Section.

    2. The Out sockets of both the "Corpo" and "Streetkid" Section nodes are connected to the input sockets of a single Hub.

    3. The Hub's single Out socket then connects to the next part of the scene that all players experience, regardless of which dialogue branch they took.

Checklist

  • Use a Hub whenever you need to merge two or more execution paths into a single path or when you need to split signals

  • It's an organizational tool: stateless, with no internal logic or properties.

  • It helps keep complex scene graphs tidy and easy to read by reducing visual clutter.

🚪Xor

scnXorNode

The Xor node (short for Exclusive OR) is a 'first-come, first-served' gate. It's designed to solve a common problem: what to do when multiple different events could trigger the same outcome, and you need to ensure that outcome only happens once.

It listens to all its inputs, but only allows the very first signal that arrives to pass through to its Out socket. Once it has fired, it enters a "latched" or "closed" state and will ignore all subsequent signals. This prevents unwanted "double triggers" from multiple sources.

Sockets

Pin
Direction
Type
Description

In, In1, ...

In

Execution

Any number of dynamically created input sockets.

Cancel

In

Out

Out

Execution

Fires a single time when the first signal is received on any In socket.

Examples & Use-cases

Example 1: Player Action vs. Timer (The Holocall Race)

  • Scene: ep1\quest\holocalls\alex\alex_holocall.scene

The Goal: A holocall is ringing. The scene must proceed if the player picks it up, OR if a certain amount of time passes and the player doesn't pick it up. We only care about whichever happens first.

  • The Mechanism:

    1. The flow is broadcast to two PauseCondition nodes simultaneously.

    2. PauseCondition [326] is a SystemCondition waiting for the player to perform a PhonePickUp.

    3. PauseCondition [22] is a TimeCondition acting as a timer (in this case, 4 seconds and 15 milliseconds).

    4. Both of these nodes feed into the inputs of the Xor node [104].

    5. Scenario A (Player is fast): The player picks up the phone. Node [326] fires, its signal passes through Xor [104], and the scene continues down the "answered call" path. A few moments later, the timer in [22] finishes. Its signal hits the already-fired Xor node and is swallowed, preventing the "missed call" path from also triggering.

    6. Scenario B (Player is slow): The timer in [22] finishes first. Its signal passes through Xor [104] and the scene proceeds down the "missed call" path. If the player eventually picks up the phone, the signal from [326] hits the Xor and is ignored.

Example 2: Player Action vs. Proximity Trigger (The Cryo-Freezer Reveal)

  • Scene: base\quest\side_quests\sq021\scenes\sq021_03_trailer_park.scene

The Goal: After the player agrees to talk, a welcome scene should trigger as soon as either the player or Sobchak enters the trailer. The scene must not trigger twice if they both enter.

  • The Mechanism:

    1. The player makes a Choice [1085]. The first option outputs to start two simultaneous checks.

    2. Path 1 (Check NPC): PauseCondition [685] checks if Sobchak is IsInside the trailer's trigger area.

    3. Path 2 (Check Player): PauseCondition [599] checks if the Player is IsInside the same trigger area.

    4. Both conditions feed into the Xor node [1098].

    5. The Xor's output starts the conversation Section [781].

  • Why the Xor is Necessary: The player and Sobchak can easily be inside the trigger area at the same time.

    • If a Hub were used, it would receive a signal from the player check and a signal from the Sobchak check, firing its output twice. This would cause the welcome dialogue in Section [781] to restart, creating a bug.

    • The Xor guarantees that the first entity detected - whether it's the player or the NPC, triggers the scene. The Xor immediately latches shut, and when the second entity is detected moments later, that signal is simply ignored. The conversation correctly starts only once.

Checklist

  • Use Xor whenever you need to ensure an action is triggered exactly once, especially when there are multiple possible triggers (e.g., player action, a timer, a proximity check).

  • It's a "one-shot" gate: it fires on the first signal it receives and then ignores everything else until it is reset.


🔗And

What it does

The And node is a synchronization point or a gatekeeper. Its purpose is to pause the execution flow until multiple, separate, parallel paths have all been completed.

It waits until it has received a signal on every single one of its input sockets. Only when the last required signal has arrived does the And node fire a single signal from its Out socket.

Sockets

Pin

Direction

Type

Description

In, In1, ...

In

Execution

The node will wait until a signal has been received on every one of these input sockets. The number of sockets is determined by how many connections are made to the node.

Out

Out

Execution

Fires a single time, only after all input sockets have received a signal.

Examples

Example 1: Waiting for Characters to Spawn

  • Scene: base/quest/side_quests/sq026/scenes/sq026_12_penthouse_gameplay.scene

This is the most common and critical use case for an And node: ensuring all necessary characters are present before a scene begins.

  • The Goal: Start a conversation in a penthouse, but only after two specific characters, Roxanne and Tom, have both finished spawning and are present in the scene.

  • The Mechanism:

    1. The execution flow splits to start two simultaneous checks.

    2. Path 1: PauseCondition [283] pauses the flow until the character roxanne has CharacterSpawned.

    3. Path 2: PauseCondition [281] pauses the flow until the character tom has CharacterSpawned.

    4. The outputs of both PauseCondition nodes are connected to the inputs of the And node [289].

    5. The Out socket of the And node connects to the next part of the scene (e.g., the main dialogue Section).

  • Why the And is Necessary: Spawning characters can take a variable amount of time. Without the And node, the scene's timing would be unreliable.

    • If you only waited for Roxanne to spawn, the conversation could start while Tom is still invisible or not yet in the world, leading to characters talking to empty space or other visual bugs.

    • The And node acts as the rendezvous point. It doesn't matter if Roxanne spawns first or Tom spawns first. The And node will patiently wait, holding the scene, until it receives signals from both spawn checks. Only then does it allow the scene to proceed, guaranteeing that all participants are ready and the scene can play out correctly.


Last updated