How do I make a saving death counter leaderstats - roblox

So I am trying to make a game, but cant keep the stats. I already have a working death counter but can't figure out how to save it, it resets everytime I rejoin. Here are two codes I've tried:
1)
local pointsDataStore = game:GetService("DataStoreService"):GetDataStore("Deaths")
game.Players.PlayerAdded:Connect(function(player)
local playerKey = "Player_" .. player.UserId
local success, err = pcall(function()
pointsDataStore:UpdateAsync(playerKey, function(oldValue)
local newValue = oldValue or 0
newValue = newValue + 0
return newValue
end)
end)
end)
2)
local DS = game:GetService("DataStoreService"):GetDataStore("Points")
game.Player.PlayerAdded:connect(plr)
local leaderstats = Instance.new("Model",plr)
leaderstats.Name = "leaderstats"
local currency = Instance.new("IntValue", leaderstats)
currency.Name = "Deaths"
currency.Value = 1
while wait(5) do
DS:SetAsync(plr.userId.."_DS", currency.Value)
end
end)

I would load the value from a datastore when the player joins, then increment it on each death and also save it to the datastore.
Note, that for triggering death, the script is using the Humanoid.Died event.
local deathsStore = game:GetService("DataStoreService"):GetDataStore("Deaths")
function playerAddedHandler(plr)
-- key that is used to store the death value
local playerKey = "Player_" .. plr.UserId
-- Add leader board
local leaderstats = Instance.new("Folder", plr)
leaderstats.Name = "leaderstats"
-- Add "Deaths" column to leader board
local deaths = Instance.new("IntValue", leaderstats)
deaths.Name = "Deaths"
-- Load Deaths value from previous game
deaths.Value = deathsStore:GetAsync(playerKey)
-- Hook up event handler that is triggered when character dies
plr.CharacterAdded:Connect(function(char)
char.Humanoid.Died:Connect(function()
-- increment death value on the leader board
plr.leaderstats.Deaths.Value = plr.leaderstats.Deaths.Value + 1
-- save the value in our deaths datastore
local success, err = pcall(function()
deathsStore:SetAsync(playerKey, plr.leaderstats.Deaths.Value)
end)
end)
end)
end
game.Players.PlayerAdded:Connect(playerAddedHandler) -- call function "playerAddedHandler" every time a player joins the game
Also. Don't forget to enable datastore usage, otherwise it will give you a 403 error in your output. You do that on the roblox website in your game's basic settings:

Related

ServerScriptService.Size:4: attempt to index nil with 'Humanoid'

Cant figure out what the problem is
while wait(.5) do
local children = game.Players:GetChildren("Humanoid")
for i = 1, #children do
local hum = children[i] .Character.Humanoid
hum.HeadScale.Value = children[i].leaderstats.Points.Value/50 +1
hum.BodyHeightScale.Value = children[i].leaderstats.Points.Value/50 +1
hum.BodyWidthScale.Value = children[i].leaderstats.Points.Value/50 +1
hum.BodyDepthScale.Value = children[i].leaderstats.Points.Value/50 +1
hum.WalkSpeed = children[i].leaderstats.Points.Value/3.12
hum.JumpPower = children[i].leaderstats.Points.Value
hum.MaxHealth = children[i].leaderstats.Points.Value+25
end
end
was trying to get a simple size script to work.
The attempt to index nil with Humanoid error is telling you that the object that you are trying to grab the Humanoid out of doesn't exist. This line specifically :
local hum = children[i].Character.Humanoid
When a player joins the game, there is an indeterminate amount of time before their character model actually spawns into the world. So between when they join and when their character spawns, the Player.Character property is nil.
Your code does not handle the possibility that the character model is nil, and you are trying to access the humanoid immediately.
A safer approach is not to use a loop, but to observe changes to the leaderstats values and react to those changes. So in your code that creates your leaderstats objects, do something like this :
local Players = game:GetService("Players")
local function updateCharacter(hum : Humanoid, points : number)
local bodyScale = (points / 50) + 1
local walkSpeed = points / 3.12
local jump = points
local health = points + 25
hum.HeadScale.Value = bodyScale
hum.BodyHeightScale.Value = bodyScale
hum.BodyWidthScale.Value = bodyScale
hum.BodyDepthScale.Value = bodyScale
hum.WalkSpeed = walkSpeed
hum.JumpPower = jump
hum.MaxHealth = health
end
Players.PlayerAdded:Connect(function(player)
-- when a player joins the game, give them a leaderstats folder
local leaderstatsFolder = Instance.new("Folder")
leaderstatsFolder.Name = "leaderstats"
local pointsValue = Instance.new("IntValue", leaderstats)
pointsValue.Name = "Points"
pointsValue.Value = 0 -- or load from dataStores
leaderstatsFolder.Parent = player
-- listen for changes to the points and resize the character
pointsValue.Changed:Connect(function(newValue)
-- escape if the character doesn't exist
local character = player.Character
if character then
updateCharacter(character.Humanoid, newValue)
end
end)
-- when the character model spawns into the world, update it immediately with the player's point size
player.CharacterAdded:Connect(function(character)
updateCharacter(character.Humanoid, pointsValue.Value)
end)
end)

