Only allow player to equip one sword at once from UI Shop

Hello!

I’m currently creating a swordfighting related game, and I’ve scripted (not a scripter, so I tried my best) a shop UI that lets players buy items, shows a confirmationUI, and then deducts the gems and allows them to equip the sword.

However, I’d like to adjust the script so players can only equip one sword from the shop at once. I have no idea on where to start and would appreciate some guidance, thanks.


image

PurchaseScript

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")

local buyButton = script.Parent
local equipButton = script.Parent.EquipButton
local clickSound = game.ReplicatedStorage.GameSounds.ClickSound
local hoverSound = game.ReplicatedStorage.GameSounds.HoverSound

local sword_to_give = script.Parent.Name
local sword = ReplicatedStorage.Swords:FindFirstChild(sword_to_give)

local gemCost = script.Parent.Price.Value

local buyButtonConnection
local yesButtonConnection
local uiElement = game.Players.LocalPlayer.PlayerGui:WaitForChild("UserUI").SwordPurchaseUI

local function TweenUI()
	uiElement.Position = UDim2.new(0.5, 0, 1.5, 0)
	uiElement.Size = UDim2.new(0, 0, 0, 0)
	uiElement.Visible = true
	game.Lighting.Blur.Enabled = true

	local tweenInfo = TweenInfo.new(
		1,
		Enum.EasingStyle.Quad,
		Enum.EasingDirection.Out,
		0,
		false,
		0
	)

	local targetProperties = {
		Position = UDim2.new(0.275, 0,0.258, 0),
		Size = UDim2.new(0, 589,0, 387),
	}

	local tween = TweenService:Create(uiElement, tweenInfo, targetProperties)
	tween:Play()
end

script.Parent.MouseEnter:Connect(function()
	hoverSound:Play()
end)

local function buyItem()
	local player = Players.LocalPlayer
	local playerGui = player.PlayerGui
	clickSound:Play()
	script.Parent.Parent.Parent.Visible = false

	local confirmationUI = playerGui.UserUI.SwordConfirmationUI
	confirmationUI.SwordName.Text = sword_to_give

	if confirmationUI then
		confirmationUI.Visible = true
		confirmationUI.GemsCost.Text = gemCost
		confirmationUI.SwordImage_Outline.Image = script.Parent.ImageLabel.Image
		confirmationUI.SwordImage.Image = confirmationUI.SwordImage_Outline.Image
		game.Lighting.Blur.Enabled = true

		local yesButton = confirmationUI:FindFirstChild("YesButton")
		if yesButton then
			yesButtonConnection = yesButton.MouseButton1Click:Connect(function()
				if player.leaderstats.Gems.Value >= gemCost then
					confirmationUI.Visible = false
					equipButton.Visible = true
					player.leaderstats.Gems.Value = player.leaderstats.Gems.Value - gemCost
					buyButtonConnection:Disconnect()
					yesButtonConnection:Disconnect()
					game.Players.LocalPlayer.PlayerGui.Frames.SwordsFrame.Visible = false
					game.ReplicatedStorage.GameSounds.ClickSound:Play()
					uiElement.GemCost.Text = gemCost
					uiElement.SwordName.Text = sword_to_give
					uiElement.SwordImage.Image = script.Parent.ImageLabel.Image
					TweenUI()
					game.ReplicatedStorage.GameSounds.PurchaseSound:Play()
				else
					confirmationUI.YesButton.Image = "rbxassetid://17330634285"
					wait(2)
					confirmationUI.YesButton.Image = "rbxassetid://17324203359"
				end
			end)
		end

		local noButton = confirmationUI:FindFirstChild("NoButton")
		if noButton then
			noButton.MouseButton1Click:Connect(function()
				if yesButtonConnection then
					yesButtonConnection:Disconnect()
				end
				confirmationUI.Visible = false
				game.ReplicatedStorage.GameSounds.ClickSound:Play()
				script.Parent.Parent.Parent.Visible = true
				game.Lighting.Blur.Enabled = false
			end)
		end
	end
end

buyButtonConnection = buyButton.MouseButton1Click:Connect(buyItem)

equipButton.MouseEnter:Connect(function()
	game.ReplicatedStorage.GameSounds.HoverSound:Play()
end)

equipButton.MouseButton1Click:Connect(function()
	game.ReplicatedStorage.GameSounds.ClickSound:Play()
	if equipButton.Image == "rbxassetid://17316025753" then
		if sword then
			local swordClone = sword:Clone()
			swordClone.Parent = Players.LocalPlayer.Backpack
			equipButton.Image = "rbxassetid://17316048949"
		end
	elseif equipButton.Image == "rbxassetid://17316048949" then
		local equippedSword = Players.LocalPlayer.Backpack:FindFirstChild(sword_to_give)
		if equippedSword then
			equippedSword:Destroy()
			equipButton.Image = "rbxassetid://17316025753"
		end
	end
end)

Still need help with this if possible. :slight_smile:

You can add the sword to a starter pack name “sword”. From there, you can check if the starter pack has a tool name sword. If it does, it means the player have already equipped a sword. From there, you can replace that sword with the new sword from the shop.

Thanks, do you have any advice on where to put the objectValue and how I would set/check its value?

I updated my text, I realize that might be a better way to store a sword

I highly recommend utilizing Roblox’s DataStore service. Data stores allow you to store and retrieve data across server shutdowns and player sessions, ensuring that players’ progress is saved.

By using a data store, you can store information about which players have equipped swords and retrieve this information whenever needed. This way, even if a player leaves and rejoins the game, their equipped sword status will be retained.

1 Like

