A readable catalogue of Wolfenstein II's Kiscule node types, for modders who want to wire a custom map's logic rather than just reading Kiscule Scripting's container-format writeup. Built from re_probes/kisculeref/catalogue.json — every node type, every port, every parameter, and every wiring statistic measured across all 2,408 retail scripts, 70,274 node instances, 178,559 edge ends, cross-checked against the engine's own RTTI class table. Full report: Research-Report-R3-Kisculeref.
This page is a curated summary, not the JSON — it groups nodes by what a modder actually uses them for, names typical wiring with real retail counts, and flags which ones matter for a custom map. For a node not covered here, or for exact per-port numeric ranges, read catalogue.json directly (992 KB, re_probes/kisculeref/) or use python tools/kiscule.py --signature <NodeTypeName>.
Grading: everything below is measured — a node's ports, parameters, and wiring counts come from parsing every retail script, not a guess. What is not measured: whether any of the "unused" classes (§7) actually work if added to a script by hand, and most engine-side semantics beyond name/base-class/wiring pattern. The game was not started for this catalogue; see TNC Console Unlock §4 for the one place a Kiscule node (Command) ties directly into console-command execution.
0. The shape of a node
Every node has ports of three kinds:
- Regular (
InputRegular/OutputRegular) — an execution pulse, like a wire carrying "now". - Variable (
InputVariable/OutputVariable) — a value (bool, int, float, string, vector, entity reference, list). Every parameter is also exposed as a Variable port pair of the same name, so a value can be wired in instead of typed as a constant. - Notification (
OutputNotification) — an event output, functionally a Regular output that fires asynchronously from something the engine observed (damage taken, a volume entered, a trigger fired).
205 node types are used in retail; by RTTI base chain, 153 inherit directly from idKisculeInstanceNode, 29 directly from idKisculeNodeNotification (the ~20 *Notification listener nodes, §2.1), and 23 indirectly (the typed idKisculeVariableNode<T> template family — Bool, Int, Float, EntityReference, ListEntityReference, and the five NamedVariable* globals). A further 102 node classes exist in the engine but are used in zero retail scripts (§7 covers the 13 most relevant to custom-map work).
Three properties bits on a port are behaviourally characterized (not proven from source, no engine access):
| Bit | Correlates with | Measured |
|---|---|---|
0x1 |
a per-instance, optional/variadic port rather than a fixed core one | 95.4% of 8,899 occurrences on non-core ports |
0x4 |
exclusive to FlowFlagCheck's dynamically-named per-flag ports |
176/176 occurrences, 0 elsewhere |
0x20 |
the port was never wired in any retail script | 100% both directions, 1,817 occurrences, all 0 edges — and not just the visible=false flag in disguise (88% of them are visible=true) |
1. Spawn and AI waves
| Node | Instances / scripts | Ports | Notes |
|---|---|---|---|
AiKilledNotification |
157 / 102 | Killed, DeathDone (notifications); listenedEntities (in var) |
Kill-counter input for wave logic. 73% of instances filter by entity — 84 with exactly one EntityReference wired to listenedEntities, 29 with exactly two, one outlier with eight (the multi-edge idiom, §0); 34 instead wire one ListEntityReference; the remaining 27% listen for any AI kill, unfiltered. |
PlayerStartNotification |
76 / 46 | Start, Respawned, Spawning |
Fires once per idPlayerStart chosen at map load. maxNotificationCount = -1 (unlimited) in 76/76 retail uses. |
AISpawnNotification |
8 / 7 | AI Spawned, Wave empty, Spawner empty |
Fired by an idTarget_AISpawn map entity (not kiscule) when it spawns — the listener side, not the spawner. |
ActionAISpawn |
1 / 1 | Activate, Deactivate, Spawn; params maxActiveAIs, maxNumOfSpawn, interval, spawnScenepoints, AIs |
Retail almost never spawns AI from inside kiscule this way (n=1/2408) — the proven path is the entity-layer idTarget_AISpawn per wave, same as Mission Builder Kit uses. |
Unused, relevant (exist in the EXE, 0 retail instances, untested):
| Class | Base | Plausible role |
|---|---|---|
idKisculeNodeMoveAIToSceneNotification |
Notification | Fires once an AI has been relocated into a "Midnight" cinematic scene |
idKisculeNodeActionMidnightMoveAIToScene |
InstanceNode | The action-side counterpart — moves an AI into such a scene |
2. Trigger volumes and interaction
| Node | Instances / scripts | Ports | Notes |
|---|---|---|---|
TriggerNotification |
1,100 / 452 | Touching, Untouched, Empty |
maxNotificationCount ∈ {−1, 1}. Top-5 outgoing wiring from Touching: Delay.Start (121×), SendCustomEvent.Send (117×), ActionWorldMarker.Hide (110×), ActionRemoveAIFromVolume.RemoveAIs (101×), ActionTrigger.Activate (100×). |
VolumeNotification |
857 / 458 | Enter, Leave, Touching, Untouched, Empty |
classFilter: "idPlayer" in 797/857 (93%), "idAI2" in 58/857 (7%) — AI-only volumes are real, measured retail usage, "idProp2" in 2/857. |
UseNotification |
373 / 310 | Used, CancelUsed |
classFilter = "idPlayer" in 373/373 — zero counterexample; this is the "player pressed Use" listener. |
ActionActivatable |
357 / 202 | Enable, Disable, Toggle |
Turns another entity's use/trigger interactivity on or off. |
ActionTrigger |
339 / 170 | Activate; params activator, targetEntities |
Fires an idTarget-style trigger by reference — the generic "make something happen" action. |
ActionRemoveAIFromVolume |
160 / 79 | RemoveAIs; params volume, actionType, removeDead |
Clears AI out of a volume — commonly wired straight off TriggerNotification.Touching (101/1,100 times). |
AIVolumeCountNotification |
35 / 31 | Count Reached; params types, minCount, maxCount, onlyDead/onlyAlive |
Counts AI currently inside a volume against a threshold. |
FlowEntityInVolume |
7 / 7 | In Volume, Not In Volume |
One-shot boolean check, not a persistent listener. |
Unused, relevant:
| Class | Base | Plausible role |
|---|---|---|
idKisculeNodeActivatableNotification |
Notification | A notification counterpart to ActionActivatable — fires when activation state changes, vs. only setting it |
idKisculeNodeActionCountAIInVolume |
InstanceNode | Looks like a one-shot query version of AIVolumeCountNotification, which is a persistent counter |
3. Objectives and mission flow
| Node | Instances / scripts | Ports | Notes |
|---|---|---|---|
ActionMission |
407 / 69 | MissionStart, MissionComplete, MissionEnd, ObjectiveStart, ObjectiveComplete, ObjectiveEnd, SetActiveObjective |
The objective-chain hub — a 7-port echo family, params player, mission, objectives, showNotification, completeHides. |
ActionNextMap |
80 / 69 | NextMap; params mode, mapName, spawnSpot, layers |
mode is "MODE_AUTO" in 80/80 — no other mode value is used in retail. |
MissionNotification |
12 / 6 | ObjectiveCompleted, ObjectiveFailed, MissionCompleted, MissionFailed |
Listener side of the objective chain, filtered by mission/objective params. |
FlowMissionCheck |
6 / 1 | Completed, Matching, ObjectiveActive, ObjectiveActiveNotCompleted |
One-shot query against current mission/objective state. |
ActionGameCompleted, ActionChronicle, ActionGiveSecret |
2/1/1 | — | Rare, end-of-game / secret-collectible actions. |
Unused, relevant:
| Class | Base | Plausible role |
|---|---|---|
idKisculeNodeAlarmGlobalNotification |
Notification | Global counterpart to the used AlarmNotification (20 instances) — maybe fires for any alarm, not a specific one |
idKisculeNodeAlarmBrokenNotification |
Notification | Fires when an alarm is disabled/destroyed rather than triggered |
idKisculeNodeHudTimer |
InstanceNode | Named like a countdown/objective-timer HUD element — no used node currently drives a visible countdown |
idKisculeNodeVaultCheck |
InstanceNode | Puzzle/combination check — speculative pairing with ActionGiveSecret |
4. Doors and moving geometry
No node named "Door" is used in any of the 2,408 retail scripts. idKisculeNodeDoorNotification exists in the engine, well-formed, 0 retail instances. Doors are built by combining movement/constraint nodes instead:
| Node | Instances / scripts | Ports | Notes |
|---|---|---|---|
ParametricTranslation |
178 / 54 | Start, StartReverse, ReachedStart, ReachedEnd |
Eased linear movement between two offsets — the most common door/elevator driver. |
ActionRotateEntity |
160 / 77 | Begin, End, Rotate Over Time, Full Speed, Stopped |
Swinging doors, turning fans, rotating platforms. |
KeyframedTranslation |
115 / 48 | Start, Stop, Reverse, Push, ReachedEnd |
Physically-driven movement with velocity/acceleration (can push the player). |
DisableConstraint |
60 / 15 | Disable; params constraint |
Releases a physics constraint — e.g. letting a hinged part swing free. |
ModifyConstraint |
54 / 21 | Enable, Disable; params constraints |
Batch enable/disable on a list of constraints. |
ParametricRotation, ParametricInterpolation, ParametricFollowSpline, FollowSpline |
17–89 | similar Start/Reverse/ReachedEnd shape | The wider family of eased movement nodes — rotation, generic interpolation, and spline-follow variants (ApplyImpulse, 34 instances, adds a one-shot physics impulse). |
Unused, relevant:
| Class | Base | Plausible role |
|---|---|---|
idKisculeNodeDoorNotification |
Notification | A notification counterpart that nothing currently wires |
idKisculeNodeChallengeEntity |
InstanceNode | Counterpart to the used, 10-instance ActionChallenge — possibly a gate/door tied to completing a challenge |
5. Dialogue and UI
| Node | Instances / scripts | Ports | Notes |
|---|---|---|---|
ActionSoundVoiceOver2 |
3,499 / 271 | Play, Stop, Finished, Interrupted |
The dialogue workhorse — params voiceOver, soundEvent, approachTalk, muteGroup, fromWho, subtitleOverride. |
ActionSoundVoiceOver |
102 / 18 | Play, Stop, Speaker missing |
Older/simpler variant, params voToPlay, potentialSpeakers. |
ActionTutorial |
66 / 49 | Start, Complete, Fail; params player, tutorial |
Tutorial hint prompts. |
Unused, relevant:
| Class | Base | Plausible role |
|---|---|---|
idKisculeNodeGeneralUINotification |
Notification | Notification counterpart to the used, 1-instance ActionGeneralUI |
idKisculeNodeActionShowScreen |
InstanceNode | A full-screen UI trigger — more direct than ActionTutorial's hint text |
idKisculeNodeActionIngameComment |
InstanceNode | A lightweight alternative to ActionSoundVoiceOver2 for short in-game remarks |
6. Music, sound, and RTPCs
| Node | Instances / scripts | Notes |
|---|---|---|
ActionSoundPostEvent |
1,493 / 374 | The general-purpose sound trigger (params entity/entities, soundEvent, distanceCull) — about 16% of its 620 distinct soundEvent values match /mus/, but the node itself is not music-exclusive. |
ActionSpeakerController |
122 / 58 | Start/Stop/Modify on one or more soundObjects. |
ActionSoundSetRTPC / ActionSoundGetRTPC |
22 / 14 | Set/read a real-time parameter by free-text name — RTPC names are not enumerated anywhere outside the .bnk soundbanks. |
SoundEvent |
1 / 1 | A typed variable node holding one sound-event decl reference. |
7. Checkpoint / save
ActionAutosave — 177 instances / 53 scripts. persistToStorage = true in 177/177. saveSlot is "AUTOSAVE" in 176, "TRANSITION" in 1 (a mid-level checkpoint distinct from the main autosave slot).
8. Console commands — Command
idKisculeNodeCommand (short Command) — 7 instances / 4 scripts, tiny node (Exec in/out, one command string parameter) with outsized consequences: its Exec handler queues the string straight into the engine's command-text buffer, the same mechanism resourceExec uses, reachable without ever opening the console. Full writeup, including the exact disassembly and the one caveat (none of retail's 7 instances actually needs the unrestricted path — see TNC Console Unlock §4 and Research-Report-R5-Kiscule-Command).
9. Flow control — the glue
These carry no custom_map_tags (they're used everywhere, not specific to any map feature) but are what everything above gets wired through:
| Node | Instances / scripts | Role |
|---|---|---|
GetCustomEvent / SendCustomEvent |
8,020 / 1,488 · 2,582 / 744 | The global message bus — named events, optionally cross-map (global flag). By far the most common way two unrelated parts of a script talk to each other. |
Delay |
4,103 / 1,197 | Start/Pause/Resume/Stop/Reset → Finished, params delay (ms), resetOnStart. |
Gate |
3,195 / 924 | Test/Open/Close/Toggle → Gate is Open/Gate is Closed. Has two ports both named Open — one InputRegular (pulse that opens it), one OutputRegular (pulse fired once opened) — disambiguated by port type, not name. Most common driver into Gate.Open (in): GetCustomEvent.Received (1,054×) and Delay.Finished (434×). |
ActionBoolControl |
1,979 / 963 | A stored boolean with SetTrue/SetFalse/Toggle and an Updated notification — the most common branch-flag primitive. |
ActionTestBool |
834 / 726 | One-shot branch: In → True/False on a wired value. |
RandomTime / RandomFloat / RandomInt |
1,808 / 46 / 11 | Uniform random in [min, max]. |
Log |
1,325 / 268 | prefix + text to the console/log — the standard debug aid while building a script; see the in-game test recipes on this page and TNC Console Unlock. |
Relay |
264 / 124 | A pure pass-through pulse — no logic, just a named junction point in the graph. |
Timer |
487 / 295 | Repeating Tick at interval for duration, then Finished. |
Counter |
116 / 83 | Increment/Decrement/Reset between startCount/endCount, fires Reached End. |
DynamicSwitch / StaticSwitch |
209 / 1 | Multi-output branch by index, with optional random/looping/autoIncrement. |
CompareFloat / CompareInt / CompareEntity |
96 / 13 / 1 | A == B / A > B / A < B outputs for two wired values. |
FlowFlagCheck |
72 / 48 | Tests an arbitrary list of named save-flags; its per-flag "<flag> on"/"<flag> off" ports are the only place properties bit 0x4 ever appears (§0). |
ActionActivateCountRandom / ActionActivateCount |
10 / 5 | Counts N activations before firing, with optional random delay — crowd-trigger / "every Nth time" patterns. |
10. Variables, entities, and math
| Node | Instances / scripts | Role |
|---|---|---|
EntityReference |
13,850 / 2,202 | The single most-used node in the engine — a stored reference to one entity by name. Its value output is the single highest-fan-out port measured: up to 12 edges from one instance, 2,771 instances with 2+ outgoing edges (top targets: ActionTriggerFx.targets 3,045×, ActionShowHide.showEntities 1,515×, Light.entity 1,283×). |
ListEntityReference |
1,021 / 445 | Same idea, but a list — the preferred way to wire "this whole group" instead of one EntityReference per member. |
PlayerEnt |
1,473 / 794 | Returns the local player entity — no input ports. |
Bool / Int / Float / Str / Time / Vec3 |
85–792 | Typed constant/variable holders — the basic value building blocks, each just Set in, value out. |
NamedVariableBool / …Int / …Float / …Time / …EntityReference |
57–1,206 | Script-global named variables (keyed by variableName, not graph position) — NamedVariableBool (1,206 instances) is the most common, used wherever a flag needs to survive a graph reload or be shared across node islands. |
EntityToLocation / EntityToDirectionVector / EntityToString / EntityToVelocity / EntityToRotation |
6–119 | Entity → value extractors, feeding math or comparison chains. |
AddFloat / AddVector / AddInt, SubstractVector/SubstractFloat, MultiplyFloat/MultiplyVector, DivideFloat, DotProduct, NormalizeVector |
1–29 | Plain arithmetic nodes — small counts because most logic needs only comparisons and flags, not math. |
GetItem / ListCount |
89 / 8 | Index into / measure a list-typed variable. |
11. Visibility, effects, and presentation
| Node | Instances / scripts | Role |
|---|---|---|
ActionTriggerFx |
3,532 / 538 | Fire a particle/FX event on one or more targets, with optional delay. The #1 destination wired from EntityReference.value (3,045 edges). |
ActionShowHide |
1,837 / 1,174 | Show/Hide/Toggle on entity lists — the generic visibility switch, with combined Show/Hide, Show/Toggle etc. port variants for one-pulse combined actions. |
Light |
1,417 / 507 | On/Off/FadeIn/FadeOut with fadeInTable/fadeOutTable curves. |
ActionShowHideMeshKit |
78 / 34 | Shows/hides named mesh-kit pieces on a model — the mechanism behind modular character/prop variation. |
ActionSetSkin |
14 / 9 | Swaps a skins-decl set on target entities at runtime (see the material-skin mechanism in Modding Guide §2). |
SetRenderParm |
23 / 10 | Pushes a vector/alpha value into a named renderParm on target materials. |
ActionWorldMarker |
292 / 85 | Shows/hides the on-screen objective-direction marker for an entity. |
ActionFadeView |
55 / 27 | Screen fade to a color over fadeTime. |
12. Player state and control
| Node | Instances / scripts | Role |
|---|---|---|
PlayerState |
195 / 151 | One-shot check of weapon-handling/posture state (Unarmed, Dual wield, Crouching, Wheelchair …, Panzerhund, …) for a given entity. |
WeaponState |
89 / 45 | Same idea for equipped-weapon identity (HammerGewehr, DieselGewehr, LaserGewehr, UberGewehr, Out of ammo). |
CustomPlayerMode |
46 / 36 | Switches the player into special locomotion/camera modes (Wheelchair, Firefighter, Periscope, Submarine, Ausmerzer, …) — the mechanism behind TNC's vehicle/gimmick sequences. |
DisablePlayerControl |
19 / 9 | Disables specific input channels via inhibitFlags — cutscenes, forced walks. |
ActionHudFlags |
40 / 19 | Sets/clears HUD element flags (disableJournal, disableWeaponWheel, …) per player. |
PlayerPermissions |
7 / 5 | Enables/disables specific player abilities (groundPound, kobra, specialWeaponAttacks, crouching, …). |
ActionGiveItems / ActionConsumeInventory / FlowInventoryCheck |
45 / 19 / 61 | Give, consume, and check inventory items — the loadout-management trio. |
13. AI control
| Node | Instances / scripts | Role |
|---|---|---|
ActionAIManipulate |
317 / 121 | The broad AI-state hammer — one node, kill/set_immunity/perception/muted/inhibitLookAtPlayer/forceInjured/minStance/… all as optional params on a list of ais. |
ActionModifyNavRegion |
310 / 216 | Enables/disables navmesh regions — opens/closes AI pathing through an area without touching geometry. |
ActionAITestState |
100 / 77 | One-shot query of an AI's current behavior state (Safe/Roam/Search/Combat). |
AINotification |
93 / 61 | Listener for AI perception events (Spotted Player, Spotted Enemy, Entered Combat, Noticed Something, Lost Vision Of Enemy). |
ActionNavAgentControl |
56 / 34 | Activates/deactivates nav-agent pathing for a list of agents. |
ActiveAIList / AIEquippedWeaponEnt |
25 / 25 | Query helpers — all currently-active AI, or one AI's equipped weapon entity. |
AlarmNotification |
20 / 17 | Alarm activated/Spawner empty/Stand down from alarm — the alarm-state listener behind guard-reinforcement logic. |
14. The Notification family — one shared shape
Roughly twenty node types — TriggerNotification, VolumeNotification, UseNotification, DamageNotification, AiKilledNotification, PlayerStartNotification, AINotification, AlarmNotification, MissionNotification, PickupNotification, ScenepointNotification, BreakableNotification, SeparableNotification, WeaponFireNotification, AISpawnNotification, UINotification, MapMovementNotification, WarmapNotification, SavegameNotification, and several rarer/unused ones — all inherit from idKisculeNodeNotification and share almost the identical port set:
Reset (in/out) — clears the notification's internal state
Out (notification) — fires on ANY of the type-specific events below
<type-specific events> (notification, e.g. Touching/Untouched/Empty, Spotted Player, Pickup, …)
listenedEntities (in/out var) — optional entity/list filter; unfiltered if left empty
enabled (in/out var)
activator (out var) — who/what triggered the most recent event
maxNotificationCount (in/out var) — -1 = unlimited, otherwise a hard cap
Once you recognize this shape, reading any new Notification node in catalogue.json is just "what are its type-specific event ports and its type-specific filter params" — the plumbing around them is always the same.
15. Full index, by the numbers
For anything not covered above: catalogue.json's nodes array has one entry per type (ports, parameters with measured distinct_values_seen/examples, and up to-5 typical_targets per port), sorted by nothing in particular — query it directly, e.g.
python -c "import json; d=json.load(open('re_probes/kisculeref/catalogue.json', encoding='utf-8')); \
print([n['short'] for n in sorted(d['nodes'], key=lambda x:-x['count'])[:20]])"
python tools/kiscule.py --signature idKisculeNodeDelay
The 205 catalogued types span from EntityReference (13,850 instances) down to 25 types used exactly once in all of retail — one-off nodes like ActionTrial, BulletTime, DebugPoint, LogicGateOr, CompareEntity, or title-specific set pieces (ActionAlligatorGrappleActivation, ActionPanzerhundRideCompleted, EnvironmentDamage). These are real, working node types — just rare because the content they drive is rare.
Related pages
TNC Console Unlock · Kiscule Scripting (container format, round-trip, how to edit a value) · Mission Kiscule Scripting · Mission Anatomy · Research-Report-R3-Kisculeref · Research-Report-R5-Kiscule-Command