[SOLVED] NPC Monster Attack Script

Ok so I’m trying to edit a script I’m using following a guide, but here are 2 problems.

  1. Even though I make the script not insta kill the player, it does it anyways and it only sometimes damages the player the correct amount (It’s this exact script because I tested if it was something else and it wasn’t)
  2. The attack animation does not play when the player is being attacked
    How do I fix this?
local teddy = script.Parent
local humanoid = teddy.Humanoid
local animation = script:WaitForChild('Attack')
local dance = humanoid:LoadAnimation(animation)

local function getHumPos()
    return (teddy.HumanoidRootPart.Position)
end

local function attack(target, teddyPart)
    local distance = (teddyPart.Position - getHumPos()).Magnitude
    if distance < 4 and game.Players:GetPlayerFromCharacter(target) then
        target.Humanoid.Health -= 40
        local plr = game.Players:GetPlayerFromCharacter(target)
        dance:Play()
        wait(2)
    end
end

script.Parent.Reached.Event:Connect(function(target)
    if target.Character then
        if target.Character.Humanoid.Health > 0 then
            target.Character.Humanoid.Health -= 40
            dance:Play()
            wait(2)
        end
    end
end)
local function detection(part, teddyPart)
    if part.Parent:FindFirstChild("Humanoid") then
        local character = part.Parent
        if game.Players:GetPlayerFromCharacter(character) then
            --Check the player is still alive (And it's not our own character)
            if character.Humanoid.Health > 0 and character ~= teddy then
                attack(character, teddyPart)
            end
        end
    end
end

for i,v in pairs(script.Parent:GetDescendants()) do
    if v:IsA("BasePart") or v:IsA("MeshPart") or v:IsA("UnionOperation") then
        if not string.find(v.Name, "cloth") then
            v.Touched:Connect(function(hit)
                detection(hit, v)
            end)
        end
    end
end

image

I suspect this is due to the function attack running multiple instances. You could have a variable named ‘attacked’ that can be switched to true or false, depending on whether the player is being attacked. The player can only be attacked after the 2 seconds. This would also prevent the animation from playing too many times.

Have you tested the animation works anywhere else?? Are you sure it is just during the attack?? If it is a global problem, there are some reasons why:

  1. this game is a group game and the animation was not uploaded to the group
  2. Ensure the right animation priority is set
  3. If it not a group game, ensure the animation was made by yourself
  4. Ensure the animation has been approved by roblox.

This is the example script using the attacked variable and would fix random health decreases:

E.G,

local attacked = false

local function attack(target, teddyPart)
    local distance = (teddyPart.Position - getHumPos()).Magnitude
    if distance < 4 and game.Players:GetPlayerFromCharacter(target) and attacked == false then
        attacked = true
        target.Humanoid.Health -= 40
        local plr = game.Players:GetPlayerFromCharacter(target)
        dance:Play()
        wait(2)
        attacked = false
    end
end

Yes, the animation works on different player models and it is made by me. The animation wasn’t uploaded to a group (I don’t even know how lol) and I changed the animation priority to Action. Yes, the animation was approved.

I tested the script example you gave me, and it works. After some testing, the monster still spams attack sometimes but now the player has a bigger chance of being able to escape.
Here is the script you sent me. I edited it a little bit as I found a variable that wasn’t being used.

local teddy = script.Parent
local humanoid = teddy:WaitForChild("Humanoid")
local animation = script:WaitForChild('Attack')
local dance = humanoid:LoadAnimation(animation)
dance:Play()

local function getHumPos()
	return (teddy.HumanoidRootPart.Position)
end

local attacked = false

local function attack(target, teddyPart)
	local distance = (teddyPart.Position - getHumPos()).Magnitude
	if distance < 4 and game.Players:GetPlayerFromCharacter(target) and attacked == false then
		attacked = true
		dance:Play()
		target.Humanoid.Health -= 40
		wait(2)
		attacked = false
	end
end

Note: Sorry for the late reply, I had to go to bed and I have to go to school in 2 hours.

Is the animation based off R16 or blocky avatar??

The model and animation are both R6. (“blocky avatar”)

Have you tested in a copy of the MountainMan model if the animation works?? Just a script that plays the animation or using it in the animation tester

Yes I tested it earlier and it works on different R6 models.

                                               ⚠️ Warning ⚠️

I’m only trying to help

This code was made by AI

I see a few issues with the script you provided:

  1. In the attack function, you are decreasing the target’s health by 40, but in the Reached event, you are also decreasing it by 40. This means that if the target is in range of the teddy, their health will be decreased by 80.
  2. You are using the wait function in the attack function and in the Reached event. This will pause the script for 2 seconds, which might cause problems if the script is being called frequently.
  3. The attack function has a distance check, but it is not being used in the Reached event. This means that the player’s health will be decreased even if they are not close to the teddy.

To fix these issues, you can try the following:

  1. Remove the target.Character.Humanoid.Health -= 40 line from the Reached event, since it is already being decreased in the attack function.
  2. Remove the wait(2) lines from both the attack function and the Reached event.
  3. Use the distance check in the Reached event to only attack the player if they are close enough to the teddy. You can do this by adding an if statement before the attack function is called, like this:
local function attack(target, teddyPart)
    local distance = (teddyPart.Position - getHumPos()).Magnitude
    if distance < 4 and game.Players:GetPlayerFromCharacter(target) then
        target.Humanoid.Health -= 40
        local plr = game.Players:GetPlayerFromCharacter(target)
        dance:Play()
    end
end

script.Parent.Reached.Event:Connect(function(target)
    if target.Character then
        if target.Character.Humanoid.Health > 0 then
            local distance = (target.Character.HumanoidRootPart.Position - getHumPos()).Magnitude
            if distance < 4 then
                attack(target.Character, script.Parent.HumanoidRootPart)
            end
        end
    end
end)

Thanks for the help, but this did not work. The player immediately died when going near the monster.

                                               ⚠️ Warning ⚠️

I’m only trying to help

This code was made by AI

There could be a couple of issues that might be causing this problem. Here are a few things you can try to troubleshoot:

  1. Make sure that you are using the correct target in the attack function. The target you pass to the attack function should be the player’s character, not the player object itself. You can get the player’s character using the target.Character property.
  2. Make sure that the distance check in the attack function is using the correct parts for the distance calculation. The distance should be calculated between the teddy’s root part and the player’s humanoid root part. You can use the .Position property of these parts to get their positions and then use the .Magnitude property of the resulting vector to get the distance.
  3. Make sure that the attack function is only being called when the player is within range of the teddy. You can do this by adding an if statement before calling the attack function in the Reached event, like this:
if distance < 4 then
    attack(target.Character, script.Parent.HumanoidRootPart)
end
  1. Make sure that the attack function is correctly decreasing the player’s health. You can do this by adding some print statements to the function to see what is happening:
local function attack(target, teddyPart)
    local distance = (teddyPart.Position - getHumPos()).Magnitude
    if distance < 4 and game.Players:GetPlayerFromCharacter(target) then
        print("Attacking player with health", target.Humanoid.Health)
        target.Humanoid.Health -= 40
        print("Player has health", target.Humanoid.Health)
        local plr = game.Players:GetPlayerFromCharacter(target)
        dance:Play()
    end
end

I hope these suggestions help! Let me know if you have any other questions.

I appreciate the help but I would like someone to help me instead of an AI. …People tend to know what I’m talking about instead of bots :sweat_smile:

1 Like

Hello, I am doing a follow up on this comment. Yes, I tested it earlier and it works on different R6 models.

Hi, are you sure its the model you put this script in though??

yes that’s why i sent the photo of the model. the script’s name is Kill.

No, I meant, have you tested if the animation works on the model that the animation doesn’t work on?? Like, copied the model, tested iif the same animation worked, but no other scripts, and see if that made a difference?

If you are still confused, feel free to send the model over so I can test it

Yes, I tested an animation loop and it looks like it works fine in the clone

Hmm… Is it possible you could send the model over??

Ok I will send you the model. Sorry I just got home from school 2 hours ago

Here is the file.
MountainMan.rbxm (25.8 KB)