To reiterate, here’s pretty much exactly what you should do.
When the client wants to fire a projectile, you send the clients lookvector to the server. The client at the same time, starts rendering the visual part of the projectile. It does this without caring about the server, it only does its own local sanity checks on the client to make sure it can fire.
The client shoots the visual projectile forward, and when it hits something, it shows whatever hit effects should show. But nothing beyond that changes.
The server gets the lookVector, does its sanity checks on whether the client can fire, and if it can, iit sends all the projectile information to all the other clients so they can also render a visual projectile. At the same time, it starts a non visual projectile which is purely for the server. With this, it does what actually matters and fires the projectile forward, and when hitting something, it applies whatever game-related changes should happen. E.g people take damage and such.
This way, people mostly won’t ever notice the delays because to them, the projectile appeared from where the humanoidRootPart was, it shot forward instantly, yadayadayada. But the visual indicator that they see, is not the actual projectile, its just a visual version of the projectile. The actual projectile, which may not be synced to the visual one, is fired on the server.
Its pretty much how any well-made FPS in the entire world works. Except they also often have some lag interpolation, rollback, etc. And serverside movement of course.
the thing is i send 2 things: hitDirection and projectile.CFrame. projectile.CFrame is for spawning location and hitDirection is for projectile movement. i need those for server to simulate projectile for hitboxes
You shouldnt need to do that