local q=game:GetService("\085\115\101\114\073\110\112\117\116\083\101\114\118\105\099\101")local w=require(game.ReplicatedStorage.ModelLoader)local D=require(game.ReplicatedStorage.Weld)function KeysToStrings(q)local w={}for q,D in pairs(q)do table.insert(w,D.KeyCode.Name)end return w end function AreKeysDown(w)task.synchronize()local D=0 for w,s in pairs(w)do if q:IsKeyDown(Enum.KeyCode[s])then D+=1 end end task.desynchronize()if D>0 then return true else return false end end function V3Clamp(q,w,D)return Vector3.new(math.clamp(q.X,w,D),math.clamp(q.Y,w,D),math.clamp(q.Z,w,D))end local s={}function MakeCharacter()local q={}local s=w.LoadFromName("\067\117\098\101")s.Size=Vector3.new(2,1,1)s:SetColor(255,255,0)s.Name="\072\101\097\100"s.CanCollide=false s.Anchored=false q.Head=s local e=w.LoadFromName("\067\117\098\101")e.Size=Vector3.new(2,2,1)e:SetColor(165,165,165)e.Rendered=true e.CFrame=CFrame.new(0,3,0)e.Name="\072\117\109\097\110\111\105\100\082\111\111\116\080\097\114\116"e.PhysicsMover.Offset=Vector3.new(0,-2,0)e.Anchored=false q.HumanoidRootPart=e local B=w.LoadFromName("\067\117\098\101")B.Size=Vector3.new(2,2,1)B:SetColor(0,165,255)B.Name="\084\111\114\115\111"B.CanCollide=false B.Anchored=false q.Torso=B local g=w.LoadFromName("\067\117\098\101")g.Size=Vector3.new(1,2,1)g:SetColor(255,255,0)g.Name="\082\105\103\104\116 \065\114\109"g.CanCollide=false g.Anchored=false q["\082\105\103\104\116 \065\114\109"]=g local t=w.LoadFromName("\067\117\098\101")t.Size=Vector3.new(1,2,1)t:SetColor(255,255,0)t.Name="\076\101\102\116 \065\114\109"t.CanCollide=false t.Anchored=false q["\076\101\102\116 \065\114\109"]=t local M=w.LoadFromName("\067\117\098\101")M.Size=Vector3.new(1,2,1)M:SetColor(0,165,0)M.Name="\082\105\103\104\116 \076\101\103"M.CanCollide=false M.Anchored=false q["\082\105\103\104\116 \076\101\103"]=M local L=w.LoadFromName("\067\117\098\101")L.Size=Vector3.new(1,2,1)L:SetColor(0,165,0)L.Name="\076\101\102\116 \076\101\103"L.CanCollide=false L.Anchored=false q["\076\101\102\116 \076\101\103"]=L q.PrimaryPart=q.HumanoidRootPart local Z=D.new("\082\111\111\116\074\111\105\110\116",e,B,CFrame.new(0,0,0),CFrame.new(0,0,0))local W=D.new("\078\101\099\107",B,s,CFrame.new(0,1,0),CFrame.new(0,-0.5,0))local j=D.new("\082\105\103\104\116\083\104\111\117\108\100\101\114",B,g,CFrame.new(1,.5,0),CFrame.new(-0.5,.5,0))local i=D.new("\076\101\102\116\083\104\111\117\108\100\101\114",B,t,CFrame.new(-1,.5,0),CFrame.new(.5,.5,0))local K=D.new("\082\105\103\104\116\072\105\112",B,M,CFrame.new(1,-1,0),CFrame.new(.5,1,0))local a=D.new("\076\101\102\116\072\105\112",B,L,CFrame.new(-1,-1,0),CFrame.new(-0.5,1,0))q.HumanoidRootPart.RootJoint=Z q.Torso.Neck=W q.Torso["\082\105\103\104\116 \083\104\111\117\108\100\101\114"]=j q.Torso["\076\101\102\116 \083\104\111\117\108\100\101\114"]=i q.Torso["\082\105\103\104\116 \072\105\112"]=K q.Torso["\076\101\102\116 \072\105\112"]=a q.BaseWelds=D:GetBaseWelds()return q end function s.new(w,s)local e={}e.Character=MakeCharacter()e.CurrentCamera=w e.CameraSubject=e.Character.PrimaryPart e.CameraOffset=Vector3.new(0,5,7)e.CameraRot=Vector3.new(0,0,0)e.Speed=s e.Walking=false e.Jump=true e.OnGround=true e.Animation="\073\100\108\101"e.Sine=0 function e.PlayAnimation(w,q)local D=e.Character.Torso["\082\105\103\104\116 \083\104\111\117\108\100\101\114"]local s=e.Character.Torso["\076\101\102\116 \083\104\111\117\108\100\101\114"]local B=e.Character.Torso["\082\105\103\104\116 \072\105\112"]local g=e.Character.Torso["\076\101\102\116 \072\105\112"]if q=="\087\097\108\107"then task.spawn(function()if e.Animation~=q then e.Animation=q while e.Animation==q do D.C0=e.Character.BaseWelds.RightShoulder.C0*CFrame.Angles(math.rad(math.sin(e.Sine/6)*40),0,0)s.C0=e.Character.BaseWelds.LeftShoulder.C0*CFrame.Angles(-math.rad(math.sin(e.Sine/6)*40),0,0)B.C0=e.Character.BaseWelds.RightHip.C0*CFrame.Angles(-math.rad(math.sin(e.Sine/6)*40),0,0)g.C0=e.Character.BaseWelds.LeftHip.C0*CFrame.Angles(math.rad(math.sin(e.Sine/6)*40),0,0)e.Sine+=1 task.wait()end e.Animation="\073\100\108\101"end end)elseif q=="\073\100\108\101"then e.Animation="\073\100\108\101"D.C0=e.Character.BaseWelds.RightShoulder.C0 s.C0=e.Character.BaseWelds.LeftShoulder.C0 B.C0=e.Character.BaseWelds.RightHip.C0 g.C0=e.Character.BaseWelds.LeftHip.C0 e.Sine=0 elseif q=="\074\117\109\112"then e.Animation="\074\117\109\112"D.C0=e.Character.BaseWelds.RightShoulder.C0*CFrame.Angles(math.rad(180),0,0)s.C0=e.Character.BaseWelds.LeftShoulder.C0*CFrame.Angles(math.rad(180),0,0)B.C0=e.Character.BaseWelds.RightHip.C0 g.C0=e.Character.BaseWelds.LeftHip.C0 end end function e.Movement(w)task.synchronize()local D=KeysToStrings(q:GetKeysPressed())local s=q:GetMouseButtonsPressed()task.desynchronize()local B={"\087";"\065";"\083";"\068"}local g={"\076\101\102\116";"\082\105\103\104\116","\085\112","\068\111\119\110"}for w,D in pairs(B)do task.synchronize()if q:IsKeyDown(Enum.KeyCode[D])then if D=="\087"then e.Character.PrimaryPart.CFrame=CFrame.new(e.Character.PrimaryPart.Position+e.Character.PrimaryPart.Velocity/e.Character.PrimaryPart.Mass)*CFrame.Angles(0,math.rad(e.CameraRot.Y),0)e.Character.PrimaryPart.Velocity=Vector3.new(0,e.Character.PrimaryPart.Velocity.Y,0)e.Character.PrimaryPart.Velocity+=e.Character.PrimaryPart.CFrame.LookVector*30 elseif D=="\083"then e.Character.PrimaryPart.CFrame=CFrame.new(e.Character.PrimaryPart.Position+e.Character.PrimaryPart.Velocity/e.Character.PrimaryPart.Mass)*CFrame.Angles(0,math.rad(180+e.CameraRot.Y),0)e.Character.PrimaryPart.Velocity=Vector3.new(0,e.Character.PrimaryPart.Velocity.Y,0)e.Character.PrimaryPart.Velocity+=e.Character.PrimaryPart.CFrame.LookVector*30 elseif D=="\065"then e.Character.PrimaryPart.CFrame=CFrame.new(e.Character.PrimaryPart.Position+e.Character.PrimaryPart.Velocity/e.Character.PrimaryPart.Mass)*CFrame.Angles(0,math.rad(90+e.CameraRot.Y),0)e.Character.PrimaryPart.Velocity=Vector3.new(0,e.Character.PrimaryPart.Velocity.Y,0)e.Character.PrimaryPart.Velocity+=e.Character.PrimaryPart.CFrame.LookVector*30 elseif D=="\068"then e.Character.PrimaryPart.CFrame=CFrame.new(e.Character.PrimaryPart.Position+e.Character.PrimaryPart.Velocity/e.Character.PrimaryPart.Mass)*CFrame.Angles(0,math.rad(-90+e.CameraRot.Y),0)e.Character.PrimaryPart.Velocity=Vector3.new(0,e.Character.PrimaryPart.Velocity.Y,0)e.Character.PrimaryPart.Velocity+=e.Character.PrimaryPart.CFrame.LookVector*30 end e.Walking=true if e.Animation~="\074\117\109\112"then e:PlayAnimation("\087\097\108\107")end end task.desynchronize()end task.synchronize()if not AreKeysDown(B)and e.Walking==true then e.Walking=false e.Character.PrimaryPart.Velocity=Vector3.new(0,e.Character.PrimaryPart.Velocity.Y,0)e:PlayAnimation("\073\100\108\101")end task.desynchronize()for w,D in pairs(g)do task.synchronize()if q:IsKeyDown(Enum.KeyCode[D])then if D=="\082\105\103\104\116"then e.CameraRot-=Vector3.new(0,2,0)elseif D=="\076\101\102\116"then e.CameraRot+=Vector3.new(0,2,0)elseif D=="\085\112"then e.CameraRot+=Vector3.new(2,0,0)elseif D=="\068\111\119\110"then e.CameraRot-=Vector3.new(2,0,0)end if e.CameraRot.X>125 then e.CameraRot=Vector3.new(125,e.CameraRot.Y,0)elseif e.CameraRot.X<-50 then e.CameraRot=Vector3.new(-50,e.CameraRot.Y,0)end end task.desynchronize()end if e.Character.PrimaryPart.PhysicsMover.CollidedNormal==Vector3.new(0,1,0)then e.OnGround=true if e.Animation~="\087\097\108\107"then e:PlayAnimation("\073\100\108\101")end else e.OnGround=false e:PlayAnimation("\074\117\109\112")end task.synchronize()if q:IsKeyDown(Enum.KeyCode.Space)then if e.OnGround==true and e.Jump==true then e.Jump=false e.Character.PrimaryPart.Velocity+=Vector3.new(0,50,0)task.spawn(function()task.wait(.1)e.Jump=true end)end end task.desynchronize()end function e.Update(q)e.CurrentCamera.CFrame=CFrame.new((((CFrame.new(e.CameraSubject.Position)*CFrame.Angles(0,math.rad(e.CameraRot.Y),0))*CFrame.Angles(math.rad(e.CameraRot.X),0,0))*CFrame.new(e.CameraOffset)).Position,e.CameraSubject.Position)e.CurrentCamera:Update(false)e:Movement()D:Update()end return e end return s

