Spread raycast (shotgun)

hello. i am trying to transform this gun script into a shotgun script.

	local camera = game.Workspace.CurrentCamera

	local raycastParams = RaycastParams.new()
	raycastParams.FilterType = Enum.RaycastFilterType.Exclude
	raycastParams.FilterDescendantsInstances = {script.Parent.Parent} -- get rid of player

	local middleRay = camera:ViewportPointToRay(camera.ViewportSize.X/2, camera.ViewportSize.Y/2)

	local raycastResult = workspace:Raycast(middleRay.Origin, middleRay.Direction * 1000, raycastParams)

	if raycastResult then
		local Hit = raycastResult.Instance
		print("Hit part: "..Hit.Name)
		REshoot:FireServer(Hit)
		else
		REshoot:FireServer(nil)
	end
1 Like

Try this:

local rayDir = middleRay.Direction
local spread = 5 -- Some number in degrees
rayDir = (rayDir + CFrame.Angles(
    math.rad(math.random(-spread, spread)),
    math.rad(math.random(-spread, spread)),
    math.rad(math.random(-spread, spread))
).LookVector) * 1000

You can then use rayDir as the direction for the raycast.

one question… how do i have to send the info to the shoot script?

my shoot script is a serverscript so i would have to pass all hits using the remoteevent. the serverscript has a debounce so i could not pass all at the same time.

my shoot (serverscript) looks like this

local tool = script.Parent
local REshoot = tool:WaitForChild("REshoot")

local Debris = game:GetService("Debris")

local Handle = tool:WaitForChild("Handle")



--SETUP
script.AMMO_LEFT.Value = script.AMMO.Value


function Bang()
	script.Parent.Handle.Shot.PitchShiftSoundEffect.Octave = math.random(1.5,2)
	script.Parent.Handle.Shot:Play()
	script.Parent.Handle.flare.GUI.Enabled = true
	task.wait(0.1)
	script.Parent.Handle.flare.GUI.Enabled = false
end

function Refresh_Gui()
	script.Parent.Handle.AMMO_GUI.TEXT_LABEL.Text = ""..script.AMMO_LEFT.Value.."/"..script.AMMO.Value..""
end

function ADD_DEBRIS(WHAT, duration)
	game:GetService("Debris"):AddItem(WHAT, duration)
end

function reload()
	script.Parent.Handle.RELOAD:Play()
	task.wait(script.RELOAD_TIME.Value)
end

