Need Help With a Weapons Switching System

Hi everyone!

I am trying to make a weapon switching system, like popular Roblox FPS games like Bad Business or Phantom Forces. In those games, the hotbar/backpack is disabled/hidden, and you can switch weapons by scrolling. Does anyone have any ideas on how to achieve this?

6 Likes

Well the following code would disable the HotBar:

game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false)

Then when you want to equip them a tool clone the tool into their Backpack (won’t work if it’s not in the backpack), then use:

player.Character.Humanoid:EquipTool(--tool here)
2 Likes

Thanks for your reply, and I will make sure to test your code, but your reply doesn’t fully tell how to switch tools/weapons with scroll. But thank you for replying never the less.

1 Like

Mouse.WheelForward is what you can use to detect when the player’s scroll wheel is scrolled forward. Once it’s detected, do everything @XdJackyboiiXd21 says. Clone the weapon into the backpack. This is a very simple way however. Pretty sure mechanics in Phantom Forces and such are way more complicated.

As @1Urge said you can use this Tactic but if you would want the player to switch make sure to use the tactic @XdJackyboiiXd21 told you also for a easy practice

Thanks for replying, but I also wanted to ask, how can I achieve this: https://gyazo.com/bd5fabe98e5daef0f4f2805fcca091e0 ?

Use Mouse.WheelForward and Mouse.WheelBackward to achieve this. This might only work for three slots. You’d have to make the primary weapon the middle slot.

I’m sorry to be persistent, but can you please try to give a code snippet as an example? I haven’t worked with mouse events before. Thanks!

It gives an example in the API reference link 1Urge linked on his message:

and as said, it is an event of Mouse. So you can just go to the Mouse API page and learn how to use it.

2 Likes

I highly recommend using UserInputService:

local UserInputService = game:GetService("UserInputService")

UserInputService.InputChanged:Connect(function(input, gameProcessedEvent)
    if gameProcessedEvent then
        return
    end
    if input.UserInputType == Enum.UserInputType.MouseWheel then
        local direction = input.Position.Z > 0 and "up" or "down"
    end
end)
1 Like

I know you can do it that way too. Not trying to be disrespectful, but is there an advantage to using that method rather than using the Mouse Event made for it?

Yeah, I completely understand. There are 2 main reasons why I use it:
Consistency/Efficiency and Input Registering.

UserInputService/ContextActionService can handle pretty much any input you throw at it. For consistency sakes, all you need is one service to achieve inputs such as the Mouse, Keyboard, Touch, Gamepad, etc.

Separating keyboard/mouse inputs into 2 different APIs like so;

local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")

local Player = Players.LocalPlayer
local Mouse = Player:GetMouse()

UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
	if gameProcessedEvent then
		return
	end
	if input.KeyCode == Enum.KeyCode.E then
		print("Use E skill")
	end
end)

Mouse.Button1Down:Connect(function()
	print("Basic attack")
end)

Mouse.WheelForward:Connect(function()
	print("Scroll up in inventory")
end)

Mouse.WheelBackward:Connect(function()
	print("Scroll down in inventory")
end)

There is nothing wrong with using this method but the occasional might mouse events activating while you’re focused inside a TextBox or have the escape menu opened (need citation).

Instead, however, it is recommended (as even the roblox wiki recommends it), to use UserInputService/ContexActionService for all types of inputs.

local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")

UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
	if gameProcessedEvent then
		return
	end
	if input.UserInputType == Enum.UserInputType.Keyboard then
		if input.KeyCode == Enum.KeyCode.E then
			print("Use E skill")
		end
	elseif input.UserInputType == Enum.UserInputType.MouseButton1 then
		print("Basic attack")
	end
end)

UserInputService.InputChanged:Connect(function(input, gameProcessedEvent)
	if gameProcessedEvent then
		return
	end
	if input.UserInputType == Enum.UserInputType.MouseWheel then
		local direction = input.Position.Z > 0 and "up" or "down"
		if direction == "up" then
			print("Scroll up inventory")
		elseif direction == "down" then
			print("Scroll down inventory")
		end
	end
end)

It is much cleaner and easier to work with instead of having more multiple events with 2 different APIs. Say you wanted to have an event for Mouse Movement and right click? Or have touch/controller support? Instead of creating new events for those using the Mouse API along with having to use UserInputService anyways for touch/controller, you can simply add onto the already existing UserInputService events.

Another example: say you have a debounce to your inputs, such as you’re unable to attack while casting a spell, instead of copy pasting your if checking, you only need to check it for your InputBegan and InputChanged.

local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")

local BusyState = false

UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
	if gameProcessedEvent or BusyState then
		return
	end
	BusyState = true
	if input.UserInputType == Enum.UserInputType.Keyboard then
		if input.KeyCode == Enum.KeyCode.E then
			print("Use E skill")
			wait(1)
		end
	elseif input.UserInputType == Enum.UserInputType.MouseButton1 then
		print("Basic attack")
		wait(1)
	end
	BusyState = false
end)

