zenonityisfat

[FE] Fake VR Script

Aug 10th, 2021
19,838
-1
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 14.61 KB | None | 0 1
  1. local cam = workspace.Camera
  2. local p
  3. local headObject
  4. local events = {}
  5.  
  6. local controls = {
  7.     [Enum.UserInputType.MouseButton1] = {"move", "leftHand"},
  8.     [Enum.UserInputType.MouseMovement] = {"updateTarget"}, -- do not change
  9.     [Enum.UserInputType.MouseWheel] = {"adjustOffset"},
  10.     [Enum.UserInputType.MouseButton2] = {"move", "rightHand"},
  11.     [Enum.KeyCode.W] = {"move", "head", Vector3.new(0, 1, 0)},
  12.     [Enum.KeyCode.A] = {"move", "head", Vector3.new(-1, 0, 0)},
  13.     [Enum.KeyCode.S] = {"move", "head", Vector3.new(0, -1, 0)},
  14.     [Enum.KeyCode.D] = {"move", "head", Vector3.new(1, 0, 0)},
  15.     [Enum.KeyCode.Q] = {"move", "head", Vector3.new(0, 0, -1)},
  16.     [Enum.KeyCode.E] = {"move", "head", Vector3.new(0, 0, 1)},
  17.     [Enum.KeyCode.LeftShift] = {"gesture", "Fist"},
  18.     [Enum.KeyCode.LeftControl] = {"gesture", "Index"},
  19.     [Enum.KeyCode.LeftAlt] = {"gesture", "Thumb"},
  20.     [Enum.KeyCode.Z] = {"toggle", "canOffset"},
  21.     [Enum.KeyCode.R] = {"toggle", "rotationManager"},
  22.     [Enum.KeyCode.Tab] = {"selectAxis", "rotationManager"},
  23.     [Enum.KeyCode.Left] = {"updateAxisMover", "rotationManager", -1},
  24.     [Enum.KeyCode.Right] = {"updateAxisMover", "rotationManager", 1}
  25. }
  26.  
  27. local services = {}
  28.  
  29. setmetatable(services, {
  30.     __index = function(t, k)
  31.         services[k] = rawget(services, k) or game:GetService(k)
  32.         return services[k]
  33.     end
  34. })
  35.  
  36. local function angleBetween(vecx, vecy)
  37.     return math.acos(vecx:Dot(vecy))
  38. end
  39.  
  40. local hand = {}
  41. hand.__index = hand
  42.  
  43. function hand:gesture(gestureName, keyState)
  44.     if keyState ~= 1 then
  45.         return
  46.     end
  47.  
  48.     headObject.realHeadset[self.id .. gestureName] = 1 - headObject.realHeadset[self.id .. gestureName]
  49. end
  50.  
  51. function hand:getMouseRay()
  52.     local mousePos = services.UserInputService:GetMouseLocation()
  53.     return CFrame.new(cam:ViewportPointToRay(mousePos.x, mousePos.y).Direction * (1.5 + headObject.handOffset))
  54. end
  55.  
  56. function hand:calculateEndRotation()
  57.     return CFrame.Angles(cam.CFrame:ToEulerAnglesXYZ()) * CFrame.Angles(self.rotation[1] * (math.pi/6), self.rotation[2] * (math.pi/6), self.rotation[3] * (math.pi/6))
  58. end
  59.  
  60. function hand:updateTarget()
  61.  
  62.     local camLook = (cam.CFrame.lookVector * Vector3.new(1,0,1)).unit
  63.    
  64.     local theta = angleBetween(Vector3.new(-1, 0, 0), camLook)
  65.     theta = camLook.z > 0 and (2 * math.pi) - theta or theta
  66.  
  67.     local relativeAngle = (self.id == "l" and -headObject.handAngle or headObject.handAngle)
  68.     local startPosition = CFrame.new(-math.cos(theta + relativeAngle), -0.5, -math.sin(theta + relativeAngle)) + (camLook * headObject.handOffset)
  69.  
  70.     self.targetPosition = startPosition:Lerp(self:getMouseRay(), self.alpha) * self:calculateEndRotation()
  71.    
  72.     self.replicatePosition:Fire()
  73. end
  74.  
  75. function hand:beginMove(minAlpha, maxAlpha)
  76.     local distAlpha = (maxAlpha - minAlpha) / 2
  77.  
  78.     self.moving = true
  79.     repeat
  80.         services.RunService.RenderStepped:wait()
  81.         self:updateTarget()
  82.         self.alpha += self.alphaMultiplier
  83.     until math.abs(self.alpha - minAlpha) < 0.05 or math.abs(maxAlpha - self.alpha) < 0.05 or self.alpha ~= self.alpha
  84.    
  85.     if self.alpha ~= self.alpha then
  86.         self.alpha = 0
  87.     end
  88.    
  89.     self.moving = false
  90. end
  91.  
  92. function hand:move(keyState)
  93.  
  94.     if headObject.rotationManager.active then
  95.         if self.id == "l" then
  96.             headObject.rotationManager.held = keyState == 1
  97.            
  98.             headObject.rotationManager.selectedAxis = 0
  99.         end
  100.         return
  101.     end
  102.  
  103.     self.alphaMultiplier = keyState == 1 and 0.05 or -0.05
  104.    
  105.     if not self.moving and not (keyState == 1 and self.alpha >= 1) then
  106.         if keyState == 1 then
  107.             headObject.recentHand = self
  108.         end
  109.    
  110.         self:beginMove(0, 1)
  111.     end
  112. end
  113.  
  114. function hand:new(direction, realHand)
  115.     local newHand = setmetatable({direction = direction, realHand = realHand}, hand)
  116.     newHand.alpha = 0
  117.     newHand.alphaMultiplier = 0.05
  118.     newHand.id = direction and "r" or "l"
  119.     newHand.targetPosition = CFrame.new()
  120.     newHand.moving = false
  121.     newHand.rotation = {0, 0, 0}
  122.     newHand.replicatePosition = Instance.new("BindableEvent")
  123.     newHand.replicatePosition.Event:connect(function()
  124.         events.UserCFrameChanged:Fire(newHand.direction and Enum.UserCFrame.RightHand or Enum.UserCFrame.LeftHand, newHand.targetPosition)
  125.     end)
  126.    
  127.     return newHand
  128. end
  129.  
  130. local head = {}
  131. head.__index = head
  132.  
  133. function head:handleInput(input, keyState)
  134.     local bind = controls[input.KeyCode] or controls[input.UserInputType]
  135.    
  136.     if bind then
  137.         if bind[1] == "updateTarget" and not self.rotationManager.active then
  138.             self.leftHand:updateTarget()
  139.             self.rightHand:updateTarget()
  140.         elseif bind[2] and type(self[bind[2]]) == "table" then
  141.             self[bind[2]][bind[1]](self[bind[2]], keyState, bind[3])
  142.         elseif bind[3] then
  143.             self[bind[1]](self, bind[3], keyState)
  144.         elseif bind[2] and self.recentHand[bind[1]] then
  145.             self.recentHand[bind[1]](self.recentHand, bind[2], keyState)
  146.         else
  147.             self[bind[1]](self, bind[2], keyState)
  148.         end
  149.     end
  150. end
  151.  
  152. function head:adjustOffset(_, keyState)
  153.     if self.canOffset then     
  154.         self.handOffset += keyState * 0.04
  155.         self.leftHand:updateTarget()
  156.         self.rightHand:updateTarget()
  157.     end
  158. end
  159.  
  160. function head:move(vec, keyState)
  161.     if vec.z ~= 0 then
  162.         self.realHeadset.Stick2 = math.clamp(self.realHeadset.Stick2 + (vec.z * keyState), -1, 1)
  163.     else
  164.         self.realHeadset.StickPosition += Vector3.new(vec.x, vec.y, 0) * keyState
  165.     end
  166. end
  167.  
  168. function head:freezeCam(b)
  169.     local dist = (self.realHeadset.Head.PrimaryPart.Position - cam.CFrame.p).magnitude
  170.        
  171.     p.CameraMinZoomDistance = b and dist or 0.5
  172.     p.CameraMaxZoomDistance = b and dist or 128
  173. end
  174.  
  175. function head:toggle(stat, keyState)
  176.     if keyState ~= 1 then
  177.         return
  178.     end
  179.  
  180.     self[stat] = not self[stat]
  181.    
  182.     if stat == "canOffset" then
  183.         self:freezeCam(self[stat])
  184.     end
  185. end
  186.  
  187. local rotation = {}
  188. rotation.__index = rotation
  189.  
  190. function rotation:new()
  191.     local newRotation = setmetatable({}, rotation)
  192.    
  193.     newRotation.rotationLookup = {{}, {}, {}}
  194.     newRotation.lineLookup = {{}, {}, {}}
  195.     newRotation.active = false
  196.     newRotation.held = false
  197.     newRotation.selectedAxis = 0
  198.     newRotation.angleLookup = {1, 1, 1}
  199.    
  200.     for i=1,3 do
  201.         local ref = {}
  202.         ref[i] = function() return 0 end
  203.         ref[i + 1 > 3 and ((i + 1) % 4) + 1 or i + 1] = math.cos
  204.         ref[i + 2 > 3 and ((i + 2) % 4) + 1 or i + 2] = math.sin
  205.        
  206.         local color = Color3.fromRGB(i == 1 and 255 or 0, i == 2 and 255 or 0, i == 3 and 255 or 0)
  207.        
  208.         for j=1,13 do
  209.             if j < 13 then
  210.                 local step = math.pi * (j/6)
  211.                 newRotation.rotationLookup[i][j] = Vector3.new(ref[1](step), ref[2](step), ref[3](step))
  212.             end
  213.            
  214.             local line = Drawing.new("Line")
  215.             line.Visible = true
  216.             line.Thickness = 5
  217.             line.Color = color
  218.             newRotation.lineLookup[i][j] = line
  219.         end
  220.        
  221.         local circle = Drawing.new("Circle")
  222.         circle.Visible = true
  223.         circle.Color = color
  224.         circle.Filled = true
  225.         circle.Radius = 10
  226.         circle.Position = Vector2.new(-2000, -2000)
  227.         newRotation.lineLookup[i][14] = circle
  228.        
  229.         local text = Drawing.new("Text")
  230.         text.Visible = true
  231.         text.Font = Drawing.Fonts.System
  232.         text.Size = 18
  233.         text.Color = Color3.new():lerp(color, 0.3)
  234.         text.Outline = false
  235.         newRotation.lineLookup[i][15] = text
  236.     end
  237.    
  238.     return newRotation
  239. end
  240.  
  241. function rotation:selectAxis(keyState)
  242.     self.tabActivated = keyState == 1
  243.     if self.tabActivated then
  244.         self.selectedAxis = math.clamp((self.selectedAxis + 1) % 4, 1, 3)
  245.     end
  246. end
  247.  
  248. function rotation:toggle(keyState)
  249.     if keyState == 1 and headObject.recentHand.alpha < 0.05 and not self.held then
  250.         self.active = not self.active
  251.        
  252.         if not self.active then
  253.             self:updateAxes(0)
  254.             self.selectedAxis = 0
  255.             self.held = false
  256.             headObject.recentHand:updateTarget()
  257.         end
  258.     end
  259. end
  260.  
  261. function rotation:updateAxes(visibleOverride)
  262.     local basePos = headObject.recentHand.realHand.Base.Position
  263.     local basePoint = cam:WorldToViewportPoint(basePos)
  264.  
  265.     for i=1,3 do
  266.         for j=1,12 do
  267.             local vec, visible = cam:WorldToViewportPoint(basePos + (self.rotationLookup[i][j] * 10))
  268.             local vec2, visible2 = cam:WorldToViewportPoint(basePos + ((self.rotationLookup[i][j + 1] or self.rotationLookup[i][1]) * 10))
  269.            
  270.             local line = self.lineLookup[i][j]
  271.            
  272.             line.Transparency = visibleOverride or ((visible and visible2) and 1 or 0)
  273.             line.From = Vector2.new(vec.x, vec.y)
  274.             line.To = Vector2.new(vec2.x, vec2.y)
  275.         end
  276.         local axisRotation = headObject.recentHand.rotation[i]
  277.        
  278.         local axisMover = self.lineLookup[i][13]
  279.         local axisCircle = self.lineLookup[i][14]
  280.         local axisText = self.lineLookup[i][15]
  281.        
  282.         axisMover.From = Vector2.new(basePoint.x, basePoint.y)
  283.         axisMover.To = self.lineLookup[i][math.clamp(axisRotation < 1 and 12 or axisRotation, 1, 12)].From -- sorry, lazy
  284.         axisMover.Transparency = visibleOverride or 1
  285.        
  286.         axisCircle.Position = self.lineLookup[i][13].To
  287.         axisCircle.Transparency = visibleOverride or 1
  288.        
  289.        
  290.        
  291.         axisText.Position = self.lineLookup[2][3].From + axisText.TextBounds
  292.         axisText.Text = string.char(87 + self.selectedAxis) .. ": " .. math.deg(axisRotation * (math.pi / 6))
  293.         axisText.Transparency = visibleOverride or ((self.held or self.tabActivated) and self.selectedAxis == i and 1 or 0)
  294.        
  295.         local mousePos = services.UserInputService:GetMouseLocation()
  296.         if self.held and (self.lineLookup[i][14].Position - mousePos).magnitude < 10 and self.selectedAxis == 0 then
  297.             self.selectedAxis = i
  298.         end
  299.     end
  300. end
  301.  
  302. function rotation:updateAxisMover(keyState, direction)
  303.     if keyState and direction then
  304.         if self.tabActivated and keyState == 1 then
  305.             headObject.recentHand.rotation[self.selectedAxis] = (headObject.recentHand.rotation[self.selectedAxis] + direction) % 12
  306.             headObject.recentHand:updateTarget()
  307.         end
  308.         return
  309.     end
  310.  
  311.     if self.selectedAxis ~= 0 then
  312.         local mousePos = services.UserInputService:GetMouseLocation()
  313.        
  314.         local circlePos = self.lineLookup[self.selectedAxis][12].From
  315.        
  316.         local handPos = self.lineLookup[self.selectedAxis][13].From
  317.        
  318.         local mouseDir = self.selectedAxis == 1 and headObject.recentHand.id == "r" and (Vector2.new(-mousePos.x + (handPos.x * 2), mousePos.y) - handPos).unit or (mousePos - handPos).unit
  319.         -- mouse angle relating to the red circle is reflected on the right hand, so i "re-reflect" it. bad practice
  320.        
  321.         local circleDir = (circlePos - handPos).unit
  322.        
  323.         local rotationTheta = angleBetween(mouseDir, circleDir)
  324.        
  325.         local direction = mouseDir:Cross(circleDir)
  326.        
  327.         rotationTheta = direction > 0 and rotationTheta or (2 * math.pi) - rotationTheta
  328.        
  329.         if rotationTheta == rotationTheta then
  330.             headObject.recentHand.rotation[self.selectedAxis] = math.floor(6 * rotationTheta / math.pi)
  331.            
  332.             local hand = headObject.recentHand
  333.            
  334.             hand.targetPosition *= CFrame.Angles(hand.targetPosition:inverse():ToEulerAnglesXYZ()) * hand:calculateEndRotation()
  335.             hand.replicatePosition:Fire()
  336.         end
  337.     end
  338. end
  339.  
  340. function head:new(realHeadset)
  341.     local newHead = setmetatable({realHeadset = realHeadset}, head)
  342.    
  343.     newHead.leftHand = hand:new(false, realHeadset.lHand)
  344.     newHead.rightHand = hand:new(true, realHeadset.rHand)
  345.     newHead.canOffset = false
  346.     newHead.recentHand = newHead.leftHand
  347.     newHead.handOffset = 0
  348.     newHead.handAngle = math.pi / 4
  349.    
  350.     newHead.rotationManager = rotation:new()
  351.    
  352.     newHead.chatRemote = debug.getupvalue(realHeadset.ButtonPressed, 3)
  353.    
  354.     cam:GetPropertyChangedSignal("CameraSubject"):connect(function()
  355.         if cam.CameraSubject ~= headObject.realHeadset.Head then
  356.             cam.CameraType = Enum.CameraType.Custom
  357.         end
  358.     end)
  359.    
  360.     services.UserInputService.WindowFocused:connect(function()
  361.         newHead.realHeadset.StickPosition = Vector3.new(0, 0, 0)
  362.         newHead.realHeadset.Stick2 = 0
  363.     end)
  364.    
  365.     return newHead
  366. end
  367.  
  368. local ind, nc, nind
  369.  
  370. local realVrService = game:GetService("VRService")
  371.  
  372. local fakeVrService = setmetatable({
  373.     VREnabled = true,
  374.     SetTouchpadMode = function()
  375.     end,
  376.     RecenterUserHeadCFrame = function()
  377.     end,
  378.     GetUserCFrameEnabled = function(cf)
  379.         return true
  380.     end,
  381.     GetUserCFrame = function(cf)
  382.         return CFrame.new()
  383.     end
  384.  
  385. }, {
  386.     __index = function(t, k)
  387.         local real = ind(realVrService, k)
  388.         if typeof(real) == "RBXScriptSignal" then
  389.             events[k] = events[k] or {
  390.                 Name = k,
  391.                 Connect = function(t, f)
  392.                     t.Function = f
  393.  
  394.                     if t.Name == "UserCFrameChanged" then
  395.                         headObject = head:new(debug.getupvalue(t.Function, 1))
  396.                        
  397.                         services.UserInputService.InputBegan:connect(function(i)
  398.                             headObject:handleInput(i, 1)
  399.                         end)
  400.  
  401.                         services.UserInputService.InputChanged:connect(function(i)
  402.                             headObject:handleInput(i, i.UserInputType == Enum.UserInputType.MouseWheel and i.Position.z or 0)
  403.                         end)
  404.  
  405.                         services.UserInputService.InputEnded:connect(function(i)
  406.                             headObject:handleInput(i, -1)
  407.                         end)
  408.                     end
  409.  
  410.                 end,
  411.                 Fire = function(t, ...)
  412.                     return t.Function(...)
  413.                 end
  414.             }
  415.  
  416.             return events[k]
  417.         end
  418.  
  419.         return real
  420.     end,
  421.     __call = function(t, method, vr, ...)
  422.         return t[method](...)
  423.     end
  424. })
  425.  
  426. ind = hookmetamethod(game, "__index", function(...)
  427.     local t, k = ...
  428.  
  429.     local scr = getcallingscript()
  430.  
  431.     if t == realVrService and not (scr and ind(scr, "Name") == "CameraModule") then
  432.         return fakeVrService[k]
  433.     end
  434.  
  435.     return ind(...)
  436. end)
  437.  
  438. nc = hookmetamethod(game, "__namecall", function(...)
  439.     local t = ...
  440.  
  441.     if t == realVrService then
  442.         local method = getnamecallmethod()
  443.         return fakeVrService(method, ...)
  444.     elseif t == game.GetService(game, "StarterGui") and game.IsLoaded(game) then
  445.         return
  446.     end
  447.  
  448.     return nc(...)
  449. end)
  450.  
  451. nind = hookmetamethod(game, "__newindex", function(...)
  452.     local t, k, v = ...
  453.    
  454.     local scr = getcallingscript()
  455.    
  456.     if t == cam and headObject then
  457.         if k == "CFrame" and events.UserCFrameChanged then
  458.        
  459.             events.UserCFrameChanged:Fire(Enum.UserCFrame.Head, CFrame.Angles(cam.CFrame:ToEulerAnglesXYZ()))
  460.            
  461.             if headObject.rotationManager.active then
  462.            
  463.                 headObject.rotationManager:updateAxes()
  464.                
  465.                 if headObject.rotationManager.held then
  466.                     headObject.rotationManager:updateAxisMover()
  467.                 end
  468.             end
  469.            
  470.             if headObject.rotationManager.tabActivated and services.UserInputService:IsKeyDown(Enum.KeyCode.Left) or services.UserInputService:IsKeyDown(Enum.KeyCode.Right) then -- prevent controls from messing with camera
  471.                 return
  472.             end
  473.         elseif k == "CameraType" then
  474.             nind(t, k, Enum.CameraType.Custom)
  475.             nind(t, "CameraSubject", headObject.realHeadset.Head)
  476.             headObject.leftHand:updateTarget()
  477.             headObject.rightHand:updateTarget()
  478.         end
  479.         if not (scr and scr.Name == "CameraModule") and not checkcaller() then
  480.             return
  481.         end
  482.     end
  483.    
  484.     nind(t, k, v)
  485. end)
  486.  
  487. p = services.Players.LocalPlayer or (function()
  488.     services.Players:GetPropertyChangedSignal("LocalPlayer"):wait() -- this doesnt return anything for some reason??
  489.     return services.Players.LocalPlayer
  490. end)()
  491.  
  492. p.Chatted:connect(function(c)
  493.     services.ReplicatedStorage.COM.Chat:FireServer("Chat", c)
  494. end)
Advertisement
Comments
Add Comment
Please, Sign In to add comment