Hello im working on a spread system but this is good for shotguns , i want to make it for weapons like AK-47and pistols and etc, for when you move so something like CSGO’s spread and Valorant’s Spread.
But I am bad at math and don’t know how to make a spread
Can someone help, please?
This is on a different studio using a tool but when i finish and see the spread works the way i want it to be il be importing it to my framework.
Using fastcast btw
This is the source
local fireEvent = tool.FireEvent
local FastCast = require(game.ReplicatedStorage.FastCastRedux)
local PartCache = require(game.ReplicatedStorage.PartCache)
local pellet = game:GetService("ServerStorage").Pellet
local pelletsFolder = workspace.PelletsFolder
local firePoint = tool.Handle.FirePoint
FastCast.VisualizeCasts = true
local MAX_DIST = 500
local MIN_SPREAD = 1
local MAX_SPREAD = 4
local caster = FastCast.new()
local provider = PartCache.new(pellet, 100, pelletsFolder)
local castParams = RaycastParams.new()
castParams.FilterType = Enum.RaycastFilterType.Blacklist
local behavior = FastCast.newBehavior()
behavior.RaycastParams = castParams
behavior.CosmeticBulletProvider = provider
behavior.CosmeticBulletContainer = pelletsFolder
behavior.Acceleration = Vector3.new(0, -workspace.Gravity, 0)
local function GetMousePos(unitRay)
local ori, dir = unitRay.Origin, unitRay.Direction * MAX_DIST
local result = workspace:Raycast(ori, dir, castParams)
return result and result.Position or ori + dir
end
local function Fire(direction)
local directionCF = CFrame.new(Vector3.new(), direction)
local spreadDirection = CFrame.fromOrientation(0, 0, math.random(0, math.pi * 2))
local spreadAngle = CFrame.fromOrientation(math.rad(math.random(MIN_SPREAD, MAX_SPREAD)), 0, 0)
local direction = (directionCF * spreadDirection * spreadAngle).LookVector
caster:Fire(firePoint.WorldPosition, direction, 1000, behavior)
end
tool.Equipped:Connect(function()
castParams.FilterDescendantsInstances = {tool.Parent}
end)
fireEvent.OnServerEvent:Connect(function(player, ray)
if tool.Parent:IsA("Backpack") then return end
local pos = GetMousePos(ray)
local direction = (pos - firePoint.WorldPosition).Unit
for i = 1, 10 do
Fire(direction)
end
end)
caster.LengthChanged:Connect(function(cast, lastPoint, dir, displacment, segVel, pellet)
pellet.CFrame = CFrame.lookAt(lastPoint + (dir * displacment), lastPoint)
end)
caster.RayHit:Connect(function(cast, result, segVel, pellet)
if result.Instance then
local character = result.Instance:FindFirstAncestorWhichIsA("Model")
local humanoid = character and character:FindFirstChild("Humanoid")
if humanoid then
humanoid:TakeDamage(10)
provider:ReturnPart(pellet)
else
wait(1)
provider:ReturnPart(pellet)
end
end
end)```
It suits a shotgun tho i want the spread to be like Valorant or CSGO’s like when you move and spread changes unless you stand still or spread changes when you shoot alot without stopping and waiting for gun to cool down
local RNG = Random.new() -- Put these two variables on top, somewhere near all your other variables.
local TAU = math.pi * 2
local directionalCF = CFrame.new(Vector3.new(), dir) -- put your dir variable here
local direction = (directionalCF * CFrame.fromOrientation(0, 0, RNG:NextNumber(0, TAU)) * CFrame.fromOrientation(math.rad(RNG:NextNumber(MIN_SPREAD, MAX_SPREAD)), 0, 0)).LookVector
You may have to do some tweaking to make this work with your code.
Dont worry it shouldnt be any math tweaks, just how you structure the code.
local RNG = Random.new() -- Put these two variables on top, somewhere near all your other variables.
local TAU = math.pi * 2
local directionalCF = CFrame.new(Vector3.new(), direction) -- put your dir variable here
local spreadDirection = CFrame.fromOrientation(0, 0, math.random(0, math.pi * 2))
local spreadAngle = CFrame.fromOrientation(math.rad(math.random(MIN_SPREAD, MAX_SPREAD)), 0, 0)
local direction = (directionalCF * CFrame.fromOrientation(0, 0, RNG:NextNumber(0, TAU)) * CFrame.fromOrientation(math.rad(RNG:NextNumber(MIN_SPREAD, MAX_SPREAD)), 0, 0)).LookVector
caster:Fire(firePoint.WorldPosition, direction, 1000, behavior)
end```
local MIN_SPREAD = 0
local MAX_SPREAD = 4
-- keep BOTH positive.
-- 0 minspread = it has a chance to be 100% accurate. its like a range.
-- if you NEVER want it to be 100% accurate change it to 1 or some number above 0
Yeah but in my code min_spread and max_Spread is like bullets so it has a chance of being 0 bullets shot or 4 bullets shot tho i want it to be like you can change the spread of how much it moves.
okay so i have a idea of how to make the spread like valorant
I could make it so whenever the script detects the player move the max_Spread will increase by +1 and if the player stops movin then the max_Spreads goes back to 4?
But how would i detect the player moving
but if the movedirection keeps changing its going to get bigger and bigger (very big).
so your gonna want too maybe make a bool that says if its moving or not.
also make sure ur using humanoid and not humanoidrootpart
local isMoving = false
humanoid:GetPropertyChangedSignal("MoveDirection"):Connect(function()
if humanoid.MoveDirection.Magnitude > .1 then
if isMoving == false then
isMoving = true
MAX_SPREAD = MAX_SPREAD + 1-- player is moving
end
else
MAX_SPREAD = 4
end
end)
or a simpler way is just to set MAX_SPREAD to 5 or 6 or something without adding it
yeah it says nil when its trying to find character
local player = game:GetService("Players").LocalPlayer
local Character = player.Character or player.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")```
game.Players.ChildAdded:Connect(function(player)
player.CharacterAdded:Wait()
local humanoid = player.Character:WaitForChild("Humanoid")
humanoid:GetPropertyChangedSignal("MoveDirection"):Connect(function()
if humanoid.MoveDirection.Magnitude > .1 then
if isMoving == false then
isMoving = true
MAX_SPREAD = MAX_SPREAD + 1-- player is moving
end
else
MAX_SPREAD = 4
end
end)
but when i test it out the spread doesnt seem to increase hmm but theres no error tho