Super-Nostalgia-Zone/UI/Mouse/ClickToMove.client.lua

310 lines
11 KiB
Lua

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- @CloneTrooper1019, 2018
-- ClickToMove
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Constants
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
local ContextActionService = game:GetService("ContextActionService")
local GuiService = game:GetService("GuiService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local TeleportService = game:GetService("TeleportService")
local UserInputService = game:GetService("UserInputService")
local IS_TOUCH = UserInputService.TouchEnabled
local ICON_IDLE = "rbxassetid://334630296"
local ICON_HOVER = "rbxassetid://1000000"
local ICON_CLICK = "rbxasset://textures/DragCursor.png"
local DISK_OFFSET = CFrame.Angles(math.pi / 2,0,0)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Character Listener
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
local player = game.Players.LocalPlayer
local character, humanoid
local function onCharacterAdded(char)
humanoid = char:WaitForChild("Humanoid")
character = char
end
if player.Character then
onCharacterAdded(player.Character)
end
player.CharacterAdded:Connect(onCharacterAdded)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Gui Focus
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
local isMouseHoveringUi = false
local function onInputChanged(input, gameProcessed)
local inputType = input.UserInputType.Name
if inputType == "MouseMovement" then
isMouseHoveringUi = gameProcessed
end
end
local function isGuiFocused()
return isMouseHoveringUi or GuiService.SelectedObject ~= nil
end
UserInputService.InputChanged:Connect(onInputChanged)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Movement Goal
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
local currentGoal, moveSignal
local function findAngleBetweenXZVectors(vec2, vec1)
return math.atan2(vec1.X * vec2.Z - vec1.Z * vec2.X, vec1.X * vec2.X + vec1.Z * vec2.Z)
end
local function isFinite(num)
return num == num and num ~= 1/0 and num ~= -1/0
end
local function rotateCameraTowardsGoal(dt)
local camera = workspace.CurrentCamera
if camera then
local cf = camera.CFrame
local focus = camera.Focus
local desiredAngle = CFrame.new(cf.Position, currentGoal).lookVector
local currentAngle = cf.LookVector
local angleBetween = findAngleBetweenXZVectors(desiredAngle, currentAngle)
if isFinite(angleBetween) then
local abs = math.abs(angleBetween)
local sign = math.sign(angleBetween)
local rotation = math.min(dt * .6, abs)
local cfLocal = focus:toObjectSpace(cf)
camera.CFrame = focus * CFrame.Angles(0, -rotation * sign, 0) * cfLocal
end
end
end
local function finishGoal()
if currentGoal then
currentGoal = nil
end
if moveSignal then
moveSignal:Disconnect()
moveSignal = nil
end
end
local function clickToMove(goal)
finishGoal()
currentGoal = goal
moveSignal = humanoid.MoveToFinished:Connect(finishGoal)
humanoid:Move(Vector3.new(1,1,1))
humanoid:MoveTo(currentGoal)
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Green Disk
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
local mouse = player:GetMouse()
local mouseIcon = script.Parent
mouse.TargetFilter = workspace.CurrentCamera
local lastTarget
local lastTargetCanClick = false
local adorn = Instance.new("Part", script)
local disk = Instance.new("CylinderHandleAdornment")
disk.Name = "Disk"
disk.Color3 = Color3.new(0,1,0)
disk.Radius = 1
disk.Height = 0.2
disk.Visible = false
disk.Adornee = adorn
disk.Parent = script
local goalDisk = disk:Clone()
goalDisk.Name = "Goal"
goalDisk.Parent = script
local function hasTool()
if character then
return character:FindFirstChildOfClass("Tool") ~= nil
end
return false
end
local function isFirstPerson()
if character then
local head = character:FindFirstChild("Head")
if head then
return head.LocalTransparencyModifier == 1
end
end
return false
end
local function canClickTarget()
local target = mouse.Target
if target then
if target ~= lastTarget then
local canClick = false
local clickDetector = target:FindFirstChildOfClass("ClickDetector")
if clickDetector then
local dist = player:DistanceFromCharacter(target.Position)
if dist <= clickDetector.MaxActivationDistance then
canClick = true
end
end
lastTarget = target
lastTargetCanClick = canClick
end
return lastTargetCanClick
end
end
local function canRenderDisk(rendering)
if not TeleportService:GetTeleportSetting("ClickToMove") then
return false
end
if rendering and IS_TOUCH then
return false
end
if humanoid then
local movement = humanoid.MoveDirection
if movement.Magnitude == 0 then
local pos = mouse.Hit.Position
local dist = player:DistanceFromCharacter(pos)
if dist < 32 then
local blockers = {hasTool, isFirstPerson, canClickTarget, isGuiFocused}
for _,blocker in pairs(blockers) do
if blocker() then
return false
end
end
return true
end
else
finishGoal()
end
end
return false
end
local function render3dAdorn(dt)
local dt = math.min(0.1, dt)
disk.Visible = canRenderDisk(true)
if disk.Visible then
disk.CFrame = CFrame.new(mouse.Hit.Position) * DISK_OFFSET
mouseIcon.Image = ICON_HOVER
elseif canClickTarget() then
mouseIcon.Image = ICON_CLICK
elseif not hasTool() then
mouseIcon.Image = ICON_IDLE
end
if currentGoal then
goalDisk.Visible = true
goalDisk.CFrame = CFrame.new(currentGoal) * DISK_OFFSET
rotateCameraTowardsGoal(dt)
else
goalDisk.Visible = false
end
end
RunService.Heartbeat:Connect(render3dAdorn)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Click Action
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
local function onInputBegan(input, gameProcessed)
local goal = mouse.Hit.Position
if not gameProcessed and canRenderDisk() and humanoid then
local name = input.UserInputType.Name
if name == "MouseButton1" then
clickToMove(goal)
elseif name == "Touch" then
wait(.1)
if input.UserInputState == Enum.UserInputState.End then
clickToMove(goal)
end
elseif name == "Gamepad1" then
if input.KeyCode == Enum.KeyCode.ButtonR2 then
clickToMove(goal)
end
end
end
end
UserInputService.InputBegan:Connect(onInputBegan)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- OBLITERATE the invasive click to move mode that Roblox provides
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
pcall(function ()
if IS_TOUCH then
local playerScripts = player:WaitForChild("PlayerScripts")
local no = function () end
spawn(function ()
local controlScript = playerScripts:WaitForChild("ControlScript", 86400)
if controlScript then
local masterControl = controlScript:WaitForChild("MasterControl")
local clickToMove = masterControl:WaitForChild("ClickToMoveController")
clickToMove = require(clickToMove)
clickToMove:Disable()
clickToMove.Enable = no
end
end)
spawn(function ()
local playerModule = playerScripts:WaitForChild("PlayerModule", 86400)
if playerModule then
local controlModule = playerModule:WaitForChild("ControlModule")
local clickToMove = controlModule:WaitForChild("ClickToMoveController")
clickToMove = require(clickToMove)
clickToMove:Stop()
clickToMove.Enable = no
end
end)
end
end)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------