Title is pretty self-explanatory, I’m looking for a way to handle multiple cooldowns for multiple skills at the same time, possibly on the server to make it safer.
I know I should use a dictionary, but I’m not sure on how to proceed.
I think the dictionary should look like this while in action:
Yeah when you use the skill, store the tick() of when it was used. Then when the client tries to fire the server check if the new tick() is greater than the stored tick() plus the skill cooldown. Then set the last fired to the new tick()
--client fired server event to fire their weapon
local t = tick()
if t >= self.lastFired + 1/self.rateOfFire -1/30 then --valid fire
This is an obscure application from a shooter I am working on.
The 1/self.rateOfFire is the cooldown and -1/30 is the error allowance for ping because I was having problems with getting the magazine of my whole gun to register on the server.
I don’t see any reason to run a loop when you can check the time passed from one use of the skill to the next.
Here is one method you could take. Though I am sure there are probably other more efficient methods. In this quick demo, “Fired” should only print three times.
local mt = {
__index = {
fire = (function(self)
local t = tick()
-- Less than coolDownTime indicates
-- coolDownTime has NOT elapsed
if t - self.lastFired >= self.coolDownTime then
print("Fire")
self.lastFired = tick()
end
end)
}
}
local function newSkill(coolDownTime)
local self = {
coolDownTime = coolDownTime,
lastFired = 0
}
setmetatable(self, mt)
return self
end
local fireBall = newSkill(2)
fireBall:fire()
fireBall:fire()
wait(2)
fireBall:fire()
wait(2)
fireBall:fire()
And to check if the player has the skill on cooldown:
local OnCooldown = Status:Check(Character, Skill_UID.."-cooldown")
Here are some functions from my Status module that I use for this exact purpose:
local Status = {}
function Status:Add(Unit : Character, StatusName : String, Duration : Number, Stacks : number | any)
local CallTime = tick()
local StackString = StatusName.."_Stacks"
if Duration then
Unit:SetAttribute(StatusName,CallTime+Duration)
coroutine.wrap(function()
task.wait(Duration)
local CurrentTime = tick()
local ExpireTime = Unit:GetAttribute(StatusName)
if ExpireTime and ExpireTime < CurrentTime then
Unit:SetAttribute(StatusName,nil)
Unit:SetAttribute(StackString,nil)
end
end)()
else
Unit:SetAttribute(StatusName,-1)
end
if Stacks then
local CurrentStacks = Unit:GetAttribute(StackString)
CurrentStacks += Stacks
Unit:SetAttribute(StackString,CurrentStacks)
end
end
function Status:Remove(Unit : Character, StatusName : String): (boolean, number)
local StackString = StatusName.."_Stacks"
local StacksRemoved = Unit:GetAttribute(StackString) or 0
Unit:SetAttribute(StatusName,nil)
Unit:SetAttribute(StackString,nil)
return StacksRemoved > 0, StacksRemoved
end
function Status:Check(Unit : Character, StatusName : String): (boolean, number)
local StackString = StatusName.."_Stacks"
local HasStatus = Unit:GetAttribute(StatusName) ~= nil
local CurrentStacks = Unit:GetAttribute(StackString)
return HasStatus, CurrentStacks
end
return Status
@ everyone: Sorry for the late reply - been really busy these past 2 days. Thank you for your answers!
@overflowed Do you mind explaining how it works? I’m confused about the Status and Stacks system you use. @kboy100 your system seems pretty damn good, but I’m struggling to apply it properly. For some reason it gives me this error once the :Fire event is used:
If you decide to implement your system in this manner, I would personally use module scripts. Unless I’m being pedantic of your reply, :fire() can only be called in lowercase (as the function is declared). If you wish to use a capital F, just change the code like so:
Fire = (function(self) -- Function is now called Fire and not fire
local t = tick()
-- Less than coolDownTime indicates
-- coolDownTime has NOT elapsed
if t - self.lastFired >= self.coolDownTime then
print("Fire")
self.lastFired = tick()
end
end)