Skill v1.0.0
currentAutomated scan100/100version: "1.0.0" name: rbx-camera-cutscene description: > Cinematic camera sequences that look storyboarded — multi-shot paths, focus pulls, letterboxing, and skip handling that never leaves the player stuck. Use when the user says "add a cutscene", "camera pan", "intro cinematic", "boss reveal", "fly the camera to", or when an existing cutscene traps the player, can't be skipped, or snaps back jarringly. Do not use for moving actors and props during the scene — load rbx-anim-cutscenes — or for gameplay camera rigs — load rbx-camera-controllers instead. class: AI
rbx-camera-cutscene
Laws
- Server starts it, client plays it. The trigger (boss spawn, zone enter) fires one
RemoteEvent with a scene id; playback is pure LocalScript. Any reward gated on "watched the cutscene" is validated by server-side elapsed time — never a client "done" report.
- One teardown, every exit. A single
restore()restoresCameraType = Custom, the
character's stored WalkSpeed/JumpPower (never hardcoded 16/50), re-enables jumping, and removes the letterbox. It runs on natural end, on skip, and inside the pcall error path. Two exit codepaths means one of them is broken.
- Skippable past 3 seconds. Anything longer gets a hold-to-skip (0.75 s hold, radial
progress) bound to Space + ButtonX + a touch button. Skip calls the same teardown.
- Respect reduced motion. When the game exposes the toggle (
rbx-ui-settings,
rationale in rbx-accessibility), replace pans with static shots and hard cuts.
Passes
- Shot list — a table of
{cf0, cf1, duration, easing}entries. Pans tween 1.5–3 s,
Enum.EasingStyle.Quad/InOut; hard cuts set CFrame directly with a 0.3–0.5 s hold before the next shot. Set CameraType = Scriptable once before the first shot — a tween against Custom gets overwritten every frame.
- Focus pull — track a moving subject by re-aiming each frame:
CFrame.lookAt(camPos, target.Position) with the target position lerped at math.min(dt * 4, 1) so the look-at lags a beat behind. Optical focus pulls tween DepthOfFieldEffect.FocusDistance over 0.8 s via rbx-lighting-postfx.
- Letterbox — two black Frames (ZIndex above the HUD,
BackgroundColor3pure black is
correct here — it's a mask, not UI), each tweening from 0 to 12% of viewport height over 0.4 s Quad/Out. Hide the HUD ScreenGuis by Enabled = false, restore in teardown. Never fake letterbox with FieldOfView.
- Lock the player — store then zero WalkSpeed/JumpPower,
Humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping, false); sink stray input with one ContextActionService:BindActionAtPriority covering movement keys.
- Wire skip + verify — bind the skip action, play end-to-end in Studio, then die
mid-cutscene on purpose: teardown must still run (respawn fires CharacterAdded — treat it as an exit path).
Performance budget
Zero per-frame allocations during playback; one render-step connection for focus tracking, disconnected between shots that don't need it; letterbox tweens are the only UI work; the whole scene leaves no connections, no Scriptable camera, and no locked humanoid behind — verify with a post-scene get_console_output check for your teardown log line.
Load with
rbx-anim-cutscenes the moment any actor, door, or prop moves during the scene — don't ask, include it. rbx-lighting-postfx for DoF focus pulls and grade shifts. rbx-juice-transitions when the scene opens from a UI event. rbx-audio-sfx for the stinger — a silent cutscene reads as a bug.
AI-tells
- ☐ Player stuck in Scriptable camera (or zero WalkSpeed) after the scene — teardown missed a path
- ☐ No skip on a scene longer than 3 seconds
- ☐ WalkSpeed restored to a hardcoded 16 instead of the stored value
- ☐ Camera tweened while CameraType is still Custom (default rig overwrites every frame)
- ☐ Letterbox faked by narrowing FieldOfView
- ☐ Cutscene logic in a server Script writing camera properties
- ☐ Snap cut back to gameplay with no 0.3 s ease or fade
- ☐ Reward granted because the client said the cutscene finished
Memory
Read: style-fingerprints.md (the game's motion vocabulary — easing family, pacing) and the game's projects.md block (existing cutscene module, scene ids). Write: the scene player's module path into module-library.md; shot durations and letterbox height into the game's projects.md block once the user approves a scene.