Part give coins after a certain amount of time

Hello, so I was wondering how I can make a part that when a player steps on, they have to wait about 45 seconds to receive coins. But if they step off, the timer cancels and they have to step on it again to restart it. If you know, please help. Thanks.

You would check for the Elasped Time since the Player has stood on the Part, you use Players:GetPlayerFromCharacter, and check if they are on the Part to Apply Data, To Check for the Elapsed Time, you can use tick(), which woul dreturn the TIme since the Unix Epoch (January 1, 1970), and subtract the current time, by the old time, like this:

local timestamp = tick() -- the time at that point

local ElapsedTime = (tick() - timestamp) -- The Elasped Time since a Event.
-- its essentially "the difference between now and then"

if ElaspedTime >= Number then -- if the Elapsed TIme is greater than or Equal to a specific number
    -- code
end
-- Variables
local part = script.Parent
local debounce = false
local timerDuration = 45 -- in seconds
local coinsToAdd = 10 -- the amount of coins to add after waiting

-- Function to add coins to a player
local function giveCoins(player)
    local leaderstats = player:FindFirstChild("leaderstats")
    if leaderstats then
        local coins = leaderstats:FindFirstChild("Coins")
        if coins then
            coins.Value = coins.Value + coinsToAdd
        end
    end
end

-- Function that runs when a player touches the part
local function onTouched(hit)
    local character = hit.Parent
    local player = game.Players:GetPlayerFromCharacter(character)

    if player and not debounce then
        debounce = true
        local startTime = tick()
        
        while debounce and (tick() - startTime) < timerDuration do
            wait(1)
            if not character or (character and not character:IsDescendantOf(workspace)) then
                debounce = false
            end
        end
        
        if debounce then
            giveCoins(player)
        end
        
        debounce = false
    end
end

-- Connect the 'onTouched' function to the part's Touched event
part.Touched:Connect(onTouched)

I thought this would be a 2 minute script, but it turned out to be a little harder than I expected it to be.
Example file:
AwarderOnPart.rbxl (43.1 KB)

--!strict

--// Services

local plrs = game:GetService("Players")
local rs = game:GetService("ReplicatedStorage")
local runserv = game:GetService("RunService")

--// Other Variables

local NEEDED_TIME_SECONDS: number = 1
local AWARDED_COINS: number = 1
local part = script.Parent

type touchingInfoDataType = {
	StartTime: number,
	TouchingParts: number
}

local currentlyTouching: {[Player]: touchingInfoDataType} = {}
local touchingPlayersAmount: number = 0
local playerChangeEvent = Instance.new("BindableEvent")
local step = runserv.Stepped
local rstepConnection: RBXScriptConnection? = nil
type lsTemplate = typeof(rs.leaderstats)

--// Main Code

local award = function(player: Player)
	currentlyTouching[player].StartTime = os.clock()
	local learderstats = player:WaitForChild("leaderstats") :: lsTemplate
	learderstats.Coins.Value += AWARDED_COINS
end

local checker = function()
	for player, touchInfo: touchingInfoDataType in currentlyTouching do
		if os.clock() - touchInfo.StartTime >= NEEDED_TIME_SECONDS then
			award(player)
		end
	end
end

playerChangeEvent.Event:Connect(function()
	if touchingPlayersAmount == 0 and rstepConnection ~= nil then
		rstepConnection:Disconnect()
		rstepConnection = nil
	elseif not rstepConnection then
		rstepConnection = step:Connect(checker)
	end
end)

part.Touched:Connect(function(hit: BasePart)
	local player = plrs:GetPlayerFromCharacter(hit.Parent)
	if not player then return end
	if currentlyTouching[player] then 
		currentlyTouching[player].TouchingParts += 1
		return
	end
	currentlyTouching[player] = {
		StartTime = os.clock(),
		TouchingParts = 1
	}
	touchingPlayersAmount += 1
	playerChangeEvent:Fire()
end)

part.TouchEnded:Connect(function(hit: BasePart)
	local player = plrs:GetPlayerFromCharacter(hit.Parent)
	if not player then return end
	if not currentlyTouching[player] then return end
	currentlyTouching[player].TouchingParts -= 1
	if currentlyTouching[player].TouchingParts ~= 0 then return end
	currentlyTouching[player] = nil
	touchingPlayersAmount -= 1
	playerChangeEvent:Fire()
end)

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