local U={}local F=require(script.Parent.Parent:WaitForChild("\067\111\110\102\105\103\117\114\097\116\105\111\110"))local i=F.PhysicsSolver.GRAVITY local A=F.PhysicsSolver.USE_FALLING_SIMULATION local y=(game:GetService("\087\111\114\107\115\112\097\099\101")).FallenPartsDestroyHeight local d=game:GetService("\082\117\110\083\101\114\118\105\099\101")local r=require(script.Parent:WaitForChild("\085\116\105\108"))local S=Vector3.new function U.CreateSolver(F,U)local z=true local c={}local C=U.CharacterModel:WaitForChild("\072\101\097\100")local h,Y local function D()h=U.CharacterModel:FindFirstChild("\076\101\102\116\070\111\111\116")Y=U.CharacterModel:FindFirstChild("\082\105\103\104\116\070\111\111\116")end D()local N local m,V=0,0 function c.SetNewContext(F,U)N=U+S(0,4,0)m=N.Y end function c.SetEnabled(F,U)z=U end local G=S(0,-500,0)if i>0 then G=S(0,500,0)end local a=Vector3.new(0,2,0)local k if A then local F=0 k=d.RenderStepped:Connect(function(A)if z then local d,S if N then d,S=r:FindCollidablePartOnRay(N,G,U.CharacterModel)D()elseif h and Y then local F=h.Position+a local i=Y.Position+a local A,y=r:FindCollidablePartOnRay(F,G,U.CharacterModel)local z,c=r:FindCollidablePartOnRay(i,G,U.CharacterModel)if y.Y>c.Y then d,S=A,y else d,S=z,c end elseif h then local F=h.Position+a d,S=r:FindCollidablePartOnRay(F,G,U.CharacterModel)D()elseif Y then local F=Y.Position+a d,S=r:FindCollidablePartOnRay(F,G,U.CharacterModel)D()else local F=C.Position d,S=r:FindCollidablePartOnRay(F,G,U.CharacterModel)D()end local c=S.Y F=F+i*A local V=m+F if V>c then m=V else F=0 m=c end U:SetWorldYOffset(m)if N then N=nil end if m<y then z=false U.Humanoid.Health=0 end end end)else k=d.RenderStepped:Connect(function()if z then local F,i if N then F,i=r:FindCollidablePartOnRay(N,G,U.CharacterModel)D()elseif h and Y then local A=h.Position+a local y=Y.Position+a local d,S=r:FindCollidablePartOnRay(A,G,U.CharacterModel)local z,c=r:FindCollidablePartOnRay(y,G,U.CharacterModel)if S.Y>c.Y then F,i=d,S else F,i=z,c end elseif h then local A=h.Position+a F,i=r:FindCollidablePartOnRay(A,G,U.CharacterModel)D()elseif Y then local A=Y.Position+a F,i=r:FindCollidablePartOnRay(A,G,U.CharacterModel)D()else local A=C.Position F,i=r:FindCollidablePartOnRay(A,G,U.CharacterModel)D()end if F then m=i.Y end U:SetWorldYOffset(m)if N then N=nil end if m<y then z=false U.Humanoid.Health=0 end end end)end function c.Disconnect(U)k:Disconnect()end return c end return U


local PhysicsSolver = {}



local Configuration = require(script.Parent.Parent:WaitForChild("Configuration"))
local GRAVITY = Configuration.PhysicsSolver.GRAVITY
local USE_FALLING_SIMULATION = Configuration.PhysicsSolver.USE_FALLING_SIMULATION
local DESTROY_HEIGHT = game:GetService("Workspace").FallenPartsDestroyHeight

local RunService = game:GetService("RunService")
local Util = require(script.Parent:WaitForChild("Util"))

local V3new = Vector3.new



