The problem with wait(1) isn’t that 1 is too small of a wait time, it’s because wait() is going to be called so often (every one second lol). I literally just read a post on why calling it this often is bad, i’ll try and find it.
Just asking, this should start spawning them ON THE DOT, right?
Why would you do this? Stepped happens 1/60th per second. This is not a situation where you need to use a stepped event.
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.