function blood(hit)
	warn("bleeding")
	if hit.Parent.Humanoid.Health <= script.CRIT_HEALTH.Value then
		hit.Parent:FindFirstChild("Humanoid"):TakeDamage(math.huge)
		if hit.Name == "Head" then 
			script.Parent.Handle.SPECIAL_EFFECTS.HEAD_SHOT:FindFirstChild("PitchShiftSoundEffect").Octave = math.random(1,2)
			local Head_shot_sound = script.Parent.Handle.SPECIAL_EFFECTS.HEAD_SHOT:Clone()
			Head_shot_sound.Parent = script.Parent.Parent.Head
			Head_shot_sound:Play()
			ADD_DEBRIS(Head_shot_sound,2)
		end
		local tracks= Handle.SPECIAL_SOUNDS:GetChildren()
		local rn=math.random(1,#tracks)
		local track=tracks[rn]
		if track~=nil then
			local snd = track:Clone()
			snd.PitchShiftSoundEffect.Octave = math.random(1,1.5)
			snd.Parent = hit
			snd:Play()
			ADD_DEBRIS(snd,2)
		end
		local ched = hit
		for i = 1, script.DEBRIS_AMOUNT.Value do
			local hedd = Instance.new("Part")
			hedd.Shape = "Ball"
			hedd.Size = Vector3.new(script.DEBRIS_SIZE.Value,script.DEBRIS_SIZE.Value,script.DEBRIS_SIZE.Value)
			hedd.CFrame = ched.CFrame
			ADD_DEBRIS(hedd, 10)
			ADD_DEBRIS(ched,0.01)
			hedd.Parent = game.Workspace
			hedd.Velocity = Vector3.new(math.random(-50,50),math.random(50,50),math.random(-50,50)) 
			if math.random(1,10) == 1 then
				hedd.Shape = "Block"
				hedd.BrickColor = ched.BrickColor
				hedd.Material = ched.Material
			else
				hedd.BrickColor = BrickColor.new("Maroon")
				hedd.Material = "Granite"
			end
		end
	end
end

function blah(plr,hit)
	warn("shooting")
	if hit.Parent then
		if hit.Parent:FindFirstChild("Humanoid") then
			local hum = hit.Parent:FindFirstChild("Humanoid")
			if hum then
				if hum ~= plr.Character.Humanoid then
					hit.Parent.KILL_TAG.KILLER.Value = game.Players:GetPlayerFromCharacter(script.Parent.Parent)
					local tracks = Handle.HIT_SOUNDS:GetChildren()
					local rn = math.random(1,#tracks)
					local track=tracks[rn]
					if track~=nil then
						local snd = track:Clone()
						snd.PitchShiftSoundEffect.Octave = math.random(1,1.5)
						snd.Parent = hit.Parent:FindFirstChild("Head")
						snd:Play()
						ADD_DEBRIS(snd,2)
						hum:TakeDamage(script.DAMAGE.Value)
						if hum.Parent:FindFirstChild("HumanoidRootPart") then
							local tracksl= script.RAGDOLL_SOUNDS:GetChildren()
							local rn=math.random(1,#tracksl)
							local trackl=tracksl[rn]
							if trackl~=nil then
								local snd = track:Clone()
								snd.PitchShiftSoundEffect.Octave = math.random(1,1.5)
								snd.Parent = hit.Parent:FindFirstChild("Head")
								snd:Play()
								ADD_DEBRIS(snd,2)
							end
							hum.Parent.HumanoidRootPart.AssemblyLinearVelocity = script.Parent.Parent.HumanoidRootPart.CFrame.LookVector * script.KNOCKBACK.Value
							hum.PlatformStand = true
							hum.PlatformStand = false
						end
						blood(hit)
						warn("done shot")
					end
				end
			end
		else
			warn("PART")
		end
	end
end

local Shot_db = true
function PLANNING(plr,hit)
	warn("planning")
	if script.CAN_SHOOT.Value == true then
		script.CAN_SHOOT.Value = false
		if hit ~= nil then
			warn("got "..hit.Name)
			if script.Parent.Parent.Humanoid.Health > 0 then
				if script.AMMO_LEFT.Value > 0 then
					Bang()
					script.AMMO_LEFT.Value = script.AMMO_LEFT.Value -1
					blah(plr,hit)
					Refresh_Gui()
					task.wait(script.SHOOT_DELAY.Value)
					script.CAN_SHOOT.Value = true
				else
					reload()
					script.AMMO_LEFT.Value = script.AMMO.Value
					script.CAN_SHOOT.Value = true
					Refresh_Gui()
				end
			end
		else
			if script.AMMO_LEFT.Value > 0 then
				Bang()
				script.AMMO_LEFT.Value = script.AMMO_LEFT.Value -1
				Refresh_Gui()
				task.wait(script.SHOOT_DELAY.Value)
				script.CAN_SHOOT.Value = true
			else
				reload()
				script.AMMO_LEFT.Value = script.AMMO.Value
				script.CAN_SHOOT.Value = true
				Refresh_Gui()
			end
		end
	end
end

function EQUIP()
	script.Parent.Handle.EQUIP:Play()
	Refresh_Gui()
end

function UNEQUIP()
	script.Parent.Handle.UNEQUIP:Play()
end

script.Parent.Equipped:Connect(EQUIP)
REshoot.OnServerEvent:Connect(PLANNING)



You make a loop for each shot you want to make with the shotgun. In the loop, add the script I made, and replace middleRay * 1000 with rayDir.

Would you mind editing the script that I provided to make it work? I would then mark your answer as solution

local camera = game.Workspace.CurrentCamera

local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
raycastParams.FilterDescendantsInstances = {script.Parent.Parent} -- get rid of player

local middleRay = camera:ViewportPointToRay(camera.ViewportSize.X/2, camera.ViewportSize.Y/2)

-- Shoots 10 bullets. You can change this to whatever you want.
for i = 1, 10 do
	local rayDir = middleRay.Direction
	local spread = 5 -- Some number in degrees
	rayDir = (rayDir + CFrame.Angles(
 		math.rad(math.random(-spread, spread)),
		math.rad(math.random(-spread, spread)),
		math.rad(math.random(-spread, spread))
	).LookVector) * 1000

	local raycastResult = workspace:Raycast(middleRay.Origin, rayDir, raycastParams)

	if raycastResult then
		local Hit = raycastResult.Instance
		print("Hit part: "..Hit.Name)
		REshoot:FireServer(Hit)
	else
		REshoot:FireServer(nil)
	end
end

You can create an array and for each raycast performed, insert its raycast result instance. Then you can fire the server a single time.

local hits =  {}
for i = 1, 10 do
	-- Use the raycasting code that Axominock wrote

	if raycastResult then
		local hitInstance = raycastResult.Instance
		table.insert(hits, hitInstance)
	end
end

REshoot:FireServer(hits)

But how I might suppose to implement that