(Solved) Help With NPC Wave System

  1. What do you want to achieve?
    Wave System

  2. What is the issue?
    NPC sometimes doesn’t chase the player (usually when new round starts) and sometimes
    the NPC isn’t jumping even though there’s a block front of it and sometimes it jumps.

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    Tried to search on the internet and other social medias but no results. I also tried to
    change the position of codes, But still didn’t work

NPC Script (Placed inside ServerScriptService):

local CollectionService = game:GetService("CollectionService")
local animId = nil
local PathFindingService = game:GetService("PathfindingService")
local debounce = false

game:GetService("RunService").Heartbeat:Connect(function()

	task.wait()
	for _, mob in pairs(CollectionService:GetTagged('mob')) do

		task.spawn(function()

			if #CollectionService:GetTags(mob) < 1 then return end

			local humanoid = mob:WaitForChild("Humanoid")
			local Torso = mob:WaitForChild("HumanoidRootPart")

			local dmg = mob.Settings.Damage.Value
			local cooldown = mob.Settings.AttackCooldown.Value
			local range = mob.Settings.AttackRange.Value
			local coolingDown = mob.Settings.CoolingDown

			mob.BillboardGui.Frame.TextLabel.Text = humanoid.Health .. "/" .. humanoid.MaxHealth

			local closestChar

			for _, player in pairs(game.Players:GetPlayers()) do

				local char = player.Character

				if char and char:FindFirstChild("HumanoidRootPart") and char.Humanoid.Health > 0 then

					local distance = (char.HumanoidRootPart.Position - Torso.Position).Magnitude

					if not closestChar then closestChar = char end

					local clocestDistance = (closestChar.HumanoidRootPart.Position - Torso.Position).Magnitude

					if distance < clocestDistance then
						closestChar = char
					end
				end
			end

			local path = PathFindingService:FindPathAsync(Torso.Position, closestChar:WaitForChild("HumanoidRootPart").Position)
			local waypoints = path:GetWaypoints()

			if closestChar then
				humanoid:MoveTo(closestChar:WaitForChild("HumanoidRootPart").Position)

				if path.Status == Enum.PathStatus.Success then
					for i, waypoint in pairs(waypoints) do

						if waypoint.Action == Enum.PathWaypointAction.Jump then
							humanoid.Jump = true
						end
					end
				end

				if not coolingDown.Value then

					local ray = Ray.new(Torso.Position, Torso.Position * range)

					local part = workspace:FindPartOnRay(ray, workspace:WaitForChild("MobsFolder"))

					if part then

						local player = game.Players:GetPlayerFromCharacter(part.Parent) or game.Players:GetPlayerFromCharacter(part.Parent.Parent)

						if player then

							coolingDown.Value = true

							player.Character.Humanoid:TakeDamage(dmg)

							local damageInd = Instance.new("BillboardGui")
							damageInd.Name = "DamageIndicator"
							damageInd.Parent = player.Character:WaitForChild("HumanoidRootPart")
							damageInd.AlwaysOnTop = true
							damageInd.LightInfluence = 0
							damageInd.Size = UDim2.new(1, 0, 1, 0)
							damageInd.MaxDistance = 50
							damageInd.ZIndexBehavior = Enum.ZIndexBehavior.Global
							damageInd.StudsOffsetWorldSpace = Vector3.new(0, 1, 0)
							local damageText = Instance.new("TextLabel")
							damageText.Name = "DamageText"
							damageText.Parent = damageInd
							damageText.TextStrokeTransparency = 0
							damageText.Size = UDim2.new(3, 0, 3, 0)
							damageText.BackgroundTransparency = 1
							damageText.Font = Enum.Font.Highway
							damageText.TextColor3 = Color3.fromRGB(255, 85, 0)
							damageText.TextScaled = true
							damageText.Text = "-"..dmg
							local IndTextScript = script.IndTextScript:Clone()
							IndTextScript.Parent = damageText
							IndTextScript.Disabled = false

							task.wait(cooldown)
							coolingDown.Value = false
						end
					end
				end
			end
		end)
	end
end)

Wave System (For NPC To Spawns) (I Put Here just incase if needed):


local MPS = game:GetService("MarketplaceService")
local CS = game:GetService("CollectionService")
local TeleportService = game:GetService("TeleportService")

game.Players.PlayerAdded:Connect(function(player)
	local Ls = Instance.new("Folder")
	Ls.Parent = player
	Ls.Name = "leaderstats"

	local cash = Instance.new("IntValue")
	cash.Parent = Ls
	cash.Name = "Cash"
	cash.Value = 0

	local Wins = Instance.new("NumberValue")
	Wins.Parent = Ls
	Wins.Value = 0
	Wins.Name = "Wins"

end)

local MobSpawns = game.Workspace:WaitForChild("MobSpawns")
local status = game.ReplicatedStorage:WaitForChild("StatusValue")
local MobsFolder = game.Workspace:WaitForChild("MobsFolder")

--local weapon = script:WaitForChild("ClassicSword")
local mobs = {[1] = script:WaitForChild("Bacon")}

local respawnWave = 10
local startingMobs = 1
local maxWave = 15

local AlivePlrs = {}

for _, child in pairs(MobsFolder:GetChildren()) do
	CS:RemoveTag(child, "mob")
end

MobsFolder:ClearAllChildren()

for timer = 10, 0, -1 do
	task.wait(1)
	status.Value = "Waiting..." .. timer
end