UserInputService.InputChanged:Connect(function(input, gameProcessedEvent)
	if gameProcessedEvent then
		return
	end
	if input.UserInputType == Enum.UserInputType.MouseWheel then
		local direction = input.Position.Z > 0 and "up" or "down"
		if direction == "up" then
			print("Scroll up inventory")
		elseif direction == "down" then
			print("Scroll down inventory")
		end
	end
end)

The Mouse API is superseded by UserInputService/ContextActionService that has a more widespread use, so it’s good practice to use these 2 services. Source:

2 Likes

Is it ok if you give a working example of a weapon switching system please? Thanks!

1 Like

That requires coming up with an actual custom system that you can integrate with other frameworks. It’s not easy as whipping out a 20-liner code. You need to understand why and how things work the way they do.

A SIMPLE custom example will look something like this, and will require the following knowledge:

  • A new Backpack is created every time a player spawns
  • The Backpack instance loads before the character does
  • A Tool on equip moves it inside the Player’s Character
  • A Tool on unequip moves it back to the Player’s Backpack
-- Place inside StarterPlayerScripts

--// Custom system INTEGRATED with default Roblox Tools //--
local Players = game:GetService("Players")
local StarterGui = game:GetService("StarterGui")
local UserInputService = game:GetService("UserInputService")

local Player = Players.LocalPlayer
local Tools = {}

local Keybinds = {
	[Enum.KeyCode.One] = 1,
	[Enum.KeyCode.Two] = 2,
	[Enum.KeyCode.Three] = 3,
	[Enum.KeyCode.Four] = 4,
	[Enum.KeyCode.Five] = 5,
	[Enum.KeyCode.Six] = 6,
	[Enum.KeyCode.Seven] = 7,
	[Enum.KeyCode.Eight] = 8,
	[Enum.KeyCode.Nine] = 9,
	[Enum.KeyCode.Zero] = 10,
}

--// Initializer //--
StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Backpack, false)

--// Input Handler //--
UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
	if gameProcessedEvent then
		return
	end
	if Player.Character == nil then
		return
	end
	local humanoid = Player.Character:FindFirstChild("Humanoid")
	if humanoid == nil then
		return
	end
	-- Handles 0-9 keycodes
	if input.UserInputType == Enum.UserInputType.Keyboard then
		if Keybinds[input.KeyCode] then
			local slot = Keybinds[input.KeyCode]
			local existingTool = Player.Character:FindFirstChildOfClass("Tool")
			if existingTool then
				if Tools[slot] == existingTool then
					humanoid:UnequipTools()
				else
					if Tools[slot] then
						humanoid:EquipTool(Tools[slot])
					end
				end
			else
				if Tools[slot] then
					humanoid:EquipTool(Tools[slot])
				end
			end
		end
	end
end)

UserInputService.InputChanged:Connect(function(input, gameProcessedEvent)
	if gameProcessedEvent then
		return
	end
	if Player.Character == nil then
		return
	end
	local humanoid = Player.Character:FindFirstChild("Humanoid")
	if humanoid == nil then
		return
	end
	-- Handles mouse wheel
	if input.UserInputType == Enum.UserInputType.MouseWheel then
		local direction = input.Position.Z > 0 and 1 or -1
		local existingTool = Player.Character:FindFirstChildOfClass("Tool")
		if existingTool then
			local toolSlot = table.find(Tools, existingTool)
			if toolSlot then
				local toSlot = toolSlot + direction
				if toSlot < 1 then
					toSlot = #Tools
				elseif toSlot > #Tools then
					toSlot = 1
				end
				humanoid:EquipTool(Tools[toSlot])
			end
		end
	end
end)

--// Tools Handler //--
local function AddToolToList(tool)
	if tool:IsA("Tool") then
		if not table.find(Tools, tool) then
			table.insert(Tools, tool)
		end
	end
end

local function RemoveToolFromList(tool)
	if tool:IsA("Tool") then
		if tool.Parent ~= Player.Character then -- Check if tool has been forcefully removed
			local toolIndex = table.find(Tools, tool)
			if toolIndex then
				table.remove(Tools, toolIndex)
			end
		end
	end
end

Player.ChildAdded:Connect(function(backpack)
	if backpack:IsA("Backpack") then
		local character = Player.Character or Player.CharacterAdded:Wait()
		local humanoid = character:WaitForChild("Humanoid", 5)
		if humanoid then
			-- In case any new tools gets added
			local addedConnection = backpack.ChildAdded:Connect(function(tool)
				AddToolToList(tool)
			end)
			-- In case any new tools gets destroyed
			local removedConnection = backpack.ChildRemoved:Connect(function(tool)
				RemoveToolFromList(tool)
			end)
			-- Add already-existing tools
			for _, tool in ipairs(backpack:GetChildren()) do
				AddToolToList(tool)
			end
			-- Clear upon death
			local deadConnection
			deadConnection = humanoid.Died:Connect(function()
				addedConnection:Disconnect()
				removedConnection:Disconnect()
				deadConnection:Disconnect()

				Tools = {}
			end)
		end
	end
end)
12 Likes

im new to scripting but do i have to add the tool name to each of the keybinds? (if that makes sense)

1 Like

You can just place it in StarterPlayerScripts, And Just put the tools in StarterPack And your done. Try Equipping it. It works for me just fine.