Hey there,
This NPC script works just fine on paper; it finds players and chases them as it’s supposed to. However, when I added the ‘idle()’ function and repeat loop it, for some reason, refuses to find players again. To combat this, I’ve added a boolean called ‘EnemyInSight’ - take a look for yourself, if you’d like! Any help is greatly appreciated.
I’ve already tried adding a while loop (specifically, something among the lines of “while EnemyInSight == true do”, but that also didn’t work, I’ve also searched the internet for this, but to no avail.
Again, any help is greatly appreciated! Thanks in advance.
math.randomseed(tick())
local myHuman = script.Parent:WaitForChild("Humanoid")
local myRoot = script.Parent:WaitForChild("HumanoidRootPart")
local head = script.Parent:WaitForChild("Head")
local lowerTorso = script.Parent:WaitForChild("LowerTorso")
local walkAnim = script.Parent.Walk
local walkAnimPlay = myHuman:LoadAnimation(walkAnim)
local idleAnim = script.Parent.Idle
local idleAnimPlay = myHuman:LoadAnimation(idleAnim)
local holdWeapon = script.Parent.HoldWeapon
local holdWeaponPlay = myHuman:LoadAnimation(holdWeapon)
holdWeaponPlay:Play()
local clone = script.Parent:Clone()
------- the idle animation playing
function idle()
repeat
idleAnimPlay:Play()
wait(idleAnimPlay.Length)
until script.Parent.EnemyInSight.Value == true
end
function findPath(target)
local path = game:GetService("PathfindingService"):CreatePath()
path:ComputeAsync(myRoot.Position,target.Position)
local waypoints = path:GetWaypoints()
if path.Status == Enum.PathStatus.Success then
for _, waypoint in ipairs(waypoints) do
if waypoint.Action == Enum.PathWaypointAction.Jump then
myHuman.Jump = true
end
myHuman:MoveTo(waypoint.Position)
local timeOut = myHuman.MoveToFinished:Wait(1)
if not timeOut then
myHuman.Jump = true
-- print("Path too long!")
script.Parent.EnemyInSight.Value = false
findPath(target)
break
end
if checkSight(target) then
repeat
--- print("Moving directly to the target")
script.Parent.EnemyInSight.Value = true
myHuman:MoveTo(target.Position)
wait(0.1)
if target == nil then
break
elseif target.Parent == nil then
break
end
until checkSight(target) == false or myHuman.Health < 1 or target.Parent.Humanoid.Health < 1
break
end
if (myRoot.Position - waypoints[1].Position).magnitude > 20 then
-- print("Target has moved, generating new path")
script.Parent.EnemyInSight.Value = true
findPath(target)
break
end
end
end
end
function checkSight(target)
local ray = Ray.new(myRoot.Position, (target.Position - myRoot.Position).Unit * 40)
local hit,position = workspace:FindPartOnRayWithIgnoreList(ray, {script.Parent})
if hit then
if hit:IsDescendantOf(target.Parent) and math.abs(hit.Position.Y - myRoot.Position.Y) < 3 then
--print("I can see the target")
script.Parent.EnemyInSight.Value = true
return true
end
end
return false
end
function findTarget()
local dist = script.Parent.Distance.Value
local target = nil
local potentialTargets = {}
local seeTargets = {}
for i,v in ipairs(workspace:GetChildren()) do
local human = v:FindFirstChild("Humanoid")
local torso = v:FindFirstChild("Torso") or v:FindFirstChild("HumanoidRootPart")
if human and torso and v.Name ~= script.Parent.Name then
if (myRoot.Position - torso.Position).magnitude < dist and human.Health > 0 and human.NPC.Value == false then
table.insert(potentialTargets,torso)
end
end
end
if #potentialTargets > 0 then
for i,v in ipairs(potentialTargets) do
if checkSight(v) then
table.insert(seeTargets, v)
elseif #seeTargets == 0 and (myRoot.Position - v.Position).magnitude < dist then
script.Parent.EnemyInSight.Value = false
idle()
end
end
end
if #seeTargets > 0 then
dist = 30
for i,v in ipairs(seeTargets) do
if (myRoot.Position - v.Position).magnitude < dist then
target = v
dist = (myRoot.Position - v.Position).magnitude
end
end
end
if target then
if math.random(20) == 1 then
head.Quote1:Play()
-- play sound
end
end
return target
end
lowerTorso.Touched:Connect(function(obj)
if not obj.Parent:FindFirstChild("Humanoid") then
myHuman.Jump = true
end
end)
function main()
local target = findTarget()
if target then
myHuman.WalkSpeed = script.Parent.ChaseSpeed.Value
idleAnimPlay:Stop()
walkAnimPlay:Play()
findPath(target)
else
myHuman.WalkSpeed = script.Parent.WanderSpeed.Value
script.Parent.EnemyInSight.Value = false
idle()
end
end
while wait(0.1) do
if myHuman.Health < 1 then
break
end
main()
end
