How are these two not the same?

so i was trying to make a script where when the player buys the tool in the shop it detects that, and gives them the tool, and it also detects when someone joins and has the game pass, and it gives them the tool. I have a script that works, but i was trying to recreate the script to heighten my skills, but my script was able to give them the tool when they joined with the badge, but not when they buy it in the shop. I finally gave up and compared the two scripts,and i can’t understand what is making my script not work:

local Players = game:GetService("Players")
local boomboxGamepassId = 827084219
local mps = game:GetService("MarketplaceService")

local boombox = script.BoomBox

local function giveboombox(player)
	repeat task.wait() until player ~= nil and player.Backpack ~= nil and player.Character ~= nil
	
	player.CharacterAdded:Connect(function(char)
		if mps:UserOwnsGamePassAsync(player.UserId,boomboxGamepassId) then
			if not player.Backpack:FindFirstChild(boombox.Name) and not player.Character:FindFirstChild(boombox.Name) then
				local clone = boombox:Clone()
				clone.Parent = player.Backpack
			end
		end
	end)
end

game.Players.PlayerAdded:Connect(giveboombox)

for _, player in ipairs(Players:GetPlayers()) do
	giveboombox(player)
end

mps.PromptGamePassPurchaseFinished:Connect(function(player, gamePassId, wasPurchased)
	if gamePassId == boomboxGamepassId and wasPurchased then
		giveboombox(player)
	end
end)

and make this one work:

local Players = game:GetService("Players")
local MarketplaceService = game:GetService("MarketplaceService")
local ServerStorage = game:GetService("ServerStorage")

-- Assuming the BoomBox tool is stored in ServerStorage for cloning purposes
-- Make sure to move the BoomBox tool from Workspace to ServerStorage in your game
local boomboxTool = script.BoomBox

-- Replace GAMEPASS_ID with the actual ID of your Boombox gamepass
local VIP_GAMEPASS_ID = 827084219 -- Example Gamepass ID, replace with your own

-- Function to handle giving the Boombox to a player
local function giveBoombox(player)
	repeat task.wait() until player ~= nil and player.Backpack ~= nil and player.Character ~= nil

	if not boomboxTool then
		warn("Boombox tool not found in ServerStorage")
		return
	end

	-- Check if the player already has a Boombox
	if not player.Backpack:FindFirstChild(boomboxTool.Name) and not player.Character:FindFirstChild(boomboxTool.Name) then
		print("about to give gamepass")
		local clone = boomboxTool:Clone()
		clone.Parent = player.Backpack
	end
end

-- Function to check if the player has the gamepass and give them the Boombox
local function onPlayerAdded(player)
	-- Using pcall to handle any errors that might occur when checking for the gamepass
	local success, hasGamepass = pcall(function()
		return MarketplaceService:UserOwnsGamePassAsync(player.UserId, VIP_GAMEPASS_ID)
	end)

	if success and hasGamepass then
		giveBoombox(player)
	else
		if not success then
			warn("Failed to check if player owns Boombox gamepass")
		end
	end
end

-- Connect the onPlayerAdded function to the PlayerAdded event
Players.PlayerAdded:Connect(onPlayerAdded)

-- Iterate through all existing players in case the script is added while the game is running
for _, player in ipairs(Players:GetPlayers()) do
	onPlayerAdded(player)
end

-- Listen for gamepass purchase
MarketplaceService.PromptGamePassPurchaseFinished:Connect(function(player, gamePassId, wasPurchased)
	if gamePassId == VIP_GAMEPASS_ID and wasPurchased then
		giveBoombox(player)
	end
end)

From your devforum post, i thought you meant the top one was the original and the bottom one as your recreation. I believe it is the other way around though? This is the assumption that the rest of my reply is based on.


The problem is that you’ve added player.CharacterAdded. As you are waiting for the character on the first line of the giveboombox() function, the event won’t trigger until the player resets their character.

I’m assuming that your addition of CharacterAdded was to ensure that the player gets it even if they die / reset. A way to keep this functionality while also getting the desired outcome is to add the checks once prior to the character added event.

i.e.

local function giveboombox(player)
	repeat task.wait() until player ~= nil and player.Backpack ~= nil and player.Character ~= nil
	
    if mps:UserOwnsGamePassAsync(player.UserId,boomboxGamepassId) then
		if not player.Backpack:FindFirstChild(boombox.Name) and not player.Character:FindFirstChild(boombox.Name) then
			local clone = boombox:Clone()
			clone.Parent = player.Backpack
		end
	end

	player.CharacterAdded:Connect(function(char)
		if mps:UserOwnsGamePassAsync(player.UserId,boomboxGamepassId) then
			if not player.Backpack:FindFirstChild(boombox.Name) and not player.Character:FindFirstChild(boombox.Name) then
				local clone = boombox:Clone()
				clone.Parent = player.Backpack
			end
		end
	end)

As this results in repeated code, you may wish to enclose it within another function.

e.g.

local function giveboombox(player)
	repeat task.wait() until player ~= nil and player.Backpack ~= nil and player.Character ~= nil
	local function give(char)
		if mps:UserOwnsGamePassAsync(player.UserId,boomboxGamepassId) then
			if not player.Backpack:FindFirstChild(boombox.Name) and not player.Character:FindFirstChild(boombox.Name) then
				local clone = boombox:Clone()
				clone.Parent = player.Backpack
			end
		end
	end
	
	give(player.Character)
	player.CharacterAdded:Connect(give)
end

Feel free to reply if my ‘solution’ doesn’t end up solving your issue, but know that I may take a bit to respond (timezones :smiley: )