Going About to create an 'Offline Gardening' System?

Overview
My idea of this ‘offline gardening’ system is that players are able to plant and grow their own crops for selling. The seeds grow within a stipulated time. Let’s say 8 hours. In that 8 hours, whether the player is playing or not, the seed will continue growing until the 8 hours is over. What I’m saying is basically the seeds will grow no matter whether the player is in the game or not.

This example can be seen in many games outside of Roblox. Hence, I wanted to recreate it in Roblox. Example would be Tsuki’s Adventure, a mobile game.

My question is how would I work a way to reach this goal of mine? I’ve thought of using os.time combined with Datastores.

With the method I mentioned above, would it be possible for me to keep track of the time the player has planted the seed, check whether the growth time is over when the player logs back on and if the time is equal or greater than the growth time, the plant will be ready to harvest? Therefore,

  • Is there a better way to keep track of the time. Basically, matching the player’s most recent login time with the growth time of the plant?

  • Would it be better to use tick() or os.time() ?

  • If you can’t save time, what would be an alternative?

What I said may be slightly off from my overview but I wasn’t sure if creating an idle game is possible on Roblox, if it is though, I would like to be pointed in the right direction!

Thank you for reading!

3 Likes

Your idea on how to this is actually correct. In order to achieve the offline growing feature, you’re going to need to save the current growth time, such as one minute, to a datastore. When the player rejoins the server, time the difference in time from the current time to that saved time and then replace the plant model with one that fits the current growth stage. If it’s under eight hours, repeat the first step (save the new growth time to a datastore). If it’s at least eight hours, then the plant is done. As for what to actually use, I recommend os.time() and saving all of the growth stages to a table to prevent needed a ton of datastores.

Just as a note, You can use some handy functions here on the DevForum to return a give timestamp when you input os.time() :slight_smile:

I would definitely recommend using Datastores for this.

Tick math (i.e tick() - LastTick) would be an okay solution if you were counting the growth time in seconds.
I would use os.time if you were trying to do hour, minute, or day type calculations.

If lets say the player logs on when the plant hasn’t finished growing, how would I display the time left for the plant to grow?

Whenever the said value has not yet reached the required time, you would just subtract the old value from the new value.

if tick() - LastTick >= Time then
– Code here
else
local TimeLeft = tick() - LastTick
end

You would do some math with os.time(), something like this:

local DayMath = CurrentDay - LastDay
local HourMath = CurrentHour - LastHour
local MinuteMath = CurrentMin - LastMin
local SecondMath = CurrentSec - LastSec

Then you would make a string showing the time left, string.format done like 00:00:00 would most likely work.

I’ll take in all your help and guidance and create the system! I would also open-source it to those who would want to make something similar once I make it as efficient as possible.:smile:

I’m currently working on the saving feature. I’m kinda stuck at two different points at the moment

#1. Loading of time when the player logs on. If let’s say the timing isn’t up yet(I’m going for every 2 hours)
#2.After the player harvests, reset timer and start counting down

I’m using the Modified Stravant’s Datastore to store the timing. Here is the current code for the two points

#1.Loading of time; Current code

if currentTime then --currentTime is a reference to the player's time save(if he has)
		print(currentTime)
				 HourMath = tonumber(localTimeH) - currentTime[1] --based on zQ86's code
			MinuteMath = tonumber(localTimeM) - currentTime[2] --getting the time left(all the lines)
			 SecondMath = tonumber(localTimeS) - currentTime[3]
			if HourMath >= 2 then
						game.Workspace.LemonTree.Ready.Value = true
			game.Workspace.LemonTree.BillboardGui.TextLabel.Text = "Lemon Tree: Ready!"
			else
		game.Workspace.LemonTree.BillboardGui.TextLabel.Text = "Lemon Tree: ".. tonumber(HourMath) -currentTime[1]..":".. tonumber(MinuteMath) - currentTime[2]..":".. tonumber(SecondMath) - currentTime[3] --listing the time left. I want it to be able to count down even if the player is playing.
     end
		end
if not currentTime then
	game.Workspace.LemonTree.Ready.Value = true
		game.Workspace.LemonTree.BillboardGui.TextLabel.Text = "Lemon Tree: Ready!" --if the player is new, allow the harvest state instantly
	end
end

The problem with this code is the Loading of the time left and how I want it to continue counting down. When I load it, it has this error:
ServerScriptService.sav.datLemonGrow:23: attempt to perform arithmetic on field '?' (a nil value)

#2.Counting Down

game.ReplicatedStorage.harvestHandler.OnServerEvent:Connect(function(player,treePart)
print("harvest")
local saveData = PlayerDataStore:GetSaveData(player)
local treeData = saveData:Get("Ready")
local currentTime = saveData:Get('LemonHarvestTime')
treeData = false --sets the readiness to false
saveData:Set("LemonHarvestTime",{localTimeH,localTimeM,localTimeS}) -- Is there anything wrong with this line?
treePart.Parent.status.TextLabel = "Lemon Tree: Ready in "-- how would i make it countdown 2 hours?
end)

How would I go about to make it countdown while saving the countdown(When the player goes offline and comes back for example, 30min later, the plant needs 1.5 hours to finish growing). How would I list out the time left after the player has harvested the plant(See #2)

1 Like

The error is coming from you doing TextLabel = “hello” instead of TextLabel.Text = “hello”.

Just fixed it. The saving works really well right now! Only issue I have is making a live countdown


At the moment, it isn’t counting down and I have no idea how to do that. Do I use a for loop or RunService?

You could certainly use RunService to do this.


local LastUpdate = 0
game:GetService("RunService").Heartbeat:Connect(function()
	if tick()-LastUpdate>=1 then -- Update text if a second has passed (otherwise there's no change)
		LastUpdate = tick()
		-- Update textlabel here
	end
end)