Strange backpack behavior

I must be doing something wrong in managing the tools in a backpack because I’m seeing some really strange behavior. In some situations the print statements indicate that certain tools got added to the backpack, but I don’t see them listed in the UI. In other situations i’m seeing duplicated items in my backpack. Can anyone see anything obviously wrong in my code:

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local PlayerPoints = game:GetService("DataStoreService"):GetDataStore("PlayerPoints")
local StarterPack = game:GetService("StarterPack")

local LevelChangedEvent = ReplicatedStorage:WaitForChild("LevelChangedEvent")
local WindowShatteredEvent = ReplicatedStorage:WaitForChild("WindowShatteredEvent")

local STARTING_POINTS = 0
local STARTING_LEVEL = 1

game.Players.CharacterAutoLoads = false

local function addWeapon(player, weapon)
	if not player.Backpack:FindFirstChild(weapon.Name) then
		local clone = weapon:Clone()
		clone.Parent = player.Backpack
		print("addWeapon", weapon.Name)
	end
end

local function setupLeaderboard(player)
	local folder = Instance.new("Folder")
	local points = Instance.new("IntValue")
	local level = Instance.new("IntValue")
	points.Value = STARTING_POINTS
	level.Value = STARTING_LEVEL
	folder.Name = "leaderstats"
	folder.Parent = player
	points.Name = "Points"
	points.Changed:Connect(function(newPointValue)
		print("points.Changed: ", newPointValue)
		if newPointValue < 20 then
			level.Value = 1
		end
		if newPointValue >= 20 then
			if level.Value < 2 then
				level.Value = 2
			end
		end
		if newPointValue >= 40 then
			if level.Value < 3 then
				level.Value = 3
			end
		end
		if newPointValue >= 80 then
			if level.Value < 4 then
				level.Value = 4
			end
		end
		if newPointValue >= 160 then
			if level.Value < 5 then
				level.Value = 5
			end
		end
	end)
	points.Parent = folder
	level.Name = "Level"
	level.Changed:Connect(function(newLevelValue)
		print("level.Changed: ", newLevelValue)
		if newLevelValue >= 2 then
			local weapon = ReplicatedStorage.Weapons["Grenade Launcher"]
			addWeapon(player, weapon)
		end
		if newLevelValue >= 3 then
			local weapon = ReplicatedStorage.Weapons["Automatic Rifle"]
			addWeapon(player, weapon)
		end
		if newLevelValue >= 4 then
			local weapon = ReplicatedStorage.Weapons["Rocket Launcher"]
			addWeapon(player, weapon)
		end
		if newLevelValue >= 5 then
			local weapon = ReplicatedStorage.Weapons["Railgun"]
			addWeapon(player, weapon)
		end
	end)
	level.Parent = folder
	local success, savedPlayerPoints = pcall(function()
		return PlayerPoints:GetAsync(player.UserId)
	end)
	if success then
		if savedPlayerPoints then
			points.Value = savedPlayerPoints
		else
			points.Value = STARTING_POINTS
		end
	end
end

game.Players.PlayerAdded:Connect(function(player)
	setupLeaderboard(player)
	player.CharacterAdded:Connect(function(character)
		local humanoid = character:WaitForChild("Humanoid")
		humanoid.Died:Connect(function()
			player:LoadCharacter()
		end)
	end)
	player:LoadCharacter()
end)

game.Players.PlayerRemoving:Connect(function(player)
	local success, errorMessage = pcall(function()
		PlayerPoints:SetAsync(player.UserId, player.leaderstats.Points.Value)
	end)
	if not success then
		warn(errorMessage)
	end
end)

WindowShatteredEvent.Event:Connect(function(player)
	player.leaderstats.Points.Value += 1
end)

local event = Instance.new("RemoteEvent")
event.Name = "ResetEvent"
event.OnServerEvent:Connect(function(player)
	player.leaderstats.Points.Value = STARTING_POINTS
end)
event.Parent = ReplicatedStorage
1 Like

