remotes.setup.OnServerEvent:Connect(function(Q,R,Y)local n=Y:Clone()local x=Q.Character local D=x:WaitForChild("\072\117\109\097\110\111\105\100")local s=Instance.new("\077\111\116\111\114\054\068")s.Part0=x:WaitForChild(R and"\082\105\103\104\116\072\097\110\100"or"\082\105\103\104\116 \065\114\109")s.Part1=n:WaitForChild("\072\097\110\100\108\101")s.Parent=n.Handle n.Parent=x weapons[Q]=(require(n:WaitForChild("\115\101\116\116\105\110\103\115")))(R)local V=spring.new(0,0,0,10,1)local W=spring.new(Vector2.new(),Vector2.new(),Vector2.new(),20,1)springs[Q]={}springs[Q].tilt=V springs[Q].recoil=W local N,Z if R then local Q=(x:WaitForChild("\072\101\097\100")):WaitForChild("\078\101\099\107")local R=(x:WaitForChild("\085\112\112\101\114\084\111\114\115\111")):WaitForChild("\087\097\105\115\116")local Y=(x:WaitForChild("\082\105\103\104\116\085\112\112\101\114\065\114\109")):WaitForChild("\082\105\103\104\116\083\104\111\117\108\100\101\114")local n=(x:WaitForChild("\076\101\102\116\085\112\112\101\114\065\114\109")):WaitForChild("\076\101\102\116\083\104\111\117\108\100\101\114")local D=Q.C0 local s=R.C0 local V=Y.C0 local W=n.C0 function N(x)Q.C0=D*CFrame.fromEulerAnglesYXZ(x,0,0)R.C0=s*CFrame.fromEulerAnglesYXZ(x,0,0)Y.C0=V*CFrame.fromEulerAnglesYXZ(x,0,0)n.C0=W*CFrame.fromEulerAnglesYXZ(x,0,0)end function Z(Q,R)Y.C0=Y.C0*CFrame.new(0,0,Q)n.C0=n.C0*CFrame.new(0,0,R)end else local Q=x:WaitForChild("\084\111\114\115\111")local R=x:WaitForChild("\072\117\109\097\110\111\105\100\082\111\111\116\080\097\114\116")local Y=Q:WaitForChild("\078\101\099\107")local n=R:WaitForChild("\082\111\111\116\074\111\105\110\116")local D=Q:WaitForChild("\082\105\103\104\116 \083\104\111\117\108\100\101\114")local s=Q:WaitForChild("\076\101\102\116 \083\104\111\117\108\100\101\114")local V=Q:WaitForChild("\082\105\103\104\116 \072\105\112")local W=Q:WaitForChild("\076\101\102\116 \072\105\112")local d=Y.C0 local o=n.C0 local H=D.C0 local w=s.C0 local y=V.C0 local m=W.C0 function N(Q)Y.C0=d*CFrame.fromEulerAnglesYXZ(-Q,0,0)n.C0=((o*CFrame.new(0,0,-1))*CFrame.fromEulerAnglesYXZ(-Q,0,0))*CFrame.new(0,0,1)D.C0=H*CFrame.fromEulerAnglesYXZ(0,0,Q)s.C0=w*CFrame.fromEulerAnglesYXZ(0,0,-Q)V.C0=y*CFrame.fromEulerAnglesYXZ(0,0,-Q)W.C0=m*CFrame.fromEulerAnglesYXZ(0,0,Q)end function Z(Q,R)D.C0=D.C0*CFrame.new(-Q,0,0)s.C0=s.C0*CFrame.new(R,0,0)end end local d=runService.Heartbeat:Connect(function(Q)V:update(Q)W:update(Q)N(states[D:GetState()]and 0 or V.p/2)Z(W.p.x,W.p.y)end)local o o=Q.Character.Humanoid.Died:Connect(function()d:Disconnect()o:Disconnect()end)cleanup[Q]={N,d,o,n,s,Z}end)remotes.cleanup.OnServerEvent:Connect(function(Q)local R=cleanup[Q]if R then R[2]:Disconnect()R[1](0)R[3]:Disconnect()R[4]:Destroy()R[5]:Destroy()R[6](0,0)end end)

