Health and MaxHealth DataStore (Free use)

Well, I have made this system to save Healthy MaxHealth of the player’s humanoid, I put it for them to use (Free use). Well, the script works when the player enters, if it is the first time the player enters, it will give him 100 Health and MaxHealth. When exiting the game, the data is saved in the same PlayerAdded function, inside of that is the CharacterRemoving which is what saves the data when exiting, and when you die you get the health of MaxHealth (In case you make another script change the maxhealth, that amount of maxHealth you put to life). They can change the script, if you see any bug and fix it, let me know (This is what I could do, so I don’t think it’s professional).

local DataStore = game:GetService("DataStoreService")
local Players = game:GetService("Players")

local HealthData = DataStore:GetDataStore("HealthData")

Players.PlayerAdded:Connect(function(plr)
	plr.CharacterAdded:Connect(function(char)
		local Humanoid = char:WaitForChild("Humanoid")
		
		Humanoid.Died:Connect(function()
			local Get_Data_Died = {
				Health = char.Humanoid.MaxHealth;
				MaxHealth = char.Humanoid.MaxHealth;
			}
			local Success, err = pcall(function()
				HealthData:SetAsync(plr.UserId, Get_Data_Died)
			end)
		end)	
		
		local Get_Data = nil
		local Success, err = pcall(function()
			Get_Data = HealthData:GetAsync(plr.UserId)
		end)
		if Success and Get_Data ~= nil then
			if Get_Data.Health >=  Get_Data.MaxHealth then
				Humanoid.MaxHealth = Get_Data.MaxHealth
				Humanoid.Health = Get_Data.MaxHealth
			else
				Humanoid.MaxHealth = Get_Data.MaxHealth
				Humanoid.Health = Get_Data.Health
			end
		else
			Humanoid.MaxHealth = 100
			Humanoid.Health = 100
		end
	end)
	plr.CharacterRemoving:Connect(function(char)
		local Get_Data_Removing = {
			Health = char.Humanoid.Health;
			MaxHealth = char.Humanoid.MaxHealth;
		}
		local Success, err = pcall(function()
			HealthData:SetAsync(plr.UserId, Get_Data_Removing)
		end)
		if Success then
			print("Se ha guardado correctamente / Has been saved successfully")
		else
			print("hubo un error al guardar / there was an error saving")
			warn(err)
		end
	end)
end)
7 Likes

Hi,
I’m not sure if I read it correctly,
but every time the player dies you’re calling a SetAsync function? I’m pretty sure it’s a waste of resources

3 Likes

You see, without that when you die and reappear, you get the same life you had before you died. I did it this way so that when I died, life would restart (sending a SetAsync with the MaxHealth data so that you have a lifetime depending on maxHealth)

2 Likes

In this case shouldn’t it be better to cache the value?
If the player leaves then you save the values that you cached?

6 Likes

the truth is that i’m not very good at scripting, so i can’t do advanced scripts

2 Likes

Isn’t it like, making a table, with player as the key, and health, maxhealth as the values. I don’t think that is very advanced?

4 Likes

Hello there!

I saw your script didn’t have cache, so… I added cache :partying_face:

New script with cache
local DataStore = game:GetService("DataStoreService")
local Players = game:GetService("Players")

local HealthData = DataStore:GetDataStore("HealthData")

local cache_ = {}


Players.PlayerAdded:Connect(function(plr)
	plr.CharacterAdded:Connect(function(char)
		
		spawn(function()
			
			while true do
				if char:FindFirstChild("Humanoid") then
					local Get_Data_Updated = {
						Health = char.Humanoid.MaxHealth;
						MaxHealth = char.Humanoid.MaxHealth;
					}
					
					cache_[plr.UserId] = Get_Data_Updated
					task.wait(6)
				end
			end
			
		end)
		
		local Humanoid = char:WaitForChild("Humanoid")

		Humanoid.Died:Connect(function()
			local Get_Data_Died = {
				Health = char.Humanoid.MaxHealth;
				MaxHealth = char.Humanoid.MaxHealth;
			}
			
			cache_[plr.UserId] = Get_Data_Died
		end)	

		local Get_Data = nil
		local Success, err = pcall(function()
			Get_Data = HealthData:GetAsync(plr.UserId)
		end)
		if Success and Get_Data ~= nil then
			if Get_Data.Health >=  Get_Data.MaxHealth then
				Humanoid.MaxHealth = Get_Data.MaxHealth
				Humanoid.Health = Get_Data.MaxHealth
			else
				Humanoid.MaxHealth = Get_Data.MaxHealth
				Humanoid.Health = Get_Data.Health
			end
		else
			Humanoid.MaxHealth = 100
			Humanoid.Health = 100
		end
	end)
	plr.CharacterRemoving:Connect(function(char)
		local Get_Data_Removing = {
			Health = cache_[plr.UserId].Health or 100;
			MaxHealth = cache_[plr.UserId].MaxHealth or 100;
		}
		
		print(Get_Data_Removing)
		
		local Success, err = pcall(function()
			HealthData:SetAsync(plr.UserId, Get_Data_Removing)
		end)
		if Success then
			print("Se ha guardado correctamente / Has been saved successfully")
		else
			print("hubo un error al guardar / there was an error saving")
			warn(err)
		end
		
		task.wait(1)
		cache_[plr.UserId] = nil
		
	end)
end)

And I think it’s should work just fine!

@NUTRICORP

6 Likes

Certainly, I forget to answer as to whether the data is saved. If you save the data and load it, although there is also a small possibility of a warn that you are sending a lot of data (the probability is small)

Thanks for helping me with that, although I don’t know what the cache is for but I suppose it helps to save the data and then load it, right?

2 Likes

No.

Instead of saving to DataStore every time you want to save the data

You just “cache” it locally it’s faster, easier, and doesn’t waste much resources

And at the end you just save cache to the DataStore

Ahhh I understand, I did not know about that. Well, I tried the script but it doesn’t save the data (or doesn’t load it, I don’t know the problem)

2 Likes

Sorry, I was sleeping but, what I meant by caching is to save the health, max health player last had. If they got new ones we just simply erase the data before. So it should be the same as doing 1 normal SetAsync

1 Like

It works fine but, I think it might cause a memory leak. You’re literally creating a while loop every time the character gets added, so more loops will get added as the player dies and respawns, causing huge lag.

Using a while loop with a 6-second interval isn’t very accurate, I’d suggest you use RunService.Heartbeat if you’re scared the character already gets removed the moment Players.CharacterRemoving fires, or just caching during Player.CharacterRemoving should work.

Also I’m not sure why you should get the data from the datastore every time the character is added. Shouldn’t you do that for only the first time, second time onwards use the values from the cache?

3 Likes

Can that help not to lose data? I have a player settings system (something like a game settings menu, like GTA 5 or Warzone), although the data is rarely lost, like this I thought caching might be the solution

The idea of caching is to save the data locally and finalizes it when the player leave, so no matter how many times they changed something, you only need to save once.

On the other side, if you keep saving when they changed something, it may cause data throttle and you might lose data.

2 Likes

Hey,

I used the original script and just added cache to it

1 Like

Oh sorry, my bad. I thought you revamped the entire thing lol

3 Likes

Yeah It’s ok, I didn’t notice there was a memory leak there

1 Like

All I’m going to say is this is alright. The simplicity in this is reasonable for any scripter with some advanced knowledge in Lua. I like how you’re using PCalls which are a good sign! Although, I feel like it isn’t very necessary. Just my opinion.

2 Likes