Owned text on your gamepass

how do you put text on your gamepass so when it is purchased it will say owned then they can’t purchase it anymore?

1 Like

Are you wanting to do this on a UI or what are you wanting to do this on?
I suggest you look at the PromptGamePassPurchasedFinished event to change your UI when someone has purchased a gamepass.

This can be done, but this would be inefficient since you’d have to create a datastore to save owned gamepasses (with a chance of roblox going down) or this only happening for one time. Here’s the more efficient way to do it: UserOwnsGamePassAsync

Using UserOwnsGamePassAsync, you can do a check like this in a server script and a remote function:

local plrs = game:GetService("Players")
local RS = game:GetService("ReplicatedStorage")
local returnpassowned = RS:WaitForChild("ReturnPassOwned")
local MS = game:GetService("MarketplaceService")

local passId = 0 -- Put your gamepass here
plrs.PlayerAdded:Connect(function(plr)
	while task.wait(5) do
		if MS:UserOwnsGamePassAsync(plr.UserId, passId) then
			returnpassowned:InvokeClient(plr, passId)
			--[[ Any additional benefits you wanna give the player, this is not prone to exploiters since 
			its done on the serverside and checking only if the player owns the gamepass, 
			not if it was fired by a remote or etcetera. ]]
		end
	end
end)
1 Like

Here’d be the localscript side, which changes the text to “Owned”

local RS = game:GetService("ReplicatedStorage")
local returnPassOwned = RS:WaitForChild("ReturnPassOwned")

local passIdFromBefore = 0 -- the passID from before
returnPassOwned.OnClientInvoke = function(passId)
	if passId == passIdFromBefore then
		script.Parent.Text = "Owned"
	end
end
1 Like

ok thanks guys ill need a little help with the datastore tho

No, you don’t need to do a datastore. It’s inefficient as I said. I gave you some better script examples. But if you want to, here: Data Stores | Roblox Creator Documentation

You don’t need the Remote Function and you also don’t need datastores. You can check everytime the player joins the game. (as you already said)

I wrote a small example with the UI.


local MS = game:GetService("MarketplaceService")
local ownedTXT = script.Parent.OWND
local plr = game.Players.LocalPlayer
local GamePassID = 0                   -- Your gamepass id here
game.Loaded:Connect(function()
	if MS:UserOwnsGamePassAsync(plr.UserId, GamePassID) == true then
		ownedTXT.Text = "Owned"
	else
		ownedTXT.Text = "Not Owned"
	end
end)


Screenshot_52

The text will say “owned” if you own it. If not, it will say “not owned”.

1 Like

Ok, I gave some more examples for the DataStore if you still wanna use it (but it’s not recommended) - Here’s the server sided script:

local MSS = game:GetService("MarketplaceService")
local DSS = game:GetService("DataStoreService")
local PDS = DSS:GetDataStore("Gamepasses")
local RS = game:GetService("ReplicatedStorage")
local returnpassowned = RS.ReturnPassOwned

local pass1 = 0 -- Pass ID
MSS.PromptGamePassPurchaseFinished:Connect(function(plr, passId, success)
	if success then
		if passId == pass1 then
			local s, r = pcall(function() -- Here's where the danger comes in, there's a chance of the datastore failing
				local info = PDS:GetAsync(plr.UserId)
				if info and typeof(info) == "table" then
					local newInfo = info
					table.insert(newInfo, pass1)
					PDS:SetAsync(plr.UserId, newInfo)
				else
					PDS:SetAsync(plr.UserId, {pass1})
				end
			end)
			if not s and r then
				warn(r)
			end
			returnpassowned:InvokeClient(plr, passId)
			-- Any other benefits
		end
	end
end)

And here would be the localscript from before, under the GUI text:

local RS = game:GetService("ReplicatedStorage")
local returnPassOwned = RS:WaitForChild("ReturnPassOwned")

local passIdFromBefore = 0 -- the passID from before
returnPassOwned.OnClientInvoke = function(passId)
	if passId == passIdFromBefore then
		script.Parent.Text = "Owned"
	end
end

The RemoteFunction actually is needed this time because the server saves to DataStoreService. Sorry about the last scripts I posted.

1 Like

Oops. I realised that RemoteEvents are more fitting to be used than RemoteFunctions.

You can change this line in the server script:

returnpassowned:InvokeClient(plr, passId)

To:

returnpassowned:FireClient(plr, passId)

And the localscript to this

local RS = game:GetService("ReplicatedStorage")
local returnPassOwned = RS:WaitForChild("ReturnPassOwned")

local passIdFromBefore = 0 -- the passID from before
returnPassOwned.OnClientEvent:Connect(function(passId)
	if passId == passIdFromBefore then
		script.Parent.Text = "Owned"
	end
end)

And then make a RemoteEvent in ReplicatedStorage and rename it to ReturnPassOwned and delete the RemoteFunction

1 Like

the script now: local MS = game:GetService(“MarketplaceService”)
local ownedTXT = script.Parent.OWND
local plr = game.Players.LocalPlayer
local GamePassID = 38706262
script.Parent.MouseButton1Click:Connect(function()
game:GetService(“MarketplaceService”):PromptGamePassPurchase(game.Players.LocalPlayer, 38706262)
script.Parent.Text = “REJOIN TO GET YOUR GEAR!!”
wait(1)
game.Loaded:Connect(function()
if MS:UserOwnsGamePassAsync(plr.UserId, GamePassID) == true then
ownedTXT.Text = “Owned”
else
ownedTXT.Text = “Not Owned”
end
end)
end)

1 Like

it works but the text doesnt change

Change this

game.Loaded:Connect(function()
if MS:UserOwnsGamePassAsync(plr.UserId, GamePassID) == true then
ownedTXT.Text = “Owned”
else
ownedTXT.Text = “Not Owned”
end
end)
end)

to

while task.wait(1) do
if MS:UserOwnsGamePassAsync(plr.UserId, GamePassID) == true then
ownedTXT.Text = “Owned”
else
ownedTXT.Text = “Not Owned”
end
end

Apologies, I must not have been clear enough. I was just saying to use that when someone had purchased a gamepass and had not gone into any more detail. I was not going to suggest the use of a datastore and did not mention initially checking if they own it upon joining. Thank you for expanding upon what I had said.

It appears there is an error with this: local ownedTXT = script.Parent.OWND

That is not the best of ideas. I believe that UserOwnsGamePassAsync caches data like how player:GetRankInGroup() and other things. You should just be using the event to detect when they have purchased it instead.

My bad, check the new script that I edited - I accidentally added another end

No, why would UserOwnsGamePassAsync cache GetRankInGroup? I’ve used the same method they’re using and it works perfectly so I don’t get what the point is.

The best solution is to get the information about the gamepass when joining via UserOwnsGamePassAsync - setting text to “OWNED” if bought and “NOT OWNED” if not. Later on, you can update the text if the user buys the gamepass.

The only situation in which this may not work is if the user DELETES the gamepass whilst playing, but this shouldn’t be an issue.

thanks, but would you need a bracket at the end of the last end?

No, because the while loop doesn’t have an open parentheses.