[ OPEN-SOURCE ] OTS Gun System [ NO LONGER UPDATED ]

I have made an OTS ( OVER THE SHOULDER ) Gun system recently. I have nothing to do with it so I
will put it here for free.

Features:

  • Aiming
  • Safety (G)
  • Fully customizable
  • Different sounds and particles for each material
  • Reduced server lag by handling visuals in a different way
  • Shoulder switching (Q, E)

How to use:

1. Changing the gun model:

To change the gun first find a new gun model. When you find it delete everything 
from the GunModel except for the "FirePart" Then handle and the FirePart to
fit your new model and weld everything in GunModel to the handle including the
FirePart. Once you did that it should work.

-- GunModel is a model in the gun tool.

Note:
Dont forget to put the new model for the gun in the GunModel.
2. Changing the properties:

To change the properties open the "Settings" module in the gun.

The following are the meanings for the variables:
- Ammo: Magazine capacity
- Damage: Damage made with one bullet
- Range: How far the bullet can go in studs
- Recoil: Doesnt do anything, to change go in the client and find the recoil_amount
- Automatic: Defines if the gun will fire automatically or not
- Shotgun: Defines if the gun is a shotgun
- Pellet Amount: How many pellets will be fired, only works with shotguns
- Reload: Reload time
- Rate: The lower this is, the faster it will fire
- CasingId: The bullet casing that will drop -- 1 PISTOL -- 2 RIFLE -- 3 SHOTGUN --
3. Changing the animations:

To change the animations go to the configuration folder in the tool where you will
find the animations folder. There just change the IDs.

Note: DO NOT leave an animation ID empty. It will break the system.
4. Changing the sounds.

Simply just go to the tool handle, in it there will be sounds and just
replace the sound IDs.
5. Changing the particles:

To change the fire particles simply put new ones in the FirePart. You do not have
to rename them.

To change the hit particles you can find them in the GunSystem folder in
Replicated storage. There you can find particles, hit sounds and bullet holes.
6. Directories:

* GunSystem folder, must be in Replicated Storage.
* StarterPlayer > StarterPlayerScripts, gun visuals, must be there.
* Gun Tools, can be anywhere.
7. Disabling the OTS System:

To do this you have to replace the code in every gun client script to this code:

---------------------------------------------------------------------------------------------------------
-- WAITING TILL PLAYER IS LOADED

wait(2)

-- VARIABLES

local plr = game.Players.LocalPlayer
local mouse = game.Players.LocalPlayer:GetMouse()
local tool = script.Parent

local mousedown = false
local debounce = false
local safety = false
local rel = false

local idleAnim = plr.Character:WaitForChild("Humanoid"):LoadAnimation(script.Parent.Configuration.Animations.Idle)
local reloadAnim = plr.Character:WaitForChild("Humanoid"):LoadAnimation(script.Parent.Configuration.Animations.Reload)
local shootAnim = plr.Character:WaitForChild("Humanoid"):LoadAnimation(script.Parent.Configuration.Animations.Shoot)
local safetyAnim = plr.Character:WaitForChild("Humanoid"):LoadAnimation(script.Parent.Configuration.Animations.Safety)
local aimAnim = plr.Character:WaitForChild("Humanoid"):LoadAnimation(script.Parent.Configuration.Animations.Aim)

local set = require(script.Parent.Settings)
local gui = script.AmmoGui:Clone()

local camera = game.Workspace.CurrentCamera
local random = Random.new()

local ts = game:GetService("TweenService")
local uis = game:GetService("UserInputService")
local ots = require(game.ReplicatedStorage.GunSystem["OTS Camera System"])

local InputS = game:GetService("UserInputService")

local camera = game.Workspace.CurrentCamera
local random = Random.new()

local spread_amount = math.rad(5)

local recoil_amount = 0.005
local recoil_acc = CFrame.Angles(0, 0, 0)
local recoil_decay = 0.85

function shootF()
	local shoot_cf = camera.CFrame * CFrame.Angles( 
		random:NextNumber(-recoil_amount, recoil_amount),
		random:NextNumber(-recoil_amount, recoil_amount),
		0
	)
	local shoot_ray = Ray.new(shoot_cf.p, shoot_cf.LookVector)
	camera.CFrame = camera.CFrame * recoil_acc:inverse()
	recoil_acc = recoil_acc * CFrame.Angles(recoil_amount, 0.01, 0)
	camera.CFrame = camera.CFrame * recoil_acc
