I’m trying to make an NPC head that will work the same way as in the Escape Running Head game.
There is a Felipe Killer model of such a head in the ToolBox, but this head does not behave exactly as it should. For some reason, this head only chases one player on the server, and also this head does not return to the place where it originally stood when it is not chasing players.
This model is from the ToolBox:
Felipe Killer.rbxm (14.2 KB)
Here is the script from this model:
--DuruTeru
local SearchDistance = 100000 -- How far a player can be before it detects you
local ZombieDamage = 0 -- How much damage the Zombie inficts towards the player
local canWander = false
local WanderX, WanderZ = 30, 30
-- How many studs the zombie can wander on the x and z axis in studs
--]]
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 torso = nil
for _, v in pairs(chars) do
if v:IsA'Model' and v ~= script.Parent and v.Name == GetPlayerNames() then
local charRoot = v:FindFirstChild'HumanoidRootPart'
if (charRoot.Position - part).magnitude < SearchDistance then
torso = charRoot
end
end
end
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
-- no touchy
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 -- if player detected
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 connection then
connection:Disconnect()
end
else
for i = 3, #oldpoints do
human:MoveTo( oldpoints[i].Position )
end
end
elseif enemytorso == nil and canWander then -- if player not detected
isWandering = 0
path = nil
waypoint = nil
human.MoveToFinished:Wait()
end
end
Perhaps the script in this model needs to be completely changed… I’ve been trying to do this for a very long time, but it didn’t work out.
What exactly do I need?
-
It is necessary for the NPC head to pursue the one who is closer to it. It is important that players can jump on high blocks or vice versa fall from a high cliff, where the head cannot get, and then the head should immediately go to another player even if he is very far from it, but nothing blocks the way to this player. Similarly, the head should behave if it killed the player it was chasing.
-
If all the players are out of reach, then the NPC’s head should be able to return to the point where it originally stood (that is, where I put the NPC in roblox studio, the NPC should return there in the game). The head should stay there until the player(s) are in range again.
-
Of course, when chasing a player, the head must be able to avoid obstacles in its path.
Please watch the video, this is how an NPC’s head should behave:
To make it even clearer exactly how an NPC’s head should act, try to log into this game:
Escape Running Head
I don’t understand the principle by which NPCs work in this game. Is pathfinding or raycasting used here? Or pathfinding and raycasting together? Or neither at all?
Maybe there are other NPC models with this behavior in the ToolBox.
Thank you so much for any help!