for _, player in pairs(game.Players:GetPlayers()) do
	local character = player.Character
	--player:LoadCharacter()

	table.insert(AlivePlrs, player)

	player.Character.Humanoid.Died:Connect(function()
		table.remove(AlivePlrs, AlivePlrs[player])
	end)

	if MPS:UserOwnsGamePassAsync(player.UserId, nil) then
		player.Backpack:ClearAllChildren()
		local sword = game.ReplicatedStorage:WaitForChild("2xDmgSword"):Clone()
		sword.Parent = player.Backpack
	else
		print(false)
	end
end

for i = 1, maxWave do

	for _, player in pairs(AlivePlrs) do
		player.Character.Humanoid.Health = player.Character.Humanoid.MaxHealth
	end

	local mobsSpawn = (startingMobs/2) * (2 * i)
	status.Value = "Wave "..i 
	task.wait(3)

	local MobTypeSpawn

	for waveNum, mobType in pairs(mobs) do
		if i >= waveNum then
			MobTypeSpawn = mobType
		end
	end

	while mobsSpawn > 0 do
		for x, spawner in pairs(MobSpawns:GetChildren()) do

			mobsSpawn -= 1
			local MobToClone = MobTypeSpawn:Clone()

			MobToClone:SetPrimaryPartCFrame(spawner.CFrame) --= spawner.CFrame + Vector3.new(0,10,0)

			MobToClone.Humanoid.WalkSpeed = MobToClone.Settings.Speed.Value
			MobToClone.Humanoid.MaxHealth = MobToClone.Settings.Health.Value
			MobToClone.Humanoid.Health = MobToClone.Humanoid.MaxHealth

			CS:AddTag(MobToClone, "mob")

			MobToClone.Humanoid.Died:Connect(function()
				CS:RemoveTag(MobToClone, "mob")
				MobToClone:Destroy()
			end)

			MobToClone.Parent = game.Workspace:WaitForChild("MobsFolder")

		end
	end

	repeat 
		task.wait()

		status.Value = "Wave " ..i.. " | " .. #workspace:WaitForChild("MobsFolder"):GetChildren() .. " Bacons left"
	until #MobsFolder:GetChildren() < 1 or #AlivePlrs < 1

	if i == 14 then

		local BossBacon = script:WaitForChild("BossBacon"):Clone()

		status.Value = "Warning! Boss Is Approaching!"
		task.wait(2)
		status.Value = "Be Prepared"
		task.wait(2)

		BossBacon.Parent = game.Workspace:WaitForChild("MobsFolder")

		BossBacon:SetPrimaryPartCFrame(game.Workspace.SpawnerBoss.CFrame)-- = game.Workspace.SpawnerBoss.CFrame + Vector3.new(0,10,0)
		
		BossBacon.Humanoid.WalkSpeed = BossBacon.Settings.Speed.Value
		BossBacon.Humanoid.MaxHealth = BossBacon.Settings.Health.Value
		BossBacon.Humanoid.Health = BossBacon.Humanoid.MaxHealth

		CS:AddTag(BossBacon, "mob")

		BossBacon.Humanoid.Died:Connect(function()
			CS:RemoveTag(BossBacon, "mob")
			BossBacon:Destroy()
		end)
	end

	if i == maxWave and #MobsFolder:GetChildren() < 1 then
		print("Victory!")
		status.Value = "Victory!... (TELEPORTING PLAYERS)"

		for _, player in pairs(game.Players:GetPlayers()) do
			for _, aliveplr in pairs(AlivePlrs) do
				aliveplr.leaderstats.Wins.Value += 2

				local data = {}

				data["Wins"] = player.leaderstats.Wins.Value
				TeleportService:Teleport(nil, player, data)
			end
		end
	end

	if #AlivePlrs < 1 then
		print("oof")
		status.Value = "Game Ended, All players died (Teleporting)"

		for _, player in pairs(game.Players:GetPlayers()) do
			TeleportService:Teleport(nil, player)
		end

		break
	else
		for _, playerAlive in pairs(AlivePlrs) do
			playerAlive.leaderstats.Cash.Value += (20 * i)
		end

		if i % respawnWave == 0 then
			for _, plrs in pairs(game.Players:GetPlayers()) do

				if not plrs.Character then
					plrs:LoadCharacter()

					if MPS:UserOwnsGamePassAsync(plrs.UserId, nil) then
						plrs.Backpack:ClearAllChildren()
						local sword = game.ReplicatedStorage:WaitForChild("2xDmgSword"):Clone()
						sword.Parent = plrs.Backpack
					else
						print(false)
					end
				end
			end
		end
	end
end

The problem is here I think (NPC Script):

				humanoid:MoveTo(closestChar:WaitForChild("HumanoidRootPart").Position)

				if path.Status == Enum.PathStatus.Success then
					for i, waypoint in pairs(waypoints) do

						if waypoint.Action == Enum.PathWaypointAction.Jump then
							humanoid.Jump = true
						end
					end
				end

Thank you.

1 Like

Any errors in the output?
And also you said NPC is not jumping even though there’s a block front of it, I think that’s because you didn’t script what to do when it’s facing a block blocking it’s path, so it just stucks there and trying to move to the ending point but can’t, and errors.

No errors and my bad What i mean is

The Npc SOMETIMES jumps and sometimes don’t

Some developers get around NPCs not jumping by forcing random jumps periodically.

Fixed :+1: I accidentally put the jumping npc codes on wrong place

1 Like