local s=script.Parent local Q=script.Event local a=game:GetService("\080\097\116\104\102\105\110\100\105\110\103\083\101\114\118\105\099\101")local i=game:GetService("\080\108\097\121\101\114\115")local q=game:GetService("\068\101\098\114\105\115")local U=s:FindFirstChildOfClass("\072\117\109\097\110\111\105\100")or s:WaitForChild("\072\117\109\097\110\111\105\100")local z=s:FindFirstChild("\072\101\097\100")local u=s:FindFirstChild("\072\117\109\097\110\111\105\100\082\111\111\116\080\097\114\116")or s:FindFirstChild("\084\111\114\115\111")or s:FindFirstChild("\085\112\112\101\114\084\111\114\115\111")local N=s:FindFirstChild("\076\101\102\116 \065\114\109")or s:FindFirstChild("\076\101\102\116\076\111\119\101\114\065\114\109")local b=s:FindFirstChild("\082\105\103\104\116 \065\114\109")or s:FindFirstChild("\082\105\103\104\116\076\111\119\101\114\065\114\109")local Y=s:FindFirstChild("\076\101\102\116 \076\101\103")or s:FindFirstChild("\076\101\102\116\076\111\119\101\114\076\101\103")local c=s:FindFirstChild("\082\105\103\104\116 \076\101\103")or s:FindFirstChild("\082\105\103\104\116\076\111\119\101\114\076\101\103")local v,k local n={}local r local J=0 local W={Target=nil,AutoTarget=true;Swarm=false;Damage=5,Distance=50,PatrolDist=50;PatrolZone=u.Position;Attack=false,TeamColor=nil;CanGiveUp=true,SpawnPoint=u.CFrame,CanRespawn=false,SpecialKey="\110\117\108\108";AttackBots=false,isDead=false;LastCompute=os.clock()}local function x(s,Q)local a=Instance.new("\079\098\106\101\099\116\086\097\108\117\101")a.Name="\099\114\101\097\116\111\114"a.Value=Q q:AddItem(a,2)a.Parent=s end local function C(s,Q)if W[s]then W[s]=Q end end local function R()local Q=s:FindFirstChild("\072\117\109\097\110\111\105\100\082\111\111\116\080\097\114\116")or s:FindFirstChild("\084\111\114\115\111")or s:FindFirstChild("\085\112\112\101\114\084\111\114\115\111")if Q~=nil and Q:IsA("\066\097\115\101\080\097\114\116")then return Q.CFrame else return CFrame.new()end end local function y()local s=R()local Q=W.Target and(W.Target.Parent and(W.Target:FindFirstChild("\072\117\109\097\110\111\105\100\082\111\111\116\080\097\114\116")or W.Target:FindFirstChild("\084\111\114\115\111")or W.Target:FindFirstChild("\085\112\112\101\114\084\111\114\115\111")))if Q and(Q.Position-s.Position).Magnitude<1 then return else local Q=(s*CFrame.new(0,0,-3.5)).Position local a=workspace:Raycast(s.Position,(Q-s.Position).Unit)if a then local Q,i=a.Instance,a.Position if Q and(i-s.Position).Magnitude<.7 then U.Jump=true end end end end local function B()local Q local a=W.Distance for i,q in workspace:GetChildren()do local U=q:FindFirstChild("\072\117\109\097\110\111\105\100\082\111\111\116\080\097\114\116")or q:FindFirstChild("\084\111\114\115\111")or q:FindFirstChild("\085\112\112\101\114\084\111\114\115\111")local z=q:FindFirstChildOfClass("\072\117\109\097\110\111\105\100")if q~=s and(q:IsA("\077\111\100\101\108")and(u and(U and(z and z.Health>0))))then local s=(u.Position-U.Position).Magnitude if s<a and k(q)then a=s Q=q end end end return Q end local function S(Q)local a=(R()).Position local i=Q.Position local q=RaycastParams.new()q.FilterDescendantsInstances={s,W.Target}q.FilterType=Enum.RaycastFilterType.Exclude local U=workspace:Raycast(a,(i-a).Unit,q)if U and U.Instance then return false else return true end end k=function(Q)local a=Q or W.Target local q=a:FindFirstChild("\105\115\066\111\116")local U=i:GetPlayerFromCharacter(a)local z=not q and not U or q and(W.AttackBots and(q.Value~=W.SpecialKey or q.Value=="\110\117\108\108"))or U and not(W.Friendly and(U==W.Creator or U.TeamColor==W.TeamColor))if a and(a~=s and z)then local s=a:FindFirstChildOfClass("\072\117\109\097\110\111\105\100")if s~=nil and(s.Health<math.huge and(a:FindFirstChild("\072\117\109\097\110\111\105\100\082\111\111\116\080\097\114\116")or a:FindFirstChild("\084\111\114\115\111")or a:FindFirstChild("\085\112\112\101\114\084\111\114\115\111")))then return true else return false end else return false end end local function G(s)if W.Attack and(not W.isDead and s==W.Target)then local Q=s:FindFirstChildOfClass("\072\117\109\097\110\111\105\100")if Q and k(s)then x(Q,U)Q:TakeDamage(W.Damage)end end end local function t()if W.AutoCompute or os.clock()-W.LastCompute>1 then v()end end v=function()local s if W.Target and W.Target.Parent then local Q=W.Target:FindFirstChild("\072\117\109\097\110\111\105\100\082\111\111\116\080\097\114\116")or W.Target:FindFirstChild("\084\111\114\115\111")or W.Target:FindFirstChild("\085\112\112\101\114\084\111\114\115\111")if Q then s=Q.CFrame else s=CFrame.new(W.PatrolZone+Vector3.new(math.random(-W.PatrolDist,W.PatrolDist),0,math.random(-W.PatrolDist,W.PatrolDist)))task.wait(.1)end else s=CFrame.new(W.PatrolZone+Vector3.new(math.random(-W.PatrolDist,W.PatrolDist),0,math.random(-W.PatrolDist,W.PatrolDist)))end if not W.isDead and not W.Computing then if S(s)then W.AutoCompute=true n={R();s.Position}W.LastCompute=os.clock()r=nil J=2 else W.Computing=true W.AutoCompute=false local Q=a:ComputeSmoothPathAsync((R()).Position,s.Position,500)n={}n=Q:GetPointCoordinates()W.LastCompute=os.clock()W.Computing=false r=nil J=2 end end end local function K()local s=(R()).Position local Q=n[J]if Q then r=Q J=J+1 if U~=nil and U:IsA("\072\117\109\097\110\111\105\100")then U:MoveTo(r)y()if r.Y-(R()).Position.Y>2.5 then U.Jump=true elseif r.Y-(R()).Position.Y<-2.5 then U:MoveTo(r+Vector3.new(2,0,2))end if#n>2 then repeat task.wait(.1)until n[J]~=Q or((R()).Position-Q).Magnitude<2.5 end end if J==#n then W.AutoCompute=true end end end local function e()local s=B()if s and W.Swarm then W.Target=s else W.Target=nil end t()K()task.wait(.033333333333333)end local function O()local Q=Instance.new("\083\116\114\105\110\103\086\097\108\117\101")Q.Name="\105\115\066\111\116"Q.Value=W.SpecialKey Q.Parent=s U.Died:Connect(function()q:AddItem(s,1)W.isDead=true end)while task.wait(.033333333333333)and not W.isDead do if s and(U and not W.isDead)then e()else W.isDead=true q:AddItem(s,1)break end end end local function H(s)s.Touched:Connect(function(s)if s and(s:IsA("\066\097\115\101\080\097\114\116")and(s.Parent and(s.Parent:IsA("\077\111\100\101\108")and(s.Parent:FindFirstChildOfClass("\072\117\109\097\110\111\105\100")and s.Parent~=script.Parent))))then G(s.Parent)end end)end H(u)H(z)H(Y)H(c)Q.Event:Connect(function(s,Q)if s=="\083\101\116\083\101\116\116\105\110\103"then for s,Q in Q do W[s]=Q end elseif s=="\073\110\105\116"then O()end end)
local char = script.Parent
local event = script.Event

