Gear Gamepass Issues (Speed and Gravity coils)

It could be because the playerAdded function hasn’t been called on the current players, and the script is somehow delayed? I added some print statements into my code and initialized the players at the bottom. In the output, see if you can catch “YEET” or “NAH”, which determines whether the gamepass is owned.

-- Services and Variables
local Players = game:GetService("Players")
local MarketplaceService = game:GetService("MarketplaceService")
local ServerStorage = game:GetService("ServerStorage")
local GAMEPASS_ID = 19711172

-- A cache to index if a player owns the gamepass when they join
local cache = {}

local function playerAdded(player)
	player.CharacterAdded:Connect(function(character)
		-- Repeats until ownership is detected
		if cache[player] == nil then
			repeat 
				wait()
			until
			cache[player] ~= nil
		end

		-- If the player owns the gamepass, clone the gravity coil into their backpack
		local ownsGamepasses = cache[player]
		if ownsGamepasses then
			print("YEET")
			ServerStorage.GravityCoil:Clone().Parent = player:WaitForChild("Backpack")
		else
			print("NAH")
		end
	end)
	
	-- This runs ONLY ONCE because UserOwnsGamePassAsync is an expensive function
	-- IT shouldn't be called every time the player spawns, so ownership will be indexed in the cache
	local success, hasPass = pcall(function()
		return MarketplaceService:UserOwnsGamePassAsync(player.UserId, GAMEPASS_ID)
	end)
	if success then
		cache[player] = hasPass
	else
		warn("Failed to retrieve ownership data: " .. player.Name) 
		cache[player] = false
	end
end

-- Initialize Players
for _, player in ipairs(Players:GetPlayers()) do
	coroutine.wrap(playerAdded)(player)
end
Players.PlayerAdded:Connect(playerAdded)

If you see “YEET” and the tool still isn’t in the backpack, then something is wrong with the cloning. BUT, if you see “NAH”, then you don’t own the gamepass!

Let me know if you have any questions, I’m going to head off for now but I’ll check in

This is not an expensive function since the result is cached.

1 Like

Ahhhh thank you for that useful info! I should rewrite some of my code now considering I’ve had a custom caching system for it :skull: much appreciated!

I’ll rewrite the code above soon :slight_smile:

1 Like

The result is only cached on the server (at least what it seem, based on that other functions that have this behaviour) however therefore calls on the client are expensive.

3 Likes

You can read more into this in caching behavior here: MarketplaceService | Roblox Creator Documentation

1 Like

Ah yes, i was just on that page haha! I remember now why I had a custom caching system, it was because of the PromptGamePassPurchase and the Finished event, since the caching system of this async doesn’t handle that. But since this code doesn’t handle in-game purchases and receiving the tools in real-time, using the async on each spawn should be durable :joy:

1 Like

It’s interesting why the default Roblox system doesn’t account for this, it seems like something that should have been included especially the fact that PlayerOwnsAsset doesn’t have caching behaviour. Am I the only one that wants consistency in these functions?

1 Like

FOR REAL, I really hope they make this a feature soon. I might as well create an open-sourced module that handles the caching for easy use of other developers :face_with_head_bandage:

ANYWAYS @Hattasy

Here is your refined code:

-- Services and Variables
local Players = game:GetService("Players")
local MarketplaceService = game:GetService("MarketplaceService")
local ServerStorage = game:GetService("ServerStorage")

-- PassName and ID
local passes = {
	GravityCoil = 19711172,
        -- ADD MORE HERE IF YOU WANT
}

local function playerAdded(player)
	-- Function that returns true or false, depending on ownership of pass
	local function ownsPass(name)
		return MarketplaceService:UserOwnsGamePassAsync(player.UserId, passes[name])
	end
	
	player.CharacterAdded:Connect(function(character)
		-- Check if player owns "GravityCoil"
		if ownsPass("GravityCoil") then
			ServerStorage.GravityCoil:Clone().Parent = player:WaitForChild("Backpack")
		end
	end)
end

-- Initialize Players
for _, player in ipairs(Players:GetPlayers()) do
	coroutine.wrap(playerAdded)(player)
end
Players.PlayerAdded:Connect(playerAdded)

I created a passes table where you can index the pass name and the ID. There’s a function that checks whether or not the player owns the pass, “ownsPass.” You add add more gamepasses into the table if needed and create your own events :slight_smile:

Oops lol, at the time of writing I must’ve confused events with tools. Sorry about that :grimacing:

Cheers, I have given up on adding coil gamepassed as every script I have tried fails to award the player with the gamepass

2 Likes

Would you like me to create a sample place for you to take that will work?

Yeah if that’s possible please

try making a player variable and check if they brought the gamepass

Your code logical wise seems fine, so what I am thinking is that either there’s no tool in ServerStorage named “GravityCoil” which causes the code to crash, or if there is an object named so, perhaps its not a Tool object? or maybe the code is running before everything in ServerStorage is loaded?

so to be sure, I recommend that you open the output panel by going view -> output and see if there’s any errors

Sample.rbxl (29.4 KB)