Roblox Functions are running 20+ times

I seem to be having an issue of every time I want to pass a function when an event happens such as a Humanoid.Died() or a BindableEvent it runs the function 20+ times, also adding to an IntegerValue that many times as well. I have tried debounces, BindableEvents, connection:Disconnect(), etc. Is there something I'm doing wrong or missing?
Updated original code:
function module.damageHumanoid(attacker, player, humanoid, damage)
local connection
local debounce = false
connection = humanoid.Died:Connect(function()
if not debounce then
debounce = true
connection:Disconnect()
module.onDeath(player)
end
end)
if player:FindFirstChild("damage") == nil then
newFolder = Instance.new("Folder")
newFolder.Name = "damage"
newFolder.Parent = player
end
if newFolder:FindFirstChild(tostring(attacker)) == nil then
record = Instance.new("IntValue")
record.Name = tostring(attacker)
record.Parent = newFolder
end
if record.Value >= 100 then -- sanity check
else
record.Value = record.Value + damage
end
return humanoid:TakeDamage(damage)
end
Which triggers this code:
function module.onDeath(player)
if player:FindFirstChild("damage") ~= nil then
local folder = player:WaitForChild("damage")
local contents = folder:GetChildren()
for i,v in pairs(contents) do
local item = folder[tostring(v)]
damages[item.Name] = item.Value
end
end
local debounce = false
if not debounce then
debounce = true
module.handleKill(damages)
end
end
This is the sword script's function:
function Blow(Hit)
if not Hit or not Hit.Parent or not CheckIfAlive() or not ToolEquipped then
return
end
local RightArm = Character:FindFirstChild("Right Arm") or Character:FindFirstChild("RightHand")
if not RightArm then
return
end
local RightGrip = RightArm:FindFirstChild("RightGrip")
if not RightGrip or (RightGrip.Part0 ~= Handle and RightGrip.Part1 ~= Handle) then
return
end
local character = Hit.Parent
if character == Character then
return
end
local humanoid = character:FindFirstChildOfClass("Humanoid")
if not humanoid or humanoid.Health == 0 then
return
end
local player = Players:GetPlayerFromCharacter(character)
if player and player == Player then
return
end
UntagHumanoid(humanoid)
TagHumanoid(humanoid, Player)
module.damageHumanoid(plur, player, humanoid, Damage)
end
So I guess the way I was trying to use debounce isn't correct anymore. I referred to the Roblox documentation and found this: https://create.roblox.com/docs/scripting/scripts/debounce
If anyone would like to know what ended up working for me here it is:
humanoid.Died:Connect(function()
if not humanoid:GetAttribute("Killed") then
humanoid:SetAttribute("Killed", true)
module.onDeath(player)
task.wait(10)
humanoid:SetAttribute("Killed", true)
end
end)

When I mine a rock in my game (Click it 10 times) it mines and gives 100 coins. However if someone else does it it gives it to me? Can anyone h3lp?

