You should create a loop so it would chase the closest player and if there is someone new that is close to the bot, you can stop the pathfinding and create a new path
(a loop that constantly looks for the closest player)
You should create a loop so it would chase the closest player and if there is someone new that is close to the bot, you can stop the pathfinding and create a new path
(a loop that constantly looks for the closest player)
here, this worked for me.
local SearchDistance = math.huge
local ZombieDamage = math.huge
local canWander = false
local WanderX, WanderZ = 30, 30
function getHumanoid(model)
for _, v in pairs(model:GetChildren()) do
if v:IsA'Humanoid' then
return v
end
end
end
local zombie = script.Parent
local human = getHumanoid(zombie)
local hroot = zombie.HumanoidRootPart
local zspeed = hroot.Velocity.magnitude
local pfs = game:GetService("PathfindingService")
function GetPlayerNames()
local players = game:GetService('Players'):GetChildren()
local name = nil
for _, v in pairs(players) do
if v:IsA'Player' then
name = tostring(v.Name)
end
end
return name
end
function GetPlayersBodyParts(t)
--local torso = t
--if torso then
-- local figure = torso.Parent
-- for _, v in pairs(figure:GetChildren()) do
-- if v:IsA'Part' then
-- return v.Name
-- end
-- end
--else
-- return "HumanoidRootPart"
--end
end
function GetTorso(part)
local chars = game.Workspace:GetChildren()
local torsos = {}
local torso = nil
for _, v in pairs(chars) do
if v:IsA'Model' and v ~= script.Parent and v.Name == GetPlayerNames() then
local charRoot = v.PrimaryPart
if (charRoot.Position - part).magnitude < SearchDistance then
table.insert(torsos, charRoot)
end
end
end
table.sort(torsos, function (a, b) return a.Position > b.Position end)
torso = torsos[1]
return torso
end
for _, zambieparts in pairs(zombie:GetChildren()) do
if zambieparts:IsA'Part' then
zambieparts.Touched:connect(function(p)
if p.Parent.Name == GetPlayerNames() and p.Parent.Name ~= zombie.Name then -- damage
local enemy = p.Parent
local enemyhuman = getHumanoid(enemy)
enemyhuman:TakeDamage(ZombieDamage)
end
end)
end
end
local path
local waypoint
local oldpoints
local isWandering = 0
if canWander then
spawn(function()
while isWandering == 0 do
isWandering = 1
local desgx, desgz = hroot.Position.x + math.random(-WanderX, WanderX), hroot.Position.z + math.random(-WanderZ, WanderZ)
human:MoveTo( Vector3.new(desgx, 0, desgz) )
wait(math.random(4, 6))
isWandering = 0
end
end)
end
while wait() do
local enemytorso = GetTorso(hroot.Position)
if enemytorso ~= nil then
isWandering = 1
local function checkw(t)
local ci = 3
if ci > #t then
ci = 3
end
if t[ci] == nil and ci < #t then
repeat
ci = ci + 1
wait()
until t[ci] ~= nil
return Vector3.new(1, 0, 0) + t[ci]
else
ci = 3
return t[ci]
end
end
path = pfs:FindPathAsync(hroot.Position, enemytorso.Position)
waypoint = path:GetWaypoints()
oldpoints = waypoint
local connection;
local direct = Vector3.FromNormalId(Enum.NormalId.Front)
local ncf = hroot.CFrame * CFrame.new(direct)
direct = ncf.p.unit
local rootr = Ray.new(hroot.Position, direct)
local phit, ppos = game.Workspace:FindPartOnRay(rootr, hroot)
if path and waypoint or checkw(waypoint) then
if checkw(waypoint) ~= nil and checkw(waypoint).Action == Enum.PathWaypointAction.Walk then
human:MoveTo( checkw(waypoint).Position )
human.Jump = false
end
if checkw(waypoint) ~= nil and checkw(waypoint).Action == Enum.PathWaypointAction.Jump then
human.Jump = true
connection = human.Changed:connect(function()
human.Jump = true
end)
human:MoveTo(checkw(waypoint).Position)
else
human.Jump = false
end
hroot.Touched:connect(function(p)
local bodypartnames = GetPlayersBodyParts(enemytorso)
if p:IsA'Part' and not p.Name == bodypartnames and phit and phit.Name ~= bodypartnames and phit:IsA'Part' and rootr:Distance(phit.Position) < 5 then
connection = human.Changed:connect(function()
human.Jump = true
end)
else
human.Jump = false
end
end)
if connection then
connection:Disconnect()
end
else
for i = 3, #oldpoints do
human:MoveTo( oldpoints[i].Position )
end
end
elseif enemytorso == nil and canWander then
isWandering = 0
path = nil
waypoint = nil
--human.MoveToFinished:Wait()
end
end
now it just does exactly what I said in the original post
i forgot to change this
function GetTorso(part)
local chars = game.Workspace:GetChildren()
local torsos = {}
local torso = nil
for _, v in pairs(chars) do
if v:IsA'Model' and v ~= script.Parent and v.Name == GetPlayerNames() then
local charRoot = v.PrimaryPart
if (charRoot.Position - part).magnitude < SearchDistance then
table.insert(torsos, charRoot)
end
end
end
table.sort(torsos, function (a, b) return b.Position > a.Position end)
torso = torsos[1]
return torso
end
one of you get closer to the bot and see if it chases you.
tried, still only targets player that joined last
Oh wow you’re right, thats really weird. Hold on.
Yeah, the problem is definitely in your loop. Lemme see what could be causing this.
This is the error shown in the server-side console. Turns out it was trying to compare 2 Vector3 numbers when a player joins, forcing it to just stop working when there is more than one player.
I have found the solution as it works for me.
replace your gettorso function to:
function GetTorso(part)
local chars = {}
local torsos = {}
local torso = nil
for i,v in pairs(game.Players:GetChildren()) do
table.insert(chars, v.Character)
end
if #chars == 0 then return nil end
for _, v in pairs(chars) do
local charRoot = v.PrimaryPart
if (charRoot.Position - part).magnitude < SearchDistance then
table.insert(torsos, charRoot)
end
end
table.sort(torsos, function (a, b) return (b.Position - part).magnitude > (a.Position - part).magnitude
end) -- now it sorts both magnitudes.
torso = torsos[1]
return torso
end
Good news: the pathfinding works properly now
Bad news: damage doesn’t apply to the other player
damage part of the script incase you want to help with that
you really don’t have to help with this I’m just posting in case you do
for _, zambieparts in pairs(zombie:GetChildren()) do
if zambieparts:IsA'Part' then
zambieparts.Touched:connect(function(p)
if p.Parent.Name == GetPlayerNames() and p.Parent.Name ~= zombie.Name then -- damage
local enemy = p.Parent
local enemyhuman = getHumanoid(enemy)
enemyhuman:TakeDamage(ZombieDamage)
end
end)
end
end
Sure! Ill try fixing it right now.
im gonna credit you in this game
i cannot thank you enough
Greatly appreciated! You’re welcome!
for _, zambieparts in pairs(zombie:GetChildren()) do
if zambieparts:IsA'Part' then
zambieparts.Touched:connect(function(p)
if p.Parent:FindFirstChild('Humanoid') then -- damage
local enemy = p.Parent
local enemyhuman = getHumanoid(enemy)
enemyhuman:TakeDamage(ZombieDamage)
end
end)
end
end
This works for me.
Also make sure to mark this comment i replied to as solution, so people don’t come here and try to help when its already solved.
was worried that this was gonna damage other npc’s but it doesn’t look like it damages them
Yea, it does, but NPCs have infinite health. They don’t die like the regular player, because they aren’t coded to die, so their health just goes below 0 and into the infinites.
weird, cause when I tested damage with a second dummy it didn’t do any damage to it
Well yeah, it doesn’t show that it did damage because you have to set it to show its health bar when its damaged in the dummy humanoid properties. But it does do damage you can check that by looking at the humanoid properties of the dummy and check the health.