--local functions
function weld(a, b, c0, c1)
	local w = Instance.new("Weld", a)
	w.Part0 = a
	w.Part1 = b
	if c0 then w.C0 = c0 end
	if c1 then w.C1 = c1 end
	return w
end

function setHeight(n)
	if ai.Model:findFirstChild("Right Leg") then
		ai.Model["Right Leg"]:BreakJoints()
		ai.Model["Right Leg"].Size = ai.Model["Right Leg"].Size * Vector3.new(1,0,1) + Vector3.new(0, math.max(0.2, n or 0),0)
		weld(ai.Model.Torso, ai.Model["Right Leg"], CFrame.new(0, -n + ai.Model["Right Leg"].Size.Y/2 - ai.Model.Torso.Size.Y/2,0))
	end
	if m and ai.Model:findFirstChild("Head") then
		ai.Model.Head:BreakJoints()
		weld(ai.Model.Torso, ai.Model.Head, CFrame.new(0, m - ai.Model.Head.Size.Y/2 + ai.Model.Torso.Size.Y/2,0))
	end
end

function objAhead(loc)
	if not _G.AntiJumpCache then
		_G.AntiJumpCache = {}
	end
	local ray = Ray.new(ai.Model.Torso.Position, ((loc - ai.Model.Torso.Position) * Vector3.new(1,0,1)).unit * 5)
	local obj, pos = workspace:FindPartOnRayWithIgnoreList(ray, _G.AntiJumpCache)
	if obj then
		if not obj.CanCollide then
			table.insert(_G.AntiJumpCache, obj)
		elseif obj.Parent:findFirstChild("Humanoid") then
			table.insert(_G.AntiJumpCache, obj.Parent)
		else
			return true
		end
		--add to cache if necessary, otherwise recurse
		return objAhead(loc)
	end
end

function ai.canSee(obj, fov)
	local direction = (obj.Position - ai.Model.Head.Position).unit
	if fov and direction:Dot(ai.Model.Head.CFrame.lookVector) < math.cos(math.rad(fov)) then
		return false
	end
	local ray = Ray.new(ai.Model.Head.Position, direction * 900)
	local hit, pos = workspace:FindPartOnRayWithIgnoreList(ray, {ai.Model})
	if hit then
		--add to cache if transparent?
		if hit == obj then
			return true	
		end
	end
end

function attack(hum)
	print("pow")
	lastAttack = time()
	hum:TakeDamage(atkDamage)
end

function initialize()
	for _, obj in pairs(ai.Model:GetChildren()) do
		if obj:IsA("BasePart") then
			obj.Anchored = false
		end			
	end
	setHeight(2, 1)
	ai.tWeld = weld(ai.Model.Torso, ai.Model.torso, CFrame.new(0,-1,0), CFrame.new(0,-1,0) * CFrame.Angles(math.rad(45),0,0))
	ai.hWeld = weld(ai.Model.torso, ai.Model.head2, CFrame.new(0,.8,0), CFrame.new(0,-.6,0) * CFrame.Angles(math.rad(-22.5),0,0))
	ai.lWeld1 = weld(ai.Model.torso, ai.Model.leftLeg, CFrame.new(-0.5,-1,0), CFrame.new(0,1,0) * CFrame.Angles(math.rad(-45),0,0))
	ai.lWeld2 = weld(ai.Model.torso, ai.Model.rightLeg, CFrame.new(0.5,-1,0), CFrame.new(0,1,0) * CFrame.Angles(math.rad(-45),0,0))
	ai.aWeld1 = weld(ai.Model.torso, ai.Model.leftArm, CFrame.new(-1,0.5,0), CFrame.new(0.5,0.5,0) * CFrame.Angles(math.rad(-45),0,0))
	ai.aWeld2 = weld(ai.Model.torso, ai.Model.rightArm, CFrame.new(1,0.5,0), CFrame.new(-0.5,0.5,0) * CFrame.Angles(math.rad(-45),0,0))
	ai.HWeld = weld(ai.Model.Torso, ai.Model.Head)
	anim(math.rad(20),0,0)
	ai.Humanoid = Instance.new("Humanoid", ai.Model)
	ai.Humanoid.WalkSpeed = math.random(8,14) + math.max(0, math.random(-5,3))
	ai.State = "Idle"
	ai.Model.ChildRemoved:connect(delete)
	ai.Humanoid.Died:connect(delete)
	ai.Humanoid.Running:connect(animate)
	table.insert(_G.aiTable, ai)
