ProcessReceipt Script Broken, & I cant figure out why

I recently had this processreceipt script made and I tried to make a nuke purchase, but when i set the nuketable to nil in line 180 it breaks the whole script making the player set as nil everytime.
Ive only been scripting for a year, so fixing this bug is quite hard for me to do. ive spent 1 hour trying to figure it out already…

type ReceiptInfo = {
	PurchaseId: number,
	PlayerId: number,
	ProductId: number,
	PlaceIdWherePurchased: number,
	CurrencySpent: number,
	CurrencyType: Enum.CurrencyType
}

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

--local Id = 1865174664

local playersToKill, playersToPush, killPlayerProductID, pushPlayerProductID = {}, {}, 1865174664, 1864776183
local playersToKick, KickPlayerProductID = {}, 1866120407
local KillAllPlayers, KillAllProductID = {}, 1866493836

local serverTick, purchaseCooldown = 0, 2

local purchases = {
	KillPlayer = function(player, selectedPlayer)
		playersToKill[tostring(player.UserId)] = selectedPlayer
		return killPlayerProductID
	end,
	PushPlayer = function(player, selectedPlayer)
		print(`{selectedPlayer} added to the push list`)
		playersToPush[tostring(player.UserId)] = selectedPlayer
		return pushPlayerProductID
	end,
	KickPlayer = function(player, selectedPlayer)
		playersToKick[tostring(player.UserId)] = selectedPlayer
		return KickPlayerProductID
	end,
	
	NukeKillAll = function(player)
		
		KillAllPlayers[tostring(player.UserId)] = player
		
		return KillAllProductID
	end
}

local function canProcessReceipt(localPlayer: Player, timestamp: number, guiName: string?, selectedPlayer: Player?)
	local now = workspace:GetServerTimeNow()
	
	-- cooldown
	if now < serverTick then
		return false
	end
	
	if not timestamp or typeof(timestamp) ~= "number" or timestamp <= 0 then
		print("A")
		return false
	end
	
	local latency = now - timestamp
	
	-- sync check and high latency prevention
	if now <= timestamp or latency > 0.5 then
		print("B")
		return false
	end
	
	-- troll gui means to troll others, not yourself
	-- hence why we add this check, just in case the selection localscript has unexpected behavior
	if selectedPlayer then
	if localPlayer == selectedPlayer then
		print("C")
		return false
	end
	end
	
	if typeof(guiName) ~= "string" or string.len(guiName) <= 0 or guiName == "" then
		print("D")
		return false
	end
	
	if selectedPlayer then
	if typeof(selectedPlayer) ~= "Instance" or selectedPlayer.ClassName ~= "Player" then
		print("E")
		return false
	end
	end
	
	serverTick = now + purchaseCooldown
	
	return true	
end

