Search code examples
luaroblox

How do I make a shield that lasts for 30 seconds in Roblox using a dev product?


When someone buys my dev product I want them to get a visible shield that lasts for 30 seconds.

Here's the code I have tried:

local mpService = game:GetService("MarketplaceService")
local Debris = game:GetService("Debris")

local function giveForcefield(player, duration)
    local character = player.Character
    if character then
        local forceField = Instance.new("ForceField")
        forceField.Visible = true
        forceField.Parent = character
        if duration then
            Debris:AddItem(forceField, duration)
        end
    end
end 


mpService.ProcessReceipt = function(purchaceInfo)
    local plr = game:GetService("Players"):GetPlayerByUserId(purchaceInfo.PlayerId)
    if purchaceInfo.ProductId == xxxxxxx then
        
        
        game.Players.PlayerAdded:connect(function(plr)
                repeat wait() until plr.Character
            local char = plr.Character
            giveForcefield(plr, 30)
            local forceField = Instance.new("ForceField") 
            forceField.Visible = true
            forceField.Parent = char

            end)

        

    end
    return Enum.ProductPurchaseDecision.PurchaseGranted
end

I can buy the dev product but after the code runs nothing happens. I have tried a lot of things but I am a bit lost. Can I get some help, please?


Solution

  • Both of the ways that you have coded for creating and destroying the ForceField are valid, but as Piglet has suggested, your code simply isn't getting called. Your code is saying, "once someone buys this product, wait for another player to join and spawn into the game, then give that new player the forcefield."

    Often times, game.Players.PlayerAdded:connect(function(plr) is used as a way to get access to a Player object, but you have already gotten the Player object by calling GetPlayerByUserId, so you can just use that to get access to the Character model.

    On an unrelated note, you should only mark a product as PurchaseGranted once the product has been successfully given. By having PurchaseGranted as the default return state, you run the risk of someone buying a product that hasn't been configured yet, and you will just end up taking their money without giving them anything in return.

    local PlayerService = game:GetService("Players")
    local Debris = game:GetService("Debris")
    
    mpService.ProcessReceipt = function(purchaceInfo)
        -- make sure that the player is still in the game
        local plr = PlayerService:GetPlayerByUserId(purchaceInfo.PlayerId)
        if not plr then
            warn("Player could not be found. They might have left")
            return Enum.ProductPurchaseDecision.NotProcessedYet
        end
    
        if purchaceInfo.ProductId == xxxxxxx then
            -- check if their character has spawned
            local char = plr.Character
            if not char then
                warn("Could not find player's character in game")
                return Enum.ProductPurchaseDecision.NotProcessedYet
            end
        
            -- grant the force field
            local forceField = Instance.new("ForceField", char)
    
            -- destroy the force field after a few seconds
            local duration = 30
            Debris:AddItem(forceField, duration)
    
            -- mark this item as granted
            return Enum.ProductPurchaseDecision.PurchaseGranted
        end
    
        -- not sure what thing they bought
        warn("Unprocessed item receipt", purchaseInfo)
        return Enum.ProductPurchaseDecision.NotProcessedYet
    end