Help with clicks per second

I tried to make a clicks per second but it isn’t working that good. It works when started but after it ends, it stops to work correctly:

local RunService = game:GetService("RunService")

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Modules = ReplicatedStorage:WaitForChild("Modules")
local Abbreviate = require(Modules:WaitForChild("Abbreviate"))

local player = game.Players.LocalPlayer
local Clicks = player:WaitForChild("leaderstats"):WaitForChild("Clicks")
local oldClicks = Clicks.Value

local frame = script.Parent
local TextLabel = frame:WaitForChild("TextLabel")
local ClicksPerSecondLabel = frame:WaitForChild("ClicksPerSecondLabel")

local function ResetTimer()
	script:SetAttribute("ClicksPerSecond", 0)
end

local function StartTimer()
	local startTime = tick()
	
	local changedClicks = Clicks.Value - oldClicks
	local ClicksPerSecond = script:GetAttribute("ClicksPerSecond")
	script:SetAttribute("ClicksPerSecond", ClicksPerSecond + changedClicks)

	repeat
		RunService.Heartbeat:Wait()
	until tick() - startTime >= 1
	
	ResetTimer()
end

Clicks:GetPropertyChangedSignal("Value"):Connect(function()
	TextLabel.Text = Clicks.Value

	if Clicks.Value > oldClicks then
		StartTimer()
	end

	oldClicks = Clicks.Value
end)

TextLabel.Text = Abbreviate.Abbreviate(Clicks.Value)

script:GetAttributeChangedSignal("ClicksPerSecond"):Connect(function()
	local ClicksPerSecond = script:GetAttribute("ClicksPerSecond")
	ClicksPerSecondLabel.Text = Abbreviate.Abbreviate(ClicksPerSecond)
end)

4 Likes

Why can’t you just count the clicks and update it every second?

Code:

local RunService = game:GetService("RunService")

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Modules = ReplicatedStorage:WaitForChild("Modules")
local Abbreviate = require(Modules:WaitForChild("Abbreviate"))

local player = game.Players.LocalPlayer
local Clicks = player:WaitForChild("leaderstats"):WaitForChild("Clicks")
local oldClicks = Clicks.Value

local frame = script.Parent
local TextLabel = frame:WaitForChild("TextLabel")
local ClicksPerSecondLabel = frame:WaitForChild("ClicksPerSecondLabel")

local counter = 0

Clicks.Changed:Connect(function(newValue)
	counter += newValue - oldClicks
	oldClicks = newValue

	TextLabel.Text = newValue
end)

TextLabel.Text = Abbreviate.Abbreviate(Clicks.Value)

script:GetAttributeChangedSignal("ClicksPerSecond"):Connect(function()
	local ClicksPerSecond = script:GetAttribute("ClicksPerSecond")
	ClicksPerSecondLabel.Text = "(+".. Abbreviate.Abbreviate(ClicksPerSecond) .."/sec)"
end)

while task.wait(0.5) do
	script:SetAttribute("ClicksPerSecond", counter * 2)
	counter = 0
end

I’m also using .Changed instead of :GetPropertyChangedSignal because:

3 Likes

I’ve edited the script to update every 0.5 seconds so it’s more reactive.

1 Like

I want it to start if Clicks has changed, also my new code works a little better but not what I want. I don’t like to see it restart to 0 after 1 second.

local RunService = game:GetService("RunService")

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Modules = ReplicatedStorage:WaitForChild("Modules")
local Abbreviate = require(Modules:WaitForChild("Abbreviate"))

local player = game.Players.LocalPlayer
local Clicks = player:WaitForChild("leaderstats"):WaitForChild("Clicks")
local oldClicks = Clicks.Value

local frame = script.Parent
local TextLabel = frame:WaitForChild("TextLabel")
local ClicksPerSecondLabel = frame:WaitForChild("ClicksPerSecondLabel")

local timerStarted = false

local function ResetTimer()
	script:SetAttribute("ClicksPerSecond", 0)
	timerStarted = false
end

local function StartTimer()
	timerStarted = true

	local startTime = tick()

	local ClicksPerSecond = script:GetAttribute("ClicksPerSecond")
	local changedClicks = Clicks.Value - oldClicks
	script:SetAttribute("ClicksPerSecond", ClicksPerSecond + changedClicks)

	coroutine.wrap(function()
		repeat
			RunService.Heartbeat:Wait()
		until tick() - startTime >= 1

		ResetTimer()
	end)()
end

Clicks:GetPropertyChangedSignal("Value"):Connect(function()
	TextLabel.Text = Clicks.Value

	if Clicks.Value > oldClicks and not timerStarted then
		StartTimer()

	elseif Clicks.Value > oldClicks and timerStarted then
		local ClicksPerSecond = script:GetAttribute("ClicksPerSecond")
		local changedClicks = Clicks.Value - oldClicks
		script:SetAttribute("ClicksPerSecond", ClicksPerSecond + changedClicks)
	end

	oldClicks = Clicks.Value
end)

TextLabel.Text = Abbreviate.Abbreviate(Clicks.Value)

script:GetAttributeChangedSignal("ClicksPerSecond"):Connect(function()
	local ClicksPerSecond = script:GetAttribute("ClicksPerSecond")
	ClicksPerSecondLabel.Text = Abbreviate.Abbreviate(ClicksPerSecond)
end)

