My miner npcs (controlled by collectionservice) are targetting the same ore no matter what I do to them, I tried adding tags, checking how many tags are in an object, inserting tags into objects, basically every possible thing involving tags (objectvalue ones).
Here is the script
local ReplicatedStorage = game:GetService('ReplicatedStorage')
local Players = game:GetService('Players')
local CollectionService = game:GetService('CollectionService')
local PathfindingService = game:GetService('PathfindingService')
local RaycastHitbox = require(ReplicatedStorage.RaycastHitboxV4)
local MinerNumber = 0
CollectionService:AddTag(ReplicatedStorage.AI.Miner,'Miner')
CollectionService:GetInstanceAddedSignal('Miner'):Connect(function(Miner)
spawn(function()
Miner.Name = Miner.Name..tostring(MinerNumber)
MinerNumber += 1
local humrp = Miner.HumanoidRootPart
local hum = Miner.Humanoid
local WalkAnim = hum:LoadAnimation(script.Parent.Anims.walk.WalkAnim)
local MiningAnim = hum:LoadAnimation(script.Parent.Anims.Swing)
local Mining = false
local Params = RaycastParams.new()
Params.FilterDescendantsInstances = {Miner,workspace.OreSpawningArea} --- remember to define our character!
Params.FilterType = Enum.RaycastFilterType.Blacklist
local newHitbox = RaycastHitbox.new(Miner.Handle)
newHitbox:SetPoints(Miner.Handle,{Vector3.new(0,0,2)})
newHitbox.RaycastParams = Params
newHitbox.DetectionMode = RaycastHitbox.DetectionMode.PartMode
-- relevant parts \/
local function getTags(model)
local tags = 0
for _,tag in pairs(model:GetChildren()) do
if string.find(tag.Name,'Miner') then
tags += 1
end
end
return tags
end
local function getNearestOre()
local Ores = workspace.Ores:GetChildren()
local closesetOre = Ores[1]
for _, Ore in pairs(Ores) do
if getTags(Ore) == 1 then
print(getTags(Ore))
if closesetOre:FindFirstChild(Miner.Name) then
if Ore.Main and (closesetOre.Main.Position - humrp.Position).Magnitude > (closesetOre.Main.Position - humrp.Position).Magnitude then
closesetOre = Ore
end
end
else
local Tag = Instance.new('ObjectValue')
Tag.Parent = closesetOre
Tag.Name = Miner.Name
end
end
return closesetOre
end
--relevant parts /\
local function breakOre()
if Mining == false then
Mining = true
Miner:SetPrimaryPartCFrame(CFrame.new(humrp.Position,getNearestOre().Main.Position))
MiningAnim:Play()
newHitbox:HitStart()
-- I apologize to my future self on my terrible readability on this code
newHitbox.OnHit:Connect(function(hit)
if hit:FindFirstAncestor('Ores') then
local OreHealth = hit.Parent.Health.Value
if OreHealth >= 2 then
hit.Parent.Health.Value -= 1
Miner.Handle.Hit:Play()
local Particles = script.Smoke:Clone()
delay(0.3,function()
local newPart = Instance.new('Part')
newPart.Transparency = 1
newPart.Anchored = true
newPart.Position = Miner.Handle.Attachment.WorldPosition
newPart.Parent = Miner
Particles.Parent = newPart
delay(0.5,function()
Particles.Enabled = false
game:GetService('Debris'):AddItem(newPart,1)
end)
end)
else
Miner.Handle.Break:Play()
for _,ore in pairs(hit.Parent:GetChildren()) do
if ore.Name == 'Ore' then
ore.Anchored = false
ore.Parent = workspace
ore.Touched:Connect(function(Hit)
if Players:GetPlayerFromCharacter(Hit.Parent) then
require(ReplicatedStorage.FactoryResources).Resources[ore.Name] += 1
end
end)
end
end
if hit.Parent:IsA('Model') and hit.Parent.Name ~= 'Workspace' then
hit.Parent:Destroy()
end
end
end
end)
MiningAnim.Stopped:Wait()
task.wait(0.5)
newHitbox:HitStop()
Mining = false
end
end
local function walkToOre()
local path = PathfindingService:CreatePath()
local success, errorMessage = pcall(function()
--path:ComputeAsync(humrp.Position, workspace.FrontOfFactory.Position + Vector3.new(math.random(1,10),math.random(1,10),math.random(1,10)))
path:ComputeAsync(humrp.Position, getNearestOre().Main.Position + ((humrp.Position-getNearestOre().Main.Position).Unit * 6))
end)
WalkAnim:Play()
if success and path.Status == Enum.PathStatus.Success then
local waypoints = path:GetWaypoints()
for _,waypoint in pairs(waypoints) do
if waypoint.Action == Enum.PathWaypointAction.Jump then
hum:ChangeState(Enum.HumanoidStateType.Jumping)
end
if getNearestOre() and (humrp.Position - getNearestOre().Main.Position).Magnitude <= 10 then
breakOre()
end
hum:MoveTo(waypoint.Position)
hum.MoveToFinished:Wait()
end
end
WalkAnim:Stop()
while task.wait(0.5) do
walkToOre()
end
end
walkToOre()
end)
end)
local clone = ReplicatedStorage.AI.Miner:Clone()
clone.Parent = workspace
task.wait(0.1)
local clone = ReplicatedStorage.AI.Miner:Clone()
clone.Parent = workspace
clone:SetPrimaryPartCFrame(CFrame.new(Vector3.new(-150.777, 4, 50.515)))
Here is a gif of the problem
EDIT: making the gif embedded
As seen, the npcs just move towards a single ore, regardless whether one is closer to another or not.
I’ve tried too many things to solve this, i’ve spent about an hour yesterday and today researching stuff about this and how to solve it, and I am inconclusive.
for _, Ore in pairs(Ores) do
if getTags(Ore) == 1 then
print(getTags(Ore))
if closesetOre:FindFirstChild(Miner.Name) then
Be sure to run “Format Document” in the scripting tab.
This getNearestOre a small bug that prevents it from actually calculating the nearest one.
if Ore.Main and (closesetOre.Main.Position - humrp.Position).Magnitude > (closesetOre.Main.Position - humrp.Position).Magnitude then
This is checking if the closest ore is closer than the closest ore which should never return true, this will loop through and always return Ores[1]. Change one of these to check against Ore.Main.Position.
You should also definitely store this value and use it as a parameter for breakOre, calculating this many distance checks every time you call getNearestOre() (plus the nearest ore might change) is bad for performance.
local nearest = getNearestOre()
if nearest and (humrp.Position - nearest .Main.Position).Magnitude <= 10 then
breakOre(nearest)
end
You need to mark the closest ore as soon as it’s calculated
local function walkToOre()
local path = PathfindingService:CreatePath()
local nearest = getNearestOre()
if nearest == nil then
return
end
CollectionService:AddTag(nearest, "ToBeMined")
local success, errorMessage = pcall(function()
--path:ComputeAsync(humrp.Position, workspace.FrontOfFactory.Position + Vector3.new(math.random(1,10),math.random(1,10),math.random(1,10)))
path:ComputeAsync(humrp.Position, nearest.Main.Position + ((humrp.Position-getNearestOre().Main.Position).Unit * 6))
end)
WalkAnim:Play()
-- change getNearestOre to ignore tagged
local function getNearestOre()
local Ores = workspace.Ores:GetChildren()
local closesetOre = nil
local closestDistance = nil
for _, Ore in pairs(Ores) do
local my_distance = (Ore.Main.Position - humrp.Position).Magnitude
if CollectionService:HasTag(Ore, "ToBeMined") then
continue
elseif closestOre == nil then -- nothing to compare add default
closestOre = Ore
closestDistance = my_distance
elseif Ore.Main and closestDistance > my_distance then -- default was set, time to compare
closestOre = Ore
closestDistance = my_distance
end
end
return closestOre
end
Not much of a difference really, am I doing it wrong?
new script:
local ReplicatedStorage = game:GetService('ReplicatedStorage')
local Players = game:GetService('Players')
local CollectionService = game:GetService('CollectionService')
local PathfindingService = game:GetService('PathfindingService')
local RaycastHitbox = require(ReplicatedStorage.RaycastHitboxV4)
local MinerNumber = 0
CollectionService:AddTag(ReplicatedStorage.AI.Miner,'Miner')
CollectionService:GetInstanceAddedSignal('Miner'):Connect(function(Miner)
Miner.Name = Miner.Name..tostring(MinerNumber)
MinerNumber += 1
local humrp = Miner.HumanoidRootPart
local hum = Miner.Humanoid
local WalkAnim = hum:LoadAnimation(script.Parent.Anims.walk.WalkAnim)
local MiningAnim = hum:LoadAnimation(script.Parent.Anims.Swing)
local Mining = false
local Params = RaycastParams.new()
Params.FilterDescendantsInstances = {Miner,workspace.OreSpawningArea} --- remember to define our character!
Params.FilterType = Enum.RaycastFilterType.Blacklist
local newHitbox = RaycastHitbox.new(Miner.Handle)
newHitbox:SetPoints(Miner.Handle,{Vector3.new(0,0,2)})
newHitbox.RaycastParams = Params
newHitbox.DetectionMode = RaycastHitbox.DetectionMode.PartMode
local function getTags(model)
local tags = 0
for _,tag in pairs(model:GetChildren()) do
if string.find(tag.Name,'Miner') then
tags += 1
end
end
return tags
end
local function getNearestOre()
local Ores = workspace.Ores:GetChildren()
local closesetOre = Ores[1]
for _, Ore in pairs(Ores) do
if getTags(Ore) == 1 then
print(getTags(Ore))
if closesetOre:FindFirstChild(Miner.Name) then
if Ore.Main and (closesetOre.Main.Position - humrp.Position).Magnitude > (Ore.Main.Position - humrp.Position).Magnitude then
closesetOre = Ore
end
end
else
local Tag = Instance.new('ObjectValue')
Tag.Parent = closesetOre
Tag.Name = Miner.Name
end
end
return closesetOre
end
local function breakOre()
if Mining == false then
Mining = true
Miner:SetPrimaryPartCFrame(CFrame.new(humrp.Position,getNearestOre().Main.Position))
MiningAnim:Play()
newHitbox:HitStart()
-- I apologize to my future self on my terrible readability on this code
newHitbox.OnHit:Connect(function(hit)
if hit:FindFirstAncestor('Ores') then
local OreHealth = hit.Parent.Health.Value
if OreHealth >= 2 then
hit.Parent.Health.Value -= 1
Miner.Handle.Hit:Play()
local Particles = script.Smoke:Clone()
delay(0.3,function()
local newPart = Instance.new('Part')
newPart.Transparency = 1
newPart.Anchored = true
newPart.Position = Miner.Handle.Attachment.WorldPosition
newPart.Parent = Miner
Particles.Parent = newPart
delay(0.5,function()
Particles.Enabled = false
game:GetService('Debris'):AddItem(newPart,1)
end)
end)
else
Miner.Handle.Break:Play()
for _,ore in pairs(hit.Parent:GetChildren()) do
if ore.Name == 'Ore' then
ore.Anchored = false
ore.Parent = workspace
ore.Touched:Connect(function(Hit)
if Players:GetPlayerFromCharacter(Hit.Parent) then
require(ReplicatedStorage.FactoryResources).Resources[ore.Name] += 1
end
end)
end
end
if hit.Parent:IsA('Model') and hit.Parent.Name ~= 'Workspace' then
hit.Parent:Destroy()
end
end
end
end)
MiningAnim.Stopped:Wait()
task.wait(0.5)
newHitbox:HitStop()
Mining = false
end
end
local function walkToOre()
local path = PathfindingService:CreatePath()
local success, errorMessage = pcall(function()
--path:ComputeAsync(humrp.Position, workspace.FrontOfFactory.Position + Vector3.new(math.random(1,10),math.random(1,10),math.random(1,10)))
path:ComputeAsync(humrp.Position, getNearestOre().Main.Position + ((humrp.Position-getNearestOre().Main.Position).Unit * 6))
end)
WalkAnim:Play()
if success and path.Status == Enum.PathStatus.Success then
local waypoints = path:GetWaypoints()
for _,waypoint in pairs(waypoints) do
if waypoint.Action == Enum.PathWaypointAction.Jump then
hum:ChangeState(Enum.HumanoidStateType.Jumping)
end
local nearest = getNearestOre()
if nearest and (humrp.Position - nearest .Main.Position).Magnitude <= 10 then
breakOre(nearest)
end
hum:MoveTo(waypoint.Position)
hum.MoveToFinished:Wait()
end
end
WalkAnim:Stop()
while task.wait(0.5) do
walkToOre()
end
end
spawn(function()
walkToOre()
end)
end)
local clone = ReplicatedStorage.AI.Miner:Clone()
clone.Parent = workspace
task.wait(0.1)
local clone = ReplicatedStorage.AI.Miner:Clone()
clone.Parent = workspace
clone:SetPrimaryPartCFrame(CFrame.new(Vector3.new(-150.777, 4, 50.515)))
task.wait(0.1)
local clone = ReplicatedStorage.AI.Miner:Clone()
clone.Parent = workspace
clone:SetPrimaryPartCFrame(CFrame.new(Vector3.new(-150.777, 4, 50.515)))
task.wait(0.1)
local clone = ReplicatedStorage.AI.Miner:Clone()
clone.Parent = workspace
clone:SetPrimaryPartCFrame(CFrame.new(Vector3.new(-150.777, 4, 50.515)))
local function getNearestOre()
local Ores = workspace.Ores:GetChildren()
local closesetOre = Ores[1]
local closestDistance = math.huge
for _, Ore in pairs(Ores) do
local my_distance = (Ore.Main.Position - humrp.Position).Magnitude
if Ore.Main and closestDistance > my_distance then
closestOre = Ore
closestDistance = my_distance
end
end
return closestOre
end
--functions here
CollectionService:AddTag(ReplicatedStorage.AI.Miner,'Miner')
CollectionService:GetInstanceAddedSignal('Miner'):Connect(function(Miner)
--code here
end)
then this will never be true, zero is actually the worst default, try math.huge instead
if Ore.Main and 0 > my_distance then
The tag check is so the miners do not attack the same ore, like the author wants. Which is why I start with nil closest ore, if Ores[1] is tagged then it skips the whole system and can be targeted by all miners.
I put copied and pasted that script into the appropriate places but now this error appears and the miners appear to be very glitchy now:
New script:
local ReplicatedStorage = game:GetService('ReplicatedStorage')
local Players = game:GetService('Players')
local CollectionService = game:GetService('CollectionService')
local PathfindingService = game:GetService('PathfindingService')
local RaycastHitbox = require(ReplicatedStorage.RaycastHitboxV4)
local MinerNumber = 0
CollectionService:AddTag(ReplicatedStorage.AI.Miner,'Miner')
CollectionService:GetInstanceAddedSignal('Miner'):Connect(function(Miner)
spawn(function()
Miner.Name = Miner.Name..tostring(MinerNumber)
MinerNumber += 1
local humrp = Miner.HumanoidRootPart
local hum = Miner.Humanoid
local WalkAnim = hum:LoadAnimation(script.Parent.Anims.walk.WalkAnim)
local MiningAnim = hum:LoadAnimation(script.Parent.Anims.Swing)
local Mining = false
local Params = RaycastParams.new()
Params.FilterDescendantsInstances = {Miner,workspace.OreSpawningArea} --- remember to define our character!
Params.FilterType = Enum.RaycastFilterType.Blacklist
local newHitbox = RaycastHitbox.new(Miner.Handle)
newHitbox:SetPoints(Miner.Handle,{Vector3.new(0,0,2)})
newHitbox.RaycastParams = Params
newHitbox.DetectionMode = RaycastHitbox.DetectionMode.PartMode
local function getTags(model)
local tags = 0
for _,tag in pairs(model:GetChildren()) do
if string.find(tag.Name,'Miner') then
tags += 1
end
end
return tags
end
local function getNearestOre()
local Ores = workspace.Ores:GetChildren()
local closestOre = nil
local closestDistance = nil
for _, Ore in pairs(Ores) do
local my_distance = (Ore.Main.Position - humrp.Position).Magnitude
if CollectionService:HasTag(Ore, "ToBeMined") then
continue
elseif closestOre == nil then -- nothing to compare add default
closestOre = Ore
closestDistance = my_distance
elseif Ore.Main and closestDistance > my_distance then -- default was set, time to compare
closestOre = Ore
closestDistance = my_distance
end
end
print(closestOre)
return closestOre
end
local function breakOre()
if Mining == false then
Mining = true
Miner:SetPrimaryPartCFrame(CFrame.new(humrp.Position,getNearestOre().Main.Position))
MiningAnim:Play()
newHitbox:HitStart()
-- I apologize to my future self on my terrible readability on this code
newHitbox.OnHit:Connect(function(hit)
if hit:FindFirstAncestor('Ores') then
local OreHealth = hit.Parent.Health.Value
if OreHealth >= 2 then
hit.Parent.Health.Value -= 1
Miner.Handle.Hit:Play()
local Particles = script.Smoke:Clone()
delay(0.3,function()
local newPart = Instance.new('Part')
newPart.Transparency = 1
newPart.Anchored = true
newPart.Position = Miner.Handle.Attachment.WorldPosition
newPart.Parent = Miner
Particles.Parent = newPart
delay(0.5,function()
Particles.Enabled = false
game:GetService('Debris'):AddItem(newPart,1)
end)
end)
else
Miner.Handle.Break:Play()
for _,ore in pairs(hit.Parent:GetChildren()) do
if ore.Name == 'Ore' then
ore.Anchored = false
ore.Parent = workspace
ore.Touched:Connect(function(Hit)
if Players:GetPlayerFromCharacter(Hit.Parent) then
require(ReplicatedStorage.FactoryResources).Resources[ore.Name] += 1
end
end)
end
end
if hit.Parent:IsA('Model') and hit.Parent.Name ~= 'Workspace' then
hit.Parent:Destroy()
end
end
end
end)
MiningAnim.Stopped:Wait()
task.wait(0.5)
newHitbox:HitStop()
Mining = false
end
end
local function walkToOre()
local path = PathfindingService:CreatePath()
local nearest = getNearestOre()
if nearest == nil then
return
end
CollectionService:AddTag(nearest, "ToBeMined")
local success, errorMessage = pcall(function()
--path:ComputeAsync(humrp.Position, workspace.FrontOfFactory.Position + Vector3.new(math.random(1,10),math.random(1,10),math.random(1,10)))
path:ComputeAsync(humrp.Position, nearest.Main.Position + ((humrp.Position-getNearestOre().Main.Position).Unit * 6))
end)
WalkAnim:Play()
if success and path.Status == Enum.PathStatus.Success then
local waypoints = path:GetWaypoints()
for _,waypoint in pairs(waypoints) do
if waypoint.Action == Enum.PathWaypointAction.Jump then
hum:ChangeState(Enum.HumanoidStateType.Jumping)
end
if nearest and (humrp.Position - nearest .Main.Position).Magnitude <= 10 then
breakOre(nearest)
end
hum:MoveTo(waypoint.Position)
hum.MoveToFinished:Wait()
end
end
WalkAnim:Stop()
while task.wait(0.5) do
walkToOre()
end
end
walkToOre()
end)
end)
local clone = ReplicatedStorage.AI.Miner:Clone()
clone.Parent = workspace
task.wait(0.1)
local clone = ReplicatedStorage.AI.Miner:Clone()
clone.Parent = workspace
clone:SetPrimaryPartCFrame(CFrame.new(Vector3.new(-150.777, 4, 50.515)))
task.wait(0.1)
local clone = ReplicatedStorage.AI.Miner:Clone()
clone.Parent = workspace
clone:SetPrimaryPartCFrame(CFrame.new(Vector3.new(-150.777, 4, 50.515)))
task.wait(0.1)
local clone = ReplicatedStorage.AI.Miner:Clone()
clone.Parent = workspace
clone:SetPrimaryPartCFrame(CFrame.new(Vector3.new(-150.777, 4, 50.515)))
Good! You need to replace all of your getNearestOre functions with the variable found at the start. The way the function is set up it will Tag a new ore every time it is run, so the pool decreases very fast if you are running it more than once-per-miner.
That would take a long time to do, I would have to replace all of my variables like humrp and stuff with, for example, walkToOre(humrp,hum,etc.), would it be worth it?
you wouldn’t have to do that. This line for example has a getNearestOre().Main.Position call that should just be nearest.Main.Position. You need only a careful find-and-replace.
ocal ReplicatedStorage = game:GetService('ReplicatedStorage')
local Players = game:GetService('Players')
local CollectionService = game:GetService('CollectionService')
local PathfindingService = game:GetService('PathfindingService')
local RaycastHitbox = require(ReplicatedStorage.RaycastHitboxV4)
local MinerNumber = 0
local function getTags(model)
local tags = 0
for _,tag in pairs(model:GetChildren()) do
if string.find(tag.Name,'Miner') then
tags += 1
end
end
return tags
end
local function getNearestOre()
local Ores = workspace.Ores:GetChildren()
local closestOre = nil
local closestDistance = nil
for _, Ore in pairs(Ores) do
local my_distance = (Ore.Main.Position - humrp.Position).Magnitude
if CollectionService:HasTag(Ore, "ToBeMined") then
continue
elseif closestOre == nil then -- nothing to compare add default
closestOre = Ore
closestDistance = my_distance
elseif Ore.Main and closestDistance > my_distance then -- default was set, time to compare
closestOre = Ore
closestDistance = my_distance
end
end
print(closestOre)
return closestOre
end
local function breakOre()
if Mining == false then
Mining = true
Miner:SetPrimaryPartCFrame(CFrame.new(humrp.Position,getNearestOre().Main.Position))
MiningAnim:Play()
newHitbox:HitStart()
-- I apologize to my future self on my terrible readability on this code
newHitbox.OnHit:Connect(function(hit)
if hit:FindFirstAncestor('Ores') then
local OreHealth = hit.Parent.Health.Value
if OreHealth >= 2 then
hit.Parent.Health.Value -= 1
Miner.Handle.Hit:Play()
local Particles = script.Smoke:Clone()
delay(0.3,function()
local newPart = Instance.new('Part')
newPart.Transparency = 1
newPart.Anchored = true
newPart.Position = Miner.Handle.Attachment.WorldPosition
newPart.Parent = Miner
Particles.Parent = newPart
delay(0.5,function()
Particles.Enabled = false
game:GetService('Debris'):AddItem(newPart,1)
end)
end)
else
Miner.Handle.Break:Play()
for _,ore in pairs(hit.Parent:GetChildren()) do
if ore.Name == 'Ore' then
ore.Anchored = false
ore.Parent = workspace
ore.Touched:Connect(function(Hit)
if Players:GetPlayerFromCharacter(Hit.Parent) then
require(ReplicatedStorage.FactoryResources).Resources[ore.Name] += 1
end
end)
end
end
if hit.Parent:IsA('Model') and hit.Parent.Name ~= 'Workspace' then
hit.Parent:Destroy()
end
end
end
end)
local function walkToOre()
local path = PathfindingService:CreatePath()
local nearest = getNearestOre()
if nearest == nil then
return
end
CollectionService:AddTag(nearest, "ToBeMined")
local success, errorMessage = pcall(function()
--path:ComputeAsync(humrp.Position, workspace.FrontOfFactory.Position + Vector3.new(math.random(1,10),math.random(1,10),math.random(1,10)))
path:ComputeAsync(humrp.Position, nearest.Main.Position + ((humrp.Position-getNearestOre().Main.Position).Unit * 6))
end)
WalkAnim:Play()
if success and path.Status == Enum.PathStatus.Success then
local waypoints = path:GetWaypoints()
for _,waypoint in pairs(waypoints) do
if waypoint.Action == Enum.PathWaypointAction.Jump then
hum:ChangeState(Enum.HumanoidStateType.Jumping)
end
if nearest and (humrp.Position - nearest .Main.Position).Magnitude <= 10 then
breakOre(nearest)
end
hum:MoveTo(waypoint.Position)
hum.MoveToFinished:Wait()
end
end
WalkAnim:Stop()
while task.wait(0.5) do
walkToOre()
end
end
walkToOre()
end)
then
CollectionService:AddTag(ReplicatedStorage.AI.Miner,'Miner')
CollectionService:GetInstanceAddedSignal('Miner'):Connect(function(Miner)
spawn(function()
Miner.Name = Miner.Name..tostring(MinerNumber)
MinerNumber += 1
local humrp = Miner.HumanoidRootPart
local hum = Miner.Humanoid
local WalkAnim = hum:LoadAnimation(script.Parent.Anims.walk.WalkAnim)
local MiningAnim = hum:LoadAnimation(script.Parent.Anims.Swing)
local Mining = false
local Params = RaycastParams.new()
Params.FilterDescendantsInstances = {Miner,workspace.OreSpawningArea} --- remember to define our character!
Params.FilterType = Enum.RaycastFilterType.Blacklist
local newHitbox = RaycastHitbox.new(Miner.Handle)
newHitbox:SetPoints(Miner.Handle,{Vector3.new(0,0,2)})
newHitbox.RaycastParams = Params
newHitbox.DetectionMode = RaycastHitbox.DetectionMode.PartMode
call functions in same order
end)
local ReplicatedStorage = game:GetService('ReplicatedStorage')
local Players = game:GetService('Players')
local CollectionService = game:GetService('CollectionService')
local PathfindingService = game:GetService('PathfindingService')
local RaycastHitbox = require(ReplicatedStorage.RaycastHitboxV4)
local MinerNumber = 0
CollectionService:AddTag(ReplicatedStorage.AI.Miner,'Miner')
CollectionService:GetInstanceAddedSignal('Miner'):Connect(function(Miner)
spawn(function()
Miner.Name = Miner.Name..tostring(MinerNumber)
MinerNumber += 1
local humrp = Miner.HumanoidRootPart
local hum = Miner.Humanoid
local WalkAnim = hum:LoadAnimation(script.Parent.Anims.walk.WalkAnim)
local MiningAnim = hum:LoadAnimation(script.Parent.Anims.Swing)
local Mining = false
local Params = RaycastParams.new()
Params.FilterDescendantsInstances = {Miner,workspace.OreSpawningArea} --- remember to define our character!
Params.FilterType = Enum.RaycastFilterType.Blacklist
local newHitbox = RaycastHitbox.new(Miner.Handle)
newHitbox:SetPoints(Miner.Handle,{Vector3.new(0,0,2)})
newHitbox.RaycastParams = Params
newHitbox.DetectionMode = RaycastHitbox.DetectionMode.PartMode
local function getNearestOre()
local Ores = workspace.Ores:GetChildren()
local closestOre = nil
local closestDistance = nil
for _, Ore in pairs(Ores) do
local my_distance = (Ore.Main.Position - humrp.Position).Magnitude
if CollectionService:HasTag(Ore, "ToBeMined") then
continue
elseif closestOre == nil then -- nothing to compare add default
closestOre = Ore
closestDistance = my_distance
elseif Ore.Main and closestDistance > my_distance then -- default was set, time to compare
closestOre = Ore
closestDistance = my_distance
end
end
return closestOre
end
local function breakOre(nearest)
if Mining == false then
Mining = true
Miner:SetPrimaryPartCFrame(CFrame.new(humrp.Position,nearest.Main.Position))
MiningAnim:Play()
newHitbox:HitStart()
-- I apologize to my future self on my terrible readability on this code
newHitbox.OnHit:Connect(function(hit)
if hit:FindFirstAncestor('Ores') then
local OreHealth = hit.Parent.Health.Value
if OreHealth >= 2 then
hit.Parent.Health.Value -= 1
Miner.Handle.Hit:Play()
local Particles = script.Smoke:Clone()
delay(0.3,function()
local newPart = Instance.new('Part')
newPart.Transparency = 1
newPart.Anchored = true
newPart.Position = Miner.Handle.Attachment.WorldPosition
newPart.Parent = Miner
Particles.Parent = newPart
delay(0.5,function()
Particles.Enabled = false
game:GetService('Debris'):AddItem(newPart,1)
end)
end)
else
Miner.Handle.Break:Play()
for _,ore in pairs(hit.Parent:GetChildren()) do
if ore.Name == 'Ore' then
ore.Anchored = false
ore.Parent = workspace
ore.Touched:Connect(function(Hit)
if Players:GetPlayerFromCharacter(Hit.Parent) then
require(ReplicatedStorage.FactoryResources).Resources[ore.Name] += 1
end
end)
end
end
if hit.Parent:IsA('Model') and hit.Parent.Name ~= 'Workspace' then
hit.Parent:Destroy()
end
end
end
end)
MiningAnim.Stopped:Wait()
task.wait(0.5)
newHitbox:HitStop()
Mining = false
end
end
local function walkToOre()
local path = PathfindingService:CreatePath()
local nearest = getNearestOre()
if nearest == nil then
return
end
CollectionService:AddTag(nearest, "ToBeMined")
local success, errorMessage = pcall(function()
--path:ComputeAsync(humrp.Position, workspace.FrontOfFactory.Position + Vector3.new(math.random(1,10),math.random(1,10),math.random(1,10)))
path:ComputeAsync(humrp.Position, nearest.Main.Position + ((humrp.Position-nearest.Main.Position).Unit * 6))
end)
WalkAnim:Play()
if success and path.Status == Enum.PathStatus.Success then
local waypoints = path:GetWaypoints()
for _,waypoint in pairs(waypoints) do
if waypoint.Action == Enum.PathWaypointAction.Jump then
hum:ChangeState(Enum.HumanoidStateType.Jumping)
end
if nearest and (humrp.Position - nearest .Main.Position).Magnitude <= 10 then
breakOre(nearest)
end
hum:MoveTo(waypoint.Position)
hum.MoveToFinished:Wait()
end
end
WalkAnim:Stop()
while task.wait(0.5) do
walkToOre()
end
end
walkToOre()
end)
end)
local clone = ReplicatedStorage.AI.Miner:Clone()
clone.Parent = workspace
task.wait(0.1)
local clone = ReplicatedStorage.AI.Miner:Clone()
clone.Parent = workspace
clone:SetPrimaryPartCFrame(CFrame.new(Vector3.new(-150.777, 4, 50.515)))
task.wait(0.1)
local clone = ReplicatedStorage.AI.Miner:Clone()
clone.Parent = workspace
clone:SetPrimaryPartCFrame(CFrame.new(Vector3.new(-150.777, 4, 50.515)))
task.wait(0.1)
local clone = ReplicatedStorage.AI.Miner:Clone()
clone.Parent = workspace
clone:SetPrimaryPartCFrame(CFrame.new(Vector3.new(-150.777, 4, 50.515)))
I would need to manually define all of the variables like local function breakOre(Mining,Miner,MiningAnim,newHitbox) for every single function, it would just be too much work and I don’t think that the performance change would be significant enough.