but how do i not loop through all of the parts in the region without finding the players
Function for finding nearest player
function findNearestPlayer(players)
local mob = nil -- reference the mob here
local mindistance = -- min distance
local playersinrange = {}
if not mob then return end
for _,v in pairs(players) do
If not v then continue end
local distance = (mob.PrimaryPart.Position - v.PrimaryPart.Position).magnitude
If distance <= mindistance then
playersinrange[v] = distance
end
end
local s = 0
local p = nil
for i, v in pairs(playersinrange) do
if v <= s then
s = v
p = i
end
end
return p
end
This will give you the nearest player
Im not done with ut i just gonna go do something ima edit it, with the rest in 6 minutes
I gave you the answer for that. Its in the function getPlayerCharacters
I am making it so that there are two areas, with one the enemy cant go in, but once the player goes in the other area, the enemy starts running after the player so i dont think i can use the minimum distance for this
Ohh ok give me a second to tweek it
but when the boss is chasing the player, it will be closer to the player so he will keep on following it out of the area
In order to tell if the player is on one side or the other the easiest way to do that is to have 2 huge parts, that are invisible and cant collide. Then put on at one side and one at the other. Then when the player tpuches the one near the mob, you make the mob chase them. If the touch the one away from the mob, the mob stop chasing them. Your code is wayyy to long for me to do at work, i get off in 5 hours i can do it for you then
I already have that, but i made a region 3 around that part. I probably wont be a wake when you get off of work, its 11pm for me rn, but thankyou a lot! I will try to respond back as quickly as i can
local playerService = game:GetService("Players")
local partMobActivate = nil -- Change this to a reference for the part where the mob attacks
local mob = nil -- Change this to a reference to mob
local playersInAttackRange = {}
local function onTouch(part)
local humanoid = part.Parent:FindFirstChild("Humanoid")
if humanoid and part.Parent and mob then
local player = playerService:GetPlayerFromCharacter(part.Parent)
if not player then return end
local distance = (part.Parent.PrimaryPart.Position - mob.PrimaryPart.Position).Magnitude
playersInAttackRange[player] = distance
end
end
local function onTouchEnded(part)
local humanoid = part.Parent:FindFirstChild("Humanoid")
if humanoid and part.Parent and mob then
local player = playerService:GetPlayerFromCharacter(part.Parent)
if not player then return end
playersInAttackRange[player] = nil
end
end
partMobActivate.TouchedEnded:Connect(onTouchEnded)
partMobActivate.Touched:Connect(onTouch)
while wait() do
local player = nil
local least = nil
for i, v in pairs(playersInAttackRange) do
if not least or v <= least then
player = i
least = v
end
end
If not player then continue end
local character = player.Character
if not character then continue end
local primaryPart = character.PrimaryPart
local mobHumanoid = character.Humanoid
if not primaryPart or not mobHumanoid then continue end
local location = primaryPart.Position
mobHumanoid:MoveTo(location)
end
Going to sleep tell me if this doesn’t work, or if there are any problems, I will answer when i wake up
the playersinattackrange is constantly zero even if im touching the part. but i dont know why i also dont know how it knows which one is closer
I had to do some changes to your script because the touch statment was running after the wait loop causing errors. also is there a better way than to use wait(), it makes a lot of lag this is what the script looks like now:
local playerService = game:GetService("Players")
local partMobActivate = script.Parent.Parent["Electric Area"] -- Change this to a reference for the part where the mob attacks
local mob = script.Parent -- Change this to a reference to mob
local playersInAttackRange = {}
local function onTouch(part)
local humanoid = part.Parent:FindFirstChild("Humanoid")
if humanoid and part.Parent and mob then
local player = playerService:GetPlayerFromCharacter(part.Parent)
if not player then return end
local distance = (part.Parent.PrimaryPart.Position - mob.PrimaryPart.Position).Magnitude
playersInAttackRange[player] = distance
print("touched!!!!!!!!!")
end
end
local function onTouchEnded(part)
local humanoid = part.Parent:FindFirstChild("Humanoid")
if humanoid and part.Parent and mob then
local player = playerService:GetPlayerFromCharacter(part.Parent)
if not player then return end
playersInAttackRange[player] = nil
print("touchended")
end
end
partMobActivate.Touched:Connect(onTouch)
partMobActivate.TouchEnded:Connect(onTouchEnded)
while wait() do
local player = nil
local least = nil
if #playersInAttackRange >= 1 then
for i, v in pairs(playersInAttackRange) do
if not least or v <= least then
player = i
least = v
print(i, v)
end
end
print(player)
local character = player.Character or player.CharacterAdded:Wait()
if not character then continue end
local primaryPart = character.PrimaryPart
local mobHumanoid = mob.Humanoid
if not primaryPart or not mobHumanoid then continue end
local location = primaryPart.Position
mobHumanoid:MoveTo(location)
end
end
Remove if #playersinattackrange
I updated my script also i gotta add something else i just remembered
but if i getrid of this, the loop will run before the touch statment so there will be a nil error, also what did u change
2 things it is working, its just the humanoid:MoveTo isnt working thats the only part that isnt working
proof:
it correctly detects player and its position
also this is the new updated code
local playerService = game:GetService("Players")
local partMobActivate = game.Workspace:WaitForChild("Part1") -- Change this to a reference for the part where the mob attacks
local mob = script.Parent -- Change this to a reference to mob
local playersInAttackRange = {}
local debouncet = {}
local function onTouch(part)
if debouncet[part.Parent] then return end
print("touched")
local humanoid = part.Parent:FindFirstChild("Humanoid")
if humanoid and part.Parent and mob then
local player = playerService:GetPlayerFromCharacter(part.Parent)
if not player then return end
local distance = (part.Parent.PrimaryPart.Position - mob.PrimaryPart.Position).Magnitude
playersInAttackRange[player] = distance
debouncet[part.Parent] = true
end
end
local function onTouchEnded(part)
if not debouncet[part.Parent] then return end
print("touchended")
local humanoid = part.Parent:FindFirstChild("Humanoid")
if humanoid and part.Parent and mob then
local player = playerService:GetPlayerFromCharacter(part.Parent)
if not player then return end
playersInAttackRange[player] = nil
debouncet[part.Parent] = false
end
end
print(game.Workspace.Part1)
partMobActivate.Touched:Connect(onTouch)
partMobActivate.TouchEnded:Connect(onTouchEnded)
while wait(1) do
local player = nil
local least = nil
for i, v in pairs(playersInAttackRange) do
print(i, v)
if not least or v <= least then
player = i
least = v
end
end
print(player)
if not player then continue end
local character = player.Character
if not character then continue end
local primaryPart = character.PrimaryPart
local mobHumanoid = character.Humanoid
if not primaryPart or not mobHumanoid then continue end
local location = primaryPart.Position
mobHumanoid:MoveTo(location.Unit)
print(location)
end
try and figure out why the move to isnt working, i gotta go to work, i will research why at work
edit: So the mob should finally move now, but the problem is it moves once then stops working, probably game waiting for moveToFinished im off to work, will continue later
its constantly zero because playersinattackrange
is a dictionary, you cant do #
for a dictionary, you have to manually get the length buy looping through it
The best solution is to put the magnitudes into a table and then sort the table, returning the smallest distance.
local rig = script.Parent
local electricarea = script.Parent.Parent["Electric Area"]
local range = 100 --maximum distance player can be from boss
local function findNearestPlayer(boss)
local characters = {}
for _,player in pairs(game.Players:GetChildren()) do
if player.Character ~= nil and player.Character:FindFirstChild("HumanoidRootPart") ~= nil then
local arr = {}
arr.Player = player
arr.Character = player.Character
arr.Position = player.Character.HumanoidRootPart.Position
arr.Magnitude = (boss.HumanoidRootPart.Position - player.Character.HumanoidRootPart.Position).magnitude
if arr.magnitude <= range then
table.insert(characters,arr)
end
end
end
table.sort(characters,function(a,b) return a.Magnitude < b.Magnitude end)
return characters[1]
end
while wait(1) do
local nearestPlayer = findNearestPlayer(rig)
rig.Humanoid:MoveTo(nearestPlayer.Position)
print(nearestPlayer.Magnitude)
end
That wont work cause she wants it to be an area so its not a circle range around the boss
I did some research and the problem resides in the fact that GetPartsInRegion3 is depreciated.
The recommendation is that devs use GetPartBoundsInBox instead.
I wrote this up using that, and everything works as expected.
local rig = script.Parent
local electricarea = script.Parent.Parent["Electric Area"]
local area = {}
area.CFrame = CFrame.new(0,0,0) -- center of arena
area.Size = Vector3.new(100,50,100) -- size of arena
area.OverlapParams = OverlapParams.new()
area.OverlapParams.FilterType = Enum.RaycastFilterType.Whitelist
function getCharactersInArena()
local whitelist = {}
for _,player in pairs(game.Players:GetChildren()) do
if player.Character ~= nil and player.Character:FindFirstChild("HumanoidRootPart") ~= nil then
table.insert(whitelist,player.Character.HumanoidRootPart)
end
end
area.OverlapParams.FilterDescendantsInstances = whitelist
local arr = workspace:GetPartBoundsInBox(area.CFrame,area.Size,area.OverlapParams)
return arr
end
local function findNearestPlayer(boss)
local characters = {}
local charactersInArena = getCharactersInArena()
for _,root in pairs(charactersInArena) do
local player = game.Players:GetPlayerFromCharacter(root.Parent)
local arr = {}
arr.Player = player
arr.Character = player.Character
arr.Position = player.Character.HumanoidRootPart.Position
arr.Magnitude = (boss.HumanoidRootPart.Position - player.Character.HumanoidRootPart.Position).magnitude
table.insert(characters,arr)
end
table.sort(characters,function(a,b) return a.Magnitude < b.Magnitude end)
return characters[1]
end
while wait(1) do
local root = rig.HumanoidRootPart
local nearestPlayer = findNearestPlayer(rig)
if nearestPlayer ~= nil then
rig.Humanoid:MoveTo(nearestPlayer.Position)
print(nearestPlayer.Magnitude)
end
end
local function GetClosestCharacter(position)
local closestPlayer = nil
local closestMagnitude = math.huge
for i, player in ipairs(game.Players:GetPlayers()) do
if player.Character == nil then continue end
local characterPosition = player.Character:GetPivot().Position
local magnitude = (characterPosition - position).Magnitude
if magnitude > closestMagnitude then continue end
closestPlayer = player
closestMagnitude = magnitude
end
return closestPlayer, closestMagnitude
end
local function GetCharactersWithin(position, radius)
local players = {}
for i, player in ipairs(game.Players:GetPlayers()) do
if player.Character == nil then continue end
local characterPosition = player.Character:GetPivot().Position
if (characterPosition - position).Magnitude > radius then continue end
table.insert(players, player)
end
return players
end
-- get and print the closest player to 0, 0, 0
local player, magnitude = GetClosestCharacter(Vector3.new(0, 0, 0))
print(player, magnitude)
-- get and print the closest player to electricarea
local player, magnitude = GetClosestCharacter(electricarea.Position)
print(player, magnitude)
-- get table of all players within 50 studs of electricarea
local players = GetCharactersWithin(electricarea.Position, 50)
print(players)