Detect Gamepass Ownership without rejoining/respawning

Hello developers,
I need help. When a player dies in my game a death screen appears that also has a infinite revives button that when clicked a gamepass prompt appears and if the player buys that gamepass the DeathGui should disable, enabling another gui called InfDeathGui. However when the player buys the gamepass they have to respawn and die again in order to start seeing InfDeathGui instead. Is there a way i can make it appear instantly after the gamepass is bought? No rejoining/respawning. If so please let me know. Thank you!

DeathHandler (ServerScript)

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

local DEV_PRODUCT_ID = 3424640810
local INFINITE_REVIVES_GAMEPASS_ID = 1520929427

-- RemoteEvents
local reviveEvent = Instance.new("RemoteEvent")
reviveEvent.Name = "RevivePlayers"
reviveEvent.Parent = ReplicatedStorage

local respawnEvent = Instance.new("RemoteEvent")
respawnEvent.Name = "RespawnPlayers"
respawnEvent.Parent = ReplicatedStorage

local showDeathGuiEvent = Instance.new("RemoteEvent")
showDeathGuiEvent.Name = "ShowDeathGui"
showDeathGuiEvent.Parent = ReplicatedStorage

local infiniteReviveEvent = Instance.new("RemoteEvent")
infiniteReviveEvent.Name = "InfiniteRevivePlayers"
infiniteReviveEvent.Parent = ReplicatedStorage

local canRevive = {}
local infiniteOwners = {}

-- Check Gamepass Ownership
local function checkGamepassOwnership(player)
	local success, result = pcall(function()
		return MarketplaceService:UserOwnsGamePassAsync(player.UserId, INFINITE_REVIVES_GAMEPASS_ID)
	end)
	infiniteOwners[player.UserId] = success and result
end

-- Death Handler
local function handleDeath(player)
	local deadPlayers = {player}
	local linked = player:FindFirstChild("LinkedPlayer")
	if linked and linked.Value then
		table.insert(deadPlayers, linked.Value)
	end

	for _, plr in pairs(deadPlayers) do
		if plr and plr.Character then
			local humanoid = plr.Character:FindFirstChildOfClass("Humanoid")
			if humanoid and humanoid.Health > 0 then
				humanoid.Health = 0
			end

			if infiniteOwners[plr.UserId] then
				showDeathGuiEvent:FireClient(plr, "Infinite")
			else
				showDeathGuiEvent:FireClient(plr, "Normal")
			end
		end
	end
end

-- Player Added
Players.PlayerAdded:Connect(function(player)
	checkGamepassOwnership(player)

	player.CharacterAdded:Connect(function(char)
		-- recheck ownership on each respawn
		checkGamepassOwnership(player)

		local humanoid = char:WaitForChild("Humanoid")
		humanoid.Died:Connect(function()
			handleDeath(player)
		end)
	end)
end)

-- Revive (paid)
reviveEvent.OnServerEvent:Connect(function(player)
	if not canRevive[player.UserId] then return end
	canRevive[player.UserId] = false

	local group = {player}
	local linked = player:FindFirstChild("LinkedPlayer")
	if linked and linked.Value then table.insert(group, linked.Value) end

	for _, plr in pairs(group) do
		if plr and plr.Parent then
			plr:SetAttribute("Revived", true)
			plr:LoadCharacter()
			task.wait(0.1)
			if plr.Character and plr:FindFirstChild("LastCheckpoint") then
				plr.Character:SetPrimaryPartCFrame(plr.LastCheckpoint.Value)
			end
		end
		showDeathGuiEvent:FireClient(plr, false)
	end
end)


-- Infinite Revive
infiniteReviveEvent.OnServerEvent:Connect(function(player)
	if not infiniteOwners[player.UserId] then return end

	local group = {player}
	local linked = player:FindFirstChild("LinkedPlayer")
	if linked and linked.Value then table.insert(group, linked.Value) end

	for _, plr in pairs(group) do
		if plr and plr.Parent then
			plr:SetAttribute("Revived", true)
			plr:LoadCharacter()
			task.wait(0.1)
			if plr.Character and plr:FindFirstChild("LastCheckpoint") then
				plr.Character:SetPrimaryPartCFrame(plr.LastCheckpoint.Value)
			end
		end
		showDeathGuiEvent:FireClient(plr, false)
	end
end)

-- Respawn
respawnEvent.OnServerEvent:Connect(function(player)
	local group = {player}
	local linked = player:FindFirstChild("LinkedPlayer")
	if linked and linked.Value then table.insert(group, linked.Value) end

	for _, plr in pairs(group) do
		if plr and plr.Parent then
			plr:SetAttribute("Revived", false)
			plr:LoadCharacter()
			task.wait(0.1)
			if plr.Character then
				local hrp = plr.Character:FindFirstChild("HumanoidRootPart")
				if hrp then
					hrp.CFrame = workspace.SpawnLocation.CFrame + Vector3.new(0,5,0)
				end
			end
		end
		showDeathGuiEvent:FireClient(plr, false)
	end
end)

