Hey devs, I have an issue where I have issues making the killsleaderstat to add +1 after each player the client has killed.
I’m quite new to scripting and I have somewhat beginner knowledge. I’ve made this script with support.
What do you want to achieve?
I would like to make a function that gives +1 kills after every person the client has killed.
-- local dataStoreService = game:GetService("DataStoreService")
local killSave = dataStoreService:GetDataStore("PlayerKills")
game.Players.PlayerAdded:Connect(function(player)
local totalKills
local success, err=pcall(function()
totalKills = killSave:GetAsync("Player_"..player.UserId)
end)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local kills = Instance.new("IntValue")
if success then
kills.Value = totalKills
else
kills.Value = 0
end
kills.Name = "Kills" -- Name that shows in game.
kills.Value = 0 -- Value of Kills When A Player Joins.
kills.Parent = leaderstats
local rank = Instance.new("StringValue")
rank.Name = "Rank" -- Same as Line 7.
rank.Value = "Newbie"
rank.Parent = leaderstats
local function updateKills(newKills)
if newKills then
if newKills >= 20 then -- Change number for the amount of kills to rank up.
rank.Value = "Intermediate" -- New rank name.
end
if newKills >= 30 then -- Change number for the amount of kills to rank up.
rank.Value = "Initiated" -- New rank name.
end
if newKills >= 40 then -- Change number for the amount of kills to rank up.
rank.Value = "Capable" -- New rank name.
end
if newKills >= 50 then -- Change number for the amount of kills to rank up.
rank.Value = "Skilled" -- New rank name.
end
if newKills >= 100 then -- Change number for the amount of kills to rank up.
rank.Value = "Proficient" -- New rank name.
end
if newKills >= 200 then -- Change number for the amount of kills to rank up.
rank.Value = "Professional" -- New rank name.
end
if newKills >= 300 then -- Change number for the amount of kills to rank up.
rank.Value = "Specialist" -- New rank name.
end
if newKills >= 400 then -- Change number for the amount of kills to rank up.
rank.Value = "Advanced" -- New rank name.
end
if newKills >= 500 then -- Change number for the amount of kills to rank up.
rank.Value = "Expert" -- New rank name.
end
if newKills >= 1000 then -- Change number for the amount of kills to rank up.
rank.Value = "Incredible" -- New rank name.
end
if newKills >= 2000 then -- Change number for the amount of kills to rank up.
rank.Value = "Outstanding" -- New rank name.
end
if newKills >= 3000 then -- Change number for the amount of kills to rank up.
rank.Value = "Elite" -- New rank name.
end
if newKills >= 4000 then -- Change number for the amount of kills to rank up.
rank.Value = "Superior" -- New rank name.
end
if newKills >= 5000 then -- Change number for the amount of kills to rank up.
rank.Value = "Master" -- New rank name.
end
if newKills >= 10000 then -- Change number for the amount of kills to rank up.
rank.Value = "Ultimate Master" -- New rank name.
end
end
end
updateKills()
kills.Changed:Connect(updateKills)
end)
local function save(player)
local success, err = pcall(function()
killSave:SetAsync("Player"..player.UserId,player.leaderstats.Kills.Value)
end)
if success then
print("Saving Succeeded.")
else
print("Failure.")
end
end
local function autosave()
while wait(15)do
for i, player in pairs(game:GetService("Players"):GetPlayers()) do
print("Saving")
save(player)
end
end
end
NOTE: The script does not contain the function that gives out +1 kills after a client has killed another player.
Something I’ve learned is that code should never be data or something along those lines. That confused me at first, but it has been very helpful after I understood it.
In your code you have this:
The first “wrong” thing about this is that the checks are in the wrong order, as you will now check and update a value for each possible rank, the second “wrong” thing about this is that you are now storing Data inside Code.
You could replace this by making a table containing the data instead, something along these lines:
You can then loop through this and decide which rank should be awarded.
for requirement, title in pairs(rankRequirements) do
if newKills >= rankRequirements then
rank.Value = title
end
end
This will still look through it in the wrong order, but it will use a lot let code, and makes it a lot easier to add/modify ranks.
To actually count kills you should have a script which is responsible for dealing damage. This script can very easily see which player was killed, and by whom (and even by which weapon if you set it up in that way).
Thanks for the advice, definitely useful!
The script which is the script for dealing the damage is:
local debounce = false
local HealthLoss = 10-- Change this to the damage you need.
function OnTouched(Part)
if Part.Parent ~= nil then--Keep Parentless blocks from breaking it.
if debounce == false and Part.Parent:findFirstChild("Humanoid") ~= nil then
debounce = true
Part.Parent:findFirstChild("Humanoid"):TakeDamage(HealthLoss)
wait(0.11)--Wait two seconds before the brick can hurt someone.
debounce = false
end
end
end
script.Parent.Touched:connect(OnTouched)
I know, this script is quite messy.
This script works just like a damage brick, I’m creating a punching tool and it works great!
It’s only that I’m unsure on where to place the function and how to create the function itself.
This is the point where you deal damage. If you check the HP of the humanoid hit here then you can decide whether it was killed or not. If it was killed, then update kills for the player who owns the tool/whatever this is connected to.
local debounce = false
local HealthLoss = 10-- Change this to the damage you need.
function OnTouched(Part)
if Part.Parent ~= nil then--Keep Parentless blocks from breaking it.
if debounce == false and Part.Parent:findFirstChild("Humanoid") ~= nil then
debounce = true
local humanoid = Part.Parent:FindFirstChild("Humanoid")
humanoid:TakeDamage(HealthLoss)
if humanoid.Health <= 0 then
print(humanoid.Parent, " was killed by", PLAYER)
end
task.wait(0.11)--Wait two seconds before the brick can hurt someone.
debounce = false
end
end
end
script.Parent.Touched:connect(OnTouched)
PLAYER, in the script above, is either game.Players.LocalPlayer if its a localscript, or game:GetPlayerFromCharacter(script:FindFirstAncestorWhichIsA("Tool").Parent) if it is a tool.
This is good stuff. Much better than pushing values on every single kill, every single player has, to a data store that really shouldn’t even be involved in this. Saving the data store has nothing to do with kills. Best to just keep them totally separated in everyway code wise. When a player moves a rank you update the leaderboard kills.Value variable and maybe someplace that shows it on the interface if you have that. The leaderboard sign should be on an update timer linked to the data store it uses, and will take care of itself by using the kills.Value you are setting. When the player is leaving the game would be when you update the actual data store.
Whilst I was doing the things you advised me to do, the damaging brick stopped working and it does not show any type of error.
local player = game:GetPlayerFromCharacter(script:FindFirstAncestorWhichIsA("Tool").Parent)
local debounce = false
local HealthLoss = 10-- Change this to the damage you need.
function OnTouched(Part)
if Part.Parent ~= nil then--Keep Parentless blocks from breaking it.
if debounce == false and Part.Parent:findFirstChild("Humanoid") ~= nil then
debounce = true
local humanoid = Part.Parent:FindFirstChild("Humanoid")
humanoid:TakeDamage(HealthLoss)
if humanoid.Health <= 0 then
print(humanoid.Parent, " was killed by", player)
end
task.wait(0.11)--Wait two seconds before the brick can hurt someone.
debounce = false
end
end
end
script.Parent.Touched:connect(OnTouched)
This script is a child of the handle and is not a local script.
If I’ve done anything wrong in this script, please tell me so.
vvvvvvvvvvvvvvvvvvvvvvvvvvv
local debounce = false
local HealthLoss = 10-- Change this to the damage you need.
local Player = script.Parent.Parent.Parent.Parent --tool will be in backpack and player is the parent of that backpack
--extra check
script.Parent.Parent:GetPropertyChangedSignal("Parent"):Connect(function() --parent of tool changes
local newParent = game.Players:FindFirstChild(script.Parent.Parent.Parent)
if newParent then --if he is a player
Player = newParent
end
end)
function OnTouched(Part)
if Part.Parent ~= nil then--Keep Parentless blocks from breaking it.
if debounce == false and Part.Parent:findFirstChild("Humanoid") ~= nil then
debounce = true
Part.Parent:findFirstChild("Humanoid"):TakeDamage(HealthLoss)
--adding a tag
local creatorTag = Instance.new("StringValue" , Part.Parent:findFirstChild("Humanoid"))
creatorTag.Name = "Creator"
creatorTag.Value = Player.Name
game:GetService("Debris"):AddItem(creatorTag , .3) --destroying without yeilding
wait(0.11)--Wait two seconds before the brick can hurt someone.
debounce = false
end
end
end
script.Parent.Touched:connect(OnTouched)
another script
for _ , v in pairs(workspace:GetChildren()) do
if v:IsA("Model") and v:FindFirstChildWhichIsA("Humanoid") then --is it a character?
v:FindFirstChildWhichIsA("Humanoid").Died:Connect(function() --player died
local Tag = v:FindFirstChildWhichIsA("Humanoid"):FindFirstChild("Creator") --tag we made earlier
game.Players[Tag.Value].leaderstats.Kills.Value += 1 --add a kill
end)
end
end
for _ , v in pairs(workspace:GetChildren()) do
if v:IsA("Model") and v:FindFirstChildWhichIsA("Humanoid") then --is it a character?
v:FindFirstChildWhichIsA("Humanoid").Died:Connect(function() --player died
local Tag = v:FindFirstChildWhichIsA("Humanoid"):FindFirstChild("Creator") --tag we made earlier
game.Players[Tag.Value].leaderstats.Kills.Value += 1 --add a kill
end)
end
end
local debounce = false
local HealthLoss = 10-- Change this to the damage you need.
local Player = script.Parent.Parent.Parent.Parent --tool will be in backpack and player is the parent of that backpack
--extra check
script.Parent.Parent:GetPropertyChangedSignal("Parent"):Connect(function() --parent of tool changes
local newParent = game.Players:FindFirstChild(script.Parent.Parent.Parent)
if newParent then --if he is a player
Player = newParent
end
end)
function OnTouched(Part)
if Part.Parent ~= nil then--Keep Parentless blocks from breaking it.
if debounce == false and Part.Parent:findFirstChild("Humanoid") ~= nil then
debounce = true
Part.Parent:findFirstChild("Humanoid"):TakeDamage(HealthLoss)
--adding a tag
local creatorTag = Instance.new("StringValue" , Part.Parent:findFirstChild("Humanoid"))
creatorTag.Name = "Creator"
creatorTag.Value = Player.Name
game:GetService("Debris"):AddItem(creatorTag , .3) --destroying without yeilding
wait(0.11)--Wait two seconds before the brick can hurt someone.
debounce = false
end
end
end
script.Parent.Touched:connect(OnTouched)
NOTE: This handle is in a tool.
Here’s where I’ve placed the other script:
for _ , v in pairs(workspace:GetChildren()) do
if v:IsA("Model") and v:FindFirstChildWhichIsA("Humanoid") then --is it a character?
v:FindFirstChildWhichIsA("Humanoid").Died:Connect(function() --player died
local Tag = v:FindFirstChildWhichIsA("Humanoid"):FindFirstChild("Creator") --tag we made earlier
game.Players[Tag.Value].leaderstats.Kills.Value += 1 --add a kill
end)
end
end
So far, the scripts has never printed any type of error nor I have spotted an error in the script.
while wait() do
for _ , v in pairs(game.Players:GetPlayers()) do
v.Character:FindFirstChildWhichIsA("Humanoid").Died:Connect(function() --player died
local Tag = v:FindFirstChildWhichIsA("Humanoid"):FindFirstChild("Creator") --tag we made earlier
game.Players[Tag.Value].leaderstats.Kills.Value += 1 --add a kill
end)
end
end