Advertisement
remi_

ControlModule - Client

Jun 29th, 2021
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 13.83 KB | None | 0 0
  1. --// Made by remi
  2. -- Control Module which handles the control of the vehicle.
  3. local playerService = game:GetService("Players")
  4. local userInputService = game:GetService("UserInputService")
  5. local contextActionService = game:GetService("ContextActionService")
  6. local runService = game:GetService("RunService")
  7.  
  8. local player = playerService.LocalPlayer
  9.  
  10. local speed_meter = script.CarControlGUI
  11. local interface = speed_meter.SpeedOMeter
  12. local display = interface.SpeedDisplay
  13. local needle = interface.Needle
  14. local reverse_indicator = interface.ReverseIndicator
  15. local reverse_light = reverse_indicator.Light
  16. local hover_indicator = interface.HoverMode
  17. local hover_light = hover_indicator.Light
  18.  
  19. local function reset_gui()
  20.     display.Text = "0"
  21.     needle.Rotation = 0
  22.     reverse_light.BackgroundColor3 = Color3.fromRGB(65, 0, 1)
  23.     hover_light.BackgroundColor3 = Color3.fromRGB(65, 0, 1)
  24. end
  25.  
  26. local camera = workspace.CurrentCamera
  27. local camera_height = 5
  28. local camera_distance = 22
  29.  
  30. local looking_back = false
  31.  
  32. local camera_sensitivity = 0.2
  33. local camera_fov = 70
  34. local camera_x_goal = 0
  35. local camera_y_goal = 0
  36. local camera_x = 0
  37. local camera_y = 0
  38.  
  39. local mouse_idle_count = 0.7
  40. local mouse_idle_time = 0
  41.  
  42. local steer_angle = 30
  43.  
  44. local steer = 0
  45. local throttle = 0
  46. local altitude_gain = 0
  47. local altitude = 0
  48.  
  49. local VECTOR3_ZERO = Vector3.new()
  50. local VECTOR2_ZERO = Vector2.new()
  51. local CFRAME_ZERO = CFrame.new()
  52.  
  53. local HORIZONTAL = Vector3.new(1, 0, 1)
  54.  
  55. local flipping = false
  56.  
  57. local function raycast_parameters(...)
  58.     local params = RaycastParams.new()
  59.     params.FilterType = Enum.RaycastFilterType.Blacklist
  60.     params.FilterDescendantsInstances = {...}
  61.    
  62.     return params
  63. end
  64.  
  65. local function is_upsidedown(car, chasis)
  66.     if flipping then return flipping end
  67.    
  68.     local up_vector = chasis.CFrame.UpVector
  69.     local right_vector = chasis.CFrame.RightVector
  70.     local position = chasis.Position
  71.    
  72.     local difference = (position + up_vector).Y - position.Y
  73.     local upside_down = difference <= 0.5
  74.    
  75.     local parameters = raycast_parameters(car, player.Character)
  76.    
  77.     local up_cast = up_vector * (chasis.Size.Y/1.7)
  78.     local right_cast = right_vector * (chasis.Size.X/1.7)
  79.     local left_cast = right_vector * (-chasis.Size.X/1.7)
  80.    
  81.     local up_result = workspace:Raycast(position, up_cast, parameters)
  82.     local right_result = workspace:Raycast(position, right_cast, parameters)
  83.     local left_result = workspace:Raycast(position, left_cast, parameters)
  84.    
  85.     return upside_down and (up_result or right_result or left_result)
  86. end
  87.  
  88. local function processGroundSteer(steer_constraints, steer)
  89.     for _, constraint in ipairs(steer_constraints) do
  90.         local orientation = constraint.Attachment0.Orientation
  91.         constraint.Attachment0.Orientation = Vector3.new(orientation.X, steer ,orientation.Z)
  92.     end
  93. end
  94.  
  95. local function processGroundThrottle(origin, constraints0, constraints1, speed)
  96.     for _, constraint in ipairs(constraints0) do
  97.         local relative_pos = origin:PointToObjectSpace(constraint.Attachment0.WorldPosition)
  98.        
  99.         constraint.AngularVelocity = relative_pos.X > 0 and speed or -speed
  100.     end
  101.    
  102.     for _, constraint in ipairs(constraints1) do
  103.         local relative_pos = origin:PointToObjectSpace(constraint.Attachment0.WorldPosition)
  104.  
  105.         constraint.AngularVelocity = relative_pos.X > 0 and speed or -speed
  106.     end
  107. end
  108.  
  109. local function calculateFriction(velocity, wheels, chasis)
  110.     local origin = chasis.CFrame
  111.    
  112.     for _, wheel in ipairs(wheels) do
  113.         local relative_pos = origin:PointToObjectSpace(wheel.Position)
  114.         if relative_pos.Z > 0 then continue end
  115.        
  116.         local friction = velocity <= 80 and 2 or 1.98
  117.        
  118.         if wheel.CustomPhysicalProperties.Friction == 1.9 then continue end
  119.         local default = wheel.CustomPhysicalProperties
  120.         wheel.CustomPhysicalProperties = PhysicalProperties.new(
  121.             default.Density,
  122.             default.Elasticity,
  123.             default.ElasticityWeight,
  124.             friction,
  125.             default.FrictionWeight
  126.         )
  127.     end
  128. end
  129.  
  130. local function calculateFlyForce(chasis, seat, steer, speed, altitude, dt)
  131.     local vertical_force = Vector3.new(0, altitude, 0)
  132.     local front_speed = -chasis.CFrame.LookVector * speed * 1.7
  133.     local angular_velocity = Vector3.new(0, math.clamp(steer * 0.5, -25, 25), 0)
  134.    
  135.     return vertical_force + front_speed, angular_velocity
  136. end
  137.  
  138. local function turnWheels(wheels)
  139.     for index, wheel in ipairs(wheels) do
  140.         local zero = wheel.Motor6D.Part0.CFrame:Inverse()
  141.         local goal = CFrame.new(wheel.Position, wheel.Position-Vector3.new(0, 1, 0)) * CFrame.Angles(0, math.rad(90), 0)
  142.        
  143.         wheel.Motor6D.C0 = zero * goal
  144.     end
  145. end
  146.  
  147. local function resetWheels(wheels)
  148.     for index, wheel in ipairs(wheels) do
  149.         wheel.Motor6D.C0 = CFRAME_ZERO
  150.     end
  151. end
  152.  
  153. local function reset(steer, power)
  154.     for _, constraint in ipairs(steer) do
  155.         constraint.AngularVelocity =  0
  156.        
  157.         local orientation = constraint.Attachment0.Orientation
  158.         constraint.Attachment0.Orientation = Vector3.new(orientation.X, 0 ,orientation.Z)
  159.     end
  160.    
  161.     for _, constraint in ipairs(power) do
  162.         constraint.AngularVelocity =  0
  163.     end
  164. end
  165.  
  166. local control = {}
  167. control.inputs = {
  168.     GainAltitude = Enum.KeyCode.E;
  169.     LoseAltitude = Enum.KeyCode.Q;
  170.     Turnback = Enum.UserInputType.MouseButton3;
  171.     ChangeMode = Enum.KeyCode.H;
  172. }
  173.  
  174. local modes = {
  175.     "ground";
  176.     "hover";
  177. }
  178.  
  179. local current_mode = 1
  180.  
  181. function control.Init(car, speed, turn_speed, torque, acceleration, vertical_speed, vertical_acceleration)
  182.     if control.car then return error("Player is already controlling a vehicle.") end
  183.    
  184.     local aesthetics = car.Aesthetics
  185.     local constraints = car.Body.Constraints
  186.     local physics = car.Physics
  187.    
  188.     control.car = car
  189.     control.body = car.Body
  190.    
  191.     control.seat = car.Seat
  192.     control.chasis = aesthetics.Chasis
  193.    
  194.     control.wheels = physics.Wheels:GetChildren()
  195.    
  196.     control.speed = speed
  197.     control.turn_speed = turn_speed
  198.     control.torque = torque
  199.     control.acceleration = acceleration
  200.     control.vertical_speed = vertical_speed
  201.     control.vertical_acceleration = vertical_acceleration
  202.    
  203.     control.fly_force = car.Body.FlyForce
  204.     control.control_force = car.Body.ControlForce
  205.     control.gyro = car.Body.Gyro
  206.     control.fly_rotation = car.Body.FlyRotation
  207.    
  208.     control.power = constraints.Powered:GetChildren()
  209.     control.steer = constraints.Steering:GetChildren()
  210.    
  211.     control.state = "ground"
  212.    
  213.     camera.CameraType = Enum.CameraType.Scriptable
  214.     userInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
  215.     userInputService.MouseIconEnabled = false
  216.    
  217.     for input_name, keybind in pairs(control.inputs) do
  218.         contextActionService:BindAction(input_name, control.ProcessInput, false, keybind)
  219.     end
  220.  
  221.     speed_meter.Parent = player.PlayerGui
  222.    
  223.     runService:BindToRenderStep("ControlUpdate", Enum.RenderPriority.Last.Value, control.Update)
  224. end
  225.  
  226. function control.Stop()
  227.     runService:UnbindFromRenderStep("ControlUpdate")
  228.    
  229.     flipping = false
  230.     steer = 0
  231.     throttle = 0
  232.     altitude = 0
  233.     altitude_gain = 0
  234.     camera_x = 0
  235.     camera_y = 0
  236.     camera_distance = 22
  237.    
  238.     for input_name, keybind in pairs(control.inputs) do
  239.         contextActionService:UnbindAction(input_name)
  240.     end
  241.    
  242.     reset_gui()
  243.     reset(control.steer, control.power)
  244.     current_mode = 1
  245.     control.state = "ground"
  246.     control.body.Chasis.C0 = CFRAME_ZERO
  247.     resetWheels(control.wheels)
  248.    
  249.     control.fly_force.Force = VECTOR3_ZERO
  250.     control.control_force.Velocity = VECTOR3_ZERO
  251.     control.fly_rotation.AngularVelocity = VECTOR3_ZERO
  252.    
  253.     speed_meter.Parent = script
  254.    
  255.     camera.CameraType = Enum.CameraType.Custom
  256.     userInputService.MouseBehavior = Enum.MouseBehavior.Default
  257.     userInputService.MouseIconEnabled = true
  258.    
  259.     for k, v in pairs(control) do
  260.         if k == "inputs" or k == "state" then continue end
  261.         if type(v) == "function" then continue end
  262.         control[k] = nil
  263.     end
  264. end
  265.  
  266. function control.ProcessInput(input_name, state, input)
  267.     if input_name == "Turnback" then
  268.         camera_distance = -camera_distance
  269.         looking_back = not looking_back
  270.     elseif input_name == "ChangeMode" and state == Enum.UserInputState.Begin then
  271.         current_mode += 1
  272.         if current_mode > #modes then current_mode = 1 end
  273.         local state = modes[current_mode]
  274.        
  275.         control.state = state
  276.         if state == "ground" then
  277.             resetWheels(control.wheels)
  278.             control.body.Chasis.C0 = CFRAME_ZERO
  279.             hover_light.BackgroundColor3 = Color3.fromRGB(65, 0, 1)
  280.         elseif state == "hover" then
  281.             hover_light.BackgroundColor3 = Color3.fromRGB(255, 76, 76)
  282.         end
  283.     elseif input_name == "GainAltitude" then
  284.         if state == Enum.UserInputState.Begin then
  285.             altitude_gain = 1
  286.         else
  287.             altitude_gain = 0
  288.         end
  289.     elseif input_name == "LoseAltitude" then
  290.         if state == Enum.UserInputState.Begin then
  291.             altitude_gain = -1
  292.         else
  293.             altitude_gain = 0
  294.         end
  295.     end
  296. end
  297.  
  298. function control.Update(dt)
  299.     local mouseDelta = userInputService:GetMouseDelta()
  300.     local chasis = control.chasis
  301.     local velocity = (chasis.Velocity * HORIZONTAL).Magnitude
  302.    
  303.     local fly_force = control.fly_force
  304.     local control_force = control.control_force
  305.     local fly_rotation = control.fly_rotation
  306.    
  307.     local steer_goal = -control.seat.SteerFloat * steer_angle
  308.     steer += (steer_goal - steer) * math.min(dt * control.turn_speed, 1)
  309.     steer = math.abs(steer) < 0.1 and 0 or steer
  310.    
  311.     local throttle_goal = control.seat.ThrottleFloat
  312.     throttle += (throttle_goal - throttle) * math.min(dt * control.acceleration, 1)
  313.     local speed = throttle * control.speed
  314.     speed = math.abs(speed) < 0.1 and 0 or speed
  315.    
  316.     local altitude_goal = altitude_gain * control.vertical_speed
  317.     altitude += (altitude_goal - altitude) * math.min(dt * control.vertical_acceleration, 1)
  318.     altitude = math.abs(altitude) < 0.1 and 0 or altitude
  319.    
  320.     local fov_goal = velocity > 70 and velocity or 70
  321.     camera_fov += (fov_goal - camera_fov) * dt
  322.     camera.FieldOfView = math.clamp(camera_fov, 70, 100)
  323.    
  324.     if control.state == "ground" then
  325.         control.control_force.MaxForce = VECTOR3_ZERO
  326.         control.gyro.MaxTorque = VECTOR3_ZERO
  327.         calculateFriction(chasis.Velocity.Magnitude, control.wheels, chasis)
  328.         processGroundSteer(control.steer, steer)
  329.         processGroundThrottle(chasis.CFrame, control.steer, control.power, speed)
  330.        
  331.         if is_upsidedown(control.car, chasis) and not flipping and velocity < 10 then
  332.             flipping = true
  333.         elseif fly_force ~= VECTOR3_ZERO and not flipping then
  334.             fly_rotation.AngularVelocity = VECTOR3_ZERO
  335.             fly_force.Force = VECTOR3_ZERO
  336.         elseif flipping then
  337.             fly_rotation.AngularVelocity = Vector3.new(0, 0, 1) * -math.clamp(steer, -15, 15)
  338.             fly_force.Force = steer == 0 and VECTOR3_ZERO or Vector3.new(0, 0.8, 0) * chasis.AssemblyMass * workspace.Gravity
  339.                    
  340.             local position = chasis.Position
  341.             local up_vector = chasis.CFrame.UpVector
  342.            
  343.             local parameters = raycast_parameters(control.car, player.Character)
  344.            
  345.             local larger_side = chasis.Size.X > chasis.Size.Y and chasis.Size.X or chasis.Size.Y
  346.            
  347.             local in_ground = workspace:Raycast(position, Vector3.new(0, -1.2, 0) * larger_side, parameters)
  348.            
  349.             if in_ground then
  350.                 local touching_ground = true
  351.                
  352.                 for _, wheel in ipairs(control.wheels) do
  353.                     local origin = wheel.Position
  354.                     local direction = -up_vector * wheel.Size.Y
  355.                    
  356.                     local result = workspace:Raycast(origin, direction, parameters)
  357.                     if not result then touching_ground = false break end
  358.                 end
  359.                
  360.                 local difference = (position + up_vector).Y - position.Y
  361.                 local standing = difference > 0.5
  362.                
  363.                 if touching_ground and standing then
  364.                     flipping = false
  365.                 end
  366.             else
  367.                 flipping = false
  368.             end
  369.         end
  370.     elseif control.state == "hover" then
  371.         control.control_force.MaxForce = Vector3.new(1, 1, 1) * 40000
  372.         control.gyro.MaxTorque = Vector3.new(1, 0, 1) * 400000
  373.         control.gyro.CFrame = CFrame.fromOrientation(0, 0, 0)
  374.         turnWheels(control.wheels)
  375.         local movement_force, angular_velocity = calculateFlyForce(chasis, control.seat, steer, speed, altitude, dt)
  376.        
  377.         if velocity > 2 then
  378.             local angle = chasis.CFrame.RightVector:Dot(chasis.Velocity.Unit) * -4
  379.             control.body.Chasis.C0 = CFrame.Angles(0, 0, math.rad(angle))
  380.         else
  381.             control.body.Chasis.C0 = CFRAME_ZERO
  382.         end
  383.        
  384.         fly_force.Force = Vector3.new(0, 1, 0) * chasis.AssemblyMass * workspace.Gravity
  385.         fly_rotation.AngularVelocity = angular_velocity
  386.         control_force.Velocity = movement_force
  387.     end
  388.    
  389.     if math.floor(chasis.CFrame:VectorToObjectSpace(chasis.Velocity).Z) < -10 and throttle < 0 then
  390.         if looking_back == false then
  391.             camera_distance = -camera_distance
  392.             looking_back = true
  393.         end
  394.     else
  395.         if camera_distance < 0 and not userInputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton3) then
  396.             camera_distance = -camera_distance
  397.             looking_back = false
  398.         end
  399.     end
  400.    
  401.     local rotation_goal = (math.abs(speed) / control.speed) * 180
  402.     needle.Rotation += (rotation_goal - needle.Rotation) * dt
  403.     display.Text = math.floor(velocity)
  404.     reverse_light.BackgroundColor3 = speed >= 0 and Color3.fromRGB(65, 0, 1) or Color3.fromRGB(255, 76, 76)
  405.    
  406.     camera_x_goal = math.clamp(camera_x_goal-mouseDelta.X*camera_sensitivity, -130, 130)
  407.     camera_y_goal = math.clamp(camera_y_goal+mouseDelta.Y*camera_sensitivity, -18, 45)
  408.     camera_x_goal = math.abs(camera_x_goal) < 0.05 and 0 or camera_x_goal
  409.     camera_y_goal = math.abs(camera_y_goal) < 0.05 and 0 or camera_y_goal
  410.    
  411.     if mouseDelta == VECTOR2_ZERO and not (camera_x_goal == 0 and camera_y_goal == 0) then
  412.         mouse_idle_time += dt
  413.     else
  414.         mouse_idle_time = 0
  415.     end
  416.    
  417.     if mouse_idle_time >= mouse_idle_count then
  418.         camera_x_goal -= camera_x_goal * camera_sensitivity
  419.         camera_y_goal -= camera_y_goal * camera_sensitivity
  420.     end
  421.    
  422.     camera_x += (camera_x_goal - camera_x)
  423.     camera_y += (camera_y_goal - camera_y)
  424.     camera_x = math.abs(camera_x) <= 0.05 and 0 or camera_x
  425.     camera_y = math.abs(camera_y) <= 0.05 and 0 or camera_y
  426.    
  427.     local offset = CFrame.lookAt(Vector3.new(0, camera_height, -camera_distance), (chasis.CFrame.LookVector * Vector3.new(1, 0, 1)) + Vector3.new(0, camera_height, 0))
  428.    
  429.     camera.CFrame = chasis.CFrame * CFrame.fromEulerAnglesYXZ(math.rad(camera_y), math.rad(camera_x), 0) * offset
  430. end
  431.  
  432. return control
  433.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement