Help with getting rewards for killing npc

My script is not working, but everything else is working fine? Please help.
So I made a script that when you kill someone, you get exp. However, this is not working. Please advise.
Script inside the NPC:

local humanoid = script.Parent.Humanoid
function dead()
	local tag = humanoid:FindFirstChild("creator")
	if tag ~= nil then
		if tag.Value ~= nil then
			local player = game.Players:WaitForChild(tag.Value)
			local exp = player:FindFirstChild("Exp")
			if exp ~= nil then
				exp.Value += 20
			end
		end
	end
end

humanoid.Died:Connect(dead)

Script inside the tool:

local player = game.Players.LocalPlayer
local damage = script.Parent:WaitForChild("Damage")

function TagHumanoid(humanoid, player)
	local Creator_Tag = Instance.new("ObjectValue")
	Creator_Tag.Name = "creator"
	Creator_Tag.Value = player.Name
	game:GetService("Debris"):AddItem(Creator_Tag, 2)
	Creator_Tag.Parent = humanoid
end

function UntagHumanoid(humanoid)
	for i, v in pairs(humanoid:GetChildren()) do
		if v:IsA("ObjectValue") and v.Name == "creator" then
			v:Destroy()
		end
	end
end

local function onTouch(hit)
	local humanoid = hit.Parent:FindFirstChild("Humanoid") or nil
	if humanoid ~= nil then
		local player = game.Players:GetPlayerFromCharacter(hit.Parent)
		TagHumanoid(humanoid,player)
		humanoid:TakeDamage(damage.Value)
		humanoid.Died:Connect(function()
			wait(5)
			UntagHumanoid(humanoid)
		end)
	end
end

local function activated()
	local anim = script.Parent:WaitForChild("Animation")
	local char = script.Parent.Parent
	local humanoid = char.Humanoid
	
	local animtrack = humanoid:LoadAnimation(anim)
	animtrack:Play()
end

script.Parent.Handle.Touched:Connect(onTouch)
script.Parent.Activated:Connect(activated)

Is the script inside the tool a localScript? If so, it’s creating the creator tag, but the humanoid’s script (which I assume is a server script) doesn’t see that tag because it only exists on the player’s client.

Also, a sidenote:
You don’t need to do if x ~= nil then, it’s equivalent to if x then, which is much shorter, so that’s what you should use.

you mean i should make the script inside the NPC a local?

No, you need to use a remoteEvent to send a signal to the server and have it tag the humanoid so that it replicates to all of the clients. Rather than tag the humanoid in the localScript. The script in the NPC should remain a server script.

It works, but the reward script(inside the npc)is not working still.

game.ReplicatedStorage.CreatorEvent.OnServerEvent:Connect(function(player)
	local char = player.Character
	local humanoid = char.Humanoid
	local Creator_Tag = Instance.new("ObjectValue",humanoid)
	Creator_Tag.Name = "creator"
	Creator_Tag.Value = player
	game:GetService("Debris"):AddItem(Creator_Tag, 2)
end)

It’s because you’re placing the tag inside of the player’s Character, you need to also pass the humanoid to the remoteEvent and place the tag inside of that humanoid.

I made a variable for the humanoid and placed it in the humanoid, as you can see:

local humanoid = char.Humanoid
local Creator_Tag = Instance.new("ObjectValue",humanoid)

I don’t know what you mean. That code there is setting the variable humanoid to the players’ Humanoid. You want the tag to go in the Humanoid of the NPC. So, you should be passing the humanoid value that you have in your TagHumanoid function to the remoteEvent.

The Humanoid variable in the tool script is referring to the NPC's humanoid, whilst the Player variable is referring to the player that is carrying the tool in it’s Character/Backpack.

Yes, I understand. You are not passing the NPC’s humanoid object value as you should be. You are instead placing the tag inside of the player’s character’s humanoid. I apologize if this is rude, but this is the last time I will explain this, and I will try to be thorough.

The only value you are passing to the remoteEvent is the player who called the event. You are then assigning char to player.Character, which refers to the player’s character, not the NPC.

You are then assigning humanoid to char.Humanoid, which is referring to the player’s character’s humanoid. Not the NPC’s humanoid.

Following that, you are creating the tag and parenting it to humanoid, which I previously explained is the player’s character’s humanoid. NOT THE NPC’s.

What you instead need to do, is when firing the remoteEvent, pass the NPC’s humanoid like so:
(This is your onTouch function, I am just editing it)

local function onTouch(hit)
	local humanoid = hit.Parent:FindFirstChild("Humanoid") or nil
	if humanoid ~= nil then
		local player = game.Players:GetPlayerFromCharacter(hit.Parent)
		tagHumanoid:FireServer(humanoid) --Change "tagHumanoid" to the variable that defines the correct remoteEvent
		humanoid:TakeDamage(damage.Value)
		humanoid.Died:Connect(function()
			wait(5)
			UntagHumanoid(humanoid)
		end)
	end
end

THEN, instead of defining the humanoid in the server script. You need to change your server function to look like this:
(Again, this is your script, I am just editing parts of it)

game.ReplicatedStorage.CreatorEvent.OnServerEvent:Connect(function(player, humanoid)
	local Creator_Tag = Instance.new("ObjectValue",humanoid)
	Creator_Tag.Name = "creator"
	Creator_Tag.Value = player
	game:GetService("Debris"):AddItem(Creator_Tag, 2)
end)

As I said before, this is the last time I will try to explain it. If you can’t figure it out, I’m sorry, you’ll have to get someone else’s help. What I have explained will work for your problem.

This worked, thank you so much!

1 Like