end

game:GetService("RunService").RenderStepped:Connect(function(dt)
	camera.CFrame = camera.CFrame * recoil_acc:inverse()
	recoil_acc = recoil_acc:Lerp(CFrame.new(), recoil_decay * dt)
	camera.CFrame = camera.CFrame * recoil_acc
end)

-- EQUIP AND UNEQUIP

tool.Equipped:Connect(function()
	if safety == false then
		idleAnim:Play()
	else
		safetyAnim:Play()
	end
	debounce = true
	script.Parent.Handle.Equip:Play()
	wait(0.2)
	if safety == false then
		debounce = false
	end
	gui.Ammo.Text = script.Parent.Ammo.Value
	gui.Parent = plr.PlayerGui
end)

tool.Unequipped:Connect(function()
	gui.Parent = plr
	shootAnim:Stop()
	idleAnim:Stop()
	reloadAnim:Stop()
	safetyAnim:Stop()
	script.Parent.Handle.Reload:Stop()
end)

tool.AncestryChanged:Connect(function()
	if tool.Parent ~= plr.Character then
		gui.Parent = plr
		shootAnim:Stop()
		idleAnim:Stop()
		reloadAnim:Stop()
		safetyAnim:Stop()
		script.Parent.Handle.Reload:Stop()
	end
end)

-- MOUSE FUNCTIONS

tool.Activated:Connect(function()
	if set.automatic == false then
		if debounce == false and script.Parent.Ammo.Value > 0 and safety == false then
			debounce = true
			script.Parent.Configuration.RemoteEvents.Fire:FireServer(mouse.Hit.p)
			shootAnim:Play()
			shootF()
			wait(set.rate)
			debounce = false
		end
	else
		if debounce == false and script.Parent.Ammo.Value > 0 and safety == false then
			mousedown = true
			repeat
				if plr.Character:FindFirstChild(tool.Name) and script.Parent.Ammo.Value ~= 0 and script.Parent.Ammo.Value > 0 then
					script.Parent.Configuration.RemoteEvents.Fire:FireServer(mouse.Hit.p)
					shootAnim:Play()
					shootF()
					wait(set.rate)
				end
			until mousedown == false or debounce == true or safety == true or script.Parent.Ammo.Value < 1 or script.Parent.Ammo.Value == 0
		end
	end
end)

mouse.Button1Up:Connect(function()
	if mousedown == true then
		mousedown = false
		debounce = true
		delay(set.rate, function()
			debounce = false
		end)
	end
end)

-- AMMO GUI

script.Parent.Ammo.Changed:Connect(function()
	gui.Ammo.Text = script.Parent.Ammo.Value
end)

-- KEYBINDS

uis.InputBegan:Connect(function(input, chatting)
	if input.KeyCode == Enum.KeyCode.R then
		if chatting == false and script.Parent.Ammo.Value < set.ammo and plr.Character:FindFirstChild(tool.Name) then
			if rel == false then
				rel = true
				debounce = true
				reloadAnim:Play()
				script.Parent.Configuration.RemoteEvents.Reload:FireServer()
				wait(set.reload)
				if safety == false then
					debounce = false
				end
				rel = false
			end
		end
	elseif input.KeyCode == Enum.KeyCode.G then
		if chatting == false and plr.Character:FindFirstChild(tool.Name) then
			if safety == false then
				debounce = true
				safety = true
				safetyAnim:Play()
			else
				debounce = false
				safety = false
				safetyAnim:Stop()
				idleAnim:Play()
			end
		end
	end
end)

-- KILL FEED

script.Parent.Configuration.RemoteEvents.Kill.OnClientEvent:Connect(function(plr, user)
	local t = script.Template:Clone()
	t.Parent = gui.KillFeed
	gui.KillFeed.Sound:Play()
	t.Text = "[ KILLED: "..string.upper(user).." ]"
	delay(2, function()
		ts:Create(t, TweenInfo.new(0.5), {TextTransparency = 1}):Play()
		ts:Create(t, TweenInfo.new(0.5), {TextStrokeTransparency = 1}):Play()
		wait(0.5)
		t:Destroy()
	end) 
end)

-- DEATH

plr.Character.Humanoid.Died:Connect(function()
	ots:Disable()
	ots:SetCharacterAlignment(false)
	tool:Destroy()
end)

