Charliecutscene
Based on game build 722832 | Last updated: 2026-04-28
Overview
CharlieCutscene controls the scripted cutscene sequence that plays when players approach the Atrium Gate in the Ruins. It manages camera focus and locking, collects data about the four Atrium Pillars for spawn point calculations, spawns Charlie NPC and Charlie Hand entities, and handles the gate repair animation sequence. The component uses netvars to synchronize camera lock state to clients and pushes world events to coordinate with other systems like the nightmare phase lock.
Usage example
local inst = CreateEntity()
inst:AddComponent("charliecutscene")
-- Master only: start the cutscene sequence
if TheWorld.ismastersim then
inst.components.charliecutscene:Start()
end
-- Check if gate repair is complete
local isFixed = inst.components.charliecutscene:IsGateRepaired()
-- Client-side: camera lock state is synced via netvar
if inst.replica.charliecutscene ~= nil then
local isLocked = inst.replica.charliecutscene._iscameralocked:value()
end
Dependencies & tags
Components used:
trader-- disabled during cutscene, restored on finish viaDisable()/Enable()pickable-- checked forcaninteractwithto determine gate icon stateworldsettingstimer-- checked fordestabilizedelayandcooldowntimerscolourtweener-- used for screen fade to black and revert effectsentitytracker-- tracks Charlie Hand entity referencefocalpoint-- world component used for camera focus source management
Tags:
- None identified
External dependencies:
FocalPoint_CalcBaseOffset-- global function for camera offset calculationShakeAllCameras-- global function for camera shake effectSpawnPrefab-- spawns Charlie NPC and Charlie Hand entities
Properties
| Property | Type | Default Value | Description |
|---|---|---|---|
gate_pos | Vector3 | nil | Cached position of the Atrium Gate entity. Set by CollectAtriumPillarsData(). |
atrium_pillars | table | nil | Pillar data table with back and side pillar references. Set by CollectAtriumPillarsData(). |
_iscameralocked | net_bool | false | Synced camera lock state. Dirty event: iscameralockeddirty. Controls client camera focus. |
_cameraangle | net_ushortint | 0 | Synced camera heading angle in degrees. Used by clients to set camera target. No dirty event declared (third parameter omitted in net_ushortint constructor). |
_running | boolean | false | Whether the cutscene sequence is currently active. Master only. |
_gatefixed | boolean | false | Whether the gate repair animation has completed. Persists across save/load. |
_traderenabled | boolean | nil | Stores original trader enabled state before cutscene. Restored on Finish(). Master only. |
charlie | entity | nil | Reference to spawned Charlie NPC entity. Master only. |
hand | entity | nil | Reference to spawned Charlie Hand entity. Master only. |
File-scope constants
| Constant | Type | Value | Usage |
|---|---|---|---|
LOOK_FOR_ATRIUM_PILLARS_RANGE | number | 50 | Search radius for pillar collection in InternalCollectAtriumPillarsData(). |
ATRIUM_PILLAR_MUSTTAGS | table | {"pillar_atrium"} | Required tags for pillar entity search. |
CAMERA_FOCUS_ID | string | "charlie_cutscene" | Focus source identifier for TheFocalPoint. |
CAMERA_FOCUS_DIST_MIN | number | 12 | Minimum camera focus distance. |
CAMERA_FOCUS_DIST_MAX | number | 25 | Maximum camera focus distance. |
CAMERA_PAN_GAIN | number | 4 | Camera pan gain applied in ClientLockCamera(). |
CAMERA_HEADING_GAIN | number | 1.2 | Camera heading gain applied in ClientLockCamera(). |
CAMERA_DISTANCE_GAIN | number | 0.7 | Camera distance gain applied in ClientLockCamera(). |
CAMERA_FINAL_DISTANCE | number | 25 | Final camera distance set in ClientLockCamera(). |
REPAIR_GATE_ANIM_LENGTH | number | 114 * FRAMES | Base animation length for gate repair sequence. |
CHARLIE_SPAWN_DELAY | number | 2 | Delay before spawning Charlie NPC in Start(). |
CHARLIE_START_CAST_DELAY | number | 3 | Delay before Charlie starts casting. |
CHARLIE_CAST_TIME | number | REPAIR_GATE_ANIM_LENGTH + 0.5 + (20 * FRAMES) | Total casting time for Charlie NPC. |
START_REPAIRING_GATE_DELAY | number | CHARLIE_START_CAST_DELAY + (80 * FRAMES) | Delay before starting gate repair animation. |
REPAIR_GATE_DELAY | number | START_REPAIRING_GATE_DELAY + REPAIR_GATE_ANIM_LENGTH | Delay before completing gate repair. |
START_TWEENING_DELAY | number | REPAIR_GATE_ANIM_LENGTH * 0.95 | Delay before starting colour tween to black. |
TWEEN_TO_BLACK_TIME | number | REPAIR_GATE_ANIM_LENGTH - START_TWEENING_DELAY | Duration of colour tween to black. |
REVERT_COLOUR_TIME | number | 3.5 | Duration of colour tween back to normal. |
Main functions
ClientLockCamera()
- Description: Locks player camera control and applies custom camera settings for the cutscene view. Sets camera to non-controllable, applies custom pan/heading/distance gains, sets final distance to 25 units, and sets heading target to the stored camera angle.
- Parameters: None
- Returns: nil
- Error states: Errors if
TheCameraglobal is nil or invalid. No nil guard present.
ClientUnlockCamera()
- Description: Restores player camera control by setting controllable to true. TheFocalPoint component handles resetting gain values automatically when the focus source is removed.
- Parameters: None
- Returns: nil
- Error states: Errors if
TheCameraglobal is nil or invalid. No nil guard present.
Start() (master only)
- Description: Initiates the full cutscene sequence. Sets
_runningto true, pushes world events for cutscene start and nightmare phase lock, disables the trader component, collects pillar data, schedules Charlie spawn and gate repair tasks, calculates and sets camera angle, locks camera, and triggers the camera lock dirty event. - Parameters: None
- Returns: nil
- Error states: Errors if
inst.components.traderis nil (no guard beforeDisable()call). Errors ifTheWorldglobal is nil.
Finish() (master only)
- Description: Ends the cutscene sequence. Sets
_runningto false, pushes world events for cutscene end and nightmare phase unlock, restores trader enabled state if it was originally enabled, unlocks camera, and pushesshadowrift_openedworld event. - Parameters: None
- Returns: nil
- Error states: Errors if
inst.components.traderis nil (no guard beforeEnable()call). Errors ifTheWorldglobal is nil.
CollectAtriumPillarsData()
- Description: Collects and caches data about the four Atrium Pillars surrounding the gate. Returns early if data already collected. Stores gate position and calls
InternalCollectAtriumPillarsData()to find pillars within 50 units withpillar_atriumtag, calculate their angles, and determine back/side pillar relationships. - Parameters: None
- Returns: nil
- Error states: Errors if
self.inst:GetPosition()returns nil. Errors ifInternalCollectAtriumPillarsData()fails to find valid pillars.
FindSceneCameraAngle()
- Description: Calculates the optimal camera angle for the cutscene based on pillar positions. Uses the back pillar position and gate position to compute an angle via
math.atan2, rounds to nearest 90-degree increment viaRoundPillarAngle(), then applies a -90 or +90 offset depending on the angle value. - Parameters: None
- Returns: number -- camera angle in degrees (0-360)
- Error states: Errors if
self.atrium_pillars.backis nil (no guard beforeGetPosition()call).
StartRepairingGateWithDelay(delay, delay_to_fix)
- Description: Schedules the gate repair animation sequence. Uses
DoTaskInTimeto callStartRepairingGateatdelayseconds andRepairGateatdelay_to_fixseconds. - Parameters:
delay-- number, delay in seconds before starting repair animationdelay_to_fix-- number, delay in seconds before completing repair
- Returns: nil
- Error states: None
RepairGate()
- Description: Completes the gate repair sequence. Sets
_gatefixedto true, switches animation build toatrium_gate_build, playsfixedanimation, kills thefixingsound, triggers camera shake, playsfixedsound, updates minimap icon based on pickable/timer state, and pushescooldownoridleanimation based on worldsettings timer state. - Parameters: None
- Returns: nil
- Error states: Errors if
inst.components.pickableis nil (no guard beforecaninteractwithaccess). Errors ifinst.components.worldsettingstimeris nil (no guard beforeActiveTimerExists()call). Errors ifinst.MiniMapEntityis nil.
FindCharlieSpawnPoint()
- Description: Calculates Charlie NPC spawn position. Selects a random side pillar, computes a weighted position between pillar and gate (40% pillar, 60% gate), then applies a 3-unit offset in the camera direction to position Charlie slightly ahead of the gate.
- Parameters: None
- Returns: Vector3 -- spawn position, or
nilif no valid pillar found - Error states: Errors if
self.atrium_pillarsis nil (no guard before access).
SpawnCharlieWithDelay(delay)
- Description: Schedules Charlie NPC spawn after the specified delay. Spawns
charlie_npcprefab, setsatriumreference to the gate entity, positions Charlie at the calculated spawn point, forces Charlie to face the gate, and starts Charlie's casting sequence with the configured delays. - Parameters:
delay-- number, delay in seconds before spawning
- Returns: nil
- Error states: Errors if
SpawnPrefab("charlie_npc")returns nil. Errors ifself.charliehas noTransformorForceFacePointmethods.
FindCharlieHandSpawnPoint()
- Description: Calculates Charlie Hand spawn position using pillar geometry. Collects pillar data if not already cached, then computes the inverse point of the back pillar relative to the two side pillars using vector math:
side1 + side2 - back. - Parameters: None
- Returns: Vector3 -- spawn position for Charlie Hand
- Error states: Errors if
self.atrium_pillarsis nil or any pillar reference is nil (no guards beforeGetPosition()calls).
SpawnCharlieHand()
- Description: Spawns the Charlie Hand entity and establishes bidirectional entity tracking. Spawns
charlie_handprefab, tracks the hand entity on the gate and the gate entity on the hand viaentitytrackercomponent, calculates spawn position, and initializes the hand entity. - Parameters: None
- Returns: nil
- Error states: Errors if
SpawnPrefab("charlie_hand")returns nil. Errors ifinst.components.entitytrackeris nil. Errors ifself.hand.components.entitytrackeris nil.
IsGateRepaired()
- Description: Returns whether the gate repair animation has completed.
- Parameters: None
- Returns: boolean --
trueif_gatefixedis true,falseotherwise - Error states: None
OnSave()
- Description: Returns save data table for world persistence. Returns
{running = true}if cutscene is active, or{gatefixed = true}if gate is repaired. Returnsnilif neither condition is met. - Parameters: None
- Returns: table or
nil-- save data table - Error states: None
OnLoad(data)
- Description: Restores state from save data. If
data.runningis true, callsFinish()to skip the cutscene and sets_runningto false. Ifdata.runningordata.gatefixedis true, sets_gatefixedto true, switches animation build, and updates minimap icon based on pickable/timer state. - Parameters:
data-- table -- save data fromOnSave(), ornil
- Returns: nil
- Error states: Errors if
inst.components.pickableis nil (no guard beforecaninteractwithaccess). Errors ifinst.components.worldsettingstimeris nil. Errors ifinst.MiniMapEntityis nil.
OnIsCameraLockedDirty(inst) (local)
- Description: File-scope callback triggered by
iscameralockeddirtynetvar change on clients. Returns early on dedicated servers. If camera is locked, starts a focus source onTheFocalPointwith the configured update function and distance bounds. If unlocked, stops the focus source and callsClientUnlockCamera(). - Parameters:
inst-- entity instance with charliecutscene component
- Returns: nil
- Error states: Errors if
TheFocalPoint.components.focalpointis nil. Errors ifinst.components.charliecutsceneis nil.
CharlieCam_UpdateFn(dt, params, parent, dist_sq) (local)
- Description: File-scope camera update function for the focal point system. Calculates base offset via
FocalPoint_CalcBaseOffset, adjusts Y offset by +1, applies to camera. Then checks distance squared against maxrange to determine if camera should be locked or unlocked based on player proximity. - Parameters:
dt-- number -- delta timeparams-- table -- focal point params including source component referenceparent-- entity -- focal point parent entitydist_sq-- number -- squared distance from camera to source
- Returns: nil
- Error states: Errors if
params.source.components.charliecutsceneis nil. Errors ifTheCameraglobal is nil.
TweenToNormalColour(inst) (local)
- Description: File-scope helper that starts a colour tween back to normal (white) over
REVERT_COLOUR_TIME(3.5 seconds). Called after the black fade completes. - Parameters:
inst-- entity instance with colourtweener component
- Returns: nil
- Error states: Errors if
inst.components.colourtweeneris nil.
RevertToNormalColour(inst) (local)
- Description: File-scope helper that schedules
TweenToNormalColourafter 0.2 seconds delay. - Parameters:
inst-- entity instance
- Returns: nil
- Error states: None
TweenToBlack(inst) (local)
- Description: File-scope helper that starts a colour tween to black over
TWEEN_TO_BLACK_TIMEwithRevertToNormalColouras the completion callback. - Parameters:
inst-- entity instance with colourtweener component
- Returns: nil
- Error states: Errors if
inst.components.colourtweeneris nil.
StartRepairingGate(inst) (local)
- Description: File-scope helper that begins the gate repair animation sequence. Plays
fixinganimation, starts thefixingsound loop, and schedulesTweenToBlackafterSTART_TWEENING_DELAY. - Parameters:
inst-- entity instance with charliecutscene component
- Returns: nil
- Error states: Errors if
inst.SoundEmitteris nil.
RepairGate(inst) (local)
- Description: File-scope wrapper that calls
inst.components.charliecutscene:RepairGate(). Provided for task scheduling compatibility. - Parameters:
inst-- entity instance
- Returns: result of
RepairGate()call - Error states: Errors if
inst.components.charliecutsceneis nil.
Events & listeners
- Listens to:
iscameralockeddirty(client only) -- triggered when_iscameralockednetvar changes; callsOnIsCameraLockedDirtyto manage camera focus source - Pushes:
charliecutscene-- world event with boolean data (trueon start,falseon finish) - Pushes:
ms_locknightmarephase-- world event with string"wild"on start,nilon finish - Pushes:
shadowrift_opened-- world event fired when cutscene completes