Oh, I think (hopefully) I see the problem. So I noticed a problem in your code, and I believe that is what is causing the issue.
local origin = overrideOrigin or equippedWeapon:FindFirstChild(equippedWeaponInfo.BulletOrigin).Position
...
local raycastResult = nil or raycast(targetPosition, origin, penetrateWhitelist)
As you can see from your code, origin
is equal to the BulletOrigin
, meaning that is where the bullet spawns. Then you raycast with the origin. But in the raycast function
return workspace:Raycast(Character.Torso.Position, (aimNoSpread - Character.Torso.CFrame.p).unit * 900, raycastParams)
You never used the origin
, instead you used the position of the character. What happens is that you take the direction starting from your torso, to the targetPosition
, then use that direction to move the laser.

In this image, they look different direction, but its just because of the camera angle. In my theory, they should be the same direction.
Heres my terrible drawing again.

The red cross is where the mouse is pointing, or the targetPosition
. So the code raycasts from the character, takes the direction, then uses it on the BulletOrigin
HOWEVER, this part of the code literally contradicts my direction theory
local hitPosition = raycastResult.Position
local visualRay = visualizeRay(hitPosition, nil, origin)
It casts a visual ray from the hitPosition, to the origin which is the BulletOrigin. Meaning, it should have visualized a ray from BulletOrigin to where the mouse is pointed. In your video, it wasn’t doing it (unless it has different result from the current script).
But just to test, can try this fix for the raycast
function. I used the origin
parameter of the function insted of the Torso.Position
function raycast(targetPosition, origin, ignoreList)
local rayDistance = (origin - targetPosition).magnitude
local spreadDistance = equippedWeaponInfo.BulletSpread/15*rayDistance^.5
local aimWithSpread = Vector3.new(
targetPosition.x+math.random(-spreadDistance,spreadDistance),
targetPosition.y+math.random(-spreadDistance,spreadDistance),
targetPosition.z+math.random(-spreadDistance,spreadDistance))
local aimNoSpread = origin + (targetPosition - origin).Unit*900 -- aim no spread
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {Character, ignoreList, visualizeVector(targetPosition, 0.1)}
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
print((aimNoSpread - origin).unit * 900)
return workspace:Raycast(origin, (aimNoSpread - origin).unit * 900, raycastParams)
end