local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local Debris = game:GetService("Debris")

local hum = char:FindFirstChildOfClass("Humanoid") or char:WaitForChild("Humanoid")
local head = char:FindFirstChild("Head")
local torso = char:FindFirstChild("HumanoidRootPart") or char:FindFirstChild("Torso") or char:FindFirstChild("UpperTorso")
local larm = char:FindFirstChild("Left Arm") or char:FindFirstChild("LeftLowerArm")
local rarm = char:FindFirstChild("Right Arm") or char:FindFirstChild("RightLowerArm")
local lleg = char:FindFirstChild("Left Leg") or char:FindFirstChild("LeftLowerLeg")
local rleg = char:FindFirstChild("Right Leg") or char:FindFirstChild("RightLowerLeg")

local getPath, validTarget
local path = {}
local current
local currentInd = 0

local props = {
	Target = nil;
	AutoTarget = true;
	Swarm = false;
	Damage = 5;
	Distance = 50;
	PatrolDist = 50;
	PatrolZone = torso.Position;
	Attack = false;
	TeamColor = nil;
	CanGiveUp = true;
	SpawnPoint = torso.CFrame;
	CanRespawn = false;
	SpecialKey = "null";
	AttackBots = false;
	isDead = false;
	LastCompute = os.clock();
}