If you would like more tutorials, make a comment.

PLEASE DO NOT SELL THIS OR CLAIM IT AS YOUR OWN!!!

43 Likes

So, Could you leave copies of the animations? So we don’t have to manually download them and put them in studio.

1 Like

Unfortunately, I didn’t keep them so I can’t.

1 Like

I’m kinda learning LUA and I honestly still haven’t touched anything related to serverside & clientside stuff
I’ll just ask for what I’d love to see with this system - in case you’d do it (easy excuse right? sorry)

Would it be possible to have something like, showing how many clips or ammos they got left & have a template for “purchasing” ammos/clips ?

Much thanks, great looking OTS system

I haven’t added it but it’s very possible! Thank you for your feedback. I just thought it would be stupid to limit someones ammo.

Hey I was wondering how do remove the 3rd person?

You would have to replace every client script with this code:

-- WAITING TILL PLAYER IS LOADED

wait(2)

-- VARIABLES

local plr = game.Players.LocalPlayer
local mouse = game.Players.LocalPlayer:GetMouse()
local tool = script.Parent

local mousedown = false
local debounce = false
local safety = false
local rel = false

local idleAnim = plr.Character:WaitForChild("Humanoid"):LoadAnimation(script.Parent.Configuration.Animations.Idle)
local reloadAnim = plr.Character:WaitForChild("Humanoid"):LoadAnimation(script.Parent.Configuration.Animations.Reload)
local shootAnim = plr.Character:WaitForChild("Humanoid"):LoadAnimation(script.Parent.Configuration.Animations.Shoot)
local safetyAnim = plr.Character:WaitForChild("Humanoid"):LoadAnimation(script.Parent.Configuration.Animations.Safety)
local aimAnim = plr.Character:WaitForChild("Humanoid"):LoadAnimation(script.Parent.Configuration.Animations.Aim)

local set = require(script.Parent.Settings)
local gui = script.AmmoGui:Clone()

local camera = game.Workspace.CurrentCamera
local random = Random.new()

local ts = game:GetService("TweenService")
local uis = game:GetService("UserInputService")
local ots = require(game.ReplicatedStorage.GunSystem["OTS Camera System"])

local InputS = game:GetService("UserInputService")

local camera = game.Workspace.CurrentCamera
local random = Random.new()

local spread_amount = math.rad(5)

local recoil_amount = 0.005
local recoil_acc = CFrame.Angles(0, 0, 0)
local recoil_decay = 0.85

function shootF()
	local shoot_cf = camera.CFrame * CFrame.Angles( 
		random:NextNumber(-recoil_amount, recoil_amount),
		random:NextNumber(-recoil_amount, recoil_amount),
		0
	)
	local shoot_ray = Ray.new(shoot_cf.p, shoot_cf.LookVector)
	camera.CFrame = camera.CFrame * recoil_acc:inverse()
	recoil_acc = recoil_acc * CFrame.Angles(recoil_amount, 0.01, 0)
	camera.CFrame = camera.CFrame * recoil_acc
end

game:GetService("RunService").RenderStepped:Connect(function(dt)
	camera.CFrame = camera.CFrame * recoil_acc:inverse()
	recoil_acc = recoil_acc:Lerp(CFrame.new(), recoil_decay * dt)
	camera.CFrame = camera.CFrame * recoil_acc
end)

-- EQUIP AND UNEQUIP

tool.Equipped:Connect(function()
	if safety == false then
		idleAnim:Play()
	else
		safetyAnim:Play()
	end
	debounce = true
	script.Parent.Handle.Equip:Play()
	wait(0.2)
	if safety == false then
		debounce = false
	end
	gui.Ammo.Text = script.Parent.Ammo.Value
	gui.Parent = plr.PlayerGui
end)

tool.Unequipped:Connect(function()
	gui.Parent = plr
	shootAnim:Stop()
	idleAnim:Stop()
	reloadAnim:Stop()
	safetyAnim:Stop()
	script.Parent.Handle.Reload:Stop()
end)

tool.AncestryChanged:Connect(function()
	if tool.Parent ~= plr.Character then
		gui.Parent = plr
		shootAnim:Stop()
		idleAnim:Stop()
		reloadAnim:Stop()
		safetyAnim:Stop()
		script.Parent.Handle.Reload:Stop()
	end
end)