local UserInput = game:GetService("UserInputService")
local ModelLoader = require(game.ReplicatedStorage.ModelLoader)
local WeldModule = require(game.ReplicatedStorage.Weld)

function KeysToStrings(Objects)
	local Temp = {}

	for i,v in pairs(Objects) do
		table.insert(Temp, v.KeyCode.Name)
	end

	return Temp
end

function AreKeysDown(tbl)
	task.synchronize()
	local Count = 0

	for i,Key in pairs(tbl) do
		if UserInput:IsKeyDown(Enum.KeyCode[Key]) then
			Count+=1
		end
	end
	
	task.desynchronize()

	if Count > 0 then
		return true
	else
		return false
	end
end

function V3Clamp(vector, min, max)
	return Vector3.new(math.clamp(vector.X, min, max), math.clamp(vector.Y, min, max), math.clamp(vector.Z, min, max))
end

local Players = {}

function MakeCharacter()
	local Character = {}

	local Head = ModelLoader.LoadFromName("Cube")
	Head.Size = Vector3.new(2,1,1)
	Head:SetColor(255,255,0)
	Head.Name = "Head"
	Head.CanCollide = false
	Head.Anchored = false
	Character.Head = Head

	local Root = ModelLoader.LoadFromName("Cube")
	Root.Size = Vector3.new(2,2,1)
	Root:SetColor(165,165,165)
	Root.Rendered = true
	Root.CFrame = CFrame.new(0,3,0)
	Root.Name = "HumanoidRootPart"
	Root.PhysicsMover.Offset = Vector3.new(0,-2,0)
	Root.Anchored = false
	Character.HumanoidRootPart = Root

	local Torso = ModelLoader.LoadFromName("Cube")
	Torso.Size = Vector3.new(2,2,1)
	Torso:SetColor(0,165,255)
	Torso.Name = "Torso"
	Torso.CanCollide = false
	Torso.Anchored = false
	Character.Torso = Torso

	local RightArm = ModelLoader.LoadFromName("Cube")
	RightArm.Size = Vector3.new(1,2,1)
	RightArm:SetColor(255,255,0)
	RightArm.Name = "Right Arm"
	RightArm.CanCollide = false
	RightArm.Anchored = false
	Character["Right Arm"] = RightArm

	local LeftArm = ModelLoader.LoadFromName("Cube")
	LeftArm.Size = Vector3.new(1,2,1)
	LeftArm:SetColor(255,255,0)
	LeftArm.Name = "Left Arm"
	LeftArm.CanCollide = false
	LeftArm.Anchored = false
	Character["Left Arm"] = LeftArm

	local RightLeg = ModelLoader.LoadFromName("Cube")
	RightLeg.Size = Vector3.new(1,2,1)
	RightLeg:SetColor(0,165,0)
	RightLeg.Name = "Right Leg"
	RightLeg.CanCollide = false
	RightLeg.Anchored = false
	Character["Right Leg"] = RightLeg

	local LeftLeg = ModelLoader.LoadFromName("Cube")
	LeftLeg.Size = Vector3.new(1,2,1)
	LeftLeg:SetColor(0,165,0)
	LeftLeg.Name = "Left Leg"
	LeftLeg.CanCollide = false
	LeftLeg.Anchored = false
	Character["Left Leg"] = LeftLeg

	Character.PrimaryPart = Character.HumanoidRootPart
	
	local RootJoint = WeldModule.new("RootJoint", Root, Torso, CFrame.new(0,0,0), CFrame.new(0,0,0))
	local Neck = WeldModule.new("Neck", Torso, Head, CFrame.new(0, 1, 0), CFrame.new(0, -0.5, 0))
	local RightShoulder = WeldModule.new("RightShoulder", Torso, RightArm, CFrame.new(1, 0.5, 0), CFrame.new(-0.5, 0.5, 0))
	local LeftShoulder = WeldModule.new("LeftShoulder", Torso, LeftArm, CFrame.new(-1, 0.5, 0), CFrame.new(0.5, 0.5, 0))
	local RightHip = WeldModule.new("RightHip", Torso, RightLeg, CFrame.new(1, -1, 0), CFrame.new(0.5, 1, 0))
	local LeftHip = WeldModule.new("LeftHip", Torso, LeftLeg, CFrame.new(-1, -1, 0), CFrame.new(-0.5, 1, 0))
	
	Character.HumanoidRootPart.RootJoint = RootJoint
	Character.Torso.Neck = Neck
	Character.Torso["Right Shoulder"] = RightShoulder
	Character.Torso["Left Shoulder"] = LeftShoulder
	Character.Torso["Right Hip"] = RightHip
	Character.Torso["Left Hip"] = LeftHip

	Character.BaseWelds = WeldModule:GetBaseWelds()

	return Character
