npm package: @rbxts/cmove-wrapper
Description: A sophisticated Roblox camera controller with smooth movement, rotation tracking, and intelligent occlusion detection. Features configurable smoothing, multiple tracking modes (lock/follow), and automatic obstacle avoidance with customizable reactions.
Author: irishfix
Latest version: 1.0.0

# @rbxts/cmove-wrapper

[![Documentation](https://img.shields.io/badge/docs-online-blue)](https://irishfix.github.io/rbxts-cmove-wrapper/)

Roblox-ts library for sophisticated camera control with smooth movement, rotation tracking, and intelligent occlusion detection. Control camera position and rotation with configurable smoothing, multiple tracking modes, and automatic obstacle avoidance with customizable reactions.

## Features
- Smooth camera movement with exponential interpolation (`PositionSmoothing`, `RotationSmoothing`).
- Flexible targeting: lock to positions/CFrames, follow BaseParts, or maintain distance with `FollowPosition`.
- Dual tracking modes: `Lock` (precise targeting) and `Follow` (radius-based following).
- Occlusion detection: raycast-based obstacle detection with immediate and debounced (250ms) state tracking.
- Occlusion reactions: `None`, `Passthrough` (move through obstacles), or `Avoid` (shift sideways).
- Signals: `MoveTargetOcclusionChanged`, `LookTargetOcclusionChanged`, and deferred variants for debounced events.
- Configurable raycast parameters: filter descendants, ignore water, respect CanCollide.
- Optional filter callback for custom position/rotation processing each frame.

## Documentation
Full API documentation: **[https://irishfix.github.io/rbxts-cmove-wrapper/](https://irishfix.github.io/rbxts-cmove-wrapper/)**

## Installation
```sh
npm install @rbxts/cmove-wrapper
```

## Quick start
```ts
import { CMover, CMoveWrapper, ActiveMode, OcclusionReaction } from "@rbxts/cmove-wrapper";

// Create a CMover for the workspace camera with occlusion checking enabled
const camera = Workspace.CurrentCamera!;
const mover = new CMover(camera, true);

// Configure smoothing (lower = snappier, higher = smoother)
mover.PositionSmoothing = 0.3;
mover.RotationSmoothing = 0.2;

// Set up occlusion reaction
mover.OcclusionReaction = OcclusionReaction.Avoid;
mover.OcclusionCheckActive = true;

// Move camera to a position and look at a target
const targetPart = Workspace.WaitForChild("Target") as BasePart;
mover.MoveToPosition(new Vector3(0, 50, 0));
mover.LookAt(targetPart);

// Subscribe to occlusion events
mover.MoveTargetOcclusionChanged.Connect((current, previous) => {
	print(`Move target occlusion changed: ${previous} -> ${current}`);
});

// Activate the camera system
mover.Active = true;

// Or use the wrapper with a filter callback to constrain camera height
const player = Players.LocalPlayer;
let currentHRP: BasePart | undefined;

const wrappedMover = CMoveWrapper.Wrap(camera, true, (newPosition: Vector3, newRotation: CFrame) => {
	if (currentHRP) {
		// Keep camera at least 5 studs above the character
		const filteredPosition = new Vector3(
			newPosition.X,
			math.max(currentHRP.Position.Y + 5, newPosition.Y),
			newPosition.Z
		);
		return [filteredPosition, newRotation] as LuaTuple<[Vector3, CFrame]>;
	}
	return [newPosition, newRotation] as LuaTuple<[Vector3, CFrame]>;
});

player.CharacterAdded.Connect((character) => {
	const hrp = character.WaitForChild("HumanoidRootPart") as BasePart;
	const head = character.WaitForChild("Head") as BasePart;
	currentHRP = hrp;
	
	wrappedMover.FollowPosition(hrp, 20); // Follow within 20 studs
	wrappedMover.LookAt(head);
	wrappedMover.SetOcclusionCheckIgnore(OcclusionIgnoreTarget.All, [character], true);
	wrappedMover.Active = true;
	wrappedMover.OcclusionCheckActive = true;
});
```

## API hints
- Creation: `new CMover(camera, occlusionChecking?, filterCallback?)` or `CMoveWrapper.Wrap(camera, ...)`.
- Movement: `MoveTo(cframe)`, `MoveToPosition(vector3)`, `MoveWith(part)`, `FollowPosition(part, maxDistance)`.
- Rotation: `LookAt(target)`, or set via `MoveTo` / `MoveWith` for combined control.
- Modes: `PositionMode` / `RotationMode` (set to `ActiveMode.Lock` or `ActiveMode.Follow`).
- Smoothing: `PositionSmoothing` / `RotationSmoothing` (time constants in seconds, 0 = instant).
- Occlusion: `SetOcclusionCheckIgnore(target, filterDescendants, ignoreWater?, prioritiseCanCollide?)`.
- Control: `Active` (enable/disable updates), `OcclusionCheckActive` (enable/disable occlusion detection).
- Cleanup: `Destroy()` to unbind from RenderStep and disconnect all connections.