Need help making a specific type of weapon storage system

  1. What do you want to achieve? A storage system with 3 slots by default (and more purchasable, but I’ll deal with that later) that lets you deposit a weapon into a slot, switching out your current weapon with the stored one on that slot, updating the slot’s text label to say the name of the stored weapon and the text label of the current weapon at the top of the ui to say your equipped weapon, as well as updating the leaderstats to the equipped weapon.

  2. What is the issue? I’m having real trouble making it work.

  3. What solutions have you tried so far? I have looked for solutions but I couldn’t find anything relating to the very specific type of storage system I want. I tried making it myself, tho I’m a beginner so it’s really bad and barely functional. I could make it deposit the weapon switching it out with the empty slot and be able to switch it out again but barely (I couldn’t get it to update leaderstats) and it’s also glitchy and breaks completely after that.

Scripts:

2 Likes

A few things going on here, and the first one explains why leaderstats never update.

The server can’t see your text label change.

Your LocalScript sets EquippedKaguneTextLabel.Text, and then the server does this:

game.ReplicatedStorage.KaguneValue1.OnServerEvent:Connect(function(player, KaguneValue1, Kagune1TextLabel, EquippedKaguneTextLabel)
	EquippedKaguneTextLabel.Changed:Connect(function()

GUI property changes made by a LocalScript are not replicated back to the server. The server has its own copy of that TextLabel — the one it handed out from StarterGui — and nothing on the server ever writes to it, so that .Changed never fires. Every bit of your leaderstats and ProfileStore code sits inside that callback, so it is dead code. That is exactly why you couldn’t get leaderstats to update.

The bigger one: you’re connecting OnServerEvent inside a per-player function.

InitializeWeapon is called from your PlayerAdded handler, and it connects OnServerEvent inside itself. So the second player who joins adds a second handler to the same RemoteEvent, the third adds a third, and one button click now runs all of them.

They aren’t equivalent handlers, either. profile, character and weapon are upvalues captured from whichever player’s InitializeWeapon call created that connection, while player is the inner function’s own parameter (which shadows the outer one). So when player A clicks Equip, the handler created for player B also runs — and writes to B’s profile. That is your “breaks completely after that”, and it gets worse with every extra player in the server.

Connect each remote exactly once, at the top level of the script, and look up per-player state inside the handler:

local profiles = {}   -- [player] = profile

EquipRemote.OnServerEvent:Connect(function(player, slot)
	if typeof(slot) ~= "number" or slot % 1 ~= 0 or slot < 1 or slot > 3 then return end
	local profile = profiles[player]
	if not profile then return end
	-- swap, write leaderstats, save
end)

Don’t send GUI objects through remotes at all. Send the slot number, like above. Right now the server takes the weapon name out of the client’s own text label, which means anyone can equip anything by editing a label locally — the server is trusting the exact thing the exploiter controls.

Two smaller bugs:

EquipButton1.MouseButton1Click:Connect(function(player)MouseButton1Click passes no arguments. That player is nil, and it shadows the real player you defined at the top.

repeat EquippedKaguneTextLabel.Text = "Equipped Kagune: Eto" until EquippedKaguneTextLabel.Text == "Equipped Kagune: Eto"

This is an assignment written as a loop. It either exits after one pass or spins forever with no yield in it and freezes that script. Just assign it.

Also profile.Data.Weapon = tostring(weapon) on a StringValue gives you the instance’s Name, not its Value. It only looks right because you named the instance the same as its value — use weapon.Value.

The shape I’d aim for

  • Server owns the state: profile.Data.Slots = {"None", "None", "None"} plus profile.Data.Equipped.
  • Client sends intent only — “equip slot 2”, “store my current weapon in slot 3”.
  • Server validates, swaps, writes leaderstats and the profile, then fires one remote back with the new state.
  • Client renders all four labels from whatever it just received, and never decides anything itself.

That will also collapse the file a long way. The repeated per-weapon if chains all become one table lookup keyed by weapon name, and you stop having two copies of the truth that can disagree.

theres alot of bugs in your code that i’d probably rewrite it all if i was you

Ignore deleted reply, figured it out, thanks for the help