Why is my damage script not working?

What I’m Attempting

I’m attempting to make a simple damage script.

Issues

No matter what I try, such as making a script value or rewriting the script itself, it won’t work.

Solutions I’ve tried

  1. Making a value inside the script
  2. Rewriting everything
  3. Looking at the developer forums.

Code

--[[Made By MillerrIAm]]--
--[Server Variables]--
dmg = script.Parent.DamageValue.Value
--[Main Script]--
script.Parent.Touched:Connect(function(hit)
	local plr = script.Parent:FindFirstChild("Humanoid")
	if hit then
		plr.Health = plr.Health == -dmg
	end
end)

Output

01:53:26.428 - Workspace.Part.Script:8: attempt to index local ‘plr’ (a nil value)

Thank you for taking the time to read this and help!

1 Like

You are assuming a humanoid exists inside script.Parent. Did you mean hit.Parent?

-- No need to put your name at the top, you already know you wrote this,
-- also it's good practice to always use local variables!
local dmg = script.Parent.DamageValue.Value

script.Parent.Touched:Connect(function(part)
    local humanoid = part.Parent:FindFirstChild("Humanoid")
    if humanoid then
        humanoid:TakeDamage(dmg)
    end
end)
1 Like

FindFirstChildWhichIsA!

local function findHumanoid(instance)
    local current = instance
    
    while true do
        if current == nil or not current:IsDescendantOf(workspace) then return nil end
        
        local humanoid = current:FindFirstChildWhichIsA('Humanoid')
        
        if humanoid then return humanoid end
        
        current = current.Parent
    end
end
The rest of the code
local dmgPart = script.Parent
local dmgValue = dmgPart.DamageValue

dmgPart.Touched:Connect(function(part)
    local humanoid = findHumanoid(part)

    if humanoid ~= nil then
        humanoid:TakeDamage(dmgValue.Value)
    end
end)

This version allows you to change the damage value while the script is running, and those changes will take effect instantly. Make sure to add the findHumanoid function from above.

I love being able to edit values while scripts are already running. More scripts should do that.

3 Likes

that’s not where the error is coming from, and it also errors if plr ends up being nil :stuck_out_tongue:

1 Like

I’m not sure why you are doing it like this? This is gonna hang studio since there is no yielding in the while loop. What I had was fine.

1 Like

Look closer. That while loop returns if:

  • It travels up far enough to reach workspace, or ever have an instance that is not inside workspace
  • It finds a humanoid, in which case it returns the humanoid

It will not hang studio

1 Like

At that point you have reinvented the wheel, as :FindFirstAncestor exists.

1 Like

Okay so, I did what you recommended and it now does nothing, not even print. This is what I have so far…

--[[Made By MillerrIAm]]--
--[Server Variables]--
local dmg = script.Parent.DamageValue.Value
--[Main Script]--
script.Parent.Touched:Connect(function(part)
	local plr = script.Parent:FindFirstChild("Humanoid")
	if plr then
		plr:TakeDamage(dmg)
	end
end)

FYI, the reason I have my name on the script is so when people use it, they can come to me for help.

Wrong again, that only works if the part is literally inside the Humanoid which, as far as I know, is very rare. Also only works if the Humanoid’s name is Humanoid, or you know the name of it or the model containing the Humanoid.

Not wrong. I read the code thrice. Btw recursion would work better here. Either way, the implementation is too complicated, all he needs is to see if there is a humanoid in the part’s parent (which should be a character). A humanoid inside a part is completely useless. Renaming a humanoid breaks some features I think (at least if you rename a Humanoid from a character, it breaks some Roblox character scripts).

Better yet, Players:GetPlayerFromCharacter(model) would be more reliable. It would get a player from a character model. If model is not a character, it returns nil.

@MillerrIAm you did script.Parent instead of hit.Parent.

Doing things correctly comes with a price, I guess. If you think a while loop is too complicated then you’ve clearly never made a game before. I haven’t either though.

Not if the brick touches a hat.

If you want your brick to only damage players and only NPCs.

Ooh, edited:

A humanoid inside a part? Where’d you get that? If your part is inside a hat (Accoutrement I think) which is inside a Model containing a Humanoid, my function will find the humanoid no matter what its name is.

If your Accoutrement is literally parented to a Humanoid named “Humanoid” (or parented to something else that is) then maybe I guess FindFirstAncestor('Humanoid') would work? But only in that specific case? Which is ridiculous and why I pointed out that FindFirstAncestor is near useless for this case.


I don’t know if OP wants their brick to work on hats, or damage NPCs. They get to pick their solutions, of course.

Okay so, although I do prefer your scripts… most of them are heavily edited scripts that have a lot of stuff that I don’t understand yet. I am a beginner/intermediate Lua scripter. I don’t know enough to understand most of what you’re talking about or doing. I do thank you for posting though, I did test it and it does work. I will look more into this into the future.

Well, such is the experience of learning Lua. Trust me, I used a lot of stuff I didn’t understand back when I was learning too.

If you want to write your script from scratch, be my guest. I will not be offended if you decide to go the simple route that @incapaxx suggested, purely due to its simplicity.

It’s simpler - not exactly “wronger” as my posts may imply, it misses a few edge cases, but those edge cases don’t really matter and I only account for them because I’m a perfectionist.

1 Like