Port more corescripts to yuescript
This commit is contained in:
parent
55d3a622aa
commit
686e23f0d7
|
|
@ -0,0 +1,526 @@
|
|||
local New
|
||||
New = function(className, name, props)
|
||||
if not (props ~= nil) then
|
||||
props = name
|
||||
name = nil
|
||||
end
|
||||
local obj = Instance.new(className)
|
||||
if name then
|
||||
obj.Name = name
|
||||
end
|
||||
local parent
|
||||
for k, v in pairs(props) do
|
||||
if type(k) == "string" then
|
||||
if k == "Parent" then
|
||||
parent = v
|
||||
else
|
||||
obj[k] = v
|
||||
end
|
||||
elseif type(k) == "number" and type(v) == "userdata" then
|
||||
v.Parent = obj
|
||||
end
|
||||
end
|
||||
obj.Parent = parent
|
||||
return obj
|
||||
end
|
||||
while not Game do
|
||||
wait()
|
||||
end
|
||||
while not Game:FindFirstChild("Players") do
|
||||
wait()
|
||||
end
|
||||
while not Game.Players.LocalPlayer do
|
||||
wait()
|
||||
end
|
||||
while not Game:FindFirstChild("CoreGui") do
|
||||
wait()
|
||||
end
|
||||
while not Game.CoreGui:FindFirstChild("RobloxGui") do
|
||||
wait()
|
||||
end
|
||||
local userInputService = Game:GetService("UserInputService")
|
||||
local success = pcall(function()
|
||||
return userInputService:IsLuaTouchControls()
|
||||
end)
|
||||
if not success then
|
||||
script:Destroy()
|
||||
end
|
||||
local screenResolution = Game:GetService("GuiService"):GetScreenResolution()
|
||||
local isSmallScreenDevice
|
||||
isSmallScreenDevice = function()
|
||||
return screenResolution.y <= 320
|
||||
end
|
||||
local localPlayer = Game.Players.LocalPlayer
|
||||
local thumbstickSize = 120
|
||||
if isSmallScreenDevice() then
|
||||
thumbstickSize = 70
|
||||
end
|
||||
local touchControlsSheet = "rbxasset://textures/ui/TouchControlsSheet.png"
|
||||
local ThumbstickDeadZone = 5
|
||||
local ThumbstickMaxPercentGive = 0.92
|
||||
local thumbstickTouches = { }
|
||||
local jumpButtonSize = 90
|
||||
if isSmallScreenDevice() then
|
||||
jumpButtonSize = 70
|
||||
end
|
||||
local oldJumpTouches = { }
|
||||
local currentJumpTouch
|
||||
local CameraRotateSensitivity = 0.007
|
||||
local CameraRotateDeadZone = CameraRotateSensitivity * 16
|
||||
local CameraZoomSensitivity = 0.03
|
||||
local PinchZoomDelay = 0.2
|
||||
local cameraTouch
|
||||
Game:GetService("ContentProvider"):Preload(touchControlsSheet)
|
||||
local DistanceBetweenTwoPoints
|
||||
DistanceBetweenTwoPoints = function(point1, point2)
|
||||
local dx = point2.x - point1.x
|
||||
local dy = point2.y - point1.y
|
||||
return math.sqrt(dx * dx + dy * dy)
|
||||
end
|
||||
local transformFromCenterToTopLeft
|
||||
transformFromCenterToTopLeft = function(pointToTranslate, guiObject)
|
||||
return UDim2.new(0, pointToTranslate.x - guiObject.AbsoluteSize.x / 2, 0, pointToTranslate.y - guiObject.AbsoluteSize.y / 2)
|
||||
end
|
||||
local rotatePointAboutLocation
|
||||
rotatePointAboutLocation = function(pointToRotate, pointToRotateAbout, radians)
|
||||
local sinAnglePercent = math.sin(radians)
|
||||
local cosAnglePercent = math.cos(radians)
|
||||
local transformedPoint = pointToRotate
|
||||
transformedPoint = Vector2.new(transformedPoint.x - pointToRotateAbout.x, transformedPoint.y - pointToRotateAbout.y)
|
||||
local xNew = transformedPoint.x * cosAnglePercent - transformedPoint.y * sinAnglePercent
|
||||
local yNew = transformedPoint.x * sinAnglePercent + transformedPoint.y * cosAnglePercent
|
||||
transformedPoint = Vector2.new(xNew + pointToRotateAbout.x, yNew + pointToRotateAbout.y)
|
||||
return transformedPoint
|
||||
end
|
||||
local dotProduct
|
||||
dotProduct = function(v1, v2)
|
||||
return v1.x * v2.x + v1.y * v2.y
|
||||
end
|
||||
local stationaryThumbstickTouchMove
|
||||
stationaryThumbstickTouchMove = function(thumbstickFrame, thumbstickOuter, touchLocation)
|
||||
local thumbstickOuterCenterPosition = Vector2.new(thumbstickOuter.Position.X.Offset + thumbstickOuter.AbsoluteSize.x / 2, thumbstickOuter.Position.Y.Offset + thumbstickOuter.AbsoluteSize.y / 2)
|
||||
local centerDiff = DistanceBetweenTwoPoints(touchLocation, thumbstickOuterCenterPosition)
|
||||
if centerDiff > (thumbstickSize / 2) then
|
||||
local thumbVector = Vector2.new(touchLocation.x - thumbstickOuterCenterPosition.x, touchLocation.y - thumbstickOuterCenterPosition.y)
|
||||
local normal = thumbVector.unit
|
||||
if normal.x == math.nan or normal.x == math.inf then
|
||||
normal = Vector2.new(0, normal.y)
|
||||
end
|
||||
if normal.y == math.nan or normal.y == math.inf then
|
||||
normal = Vector2.new(normal.x, 0)
|
||||
end
|
||||
local newThumbstickInnerPosition = thumbstickOuterCenterPosition + (normal * (thumbstickSize / 2))
|
||||
thumbstickFrame.Position = transformFromCenterToTopLeft(newThumbstickInnerPosition, thumbstickFrame)
|
||||
else
|
||||
thumbstickFrame.Position = transformFromCenterToTopLeft(touchLocation, thumbstickFrame)
|
||||
end
|
||||
return Vector2.new(thumbstickFrame.Position.X.Offset - thumbstickOuter.Position.X.Offset, thumbstickFrame.Position.Y.Offset - thumbstickOuter.Position.Y.Offset)
|
||||
end
|
||||
local followThumbstickTouchMove
|
||||
followThumbstickTouchMove = function(thumbstickFrame, thumbstickOuter, touchLocation)
|
||||
local thumbstickOuterCenter = Vector2.new(thumbstickOuter.Position.X.Offset + thumbstickOuter.AbsoluteSize.x / 2, thumbstickOuter.Position.Y.Offset + thumbstickOuter.AbsoluteSize.y / 2)
|
||||
if DistanceBetweenTwoPoints(touchLocation, thumbstickOuterCenter) > thumbstickSize / 2 then
|
||||
local thumbstickInnerCenter = Vector2.new(thumbstickFrame.Position.X.Offset + thumbstickFrame.AbsoluteSize.x / 2, thumbstickFrame.Position.Y.Offset + thumbstickFrame.AbsoluteSize.y / 2)
|
||||
local movementVectorUnit = Vector2.new(touchLocation.x - thumbstickInnerCenter.x, touchLocation.y - thumbstickInnerCenter.y).unit
|
||||
local outerToInnerVectorCurrent = Vector2.new(thumbstickInnerCenter.x - thumbstickOuterCenter.x, thumbstickInnerCenter.y - thumbstickOuterCenter.y)
|
||||
local outerToInnerVectorCurrentUnit = outerToInnerVectorCurrent.unit
|
||||
local movementVector = Vector2.new(touchLocation.x - thumbstickInnerCenter.x, touchLocation.y - thumbstickInnerCenter.y)
|
||||
local crossOuterToInnerWithMovement = (outerToInnerVectorCurrentUnit.x * movementVectorUnit.y) - (outerToInnerVectorCurrentUnit.y * movementVectorUnit.x)
|
||||
local angle = math.atan2(crossOuterToInnerWithMovement, dotProduct(outerToInnerVectorCurrentUnit, movementVectorUnit))
|
||||
local anglePercent = angle * math.min(movementVector.magnitude / outerToInnerVectorCurrent.magnitude, 1.0)
|
||||
if math.abs(anglePercent) > 0.00001 then
|
||||
local outerThumbCenter = rotatePointAboutLocation(thumbstickOuterCenter, thumbstickInnerCenter, anglePercent)
|
||||
thumbstickOuter.Position = transformFromCenterToTopLeft(Vector2.new(outerThumbCenter.x, outerThumbCenter.y), thumbstickOuter)
|
||||
end
|
||||
thumbstickOuter.Position = UDim2.new(0, thumbstickOuter.Position.X.Offset + movementVector.x, 0, thumbstickOuter.Position.Y.Offset + movementVector.y)
|
||||
end
|
||||
thumbstickFrame.Position = transformFromCenterToTopLeft(touchLocation, thumbstickFrame)
|
||||
local thumbstickFramePosition = Vector2.new(thumbstickFrame.Position.X.Offset, thumbstickFrame.Position.Y.Offset)
|
||||
local thumbstickOuterPosition = Vector2.new(thumbstickOuter.Position.X.Offset, thumbstickOuter.Position.Y.Offset)
|
||||
if DistanceBetweenTwoPoints(thumbstickFramePosition, thumbstickOuterPosition) > thumbstickSize / 2 then
|
||||
local vectorWithLength = (thumbstickOuterPosition - thumbstickFramePosition).unit * thumbstickSize / 2
|
||||
thumbstickOuter.Position = UDim2.new(0, thumbstickFramePosition.x + vectorWithLength.x, 0, thumbstickFramePosition.y + vectorWithLength.y)
|
||||
end
|
||||
return Vector2.new(thumbstickFrame.Position.X.Offset - thumbstickOuter.Position.X.Offset, thumbstickFrame.Position.Y.Offset - thumbstickOuter.Position.Y.Offset)
|
||||
end
|
||||
local movementOutsideDeadZone
|
||||
movementOutsideDeadZone = function(movementVector)
|
||||
return (math.abs(movementVector.x) > ThumbstickDeadZone) or (math.abs(movementVector.y) > ThumbstickDeadZone)
|
||||
end
|
||||
local constructThumbstick
|
||||
constructThumbstick = function(defaultThumbstickPos, updateFunction, stationaryThumbstick)
|
||||
local thumbstickFrame = New("Frame", "ThumbstickFrame", {
|
||||
Active = true,
|
||||
Size = UDim2.new(0, thumbstickSize, 0, thumbstickSize),
|
||||
Position = defaultThumbstickPos,
|
||||
BackgroundTransparency = 1
|
||||
})
|
||||
New("ImageLabel", "InnerThumbstick", {
|
||||
Image = touchControlsSheet,
|
||||
ImageRectOffset = Vector2.new(220, 0),
|
||||
ImageRectSize = Vector2.new(111, 111),
|
||||
BackgroundTransparency = 1,
|
||||
Size = UDim2.new(0, thumbstickSize / 2, 0, thumbstickSize / 2),
|
||||
Position = UDim2.new(0, thumbstickFrame.Size.X.Offset / 2 - thumbstickSize / 4, 0, thumbstickFrame.Size.Y.Offset / 2 - thumbstickSize / 4),
|
||||
ZIndex = 2,
|
||||
Parent = thumbstickFrame
|
||||
})
|
||||
local outerThumbstick = New("ImageLabel", "OuterThumbstick", {
|
||||
Image = touchControlsSheet,
|
||||
ImageRectOffset = Vector2.new(0, 0),
|
||||
ImageRectSize = Vector2.new(220, 220),
|
||||
BackgroundTransparency = 1,
|
||||
Size = UDim2.new(0, thumbstickSize, 0, thumbstickSize),
|
||||
Position = defaultThumbstickPos,
|
||||
Parent = Game.CoreGui.RobloxGui
|
||||
})
|
||||
local thumbstickTouch
|
||||
local userInputServiceTouchMovedCon
|
||||
local userInputSeviceTouchEndedCon
|
||||
local startInputTracking
|
||||
startInputTracking = function(inputObject)
|
||||
if thumbstickTouch then
|
||||
return
|
||||
end
|
||||
if inputObject == cameraTouch then
|
||||
return
|
||||
end
|
||||
if inputObject == currentJumpTouch then
|
||||
return
|
||||
end
|
||||
if inputObject.UserInputType ~= Enum.UserInputType.Touch then
|
||||
return
|
||||
end
|
||||
thumbstickTouch = inputObject
|
||||
table.insert(thumbstickTouches, thumbstickTouch)
|
||||
thumbstickFrame.Position = transformFromCenterToTopLeft(thumbstickTouch.Position, thumbstickFrame)
|
||||
outerThumbstick.Position = thumbstickFrame.Position
|
||||
userInputServiceTouchMovedCon = userInputService.TouchMoved:connect(function(movedInput)
|
||||
if movedInput == thumbstickTouch then
|
||||
local movementVector
|
||||
if stationaryThumbstick then
|
||||
movementVector = stationaryThumbstickTouchMove(thumbstickFrame, outerThumbstick, Vector2.new(movedInput.Position.x, movedInput.Position.y))
|
||||
else
|
||||
movementVector = followThumbstickTouchMove(thumbstickFrame, outerThumbstick, Vector2.new(movedInput.Position.x, movedInput.Position.y))
|
||||
end
|
||||
if updateFunction then
|
||||
return updateFunction(movementVector, outerThumbstick.Size.X.Offset / 2)
|
||||
end
|
||||
end
|
||||
end)
|
||||
userInputSeviceTouchEndedCon = userInputService.TouchEnded:connect(function(endedInput)
|
||||
if endedInput == thumbstickTouch then
|
||||
if updateFunction then
|
||||
updateFunction(Vector2.new(0, 0), 1)
|
||||
end
|
||||
userInputSeviceTouchEndedCon:disconnect()
|
||||
userInputServiceTouchMovedCon:disconnect()
|
||||
thumbstickFrame.Position = defaultThumbstickPos
|
||||
outerThumbstick.Position = defaultThumbstickPos
|
||||
for i, object in pairs(thumbstickTouches) do
|
||||
if object == thumbstickTouch then
|
||||
table.remove(thumbstickTouches, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
thumbstickTouch = nil
|
||||
end
|
||||
end)
|
||||
end
|
||||
userInputService.Changed:connect(function(prop)
|
||||
if prop == "ModalEnabled" then
|
||||
do
|
||||
local _tmp_0 = not userInputService.ModalEnabled
|
||||
thumbstickFrame.Visible = _tmp_0
|
||||
outerThumbstick.Visible = _tmp_0
|
||||
end
|
||||
end
|
||||
end)
|
||||
thumbstickFrame.InputBegan:connect(startInputTracking)
|
||||
return thumbstickFrame
|
||||
end
|
||||
local setupCharacterMovement
|
||||
setupCharacterMovement = function(parentFrame)
|
||||
local lastMovementVector, lastMaxMovement
|
||||
local moveCharacterFunc = localPlayer.MoveCharacter
|
||||
local moveCharacterFunction
|
||||
moveCharacterFunction = function(movementVector, maxMovement)
|
||||
if localPlayer then
|
||||
if movementOutsideDeadZone(movementVector) then
|
||||
lastMovementVector = movementVector
|
||||
lastMaxMovement = maxMovement
|
||||
if movementVector.magnitude / maxMovement > ThumbstickMaxPercentGive then
|
||||
maxMovement = movementVector.magnitude - 1
|
||||
end
|
||||
return moveCharacterFunc(localPlayer, movementVector, maxMovement)
|
||||
else
|
||||
lastMovementVector = Vector2.new(0, 0)
|
||||
lastMaxMovement = 1
|
||||
return moveCharacterFunc(localPlayer, lastMovementVector, lastMaxMovement)
|
||||
end
|
||||
end
|
||||
end
|
||||
local thumbstickPos = UDim2.new(0, thumbstickSize / 2, 1, -thumbstickSize * 1.75)
|
||||
if isSmallScreenDevice() then
|
||||
thumbstickPos = UDim2.new(0, (thumbstickSize / 2) - 10, 1, -thumbstickSize - 20)
|
||||
end
|
||||
local characterThumbstick = constructThumbstick(thumbstickPos, moveCharacterFunction, false)
|
||||
characterThumbstick.Name = "CharacterThumbstick"
|
||||
characterThumbstick.Parent = parentFrame
|
||||
local refreshCharacterMovement
|
||||
refreshCharacterMovement = function()
|
||||
if localPlayer and moveCharacterFunc and lastMovementVector and lastMaxMovement then
|
||||
return moveCharacterFunc(localPlayer, lastMovementVector, lastMaxMovement)
|
||||
end
|
||||
end
|
||||
return refreshCharacterMovement
|
||||
end
|
||||
local setupJumpButton
|
||||
setupJumpButton = function(parentFrame)
|
||||
local jumpButton = New("ImageButton", "JumpButton", {
|
||||
BackgroundTransparency = 1,
|
||||
Image = touchControlsSheet,
|
||||
ImageRectOffset = Vector2.new(176, 222),
|
||||
ImageRectSize = Vector2.new(174, 174),
|
||||
Size = UDim2.new(0, jumpButtonSize, 0, jumpButtonSize),
|
||||
Position = UDim2.new(1, (function()
|
||||
if isSmallScreenDevice() then
|
||||
return -(jumpButtonSize * 2.25), 1, -jumpButtonSize - 20
|
||||
else
|
||||
return -(jumpButtonSize * 2.75), 1, -jumpButtonSize - 120
|
||||
end
|
||||
end)())
|
||||
})
|
||||
local playerJumpFunc = localPlayer.JumpCharacter
|
||||
local doJumpLoop
|
||||
doJumpLoop = function()
|
||||
while currentJumpTouch do
|
||||
if localPlayer then
|
||||
playerJumpFunc(localPlayer)
|
||||
end
|
||||
wait(1 / 60)
|
||||
end
|
||||
end
|
||||
jumpButton.InputBegan:connect(function(inputObject)
|
||||
if inputObject.UserInputType ~= Enum.UserInputType.Touch then
|
||||
return
|
||||
end
|
||||
if currentJumpTouch then
|
||||
return
|
||||
end
|
||||
if inputObject == cameraTouch then
|
||||
return
|
||||
end
|
||||
for _, touch in pairs(oldJumpTouches) do
|
||||
if touch == inputObject then
|
||||
return
|
||||
end
|
||||
end
|
||||
currentJumpTouch = inputObject
|
||||
jumpButton.ImageRectOffset = Vector2.new(0, 222)
|
||||
jumpButton.ImageRectSize = Vector2.new(174, 174)
|
||||
return doJumpLoop()
|
||||
end)
|
||||
jumpButton.InputEnded:connect(function(inputObject)
|
||||
if inputObject.UserInputType ~= Enum.UserInputType.Touch then
|
||||
return
|
||||
end
|
||||
jumpButton.ImageRectOffset = Vector2.new(176, 222)
|
||||
jumpButton.ImageRectSize = Vector2.new(174, 174)
|
||||
if inputObject == currentJumpTouch then
|
||||
table.insert(oldJumpTouches, currentJumpTouch)
|
||||
currentJumpTouch = nil
|
||||
end
|
||||
end)
|
||||
userInputService.InputEnded:connect(function(globalInputObject)
|
||||
for i, touch in pairs(oldJumpTouches) do
|
||||
if touch == globalInputObject then
|
||||
table.remove(oldJumpTouches, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
end)
|
||||
userInputService.Changed:connect(function(prop)
|
||||
if prop == "ModalEnabled" then
|
||||
jumpButton.Visible = not userInputService.ModalEnabled
|
||||
end
|
||||
end)
|
||||
jumpButton.Parent = parentFrame
|
||||
end
|
||||
local isTouchUsedByJumpButton
|
||||
isTouchUsedByJumpButton = function(touch)
|
||||
if touch == currentJumpTouch then
|
||||
return true
|
||||
end
|
||||
for _, touchToCompare in pairs(oldJumpTouches) do
|
||||
if touch == touchToCompare then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
local isTouchUsedByThumbstick
|
||||
isTouchUsedByThumbstick = function(touch)
|
||||
for _, touchToCompare in pairs(thumbstickTouches) do
|
||||
if touch == touchToCompare then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
local setupCameraControl
|
||||
setupCameraControl = function(parentFrame, refreshCharacterMoveFunc)
|
||||
local lastPos
|
||||
local hasRotatedCamera = false
|
||||
local rotateCameraFunc = userInputService.RotateCamera
|
||||
local pinchTime = -1
|
||||
local shouldPinch = false
|
||||
local lastPinchScale
|
||||
local zoomCameraFunc = userInputService.ZoomCamera
|
||||
local pinchTouches = { }
|
||||
local pinchFrame
|
||||
local resetCameraRotateState
|
||||
resetCameraRotateState = function()
|
||||
cameraTouch = nil
|
||||
hasRotatedCamera = false
|
||||
lastPos = nil
|
||||
end
|
||||
local resetPinchState
|
||||
resetPinchState = function()
|
||||
pinchTouches = { }
|
||||
lastPinchScale = nil
|
||||
shouldPinch = false
|
||||
pinchFrame:Destroy()
|
||||
pinchFrame = nil
|
||||
end
|
||||
local startPinch
|
||||
startPinch = function(firstTouch, secondTouch)
|
||||
if pinchFrame ~= nil then
|
||||
pinchFrame:Destroy()
|
||||
end
|
||||
pinchFrame = New("Frame", {
|
||||
Name = "PinchFrame",
|
||||
BackgroundTransparency = 1,
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
Parent = parentFrame
|
||||
})
|
||||
pinchFrame.InputChanged:connect(function(inputObject)
|
||||
if not shouldPinch then
|
||||
resetPinchState()
|
||||
return
|
||||
end
|
||||
resetCameraRotateState()
|
||||
if not (lastPinchScale ~= nil) then
|
||||
if inputObject == firstTouch then
|
||||
lastPinchScale = (inputObject.Position - secondTouch.Position).magnitude
|
||||
firstTouch = inputObject
|
||||
elseif inputObject == secondTouch then
|
||||
lastPinchScale = (inputObject.Position - firstTouch.Position).magnitude
|
||||
secondTouch = inputObject
|
||||
end
|
||||
else
|
||||
local newPinchDistance = 0
|
||||
if inputObject == firstTouch then
|
||||
newPinchDistance = (inputObject.Position - secondTouch.Position).magnitude
|
||||
firstTouch = inputObject
|
||||
elseif inputObject == secondTouch then
|
||||
newPinchDistance = (inputObject.Position - firstTouch.Position).magnitude
|
||||
secondTouch = inputObject
|
||||
end
|
||||
if newPinchDistance ~= 0 then
|
||||
local pinchDiff = newPinchDistance - lastPinchScale
|
||||
if pinchDiff ~= 0 then
|
||||
zoomCameraFunc(userInputService, (pinchDiff * CameraZoomSensitivity))
|
||||
end
|
||||
lastPinchScale = newPinchDistance
|
||||
end
|
||||
end
|
||||
end)
|
||||
return pinchFrame.InputEnded:connect(function(inputObject)
|
||||
if inputObject == firstTouch or inputObject == secondTouch then
|
||||
return resetPinchState()
|
||||
end
|
||||
end)
|
||||
end
|
||||
local pinchGestureReceivedTouch
|
||||
pinchGestureReceivedTouch = function(inputObject)
|
||||
if #pinchTouches < 1 then
|
||||
table.insert(pinchTouches, inputObject)
|
||||
pinchTime = tick()
|
||||
shouldPinch = false
|
||||
elseif #pinchTouches == 1 then
|
||||
shouldPinch = ((tick() - pinchTime) <= PinchZoomDelay)
|
||||
if shouldPinch then
|
||||
table.insert(pinchTouches, inputObject)
|
||||
return startPinch(pinchTouches[1], pinchTouches[2])
|
||||
else
|
||||
pinchTouches = { }
|
||||
end
|
||||
end
|
||||
end
|
||||
parentFrame.InputBegan:connect(function(inputObject)
|
||||
if inputObject.UserInputType ~= Enum.UserInputType.Touch then
|
||||
return
|
||||
end
|
||||
if isTouchUsedByJumpButton(inputObject) then
|
||||
return
|
||||
end
|
||||
local usedByThumbstick = isTouchUsedByThumbstick(inputObject)
|
||||
if not usedByThumbstick then
|
||||
pinchGestureReceivedTouch(inputObject)
|
||||
end
|
||||
if not (cameraTouch ~= nil) and not usedByThumbstick then
|
||||
cameraTouch = inputObject
|
||||
lastPos = Vector2.new(cameraTouch.Position.x, cameraTouch.Position.y)
|
||||
end
|
||||
end)
|
||||
userInputService.InputChanged:connect(function(inputObject)
|
||||
if inputObject.UserInputType ~= Enum.UserInputType.Touch then
|
||||
return
|
||||
end
|
||||
if cameraTouch ~= inputObject then
|
||||
return
|
||||
end
|
||||
local newPos = Vector2.new(cameraTouch.Position.x, cameraTouch.Position.y)
|
||||
local touchDiff = (lastPos - newPos) * CameraRotateSensitivity
|
||||
if not hasRotatedCamera and (touchDiff.magnitude > CameraRotateDeadZone) then
|
||||
hasRotatedCamera = true
|
||||
lastPos = newPos
|
||||
end
|
||||
if hasRotatedCamera and (lastPos ~= newPos) then
|
||||
rotateCameraFunc(userInputService, touchDiff)
|
||||
refreshCharacterMoveFunc()
|
||||
lastPos = newPos
|
||||
end
|
||||
end)
|
||||
return userInputService.InputEnded:connect(function(inputObject)
|
||||
if cameraTouch == inputObject or not (cameraTouch ~= nil) then
|
||||
resetCameraRotateState()
|
||||
end
|
||||
for i, touch in pairs(pinchTouches) do
|
||||
if touch == inputObject then
|
||||
table.remove(pinchTouches, i)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
local setupTouchControls
|
||||
setupTouchControls = function()
|
||||
local touchControlFrame = New("Frame", "TouchControlFrame", {
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
BackgroundTransparency = 1,
|
||||
Parent = Game.CoreGui.RobloxGui
|
||||
})
|
||||
local refreshCharacterMoveFunc = setupCharacterMovement(touchControlFrame)
|
||||
setupJumpButton(touchControlFrame)
|
||||
setupCameraControl(touchControlFrame, refreshCharacterMoveFunc)
|
||||
return userInputService.ProcessedEvent:connect(function(inputObject, processed)
|
||||
if not processed then
|
||||
return
|
||||
end
|
||||
if inputObject == cameraTouch and inputObject.UserInputState == Enum.UserInputState.Begin then
|
||||
cameraTouch = nil
|
||||
end
|
||||
end)
|
||||
end
|
||||
return setupTouchControls()
|
||||
|
|
@ -0,0 +1,576 @@
|
|||
-- This is responsible for all touch controls we show (as of this writing, only on iOS)
|
||||
-- this includes character move thumbsticks, and buttons for jump, use of items, camera, etc.
|
||||
-- Written by Ben Tkacheff, Roblox 2013
|
||||
|
||||
-- Heliodex's basic New function (basically a simplified version of melt)
|
||||
New = (className, name, props) ->
|
||||
if not props? -- no name was provided
|
||||
props = name
|
||||
name = nil
|
||||
|
||||
obj = Instance.new className
|
||||
obj.Name = name if name
|
||||
local parent
|
||||
|
||||
for k, v in pairs props
|
||||
if type(k) == "string"
|
||||
if k == "Parent"
|
||||
parent = v
|
||||
else
|
||||
obj[k] = v
|
||||
|
||||
elseif type(k) == "number" and type(v) == "userdata"
|
||||
v.Parent = obj
|
||||
|
||||
obj.Parent = parent
|
||||
obj
|
||||
--
|
||||
|
||||
-- obligatory stuff to make sure we don't access nil data
|
||||
wait! until Game
|
||||
wait! until Game\FindFirstChild "Players"
|
||||
wait! until Game.Players.LocalPlayer
|
||||
wait! until Game\FindFirstChild "CoreGui"
|
||||
wait! until Game.CoreGui\FindFirstChild "RobloxGui"
|
||||
|
||||
userInputService = Game\GetService "UserInputService"
|
||||
success = try
|
||||
userInputService\IsLuaTouchControls!
|
||||
|
||||
if not success
|
||||
script\Destroy!
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
----------------------------------------------------------------------------
|
||||
-- Variables
|
||||
screenResolution = Game\GetService("GuiService")\GetScreenResolution!
|
||||
isSmallScreenDevice = ->
|
||||
return screenResolution.y <= 320
|
||||
|
||||
|
||||
localPlayer = Game.Players.LocalPlayer
|
||||
thumbstickSize = 120
|
||||
if isSmallScreenDevice!
|
||||
thumbstickSize = 70
|
||||
|
||||
|
||||
touchControlsSheet = "rbxasset://textures/ui/TouchControlsSheet.png"
|
||||
ThumbstickDeadZone = 5
|
||||
ThumbstickMaxPercentGive = 0.92
|
||||
thumbstickTouches = {}
|
||||
|
||||
jumpButtonSize = 90
|
||||
if isSmallScreenDevice!
|
||||
jumpButtonSize = 70
|
||||
|
||||
oldJumpTouches = {}
|
||||
local currentJumpTouch
|
||||
|
||||
CameraRotateSensitivity = 0.007
|
||||
CameraRotateDeadZone = CameraRotateSensitivity * 16
|
||||
CameraZoomSensitivity = 0.03
|
||||
PinchZoomDelay = 0.2
|
||||
local cameraTouch
|
||||
|
||||
-- make sure all of our images are good to go
|
||||
Game\GetService("ContentProvider")\Preload touchControlsSheet
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
----------------------------------------------------------------------------
|
||||
-- Functions
|
||||
|
||||
DistanceBetweenTwoPoints = (point1, point2) ->
|
||||
dx = point2.x - point1.x
|
||||
dy = point2.y - point1.y
|
||||
math.sqrt dx * dx + dy * dy
|
||||
|
||||
|
||||
transformFromCenterToTopLeft = (pointToTranslate, guiObject) ->
|
||||
UDim2.new(
|
||||
0,
|
||||
pointToTranslate.x - guiObject.AbsoluteSize.x / 2,
|
||||
0,
|
||||
pointToTranslate.y - guiObject.AbsoluteSize.y / 2
|
||||
)
|
||||
|
||||
|
||||
rotatePointAboutLocation = (pointToRotate, pointToRotateAbout, radians) ->
|
||||
sinAnglePercent = math.sin radians
|
||||
cosAnglePercent = math.cos radians
|
||||
|
||||
transformedPoint = pointToRotate
|
||||
|
||||
-- translate point back to origin:
|
||||
transformedPoint = Vector2.new transformedPoint.x - pointToRotateAbout.x, transformedPoint.y - pointToRotateAbout.y
|
||||
|
||||
-- rotate point
|
||||
xNew = transformedPoint.x * cosAnglePercent - transformedPoint.y * sinAnglePercent
|
||||
yNew = transformedPoint.x * sinAnglePercent + transformedPoint.y * cosAnglePercent
|
||||
|
||||
-- translate point back:
|
||||
transformedPoint = Vector2.new xNew + pointToRotateAbout.x, yNew + pointToRotateAbout.y
|
||||
|
||||
transformedPoint
|
||||
|
||||
|
||||
dotProduct = (v1, v2) -> v1.x * v2.x + v1.y * v2.y
|
||||
|
||||
|
||||
stationaryThumbstickTouchMove = (thumbstickFrame, thumbstickOuter, touchLocation) ->
|
||||
thumbstickOuterCenterPosition = Vector2.new(
|
||||
thumbstickOuter.Position.X.Offset + thumbstickOuter.AbsoluteSize.x / 2,
|
||||
thumbstickOuter.Position.Y.Offset + thumbstickOuter.AbsoluteSize.y / 2
|
||||
)
|
||||
centerDiff = DistanceBetweenTwoPoints touchLocation, thumbstickOuterCenterPosition
|
||||
|
||||
-- thumbstick is moving outside our region, need to cap its distance
|
||||
if centerDiff > (thumbstickSize / 2)
|
||||
thumbVector = Vector2.new(
|
||||
touchLocation.x - thumbstickOuterCenterPosition.x,
|
||||
touchLocation.y - thumbstickOuterCenterPosition.y
|
||||
)
|
||||
normal = thumbVector.unit
|
||||
if normal.x == math.nan or normal.x == math.inf
|
||||
normal = Vector2.new 0, normal.y
|
||||
|
||||
if normal.y == math.nan or normal.y == math.inf
|
||||
normal = Vector2.new normal.x, 0
|
||||
|
||||
|
||||
newThumbstickInnerPosition = thumbstickOuterCenterPosition + (normal * (thumbstickSize / 2))
|
||||
thumbstickFrame.Position = transformFromCenterToTopLeft newThumbstickInnerPosition, thumbstickFrame
|
||||
else
|
||||
thumbstickFrame.Position = transformFromCenterToTopLeft touchLocation, thumbstickFrame
|
||||
|
||||
|
||||
Vector2.new(
|
||||
thumbstickFrame.Position.X.Offset - thumbstickOuter.Position.X.Offset,
|
||||
thumbstickFrame.Position.Y.Offset - thumbstickOuter.Position.Y.Offset
|
||||
)
|
||||
|
||||
|
||||
followThumbstickTouchMove = (thumbstickFrame, thumbstickOuter, touchLocation) ->
|
||||
thumbstickOuterCenter = Vector2.new(
|
||||
thumbstickOuter.Position.X.Offset + thumbstickOuter.AbsoluteSize.x / 2,
|
||||
thumbstickOuter.Position.Y.Offset + thumbstickOuter.AbsoluteSize.y / 2
|
||||
)
|
||||
|
||||
-- thumbstick is moving outside our region, need to position outer thumbstick texture carefully (to make look and feel like actual joystick controller)
|
||||
if DistanceBetweenTwoPoints(touchLocation, thumbstickOuterCenter) > thumbstickSize / 2
|
||||
thumbstickInnerCenter = Vector2.new(
|
||||
thumbstickFrame.Position.X.Offset + thumbstickFrame.AbsoluteSize.x / 2,
|
||||
thumbstickFrame.Position.Y.Offset + thumbstickFrame.AbsoluteSize.y / 2
|
||||
)
|
||||
movementVectorUnit = Vector2.new(touchLocation.x - thumbstickInnerCenter.x, touchLocation.y - thumbstickInnerCenter.y).unit
|
||||
|
||||
outerToInnerVectorCurrent = Vector2.new(
|
||||
thumbstickInnerCenter.x - thumbstickOuterCenter.x,
|
||||
thumbstickInnerCenter.y - thumbstickOuterCenter.y
|
||||
)
|
||||
outerToInnerVectorCurrentUnit = outerToInnerVectorCurrent.unit
|
||||
movementVector = Vector2.new touchLocation.x - thumbstickInnerCenter.x, touchLocation.y - thumbstickInnerCenter.y
|
||||
|
||||
-- First, find the angle between the new thumbstick movement vector,
|
||||
-- and the vector between thumbstick inner and thumbstick outer.
|
||||
-- We will use this to pivot thumbstick outer around thumbstick inner, gives a nice joystick feel
|
||||
crossOuterToInnerWithMovement = (outerToInnerVectorCurrentUnit.x * movementVectorUnit.y) -
|
||||
(outerToInnerVectorCurrentUnit.y * movementVectorUnit.x)
|
||||
angle = math.atan2 crossOuterToInnerWithMovement, dotProduct outerToInnerVectorCurrentUnit, movementVectorUnit
|
||||
anglePercent = angle * math.min(movementVector.magnitude / outerToInnerVectorCurrent.magnitude, 1.0)
|
||||
|
||||
-- If angle is significant, rotate about the inner thumbsticks current center
|
||||
if math.abs(anglePercent) > 0.00001
|
||||
outerThumbCenter = rotatePointAboutLocation thumbstickOuterCenter, thumbstickInnerCenter, anglePercent
|
||||
thumbstickOuter.Position = transformFromCenterToTopLeft Vector2.new(outerThumbCenter.x, outerThumbCenter.y), thumbstickOuter
|
||||
|
||||
|
||||
-- now just translate outer thumbstick to make sure it stays nears inner thumbstick
|
||||
thumbstickOuter.Position = UDim2.new(
|
||||
0,
|
||||
thumbstickOuter.Position.X.Offset + movementVector.x,
|
||||
0,
|
||||
thumbstickOuter.Position.Y.Offset + movementVector.y
|
||||
)
|
||||
|
||||
|
||||
thumbstickFrame.Position = transformFromCenterToTopLeft touchLocation, thumbstickFrame
|
||||
|
||||
-- a bit of error checking to make sure thumbsticks stay close to eachother
|
||||
thumbstickFramePosition = Vector2.new thumbstickFrame.Position.X.Offset, thumbstickFrame.Position.Y.Offset
|
||||
thumbstickOuterPosition = Vector2.new thumbstickOuter.Position.X.Offset, thumbstickOuter.Position.Y.Offset
|
||||
if DistanceBetweenTwoPoints(thumbstickFramePosition, thumbstickOuterPosition) > thumbstickSize / 2
|
||||
vectorWithLength = (thumbstickOuterPosition - thumbstickFramePosition).unit * thumbstickSize / 2
|
||||
thumbstickOuter.Position = UDim2.new(
|
||||
0,
|
||||
thumbstickFramePosition.x + vectorWithLength.x,
|
||||
0,
|
||||
thumbstickFramePosition.y + vectorWithLength.y
|
||||
)
|
||||
|
||||
|
||||
Vector2.new(
|
||||
thumbstickFrame.Position.X.Offset - thumbstickOuter.Position.X.Offset,
|
||||
thumbstickFrame.Position.Y.Offset - thumbstickOuter.Position.Y.Offset
|
||||
)
|
||||
|
||||
|
||||
movementOutsideDeadZone = (movementVector) ->
|
||||
(math.abs(movementVector.x) > ThumbstickDeadZone) or (math.abs(movementVector.y) > ThumbstickDeadZone)
|
||||
|
||||
|
||||
constructThumbstick = (defaultThumbstickPos, updateFunction, stationaryThumbstick) ->
|
||||
thumbstickFrame = New "Frame", "ThumbstickFrame"
|
||||
Active: true
|
||||
Size: UDim2.new 0, thumbstickSize, 0, thumbstickSize
|
||||
Position: defaultThumbstickPos
|
||||
BackgroundTransparency: 1
|
||||
|
||||
New "ImageLabel", "InnerThumbstick"
|
||||
Image: touchControlsSheet
|
||||
ImageRectOffset: Vector2.new 220, 0
|
||||
ImageRectSize: Vector2.new 111, 111
|
||||
BackgroundTransparency: 1
|
||||
Size: UDim2.new 0, thumbstickSize / 2, 0, thumbstickSize / 2
|
||||
Position: UDim2.new(
|
||||
0,
|
||||
thumbstickFrame.Size.X.Offset / 2 - thumbstickSize / 4,
|
||||
0,
|
||||
thumbstickFrame.Size.Y.Offset / 2 - thumbstickSize / 4
|
||||
)
|
||||
ZIndex: 2
|
||||
Parent: thumbstickFrame
|
||||
|
||||
outerThumbstick = New "ImageLabel", "OuterThumbstick"
|
||||
Image: touchControlsSheet
|
||||
ImageRectOffset: Vector2.new 0, 0
|
||||
ImageRectSize: Vector2.new 220, 220
|
||||
BackgroundTransparency: 1
|
||||
Size: UDim2.new 0, thumbstickSize, 0, thumbstickSize
|
||||
Position: defaultThumbstickPos
|
||||
Parent: Game.CoreGui.RobloxGui
|
||||
|
||||
|
||||
local thumbstickTouch
|
||||
local userInputServiceTouchMovedCon
|
||||
local userInputSeviceTouchEndedCon
|
||||
|
||||
startInputTracking = (inputObject) ->
|
||||
return if thumbstickTouch
|
||||
return if inputObject == cameraTouch
|
||||
return if inputObject == currentJumpTouch
|
||||
return if inputObject.UserInputType ~= Enum.UserInputType.Touch
|
||||
|
||||
thumbstickTouch = inputObject
|
||||
table.insert thumbstickTouches, thumbstickTouch
|
||||
|
||||
thumbstickFrame.Position = transformFromCenterToTopLeft(thumbstickTouch.Position, thumbstickFrame)
|
||||
outerThumbstick.Position = thumbstickFrame.Position
|
||||
|
||||
userInputServiceTouchMovedCon = userInputService.TouchMoved\connect (movedInput) ->
|
||||
if movedInput == thumbstickTouch
|
||||
local movementVector
|
||||
if stationaryThumbstick
|
||||
movementVector = stationaryThumbstickTouchMove(
|
||||
thumbstickFrame,
|
||||
outerThumbstick,
|
||||
Vector2.new movedInput.Position.x, movedInput.Position.y
|
||||
)
|
||||
else
|
||||
movementVector = followThumbstickTouchMove(
|
||||
thumbstickFrame,
|
||||
outerThumbstick,
|
||||
Vector2.new movedInput.Position.x, movedInput.Position.y
|
||||
)
|
||||
|
||||
|
||||
if updateFunction
|
||||
updateFunction movementVector, outerThumbstick.Size.X.Offset / 2
|
||||
|
||||
|
||||
userInputSeviceTouchEndedCon = userInputService.TouchEnded\connect (endedInput) ->
|
||||
if endedInput == thumbstickTouch
|
||||
if updateFunction
|
||||
updateFunction Vector2.new(0, 0), 1
|
||||
|
||||
|
||||
userInputSeviceTouchEndedCon\disconnect!
|
||||
userInputServiceTouchMovedCon\disconnect!
|
||||
|
||||
thumbstickFrame.Position = defaultThumbstickPos
|
||||
outerThumbstick.Position = defaultThumbstickPos
|
||||
|
||||
for i, object in pairs thumbstickTouches
|
||||
if object == thumbstickTouch
|
||||
table.remove thumbstickTouches, i
|
||||
break
|
||||
|
||||
thumbstickTouch = nil
|
||||
|
||||
userInputService.Changed\connect (prop) ->
|
||||
if prop == "ModalEnabled"
|
||||
thumbstickFrame.Visible = outerThumbstick.Visible = not userInputService.ModalEnabled
|
||||
|
||||
thumbstickFrame.InputBegan\connect startInputTracking
|
||||
thumbstickFrame
|
||||
|
||||
setupCharacterMovement = (parentFrame) ->
|
||||
local lastMovementVector, lastMaxMovement
|
||||
moveCharacterFunc = localPlayer.MoveCharacter
|
||||
moveCharacterFunction = (movementVector, maxMovement) ->
|
||||
if localPlayer
|
||||
if movementOutsideDeadZone movementVector
|
||||
lastMovementVector = movementVector
|
||||
lastMaxMovement = maxMovement
|
||||
-- sometimes rounding error will not allow us to go max speed at some
|
||||
-- thumbstick angles, fix this with a bit of fudging near 100% throttle
|
||||
if movementVector.magnitude / maxMovement > ThumbstickMaxPercentGive
|
||||
maxMovement = movementVector.magnitude - 1
|
||||
|
||||
moveCharacterFunc localPlayer, movementVector, maxMovement
|
||||
else
|
||||
lastMovementVector = Vector2.new 0, 0
|
||||
lastMaxMovement = 1
|
||||
moveCharacterFunc localPlayer, lastMovementVector, lastMaxMovement
|
||||
|
||||
thumbstickPos = UDim2.new 0, thumbstickSize / 2, 1, -thumbstickSize * 1.75
|
||||
if isSmallScreenDevice!
|
||||
thumbstickPos = UDim2.new 0, (thumbstickSize / 2) - 10, 1, -thumbstickSize - 20
|
||||
|
||||
characterThumbstick = constructThumbstick thumbstickPos, moveCharacterFunction, false
|
||||
characterThumbstick.Name = "CharacterThumbstick"
|
||||
characterThumbstick.Parent = parentFrame
|
||||
|
||||
refreshCharacterMovement = ->
|
||||
if localPlayer and moveCharacterFunc and lastMovementVector and lastMaxMovement
|
||||
moveCharacterFunc localPlayer, lastMovementVector, lastMaxMovement
|
||||
|
||||
refreshCharacterMovement
|
||||
|
||||
setupJumpButton = (parentFrame) ->
|
||||
jumpButton = New "ImageButton", "JumpButton"
|
||||
BackgroundTransparency: 1
|
||||
Image: touchControlsSheet
|
||||
ImageRectOffset: Vector2.new 176, 222
|
||||
ImageRectSize: Vector2.new 174, 174
|
||||
Size: UDim2.new 0, jumpButtonSize, 0, jumpButtonSize
|
||||
Position: UDim2.new 1, if isSmallScreenDevice!
|
||||
-(jumpButtonSize * 2.25), 1, -jumpButtonSize - 20
|
||||
else
|
||||
-(jumpButtonSize * 2.75), 1, -jumpButtonSize - 120
|
||||
|
||||
|
||||
playerJumpFunc = localPlayer.JumpCharacter
|
||||
|
||||
doJumpLoop = ->
|
||||
while currentJumpTouch
|
||||
if localPlayer
|
||||
playerJumpFunc localPlayer
|
||||
|
||||
wait 1 / 60
|
||||
|
||||
|
||||
jumpButton.InputBegan\connect (inputObject) ->
|
||||
return if inputObject.UserInputType ~= Enum.UserInputType.Touch
|
||||
return if currentJumpTouch
|
||||
return if inputObject == cameraTouch
|
||||
for _, touch in pairs oldJumpTouches
|
||||
return if touch == inputObject
|
||||
|
||||
currentJumpTouch = inputObject
|
||||
jumpButton.ImageRectOffset = Vector2.new 0, 222
|
||||
jumpButton.ImageRectSize = Vector2.new 174, 174
|
||||
doJumpLoop!
|
||||
|
||||
jumpButton.InputEnded\connect (inputObject) ->
|
||||
return if inputObject.UserInputType ~= Enum.UserInputType.Touch
|
||||
|
||||
jumpButton.ImageRectOffset = Vector2.new 176, 222
|
||||
jumpButton.ImageRectSize = Vector2.new 174, 174
|
||||
|
||||
if inputObject == currentJumpTouch
|
||||
table.insert oldJumpTouches, currentJumpTouch
|
||||
currentJumpTouch = nil
|
||||
|
||||
|
||||
userInputService.InputEnded\connect (globalInputObject) ->
|
||||
for i, touch in pairs oldJumpTouches
|
||||
if touch == globalInputObject
|
||||
table.remove oldJumpTouches, i
|
||||
break
|
||||
|
||||
userInputService.Changed\connect (prop) ->
|
||||
if prop == "ModalEnabled"
|
||||
jumpButton.Visible = not userInputService.ModalEnabled
|
||||
|
||||
jumpButton.Parent = parentFrame
|
||||
|
||||
|
||||
isTouchUsedByJumpButton = (touch) ->
|
||||
if touch == currentJumpTouch
|
||||
return true
|
||||
|
||||
for _, touchToCompare in pairs oldJumpTouches
|
||||
if touch == touchToCompare
|
||||
return true
|
||||
false
|
||||
|
||||
isTouchUsedByThumbstick = (touch) ->
|
||||
for _, touchToCompare in pairs thumbstickTouches
|
||||
if touch == touchToCompare
|
||||
return true
|
||||
false
|
||||
|
||||
|
||||
setupCameraControl = (parentFrame, refreshCharacterMoveFunc) ->
|
||||
local lastPos
|
||||
hasRotatedCamera = false
|
||||
rotateCameraFunc = userInputService.RotateCamera
|
||||
|
||||
pinchTime = -1
|
||||
shouldPinch = false
|
||||
local lastPinchScale
|
||||
zoomCameraFunc = userInputService.ZoomCamera
|
||||
pinchTouches = {}
|
||||
local pinchFrame
|
||||
|
||||
resetCameraRotateState = ->
|
||||
cameraTouch = nil
|
||||
hasRotatedCamera = false
|
||||
lastPos = nil
|
||||
|
||||
resetPinchState = ->
|
||||
pinchTouches = {}
|
||||
lastPinchScale = nil
|
||||
shouldPinch = false
|
||||
pinchFrame\Destroy!
|
||||
pinchFrame = nil
|
||||
|
||||
startPinch = (firstTouch, secondTouch) ->
|
||||
-- track pinching in new frame
|
||||
pinchFrame?\Destroy!
|
||||
-- make sure we didn't track in any mud
|
||||
pinchFrame = New "Frame"
|
||||
Name: "PinchFrame"
|
||||
BackgroundTransparency: 1
|
||||
Size: UDim2.new 1, 0, 1, 0
|
||||
Parent: parentFrame
|
||||
|
||||
pinchFrame.InputChanged\connect (inputObject) ->
|
||||
if not shouldPinch
|
||||
resetPinchState!
|
||||
return
|
||||
|
||||
resetCameraRotateState!
|
||||
|
||||
if not lastPinchScale? then -- first pinch move, just set up scale
|
||||
if inputObject == firstTouch
|
||||
lastPinchScale = (inputObject.Position - secondTouch.Position).magnitude
|
||||
firstTouch = inputObject
|
||||
elseif inputObject == secondTouch
|
||||
lastPinchScale = (inputObject.Position - firstTouch.Position).magnitude
|
||||
secondTouch = inputObject
|
||||
|
||||
else -- we are now actually pinching, do comparison to last pinch size
|
||||
newPinchDistance = 0
|
||||
if inputObject == firstTouch
|
||||
newPinchDistance = (inputObject.Position - secondTouch.Position).magnitude
|
||||
firstTouch = inputObject
|
||||
elseif inputObject == secondTouch
|
||||
newPinchDistance = (inputObject.Position - firstTouch.Position).magnitude
|
||||
secondTouch = inputObject
|
||||
|
||||
if newPinchDistance ~= 0
|
||||
pinchDiff = newPinchDistance - lastPinchScale
|
||||
if pinchDiff ~= 0
|
||||
zoomCameraFunc userInputService, (pinchDiff * CameraZoomSensitivity)
|
||||
|
||||
lastPinchScale = newPinchDistance
|
||||
|
||||
pinchFrame.InputEnded\connect (inputObject) -> -- pinch is over, destroy all
|
||||
if inputObject == firstTouch or inputObject == secondTouch
|
||||
resetPinchState!
|
||||
|
||||
|
||||
pinchGestureReceivedTouch = (inputObject) ->
|
||||
if #pinchTouches < 1
|
||||
table.insert pinchTouches, inputObject
|
||||
pinchTime = tick!
|
||||
shouldPinch = false
|
||||
elseif #pinchTouches == 1
|
||||
shouldPinch = ((tick! - pinchTime) <= PinchZoomDelay)
|
||||
|
||||
if shouldPinch
|
||||
table.insert pinchTouches, inputObject
|
||||
startPinch pinchTouches[1], pinchTouches[2]
|
||||
else -- shouldn't ever get here, but just in case
|
||||
pinchTouches = {}
|
||||
|
||||
parentFrame.InputBegan\connect (inputObject) ->
|
||||
return if inputObject.UserInputType ~= Enum.UserInputType.Touch
|
||||
return if isTouchUsedByJumpButton inputObject
|
||||
|
||||
usedByThumbstick = isTouchUsedByThumbstick inputObject
|
||||
if not usedByThumbstick
|
||||
pinchGestureReceivedTouch inputObject
|
||||
|
||||
|
||||
if not cameraTouch? and not usedByThumbstick
|
||||
cameraTouch = inputObject
|
||||
lastPos = Vector2.new cameraTouch.Position.x, cameraTouch.Position.y
|
||||
-- lastTick = tick!
|
||||
|
||||
userInputService.InputChanged\connect (inputObject) ->
|
||||
return if inputObject.UserInputType ~= Enum.UserInputType.Touch
|
||||
return if cameraTouch ~= inputObject
|
||||
|
||||
newPos = Vector2.new cameraTouch.Position.x, cameraTouch.Position.y
|
||||
touchDiff = (lastPos - newPos) * CameraRotateSensitivity
|
||||
|
||||
-- first time rotating outside deadzone, just setup for next changed event
|
||||
if not hasRotatedCamera and (touchDiff.magnitude > CameraRotateDeadZone)
|
||||
hasRotatedCamera = true
|
||||
lastPos = newPos
|
||||
|
||||
|
||||
-- fire everytime after we have rotated out of deadzone
|
||||
if hasRotatedCamera and (lastPos ~= newPos)
|
||||
rotateCameraFunc userInputService, touchDiff
|
||||
refreshCharacterMoveFunc!
|
||||
lastPos = newPos
|
||||
|
||||
|
||||
userInputService.InputEnded\connect (inputObject) ->
|
||||
if cameraTouch == inputObject or not cameraTouch?
|
||||
resetCameraRotateState!
|
||||
|
||||
for i, touch in pairs pinchTouches
|
||||
if touch == inputObject
|
||||
table.remove pinchTouches, i
|
||||
|
||||
setupTouchControls = ->
|
||||
touchControlFrame = New "Frame", "TouchControlFrame"
|
||||
Size: UDim2.new 1, 0, 1, 0
|
||||
BackgroundTransparency: 1
|
||||
Parent: Game.CoreGui.RobloxGui
|
||||
|
||||
refreshCharacterMoveFunc = setupCharacterMovement touchControlFrame
|
||||
setupJumpButton touchControlFrame
|
||||
setupCameraControl touchControlFrame, refreshCharacterMoveFunc
|
||||
|
||||
userInputService.ProcessedEvent\connect (inputObject, processed) ->
|
||||
return if not processed
|
||||
|
||||
-- kill camera pan if the touch is used by some user controls
|
||||
if inputObject == cameraTouch and inputObject.UserInputState == Enum.UserInputState.Begin
|
||||
cameraTouch = nil
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
----------------------------------------------------------------------------
|
||||
-- Start of Script
|
||||
|
||||
-- if true then --userInputService\IsLuaTouchControls!
|
||||
setupTouchControls!
|
||||
-- else
|
||||
-- script\Destroy!
|
||||
|
||||
|
|
@ -0,0 +1,389 @@
|
|||
if game.CoreGui.Version < 7 then
|
||||
return
|
||||
end
|
||||
local waitForChild
|
||||
waitForChild = function(instance, name)
|
||||
while not instance:FindFirstChild(name) do
|
||||
instance.ChildAdded:wait()
|
||||
end
|
||||
return instance:FindFirstChild(name)
|
||||
end
|
||||
local waitForProperty
|
||||
waitForProperty = function(instance, property)
|
||||
while not instance[property] do
|
||||
instance.Changed:wait()
|
||||
end
|
||||
end
|
||||
waitForChild(game, "Players")
|
||||
if #game.Players:GetChildren() < 1 then
|
||||
game.Players.ChildAdded:wait()
|
||||
end
|
||||
waitForProperty(game.Players, "LocalPlayer")
|
||||
local backpack = script.Parent
|
||||
waitForChild(backpack, "Gear")
|
||||
local screen = script.Parent.Parent
|
||||
assert(screen:IsA("ScreenGui"))
|
||||
waitForChild(backpack, "Tabs")
|
||||
waitForChild(backpack.Tabs, "CloseButton")
|
||||
local closeButton = backpack.Tabs.CloseButton
|
||||
waitForChild(backpack.Tabs, "InventoryButton")
|
||||
local inventoryButton = backpack.Tabs.InventoryButton
|
||||
local wardrobeButton
|
||||
if game.CoreGui.Version >= 8 then
|
||||
waitForChild(backpack.Tabs, "WardrobeButton")
|
||||
wardrobeButton = backpack.Tabs.WardrobeButton
|
||||
end
|
||||
waitForChild(backpack.Parent, "ControlFrame")
|
||||
local backpackButton = waitForChild(backpack.Parent.ControlFrame, "BackpackButton")
|
||||
local currentTab = "gear"
|
||||
local searchFrame = waitForChild(backpack, "SearchFrame")
|
||||
waitForChild(backpack.SearchFrame, "SearchBoxFrame")
|
||||
local searchBox = waitForChild(backpack.SearchFrame.SearchBoxFrame, "SearchBox")
|
||||
local searchButton = waitForChild(backpack.SearchFrame, "SearchButton")
|
||||
local resetButton = waitForChild(backpack.SearchFrame, "ResetButton")
|
||||
local robloxGui = waitForChild(Game.CoreGui, "RobloxGui")
|
||||
local currentLoadout = waitForChild(robloxGui, "CurrentLoadout")
|
||||
local loadoutBackground = waitForChild(currentLoadout, "Background")
|
||||
local canToggle = true
|
||||
local readyForNextEvent = true
|
||||
local backpackIsOpen = false
|
||||
local active = true
|
||||
local disabledByDeveloper = false
|
||||
local humanoidDiedCon
|
||||
local guiTweenSpeed = 0.25
|
||||
local searchDefaultText = "Search..."
|
||||
local tilde = "~"
|
||||
local backquote = "`"
|
||||
local backpackSize = UDim2.new(0, 600, 0, 400)
|
||||
if robloxGui.AbsoluteSize.Y <= 320 then
|
||||
backpackSize = UDim2.new(0, 200, 0, 140)
|
||||
end
|
||||
local createPublicEvent
|
||||
createPublicEvent = function(eventName)
|
||||
assert(eventName, "eventName is nil")
|
||||
assert(tostring(eventName), "eventName is not a string")
|
||||
local _with_0 = Instance.new("BindableEvent")
|
||||
_with_0.Name = tostring(eventName)
|
||||
_with_0.Parent = script
|
||||
return _with_0
|
||||
end
|
||||
local createPublicFunction
|
||||
createPublicFunction = function(funcName, invokeFunc)
|
||||
assert(funcName, "funcName is nil")
|
||||
assert(tostring(funcName), "funcName is not a string")
|
||||
assert(invokeFunc, "invokeFunc is nil")
|
||||
assert(type(invokeFunc) == "function", "invokeFunc should be of type 'function'")
|
||||
local _with_0 = Instance.new("BindableFunction")
|
||||
_with_0.Name = tostring(funcName)
|
||||
_with_0.OnInvoke = invokeFunc
|
||||
_with_0.Parent = script
|
||||
return _with_0
|
||||
end
|
||||
local resizeEvent = createPublicEvent("ResizeEvent")
|
||||
local backpackOpenEvent = createPublicEvent("BackpackOpenEvent")
|
||||
local backpackCloseEvent = createPublicEvent("BackpackCloseEvent")
|
||||
local tabClickedEvent = createPublicEvent("TabClickedEvent")
|
||||
local searchRequestedEvent = createPublicEvent("SearchRequestedEvent")
|
||||
local resetSearchBoxGui
|
||||
resetSearchBoxGui = function()
|
||||
resetButton.Visible = false
|
||||
searchBox.Text = searchDefaultText
|
||||
end
|
||||
local resetSearch
|
||||
resetSearch = function()
|
||||
resetSearchBoxGui()
|
||||
return searchRequestedEvent:Fire()
|
||||
end
|
||||
local deactivateBackpack
|
||||
deactivateBackpack = function()
|
||||
backpack.Visible = false
|
||||
active = false
|
||||
end
|
||||
local initHumanoidDiedConnections
|
||||
initHumanoidDiedConnections = function()
|
||||
if humanoidDiedCon then
|
||||
humanoidDiedCon:disconnect()
|
||||
end
|
||||
waitForProperty(game.Players.LocalPlayer, "Character")
|
||||
waitForChild(game.Players.LocalPlayer.Character, "Humanoid")
|
||||
humanoidDiedCon = game.Players.LocalPlayer.Character.Humanoid.Died:connect(deactivateBackpack)
|
||||
end
|
||||
local hideBackpack
|
||||
hideBackpack = function()
|
||||
backpackIsOpen = false
|
||||
readyForNextEvent = false
|
||||
backpackButton.Selected = false
|
||||
resetSearch()
|
||||
backpackCloseEvent:Fire(currentTab)
|
||||
backpack.Tabs.Visible = false
|
||||
searchFrame.Visible = false
|
||||
backpack:TweenSizeAndPosition(UDim2.new(0, backpackSize.X.Offset, 0, 0), UDim2.new(0.5, -backpackSize.X.Offset / 2, 1, -85), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed, true, function()
|
||||
game.GuiService:RemoveCenterDialog(backpack)
|
||||
backpack.Visible = false
|
||||
backpackButton.Selected = false
|
||||
end)
|
||||
return delay(guiTweenSpeed, function()
|
||||
game.GuiService:RemoveCenterDialog(backpack)
|
||||
backpack.Visible = false
|
||||
backpackButton.Selected = false
|
||||
readyForNextEvent = true
|
||||
canToggle = true
|
||||
end)
|
||||
end
|
||||
local showBackpack
|
||||
showBackpack = function()
|
||||
game.GuiService:AddCenterDialog(backpack, Enum.CenterDialogType.PlayerInitiatedDialog, function()
|
||||
backpack.Visible = true
|
||||
backpackButton.Selected = true
|
||||
end, function()
|
||||
backpack.Visible = false
|
||||
backpackButton.Selected = false
|
||||
end)
|
||||
backpack.Visible = true
|
||||
backpackButton.Selected = true
|
||||
backpack:TweenSizeAndPosition(backpackSize, UDim2.new(0.5, -backpackSize.X.Offset / 2, 1, -backpackSize.Y.Offset - 88), Enum.EasingDirection.Out, Enum.EasingStyle.Quad, guiTweenSpeed, true)
|
||||
return delay(guiTweenSpeed, function()
|
||||
backpack.Tabs.Visible = false
|
||||
searchFrame.Visible = true
|
||||
backpackOpenEvent:Fire(currentTab)
|
||||
canToggle = true
|
||||
readyForNextEvent = true
|
||||
backpackButton.Image = "http://www.roblox.com/asset/?id=97644093"
|
||||
backpackButton.Position = UDim2.new(0.5, -60, 1, -backpackSize.Y.Offset - 103)
|
||||
end)
|
||||
end
|
||||
local toggleBackpack
|
||||
toggleBackpack = function()
|
||||
if not game.Players.LocalPlayer then
|
||||
return
|
||||
end
|
||||
if not game.Players.LocalPlayer["Character"] then
|
||||
return
|
||||
end
|
||||
if not canToggle then
|
||||
return
|
||||
end
|
||||
if not readyForNextEvent then
|
||||
return
|
||||
end
|
||||
readyForNextEvent = false
|
||||
canToggle = false
|
||||
backpackIsOpen = not backpackIsOpen
|
||||
if backpackIsOpen then
|
||||
loadoutBackground.Image = "http://www.roblox.com/asset/?id=97623721"
|
||||
loadoutBackground.Position = UDim2.new(-0.03, 0, -0.17, 0)
|
||||
loadoutBackground.Size = UDim2.new(1.05, 0, 1.25, 0)
|
||||
loadoutBackground.ZIndex = 2.0
|
||||
loadoutBackground.Visible = true
|
||||
return showBackpack()
|
||||
else
|
||||
backpackButton.Position = UDim2.new(0.5, -60, 1, -44)
|
||||
loadoutBackground.Visible = false
|
||||
backpackButton.Selected = false
|
||||
backpackButton.Image = "http://www.roblox.com/asset/?id=97617958"
|
||||
loadoutBackground.Image = "http://www.roblox.com/asset/?id=96536002"
|
||||
loadoutBackground.Position = UDim2.new(-0.1, 0, -0.1, 0)
|
||||
loadoutBackground.Size = UDim2.new(1.2, 0, 1.2, 0)
|
||||
hideBackpack()
|
||||
local clChildren = currentLoadout:GetChildren()
|
||||
for i = 1, #clChildren do
|
||||
if clChildren[i] and clChildren[i]:IsA("Frame") then
|
||||
local frame = clChildren[i]
|
||||
if #frame:GetChildren() > 0 then
|
||||
backpackButton.Position = UDim2.new(0.5, -60, 1, -108)
|
||||
backpackButton.Visible = true
|
||||
loadoutBackground.Visible = true
|
||||
if frame:GetChildren()[1]:IsA("ImageButton") then
|
||||
local imgButton = frame:GetChildren()[1]
|
||||
imgButton.Active = true
|
||||
imgButton.Draggable = false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
local activateBackpack
|
||||
activateBackpack = function()
|
||||
initHumanoidDiedConnections()
|
||||
active = true
|
||||
backpack.Visible = backpackIsOpen
|
||||
if backpackIsOpen then
|
||||
return toggleBackpack()
|
||||
end
|
||||
end
|
||||
local closeBackpack
|
||||
closeBackpack = function()
|
||||
if backpackIsOpen then
|
||||
return toggleBackpack()
|
||||
end
|
||||
end
|
||||
local setSelected
|
||||
setSelected = function(tab)
|
||||
assert(tab)
|
||||
assert(tab:IsA("TextButton"))
|
||||
tab.BackgroundColor3 = Color3.new(1, 1, 1)
|
||||
tab.TextColor3 = Color3.new(0, 0, 0)
|
||||
tab.Selected = true
|
||||
tab.ZIndex = 3
|
||||
return tab
|
||||
end
|
||||
local setUnselected
|
||||
setUnselected = function(tab)
|
||||
assert(tab)
|
||||
assert(tab:IsA("TextButton"))
|
||||
tab.BackgroundColor3 = Color3.new(0, 0, 0)
|
||||
tab.TextColor3 = Color3.new(1, 1, 1)
|
||||
tab.Selected = false
|
||||
tab.ZIndex = 1
|
||||
return tab
|
||||
end
|
||||
local updateTabGui
|
||||
updateTabGui = function(selectedTab)
|
||||
assert(selectedTab)
|
||||
if selectedTab == "gear" then
|
||||
setSelected(inventoryButton)
|
||||
return setUnselected(wardrobeButton)
|
||||
elseif selectedTab == "wardrobe" then
|
||||
setSelected(wardrobeButton)
|
||||
return setUnselected(inventoryButton)
|
||||
end
|
||||
end
|
||||
local mouseLeaveTab
|
||||
mouseLeaveTab = function(button)
|
||||
assert(button)
|
||||
assert(button:IsA("TextButton"))
|
||||
if button.Selected then
|
||||
return
|
||||
end
|
||||
button.BackgroundColor3 = Color3.new(0, 0, 0)
|
||||
end
|
||||
local mouseOverTab
|
||||
mouseOverTab = function(button)
|
||||
assert(button)
|
||||
assert(button:IsA("TextButton"))
|
||||
if button.Selected then
|
||||
return
|
||||
end
|
||||
button.BackgroundColor3 = Color3.new(39 / 255, 39 / 255, 39 / 255)
|
||||
end
|
||||
local newTabClicked
|
||||
newTabClicked = function(tabName)
|
||||
assert(tabName)
|
||||
tabName = string.lower(tabName)
|
||||
currentTab = tabName
|
||||
updateTabGui(tabName)
|
||||
tabClickedEvent:Fire(tabName)
|
||||
return resetSearch()
|
||||
end
|
||||
local trim
|
||||
trim = function(s)
|
||||
return s:gsub("^%s*(.-)%s*$", "%1")
|
||||
end
|
||||
local doSearch
|
||||
doSearch = function()
|
||||
local searchText = searchBox.Text
|
||||
if searchText == "" then
|
||||
resetSearch()
|
||||
return
|
||||
end
|
||||
searchText = trim(searchText)
|
||||
resetButton.Visible = true
|
||||
return searchRequestedEvent:Fire(searchText)
|
||||
end
|
||||
local backpackReady
|
||||
backpackReady = function()
|
||||
readyForNextEvent = true
|
||||
end
|
||||
local coreGuiChanged
|
||||
coreGuiChanged = function(coreGuiType, enabled)
|
||||
if coreGuiType == Enum.CoreGuiType.Backpack or coreGuiType == Enum.CoreGuiType.All then
|
||||
active = enabled
|
||||
disabledByDeveloper = not enabled
|
||||
do
|
||||
local _with_0 = game:GetService("GuiService")
|
||||
if disabledByDeveloper then
|
||||
pcall(function()
|
||||
_with_0:RemoveKey(tilde)
|
||||
return _with_0:RemoveKey(backquote)
|
||||
end)
|
||||
else
|
||||
_with_0:AddKey(tilde)
|
||||
_with_0:AddKey(backquote)
|
||||
end
|
||||
end
|
||||
resetSearch()
|
||||
searchFrame.Visible = enabled and backpackIsOpen
|
||||
currentLoadout.Visible = enabled
|
||||
backpack.Visible = enabled
|
||||
backpackButton.Visible = enabled
|
||||
end
|
||||
end
|
||||
createPublicFunction("CloseBackpack", hideBackpack)
|
||||
createPublicFunction("BackpackReady", backpackReady)
|
||||
pcall(function()
|
||||
coreGuiChanged(Enum.CoreGuiType.Backpack, Game.StarterGui:GetCoreGuiEnabled(Enum.CoreGuiType.Backpack))
|
||||
return Game.StarterGui.CoreGuiChangedSignal:connect(coreGuiChanged)
|
||||
end)
|
||||
inventoryButton.MouseButton1Click:connect(function()
|
||||
return newTabClicked("gear")
|
||||
end)
|
||||
inventoryButton.MouseEnter:connect(function()
|
||||
return mouseOverTab(inventoryButton)
|
||||
end)
|
||||
inventoryButton.MouseLeave:connect(function()
|
||||
return mouseLeaveTab(inventoryButton)
|
||||
end)
|
||||
if game.CoreGui.Version >= 8 then
|
||||
wardrobeButton.MouseButton1Click:connect(function()
|
||||
return newTabClicked("wardrobe")
|
||||
end)
|
||||
wardrobeButton.MouseEnter:connect(function()
|
||||
return mouseOverTab(wardrobeButton)
|
||||
end)
|
||||
wardrobeButton.MouseLeave:connect(function()
|
||||
return mouseLeaveTab(wardrobeButton)
|
||||
end)
|
||||
end
|
||||
closeButton.MouseButton1Click:connect(closeBackpack)
|
||||
screen.Changed:connect(function(prop)
|
||||
if prop == "AbsoluteSize" then
|
||||
return resizeEvent:Fire(screen.AbsoluteSize)
|
||||
end
|
||||
end)
|
||||
do
|
||||
local _with_0 = game:GetService("GuiService")
|
||||
_with_0:AddKey(tilde)
|
||||
_with_0:AddKey(backquote)
|
||||
_with_0.KeyPressed:connect(function(key)
|
||||
if not active or disabledByDeveloper then
|
||||
return
|
||||
end
|
||||
if key == tilde or key == backquote then
|
||||
return toggleBackpack()
|
||||
end
|
||||
end)
|
||||
end
|
||||
backpackButton.MouseButton1Click:connect(function()
|
||||
if not active or disabledByDeveloper then
|
||||
return
|
||||
end
|
||||
return toggleBackpack()
|
||||
end)
|
||||
if game.Players.LocalPlayer["Character"] then
|
||||
activateBackpack()
|
||||
end
|
||||
game.Players.LocalPlayer.CharacterAdded:connect(activateBackpack)
|
||||
searchBox.FocusLost:connect(function(enterPressed)
|
||||
if enterPressed or searchBox.Text ~= "" then
|
||||
return doSearch()
|
||||
elseif searchBox.Text == "" then
|
||||
return resetSearch()
|
||||
end
|
||||
end)
|
||||
searchButton.MouseButton1Click:connect(doSearch)
|
||||
resetButton.MouseButton1Click:connect(resetSearch)
|
||||
if searchFrame and robloxGui.AbsoluteSize.Y <= 320 then
|
||||
searchFrame.RobloxLocked = false
|
||||
return searchFrame:Destroy()
|
||||
end
|
||||
411
yue/89449093.yue
411
yue/89449093.yue
|
|
@ -0,0 +1,411 @@
|
|||
-- This script manages context switches in the backpack (Gear to Wardrobe, etc.) and player state changes. Also manages global functions across different tabs (currently only search)
|
||||
return if game.CoreGui.Version < 7
|
||||
-- peace out if we aren't using the right client
|
||||
|
||||
-- basic functions
|
||||
waitForChild = (instance, name) ->
|
||||
until instance\FindFirstChild name
|
||||
instance.ChildAdded\wait!
|
||||
|
||||
instance\FindFirstChild name
|
||||
|
||||
waitForProperty = (instance, property) ->
|
||||
until instance[property]
|
||||
instance.Changed\wait!
|
||||
|
||||
-- don't do anything if we are in an empty game
|
||||
waitForChild game, "Players"
|
||||
if #game.Players\GetChildren! < 1
|
||||
game.Players.ChildAdded\wait!
|
||||
|
||||
-- make sure everything is loaded in before we do anything
|
||||
-- get our local player
|
||||
waitForProperty game.Players, "LocalPlayer"
|
||||
|
||||
------------------------ Locals ------------------------------
|
||||
backpack = script.Parent
|
||||
waitForChild backpack, "Gear"
|
||||
|
||||
screen = script.Parent.Parent
|
||||
assert screen\IsA "ScreenGui"
|
||||
|
||||
waitForChild backpack, "Tabs"
|
||||
waitForChild backpack.Tabs, "CloseButton"
|
||||
closeButton = backpack.Tabs.CloseButton
|
||||
|
||||
waitForChild backpack.Tabs, "InventoryButton"
|
||||
inventoryButton = backpack.Tabs.InventoryButton
|
||||
|
||||
local wardrobeButton
|
||||
if game.CoreGui.Version >= 8
|
||||
waitForChild backpack.Tabs, "WardrobeButton"
|
||||
wardrobeButton = backpack.Tabs.WardrobeButton
|
||||
|
||||
waitForChild backpack.Parent, "ControlFrame"
|
||||
backpackButton = waitForChild backpack.Parent.ControlFrame, "BackpackButton"
|
||||
currentTab = "gear"
|
||||
|
||||
searchFrame = waitForChild backpack, "SearchFrame"
|
||||
waitForChild backpack.SearchFrame, "SearchBoxFrame"
|
||||
searchBox = waitForChild backpack.SearchFrame.SearchBoxFrame, "SearchBox"
|
||||
searchButton = waitForChild backpack.SearchFrame, "SearchButton"
|
||||
resetButton = waitForChild backpack.SearchFrame, "ResetButton"
|
||||
|
||||
robloxGui = waitForChild Game.CoreGui, "RobloxGui"
|
||||
currentLoadout = waitForChild robloxGui, "CurrentLoadout"
|
||||
loadoutBackground = waitForChild currentLoadout, "Background"
|
||||
|
||||
canToggle = true
|
||||
readyForNextEvent = true
|
||||
backpackIsOpen = false
|
||||
active = true
|
||||
disabledByDeveloper = false
|
||||
|
||||
local humanoidDiedCon
|
||||
|
||||
guiTweenSpeed = 0.25 -- how quickly we open/close the backpack
|
||||
|
||||
searchDefaultText = "Search..."
|
||||
tilde = "~"
|
||||
backquote = "`"
|
||||
|
||||
backpackSize = UDim2.new 0, 600, 0, 400
|
||||
|
||||
if robloxGui.AbsoluteSize.Y <= 320
|
||||
backpackSize = UDim2.new 0, 200, 0, 140
|
||||
|
||||
|
||||
------------------------ End Locals ---------------------------
|
||||
|
||||
---------------------------------------- Public Event Setup ----------------------------------------
|
||||
|
||||
createPublicEvent = (eventName) ->
|
||||
assert eventName, "eventName is nil"
|
||||
assert "#{eventName}", "eventName is not a string"
|
||||
|
||||
with Instance.new "BindableEvent"
|
||||
.Name = "#{eventName}"
|
||||
.Parent = script
|
||||
|
||||
createPublicFunction = (funcName, invokeFunc) ->
|
||||
assert funcName, "funcName is nil"
|
||||
assert "#{funcName}", "funcName is not a string"
|
||||
assert invokeFunc, "invokeFunc is nil"
|
||||
assert type(invokeFunc) == "function", "invokeFunc should be of type 'function'"
|
||||
|
||||
with Instance.new "BindableFunction"
|
||||
.Name = "#{funcName}"
|
||||
.OnInvoke = invokeFunc
|
||||
.Parent = script
|
||||
|
||||
-- Events
|
||||
resizeEvent = createPublicEvent "ResizeEvent"
|
||||
backpackOpenEvent = createPublicEvent "BackpackOpenEvent"
|
||||
backpackCloseEvent = createPublicEvent "BackpackCloseEvent"
|
||||
tabClickedEvent = createPublicEvent "TabClickedEvent"
|
||||
searchRequestedEvent = createPublicEvent "SearchRequestedEvent"
|
||||
---------------------------------------- End Public Event Setup ----------------------------------------
|
||||
|
||||
--------------------------- Internal Functions ----------------------------------------
|
||||
|
||||
resetSearchBoxGui = ->
|
||||
resetButton.Visible = false
|
||||
searchBox.Text = searchDefaultText
|
||||
|
||||
resetSearch = ->
|
||||
resetSearchBoxGui!
|
||||
searchRequestedEvent\Fire!
|
||||
|
||||
deactivateBackpack = ->
|
||||
backpack.Visible = false
|
||||
active = false
|
||||
|
||||
initHumanoidDiedConnections = ->
|
||||
if humanoidDiedCon
|
||||
humanoidDiedCon\disconnect!
|
||||
|
||||
waitForProperty game.Players.LocalPlayer, "Character"
|
||||
waitForChild game.Players.LocalPlayer.Character, "Humanoid"
|
||||
humanoidDiedCon = game.Players.LocalPlayer.Character.Humanoid.Died\connect deactivateBackpack
|
||||
|
||||
hideBackpack = ->
|
||||
backpackIsOpen = false
|
||||
readyForNextEvent = false
|
||||
backpackButton.Selected = false
|
||||
resetSearch!
|
||||
backpackCloseEvent\Fire currentTab
|
||||
backpack.Tabs.Visible = false
|
||||
searchFrame.Visible = false
|
||||
backpack\TweenSizeAndPosition(
|
||||
UDim2.new(0, backpackSize.X.Offset, 0, 0),
|
||||
UDim2.new(0.5, -backpackSize.X.Offset / 2, 1, -85),
|
||||
Enum.EasingDirection.Out,
|
||||
Enum.EasingStyle.Quad,
|
||||
guiTweenSpeed,
|
||||
true,
|
||||
->
|
||||
game.GuiService\RemoveCenterDialog backpack
|
||||
backpack.Visible = false
|
||||
backpackButton.Selected = false
|
||||
)
|
||||
delay guiTweenSpeed, ->
|
||||
game.GuiService\RemoveCenterDialog backpack
|
||||
backpack.Visible = false
|
||||
backpackButton.Selected = false
|
||||
readyForNextEvent = true
|
||||
canToggle = true
|
||||
|
||||
showBackpack = ->
|
||||
game.GuiService\AddCenterDialog(backpack, Enum.CenterDialogType.PlayerInitiatedDialog, ->
|
||||
backpack.Visible = true
|
||||
backpackButton.Selected = true
|
||||
->
|
||||
backpack.Visible = false
|
||||
backpackButton.Selected = false
|
||||
)
|
||||
backpack.Visible = true
|
||||
backpackButton.Selected = true
|
||||
backpack\TweenSizeAndPosition(
|
||||
backpackSize,
|
||||
UDim2.new(0.5, -backpackSize.X.Offset / 2, 1, -backpackSize.Y.Offset - 88),
|
||||
Enum.EasingDirection.Out,
|
||||
Enum.EasingStyle.Quad,
|
||||
guiTweenSpeed,
|
||||
true
|
||||
)
|
||||
delay guiTweenSpeed, ->
|
||||
backpack.Tabs.Visible = false
|
||||
searchFrame.Visible = true
|
||||
backpackOpenEvent\Fire currentTab
|
||||
canToggle = true
|
||||
readyForNextEvent = true
|
||||
backpackButton.Image = "http://www.roblox.com/asset/?id=97644093"
|
||||
backpackButton.Position = UDim2.new 0.5, -60, 1, -backpackSize.Y.Offset - 103
|
||||
|
||||
toggleBackpack = ->
|
||||
return if not game.Players.LocalPlayer
|
||||
return if not game.Players.LocalPlayer["Character"]
|
||||
return if not canToggle
|
||||
return if not readyForNextEvent
|
||||
|
||||
readyForNextEvent = false
|
||||
canToggle = false
|
||||
|
||||
backpackIsOpen = not backpackIsOpen
|
||||
|
||||
if backpackIsOpen
|
||||
with loadoutBackground
|
||||
.Image = "http://www.roblox.com/asset/?id=97623721"
|
||||
.Position = UDim2.new -0.03, 0, -0.17, 0
|
||||
.Size = UDim2.new 1.05, 0, 1.25, 0
|
||||
.ZIndex = 2.0
|
||||
.Visible = true
|
||||
showBackpack!
|
||||
else
|
||||
backpackButton.Position = UDim2.new 0.5, -60, 1, -44
|
||||
loadoutBackground.Visible = false
|
||||
backpackButton.Selected = false
|
||||
backpackButton.Image = "http://www.roblox.com/asset/?id=97617958"
|
||||
loadoutBackground.Image = "http://www.roblox.com/asset/?id=96536002"
|
||||
loadoutBackground.Position = UDim2.new -0.1, 0, -0.1, 0
|
||||
loadoutBackground.Size = UDim2.new 1.2, 0, 1.2, 0
|
||||
hideBackpack!
|
||||
|
||||
clChildren = currentLoadout\GetChildren!
|
||||
for i = 1, #clChildren
|
||||
if clChildren[i] and clChildren[i]\IsA "Frame"
|
||||
frame = clChildren[i]
|
||||
if #frame\GetChildren! > 0
|
||||
backpackButton.Position = UDim2.new 0.5, -60, 1, -108
|
||||
backpackButton.Visible = true
|
||||
loadoutBackground.Visible = true
|
||||
if frame\GetChildren![1]\IsA "ImageButton"
|
||||
imgButton = frame\GetChildren![1]
|
||||
imgButton.Active = true
|
||||
imgButton.Draggable = false
|
||||
|
||||
|
||||
activateBackpack = ->
|
||||
initHumanoidDiedConnections!
|
||||
active = true
|
||||
backpack.Visible = backpackIsOpen
|
||||
if backpackIsOpen
|
||||
toggleBackpack!
|
||||
|
||||
closeBackpack = ->
|
||||
if backpackIsOpen
|
||||
toggleBackpack!
|
||||
|
||||
setSelected = (tab) ->
|
||||
assert tab
|
||||
with tab
|
||||
assert \IsA "TextButton"
|
||||
.BackgroundColor3 = Color3.new 1, 1, 1
|
||||
.TextColor3 = Color3.new 0, 0, 0
|
||||
.Selected = true
|
||||
.ZIndex = 3
|
||||
|
||||
setUnselected = (tab) ->
|
||||
assert tab
|
||||
with tab
|
||||
assert \IsA "TextButton"
|
||||
.BackgroundColor3 = Color3.new 0, 0, 0
|
||||
.TextColor3 = Color3.new 1, 1, 1
|
||||
.Selected = false
|
||||
.ZIndex = 1
|
||||
|
||||
updateTabGui = (selectedTab) ->
|
||||
assert selectedTab
|
||||
|
||||
if selectedTab == "gear"
|
||||
setSelected inventoryButton
|
||||
setUnselected wardrobeButton
|
||||
elseif selectedTab == "wardrobe"
|
||||
setSelected wardrobeButton
|
||||
setUnselected inventoryButton
|
||||
|
||||
mouseLeaveTab = (button) ->
|
||||
assert button
|
||||
assert button\IsA "TextButton"
|
||||
|
||||
return if button.Selected
|
||||
|
||||
button.BackgroundColor3 = Color3.new 0, 0, 0
|
||||
|
||||
mouseOverTab = (button) ->
|
||||
assert button
|
||||
assert button\IsA "TextButton"
|
||||
|
||||
return if button.Selected
|
||||
|
||||
button.BackgroundColor3 = Color3.new 39 / 255, 39 / 255, 39 / 255
|
||||
|
||||
|
||||
newTabClicked = (tabName) ->
|
||||
assert tabName
|
||||
tabName = string.lower tabName
|
||||
currentTab = tabName
|
||||
|
||||
updateTabGui tabName
|
||||
tabClickedEvent\Fire tabName
|
||||
resetSearch!
|
||||
|
||||
|
||||
trim = (s) -> s\gsub "^%s*(.-)%s*$", "%1"
|
||||
|
||||
|
||||
-- splitByWhitespace = (text) ->
|
||||
-- return if type(text) ~= "string"
|
||||
|
||||
-- terms = {}
|
||||
-- for token in string.gmatch text, "[^%s]+"
|
||||
-- if string.len(token) > 0
|
||||
-- table.insert terms, token
|
||||
|
||||
-- terms
|
||||
|
||||
doSearch = ->
|
||||
searchText = searchBox.Text
|
||||
if searchText == ""
|
||||
resetSearch!
|
||||
return
|
||||
|
||||
searchText = trim searchText
|
||||
resetButton.Visible = true
|
||||
-- termTable = splitByWhitespace(searchText)
|
||||
searchRequestedEvent\Fire searchText -- todo: replace this with termtable when table passing is possible
|
||||
|
||||
backpackReady = ->
|
||||
readyForNextEvent = true
|
||||
|
||||
coreGuiChanged = (coreGuiType, enabled) ->
|
||||
if coreGuiType == Enum.CoreGuiType.Backpack or coreGuiType == Enum.CoreGuiType.All
|
||||
active = enabled
|
||||
disabledByDeveloper = not enabled
|
||||
|
||||
with game\GetService "GuiService"
|
||||
if disabledByDeveloper
|
||||
try
|
||||
\RemoveKey tilde
|
||||
\RemoveKey backquote
|
||||
else
|
||||
\AddKey tilde
|
||||
\AddKey backquote
|
||||
|
||||
|
||||
resetSearch!
|
||||
searchFrame.Visible = enabled and backpackIsOpen
|
||||
|
||||
currentLoadout.Visible = enabled
|
||||
backpack.Visible = enabled
|
||||
backpackButton.Visible = enabled
|
||||
|
||||
|
||||
|
||||
--------------------------- End Internal Functions -------------------------------------
|
||||
|
||||
------------------------------ Public Functions Setup -------------------------------------
|
||||
createPublicFunction "CloseBackpack", hideBackpack
|
||||
createPublicFunction "BackpackReady", backpackReady
|
||||
------------------------------ End Public Functions Setup ---------------------------------
|
||||
|
||||
------------------------ Connections/Script Main -------------------------------------------
|
||||
|
||||
try
|
||||
coreGuiChanged Enum.CoreGuiType.Backpack, Game.StarterGui\GetCoreGuiEnabled Enum.CoreGuiType.Backpack
|
||||
Game.StarterGui.CoreGuiChangedSignal\connect coreGuiChanged
|
||||
|
||||
with inventoryButton
|
||||
.MouseButton1Click\connect -> newTabClicked "gear"
|
||||
.MouseEnter\connect -> mouseOverTab inventoryButton
|
||||
.MouseLeave\connect -> mouseLeaveTab inventoryButton
|
||||
|
||||
if game.CoreGui.Version >= 8
|
||||
with wardrobeButton
|
||||
.MouseButton1Click\connect -> newTabClicked "wardrobe"
|
||||
.MouseEnter\connect -> mouseOverTab wardrobeButton
|
||||
.MouseLeave\connect -> mouseLeaveTab wardrobeButton
|
||||
|
||||
closeButton.MouseButton1Click\connect closeBackpack
|
||||
|
||||
screen.Changed\connect (prop) ->
|
||||
if prop == "AbsoluteSize"
|
||||
resizeEvent\Fire screen.AbsoluteSize
|
||||
|
||||
|
||||
-- GuiService key setup
|
||||
with game\GetService "GuiService"
|
||||
\AddKey tilde
|
||||
\AddKey backquote
|
||||
.KeyPressed\connect (key) ->
|
||||
return if not active or disabledByDeveloper
|
||||
|
||||
if key == tilde or key == backquote
|
||||
toggleBackpack!
|
||||
|
||||
|
||||
backpackButton.MouseButton1Click\connect ->
|
||||
return if not active or disabledByDeveloper
|
||||
|
||||
toggleBackpack!
|
||||
|
||||
if game.Players.LocalPlayer["Character"]
|
||||
activateBackpack!
|
||||
|
||||
|
||||
game.Players.LocalPlayer.CharacterAdded\connect activateBackpack
|
||||
|
||||
-- search functions
|
||||
searchBox.FocusLost\connect (enterPressed) ->
|
||||
if enterPressed or searchBox.Text ~= ""
|
||||
doSearch!
|
||||
elseif searchBox.Text == ""
|
||||
resetSearch!
|
||||
|
||||
|
||||
searchButton.MouseButton1Click\connect doSearch
|
||||
resetButton.MouseButton1Click\connect resetSearch
|
||||
|
||||
if searchFrame and robloxGui.AbsoluteSize.Y <= 320
|
||||
searchFrame.RobloxLocked = false
|
||||
searchFrame\Destroy!
|
||||
Loading…
Reference in New Issue