function PhysicsSolver:CreateSolver(CharacterClass)
	local Enabled = true
	local PhysicsSolverClass = {}
	local Head = CharacterClass.CharacterModel:WaitForChild("Head")
	local LeftFoot,RightFoot
	local function UpdateFeet()
		LeftFoot = CharacterClass.CharacterModel:FindFirstChild("LeftFoot")
		RightFoot = CharacterClass.CharacterModel:FindFirstChild("RightFoot")
	end
	UpdateFeet()
	
	local OverridePos
	local LastY,LastTargetY = 0,0
	function PhysicsSolverClass:SetNewContext(NewOverridePos)
		OverridePos = NewOverridePos + V3new(0,4,0)
		LastY = OverridePos.Y
	end
	
	function PhysicsSolverClass:SetEnabled(NewEnabled)
		Enabled = NewEnabled
	end
	
	local DownDirection500 = V3new(0,-500,0)
	if GRAVITY > 0 then
		DownDirection500 = V3new(0,500,0)
	end
	
	local FootOffset = Vector3.new(0,2,0)
	local SolverEvent
	if USE_FALLING_SIMULATION then
		local Velocity = 0
		
		SolverEvent = RunService.RenderStepped:Connect(function(DeltaTime)
			if Enabled then
				local EndPart,BottomPos
				if OverridePos then
					EndPart,BottomPos = Util:FindCollidablePartOnRay(OverridePos,DownDirection500,CharacterClass.CharacterModel)
					UpdateFeet()
				elseif LeftFoot and RightFoot then
					local LeftFootPos = LeftFoot.Position + FootOffset
					local RightFootPos = RightFoot.Position + FootOffset
					
					local LeftEndPart,LeftBottomPos = Util:FindCollidablePartOnRay(LeftFootPos,DownDirection500,CharacterClass.CharacterModel)
					local RightEndPart,RightBottomPos = Util:FindCollidablePartOnRay(RightFootPos,DownDirection500,CharacterClass.CharacterModel)
					
					if LeftBottomPos.Y > RightBottomPos.Y then
						EndPart,BottomPos = LeftEndPart,LeftBottomPos
					else
						EndPart,BottomPos = RightEndPart,RightBottomPos
					end
				elseif LeftFoot then
					local LeftFootPos = LeftFoot.Position + FootOffset
					EndPart,BottomPos = Util:FindCollidablePartOnRay(LeftFootPos,DownDirection500,CharacterClass.CharacterModel)
					UpdateFeet()					
				elseif RightFoot then
					local RightFootPos = RightFoot.Position + FootOffset
					EndPart,BottomPos = Util:FindCollidablePartOnRay(RightFootPos,DownDirection500,CharacterClass.CharacterModel)
					UpdateFeet()
				else
					local HeadPos = Head.Position
					EndPart,BottomPos = Util:FindCollidablePartOnRay(HeadPos,DownDirection500,CharacterClass.CharacterModel)
					UpdateFeet()
				end
				
				local EndY = BottomPos.Y
				Velocity = Velocity + (GRAVITY * DeltaTime)
				local DestinationY = LastY + Velocity	
				
				if DestinationY > EndY then			
					LastY = DestinationY
				else
					Velocity = 0
					LastY = EndY	
				end	
				CharacterClass:SetWorldYOffset(LastY)
				
				if OverridePos then
					OverridePos = nil
				end
				
				if LastY < DESTROY_HEIGHT then
					Enabled = false
					CharacterClass.Humanoid.Health = 0
				end
			end
		end)
	else
		SolverEvent = RunService.RenderStepped:Connect(function()
			if Enabled then
				local EndPart,BottomPos
				if OverridePos then
					EndPart,BottomPos = Util:FindCollidablePartOnRay(OverridePos,DownDirection500,CharacterClass.CharacterModel)
					UpdateFeet()
				elseif LeftFoot and RightFoot then
					local LeftFootPos = LeftFoot.Position + FootOffset
					local RightFootPos = RightFoot.Position  + FootOffset
					
					local LeftEndPart,LeftBottomPos = Util:FindCollidablePartOnRay(LeftFootPos,DownDirection500,CharacterClass.CharacterModel)
					local RightEndPart,RightBottomPos = Util:FindCollidablePartOnRay(RightFootPos,DownDirection500,CharacterClass.CharacterModel)
					
					if LeftBottomPos.Y > RightBottomPos.Y then
						EndPart,BottomPos = LeftEndPart,LeftBottomPos
					else
						EndPart,BottomPos = RightEndPart,RightBottomPos
					end
				elseif LeftFoot then
					local LeftFootPos = LeftFoot.Position + FootOffset
					EndPart,BottomPos = Util:FindCollidablePartOnRay(LeftFootPos,DownDirection500,CharacterClass.CharacterModel)
					UpdateFeet()					
				elseif RightFoot then
					local RightFootPos = RightFoot.Position + FootOffset
					EndPart,BottomPos = Util:FindCollidablePartOnRay(RightFootPos,DownDirection500,CharacterClass.CharacterModel)
					UpdateFeet()
				else
					local HeadPos = Head.Position
					EndPart,BottomPos = Util:FindCollidablePartOnRay(HeadPos,DownDirection500,CharacterClass.CharacterModel)
					UpdateFeet()
				end
				
				if EndPart then			
					LastY = BottomPos.Y		
				end	
				CharacterClass:SetWorldYOffset(LastY)
				
				if OverridePos then
					OverridePos = nil
				end
				
				if LastY < DESTROY_HEIGHT then
					Enabled = false
					CharacterClass.Humanoid.Health = 0
				end
			end
		end)
	end
	
	function PhysicsSolverClass:Disconnect()
		SolverEvent:Disconnect()
	end
	
	return PhysicsSolverClass
end

return PhysicsSolver
