2 issues (Soultion Found :DDDDDD)

As long as you are using a server script, the code runs on the server.

They are both normal scripts. So would that mean they are server scripts?

Yes, that means they are server scripts.

My point is that when adding “Souls” to yourself, you need to do it through the server.

Yes I get that. So what in my script needs changing in order to accomplish that.

You shouldn’t need to change anything in your code to get it to run on the server, i’m trying to explain that when you give yourself “Souls” to test the selling and saving, that needs to be done on the server, but incase im misunderstanding the problem you’re having, i’ll give you the placefile with the changes i made to fix the problems you had.

DataTest.rbxl (32.9 KB)

1 Like

The scripts are exactly the same, though yours works, and mine doesn’t. I’m sorry if i’m not understanding correctly is just what am i doing wrong?

1 Like

The reason why it isn’t saving is the because the server is shutting before it can. To stop this you add BindToClose
This causes the server to complete the function specified before it closes.

Here is my script

local DataStoreService = game:GetService("DataStoreService")
local playerData = DataStoreService:GetDataStore("playerData")
local function onPlayerJoin(player)

local QuestsFolder = Instance.new("Folder")
QuestsFolder.Name = "QuestsFolder"
QuestsFolder.Parent = player

local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player

local gold = Instance.new("IntValue")
gold.Name = "Gold"
gold.Parent = leaderstats

local level = Instance.new("IntValue")
level.Name = "Level"
level.Parent = leaderstats

local kills = Instance.new("IntValue")
kills.Name = "Kills"
kills.Parent = leaderstats

local xp = Instance.new("IntValue")
xp.Name = "XP"
xp.Parent = leaderstats

local maxXP = Instance.new("IntValue")
maxXP.Name = "MaxXP"
maxXP.Parent = player

local playerUserId = player.UserId
local data = playerData:GetAsync("Player_"..playerUserId)  

if data then
	gold.Value = data['Gold']
	level.Value = data['Level']
	kills.Value = data['Kills'] 
	xp.Value = data['XP']
else
	gold.Value = 50
	level.Value = 1
	kills.Value = 0
	xp.Value = 0
    end
end

local function onPlayerExit(player)
 local player_stats = {}
	if player then
	for i, stat in pairs(player:WaitForChild("leaderstats"):GetChildren()) do
		player_stats[stat.Name] = stat.Value
	end

	playerData:SetAsync("Player_"..player.UserId, player_stats)
    end
end

game.Players.PlayerAdded:Connect(onPlayerJoin)
game.Players.PlayerRemoving:Connect(onPlayerExit)
game:BindToClose(function()
    for i, player in pairs(game:GetService("Players"):GetPlayers()) do
    	onPlayerExit()
    end
end)

The script will still work if you test it in a regular server but this also helps with server crashes and testing in studio. I would reccommend it.

1 Like

I put the bind to close script into it. Though it still doesn’t work!
Did i implement it into the script correctly?

local DataStoreService = game:GetService("DataStoreService")

local playerData = DataStoreService:GetDataStore("PlayerData")


local function onPlayerJoin(player)  -- Runs when players join

	local leaderstats = Instance.new("Folder")  --Sets up leaderstats folder

	leaderstats.Name = "leaderstats"

	leaderstats.Parent = player



	local souls = Instance.new("IntValue") --Sets up value for leaderstats

	souls.Name = "Souls"

	souls.Parent = leaderstats



	local coins = Instance.new("IntValue") --Sets up value for leaderstats

	coins.Name = "Coins"

	coins.Parent = leaderstats



	local playerUserId = "Player_" .. player.UserId  --Gets player ID

	local data = playerData:GetAsync(playerUserId)  --Checks if player has stored data

	if data then

		souls.Value = data['Souls']

		coins.Value = data['Coins']

	else

		-- Data store is working, but no current data for this player

		souls.Value = 0

		coins.Value = 0

	end

end


local function create_table(player)

	local player_stats = {}

	for _, stat in pairs(player.leaderstats:GetChildren()) do

		player_stats[stat.Name] = stat.Value

	end

	return player_stats

end


