-- Local
local FireDirection = (Mouse.Hit.p - FirePointObject.WorldPosition).Unit -- Firepoint object is an attachemnt on the gun
-- Server
local RNG = Random.new()
-- Inside a fire function which is called whenever player fires
local directionalCF = CFrame.new(Vector3.new(), FiringDirection)
local direction = (directionalCF * CFrame.fromOrientation(0, 0, RNG:NextNumber(0, TAU)) * CFrame.fromOrientation(math.rad(RNG:NextNumber(MIN_BULLET_SPREAD_ANGLE, MAX_BULLET_SPREAD_ANGLE)), 0, 0)).LookVector -- Direction to cast ray
The important bit here is MIN_BULLET_SPREAD_ANGLE and MAX_BULLET_SPREAD_ANGLE, quoting from the fastcast module:
“THIS VALUE IS VERY SENSITIVE. Try to keep changes to it small. The least accurate the bullet can be. This angle value is in degrees. A value of 0 means straight forward.”
Although It’s better off if you directly refer to the module then ask me how it works, my eye’s usually glaze over when looking at this kind of maths.