-- MOUSE FUNCTIONS

tool.Activated:Connect(function()
	if set.automatic == false then
		if debounce == false and script.Parent.Ammo.Value > 0 and safety == false then
			debounce = true
			script.Parent.Configuration.RemoteEvents.Fire:FireServer(mouse.Hit.p)
			shootAnim:Play()
			shootF()
			wait(set.rate)
			debounce = false
		end
	else
		if debounce == false and script.Parent.Ammo.Value > 0 and safety == false then
			mousedown = true
			repeat
				if plr.Character:FindFirstChild(tool.Name) and script.Parent.Ammo.Value ~= 0 and script.Parent.Ammo.Value > 0 then
					script.Parent.Configuration.RemoteEvents.Fire:FireServer(mouse.Hit.p)
					shootAnim:Play()
					shootF()
					wait(set.rate)
				end
			until mousedown == false or debounce == true or safety == true or script.Parent.Ammo.Value < 1 or script.Parent.Ammo.Value == 0
		end
	end
end)

mouse.Button1Up:Connect(function()
	if mousedown == true then
		mousedown = false
		debounce = true
		delay(set.rate, function()
			debounce = false
		end)
	end
end)

-- AMMO GUI

script.Parent.Ammo.Changed:Connect(function()
	gui.Ammo.Text = script.Parent.Ammo.Value
end)

-- KEYBINDS

uis.InputBegan:Connect(function(input, chatting)
	if input.KeyCode == Enum.KeyCode.R then
		if chatting == false and script.Parent.Ammo.Value < set.ammo and plr.Character:FindFirstChild(tool.Name) then
			if rel == false then
				rel = true
				debounce = true
				reloadAnim:Play()
				script.Parent.Configuration.RemoteEvents.Reload:FireServer()
				wait(set.reload)
				if safety == false then
					debounce = false
				end
				rel = false
			end
		end
	elseif input.KeyCode == Enum.KeyCode.G then
		if chatting == false and plr.Character:FindFirstChild(tool.Name) then
			if safety == false then
				debounce = true
				safety = true
				safetyAnim:Play()
			else
				debounce = false
				safety = false
				safetyAnim:Stop()
				idleAnim:Play()
			end
		end
	end
end)

-- KILL FEED

script.Parent.Configuration.RemoteEvents.Kill.OnClientEvent:Connect(function(plr, user)
	local t = script.Template:Clone()
	t.Parent = gui.KillFeed
	gui.KillFeed.Sound:Play()
	t.Text = "[ KILLED: "..string.upper(user).." ]"
	delay(2, function()
		ts:Create(t, TweenInfo.new(0.5), {TextTransparency = 1}):Play()
		ts:Create(t, TweenInfo.new(0.5), {TextStrokeTransparency = 1}):Play()
		wait(0.5)
		t:Destroy()
	end) 
end)

-- DEATH

plr.Character.Humanoid.Died:Connect(function()
	ots:Disable()
	ots:SetCharacterAlignment(false)
	tool:Destroy()
end)
2 Likes

Thank you, this really helped a lot.

Hey, do you know how to reduce lag in your guns. When I tested it with my friends they said it was laggy.

You can since you own it, you can put it back into the game by going to toolbox, going to my animations and click your animation

image

image

1 Like

Heya, very good system; Though I was wondering how do you change the de-spawn time on the bullets?

That is veryy good and useful, I love it! I don’t think I’ll be using it because I have my own fps framework, but it would be very nice if you have the character look up and down as the camera. I can help you if you need.

There is one problem is that your bullet count is getting to negative. You may want to change it to > 0 or >= 1 for the statement

You can’t the lag has been reduced as much as possible, the visuals are on the client might be FPS lag but that’s it.

1 Like

I know how to do it but I’m not sure how to make it disable when the tool is unequipped

You have to go to StarterPlayerScripts, open the Gun script and change it. It’s complicated if you don’t know scripting so I would not recommend.

Let me make this clear. The animations wont be released since they are old, I cannot find them and they are bad. I am not an animator and it doesn’t take much effort to remake them.

What line exactly is it in? I’m not exactly a scripter but I know basic stuff.

They should be in your toolbox under animations. And Even if they’re old it is still useable.

There is only a time of disappearing when it doesn’t hit anything. That would be in line 33. It’s currently set to 5 seconds. If you want to change the speed of it flying you can do it in line 39.