Problem: NPC running to player’s humanoidrootpart then stops doing anything or delaying too much unlike in Roblox studio
local RunService = game:GetService("RunService")
local npc = script.Parent
local humanoid = npc:WaitForChild("Humanoid")
local hrp = npc:WaitForChild("HumanoidRootPart")
local stuck = false
local Chase = script.ChaseValue.Value
local inv = npc.Allpart:FindFirstChild("Head")
--Timing
local lastSoundTime = 0
local soundCooldown = math.random(9, 11)
--Animation
local walkAnim = humanoid.Animator:LoadAnimation(script.Walk)
local attackAnim = humanoid.Animator:LoadAnimation(script.Attack)
local runAnim = humanoid.Animator:LoadAnimation(script.Run)
local idleAnim = humanoid.Animator:LoadAnimation(script.Idle)
local breathing = npc.HumanoidRootPart:WaitForChild("Breathing")
local walk = npc.HumanoidRootPart:WaitForChild("walk")
--sound group
local sounds = {
npc.HumanoidRootPart:WaitForChild("happy1"),
npc.HumanoidRootPart:WaitForChild("Happy2"),
npc.HumanoidRootPart:WaitForChild("happy4"),
npc.HumanoidRootPart:WaitForChild("happy5"),
npc.HumanoidRootPart:WaitForChild("Pancake!"),
npc.HumanoidRootPart:WaitForChild("ScaryBreathing"),
npc.HumanoidRootPart:WaitForChild("Lion Roar Growl Exhale Low Rumble Breath 1 (SFX)")
}
-- Pathfinding parameters
local pathParams = {
AgentHeight = 8.8,
AgentRadius = hrp.Size.X > 0 and hrp.Size.X or hrp.Size.Y,
AgentCanJump = true,
}
-- Raycast parameters
local rayParams = RaycastParams.new()
rayParams.FilterType = Enum.RaycastFilterType.Exclude
rayParams.FilterDescendantsInstances = {npc}
local RANGE = script:WaitForChild("Range").Value
local Speed = script:WaitForChild("Runner").Value
local NorSpeed = script:WaitForChild("Walker").Value
local debounce = false
--see Target function
local function canSeeTarget(target)
local origin = hrp.Position
local direction = (target.HumanoidRootPart.Position - origin).Unit * RANGE
local ray = workspace:Raycast(origin, direction, rayParams)
return ray and ray.Instance:IsDescendantOf(target)
end
--get a random sound
local function getRandomSound()
local randomValue = math.random(1, 100)
if randomValue <= 80 then
return sounds[7] -- Predetermined sound
else
return sounds[math.random(1, #sounds)] -- Random sound from the list
end
end
-- play a random sound
local function playRandomSound()
local currentTime = tick()
if currentTime - lastSoundTime >= soundCooldown then
local soundToPlay = getRandomSound()
soundToPlay:Play()
lastSoundTime = currentTime
end
end
-- find the nearest target
local function findTarget()
local players = game.Players:GetPlayers()
local nearestTarget
local maxDistance = RANGE
if inv.Transparency == 0 then
for _, player in pairs(players) do
if player.Character and player.Character:FindFirstChild("HumanoidRootPart") then
local target = player.Character
local distance = (hrp.Position - target.HumanoidRootPart.Position).Magnitude
if distance < maxDistance and canSeeTarget(target) then
local attackableValue = player:FindFirstChild("Attackable")
if attackableValue and attackableValue.Value == true and target.Humanoid.Health > 0 then
nearestTarget = target
maxDistance = distance
humanoid.WalkSpeed = Speed
playRandomSound()
end
end
end
end
end
return nearestTarget
end
-- get path to a destination
local function getPath(destination)
local path = PathfindingService:CreatePath(pathParams)
path:ComputeAsync(hrp.Position, destination.Position)
return path
end
-- attack a target
local function attack(target)
local distance = (hrp.Position - target.HumanoidRootPart.Position).Magnitude
local player = game.Players:GetPlayerFromCharacter(target)
local attackableValue = player and player:FindFirstChild("Attackable")
if attackableValue and attackableValue.Value == true then
if distance <= 4 then
if not debounce then
debounce = true
attackAnim:Play()
target.Humanoid.Health = 0
attackAnim.Stopped:Wait()
debounce = false
Chase = false
wait(0.5)
Chase = true
end
else
humanoid:MoveTo(target.HumanoidRootPart.Position)
end
end
end
local function idle()
walkAnim:Stop()
local idleTime = math.random(5, 7)
humanoid.WalkSpeed = 0
breathing:Play()
walk:Stop()
walkAnim:Stop()
runAnim:Stop()
idleAnim:Play()
wait(idleTime)
walk:Play()
breathing:Stop()
idleAnim:Stop()
walkAnim:Play()
humanoid.WalkSpeed = NorSpeed
end
local function walkTo(destination)
local path = getPath(destination)
if path.Status == Enum.PathStatus.Success then
for _, waypoint in pairs(path:GetWaypoints()) do
if waypoint.Action == Enum.PathWaypointAction.Jump then
humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
local target = findTarget()
if target and target.Humanoid.Health > 0 then
local currentTargetPosition = target.HumanoidRootPart.Position
if canSeeTarget(target) then
humanoid:MoveTo(currentTargetPosition)
runAnim:Play()
walkAnim:Stop()
humanoid.MoveToFinished:Wait()
attack(target)
break
end
end
humanoid:MoveTo(waypoint.Position)
humanoid.MoveToFinished:Wait()
if math.random() < 0.05 then
idle()
end
end
end
end
local function patrol()
if Chase then
local waypoints = workspace.Waypoints:GetChildren()
local randomNum = math.random(1, #waypoints)
walkTo(waypoints[randomNum])
walkAnim:Play()
runAnim:Stop()
end
end
-- check vase interaction
local function checkVase()
local vaseFolder = workspace:FindFirstChild("VaseandTable")
local vase = vaseFolder and vaseFolder:FindFirstChild("VaseTable").Vase
if vase and vase.TouchValue.Value == true then
local vasePosition = vase.Position
if (hrp.Position - vasePosition).Magnitude <= 1000 then
local path = getPath(vase)
if path.Status == Enum.PathStatus.Success then
for _, waypoint in pairs(path:GetWaypoints()) do
if waypoint.Action == Enum.PathWaypointAction.Jump then
humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
humanoid:MoveTo(waypoint.Position)
humanoid.MoveToFinished:Wait()
local target = findTarget()
if target then
attack(target)
return
end
end
vase.TouchValue.Value = false -- Reset the BoolValue
idle()
end
end
end
end
--check Eye Trap interaction
local function EyeTrap()
local eyeFolder = workspace:FindFirstChild("EyeMonsterTrapFolder")
local eyeMonster = eyeFolder and eyeFolder:FindFirstChild("EyeMonster")
local eyeTrapValue = eyeMonster and eyeMonster.Hunting.EyeCheckValue
local eyeTrap = eyeMonster and eyeMonster.HumanoidRootPart
if eyeTrap and eyeTrapValue.Value == true then
local eyePosition = eyeTrap.Position
if (hrp.Position - eyePosition).Magnitude <= 1000 then
local path = getPath(eyeTrap)
if path.Status == Enum.PathStatus.Success then
for _, waypoint in pairs(path:GetWaypoints()) do
if waypoint.Action == Enum.PathWaypointAction.Jump then
humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
humanoid:MoveTo(waypoint.Position)
humanoid.MoveToFinished:Wait()
local target = findTarget()
if target then
attack(target)
return
end
end
eyeTrapValue.Value = false
end
end
end
end
-- Main loop
while RunService.Heartbeat:Wait(0.1) do
patrol()
checkVase()
EyeTrap()
end