local t=game:GetService("\085\115\101\114\073\110\112\117\116\083\101\114\118\105\099\101")local U=game:GetService("\084\119\101\101\110\083\101\114\118\105\099\101")local D=game:GetService("\082\117\110\083\101\114\118\105\099\101")local j=game:GetService("\080\108\097\121\101\114\115")local u=j.LocalPlayer local L=script:WaitForChild("\084\111\107\101\110\084\114\097\110\115\105\116\105\111\110\071\117\105")local T=L:WaitForChild("\086\105\101\119\112\111\114\116\070\114\097\109\101")local b=T:WaitForChild("\084\111\107\101\110")local P=T:WaitForChild("\071\108\111\119\080\097\114\116")local k=P:WaitForChild("\071\108\111\119\068\101\099\097\108")local q=L:WaitForChild("\066\097\099\107\103\114\111\117\110\100")local X=L:WaitForChild("\070\108\121\083\111\117\110\100")local O=Instance.new("\067\097\109\101\114\097")O.CameraType=Enum.CameraType.Scriptable O.CFrame=CFrame.new(0,0,0)O.FieldOfView=40 O.Parent=T T.CurrentCamera=O local W=3 local C=-0.25 local x=.3 local I=.15 local Z=1.5 local a=2 local d=3 local p=Random.new()local r=math.pi*.5 local F=math.pi*2 local h=false local n=0 local R=false local o=nil local H=false local S=b.PrimaryPart.CFrame local f={}for t,U in pairs(b:GetDescendants())do if U:IsA("\066\097\115\101\080\097\114\116")and U~=b.PrimaryPart then f[U]=U.CFrame:ToObjectSpace(b.PrimaryPart.CFrame)end end local v=0 local G=0 function spinToken(t)v=(v+(t*F)*(C+G))%F if math.abs(G)<t*I then G=0 else G=G-(t*I)*math.sign(G)end local U=S*CFrame.Angles(0,v,0)b.PrimaryPart.CFrame=U for t,D in pairs(f)do t.CFrame=U*D end local D=math.sin(v*2+r)*.5+.5 k.Transparency=.75+.1*(1-D)local j=7.5+1*D P.Size=Vector3.new(j,.01,j)end function requestBadge()if not H then H=true end end function spinAction(t)G=math.clamp(G+x*t,-Z,Z)requestBadge()end local A={[Enum.KeyCode.DPadLeft]=true,[Enum.KeyCode.ButtonL1]=true,[Enum.KeyCode.A]=true;[Enum.KeyCode.Left]=true}local Q={[Enum.KeyCode.DPadRight]=true;[Enum.KeyCode.ButtonR1]=true;[Enum.KeyCode.D]=true;[Enum.KeyCode.Right]=true}function handleInput(t,U)if t and t.UserInputState==Enum.UserInputState.Begin then if t.UserInputType==Enum.UserInputType.Touch or t.UserInputType==Enum.UserInputType.MouseButton1 then local U=math.sign(t.Position.X-T.AbsoluteSize.X*.5)spinAction(U)elseif t.UserInputType==Enum.UserInputType.Gamepad1 or t.UserInputType==Enum.UserInputType.Keyboard then if A[t.KeyCode]then spinAction(-1)elseif Q[t.KeyCode]then spinAction(1)end end end end function enable(j)local b=u:FindFirstChild("\080\108\097\121\101\114\071\117\105")if not h and b then h=true n=n+1 local u=n if not L.Enabled then v=F*.9 G=0 q.BackgroundTransparency=1 O.CFrame=CFrame.new(-7,0,-10)end T.ImageTransparency=0 T.Visible=true L.Parent=b L.Enabled=true X.PlaybackSpeed=.5 X.Volume=.5 X:Play()if not R then R=true D:BindToRenderStep("\084\111\107\101\110\084\114\097\110\115\105\116\105\111\110",Enum.RenderPriority.Camera.Value-1,spinToken)end;(U:Create(X,TweenInfo.new(W,Enum.EasingStyle.Quad,Enum.EasingDirection.In),{Volume=.5})):Play();(U:Create(T,TweenInfo.new(.1,Enum.EasingStyle.Quad,Enum.EasingDirection.In),{ImageTransparency=0})):Play();(U:Create(O,TweenInfo.new(1.5,Enum.EasingStyle.Quad,Enum.EasingDirection.Out),{CFrame=CFrame.new(0,0,-10)})):Play()task.delay(1.5,function()if u==n then if o then o:Disconnect()o=nil end if j then o=t.InputBegan:connect(handleInput)end;(U:Create(q,TweenInfo.new(.5,Enum.EasingStyle.Quad,Enum.EasingDirection.InOut),{BackgroundTransparency=0})):Play();(U:Create(O,TweenInfo.new(4,Enum.EasingStyle.Quad,Enum.EasingDirection.InOut),{CFrame=CFrame.new(0,0,0)})):Play()end end)end end function disable()local t=u:FindFirstChild("\080\108\097\121\101\114\071\117\105")if h and t then h=false n=n+1 local t=n if o then o:Disconnect()o=nil end X.PlaybackSpeed=.5 X:Play();(U:Create(X,TweenInfo.new(W,Enum.EasingStyle.Quad,Enum.EasingDirection.In),{Volume=0})):Play();(U:Create(O,TweenInfo.new(W,Enum.EasingStyle.Quad,Enum.EasingDirection.In),{CFrame=CFrame.new(0,0,300)})):Play();(U:Create(q,TweenInfo.new(W,Enum.EasingStyle.Quad,Enum.EasingDirection.In),{BackgroundTransparency=1})):Play();(U:Create(T,TweenInfo.new(W,Enum.EasingStyle.Quad,Enum.EasingDirection.In),{ImageTransparency=1})):Play()task.delay(W,function()if t==n then for t,U in pairs(L:GetChildren())do if U and(U.Parent and U.Name=="\067\108\101\097\110\105\110\103\085\112\073\099\111\110")or U.Name=="\073\099\111\110"then U:Destroy()end end L.Enabled=false L.ViewportFrame.Visible=false L.Parent=script if not R then R=false D:UnbindFromRenderStep("\084\111\107\101\110\084\114\097\110\115\105\116\105\111\110")end end end)end end local J={Enable=enable,Disable=disable}return J
-- Luke

