Help on Making a Daily, Self-Updating Shop?

You could use a table like this:

local Items = {"Item1", "Item2", "Item3", "Item4",}
local Daily_Items = {

            ["Daily_Item1"] = math.random(1, #Items),
            ["Daily_Item2"] = math.random(1, #Items),
            ["Daily_Item3"] = math.random(1, #Items),
            ["Daily_Item4"] = math.random(1, #Items)

}

--[[ Then make them just like if Daily_Item1 is a Emote called test for example, make it so it will show on the spot a gui with the emote called test and others.
]]--
1 Like

Yeah, I get this concept. Okay, the problem is that my function to pick items is completely random.

So, if a new day passed, I would get my function to roll and pick 10 different items, for example. But, this wouldn’t sync the items across all servers because they’re rolling 10 times in a completely random function.

Do you know how I can generate items with a seed, and still keep weighted randomization (like Common, Rare, Legendary)? If there is, I can switch to that.

1 Like

This wouldn’t sync across all servers, though, right? Because math.random isn’t always going to be the same set of numbers.

How would I generate by seed, and still keep weight of the rarities?

1 Like

In order to get the same randomness on all the servers just seed the randomness with the day. How you handle the randomness to generate items is a different story.

You can have the function that picks items have “seed” as an argument so when you call it you can also pass it the seed for the math.random functions.

1 Like

The easiest thing to do is have a external server handle the random items. And use httpService to get it in each server. And update it every hour or something

I recommend using glitch (because its free) and the server should have an endpoint that returns the item.

This fixes the problem because its only ONE server.

1 Like

To get it to sync, I recommend you try this tutorial:

Then you update the spreadsheet manually. I would make the key in the spread sheet the date and make the value equal to what item are in the shop.

1 Like

I agree with this, this would fix all my problems. Is Glitch’s language also Lua? Because I wouldn’t know how to code it if it wasn’t. Otherwise, I guess I can learn its language.

Right now though, I’m still trying to see if I can do this in game, so I’ll use this as a last resort option.

1 Like

Its node.js (Javascript). its pretty simple to learn tho

1 Like

This would work, except I’m not trying to update the shop manually, because I know for sure that some times I won’t be available/ won’t have the strength to update every single item in ALL of my future shops every single day. I could look into this and see if I can randomize the keys and values by weight. I’ll also use this as one of my “last resort” options as well.

1 Like

Good idea, I can try to test this out later and look at some results.

1 Like

If you make the key the date, you would only have to update it once a week or something, so if you miss a day it’s not terrible.

1 Like

Yeah, you’re right, but right now the highest priority for me is to find a way to get this done all by code.

1 Like

To get time, use os.time or os.date, called from a server script of course.

For the random numbers, use math.randomseed to make the seed the same in all server instances, perhaps by using the current year and day of year. This was pointed out by another person here as well. For those who don’t know, math.random is pseudorandom, so if the seed is the same across servers, the random numbers will be the same across all servers. Or maybe you can use a non-random rotation.

You may also be able to use datastores for some things, but be aware of its limits.

If you want to get crazy, use httpservice and set up your own server or something.

2 Likes

Maybe try adding a script that uses data stores to save a new random code for the shop every 2 minutes. Sort of like this:

local dss = game:GetService("DataStoreService")
local ShopDS = dss:GetDataStore("ShopDataStore")

local TodaysShop = ShopDS:GetAsync(ShopDS:GetAsync("CurrentDate"))

while wait(120) do
    local totalDates = ShopDS:GetAsync("TotalDates")
    ShopDS:SetAsync(totalDates, RandomNumberHere) -- Replace with your random number thingy
    ShopDS:SetAsync("TotalDates", totalDates + 1)
    if ReplaceWithCurrentHour == 24 and ReplaceWithCurrentMinute > 58 then -- Replace the variables with current hour/minute
        --Shop needs to be updated!
        local yesterday = ShopDS:GetAsync("CurrentDate")
        wait(120)
        ShopDS:SetAsync(yesterday + 1)
        TodaysShop = yesterday + 1
end

That may seem confusing, but if it works it should update the list every 2 minutes. The only limitations I see are the data store limitation, and the fact that you would need to have at least on server running every day at midnight (or whenever you switch shops) and you would need to reset everything every 99999999999999999999 days (so you wouldn’t break the max length of a datastore’s key).

This is probably over-complicated though.

2 Likes

This just gave me an idea. Maybe, I could generate a set of items, and then save it to a data store WITH the seed generated for that day. Then, I could add a conditional where it does :GetAsync and then check to see if the seed value in the data store is equal to the seed generated for the current day (which would be the same for every server, as long as its the same day). That way, if the value isn’t the same, it would generate a new set and update the data store with the new seed value. Only thing is wouldn’t all of the servers end up doing :GetAsync at the same time? So, they would all detect an old value because there’s no way for a server to “wait” for another server to update it? Or would it still work because all the servers are still updating the Async regardless?

All I need to know how to do to solve this problem is one of these options:

  • Find a way to generate new items with a seed and keep weighted randomization (to keep different rarities)

  • Update a data store or a global value somewhere + make sure servers aren’t overwriting each other

Or, any other way someone can offer.

Here’s my code so far for it to update every 24 hours at 5:00 PM PST. I still need to add a seed, of course.

local syncedtime = require(game.ReplicatedStorage.SyncedTime) -- returns a synced time, because it's external. I'm not using os.time() because there have been a lot of reports of it not being synced
 
local lt = require(game.ServerScriptService.LootTable) -- The module I'm using for rolling and picking items
syncedtime.init()

local offset = (60 * 60 * 17)  -- 17 hours, or 61,200 seconds

while wait(1) do
	local t = (math.floor(syncedtime.time())) + offset -- Sets the date to Thursday 5PM PST
	local origtime = t - offset
	
	local daypass = origtime % 86400 -- basically, this would output how far into the day we are in seconds
	print(daypass)
	
	if daypass == 0 then --- we know exactly one day has passed, I'd do all of my shop functions under this
		print("It is 5:00 PM PST.")  

	else
		local timeleft = 86400 - daypass  -- finds out how much time is left until the next day
		
		local timeleftstring = toHMS(timeleft)  -  just formatting to get it to HH:MM:SS 
		
		--print("The time left until 5:00 PM PST is ".. timeleftstring)  <-- Obviously I would just use "timeleftstring" for a timer in a shop
	end
end

Keep in mind this may be too complicated, as you are probably able to arrange for each server to select the items on their own. The items would all be the same, as the random number seeds would all be the same.

Otherwise, to have different weights, just use different random number ranges. You may use
a = math.random(1, 10) for regular items and b = math.random(1, 100) for rare items.

To make sure severs don’t overwrite each other, use the year and day of year as a key (such as 2020150) for each new real life day and use UpdateAsync to check if the data store has been set up for that day. If not, write to the data store. Be sure to keep in the mind the limits of data stores.

Yeah, that’s what I was trying to get at in my previous reply - updating a data store if the seed in it doesn’t match the seed for the current day. Basically, what you said.

Let’s say that the seed for the previous day is 2020519, and then 5:00 PST hits. The seed becomes 2020520, and the servers try to update. So, if one server updates the data store, the other ones running at the same time wouldn’t have to, right, because of the conditional?

The only reason why I’m kinda confused about this is because I’m thinking that all of the servers running would see the old key because all of them are checking at the same time (so nothing would be updated yet), and then all of them would try to update it. Unless, there’s some sort of latency so only one server is able to update it, so the other ones wouldn’t have to because the data store is already updated.

I’ll be back, I have to go now

This just gave me an idea that was so simple! Basically, what I can do is regenerate the shop items separately, using a time increment of let’s say like 1 hour (just to not exhaust the data store), and then just have the shop update to whatever’s in the data store when a new day hits.

And yeah, the limitation to this is that I’d always need a server running. But, if I just lowered the time increment, then by the time the shop updates again the values should already be something different. So, I’ll go with this as the solution for now. Thanks!

Edit: This is still the solution, I just thought of a smarter way to do this.
I can just connect the item generation/update function to PlayerAdded, with a cooldown, so that as long as 1 person joins/stays in the game longer than the cooldown, the shop will rotate by itself.

Yes, there could be an issue if a bunch of servers access one key at the same time. That’s why I don’t recommend it. Theoretically, a bunch of servers would try to update the value using UpdateAsync, and they would then see that the value has already been updated and would stop. But in reality, something may break because of the limitations.

see “game limits”