I’m currently working on an RPG leaderboard / stat tracker and everything is currently working except the players max health increase per level. I’d appreciate any advice. The first codeblock is a snippet of the script that regards the health increase and the codeblock below is the full script.
What advices? I am sorry if I am exaggerating, but is his script not working? Does he need help with how to organize his code better? How to comment it correctly?
local function SetCharacterLevel(player, level)
if player.Character == nil then return end
local humanoid = player.Character:WaitForChild("Humanoid")
local health = level * 5
humanoid.MaxHealth = health
humanoid.Health = health
end
game.Players.PlayerAdded:Connect(function(player)
local playerDataFolder = player:WaitForChild("Data")
local levelValue = playerDataFolder:WaitForChild("Level")
SetCharacterLevel(player, levelValue.Value)
player.CharacterAdded:Connect(function(character)
SetCharacterLevel(player, levelValue.Value)
end)
levelValue.Changed:Connect(function(value)
SetCharacterLevel(player, value)
end
end)
and maybe something like this for the datastore
local playerLoaded = {}
game.Players.PlayerAdded:Connect(function(player)
-- when the player enters the game try to load there data
local success, value = pcall(dataStore.GetAsync, dataStore, player.UserId)
if success == false then return end
-- if the value = nil then set value to a empty table
value = value or {}
-- clone the data folder inside this script with all its values
local folder = script.Data:Clone()
-- loop all values and set them to match what was last saved in the datastore
for i, child in ipairs(folder) do child.Value = value[child.Name] or child.Value end
-- place the folder into the player
folder.Parent = player
-- set the playerloaded to true so we can keep track if there are players loaded so that bind to close can wait
playerLoaded[player] = true
end)
game.Players.PlayerRemoving:Connect(function(player)
-- if player loaded == nil meaning the player failed to load when they entered we simple exit because we dont want to overwrite the old data
if playerLoaded[player] == nil then return end
-- create a table and set the the values from there data folder
local playerData = {}
for i, child in ipairs(player.Data:GetChildren()) do
playerData[child.Name] = child.Value
end
-- now save this table to the datastore
local success, value = pcall(dataStore.SetAsync, dataStore, player.UserId, playerData)
-- now set playerLoaded to nil so that bindtoclose can stop looping and allow the server to close
playerLoaded[player] = nil
end)
-- while players are loaded dont close the server (only works upto 30 seconds)
game:BindToClose(function()
while next(playerLoaded) ~= nil do
task.wait()
end
end)
PlayerDataFolder and LevelValue is not a thing before he creates them when a player joins the game, so you can’t wait for them to be there, when they’re non existent
Also there’s a few issues with your SetCharacterLevel function. Haven’t taken a look at the bottom script.
Edit: After looking at the bottom script. Don’t have multiple CharacterAdded or PlayerAdded events in your game.
in the second script it creates PlayerDataFolder and LevelValue so the first script will wait until the second script has created them
iv just double checked the SetCharacterLevel function and i see no problem what problem do you see?
the hole point of events is to have as many functions as you like connected to them i’m not sure why you think you should only have one function connected to a event
and we are not using unsynchronised threads so not sure what the image is about
so that’s correct if you connect multiple functions to the same event the order that the functions will be called is undefined so that’s why i’m waitForChild to make sure the order is correct
currently Roblox only uses 1 thread (that’s why functions get called one after the other and not at the same time) but they do have a beta feature that allows you to have multiple threads in studio but not in published games you can read more here Parallel Lua Beta
i believe the Unsafe warning has something to do with the new parallel lua feature but i’m not sure because i have not really tested it
Alright, I will read the article when I have the time.
But since you’re WaitingForChild anyway I would suggest only having 1 PlayerAdded event, since I personally feel that it’s a unneccessary wait.
I personally do this approach:
Create all core ReplicatedDataValues (leaderstats or what fits your game)
Load PlayerData (or give defaultData if no Data was found for the core ReplicatedDataValue, and create ReplicatedDataValues for non-core Data (like if you have a dictionary of pets you own or something)
Parent all ReplicatedDataValues into leaderstats(or what ever fits your game), since we don’t want to add them before the values of them are correct
Hey, thanks for all the replies guys as stated in the original description everything in the script is working properly except the health increasing per level.
plr.MaxHealth = plr.MaxHealth + 5 * plr.Values[LevelName].Value
-- In this case do this instead:
plr.MaxHealth += 5 * plr.Values[LevelName].Value
This is the current line in the script and I’m wondering how i can get it to work properly? Its currently not increasing the players max health per level as intended and I’m stumped on how to fix the problem.
I ended up finding a solution while looking through some free models. For anyone curious or looking for a solution I’ve put an exerpt from the script i found below.
local hum = child.Character:FindFirstChild("Humanoid")
if (hum ~= nil) then
hum.MaxHealth = hum.MaxHealth + 5 * lvl.Value
hum.Health = hum.MaxHealth
end end)
child.CharacterAdded:connect(
function(character)
local hum = character:FindFirstChild("Humanoid")
if (hum ~= nil) then
hum.MaxHealth = hum.MaxHealth + 5 * lvl.Value
hum.Health = hum.MaxHealth
end