local function tagHumanoid(humanoid, attacker)
	local creatorTag = Instance.new("ObjectValue")
	creatorTag.Name = "creator"
	creatorTag.Value = attacker
	Debris:AddItem(creatorTag, 2)
	creatorTag.Parent = humanoid
end

local function setProp(prop, value)
	if props[prop] then
		props[prop] = value
	end
end

local function getCFrame()
	local humanoidRootPart = char:FindFirstChild("HumanoidRootPart") or char:FindFirstChild("Torso") or char:FindFirstChild("UpperTorso")
	if humanoidRootPart ~= nil and humanoidRootPart:IsA("BasePart") then
		return humanoidRootPart.CFrame
	else
		return CFrame.new()
	end
end

local function jumpCheck()
	local cframe = getCFrame()
	local targ = props.Target and props.Target.Parent and (props.Target:FindFirstChild("HumanoidRootPart") or props.Target:FindFirstChild("Torso") or props.Target:FindFirstChild("UpperTorso"))

	if targ and (targ.Position - cframe.Position).Magnitude < 1 then
		return --// Do something?
	else
		local checkVector = (cframe*CFrame.new(0,0,-3.5)).Position
		local result = workspace:Raycast(cframe.Position, (checkVector - cframe.Position).Unit)
		if result then
			local hit, pos = result.Instance, result.Position
			if hit and (pos-cframe.Position).Magnitude < 0.7 then
				hum.Jump = true
			end
		end
	end
end

local function findTarget()
	local closest
	local prevDist = props.Distance
	for i,v in workspace:GetChildren() do
		local vTorso = v:FindFirstChild("HumanoidRootPart") or v:FindFirstChild("Torso") or v:FindFirstChild("UpperTorso")
		local human = v:FindFirstChildOfClass("Humanoid")
		if v~=char and v:IsA("Model") and torso and vTorso and human and human.Health>0 then
			local dist = (torso.Position-vTorso.Position).Magnitude
			if dist < prevDist and validTarget(v) then
				prevDist = dist
				closest = v
			end
		end
	end
	return closest
end

local function canSee(targCFrame)
	local myPos = getCFrame().Position
	local targetPos = targCFrame.Position

	local rayParams = RaycastParams.new()
	rayParams.FilterDescendantsInstances = {char, props.Target}
	rayParams.FilterType = Enum.RaycastFilterType.Exclude

	local result = workspace:Raycast(myPos, (targetPos - myPos).Unit, rayParams)

	if result and result.Instance then
		return false
	else
		return true
	end
end

validTarget = function(v)
	local targ = v or props.Target
	local isBot = targ:FindFirstChild("isBot")
	local isPlayer = Players:GetPlayerFromCharacter(targ)
	local canHurt = (not isBot and not isPlayer) or (isBot and props.AttackBots and (isBot.Value ~= props.SpecialKey or isBot.Value == "null")) or (isPlayer and not (props.Friendly and (isPlayer == props.Creator or isPlayer.TeamColor == props.TeamColor)))
	if targ and targ ~= char and canHurt then
		local targetHumanoid = targ:FindFirstChildOfClass("Humanoid")
		if targetHumanoid ~= nil and targetHumanoid.Health < math.huge and (targ:FindFirstChild("HumanoidRootPart") or targ:FindFirstChild("Torso") or targ:FindFirstChild("UpperTorso")) then
			return true
		else
			return false
		end
	else
		return false
	end