-- change as you need
MarketplaceService.ProcessReceipt = function(receiptInfo: ReceiptInfo)
	local userID = tostring(receiptInfo.PlayerId)
	
	
	local chosenPlayer = playersToKill[userID]
	local KickPlayer = playersToKick[userID]
	local pushPlayer = playersToPush[userID]
	local PlaceholderKillAll = KillAllPlayers[userID]
	
	
	if receiptInfo.ProductId == killPlayerProductID then
		local opponentCharacter = chosenPlayer.Character
		if not opponentCharacter then
			return Enum.MarketplaceItemPurchaseStatus.NotAvailableForPurchaser
		end
		
		local opponentHumanoid = opponentCharacter:FindFirstChildOfClass("Humanoid")
		
		if not opponentHumanoid or opponentHumanoid.Health <= 0 then
			return Enum.MarketplaceItemPurchaseStatus.NotAvailableForPurchaser
		end
		
		opponentHumanoid.Health = 0

		playersToKill[userID] = nil

		return Enum.MarketplaceItemPurchaseStatus.Success
	end
	
	if receiptInfo.ProductId == pushPlayerProductID then
		
		local pushCharacter = pushPlayer.Character
		if not pushCharacter then
			return Enum.MarketplaceItemPurchaseStatus.NotAvailableForPurchaser
		end

		local pushHumanoid = pushCharacter:FindFirstChildOfClass("Humanoid")

		if not pushHumanoid or pushHumanoid.Health <= 0 then
			return Enum.MarketplaceItemPurchaseStatus.NotAvailableForPurchaser
		end
		
		ReplicatedStorage.Events.PushEvent:FireClient(pushPlayer)
		
		playersToPush[userID] = nil
		return Enum.MarketplaceItemPurchaseStatus.Success
	end
	
	if receiptInfo.ProductId == KickPlayerProductID then
		local opponentCharacter = KickPlayer.Character
		if not opponentCharacter then
			return Enum.MarketplaceItemPurchaseStatus.NotAvailableForPurchaser
		end

		KickPlayer:Kick("You Have Been Kicked, GET TROLLED!")

		playersToKick[userID] = nil

		return Enum.MarketplaceItemPurchaseStatus.Success
	end
	
	if receiptInfo.ProductId == KillAllProductID then
					
		if PlaceholderKillAll then
					
		workspace.Sounds.Nuke:Play()
		
		workspace.Sounds.Nuke.Ended:Wait()
		
		for _, Player in pairs(game:GetService("Players"):GetPlayers()) do

			

			if Player.UserId ~= receiptInfo.PlayerId then 
			
			local Explode = ReplicatedStorage.Sounds.Explode:Clone()
			Explode.Parent = Player
			Explode:Destroy()
			
			
			local Humanoid = Player.Character:WaitForChild("Humanoid")

			Humanoid.Health = 0
			end
		end
		

		KillAllPlayers[userID] = nil	

		return Enum.MarketplaceItemPurchaseStatus.Success
		end
	end
		
	KillAllPlayers[userID] = nil		
	playersToKill[userID] = nil
	playersToPush[userID] = nil
	playersToKick[userID] = nil
	
	
	return Enum.MarketplaceItemPurchaseStatus.NotAvailableForPurchaser
end

ReplicatedStorage.Events.PushEvent.OnServerEvent:Connect(function(player, timestamp, actionName, selectedPlayer)
	if canProcessReceipt(player, timestamp, actionName, selectedPlayer) then
		local receipt = purchases[actionName]
		if receipt ~= nil then
			local receiptId = receipt(player, selectedPlayer)
			MarketplaceService:PromptProductPurchase(player, receiptId)
		end
	end
end)

ReplicatedStorage.Events.TrollPurchaseEvent.OnServerEvent:Connect(function(player, timestamp, buttonName, selectedPlayer)
	--print("server before process")
	if canProcessReceipt(player, timestamp, buttonName, selectedPlayer) then
		--print("server after process")
		local receipt = purchases[buttonName]
		if receipt ~= nil then
			local receiptId = receipt(player, selectedPlayer)
			MarketplaceService:PromptProductPurchase(player, receiptId)
		else
			--print("invalid receipt")
		end

	end
	
	
end)

ReplicatedStorage.Events.KILLALLEVENT.OnServerEvent:Connect(function(player, timestamp, buttonName)
	--print("server before process")
	if canProcessReceipt(player, timestamp, buttonName) then
		
		local receipt = purchases[buttonName]
		
		if receipt ~= nil then
			
			local receiptId = receipt(player)
			
			MarketplaceService:PromptProductPurchase(player, receiptId)
		
		end

	end


end)
1 Like

first off… really good progress for someone who has been scripting for a year. second of all

what do you mean by “making the player set as nil”

1 Like

sorry lol, when I set the players userId in the table as nil (" KillAllPlayers[userID] = nil ") line 180

and its only this line that breaks everything and makes the player set as nil. When I use the script again it always does this error, attempt to index nil with character line: 111

1 Like

well ofcourse if you deleted the player from the table you will have to set the player back there again.
I’m assuming this code only runs once then begins to error.

Yeah, however it works doing that for the 3 events before it, just not for the kill all event