It’s better than repeatedly using wait(). Also, event connections are relatively inexpensive so there’s nothing wrong with using .Stepped as a loop.
Nope, it uses the cooldown on the first iteration as well but that can easily be changed.
Ok would this code work then?
local RunService = game:GetService("RunService")
local cooldown = 20
local lastSpawnedTime
repeat
if os.time() == os.time({year = 2020; month = 5; day = 16}) then
spawnThem()
lastSpawnedTime = tick()
RunService.Stepped:Connect(function() -- these parameters aren't needed but i'm just showing that they exist
if tick() - lastSpawnedTime >= cooldown then
spawnThem()
lastSpawnedTime = tick()
end
end)
end
until os.time() ~= os.time({year = 2020; month = 5; day = 16})
Also what if this happens:
Player joins at like 5:16 or something not on the dot?
you don’t need repeat/until. just the if statement is enough.
also you have to fill in the spawnThem() function
Ik. Just was putting pseudocode for the function.
I still need the answer to this question.
Also won’t the if statement only run once?
Ok so here is my code so far:
MAIN SCRIPT:
local RunService = game:GetService("RunService")
local module = require(game.ReplicatedStorage.Modules.CrystalDropParty)
local cooldown = 20
local lastSpawnedTime
local date = os.date("!*t", os.time())
local yday = 137 -- the actual yday, 131 is for testing
if date.yday == 131 and date.year == 2020 then
module.StartDropParty()
lastSpawnedTime = tick()
RunService.Stepped:Connect(function()
if tick() - lastSpawnedTime >= cooldown then
module.StartDropParty()
lastSpawnedTime = tick()
end
end)
end
MODULE SCRIPT:
local module = {}
local RNG = Random.new()
local bases = {
{Object = workspace.Base, Weight = 3};
{Object = workspace.Base2, Weight = 4};
}
--local functions
local function random(choices)
local weightSum = 0
for i = 1, #choices do
weightSum = weightSum + choices[i].Weight
end
local rand = RNG:NextInteger(0, weightSum)
for i = 1, #choices do
if rand <= choices[i].Weight then
return choices[i].Object
end
rand = rand - choices[i].Weight
end
end
local function setRandomPosition(item)
local Base = random(bases)
item.CFrame = CFrame.new(
RNG:NextInteger((-Base.Size.X / 2), (Base.Size.X / 2)),
Base.Position.Y + (Base.Size.Y / 2) + (item.Size.Y / 2),
RNG:NextInteger((-Base.Size.Z / 2), (Base.Size.Z / 2))
) * CFrame.Angles(0, math.rad(RNG:NextInteger(0, 360)), 0)
end
--public functions
function module.StartDropParty()
local secs = 60
repeat
local waitSeconds = math.random(9,16)
local randomAmount = math.random(4,7)
wait(waitSeconds)
for i = 1, randomAmount do
local clonedCrystal = script.Crystal:Clone()
clonedCrystal.Parent = workspace.Crystals
setRandomPosition(clonedCrystal)
end
secs = secs - waitSeconds
until secs <= 0
end
return module
CRYSTAL TOUCHED SCRIPT:
local function crystalTouched(crystal, hit)
if hit.Parent:FindFirstChild("Humanoid") then
local plr = game.Players:GetPlayerFromCharacter(hit.Parent)
local crystals = plr:WaitForChild('leaderstats').Crystals
crystals.Value = crystals.Value + (1 * plr:WaitForChild("Gamepasses").CrystalsMultiplier.Value)
crystal:Destroy()
end
end
local function debounce(func)
local deb = false
return function()
if not deb then
deb = true
print("BEFORE FUNC")
func()
deb = false
print("AFTER FUNC")
end
end
end
script.Parent.Touched:Connect(function(hit)
debounce(crystalTouched(script.Parent, hit))
end)
I haven’t tested yet since it’s really late but I will soon!
Uhh… So I tested it out and the first drop party went well, and then like a few seconds later there were just a whole bunch of crystals dropping…
local RunService = game:GetService("RunService")
local module = require(game.ReplicatedStorage.Modules.CrystalDropParty)
local cooldown = 20
local lastSpawnedTime
local date = os.date("!*t", os.time())
local yday = 137
if date.yday == 131 and date.year == 2020 then
module.StartDropParty()
lastSpawnedTime = tick()
RunService.Stepped:Connect(function()
if tick() - lastSpawnedTime >= cooldown then
module.StartDropParty()
lastSpawnedTime = tick()
end
end)
end
I’m suspecting it has to do with this:
RunService.Stepped:Connect(function()
if tick() - lastSpawnedTime >= cooldown then
module.StartDropParty()
lastSpawnedTime = tick()
end
end)
That makes it drop again every 20 seconds
I combined what I learned here and in this topic and came up with this script:
local date = os.date("!*t", os.time())
local crystalModule = require(game.ReplicatedStorage.Modules.CrystalDropParty)
local cocoaModule = require(game.ReplicatedStorage.Modules.CocoaDropParty)
local function crystalDropParty()
local CurrentSec = date.min * 60 + date.sec
local HalfHourSec = 60 * 20
local TimeToWait = HalfHourSec - CurrentSec
print(TimeToWait)
if TimeToWait < 0 then
TimeToWait = 2 * HalfHourSec - CurrentSec
print(TimeToWait)
end
wait(TimeToWait)
repeat
crystalModule.StartDropParty()
wait(HalfHourSec)
until os.time() ~= os.time({year = 2020; month = 5; day = 10})
end
local function cocoaDropParty()
local CurrentSec = date.min * 60 + date.sec
local HalfHourSec = 60 * 15
local TimeToWait = HalfHourSec - CurrentSec
print(TimeToWait)
if TimeToWait < 0 then
TimeToWait = 2 * HalfHourSec - CurrentSec
print(TimeToWait)
end
wait(TimeToWait)
repeat
cocoaModule.StartDropParty()
wait(HalfHourSec)
until os.time() ~= os.time({year = 2020; month = 5; day = 10})
end
if date.year == 2020 and date.month == 5 and date.day == 10 then
coroutine.wrap(crystalDropParty)()
coroutine.wrap(cocoaDropParty)()
else
local timeUntilDate = os.time({year = 2020; month = 5; day = 10}) - os.time()
print(timeUntilDate)
wait(timeUntilDate)
coroutine.wrap(crystalDropParty)()
coroutine.wrap(cocoaDropParty)()
end
The module and touch handler have not been edited.
Oh but sometimes when the TimeToWait is lower than 0 the new TimeToWait is still lower than 0.
@Quackers337 if you’re there please help!
That’s because you’re multiplying a negative number by 2 so it just gets twice as lower than before. Instead of multiplying by 2, try multiplying by -1.
Actually,
So it’s 40 minutes/30 minutes (crystals/cocoa) - the current sec
Idk maybe I’d do *-0.5?
What is halfhoursec for? (30 chars)
HalfHourSec is how long the cooldown is (SecsInAMinute * Minutes) so 60 * 15 would be 15 minutes.
Wait so if TimeToWait is negative, that means the crystal party is already late? In that case, you should just run the function, not add more time.
BUT… that means it could be at 11:13 or something and it would throw the time off since the next time (for crystals) would be at 11:33, then at 11:53, and so on.
Remember: I want to have it ON THE DOT.
try this:
TimeToWait = HalfHourSec + TimeToWait
it adds another 20 minutes and removes the existing negative time from it.
I think you have misunderstood. HalfHourSec
is the number of seconds in half an hour, namely 1800
. It should be 60 * 30
, not 60 * 20
, this is why you are getting TimeToWait
as lower than 0 even after you add it again.
I want it to be crystals every 20 minutes, and cocoa every 15 minutes, so that’s why I made it 20 and 15. I just didn’t change the variable name.
In that case, you would need to restructure the code a little bit. The example I gave was specifically targeted to reset every half an hour, because the if TimeToWait < 0
statement only checks once. It only needed to check once because 1 hour divided into half hours gives 2 (there are 2 half hours in an hour), so it needed to check once (n - 1, where n is how many times an hour can be divided into the sections of the length you want). If we were going by 20 minutes, we would need to check twice, because 1 hour can be divided into 3 20 minute sections.
The restructured code would look a bit like this:
local CurrentSec = date.min * 60 + date.sec
local AlignMinutes = 20 -- align with 20 minute intervals
local AlignMinutesSec = 60 * AlignMinutes -- the number of seconds in each 20 minute section
-- Align the time to the AlignMinutes intervals
local TimeToWait = AlignMinutesSec - CurrentSec
print(TimeToWait)
for i = 1, math.floor(60 / AlignMinutesSec) - 1 do
if TimeToWait < 0 then
TimeToWait = (i + 1) * HalfHourSec - CurrentSec
print(TimeToWait)
else break
end
end
The TimeToWait is obviously under 0, but somehow this code doesn’t run (I think):
for i = 1, math.floor(60 / AlignMinSecs) - 1 do
if TimeToWait < 0 then
TimeToWait = (i + 1) * AlignMinSecs - CurrentSec
print(TimeToWait)
else warn("TimeToWait is not under 0") break
end
end
I didn’t get the warn message when TimeToWait was over 0 either.