local uis = game:GetService("UserInputService")
local tweenService = game:GetService("TweenService")
local runService = game:GetService("RunService")
local playersService = game:GetService("Players")
local localPlayer = playersService.LocalPlayer
local gui = script:WaitForChild("TokenTransitionGui")
local viewportFrame = gui:WaitForChild("ViewportFrame")
local tokenModel = viewportFrame:WaitForChild("Token")
local glowPart = viewportFrame:WaitForChild("GlowPart")
local glowDecal = glowPart:WaitForChild("GlowDecal")
local background = gui:WaitForChild("Background")
local sound = gui:WaitForChild("FlySound")

local camera = Instance.new("Camera")
camera.CameraType = Enum.CameraType.Scriptable
camera.CFrame = CFrame.new(0, 0, 0)
camera.FieldOfView = 40
camera.Parent = viewportFrame
viewportFrame.CurrentCamera = camera

local DISABLE_TIME = 3

local TOKEN_SPIN_RATE = -0.25
local CLICK_VELOCITY = 0.3
local SPIN_DAMPER = 0.15
local MAX_SPEED = 1.5

local ICON_FADE_IN_TIME = 2
local ICON_FADE_OUT_TIME = 3

local rng = Random.new()
local qpi = math.pi * 0.5
local tau = math.pi * 2

local enabled = false
local changeIndex = 0
local renderstepBound = false
local inputConnection = nil
local requestedBadge = false

local tokenOriginalCF = tokenModel.PrimaryPart.CFrame
local tokenPartCFrames = {}
for _, child in pairs(tokenModel:GetDescendants()) do
	if child:IsA("BasePart") and child ~= tokenModel.PrimaryPart then
		tokenPartCFrames[child] = child.CFrame:ToObjectSpace(tokenModel.PrimaryPart.CFrame)
	end
end

local spin = 0
local spinVelocity = 0
function spinToken(delta)
	--local spin = os.clock()*tau*TOKEN_SPIN_RATE
	spin = (spin + delta * tau * (TOKEN_SPIN_RATE + spinVelocity)) % tau
	if math.abs(spinVelocity) < delta * SPIN_DAMPER then
		spinVelocity = 0
	else
		spinVelocity = spinVelocity - delta * SPIN_DAMPER * math.sign(spinVelocity)
	end

	local newCFrame = tokenOriginalCF * CFrame.Angles(0, spin, 0)
	tokenModel.PrimaryPart.CFrame = newCFrame
	for tokenModelPart, cframeOffset in pairs(tokenPartCFrames) do
		tokenModelPart.CFrame = newCFrame * cframeOffset
	end

	local glownessPercent = math.sin(spin * 2 + qpi) * 0.5 + 0.5
	glowDecal.Transparency = 0.75 + 0.1 * (1 - glownessPercent)
	local width = 7.5 + 1 * glownessPercent
	glowPart.Size = Vector3.new(width, 0.01, width)
end

function requestBadge()
	if not requestedBadge then --TODO: replace with a debounce timer
		requestedBadge = true
		--TODO: request badge
	end
end

function spinAction(direction)
	spinVelocity = math.clamp(spinVelocity + CLICK_VELOCITY * direction, -MAX_SPEED, MAX_SPEED)
	requestBadge()
end