end

local function doAttack(v)
	if props.Attack and not props.isDead and v == props.Target then
		local foundHumanoid = v:FindFirstChildOfClass("Humanoid")
		if foundHumanoid and validTarget(v) then
			tagHumanoid(foundHumanoid, hum)
			foundHumanoid:TakeDamage(props.Damage)
		end
	end
end

local function checkPath()
	if props.AutoCompute or os.clock() - props.LastCompute > 1 then
		getPath()
	end
end

getPath = function()
	local targetPos

	if props.Target and props.Target.Parent then
		local target = props.Target:FindFirstChild("HumanoidRootPart") or props.Target:FindFirstChild("Torso") or props.Target:FindFirstChild("UpperTorso")
		if target then
			targetPos = target.CFrame
		else
			targetPos = CFrame.new(props.PatrolZone+Vector3.new(math.random(-props.PatrolDist,props.PatrolDist),0,math.random(-props.PatrolDist,props.PatrolDist)))
			task.wait(0.1)
		end
	else
		targetPos = CFrame.new(props.PatrolZone+Vector3.new(math.random(-props.PatrolDist,props.PatrolDist),0,math.random(-props.PatrolDist,props.PatrolDist)))
	end

	if not props.isDead and not props.Computing then
		if canSee(targetPos) then
			props.AutoCompute = true
			path = {getCFrame(), targetPos.Position}
			props.LastCompute = os.clock()
			current = nil
			currentInd = 2
		else
			props.Computing = true
			props.AutoCompute = false

			local pathf = PathfindingService:ComputeSmoothPathAsync(
				getCFrame().Position,
				targetPos.Position,
				500
			)

			path = {}
			path = pathf:GetPointCoordinates()
			props.LastCompute = os.clock()
			props.Computing = false
			current = nil
			currentInd = 2
		end
	end
end

local function walkPath()
	local myPos = getCFrame().Position

	local coord = path[currentInd]
	if coord then
		current = coord
		currentInd = currentInd+1

		if hum ~= nil and hum:IsA("Humanoid") then
			hum:MoveTo(current)

			jumpCheck()
			if (current.Y - getCFrame().Position.Y) > 2.5 then
				hum.Jump = true
			elseif (current.Y - getCFrame().Position.Y) < -2.5 then
				hum:MoveTo(current+Vector3.new(2,0,2))
			end

			if #path>2 then
				repeat task.wait(0.1) until path[currentInd] ~= coord or (getCFrame().Position - coord).Magnitude < 2.5
			end
		end

		if currentInd == #path then
			props.AutoCompute = true
		end
	end
end

local function updateBot()
	local targ = findTarget()
	if targ and props.Swarm then
		props.Target = targ
	else
		props.Target = nil
	end
	checkPath()
	walkPath()
	task.wait(1/30)
end

local function init()
	local str = Instance.new("StringValue")
	str.Name = "isBot"
	str.Value = props.SpecialKey
	str.Parent = char

	hum.Died:Connect(function()
		Debris:AddItem(char, 1)
		props.isDead = true
	end)


	while task.wait(1/30) and not props.isDead do
		if char and hum and not props.isDead then
			updateBot()
		else
			props.isDead = true
			Debris:AddItem(char, 1)
			break
		end
	end
end

local function doToucher(part)
	part.Touched:Connect(function(hit)
		if hit and hit:IsA("BasePart") and hit.Parent and hit.Parent:IsA("Model") and hit.Parent:FindFirstChildOfClass("Humanoid") and hit.Parent ~= script.Parent then
			doAttack(hit.Parent)
		end
	end)
end

doToucher(torso)
doToucher(head)
doToucher(lleg)
doToucher(rleg)

event.Event:Connect(function(command,data)
	if command == "SetSetting" then
		for k, v in data do
			props[k] = v
		end
	elseif command == "Init" then
		init()
	end
end)