end

function delete()
	wait(0)
	if not ai.Humanoid or not (ai.Humanoid.Health > 0) or not ai.Model:findFirstChild("Torso") or not ai.Model:FindFirstChild("Head") or not ai.Model:FindFirstChild("head2") then
		for i, a in pairs(_G.aiTable) do
			if a == ai then
				table.remove(_G.aiTable, i)
			end
		end
		ai.Model:BreakJoints()
		game.Debris:AddItem(ai.Model, 3)
		for i, obj in pairs(ai.Model:GetChildren()) do
			if obj:IsA("BasePart") and obj.Transparency ~= 1 then
				obj.CanCollide = true
			elseif obj ~= script then
				obj:Destroy()
			end
		end
		ai = nil
		goalPos = nil
	elseif not (ai.Model:FindFirstChild("leftLeg") and ai.Model:FindFirstChild("rightLeg")) and not crawling then
		crawl()
	end
	if ai and crawling and not (ai.Model:FindFirstChild("leftArm") and ai.Model:FindFirstChild("rightArm")) then
		ai.Humanoid.Health = 0
	end
end

function animate(a)
	if not running2 then
		running = a > 0
		if running then
			Spawn(function()
				running2 = true
				local start = time()
				while running do
					wait(0)
					local cycle = (tick() - start) * 5
					local tPitch = math.rad(25 + math.cos(cycle * 2) * -5)
					local tRoll = math.rad(math.sin(cycle) * 10)
					local lPitch = math.rad(math.sin(cycle) * 45)
					anim(tPitch, tRoll, lPitch)
				end
				running2 = false
				anim(math.rad(20),0,0)
			end)
		end
	else
		running = a > 0
	end
end

function anim(tPitch, tRoll, lPitch)
	if not ai then return end
	local crawlMod = crawling and math.rad(50) or 0
	local crawlMod2 = crawling and 4 or 1
	local attackMod = (attackTime - math.min(attackTime,(time() - lastAttack)))/attackTime * math.rad(140)
	lPitch2 = crawling and lPitch / 3 or lPitch
	if ai.tWeld then
		ai.tWeld.C1 =  CFrame.new(0,-1,0) * CFrame.Angles(tPitch + crawlMod,0,tRoll + limp[1] * .4)
	end
	if ai.hWeld then
		ai.hWeld.C1 =  CFrame.new(0,-0.6,0) * CFrame.Angles(-tPitch/2,0,tRoll + limp[2] * .4)
	end
	if ai.lWeld1 then
		ai.lWeld1.C1 = CFrame.new(0,1,0) * CFrame.Angles(lPitch2 - tPitch + crawlMod + limp[3] * .4,0,-tRoll - limp[1] * .4)
	end
	if ai.lWeld2 then
		ai.lWeld2.C1 = CFrame.new(0,1,0) * CFrame.Angles(-lPitch2 - tPitch + crawlMod + limp[4] * .4,0,-tRoll - limp[1] * .4)
	end
	if ai.aWeld1 then
		ai.aWeld1.C1 =  CFrame.new(0.5,0.5,0) * CFrame.Angles(0,0, crawlMod/2) * CFrame.Angles(lPitch * math.abs(limp[5]) * -0.4 * crawlMod2 - tPitch - crawlMod - attackMod + limp[5] * .2, 0, -tRoll - limp[1] * .4)
	end
	if ai.aWeld2 then
		ai.aWeld2.C1 =  CFrame.new(-0.5,0.5,0) * CFrame.Angles(0,0, -crawlMod/2) * CFrame.Angles(lPitch * math.abs(limp[6]) * 0.4 * crawlMod2 - tPitch - crawlMod - attackMod + limp[6] * .2, 0, -tRoll  - limp[1] * .4)
	end
	if ai.HWeld and ai.Model:findFirstChild("head2") then
		ai.HWeld.C0 = ai.Model.Torso.CFrame:toObjectSpace(ai.Model.head2.CFrame)
	end
end

function crawl()
	crawling = true
	setHeight(0,0)
	ai.Humanoid.WalkSpeed = math.random(4, 6)
end

while not _G.aiTable do
	wait(0)
end
initialize()