local leftControls = {
	[Enum.KeyCode.DPadLeft] = true,
	[Enum.KeyCode.ButtonL1] = true,
	[Enum.KeyCode.A] = true,
	[Enum.KeyCode.Left] = true,
}
local rightControls = {
	[Enum.KeyCode.DPadRight] = true,
	[Enum.KeyCode.ButtonR1] = true,
	[Enum.KeyCode.D] = true,
	[Enum.KeyCode.Right] = true,
}
function handleInput(input, processed)
	if input and input.UserInputState == Enum.UserInputState.Begin then
		if
			input.UserInputType == Enum.UserInputType.Touch
			or input.UserInputType == Enum.UserInputType.MouseButton1
		then
			local direction = math.sign(input.Position.X - viewportFrame.AbsoluteSize.X * 0.5)
			spinAction(direction)
		elseif
			input.UserInputType == Enum.UserInputType.Gamepad1 or input.UserInputType == Enum.UserInputType.Keyboard
		then
			if leftControls[input.KeyCode] then
				spinAction(-1)
			elseif rightControls[input.KeyCode] then
				spinAction(1)
			end
		end
	end
end

function enable(spinControl)
	local playerGui = localPlayer:FindFirstChild("PlayerGui")
	if not enabled and playerGui then
		enabled = true
		changeIndex = changeIndex + 1
		local thisChangeIndex = changeIndex
		if not gui.Enabled then
			spin = tau * 0.9 -- Initial rotation
			spinVelocity = 0
			background.BackgroundTransparency = 1
			camera.CFrame = CFrame.new(-7, 0, -10)
		end
		viewportFrame.ImageTransparency = 0
		viewportFrame.Visible = true
		gui.Parent = playerGui
		gui.Enabled = true
		sound.PlaybackSpeed = 0.5
		sound.Volume = 0.5
		sound:Play()

		if not renderstepBound then
			renderstepBound = true
			runService:BindToRenderStep("TokenTransition", Enum.RenderPriority.Camera.Value - 1, spinToken)
		end

		tweenService
			:Create(
				sound,
				TweenInfo.new(DISABLE_TIME, Enum.EasingStyle.Quad, Enum.EasingDirection.In),
				{ ["Volume"] = 0.5 }
			)
			:Play()
		tweenService
			:Create(
				viewportFrame,
				TweenInfo.new(0.1, Enum.EasingStyle.Quad, Enum.EasingDirection.In),
				{ ["ImageTransparency"] = 0 }
			)
			:Play()
		tweenService
			:Create(
				camera,
				TweenInfo.new(1.5, Enum.EasingStyle.Quad, Enum.EasingDirection.Out),
				{ ["CFrame"] = CFrame.new(0, 0, -10) }
			)
			:Play()
		task.delay(1.5, function()
			if thisChangeIndex == changeIndex then
				if inputConnection then
					inputConnection:Disconnect()
					inputConnection = nil
				end
				if spinControl then
					inputConnection = uis.InputBegan:connect(handleInput)
				end
				tweenService
					:Create(
						background,
						TweenInfo.new(0.5, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut),
						{ ["BackgroundTransparency"] = 0 }
					)
					:Play()
				tweenService
					:Create(
						camera,
						TweenInfo.new(4, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut),
						{ ["CFrame"] = CFrame.new(0, 0, 0) }
					)
					:Play()
			end
		end)
	end
end

function disable()
	local playerGui = localPlayer:FindFirstChild("PlayerGui")
	if enabled and playerGui then
		enabled = false
		changeIndex = changeIndex + 1
		local thisChangeIndex = changeIndex
		if inputConnection then
			inputConnection:Disconnect()
			inputConnection = nil
		end

		sound.PlaybackSpeed = 0.5
		sound:Play()
		tweenService
			:Create(
				sound,
				TweenInfo.new(DISABLE_TIME, Enum.EasingStyle.Quad, Enum.EasingDirection.In),
				{ ["Volume"] = 0 }
			)
			:Play()
		tweenService
			:Create(
				camera,
				TweenInfo.new(DISABLE_TIME, Enum.EasingStyle.Quad, Enum.EasingDirection.In),
				{ ["CFrame"] = CFrame.new(0, 0, 300) }
			)
			:Play()
		tweenService
			:Create(
				background,
				TweenInfo.new(DISABLE_TIME, Enum.EasingStyle.Quad, Enum.EasingDirection.In),
				{ ["BackgroundTransparency"] = 1 }
			)
			:Play()
		tweenService
			:Create(
				viewportFrame,
				TweenInfo.new(DISABLE_TIME, Enum.EasingStyle.Quad, Enum.EasingDirection.In),
				{ ["ImageTransparency"] = 1 }
			)
			:Play()
		task.delay(DISABLE_TIME, function()
			if thisChangeIndex == changeIndex then
				for _, iconLabel in pairs(gui:GetChildren()) do
					if
						iconLabel and iconLabel.Parent and iconLabel.Name == "CleaningUpIcon"
						or iconLabel.Name == "Icon"
					then
						iconLabel:Destroy()
					end
				end
				gui.Enabled = false
				gui.ViewportFrame.Visible = false
				gui.Parent = script
				if not renderstepBound then
					renderstepBound = false
					runService:UnbindFromRenderStep("TokenTransition")
				end
			end
		end)
	end
end

local module = {
	Enable = enable,
	Disable = disable,
}

return module
