Hey, this question is about something I've been looking at for weeks which is now causing my project to come to a stop until it is resolved.
I have a script, and I'm sorry but for now I will have to post the whole script due to the possibility of not being able to work out my problem through a segment of it. But anyway this script gives each player their stats and levels etc... But when a player dies at the same time as another player or even after in some cases, the script will give that number of players the same level as everyone else.
For example; I'm level 3 in the game and there are two other players, level 1. When the round ends and all three of us are 'reset' the other two players in the game will be level 3 aswell as me. Or I will be level 1 the same as them.
I hope that is enough of an explanation for you to be able to understand my problem. Thanks for any help given in advance, it is highly appreciated!
local ds = game:GetService("DataStoreService"):GetDataStore("dataone") function CharacterRemoving(newPlayer) p = game.Players:GetPlayers() for i = 1, #p do s = Instance.new("StringValue", p[i].Character) s.Name = "Playing" end local stats = Instance.new("IntValue") stats.Name = "leaderstats" coins = Instance.new("IntValue") coins.Name = "Coins" tokens = Instance.new("IntValue") tokens.Name = "Tokens" xp = Instance.new("IntValue") xp.Name = "XP" levels = Instance.new("IntValue") levels.Name = "Levels" coins.Parent = stats tokens.Parent = stats xp.Parent = stats levels.Parent = stats stats.Parent = newPlayer if ds:GetAsync("Key" .. newPlayer.Name) then coins.Value = ds:GetAsync("Key" .. newPlayer.Name) else coins.Value = 0 end if ds:GetAsync("Key1" .. newPlayer.Name) then tokens.Value = ds:GetAsync("Key1" .. newPlayer.Name) else tokens.Value = 0 end if ds:GetAsync("Key2" .. newPlayer.Name) then xp.Value = ds:GetAsync("Key2" .. newPlayer.Name) else xp.Value = 0 end if ds:GetAsync("Key3" .. newPlayer.Name) then levels.Value = ds:GetAsync("Key3" .. newPlayer.Name) else levels.Value = 1 levels.Changed:connect(function(save) ds:SetAsync("Key3" .. newPlayer.Name, save) end) end while true do wait(1) coins.Changed:connect(function(save) ds:SetAsync("Key" .. newPlayer.Name, save) end) tokens.Changed:connect(function(save) ds:SetAsync("Key1" .. newPlayer.Name, save) end) xp.Changed:connect(function(save) ds:SetAsync("Key2" .. newPlayer.Name, save) end) end end game.Players.PlayerAdded:connect(CharacterRemoving) -- Problem is just under here i'm guessing. function CharacterRemoving(newPlayer) levels.Value = ds:GetAsync("Key3" .. newPlayer.Name) wait(1) wait(0.1) if xp.Value >= 100 then levels.Value = levels.Value + 1 xp.Value = 0 end gui=Instance.new("BillboardGui") gui.Parent=newPlayer.Character.Head gui.Adornee=newPlayer.Character.Head gui.Size=UDim2.new(3,0,2,0) gui.StudsOffset=Vector3.new(0,2,0) text=Instance.new("TextLabel") text.Text = "Level " .. newPlayer.leaderstats.Levels.Value text.Size=UDim2.new(1.25,0,0.5,0) text.Position=UDim2.new(-0.125,0,-0.25,0) text.BackgroundTransparency = 1 text.Parent=gui text.FontSize = ("Size36") text.Font = ("ArialBold") text.TextColor3 = Color3.new(255, 255, 0) text.TextStrokeColor3 = Color3.new(0, 0, 0) text.TextStrokeTransparency = 0 w = game.Lighting.WepsGroup:GetChildren() for i = 1,#w do w[i]:Clone().Parent = newPlayer.Backpack end end function onPlayerEntered(newPlayer) newPlayer.Changed:connect(function (property) if (property == "Character") then CharacterRemoving(newPlayer) end end) end game.Players.PlayerAdded:connect(onPlayerEntered) game.Players.ChildAdded:connect(CharacterRemoving) game.Players.PlayerAdded:connect(CharacterRemoving)
There are a lot of problems with your code. I'm going to go through it line by line and refactor it. This may not fix anything, but it will run a lot better.
local ds = game:GetService("DataStoreService"):GetDataStore("dataone") function PlayerAdded(newPlayer) --This function is called when a Player gets added. Why is it called 'CharacterRemoving'? --I'm not really sure what to do with this block of code. It definitely doesn't go inside the PlayerAdded function. What are you trying to do with this? --[[ p = game.Players:GetPlayers() for i = 1, #p do s = Instance.new("StringValue", p[i].Character) s.Name = "Playing" end]] local stats = Instance.new("IntValue", newPlayer) --We can use this second argument to set the Parent on the same line. stats.Name = "leaderstats" local coins = Instance.new("IntValue", stats) --ALL of these properties are now local! If they aren't, they will overwrite each other and we don't want that. coins.Name = "Coins" local tokens = Instance.new("IntValue", stats) tokens.Name = "Tokens" local xp = Instance.new("IntValue", stats) xp.Name = "XP" local levels = Instance.new("IntValue", stats) levels.Name = "Levels" local coinKey = ds:GetAsync("Key" .. newPlayer.Name) --GetAsync called more than once is wasteful. You have a limit to the number of times you can call this per minute! if coinKey then coins.Value = coinKey else coins.Value = 0 end local tokensKey = ds:GetAsync("Key1" .. newPlayer.Name) if tokensKey then tokens.Value = tokensKey else tokens.Value = 0 end local xpKey = ds:GetAsync("Key2" .. newPlayer.Name) if xpKey then xp.Value =xpKey else xp.Value = 0 end local levelsKey = ds:GetAsync("Key3" .. newPlayer.Name) if then levels.Value = ds:GetAsync("Key3" .. newPlayer.Name) else levels.Value = 1 end --This while loop was repeatedly creating these function connections once a second. Changed events will fire every single time they are fired! coins.Changed:connect(function(save) ds:SetAsync("Key" .. newPlayer.Name, save) end) tokens.Changed:connect(function(save) ds:SetAsync("Key1" .. newPlayer.Name, save) end) local xpDeb = false xp.Changed:connect(function() --I made this function control saving of both levels and xp, based on your formula below. if xpDeb then return end xpDeb = true while xp.Value >= 100 do xp.Value = xp.Value - 100 levels.Value = levels.Value + 1 end ds:SetAsync("Key2" .. newPlayer.Name, xp.Value) ds:SetAsync("Key3" .. newPlayer.Name, levels.Value) xpDeb = false end) local function CharacterAdded(newCharacter) --NEVER use the same global function name twice. This can cause unforeseeable bugs and errors! --This function had to be moved inside here so that trying to access the various ValueObjects that are now local don't cause any errors. --We already loaded this above! No need to do it again. --levels.Value = ds:GetAsync("Key3" .. newPlayer.Name) wait(1.1) --No need for two wait statements local gui = Instance.new("BillboardGui") --This could have been your error! When this function was called more than once, the global `gui` variable got overwritten. Setting it to be a local variable makes sure that your code works as intended: only editing THIS BillboardGui. gui.Parent = newPlayer.Character.Head gui.Adornee = newPlayer.Character.Head gui.Size = UDim2.new(3,0,2,0) gui.StudsOffset = Vector3.new(0,2,0) local text = Instance.new("TextLabel") text.Text = "Level " .. newPlayer.leaderstats.Levels.Value text.Size = UDim2.new(1.25,0,0.5,0) text.Position = UDim2.new(-0.125,0,-0.25,0) text.BackgroundTransparency = 1 text.Parent = gui text.FontSize = ("Size36") text.Font = ("ArialBold") text.TextColor3 = Color3.new(255, 255, 0) text.TextStrokeColor3 = Color3.new(0, 0, 0) text.TextStrokeTransparency = 0 for _, wep in ipairs(game.Lighting.WepsGroup:GetChildren()) do --A generic `for` is better here than a numeric. wep:Clone().Parent = newPlayer.Backpack end end newPlayer.CharacterAdded:connect(CharacterAdded) end game.Players.PlayerAdded:connect(PlayerAdded) --All the lines after this are completely unnecessary.
If this still errors, please let me know where.