Hello, I am currently making a gun system but the problem is it’s not working as expected. The main issue is the bullet either fires above the mouse, or fires accurately on the mouse. Here’s a video of the problem
I’ve tried multiple solutions like removing gun spread, messing with .unit vector but I still can’t seem to figure it out. Any help would be much appreciated.
Here is the client code for a gun
Gun client
local require = require(game:GetService('ReplicatedStorage'):WaitForChild('library').require)
local index = require('utility', 'index')
local service = require('utility', 'service')
--// services
local input = service.UserInputService
local run = service.RunService
--// remotes
local gun_ev = require('events', 'gun')
--// tool
local tool = script.Parent
local handle = tool:WaitForChild('Handle')
local point = handle.point
local set = require(tool.settings)
--// player
local player = service.Players.LocalPlayer
local mouse = player:GetMouse()
--// objects
local site = workspace:WaitForChild('site')
local outside = site.outside
local library = service.ReplicatedStorage.library
local assets = library.assets
local gun_folder = assets.gun
local ui = gun_folder.gun_ui
--// variables
local rates = {}
local current_ammo = set.gun.ammo
local last_shot, reloading = nil, false
--// indexing
local ray = Ray.new
local fpor = workspace.FindPartOnRayWithIgnoreList
local function update_ui(custom, dir, ignore)
local new = player.PlayerGui:FindFirstChild(ui.Name)
if new then
local crosshair = new.crosshair
local frame = new.right
local ammo = frame.ammo
local counter = ammo.counter
local name = frame.name
if custom == 'mouse' then
local pos = input:GetMouseLocation()
crosshair.Position = UDim2.new(0, pos.X, 0, pos.Y - 36)
else
name.Text = custom and custom ~= 'gun' and custom or tool.Name
name.shadow.Text = name.Text
counter.Text = current_ammo
counter.shadow.Text = counter.Text
end
end
end
local function fire(dir, ignore)
if not rates[tool] or tick() - rates[tool] >= (60 / set.gun.rpm) then rates[tool] = tick() else return end
if current_ammo <= 0 or reloading then return end
last_shot = tick()
gun_ev:FireServer('fire', tool, dir, ignore)
current_ammo = current_ammo - 1
update_ui('gun', dir, ignore)
end
input.InputBegan:connect(function(key, processed)
if tool.Parent:IsA('Backpack') then return end
if key.UserInputType == Enum.UserInputType.MouseButton1 and not processed then
local dir = (mouse.Hit.p - point.WorldPosition).unit
if set.gun.type:lower() == 'semi' or set.gun.type:lower() == 'shotgun' then
fire(dir, {tool.Parent, outside.vegetation})
elseif set.gun.type:lower() == 'auto' then
while input:IsMouseButtonPressed(Enum.UserInputType.MouseButton1) do
dir = (mouse.Hit.p - point.WorldPosition) do
fire(dir, {tool.Parent, outside.vegetation})
end
run.Heartbeat:wait()
end
end
end
if key.KeyCode == Enum.KeyCode.R then
if not last_shot or tick() - last_shot >= 1 and current_ammo < set.gun.ammo then
reloading = true
update_ui('RELOADING')
delay(1, function()
reloading = false
current_ammo = set.gun.ammo
update_ui()
end)
end
end
end)
tool.Equipped:connect(function(m)
input.MouseIconEnabled = false
if player.PlayerGui:FindFirstChild(ui.Name) then
player.PlayerGui:FindFirstChild(ui.Name):Destroy()
end
ui:Clone().Parent = player.PlayerGui do
update_ui()
end
update_ui('mouse')
m.Move:connect(function()
update_ui('mouse')
end)
end)
tool.Unequipped:connect(function()
input.MouseIconEnabled = true
if player.PlayerGui:FindFirstChild(ui.Name) then
player.PlayerGui:FindFirstChild(ui.Name):Destroy()
end
end)
Here is the bullet visualizer
Visualizer
local req = require(game:GetService('ReplicatedStorage'):WaitForChild('library').require)
local index = req('utility', 'index')
local service = req('utility', 'service')
--// remotes
local gun_ev = req('events', 'gun')
--// indexing
local ray = Ray.new
local fpor = workspace.FindPartOnRayWithIgnoreList
--// player
local player = service.Players.LocalPlayer
gun_ev.OnClientEvent:connect(function(...)
local args = {...}
if args[1] == 'replicate_bullet' then
local tool, set, dir, ignore, ray = args[2], args[3], args[4], args[5], args[6]
local handle = tool.Handle
local point = handle.point
local hit, pos = fpor(workspace, ray, ignore, false, true)
local new_length = (point.WorldPosition - pos).magnitude
local sizer = Instance.new('Part')
sizer.Parent = point
sizer.CFrame = CFrame.new(point.WorldPosition, pos)
sizer.Transparency = 1
sizer.Size = Vector3.new(.05, .05, .05)
sizer.Anchored = true
local bullet = Instance.new('LineHandleAdornment')
bullet.Parent = sizer
bullet.Adornee = sizer
bullet.Length = new_length
bullet.Transparency = .5
bullet.Color3 = Color3.fromRGB(255, 255, 130)
delay(.15, function()
sizer:Destroy()
end)
end
if args[1] == 'update_crosshair' then
local new = player.PlayerGui:FindFirstChild('gun_ui')
if new then
local crosshair = new.crosshair
crosshair.Image = args[2]
end
end
end)