DeathClient (LocalScript)

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local MarketplaceService = game:GetService("MarketplaceService")
local player = Players.LocalPlayer

local DEV_PRODUCT_ID = 3424640810
local INFINITE_REVIVES_GAMEPASS_ID = 1520929427

-- Remotes
local reviveEvent = ReplicatedStorage:WaitForChild("RevivePlayers")
local respawnEvent = ReplicatedStorage:WaitForChild("RespawnPlayers")
local infiniteReviveEvent = ReplicatedStorage:WaitForChild("InfiniteRevivePlayers")
local showDeathGuiEvent = ReplicatedStorage:WaitForChild("ShowDeathGui")

-- GUI references
local deathGui = player:WaitForChild("PlayerGui"):WaitForChild("DeathGui")
local infDeathGui = player:WaitForChild("PlayerGui"):WaitForChild("InfDeathGui")

-- Normal GUI
local buttons = deathGui.Holder.Buttons
local reviveButton = buttons.Revive
local respawnButton = buttons.Respawn
local infiniteButton = buttons.InfiniteRevives

-- Infinite GUI
local infButtons = infDeathGui.Holder.Buttons
local infReviveButton = infButtons.Revive

deathGui.Enabled = false
infDeathGui.Enabled = false

-- Show GUI depending on type
showDeathGuiEvent.OnClientEvent:Connect(function(mode)
	if mode == "Infinite" then
		deathGui.Enabled = false
		infDeathGui.Enabled = true
	elseif mode == "Normal" then
		deathGui.Enabled = true
		infDeathGui.Enabled = false
	else
		deathGui.Enabled = false
		infDeathGui.Enabled = false
	end
end)

-- Normal Revive
reviveButton.MouseButton1Click:Connect(function()
	MarketplaceService:PromptProductPurchase(player, DEV_PRODUCT_ID)
end)
MarketplaceService.PromptProductPurchaseFinished:Connect(function(userId, productId, wasPurchased)
	if userId == player.UserId and productId == DEV_PRODUCT_ID and wasPurchased then
		reviveEvent:FireServer()
	end
end)

-- Respawn
respawnButton.MouseButton1Click:Connect(function()
	respawnEvent:FireServer()
end)

-- Infinite Revives purchase button
infiniteButton.MouseButton1Click:Connect(function()
	MarketplaceService:PromptGamePassPurchase(player, INFINITE_REVIVES_GAMEPASS_ID)
end)

-- Infinite Revive button
infReviveButton.MouseButton1Click:Connect(function()
	infiniteReviveEvent:FireServer()
end)

-- Detect gamepass purchase immediately
MarketplaceService.PromptGamePassPurchaseFinished:Connect(function(userId, gamePassId, wasPurchased)
	if userId == player.UserId and gamePassId == INFINITE_REVIVES_GAMEPASS_ID and wasPurchased then
		-- Immediately enable infinite GUI
		infDeathGui.Enabled = true
		deathGui.Enabled = false

		-- Tell server we now own it for future deaths
		local success, result = pcall(function()
			return MarketplaceService:UserOwnsGamePassAsync(player.UserId, INFINITE_REVIVES_GAMEPASS_ID)
		end)
		if success and result then
			ReplicatedStorage:WaitForChild("InfiniteRevivePlayers"):FireServer() -- optional, only if you want server aware
		end
	end
end)

You might wanna check if user has that gamepass

im pretty sure you can just have a while loop with like a 1 second delay and then it will detect if player has gamepass

the reason why people have to rejoin for gamepasses is because the gamepass ownership is only checked when the player joins

You have to use PromptGamePassPurchaseFinished

2 Likes

I don’t think there’s a surefire way to do it considering Roblox’s caching system, but like others have said, you use MarketplaceService:UserOwnsGamepassAsync(gamepassId) but it’s a 50/50 shot regarding whether the previous result had already been cached.

What you could try doing to get a more surefire result is using MarketplaceService.PromptGamePassPurchaseFinished like @DonaldDuck5150 suggested, but the problem is that because of an insecurity in the event, you would likely have to verify using MarketplaceService:UserOwnsGamepassAsync(gamepassId) every time the event was fired, but that would run you into the same issue that I outlined originally.

A way to get around that could possible be accessing an API endpoint to access the user’s gamepasses each time the event was fired, but there are issues in itself by doing that.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.