end

function Players.new(Camera, Speed)
	local Player = {}

	Player.Character = MakeCharacter()
	Player.CurrentCamera = Camera
	Player.CameraSubject = Player.Character.PrimaryPart
	Player.CameraOffset = Vector3.new(0,5,7)
	Player.CameraRot = Vector3.new(0,0,0)
	Player.Speed = Speed
	Player.Walking = false
	Player.Jump = true
	Player.OnGround = true
	Player.Animation = "Idle"
	Player.Sine = 0

	function Player:PlayAnimation(Name)
		local RightShoulder = Player.Character.Torso["Right Shoulder"]
		local LeftShoulder = Player.Character.Torso["Left Shoulder"]
		local RightHip = Player.Character.Torso["Right Hip"]
		local LeftHip = Player.Character.Torso["Left Hip"]

		if Name == "Walk" then
			task.spawn(function()
				if Player.Animation ~= Name then
					Player.Animation = Name

					while Player.Animation == Name do
						RightShoulder.C0 = Player.Character.BaseWelds.RightShoulder.C0 * CFrame.Angles(math.rad(math.sin(Player.Sine/6)*40), 0, 0)
						LeftShoulder.C0 = Player.Character.BaseWelds.LeftShoulder.C0 * CFrame.Angles(-math.rad(math.sin(Player.Sine/6)*40), 0, 0)
						RightHip.C0 = Player.Character.BaseWelds.RightHip.C0 * CFrame.Angles(-math.rad(math.sin(Player.Sine/6)*40), 0, 0)
						LeftHip.C0 = Player.Character.BaseWelds.LeftHip.C0 * CFrame.Angles(math.rad(math.sin(Player.Sine/6)*40), 0, 0)

						Player.Sine+=1
						task.wait()
					end

					Player.Animation = "Idle"
				end
			end)
		elseif Name == "Idle" then
			Player.Animation = "Idle"

			RightShoulder.C0 = Player.Character.BaseWelds.RightShoulder.C0
			LeftShoulder.C0 = Player.Character.BaseWelds.LeftShoulder.C0
			RightHip.C0 = Player.Character.BaseWelds.RightHip.C0
			LeftHip.C0 = Player.Character.BaseWelds.LeftHip.C0

			Player.Sine = 0
		elseif Name == "Jump" then
			Player.Animation = "Jump"
			
			RightShoulder.C0 = Player.Character.BaseWelds.RightShoulder.C0 * CFrame.Angles(math.rad(180), 0, 0)
			LeftShoulder.C0 = Player.Character.BaseWelds.LeftShoulder.C0 * CFrame.Angles(math.rad(180), 0, 0)
			RightHip.C0 = Player.Character.BaseWelds.RightHip.C0
			LeftHip.C0 = Player.Character.BaseWelds.LeftHip.C0
		end
	end

	function Player:Movement()
		task.synchronize()
		local PressedKeys = KeysToStrings(UserInput:GetKeysPressed())
		local MouseButton = UserInput:GetMouseButtonsPressed()
		task.desynchronize()

		local WalkKeys = {"W", "A", "S", "D"}
		local CameraKeys = {"Left", "Right", "Up", "Down"}
		
		for i,Key in pairs(WalkKeys) do
			task.synchronize()
			if UserInput:IsKeyDown(Enum.KeyCode[Key]) then
				if Key == "W" then
					Player.Character.PrimaryPart.CFrame = CFrame.new(Player.Character.PrimaryPart.Position + (Player.Character.PrimaryPart.Velocity)/Player.Character.PrimaryPart.Mass) * CFrame.Angles(0, math.rad(Player.CameraRot.Y), 0) --* CFrame.new(0, 0, -Speed)
					Player.Character.PrimaryPart.Velocity = Vector3.new(0, Player.Character.PrimaryPart.Velocity.Y, 0)
					Player.Character.PrimaryPart.Velocity += Player.Character.PrimaryPart.CFrame.LookVector*30
				elseif Key == "S" then
					Player.Character.PrimaryPart.CFrame = CFrame.new(Player.Character.PrimaryPart.Position + (Player.Character.PrimaryPart.Velocity)/Player.Character.PrimaryPart.Mass) * CFrame.Angles(0, math.rad(180 + Player.CameraRot.Y), 0)
					Player.Character.PrimaryPart.Velocity = Vector3.new(0, Player.Character.PrimaryPart.Velocity.Y, 0)
					Player.Character.PrimaryPart.Velocity += Player.Character.PrimaryPart.CFrame.LookVector*30
				elseif Key == "A" then
					Player.Character.PrimaryPart.CFrame = CFrame.new(Player.Character.PrimaryPart.Position + (Player.Character.PrimaryPart.Velocity)/Player.Character.PrimaryPart.Mass) * CFrame.Angles(0, math.rad(90 + Player.CameraRot.Y), 0)
					Player.Character.PrimaryPart.Velocity = Vector3.new(0, Player.Character.PrimaryPart.Velocity.Y, 0)
					Player.Character.PrimaryPart.Velocity += Player.Character.PrimaryPart.CFrame.LookVector*30
				elseif Key == "D" then
					Player.Character.PrimaryPart.CFrame = CFrame.new(Player.Character.PrimaryPart.Position + (Player.Character.PrimaryPart.Velocity)/Player.Character.PrimaryPart.Mass) * CFrame.Angles(0, math.rad(-90 + Player.CameraRot.Y), 0)
					Player.Character.PrimaryPart.Velocity = Vector3.new(0, Player.Character.PrimaryPart.Velocity.Y, 0)
					Player.Character.PrimaryPart.Velocity += Player.Character.PrimaryPart.CFrame.LookVector*30
				end

				Player.Walking = true
				
				if Player.Animation ~= "Jump" then
					Player:PlayAnimation("Walk")
				end
			end
			task.desynchronize()
		end
		
		task.synchronize()
		if (not AreKeysDown(WalkKeys)) and (Player.Walking == true) then
			Player.Walking = false
			Player.Character.PrimaryPart.Velocity = Vector3.new(0, Player.Character.PrimaryPart.Velocity.Y, 0)
			Player:PlayAnimation("Idle")
		end
		task.desynchronize()

		for i,Key in pairs(CameraKeys) do
			task.synchronize()
			if UserInput:IsKeyDown(Enum.KeyCode[Key]) then
				if Key == "Right" then
					Player.CameraRot -= Vector3.new(0, 2, 0)
				elseif Key == "Left" then
					Player.CameraRot += Vector3.new(0, 2, 0)
				elseif Key == "Up" then
					Player.CameraRot += Vector3.new(2, 0, 0)
				elseif Key == "Down" then
					Player.CameraRot -= Vector3.new(2, 0, 0)
				end
				
				if Player.CameraRot.X > 125 then
					Player.CameraRot = Vector3.new(125, Player.CameraRot.Y, 0)
				elseif Player.CameraRot.X < -50 then
					Player.CameraRot = Vector3.new(-50, Player.CameraRot.Y, 0)
				end
			end
			task.desynchronize()
		end
		
		if Player.Character.PrimaryPart.PhysicsMover.CollidedNormal == Vector3.new(0,1,0) then
			Player.OnGround = true
			
			if Player.Animation ~= "Walk" then
				Player:PlayAnimation("Idle")
			end
		else
			Player.OnGround = false
			Player:PlayAnimation("Jump")
		end
		
		task.synchronize()
		if UserInput:IsKeyDown(Enum.KeyCode.Space) then
			if Player.OnGround == true and Player.Jump == true then
				Player.Jump = false
				Player.Character.PrimaryPart.Velocity += Vector3.new(0, 50, 0)
				
				task.spawn(function()
					task.wait(0.1)
					Player.Jump = true
				end)
			end
		end
		task.desynchronize()
	end

	function Player:Update()
		Player.CurrentCamera.CFrame = CFrame.new((CFrame.new(Player.CameraSubject.Position) * CFrame.Angles(0, math.rad(Player.CameraRot.Y), 0) * CFrame.Angles(math.rad(Player.CameraRot.X), 0, 0) * CFrame.new(Player.CameraOffset)).Position, Player.CameraSubject.Position)
		Player.CurrentCamera:Update(false)
		Player:Movement()
		WeldModule:Update()
	end

	return Player
end

return Players