So when I click it 10 times it mines however it only give coins to me when someone else mines it. I have no clue really what to do so i need help. Ok so here is the script:
game.Players.PlayerAdded:Connect(function(player)
script.Parent:Clone()
local money = player:WaitForChild("leaderstats").Money
script.Parent.ClickDetector.MouseClick:Connect(function()
local billboard = script.Parent.BillboardGui
print(health)
health = health - 1
billboard.Enabled = true
billboard.TextLabel.Text = health
if health == 0 then
local clickdetector = script.Parent.ClickDetector
billboard.Enabled = false
money.Value = money.Value + 100
script.Parent.ClickDetector.Parent = nil
script.Parent.Union.Transparency = 1
script.Parent.Union.CanCollide = false
wait(5)
clickdetector.Parent = script.Parent
script.Parent.Union.Transparency = 0
script.Parent.Union.CanCollide = true
health = 10
end
end)
end)
The problem is that you need to make sure the player variable matches the player that clicked it.
script.Parent.ClickDetector.MouseClick:Connect(function()
should be:
script.Parent.ClickDetector.MouseClick:Connect(function(clicker)
and use an if statement:
if clicker == player then
--code that gives points
end
Also when you clone the parent it clones the script so that may cause bugs.

(Also roblox related)Countdown freezes at a random number

so there are 2 scripts: script and localscript.
The script determines how many seconds there will be and then it fires it to all player clients & the localscript changes the text to seconds. But when i tested the game the countdow freezes either at a number or a random number anyway here's the script again:
script:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("IntermissonEvent")
local secondsRemaining = 15
for t = secondsRemaining, 0, -1 do
remoteEvent:FireAllClients(t)
wait(1)
end
localscript:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("IntermissonEvent")
local function onTimerUpdate(seconds)
script.Parent.Text =(seconds)
wait(15)
script.Parent.Parent.CountdownText.Visible = false
script.Parent.Parent.IntermissionText.Visible = false
script.Parent.Parent.TextLabel.Text ="Vote for a Map!"
script.Parent.Parent.MapVotingFrame.Visible = true
end
remoteEvent.OnClientEvent:Connect(onTimerUpdate)
Your LocalScript is running all of this logic every single time the server fires the event. Instead of waiting, check the value with an if-then.
local function onTimerUpdate(seconds)
script.Parent.Text = tostring(seconds)
if seconds == 0 then
script.Parent.Parent.CountdownText.Visible = false
script.Parent.Parent.IntermissionText.Visible = false
script.Parent.Parent.TextLabel.Text = "Vote for a Map!"
script.Parent.Parent.MapVotingFrame.Visible = true
end
end

How do I change a value in the leaderstats via touching a part? (Roblox)

Here's the error and what I've tried.
Error: Workspace.Part.Script:4: attempt to index nil with 'leaderstats'
My code:
Making Leaderstats:
game.Players.PlayerAdded:Connect(function(plr)
local ls = Instance.new("Model")
ls.Name = "leaderstats"
ls.Parent = plr
local m = Instance.new("IntValue")
m.Name = "Stars"
m.Value = 0
m.Parent = ls
end)
Touch Code:
local collected = false
script.Parent.Touched:Connect(function()
if collected == false then
game.Players.LocalPlayer.leaderstats.Stars.Value = game.Players.LocalPlayer.leaderstats.Stars.Value + 1
end
collected = true
end)
A server script would suit your need better. In a localscript, the change would only appear for the player. Also, it's better practice to use the Players service offered by Roblox. Here's an example:
local Players = game:GetService('Players')
local collected = false
script.Parent.Touched:Connect(function(partTouched)
if partTouched.Parent:IsA('Model') and partTouched.Parent:FindFirstChild('Humanoid') and partTouched:IsA('BasePart') then -- Is this a player? If so, then..
local player = Players:GetPlayerFromCharacter(partTouched.Parent)
if collected == false then
player.leaderstats.Stars.Value += 1 -- shorter syntax
end
collected = true
--script.Parent:Destroy() optional if this part won't be used again.
end
end)
If you're planning to use this for many parts, using a central ModuleScript would save you lots of changing things back and forth: https://developer.roblox.com/en-us/api-reference/class/ModuleScript