npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@rbxts/nextcast

v0.1.1-debug

Published

A FastCast-like method for simulating projectile physics.

Readme

NextCast

A raycasting module for Roblox developers with power users in mind.

Inspiration

FastCast has been one of the best and most powerful raycasting modules in roblox development. Unfortunately, the project has gone stale with no maintainers working on it as of July 2023. This module is intended to modernize FastCast as well as rewrite it entirely in roblox-ts so that it may remain maintainable for years to come.

Guarantees

This module will remain 1:1 backwards compatible with any FastCast API calls that are necessary. If there is a good reason to remove such functionality, such as roblox releasing breaking changes to the engine, this module will change its release version in accordance to semver as well as note any changes to default behavior in this section.

Additions

  • SphereCasts are implemented
  • Simpler constructors for use
  • UserData types

Examples

Below is an example of a typical gun used in the orignal module's example in typescript.

import { Caster, PartCache, HighFidelityBehavior, ActiveCast } from "@rbxts/nextcast";

// UserData is now typed. cast.UserData will be typed as Partial<UserData> since the table is still empty on creation.
interface UserData {
	Hits: number;
}

const Tool = script.Parent as Tool; // As an example, we're assuming the script is a descendant of the actual tool.
const MouseEvent = Tool.MouseEvent as RemoteEvent; // Another example.

const BULLET_MAXDIST = 1000;
const BULLET_GRAVITY = new Vector3(0, -game.GetService("Workspace").Gravity, 0);
const DEBUG = false;
const RNG = new Random();

const CosmeticBullet = new Instance("Part");
CosmeticBullet.Material = Enum.Material.Neon;
CosmeticBullet.Color = Color3.fromRGB(0, 196, 255);
CosmeticBullet.CanCollide = false;
CosmeticBullet.Anchored = true;
CosmeticBullet.Size = new Vector3(0.2, 0.2, 2.4);

const PartProvider = new PartCache(CosmeticBullet, 100, game.GetService("Workspace")); // In real games this would be a Projectiles folder in workspace or similar, but this is fine for an example.

const NextCastCaster = new Caster<UserData>();

const CastParams = new RaycastParams();
CastParams.IgnoreWater = true;
CastParams.FilterType = Enum.RaycastFilterType.Exclude; // Blacklist is still supported, but the use of Exclude is recommended.
CastParams.FilterDescendantsInstances = [];

const CastBehavior = NextCast.newBehavior();
CastBehavior.RaycastParams = CastParams;
CastBehavior.MaxDistance = BULLET_MAXDIST;
// Can be prefixed with NextCast, but this is the recommended way.
// CastBehavior.HighFidelityBehavior = NextCast.HighFidelityBehavior.Default is still valid.
CastBehavior.HighFidelityBehavior = HighFidelityBehavior.Default;

// CastBehavior.CosmeticBulletTemplate = CosmeticBullet // Uncomment if you just want a simple template part and aren't using PartCache
CastBehavior.CosmeticBulletProvider = CosmeticPartProvider;

CastBehavior.CosmeticBulletContainer = game.GetService("Workspace");
CastBehavior.Acceleration = BULLET_GRAVITY;
CastBehavior.AutoIgnoreContainer = false;
// NEW
CastBehavior.SphereSize = 0; // Anything above 0 will change the raycast to a spherecast. Set to 0 to preserve original behavior.

const CanRayPierce = (cast: ActiveCast<UserData>, rayResult: RaycastResult, segmentVelocity: Vector3) => {
	if (cast.UserData.Hits === undefined) cast.UserData.Hits = 1;
	cast.UserData.Hits++;
	if (cast.UserData.Hits > 3) return false;

	const hitPart = rayResult.Instance;
	if (hitPart !== undefined && hitPart.Parent !== undefined)
		hitPart.Parent.FindFirstChildOfClass("Humanoid")?.TakeDamage(10);

	// Any other logic you want to do before terminating a cast.
	return true; // Continue the simulation.
};

const Fire = (direction: Vector3) => {
	if (Tool.Parent.IsA("BackPack")) return;

	const directionalCF = new CFrame(new Vector3(), direction);

	const direction = directionalCF
		.mul(CFrame.fromOrientation(0, 0, RNG.NextNumber(0, TAU)))
		.mul(
			CFrame.fromOrientation(math.rad(RNG.NextNumber(MIN_BULLET_SPREAD_ANGLE, MAX_BULLET_SPREAD_ANGLE)), 0, 0),
		).LookVector;
	const humanoidRootPart = Tool.Parent.WaitForChild("HumanoidRootPart", 1);
	const movementSpeed = humanoidRootPart.Velocity;
	const modifiedBulletSpeed = direction.mul(BULLET_SPEED);

	CastBehavior.CanPierceFunction = CanRayPierce;

	const simBullet = NextCastCaster.Fire(
		Tool.Handle.FirePointObject.WorldPosition,
		direction,
		modifiedBulletSpeed,
		CastBehavior,
	);
};

Tool.Equipped.Connect(() => (CastParams.FilterDescendantsInstances = [Tool.Parent]));
MouseEvent.OnServerEvent.Connect((client, mousePoint) => {
	const mouseDirection = mousePoint.sub(Tool.Handle.FirePointObject.WorldPosition).Unit;
	Fire(mouseDirection);
});

A more recent example using some of the changes includes:

import { Caster, HighFidelityBehavior } from "@rbxts/nextcast";

interface UserData {
	UUID: number;
}

const caster = Caster.createSimple<UserData>({
	RaycastParams: new RaycastParams(),
	Acceleration: new Vector3(),
	MaxDistance: 10000,
	HighFidelityBehavior: HighFidelityBehavior.Default,
	HighFidelitySegmentSize: 0,
	CosmeticBulletTemplate: undefined, // This configuration does not simulate a bullet. Useful for server-side casting.
	CosmeticBulletProvider: undefined,
	CosmeticBulletContainer: undefined,
	AutoIgnoreContainer: true,
	SphereSize: 1,
});

const projectile = caster.Fire(new Vector3(), new Vector3(0, 100, 0), 100); // Notice that CastBehavior is no longer passed in, only origin, direction, and velocity are.

projectile.UserData.UUID = 12345679; // Whatever UUID system you want.

Contributing

This project is open for PRs. If you want to add something to the module, you are more than welcome to, but make sure that you don't make changes to behavior expected from normal FastCast.

Special Thanks

This project would not be possible without Eti's FastCast module, roblox-ts, and the entire roblox open-source community. Thank you all for supporting myself and many other developers out there.