you should add special exceptions and add extra ‘and’ statements

newLevelValue >= 2 and newLevelValue < 3

dont forget to apply it to the other ones with a similar concept

No, that part of the code works the way I want it to work. So, for example, when you return to a game (or spawn in after dying) you receive all the weapons up to and including the level you achieved. What’s weird is that I end up with duplicates in my backpack when I would think the following code would prevent that:

local function addWeapon(player, weapon)
	if not player.Backpack:FindFirstChild(weapon.Name) then
		local clone = weapon:Clone()
		clone.Parent = player.Backpack
		print("addWeapon", weapon.Name)
	end
end
1 Like

you need to add an “and” write down player.Character:FindFirstChild(weapon.Name) as well because when you get one and hold it, it goes inside your model and then if you level up again there’ll be a duplicate of the one your holding

1 Like

Awesome. I was able to fix the duplicates issue with this variation of the code you suggested:

local function addWeapon(player, weapon)
	print("addWeapon1", weapon.Name)
	if player.Character and not player.Character:FindFirstChild(weapon.Name)  then
		if not player.Backpack:FindFirstChild(weapon.Name) then
			local clone = weapon:Clone()
			clone.Parent = player.Backpack
			print("addWeapon2", weapon.Name)
		end
	end
end

Now my remaining problem is when I return to a game at level 5, for example, I see the print statements for all the level changes but the weapons aren’t showing up in my backpack… The output looks like this:

  12:01:07.066  points.Changed:  179  -  Server - LeaderboardServerEvents:35
  12:01:07.066  level.Changed:  2  -  Server - LeaderboardServerEvents:63
  12:01:07.066  addWeapon1 Grenade Launcher  -  Server - LeaderboardServerEvents:15
  12:01:07.066  level.Changed:  3  -  Server - LeaderboardServerEvents:63
  12:01:07.067  addWeapon1 Grenade Launcher  -  Server - LeaderboardServerEvents:15
  12:01:07.067  addWeapon1 Automatic Rifle  -  Server - LeaderboardServerEvents:15
  12:01:07.067  level.Changed:  4  -  Server - LeaderboardServerEvents:63
  12:01:07.067  addWeapon1 Grenade Launcher  -  Server - LeaderboardServerEvents:15
  12:01:07.067  addWeapon1 Automatic Rifle  -  Server - LeaderboardServerEvents:15
  12:01:07.067  addWeapon1 Rocket Launcher  -  Server - LeaderboardServerEvents:15
  12:01:07.067  level.Changed:  5  -  Server - LeaderboardServerEvents:63
  12:01:07.067  addWeapon1 Grenade Launcher  -  Server - LeaderboardServerEvents:15
  12:01:07.068  addWeapon1 Automatic Rifle  -  Server - LeaderboardServerEvents:15
  12:01:07.068  addWeapon1 Rocket Launcher  -  Server - LeaderboardServerEvents:15
  12:01:07.068  addWeapon1 Railgun  -  Server - LeaderboardServerEvents:15

This would imply that player.Character is nil at this point in the process, right? How do I get around that?

i think this is because you only receive the weapons when your level changes but since your maximum level, there’s no natural way to level up again for the addweapon function to trigger

so i suggest making a new function, then write these inside the function

and trigger the function after the player’s level has loaded

1 Like

by the way, are you sure that is not from your previous outputs?

1 Like

I figured out the problem. It’s related to your other suggestion. Basically I needed to move the setting up of the leaderboard/levels until after the player’s Character is created, like this:

game.Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(character)
		local humanoid = character:WaitForChild("Humanoid")
		humanoid.Died:Connect(function()
			player:LoadCharacter()
		end)
	end)
	player:LoadCharacter()
	setupLeaderboard(player)
end)

This is because “When a player’s character spawns, the contents of the StarterPack and their StarterGear are copied into their Backpack.”