local i=script.Parent local M=require(game.ReplicatedStorage.Modules.GameData)local Y={}function GetDictionaryLength(i)local M=0 for i,Y in next,i do M=M+1 end return M end addAnt=coroutine.wrap(function()while wait(5)do if GetDictionaryLength(Y)<3 then local M=game.ServerStorage.Creatures["\083\099\097\118\101\110\103\101\114 \065\110\116"]:Clone()M:SetPrimaryPartCFrame(i.PrimaryPart.CFrame*CFrame.new(0,5,0))M.Parent=i Y[M]={carrying=nil;target=nil,destination=M.PrimaryPart.Position,lastOrder=tick();lastScan=tick(),anims={}}for i,U in next,game.ReplicatedStorage.NPCAnimations.Ant:GetChildren()do Y[M].anims[U.Name]=(M:WaitForChild("\072\117\109")):LoadAnimation(U)end;(M:WaitForChild("\072\101\097\108\116\104")).Changed:connect(function()M.PrimaryPart.Hurt.Pitch=M.PrimaryPart.Hurt.OriginalPitch.Value+math.random(-100,100)/100 M.PrimaryPart.Hurt:Play()end)M.AncestryChanged:connect(function()Y[M]=nil end)end wait(55)end end)addAnt()function Seeking(i,M)for i,Y in pairs(i)do if Y==M then return true end end return false end manageAnts=coroutine.wrap(function()while wait(1)do local U={}for X,C in next,Y do spawn(function()if X and(X.PrimaryPart and(X:FindFirstChild("\072\117\109")and(X.Hum.Health>0 and X:IsDescendantOf(workspace))))then Y[X].lastScan=tick()if not Y[X].carrying then local i,C=nil,math.huge for Y,I in next,workspace.Critters:GetChildren()do if not Seeking(U,I)and(I:FindFirstChild("\072\105\116\083\104\101\108\108")and M[I.Name].abductable)then local M,Y=X.PrimaryPart,I.PrimaryPart if not Y then Y=I:FindFirstChildOfClass("\066\097\115\101\080\097\114\116")end local U=(Y.Position-M.Position).magnitude if U<C then i=I C=U end end end if X and i then Y[X].destination=i.PrimaryPart.Position Y[X].target=i table.insert(U,i)Y[X].target.AncestryChanged:connect(function()Y[X].target=nil end)end else Y[X].destination=i.PrimaryPart.Position+Vector3.new(0,3,0)end if Y[X].destination then X.Hum:MoveTo(Y[X].destination)if not Y[X].anims.AntWalk.IsPlaying then Y[X].anims.AntWalk:Play()end if C.target and not C.carrying then local i=(X.PrimaryPart.Position-Y[X].target.PrimaryPart.Position).magnitude if i<5 then local i=game.ServerStorage.Misc["\065\098\100\117\099\116\101\100 \083\104\101\108\108\121"]:Clone()C.carrying=i i.Shell.Material=C.target.Shell.Material i.Shell.Color=C.target.Shell.Color i.ActualName.Value=C.target.Name C.target:Destroy()i.Parent=X Y[X].anims.AntWalk:Stop()Y[X].anims.AntHold:Play()X.PrimaryPart.Chatter:Play()X.PrimaryPart.ShellyAbduct:Play()local M=Instance.new("\077\097\110\117\097\108\087\101\108\100")M.Parent=X.PrimaryPart M.Part0=X.PrimaryPart M.Part1=i.PrimaryPart M.C0=CFrame.new(-0.4,.4,-1.6)*CFrame.Angles(0,math.rad(90),0)end elseif C.carrying then local i=(X.PrimaryPart.Position-Y[X].destination).magnitude if i<7 then X.Hum:MoveTo(X.PrimaryPart.Position)X.PrimaryPart.Chatter:Play()Y[X].anims.AntHold:Stop()Y[X].anims.AntWalk:Stop()Y[X].carrying:Destroy()Y[X].carrying=nil Y[X].destination=nil Y[X].target=nil end end end end end)end end end)manageAnts()
--DevVince was here.:o (4/23/2019)
--Fixed some stuff and made ants go after diffrent targets.
local hill = script.Parent
local itemData = require(game.ReplicatedStorage.Modules.GameData)
local activeAnts = {}

function GetDictionaryLength(tab)
	local total = 0
	for _, v in next, tab do
		total = total + 1
	end
	return total
end