remotes.setup.OnServerEvent:Connect(function(player, isR15, weapon)
	local weapon = weapon:Clone();
	
	local character = player.Character;
	local humanoid = character:WaitForChild("Humanoid");
	
	local joint = Instance.new("Motor6D");
	joint.Part0 = character:WaitForChild(isR15 and "RightHand" or "Right Arm");
	joint.Part1 = weapon:WaitForChild("Handle");
	joint.Parent = weapon.Handle;
	
	weapon.Parent = character;
	weapons[player] = require(weapon:WaitForChild("settings"))(isR15);
	
	local tilt = spring.new(0, 0, 0, 10, 1);
	local recoil = spring.new(Vector2.new(), Vector2.new(), Vector2.new(), 20, 1);
	
	springs[player] = {};
	springs[player].tilt = tilt;
	springs[player].recoil = recoil;
	
	-- update the character according to their rig type
	local tiltFunc, recoilFunc;
	if (isR15) then
		local neck = character:WaitForChild("Head"):WaitForChild("Neck");
		local waist = character:WaitForChild("UpperTorso"):WaitForChild("Waist");
		local rShoulder = character:WaitForChild("RightUpperArm"):WaitForChild("RightShoulder");
		local lShoulder = character:WaitForChild("LeftUpperArm"):WaitForChild("LeftShoulder");
		
		local neckC0 = neck.C0;
		local waistC0 = waist.C0;
		local rShoulderC0 = rShoulder.C0;
		local lShoulderC0 = lShoulder.C0;
		
		function tiltFunc(theta)
			neck.C0 = neckC0 * CFrame.fromEulerAnglesYXZ(theta, 0, 0);
			waist.C0 = waistC0 * CFrame.fromEulerAnglesYXZ(theta, 0, 0);
			rShoulder.C0 = rShoulderC0 * CFrame.fromEulerAnglesYXZ(theta, 0, 0);
			lShoulder.C0 = lShoulderC0 * CFrame.fromEulerAnglesYXZ(theta, 0, 0);
		end
		
		function recoilFunc(x, y)
			rShoulder.C0 = rShoulder.C0 * CFrame.new(0, 0, x);
			lShoulder.C0 = lShoulder.C0 * CFrame.new(0, 0, y);
		end
	else
		local torso = character:WaitForChild("Torso");
		local hrp = character:WaitForChild("HumanoidRootPart");
		
		local neck = torso:WaitForChild("Neck");
		local root = hrp:WaitForChild("RootJoint");
		local rShoulder = torso:WaitForChild("Right Shoulder");
		local lShoulder = torso:WaitForChild("Left Shoulder");
		local rHip = torso:WaitForChild("Right Hip");
		local lHip = torso:WaitForChild("Left Hip");
		
		local neckC0 = neck.C0;
		local rootC0 = root.C0;
		local rShoulderC0 = rShoulder.C0;
		local lShoulderC0 = lShoulder.C0;
		local rHipC0 = rHip.C0;
		local lHipC0 = lHip.C0;
		
		-- rotating the R6 joints is so arbitrary
		function tiltFunc(theta)
			neck.C0 = neckC0 * CFrame.fromEulerAnglesYXZ(-theta, 0, 0);
			root.C0 = rootC0 * CFrame.new(0, 0, -1) * CFrame.fromEulerAnglesYXZ(-theta, 0, 0) * CFrame.new(0, 0, 1);
			rShoulder.C0 = rShoulderC0 * CFrame.fromEulerAnglesYXZ(0, 0, theta);
			lShoulder.C0 = lShoulderC0 * CFrame.fromEulerAnglesYXZ(0, 0, -theta);
			rHip.C0 = rHipC0 * CFrame.fromEulerAnglesYXZ(0, 0, -theta);
			lHip.C0 = lHipC0 * CFrame.fromEulerAnglesYXZ(0, 0, theta);
		end
		
		function recoilFunc(x, y)
			rShoulder.C0 = rShoulder.C0 * CFrame.new(-x, 0, 0);
			lShoulder.C0 = lShoulder.C0 * CFrame.new(y, 0, 0);
		end
	end
	
	local heartBeat = runService.Heartbeat:Connect(function(dt)
		tilt:update(dt);
		recoil:update(dt);
		
		tiltFunc(states[humanoid:GetState()] and 0 or tilt.p / 2);
		recoilFunc(recoil.p.x, recoil.p.y);
	end)
	
	-- disconnect on death
	local died; died = player.Character.Humanoid.Died:Connect(function()
		heartBeat:Disconnect();
		died:Disconnect();
	end)
	
	-- store this for later
	cleanup[player] = {
		tiltFunc;
		heartBeat;
		died;
		weapon;
		joint;
		recoilFunc;
	}
end)

remotes.cleanup.OnServerEvent:Connect(function(player)
	local clean = cleanup[player];
	if (clean) then
		clean[2]:Disconnect();
		clean[1](0);
		clean[3]:Disconnect();
		clean[4]:Destroy();
		clean[5]:Destroy();
		clean[6](0, 0);
	end
end)