1 Like

Just use a bit of maths:

local mouse = game.Players.LocalPlayer:GetMouse()
local startclick = tick()
local clicks = 0
mouse.Button1Up:Connect(function()
   clicks = 1/(tick()-startclick)
   startclick = tick()
end)
1 Like

Here’s my attempt:

local sampleTime = 1.4 --check the clicks of the last 1.4 seconds

local clicks = {} 

--connect this to the click event you're listening to
local function onClick()
	local current = os.clock()
	table.insert(clicks, current)
	--remove the clicks we don't need anymore to avoid memory leakage
	for i, v in pairs(clicks) do
		if current-v > sampleTime then table.remove(clicks, i) end
	end
end

--returns the current CPS
local function getLastSecondClicks(): number 
	local amount = 0
	local current = os.clock()
	for _, click in pairs(clicks) do
		amount += current-click <= sampleTime and 1 or 0
	end
	return amount/sampleTime 
end

local function round(x: number, decimals: number): number 
	local p = 10^decimals
	return math.round(x*p)/p
end

--example using the mouse click
game.Players.LocalPlayer:GetMouse().Button1Down:Connect(onClick)

--refresh time here will only impact the visuals
while task.wait(0.2) do 
	local CPS = round(getLastSecondClicks(), 2)
	print("CPS: "..CPS)
end
1 Like

Thats quite confusing.

I still want to keep my code since I can understand it better.

local RunService = game:GetService("RunService")

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Modules = ReplicatedStorage:WaitForChild("Modules")
local Abbreviate = require(Modules:WaitForChild("Abbreviate"))

local player = game.Players.LocalPlayer
local Clicks = player:WaitForChild("leaderstats"):WaitForChild("Clicks")
local oldClicks = Clicks.Value

local frame = script.Parent
local TextLabel = frame:WaitForChild("TextLabel")
local ClicksPerSecondLabel = frame:WaitForChild("ClicksPerSecondLabel")

local timerStarted = false
local counter = 0

local function ResetTimer()
	script:SetAttribute("ClicksPerSecond", counter)
	counter = 0
	timerStarted = false
end

local function StartTimer()
	timerStarted = true

	local startTime = tick()

	coroutine.wrap(function()
		repeat
			RunService.Heartbeat:Wait()
		until tick() - startTime >= 1

		ResetTimer()
	end)()
end

Clicks.Changed:Connect(function(newValue)
	TextLabel.Text = Abbreviate.Abbreviate(newValue)

	local changedClicks = newValue - oldClicks
	counter += changedClicks

	if newValue > oldClicks and not timerStarted then
		StartTimer()
	end

	oldClicks = newValue
end)

TextLabel.Text = Abbreviate.Abbreviate(Clicks.Value)

script:GetAttributeChangedSignal("ClicksPerSecond"):Connect(function()
	local ClicksPerSecond = script:GetAttribute("ClicksPerSecond")
	ClicksPerSecondLabel.Text = "(+"..Abbreviate.Abbreviate(ClicksPerSecond).."/sec)"
end)

Result:

What I want:

1 Like

Just use my code instead for setting the ClicksPerSecond attribute:

local sampleTime = 1.4 --check the clicks of the last 1.4 seconds

local clicks = {} 

--connect this to the click event you're listening to
local function onClick()
	local current = os.clock()
	table.insert(clicks, current)
	--remove the clicks we don't need anymore to avoid memory leakage
	for i, v in pairs(clicks) do
		if current-v > sampleTime then table.remove(clicks, i) end
	end
end

--returns the current CPS
local function getLastSecondClicks(): number 
	local amount = 0
	local current = os.clock()
	for _, click in pairs(clicks) do
		amount += current-click <= sampleTime and 1 or 0
	end
	return amount/sampleTime 
end

local function round(x: number, decimals: number): number 
	local p = 10^decimals
	return math.round(x*p)/p
end

yourUIButton.MouseButton1Click:Connect(onClick)

while task.wait(0.1) do --refresh rate
	--replace 2 with 0 if you want an integer
	local CPS = round(getLastSecondClicks(), 2) 
	otherScript:SetAttribute("ClicksPerSecond", CPS)
end

That code snippet should replace the current code of the button that I assume sets the Clicks value. Also, you should remove/comment out the other code that changes/interferes with the ClicksPerSecond attribute to avoid any weird errors during debugging.

If you want to achieve the effect shown in the video, where the clicks are in enormous amounts such as in Qn just multiply the calculated CPS with the player multipliers responsible for their click speed.

1 Like

You can try adding the changed amount of clicks, update the UI, then after 1 second, delete that much amount of clicks and updating the UI again:

-- Variables
local player = game.Players.LocalPlayer
local Clicks = player:WaitForChild("leaderstats"):WaitForChild("Clicks")
local oldClicks = Clicks.Value

local frame = script.Parent
local TextLabel = frame:WaitForChild("TextLabel")
local ClicksPerSecondLabel = frame:WaitForChild("ClicksPerSecondLabel")

-- UI
local CPS = 0
Clicks.Changed:Connect(function(newValue)
	CPS += newValue
	TextLabel.Text = CPS
	task.wait(1)
	CPS -= newValue
	TextLabel.Text = CPS
end)
2 Likes

Wow! That was so simple. Thank you!

1 Like

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