addAnt = coroutine.wrap(function()
	while wait(5) do
		if GetDictionaryLength(activeAnts) < 3 then
			local newAnt = game.ServerStorage.Creatures["Scavenger Ant"]:Clone()
			newAnt:SetPrimaryPartCFrame(hill.PrimaryPart.CFrame * CFrame.new(0, 5, 0))
			newAnt.Parent = hill

			activeAnts[newAnt] = {
				["carrying"] = nil,
				["target"] = nil,
				["destination"] = newAnt.PrimaryPart.Position,
				["lastOrder"] = tick(),
				["lastScan"] = tick(),
				["anims"] = {},
			}

			for _, anim in next, game.ReplicatedStorage.NPCAnimations.Ant:GetChildren() do
				activeAnts[newAnt].anims[anim.Name] = newAnt:WaitForChild("Hum"):LoadAnimation(anim)
			end

			newAnt:WaitForChild("Health").Changed:connect(function()
				newAnt.PrimaryPart.Hurt.Pitch = newAnt.PrimaryPart.Hurt.OriginalPitch.Value
					+ (math.random(-100, 100) / 100)
				newAnt.PrimaryPart.Hurt:Play()
			end)

			newAnt.AncestryChanged:connect(function()
				activeAnts[newAnt] = nil
			end)
		end
		wait(55)
	end
end)

addAnt()

function Seeking(array, target) --Queen ant keeps track of her workers. ;)
	for i, v in pairs(array) do
		if v == target then
			return true
		end
	end
	return false
end

manageAnts = coroutine.wrap(function()
	while wait(1) do
		local seeking = {}
		for ant, antData in next, activeAnts do
			spawn(function()
				if
					ant
					and ant.PrimaryPart
					and ant:FindFirstChild("Hum")
					and ant.Hum.Health > 0
					and ant:IsDescendantOf(workspace)
				then
					activeAnts[ant].lastScan = tick()
					-- scan for nearest Shelly
					if not activeAnts[ant].carrying then
						local nearestShelly, closestDist = nil, math.huge

						for _, creature in next, workspace.Critters:GetChildren() do
							if
								not Seeking(seeking, creature)
								and creature:FindFirstChild("HitShell")
								and itemData[creature.Name].abductable
							then
								local a, c = ant.PrimaryPart, creature.PrimaryPart

								if not c then
									c = creature:FindFirstChildOfClass("BasePart")
								end

								local dist = (c.Position - a.Position).magnitude

								if dist < closestDist then
									nearestShelly = creature
									closestDist = dist
								end
							end
						end

						if ant and nearestShelly then
							activeAnts[ant].destination = nearestShelly.PrimaryPart.Position
							activeAnts[ant].target = nearestShelly
							table.insert(seeking, nearestShelly)

							activeAnts[ant].target.AncestryChanged:connect(function()
								activeAnts[ant].target = nil
							end)
						end
					else
						activeAnts[ant].destination = hill.PrimaryPart.Position + Vector3.new(0, 3, 0)
					end

					if activeAnts[ant].destination then
						ant.Hum:MoveTo(activeAnts[ant].destination)
						if not activeAnts[ant].anims.AntWalk.IsPlaying then
							activeAnts[ant].anims.AntWalk:Play()
						end

						if antData.target and not antData.carrying then
							local dist = (ant.PrimaryPart.Position - activeAnts[ant].target.PrimaryPart.Position).magnitude
							if dist < 5 then
								-- let's get a new shelly
								local abductedShelly = game.ServerStorage.Misc["Abducted Shelly"]:Clone()
								antData.carrying = abductedShelly
								abductedShelly.Shell.Material = antData.target.Shell.Material
								abductedShelly.Shell.Color = antData.target.Shell.Color
								abductedShelly.ActualName.Value = antData.target.Name
								--game.ReplicatedStorage.Events.NPCAttack:Fire(antData.target,math.huge)
								antData.target:Destroy()
								abductedShelly.Parent = ant
								activeAnts[ant].anims.AntWalk:Stop()
								activeAnts[ant].anims.AntHold:Play()
								ant.PrimaryPart.Chatter:Play()
								ant.PrimaryPart.ShellyAbduct:Play()
								-- weld the shelly to the torso
								local weld = Instance.new("ManualWeld")
								weld.Parent = ant.PrimaryPart
								weld.Part0 = ant.PrimaryPart
								weld.Part1 = abductedShelly.PrimaryPart
								weld.C0 = CFrame.new(-0.4, 0.4, -1.6) * CFrame.Angles(0, math.rad(90), 0)
							end
						elseif antData.carrying then
							local dist = (ant.PrimaryPart.Position - activeAnts[ant].destination).magnitude
							if dist < 7 then
								ant.Hum:MoveTo(ant.PrimaryPart.Position)
								ant.PrimaryPart.Chatter:Play()
								activeAnts[ant].anims.AntHold:Stop()
								activeAnts[ant].anims.AntWalk:Stop()
								activeAnts[ant].carrying:Destroy()
								activeAnts[ant].carrying = nil
								activeAnts[ant].destination = nil
								activeAnts[ant].target = nil
							end
						end
					end
				end
			end) --Help prevent breaking and faster responding times for ants.
		end --Shouldn't error now though.
	end
end)

manageAnts()
