I made a custom gun script!

Hey developers, I made a custom gun script, and I want to check what you guys think. My gun will not make a bullet to where the mouse if pointing (sometimes), but let me know what you guys think.

Server Script:

local tool = script.Parent
local shoot_part = tool:WaitForChild("Handle")
local remote = tool:WaitForChild("OnShoot")

local Workspace = game:GetService("Workspace")
local ServerStorage = game:GetService("ServerStorage")

remote.OnServerEvent:Connect(function(player, position)
	local origin = shoot_part.Position
	local direction = (position - origin).Unit*300
	local result = Workspace:Raycast(origin, direction)

	local intersection = result and result.Position or origin + direction
	local distance = (origin - intersection).Magnitude

	local bullet_clone = ServerStorage.Bullet:Clone()
	bullet_clone.Size = Vector3.new(0.1, 0.1, distance)
	bullet_clone.CFrame = CFrame.new(origin, intersection)*CFrame.new(0, 0, -distance/2)
	bullet_clone.Parent = Workspace
	
	local PlayerName = Instance.new("StringValue")
	PlayerName.Name = "Attacker"
	PlayerName.Value = player.Name
	PlayerName.Parent = bullet_clone

	if result then
		local part = result.Instance
		local humanoid = part.Parent:FindFirstChild("Humanoid") or part.Parent.Parent:FindFirstChild("Humanoid")

		if humanoid and humanoid.Parent.Name ~= bullet_clone.Attacker.Value then
			humanoid:TakeDamage(math.random(10,14))
			local db = false
			if humanoid.Health <= 0 then
				if db == false then
					db = true
					player.leaderstats.Points.Value += 15
					task.wait(1.2)
					db = false
				end
			end
		end
	end

	wait(0.25)
	bullet_clone:Destroy()
end)

Client Script:

local tool = script.Parent
local remote = tool:WaitForChild("OnShoot")
local maxAmmo = 14
local CoolDown = 0.002
local ammo = maxAmmo
local reloading = false

local Players = game:GetService("Players")
local client = Players.LocalPlayer
local cursor = client:GetMouse() 
local CAS = game:GetService("ContextActionService")
local Camera = game:GetService("Workspace").CurrentCamera

local plrgui = client.PlayerGui
local text = plrgui:WaitForChild("Ammo").AmmoCount

local BoolValue = script.Parent:WaitForChild("EquippedValue")

local ZoomTypes = { Enum.UserInputType.MouseButton2, Enum.KeyCode.ButtonL2 }
local ReloadTypes = { Enum.KeyCode.R, Enum.KeyCode.ButtonX }
local FireTypes = { Enum.UserInputType.MouseButton1, Enum.KeyCode.ButtonR2 }
local gunCooldown = false

local function GunHandler(ActionName, inputState, inputObject)
	if ActionName == "WeaponZoom" and BoolValue.Value and inputState == Enum.UserInputState.Begin and (table.find(ZoomTypes, inputObject.UserInputType) or table.find(ZoomTypes, inputObject.KeyCode)) then
		Camera.FieldOfView = 40
		client.Character:WaitForChild("Humanoid").WalkSpeed = 14.5
		plrgui:WaitForChild("HotBarGUI").Enabled = false
	end

	if ActionName == "WeaponZoom" and inputState == Enum.UserInputState.End and (table.find(ZoomTypes, inputObject.UserInputType) or table.find(ZoomTypes, inputObject.KeyCode)) then
		Camera.FieldOfView = 70
		client.Character:WaitForChild("Humanoid").WalkSpeed = 17.5
		plrgui:WaitForChild("HotBarGUI").Enabled = true
	end

	if ActionName == "Reload" and BoolValue.Value and table.find(ReloadTypes, inputObject.KeyCode) and not reloading then
		reloading = true
		tool.Handle.reload:Play()
		task.wait(1)
		ammo = maxAmmo
		reloading = false
	end

	if ActionName == "FireWeapon" and BoolValue.Value and (table.find(FireTypes, inputObject.UserInputType) or table.find(FireTypes, inputObject.KeyCode)) and not reloading and ammo > 0 and not gunCooldown then
		gunCooldown = true
		ammo = ammo - 1
		task.wait(CoolDown)
		remote:FireServer(cursor.Hit.Position)
		tool.Handle.gunshot:Play()
		tool.Handle.PointLight.Enabled = true
		task.wait(0.2)
		tool.Handle.PointLight.Enabled = false
		task.delay(CoolDown, function() gunCooldown = false end)
	elseif ActionName == "FireWeapon" and BoolValue.Value and (table.find(FireTypes, inputObject.UserInputType) or table.find(FireTypes, inputObject.KeyCode)) and not reloading and not gunCooldown then
		reloading = true
		tool.Handle.reload:Play()
		task.wait(1)
		ammo = maxAmmo
		reloading = false
		tool.Handle.gunshot:Stop()
	end
end

task.spawn(function()
	while true do
		text.Text = (ammo).." / "..tostring(maxAmmo)
		task.wait()
	end
end)

tool.Equipped:Connect(function()
	BoolValue.Value = true

	cursor.Icon = "rbxassetid://42445293"

	plrgui.Ammo.Enabled = true
	text.DisableScript.Disabled = true
	plrgui.Shop.Enabled = false
	plrgui.Inventory.Enabled = false

	CAS:BindAction("FireWeapon", GunHandler, true, Enum.UserInputType.MouseButton1, Enum.KeyCode.ButtonR2)
	CAS:BindAction("Reload", GunHandler, true, Enum.KeyCode.R, Enum.KeyCode.ButtonX)
	CAS:BindAction("WeaponZoom", GunHandler, true, Enum.UserInputType.MouseButton2, Enum.KeyCode.ButtonL2)

end)

script.Parent.Unequipped:Connect(function()
	plrgui.Ammo.Enabled = false
	text.DisableScript.Disabled = false
	plrgui.Shop.Enabled = true
	plrgui.HotBarGUI.Enabled = true
	plrgui.Inventory.Enabled = true

	BoolValue.Value = false

	Camera.FieldOfView = 70
	client.Character:WaitForChild("Humanoid").WalkSpeed = 17.5
	plrgui:WaitForChild("HotBarGUI").Enabled = true

	CAS:UnbindAction("FireWeapon")
	CAS:UnbindAction("Reload")
	CAS:UnbindAction("WeaponZoom")
end)

thanks,

papahetfan

3 Likes

If you want to improve your gun and are willing to switch to a module, you can try using FastCast for the bullet hitbox. It’s a reliable hitbox module made for ranged weapons (guns, bows, etc.) that uses raycasting aswell.

This module is a lifesaver because not only does it make the bullet’s hitbox for you, but also helps you smoothly replicate it on the server (and avoid bullet lag/jittering).


Other than that, this is a great start for a gun script. Nice job!

1 Like