local function onPlayerExit(player)  --Runs when players exit



	local player_stats = create_table(player)

	local success, err = pcall(function()

		local playerUserId = "Player_" .. player.UserId

		playerData:SetAsync(playerUserId, player_stats) --Saves player data

	end)


	if not success then

		warn('Could not save data!')

	end

end


game.Players.PlayerAdded:Connect(onPlayerJoin)

game.Players.PlayerRemoving:Connect(onPlayerExit)

game.Players.PlayerAdded:Connect(onPlayerJoin)
game.Players.PlayerRemoving:Connect(onPlayerExit)
game:BindToClose(function()
	for i, player in pairs(game:GetService("Players"):GetPlayers()) do
		onPlayerExit()
	end
end)

why do you have multiple of the same things?

I would recommend doing my script ignore the call to create table.

So use your script but replace your variables with mine?

If you want to but it works for me.

alright…


local DataStoreService = game:GetService("DataStoreService")
local playerData = DataStoreService:GetDataStore("playerData")

local function onPlayerJoin(player)

local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player

local souls = Instance.new("IntValue")
souls.Name = "Souls"
souls.Parent = leaderstats

local coins = Instance.new("IntValue")
coins.Name = "Coins"
coins.Parent = leaderstats

local playerUserId = player.UserId
local data = playerData:GetAsync("Player_"..playerUserId)  

if data then
	souls.Value = data['Souls']
	coins.Value = data['Coins']
else
	souls.Value = 50
	coins.Value = 1
end
end

local function onPlayerExit(player)
local player_stats = {}
if player then
	for i, stat in pairs(player:WaitForChild("leaderstats"):GetChildren()) do
		player_stats[stat.Name] = stat.Value
	end

	playerData:SetAsync("Player_"..player.UserId, player_stats)
end
end

game.Players.PlayerAdded:Connect(onPlayerJoin)
game.Players.PlayerRemoving:Connect(onPlayerExit)
game:BindToClose(function()
for i, player in pairs(game:GetService("Players"):GetPlayers()) do
	onPlayerExit()
end
end)

figured I would do it just cause I had it formatted. Sorry if I wasted your time a bit.

Thanks for the script. Though it doesn’t work. It may be because a different script of mine isn’t working.

basically in the game you kill mobs and the starter weapon is a stick. And when i kill something i get an error message on line 38.
Players.trueblockhead101.Backpack.Stick.Slash:38: attempt to index nil with ‘FindFirstChild’
Part that is giving an error message:

local humanOther = partOther.Parent:FindFirstChild("Humanoid")

Full Script:


local tool = script.Parent
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")

local InputService = game:GetService("UserInputService")
local InputType = Enum.UserInputType

local animation = nil
local slashAnimation = nil

tool.Equipped:Connect(function()
	animation = Instance.new("Animation")
	animation.AnimationId = "rbxassetid://7132227504"
	slashAnimation = humanoid:LoadAnimation(animation)
end)

tool.Unequipped:Connect(function()
	animation:Destroy()
	slashAnimation = nil
end)

local debounce = false
InputService.InputBegan:Connect(function(input, processed)
	if input.UserInputType == InputType.MouseButton1 and slashAnimation and not processed then
		if debounce == false then
			debounce = true

			slashAnimation:Play()
			local Connection
			local tool = script.Parent

			local function onTouch(partOther)

				local humanOther = partOther.Parent:FindFirstChild("Humanoid")

				if not humanOther then return end

				if humanOther.Parent == tool then return end

				humanOther:TakeDamage(5)
				if humanOther.Health <= 0 then
					player.leaderstats.Souls.Value =  player.leaderstats.Souls.Value + 1 
					humanOther.Parent:Destroy()
				end
			end

			Connection = tool:WaitForChild("Handle").Touched:Connect(onTouch)

			slashAnimation.Stopped:Wait() 
			debounce = false
			Connection:Disconnect()
			wait(.2)
			debounce = false

		end

	end
end)

you are not passing along a value.

Give me a second to look at my sword script

1 Like

no problem


Alright, first off you have a debounce which is really good.

But the issue lies in the Connection = tool:WaitForChild(“Handle”).Touched:Connect(onTouch)

In my script I have it coded differently but I see how this would work.