I'm making a VIP door and if someone doesn't own the gamepass in my game, they get a prompt to buy it. I tried to make it so that if they did buy the gamepass they would be allowed to enter and if they didn't they would get killed. I tried using PromptGamePassPurchaseFinished for the first time but it gives me the error "attempt to call field 'PromptGamePassPurchaseFinished' (a userdata value)". Here's my script:
function Touched(part) if part.Parent:FindFirstChild("Humanoid") ~= nil then local MP = game:GetService("MarketplaceService") local Player = game.Players:GetPlayerFromCharacter(part.Parent) local OldWS = part.Parent.Humanoid.WalkSpeed if MP:UserOwnsGamePassAsync(Player.UserId, 1087508) then print("User Owns GP") else part.Parent.Humanoid.WalkSpeed = 0 MP:PromptGamePassPurchase(Player, 1087508) wait(1) repeat wait() until MP.PromptGamePassPurchaseFinished(Player, 1087508) if MP:UserOwnsGamePassAsync(Player.UserId, 1087508) then print("User Bought GP") part.Parent.Humanoid.WalkSpeed = OldWS else part.Parent.Humanoid.Health = 0 end end end end script.Parent.Touched:Connect(Touched)
You're treating PromptGamePassPurchaseFinished
as if it were a function that returns a boolean
, determining if the purchase was finished or not.
It is an event; you listen for it.
The listeners of this event get three arguments:
But instead of connecting a function, we'll wait for it via the :Wait()
method.
:Wait()
returns what would be given as arguments to the listeners.
This code can also definitely be cleaned up. MP
is a constant as the value won't change, so why declare the variable each time the part is touched?
local Players, MarketplaceService = game:GetService("Players"), game:GetService("MarketplaceService"); local PASS_ID = 1087508; -- constant number local function protectedOwnsPass(client, passId) -- Functions labeled as 'Async' make web requests and may fail local success, result = pcall( MarketplaceService.UserOwnsGamePassAsync, MarketplaceService, client.UserId, passId ); if (success) then return result; -- successful web request end warn("Error whilst web request:", result); end script.Parent.Touched:Connect(function(part) local client = Players:GetPlayerFromCharacter(part.Parent); if (client and protectedOwnsPass(client, PASS_ID)) then return; -- they own the game pass, no more needs to be done end local humanoid = client.Character.Humanoid local prevSpeed = humanoid.WalkSpeed local bought = select(3, MarketplaceService.PromptGamePassPurchaseFinished:Wait()); if (not bought) then -- they didn't buy it humanoid:TakeDamage(humanoid.Health); -- basically just kills them else humanoid.WalkSpeed = prevSpeed; -- they bought it end end);
select
selects a certain argument, and everything after it. So select(2, 'a', 'b', 'c', 'd')
evaluates to 'b', 'c', 'd'
since the second argument is selected, and everything else after it is selected also. If the first argument is a '#'
, it returns how many arguments were passed (excluding the first, which is what to select).
pcall
(short for protected call), takes a function, and calls it in protected mode, so any runtime errors will not be propagated. Important for if your function makes web requests, or is just prone to error in general. The first result of this function is a boolean, true
if the function was successfully called without errors, false
otherwise. Everything after the first return value is what the function returns, but only if there wasn't an error. If there was an error, the first return value is false
, and the second return value is the error message.