I was also worrying about this, as you can see the PurchaseScript is really messy and basic since I have little programming experience but enough to understand things.

Do you think you could provide a sample/short explanation on how I would use DataStore within this script? Thanks alot.

Place sword in serverstorage and place to clone in purchase and clone parent
Is plr.BackPack or plr.Character

Please read the topic, I don’t require assistance on how to make the swords equipable, I need help on only making one equipable at once.

The script already has the features you are describing.

LocalScripts cannot directly access data stores. However, you can work around this limitation by using RemoteEvents or RemoteFunctions. These allow the LocalScript to send requests or data to the server, which can then handle the data store interactions.

I would also highly recommend learning about DataStore from the Roblox documentation, as it provides a great overview of how it works. I’m here to help you, not to spoon-feed you code… You can find more information in the Data Stores Documentation on the Roblox Creator Hub.

I don’t want to be spoon-fed, I’m just asking if I could get some pointers or samples so I can work from there.

I’m not a scripter/programmer so these new terms are difficult for me, I appreciate the documentation you’ve provided me however I’m really going to need some further explanation on how I would work around the DataStore limitation by using a RemoteEvent or RemoteFunction.

Again, I don’t wish to be spoon-fed as I am also interested in learning for myself I’d just appreciate some advice on how I would use one of the two RemoteEvent or RemoteFunction to work around the DataStore limitation within LocalScripts as I’ve just looked through the documentation but still struggling to understand, thanks.

Work with this

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")

local buyButton = script.Parent
local equipButton = script.Parent.EquipButton
local clickSound = ReplicatedStorage.GameSounds.ClickSound
local hoverSound = ReplicatedStorage.GameSounds.HoverSound

local sword_to_give = script.Parent.Name
local sword = ReplicatedStorage.Swords:FindFirstChild(sword_to_give)

local gemCost = script.Parent.Price.Value

local buyButtonConnection
local yesButtonConnection
local uiElement = game.Players.LocalPlayer.PlayerGui:WaitForChild("UserUI").SwordPurchaseUI

-- Added: Variable to track the currently equipped sword
local currentlyEquippedSword = nil

local function TweenUI()
    -- TweenUI Code Unchanged
end

-- Unchanged: MouseEnter Connections

local function buyItem()
    -- buyItem Code Unchanged, except for parts that involve equipping swords
end

buyButtonConnection = buyButton.MouseButton1Click:Connect(buyItem)

equipButton.MouseEnter:Connect(function()
    -- Unchanged: Play HoverSound
end)

equipButton.MouseButton1Click:Connect(function()
    clickSound:Play()
    local player = Players.LocalPlayer
    local backpack = player.Backpack
    
    if equipButton.Image == "rbxassetid://17316025753" then
        if sword then
            -- Check if another sword is already equipped
            if currentlyEquippedSword then
                -- If so, remove the previously equipped sword
                local prevEquippedSword = backpack:FindFirstChild(currentlyEquippedSword)
                if prevEquippedSword then
                    prevEquippedSword:Destroy()
                end
            end
            -- Equip the new sword and update the currently equipped sword
            local swordClone = sword:Clone()
            swordClone.Parent = backpack
            currentlyEquippedSword = sword_to_give
            equipButton.Image = "rbxassetid://17316048949"
        end
    elseif equipButton.Image == "rbxassetid://17316048949" then
        local equippedSword = backpack:FindFirstChild(sword_to_give)
        if equippedSword then
            equippedSword:Destroy()
            equipButton.Image = "rbxassetid://17316025753"
            -- Update the currently equipped sword to nil since no sword is equipped now
            currentlyEquippedSword = nil
        end
    end
end)

In the server script, the code retrieves data from the DataStore to determine if players have swords equipped, and it listens for RemoteFunction calls named “EquipSwordFunction” to handle requests from clients.

local DataStoreService = game:GetService("DataStoreService")
local equippedSwordsDataStore = DataStoreService:GetDataStore("EquippedSwords")

-- Example of a RemoteFunction?
game:GetService("ReplicatedStorage").EquipSwordFunction.OnServerInvoke = function(player)
    -- Handle DataStore here (read/write data)
    local success, equipped = pcall(function()
        return equippedSwordsDataStore:GetAsync(tostring(player.UserId))
    end)
    if success then
        return equipped or false
    else
        warn("Error", player.Name)
        return false
    end
end

In the LocalScript, the code invokes the RemoteFunction “EquipSwordFunction” on the server, passing the local player as an argument, and it handles the server’s response by printing whether the player has a sword equipped or logging an error message if the invocation fails, these should get you started.

local success, isEquipped = pcall(game:GetService("ReplicatedStorage").EquipSwordFunction.InvokeServer, game.Players.LocalPlayer)
if success then
    print("Sword equipped?", isEquipped)
else
    warn("Error?", isEquipped)
end

I want to give a little more information to what @Xethele is trying to say, you can try storing some value as a dictionary so that when you retrieve the saved value from Datastore, you can have the code act upon that value. For example:

-- This is pseudocode, none of this would run when copy and pasting
Datastore = DataContainer
Data = Get player data from datastore

if data then
     if data.equipSwordData = 5 then
          equip sword type 5 to player
     end
end

function storingData()
     dataTable = {
          swordEquipData = current sword type equipped
     }

     Datastore.storedata = dataTable
end

You Need remove the already tool and after remove give
local ok = character:findfirstchild(“Your2Tool”)
if ok
ok:Destroy()
end
YourTool:Clone.Parent = character
– This make one sword per time in you character/backpack

Put the swords in the player game.players.player.backback INSTEAD of just parenting it to the player model. this allows for inserting tools without equipping more then 1.