Making a combat game with ranged weapons? FastCast may be the module for you!

My friend @Validark made the original Signal module, but mine is faster and has an API that’s more like a BindableEvent. I think he deserves the credit more than me.

2 Likes

this module is working great so far, i needed something to stop the delay happenning for projectiles and this works perfectly. however for some reason it ignores the blacklist and still hits a part on it (local player character). the same goes for just shooting. sometimes the ray gets casted through an object thinking that there’s no object and therefor making the projectile go through the object.

I fixed the delay for projectiles by shooting on the client, and then only updating it for other players, so a for loop, checking if the player name is not the local player name (the one who fired the remote), then use FireClient

This is something I made, alternatively. I had a bullet system that tied to this and fired the impacted event, but you can just replace that with a bindable event if you’re willing to make the bullet system. :update() should be called on the created trajectory every RenderStepped, although it is still tied to time rather than an execution count.

Includes a reflection method for more complex weapons and wallbangs.

function physics.trajectory.new(initial, velocity)
	local self 				= setmetatable({},{__index = physics.trajectory})
	
	-- declaring critical variables
	self.position			= initial
	self.velocity			= velocity
	self.impacted			= event.new("impacted")
	self.tracing			= false
	self.tracetype			= "interface"
	
	self.start				= tick()
	self.t					= self.start
	
	return self
end

function physics.trajectory:update()
	local dt 				= tick() - self.t
	self.t 					= tick()
	
	self.position 			= self.position + (self.velocity * dt)
	self.velocity			= (self.velocity + .5 * Vector3.new(0,-1,0) * dt)
end

function physics.trajectory:reflect(normal)
	self.trajectory			= -2 * self.velocity.unit:Dot(normal.unit) * normal.unit + self.velocity.unit;
end
4 Likes

Wish the example gun included a spread/accuracy implementation.

Excellent point. That is a valuable piece of information for people looking to get into FPS/TPS design. I’ll get to adding that as soon as I can :smiley:

Status update: This change is now live! Get the latest version of the example gun.

3 Likes

This is certainly interesting. I may not include such extensions natively (Only specific use cases may require something like bullet ricochet e.g. specific laser weapons. They aren’t prominent enough to add as part of the stock code) but I do most certainly encourage you to publish a module of your own to implement this stuff.

One immediate suggestion I have is adding a module that has FastCast as a child, where your module can automate casts and add extra functionality to bullets through pre-handled sequences.

1 Like

Awesome, thanks for your work man!!!

1 Like

How would I go about making the end of the projectile the starting position rather then the center as it is in the example, Lets say you have a LONG projectile like a beam when you spawn it at the OUTPUT of weapon it uses the projectiles center rather then the end or the beginning of it. I tried just offsetting it by a vector but that makes it look ugly when shooting sideways.

1 Like

Append this to the end of setting the cosmetic bullet CFrame in LengthChanged

... * CFrame.new(0, 0, -CosmeticBulletObject.Size.Z/2)

This will move the bullet forward by half it’s size relative to however it’s rotated, resulting in exactly what you want.

2 Likes

Thank you for a quick response, that solved it.

Hey, I’ve been experimenting quite a bit but haven’t managed to get what I’m aiming for. How can I make the bullet only stay on a certain Y axis as it travels, as in I don’t want to fire into the sky, only things on the same “level” as the character.

Wow I finally solved it, I was playing around with the server script but all I had to do was actually experiment in the client.

replaced the default firedirection with
local FireDirection = (Vector3.new(Mouse.Hit.p.X,game.Players.LocalPlayer.Character.PrimaryPart.Position.Y, Mouse.Hit.p.Z) - FirePointObject.WorldPosition)

2 Likes

remember to change the ray’s fire direction based on a unit vector otherwise you’ll end up with wack stuff where the spread changes based on how far away someone is. I’ve seen lots of games on roblox do this and it’s incredibly annoying.

1 Like

I am having trouble solving Delay issue.

Displayed here https://gyazo.com/838f2e40c33548576573fda7b0b24e7c

Gun has some significant delay, which’s probably due to fact, that when player presses the button, program gets the current position at that time, but since player is moving sideways, position is not correct anymore.

The solution I had for this is to do client to client replication and have the server verify rather then client to server and have the server render. Obviously verify it on the server then send it back to the other clients to render, excluding the source client which can render right away.

In short everything looks much smoother if you render it on the client/clients rather then the server in most cases.

3 Likes

But how would you actually implement that?

Well, a remote event, a server and client script, and the tool client script. All three of these need access to the fastcast module. So I would put it in ReplicatedStorage. The tool script will work as normal, except remove the damage function, and have it call a remote event to fire it serverside to do the hit verification(basically just fire the fastcast but have the CosmeticObject set to nil or make it invisible via transparency) - The server will be what we use for damage (I’ve seen many people make the mistake of trusting the client and this allows for easy exploitation). Have the server send all the information it received fired to all other clients as soon as its received.

When you do the server script receiving the RemoteEvent call it is vital you verify what your receiving and limit what your receiving from the client. I would only recommend you receive the direction and the tool.

Plug in the stuff you received from the client and manually insert the rest into the Fire() call for now you can make a system later if you have multiple tools that use fastcast. You can derive a start position from the tool you got sent. Use its handle or a specified output part. When you send this back to the clients (not the original client) only provide the tool and Direction, Use the same technique of plugging in the constants as you did for the server. let the client decide a start position this will solve your issue in the gif.

14 Likes

Yo I was wondering if you think there would be issues if each client only had like 2 casters, 1 for the bullets they fire, and 1 caster to render all the other bullets from players. Potentially, if there are many players, one of the casters could be called a lot. Do you think this could be an issue?

Generally speaking only one caster should handle both rendering and detection if you’re doing both on the client (Why render something with a separate object doing the literal exact same thing?)

Otherwise, no. This module is designed for intensive workload. It should not be problematic to have multiple casters each firing several bullets at once.

2 Likes