How would I make a NPC jump when using :MoveTo()

Weird. It works fine for me. I will send a video soon.

1 Like

Uploaded it to YouTube instead of directly uploading it here

It works without any issues. It could be your game that is lagging and not the script. Or another script interfering with the movement.

Oh, I donā€™t like how it is like delayed so the player has a chance to run :confused:

Also that is a funny YT username lol.

I guess I have to make it so the NPC canā€™t climb/jump

I donā€™t really want to give up because I feel like there can be a way to do this; i might even post a feature req for the thing that your using :MoveTo() on to jump when it needs to.

Found the fix. Here is the new script:

local pathservice = game:GetService("PathfindingService")
local runservice = game:GetService("RunService")
local players = game:GetService("Players")

local path = pathservice:CreatePath()

local function WaitEvent(ev,t)
	local obj = Instance.new("BoolValue")
	local returns
	local c;c = ev:Connect(function(...)
		c:Disconnect()
		c = nil
		returns = {...}
		obj.Value = true
	end)
	do
		coroutine.wrap(function()
			local ti = tick()
			local waitTime = t
			while (tick()-ti < waitTime) do
				if (returns) then return end
				waitTime = t + runservice.Heartbeat:Wait()
			end
			if (returns) then return end
			c:Disconnect()
			obj.Value = true
		end)()
	end
	obj:GetPropertyChangedSignal("Value"):Wait()
	obj:Destroy()
	return (returns) and unpack(returns) or nil
end

local dir = Vector3.new(0,-4,0)

local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Blacklist
-- Make sure to change the ignore list right here if required
params.FilterDescendantsInstances = {workspace:FindFirstChild("Zombies") or script.Parent}

local function CheckSight(root,target)
	local dif = target.Position-root.Position
	local mag = dif.Magnitude
	
	local p = workspace:Raycast(root.Position,dif.Unit*mag,params)
	
	if ((p) and (p.Instance:IsDescendantOf(target.Parent)) and (math.abs(target.Position.Y-root.Position.Y) < 3)) then
		if (mag <= 20) then
			local mid = root.Position:Lerp(target.Position,0.5)
			local p = workspace:Raycast(mid,dir,params)
			if (not p) then
				return false
			end
		else
			for i = 0.125,0.875,0.125 do
				local mid = root.Position:Lerp(target.Position,i)
				local p = workspace:Raycast(mid,dir,params)
				if (not p) then
					return false
				end
			end
		end
		--print("ey")
		return true
	end
	
	return false
end

for _,v in pairs(script.Parent:GetDescendants()) do
	if (v:IsA("BasePart")) then
		v:SetNetworkOwner()
	end
end

local jumpstates = {
	Enum.HumanoidStateType.Running;
	Enum.HumanoidStateType.RunningNoPhysics;
}

local function Jump(humanoid)
	local state = humanoid:GetState()
	if (not table.find(jumpstates,state)) then
		local c;c = humanoid.StateChanged:Connect(function(state)
			if (not table.find(jumpstates,state)) then return end
			c:Disconnect()
			c = nil
			humanoid.Jump = true
		end)
	else
		humanoid.Jump = true
	end
	return true
end

local function FindNearestPlayer()
	local plrs = players:GetPlayers()
	local nearPlr,near
	for i = 1,#plrs do
		local v = plrs[i]
		if ((v.Name ~= script.Parent.Name) and (v.Character) and (v.Character.Humanoid.Health > 0)) then
			local mag = (script.Parent.HumanoidRootPart.Position-v.Character.HumanoidRootPart.Position).Magnitude
			if (not near) then
				near = mag
				nearPlr = v.Character.HumanoidRootPart
			elseif (near > mag) then
				near = mag
				nearPlr = v.Character.HumanoidRootPart
			end
		end
	end
	return nearPlr
end

-- // Zombie Damage \\ --

local coolDown = {}

script.Parent.HumanoidRootPart.Touched:Connect(function(hit)
	if (hit.Parent.Name == script.Parent.Name) then return end
	local hum = hit.Parent:FindFirstChild("Humanoid")
	if ((not hum) or (coolDown[hum])) then return end
	coolDown[hum] = true
	hum:TakeDamage(10)
	wait(1)
	coolDown[hum] = nil
end)

---------------------------

while true do
	local root = FindNearestPlayer()
	if (root) then
		local isVisible = CheckSight(script.Parent.HumanoidRootPart,root)
		
		if (isVisible) then
			script.Parent.Humanoid:MoveTo(root.Position)
			wait()
		else
			path:ComputeAsync(script.Parent.HumanoidRootPart.Position,root.Position)
			if (path.Status == Enum.PathStatus.Success) then
				local wp = path:GetWaypoints()
				for i = 3,#wp do
					local v = wp[i]
					if (v.Action == Enum.PathWaypointAction.Jump) then
						Jump(script.Parent.Humanoid)
					end
					script.Parent.Humanoid:MoveTo(v.Position)
					local reached = WaitEvent(script.Parent.Humanoid.MoveToFinished,1)
					if (not reached) then
						--print("stuck!")
						Jump(script.Parent.Humanoid)
						break
					end
					if (CheckSight(script.Parent.HumanoidRootPart,root)) then
						script.Parent.Humanoid:MoveTo(root.Position)
						break
					end
					if ((root.Position-wp[#wp].Position).Magnitude >= 40) then
						if ((root.Position-script.Parent.HumanoidRootPart.Position).Magnitude <= 20) then
							script.Parent.Humanoid:MoveTo(root.Position)
						elseif (wp[i+1]) then
							script.Parent.Humanoid:MoveTo(wp[i+1].Position)
						end
						--print("target moved")
						break
					end
				end
				wait()
			else
				--print("couldnt find path")
				script.Parent.Humanoid:MoveTo(root.Position)
				wait(0.1)
			end
		end
	else
		wait()
	end
end
7 Likes

Ok, let me try it now.

BOOOOOM! Thanks so much! You are the best!

Just for future reference of anyone finding this post, using

humanoid.Jump = true

to make NPCs jump has been more reliable than using Humanoid:ChangeState() in my own testing.

1 Like

how would i define how far the ā€˜zombieā€™ can detect/see you from

nevermind, i managed to script it myself, thanks.