Humanoid.Died doesn't fire for first death

To keep it simple I’ve merged the datastores and the death function of a player in the same server script, however this also brings me the issue that Humanoid.Died doesn’t fire when the player first dies, and I am unsure of why, is this a simple fix I cannot see?

local services = {
	players = game:GetService("Players"),
	dataStore = game:GetService("DataStoreService")
}

local datastores = {
	killEffect = services.dataStore:GetDataStore("killEffect"),
	killCountData = services.dataStore:GetDataStore("killCountData"),
	cashData = services.dataStore:GetDataStore("cashData"),
	spreeCountData = services.dataStore:GetDataStore("spreeCountData")
}

local function reward(player,amount)
	services.players[player]:FindFirstChild("library").cashCount = services.players[player]:FindFirstChild("library").cashCount + amount
end

services.players.PlayerAdded:Connect(function(player)
	local library = Instance.new("Folder")
	library.Name = "library"
	library.Parent = player
	
	local killId = Instance.new("IntValue",library)
	killId.Name = "killEffect"
	killId.Value = datastores.killEffect:GetAsync(player.UserId) or 0
	
	local killCount = Instance.new("IntValue",library)
	killCount.Name = "killCount"
	killCount.Value = datastores.killCountData:GetAsync(player.UserId) or 0
	
	local spreeCount = Instance.new("IntValue",library)
	spreeCount.Name = "spreeCount"
	spreeCount.Value = datastores.spreeCountData:GetAsync(player.UserId) or 0
	
	local cashCount = Instance.new("IntValue",library)
	cashCount.Name = "cashCount"
	cashCount.Value = datastores.cashData:GetAsync(player.UserId) or 0
	
	player.CharacterAdded:Connect(function(character)
		character:FindFirstChild("Humanoid").Died:Connect(function()
			if character.Humanoid:FindFirstChild("creator") then
				local deadPlayer = game:GetService("Players"):GetPlayerFromCharacter(character)
				deadPlayer.library:FindFirstChild("spreeCount").Value = 0
				local creator = character.Humanoid:FindFirstChild("creator").Value
				creator.library:FindFirstChild("killCount").Value = creator.library:FindFirstChild("killCount").Value + 1
				creator.library:FindFirstChild("spreeCount").Value = creator.library:FindFirstChild("spreeCount").Value + 1
			end
		end)
	end)
end)

services.players.PlayerRemoving:Connect(function(player)
	datastores.killEffect:SetAsync(player.UserId, player:FindFirstChild("library").killEffect.Value)
	datastores.spreeCountData:SetAsync(player.UserId, player:FindFirstChild("library").spreeCount.Value)
	datastores.killCountData:SetAsync(player.UserId, player:FindFirstChild("library").killCount.Value)
	datastores.cashData:SetAsync(player.UserId, player:FindFirstChild("library").cashCount.Value)
end)

Sometimes this happens because the CharacterAdded event has already been fired by the time the connection is reached, so it won’t fire again until the character is re-added to the game.

A way to combat this is to call the CharacterAdded function with the player’s existing character if they have one, as shown in the restructured code below.

...
local function characterAdded(character)
    character:WaitForChild("Humanoid").Died:Connect(function()
		if character.Humanoid:FindFirstChild("creator") then
			local deadPlayer = game:GetService("Players"):GetPlayerFromCharacter(character)
			deadPlayer.library:FindFirstChild("spreeCount").Value = 0
			
            local creator = character.Humanoid:FindFirstChild("creator").Value
			creator.library:FindFirstChild("killCount").Value = creator.library:FindFirstChild("killCount").Value + 1
			creator.library:FindFirstChild("spreeCount").Value = creator.library:FindFirstChild("spreeCount").Value + 1
		end
	end)
end

if player.Character then
    characterAdded(player.Character)
end
player.CharacterAdded:Connect(characterAdded)