forked from aya/aya
Initial commit
This commit is contained in:
656
client/common/content/scripts/CoreScripts/2016/BubbleChat.lua
Normal file
656
client/common/content/scripts/CoreScripts/2016/BubbleChat.lua
Normal file
@@ -0,0 +1,656 @@
|
||||
--[[
|
||||
// FileName: BubbleChat.lua
|
||||
// Written by: jeditkacheff
|
||||
// Description: Code for rendering bubble chat
|
||||
]]
|
||||
|
||||
--[[ SERVICES ]]
|
||||
local RunService = game:GetService('RunService')
|
||||
local CoreGuiService = game:GetService('CoreGui')
|
||||
local PlayersService = game:GetService('Players')
|
||||
local ChatService = game:GetService("Chat")
|
||||
local TextService = game:GetService("TextService")
|
||||
local GameOptions = settings()["Game Options"]
|
||||
--[[ END OF SERVICES ]]
|
||||
|
||||
|
||||
while PlayersService.LocalPlayer == nil do PlayersService.ChildAdded:wait() end
|
||||
local GuiRoot = CoreGuiService:WaitForChild('RobloxGui')
|
||||
local playerDropDownModule = require(GuiRoot.Modules:WaitForChild("PlayerDropDown"))
|
||||
local blockingUtility = playerDropDownModule:CreateBlockingUtility()
|
||||
|
||||
--[[ SCRIPT VARIABLES ]]
|
||||
local CHAT_BUBBLE_FONT = Enum.Font.SourceSans
|
||||
local CHAT_BUBBLE_FONT_SIZE = Enum.FontSize.Size24 -- if you change CHAT_BUBBLE_FONT_SIZE_INT please change this to match
|
||||
local CHAT_BUBBLE_FONT_SIZE_INT = 24 -- if you change CHAT_BUBBLE_FONT_SIZE please change this to match
|
||||
local CHAT_BUBBLE_LINE_HEIGHT = CHAT_BUBBLE_FONT_SIZE_INT + 10
|
||||
local CHAT_BUBBLE_TAIL_HEIGHT = 14
|
||||
local CHAT_BUBBLE_WIDTH_PADDING = 30
|
||||
local CHAT_BUBBLE_FADE_SPEED = 1.5
|
||||
|
||||
local BILLBOARD_MAX_WIDTH = 400
|
||||
local BILLBOARD_MAX_HEIGHT = 250 --This limits the number of bubble chats that you see above characters
|
||||
|
||||
local ELIPSES = "..."
|
||||
local CchMaxChatMessageLength = 128 -- max chat message length, including null terminator and elipses.
|
||||
local CchMaxChatMessageLengthExclusive = CchMaxChatMessageLength - string.len(ELIPSES) - 1
|
||||
|
||||
local NEAR_BUBBLE_DISTANCE = 65 --previously 45
|
||||
local MAX_BUBBLE_DISTANCE = 100 --previously 80
|
||||
|
||||
--[[ END OF SCRIPT VARIABLES ]]
|
||||
|
||||
|
||||
-- [[ SCRIPT ENUMS ]]
|
||||
local ChatType = { PLAYER_CHAT = "pChat",
|
||||
PLAYER_TEAM_CHAT = "pChatTeam",
|
||||
PLAYER_WHISPER_CHAT = "pChatWhisper",
|
||||
GAME_MESSAGE= "gMessage",
|
||||
PLAYER_GAME_CHAT = "pGame",
|
||||
BOT_CHAT = "bChat" }
|
||||
|
||||
local BubbleColor = { WHITE = "dub",
|
||||
BLUE = "blu",
|
||||
GREEN = "gre",
|
||||
RED = "red" }
|
||||
|
||||
--[[ END OF SCRIPT ENUMS ]]
|
||||
|
||||
|
||||
|
||||
--[[ FUNCTIONS ]]
|
||||
|
||||
local function lerpLength(msg, min, max)
|
||||
return min + (max-min) * math.min(string.len(msg)/75.0, 1.0)
|
||||
end
|
||||
|
||||
local function createFifo()
|
||||
local this = {}
|
||||
this.data = {}
|
||||
|
||||
local emptyEvent = Instance.new("BindableEvent")
|
||||
this.Emptied = emptyEvent.Event
|
||||
|
||||
function this:Size()
|
||||
return #this.data
|
||||
end
|
||||
|
||||
function this:Empty()
|
||||
return this:Size() <= 0
|
||||
end
|
||||
|
||||
function this:PopFront()
|
||||
table.remove(this.data, 1)
|
||||
if this:Empty() then emptyEvent:Fire() end
|
||||
end
|
||||
|
||||
function this:Front()
|
||||
return this.data[1]
|
||||
end
|
||||
|
||||
function this:Get(index)
|
||||
return this.data[index]
|
||||
end
|
||||
|
||||
function this:PushBack(value)
|
||||
table.insert(this.data, value)
|
||||
end
|
||||
|
||||
function this:GetData()
|
||||
return this.data
|
||||
end
|
||||
|
||||
return this
|
||||
end
|
||||
|
||||
local function createCharacterChats()
|
||||
local this = {}
|
||||
|
||||
this.Fifo = createFifo()
|
||||
this.BillboardGui = nil
|
||||
|
||||
return this
|
||||
end
|
||||
|
||||
local function createMap()
|
||||
local this = {}
|
||||
this.data = {}
|
||||
local count = 0
|
||||
|
||||
function this:Size()
|
||||
return count
|
||||
end
|
||||
|
||||
function this:Erase(key)
|
||||
if this.data[key] then count = count - 1 end
|
||||
this.data[key] = nil
|
||||
end
|
||||
|
||||
function this:Set(key, value)
|
||||
this.data[key] = value
|
||||
if value then count = count + 1 end
|
||||
end
|
||||
|
||||
function this:Get(key)
|
||||
if not this.data[key] then
|
||||
this.data[key] = createCharacterChats()
|
||||
local emptiedCon = nil
|
||||
emptiedCon = this.data[key].Fifo.Emptied:connect(function()
|
||||
emptiedCon:disconnect()
|
||||
this:Erase(key)
|
||||
end)
|
||||
end
|
||||
return this.data[key]
|
||||
end
|
||||
|
||||
function this:GetData()
|
||||
return this.data
|
||||
end
|
||||
|
||||
return this
|
||||
end
|
||||
|
||||
local function createChatLine(chatType, message, bubbleColor, isLocalPlayer)
|
||||
local this = {}
|
||||
|
||||
function this:ComputeBubbleLifetime(msg, isSelf)
|
||||
if isSelf then
|
||||
return lerpLength(msg,8,15)
|
||||
else
|
||||
return lerpLength(msg,12,20)
|
||||
end
|
||||
end
|
||||
|
||||
function this:IsPlayerChat()
|
||||
if not this.ChatType then return false end
|
||||
|
||||
if this.ChatType == ChatType.PLAYER_CHAT or
|
||||
this.ChatType == ChatType.PLAYER_WHISPER_CHAT or
|
||||
this.ChatType == ChatType.PLAYER_TEAM_CHAT then
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
this.ChatType = chatType
|
||||
this.Origin = nil
|
||||
this.RenderBubble = nil
|
||||
this.Message = message
|
||||
this.BubbleDieDelay = this:ComputeBubbleLifetime(message, isLocalPlayer)
|
||||
this.BubbleColor = bubbleColor
|
||||
this.IsLocalPlayer = isLocalPlayer
|
||||
|
||||
return this
|
||||
end
|
||||
|
||||
local function createPlayerChatLine(chatType, player, message, isLocalPlayer)
|
||||
local this = createChatLine(chatType, message, BubbleColor.WHITE, isLocalPlayer)
|
||||
|
||||
if player then
|
||||
this.User = player.Name
|
||||
this.Origin = player.Character
|
||||
end
|
||||
|
||||
return this
|
||||
end
|
||||
|
||||
local function createGameChatLine(origin, message, isLocalPlayer, bubbleColor)
|
||||
local this = createChatLine(origin and ChatType.PLAYER_GAME_CHAT or ChatType.BOT_CHAT, message, bubbleColor, isLocalPlayer)
|
||||
this.Origin = origin
|
||||
|
||||
return this
|
||||
end
|
||||
|
||||
function createChatBubbleMain(filePrefix, sliceRect)
|
||||
local chatBubbleMain = Instance.new("ImageLabel")
|
||||
chatBubbleMain.Name = "ChatBubble"
|
||||
chatBubbleMain.ScaleType = Enum.ScaleType.Slice
|
||||
chatBubbleMain.SliceCenter = sliceRect
|
||||
chatBubbleMain.Image = "ayaasset://textures/" .. tostring(filePrefix) .. ".png"
|
||||
chatBubbleMain.BackgroundTransparency = 1
|
||||
chatBubbleMain.BorderSizePixel = 0
|
||||
chatBubbleMain.Size = UDim2.new(1.0, 0, 1.0, 0)
|
||||
chatBubbleMain.Position = UDim2.new(0,0,0,0)
|
||||
|
||||
return chatBubbleMain
|
||||
end
|
||||
|
||||
function createChatBubbleTail(position, size)
|
||||
local chatBubbleTail = Instance.new("ImageLabel")
|
||||
chatBubbleTail.Name = "ChatBubbleTail"
|
||||
chatBubbleTail.Image = "ayaasset://textures/ui/dialog_tail_old.png"
|
||||
chatBubbleTail.BackgroundTransparency = 1
|
||||
chatBubbleTail.BorderSizePixel = 0
|
||||
chatBubbleTail.Position = position
|
||||
chatBubbleTail.Size = size
|
||||
|
||||
return chatBubbleTail
|
||||
end
|
||||
|
||||
function createChatBubbleWithTail(filePrefix, position, size, sliceRect)
|
||||
local chatBubbleMain = createChatBubbleMain(filePrefix, sliceRect)
|
||||
|
||||
local chatBubbleTail = createChatBubbleTail(position, size)
|
||||
chatBubbleTail.Parent = chatBubbleMain
|
||||
|
||||
return chatBubbleMain
|
||||
end
|
||||
|
||||
function createScaledChatBubbleWithTail(filePrefix, frameScaleSize, position, sliceRect)
|
||||
local chatBubbleMain = createChatBubbleMain(filePrefix, sliceRect)
|
||||
|
||||
local frame = Instance.new("Frame")
|
||||
frame.Name = "ChatBubbleTailFrame"
|
||||
frame.BackgroundTransparency = 1
|
||||
frame.SizeConstraint = Enum.SizeConstraint.RelativeXX
|
||||
frame.Position = UDim2.new(0.5, 0, 1, 0)
|
||||
frame.Size = UDim2.new(frameScaleSize, 0, frameScaleSize, 0)
|
||||
frame.Parent = chatBubbleMain
|
||||
|
||||
local chatBubbleTail = createChatBubbleTail(position, UDim2.new(1,0,0.5,0))
|
||||
chatBubbleTail.Parent = frame
|
||||
|
||||
return chatBubbleMain
|
||||
end
|
||||
|
||||
function createChatImposter(filePrefix, dotDotDot, yOffset)
|
||||
local result = Instance.new("ImageLabel")
|
||||
result.Name = "DialogPlaceholder"
|
||||
result.Image = "ayaasset://textures/" .. tostring(filePrefix) .. ".png"
|
||||
result.BackgroundTransparency = 1
|
||||
result.BorderSizePixel = 0
|
||||
result.Position = UDim2.new(0, 0, -1.25, 0)
|
||||
result.Size = UDim2.new(1, 0, 1, 0)
|
||||
|
||||
local image = Instance.new("ImageLabel")
|
||||
image.Name = "DotDotDot"
|
||||
image.Image = "ayaasset://textures/" .. tostring(dotDotDot) .. ".png"
|
||||
image.BackgroundTransparency = 1
|
||||
image.BorderSizePixel = 0
|
||||
image.Position = UDim2.new(0.001, 0, yOffset, 0)
|
||||
image.Size = UDim2.new(1, 0, 0.7, 0)
|
||||
image.Parent = result
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
local function createChatOutput()
|
||||
|
||||
local this = {}
|
||||
this.ChatBubble = {}
|
||||
this.ChatBubbleWithTail = {}
|
||||
this.ScalingChatBubbleWithTail = {}
|
||||
this.CharacterSortedMsg = createMap()
|
||||
|
||||
-- init chat bubble tables
|
||||
local function initChatBubbleType(chatBubbleType, fileName, imposterFileName, isInset, sliceRect)
|
||||
this.ChatBubble[chatBubbleType] = createChatBubbleMain(fileName, sliceRect)
|
||||
this.ChatBubbleWithTail[chatBubbleType] = createChatBubbleWithTail(fileName, UDim2.new(0.5, -CHAT_BUBBLE_TAIL_HEIGHT, 1, isInset and -1 or 0), UDim2.new(0, 30, 0, CHAT_BUBBLE_TAIL_HEIGHT), sliceRect)
|
||||
this.ScalingChatBubbleWithTail[chatBubbleType] = createScaledChatBubbleWithTail(fileName, 0.5, UDim2.new(-0.5, 0, 0, isInset and -1 or 0), sliceRect)
|
||||
end
|
||||
|
||||
initChatBubbleType(BubbleColor.WHITE, "ui/dialog_white_old", "ui/chatBubble_white_notify_bkg", false, Rect.new(5,5,15,15))
|
||||
initChatBubbleType(BubbleColor.BLUE, "ui/dialog_blue", "ui/chatBubble_blue_notify_bkg", true, Rect.new(7,7,33,33))
|
||||
initChatBubbleType(BubbleColor.RED, "ui/dialog_red", "ui/chatBubble_red_notify_bkg", true, Rect.new(7,7,33,33))
|
||||
initChatBubbleType(BubbleColor.GREEN, "ui/dialog_green", "ui/chatBubble_green_notify_bkg", true, Rect.new(7,7,33,33))
|
||||
|
||||
function this:SanitizeChatLine(msg)
|
||||
if string.len(msg) > CchMaxChatMessageLengthExclusive then
|
||||
return string.sub(msg, 1, CchMaxChatMessageLengthExclusive + string.len(ELIPSES))
|
||||
else
|
||||
return msg
|
||||
end
|
||||
end
|
||||
|
||||
local function createBillboardInstance(adornee)
|
||||
local billboardGui = Instance.new("BillboardGui")
|
||||
billboardGui.Adornee = adornee
|
||||
billboardGui.RobloxLocked = true
|
||||
billboardGui.Size = UDim2.new(0,BILLBOARD_MAX_WIDTH,0,BILLBOARD_MAX_HEIGHT)
|
||||
billboardGui.StudsOffset = Vector3.new(0, 1.5, 2)
|
||||
billboardGui.Parent = CoreGuiService
|
||||
|
||||
local billboardFrame = Instance.new("Frame")
|
||||
billboardFrame.Name = "BillboardFrame"
|
||||
billboardFrame.Size = UDim2.new(1,0,1,0)
|
||||
billboardFrame.Position = UDim2.new(0,0,-0.5,0)
|
||||
billboardFrame.BackgroundTransparency = 1
|
||||
billboardFrame.Parent = billboardGui
|
||||
|
||||
local billboardChildRemovedCon = nil
|
||||
billboardChildRemovedCon = billboardFrame.ChildRemoved:connect(function()
|
||||
if #billboardFrame:GetChildren() <= 1 then
|
||||
billboardChildRemovedCon:disconnect()
|
||||
billboardGui:Destroy()
|
||||
end
|
||||
end)
|
||||
|
||||
this:CreateSmallTalkBubble(BubbleColor.WHITE).Parent = billboardFrame
|
||||
|
||||
return billboardGui
|
||||
end
|
||||
|
||||
function this:CreateBillboardGuiHelper(instance, onlyCharacter)
|
||||
if not this.CharacterSortedMsg:Get(instance)["BillboardGui"] then
|
||||
if not onlyCharacter then
|
||||
if instance:IsA("Part") then
|
||||
-- Create a new billboardGui object attached to this player
|
||||
local billboardGui = createBillboardInstance(instance)
|
||||
this.CharacterSortedMsg:Get(instance)["BillboardGui"] = billboardGui
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if instance:IsA("Model") then
|
||||
local head = instance:FindFirstChild("Head")
|
||||
if head and head:IsA("Part") then
|
||||
-- Create a new billboardGui object attached to this player
|
||||
local billboardGui = createBillboardInstance(head)
|
||||
this.CharacterSortedMsg:Get(instance)["BillboardGui"] = billboardGui
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function distanceToBubbleOrigin(origin)
|
||||
if not origin then return 100000 end
|
||||
|
||||
return (origin.Position - game.Workspace.CurrentCamera.CoordinateFrame.p).magnitude
|
||||
end
|
||||
|
||||
local function isPartOfLocalPlayer(adornee)
|
||||
if adornee and PlayersService.LocalPlayer.Character then
|
||||
return adornee:IsDescendantOf(PlayersService.LocalPlayer.Character)
|
||||
end
|
||||
end
|
||||
|
||||
function this:SetBillboardLODNear(billboardGui)
|
||||
local isLocalPlayer = isPartOfLocalPlayer(billboardGui.Adornee)
|
||||
billboardGui.Size = UDim2.new(0, BILLBOARD_MAX_WIDTH, 0, BILLBOARD_MAX_HEIGHT)
|
||||
billboardGui.StudsOffset = Vector3.new(0, isLocalPlayer and 1.5 or 2.5, isLocalPlayer and 2 or 0)
|
||||
billboardGui.Enabled = true
|
||||
local billChildren = billboardGui.BillboardFrame:GetChildren()
|
||||
for i = 1, #billChildren do
|
||||
billChildren[i].Visible = true
|
||||
end
|
||||
billboardGui.BillboardFrame.SmallTalkBubble.Visible = false
|
||||
end
|
||||
|
||||
function this:SetBillboardLODDistant(billboardGui)
|
||||
local isLocalPlayer = isPartOfLocalPlayer(billboardGui.Adornee)
|
||||
billboardGui.Size = UDim2.new(4,0,3,0)
|
||||
billboardGui.StudsOffset = Vector3.new(0, 3, isLocalPlayer and 2 or 0)
|
||||
billboardGui.Enabled = true
|
||||
local billChildren = billboardGui.BillboardFrame:GetChildren()
|
||||
for i = 1, #billChildren do
|
||||
billChildren[i].Visible = false
|
||||
end
|
||||
billboardGui.BillboardFrame.SmallTalkBubble.Visible = true
|
||||
end
|
||||
|
||||
function this:SetBillboardLODVeryFar(billboardGui)
|
||||
billboardGui.Enabled = false
|
||||
end
|
||||
|
||||
function this:SetBillboardGuiLOD(billboardGui, origin)
|
||||
if not origin then return end
|
||||
|
||||
if origin:IsA("Model") then
|
||||
local head = origin:FindFirstChild("Head")
|
||||
if not head then origin = origin.PrimaryPart
|
||||
else origin = head end
|
||||
end
|
||||
|
||||
local bubbleDistance = distanceToBubbleOrigin(origin)
|
||||
|
||||
if bubbleDistance < NEAR_BUBBLE_DISTANCE then
|
||||
this:SetBillboardLODNear(billboardGui)
|
||||
elseif bubbleDistance >= NEAR_BUBBLE_DISTANCE and bubbleDistance < MAX_BUBBLE_DISTANCE then
|
||||
this:SetBillboardLODDistant(billboardGui)
|
||||
else
|
||||
this:SetBillboardLODVeryFar(billboardGui)
|
||||
end
|
||||
end
|
||||
|
||||
function this:CameraCFrameChanged()
|
||||
for index, value in pairs(this.CharacterSortedMsg:GetData()) do
|
||||
local playerBillboardGui = value["BillboardGui"]
|
||||
if playerBillboardGui then this:SetBillboardGuiLOD(playerBillboardGui, index) end
|
||||
end
|
||||
end
|
||||
|
||||
function this:CreateBubbleText(message)
|
||||
local bubbleText = Instance.new("TextLabel")
|
||||
bubbleText.Name = "BubbleText"
|
||||
bubbleText.BackgroundTransparency = 1
|
||||
bubbleText.Position = UDim2.new(0,CHAT_BUBBLE_WIDTH_PADDING/2,0,0)
|
||||
bubbleText.Size = UDim2.new(1,-CHAT_BUBBLE_WIDTH_PADDING,1,0)
|
||||
bubbleText.Font = CHAT_BUBBLE_FONT
|
||||
bubbleText.TextWrapped = true
|
||||
bubbleText.FontSize = CHAT_BUBBLE_FONT_SIZE
|
||||
bubbleText.Text = message
|
||||
bubbleText.Visible = false
|
||||
|
||||
return bubbleText
|
||||
end
|
||||
|
||||
function this:CreateSmallTalkBubble(chatBubbleType)
|
||||
local smallTalkBubble = this.ScalingChatBubbleWithTail[chatBubbleType]:Clone()
|
||||
smallTalkBubble.Name = "SmallTalkBubble"
|
||||
smallTalkBubble.Position = UDim2.new(0,0,1,-40)
|
||||
smallTalkBubble.Visible = false
|
||||
local text = this:CreateBubbleText("...")
|
||||
text.TextScaled = true
|
||||
text.TextWrapped = false
|
||||
text.Visible = true
|
||||
text.Parent = smallTalkBubble
|
||||
|
||||
return smallTalkBubble
|
||||
end
|
||||
|
||||
function this:UpdateChatLinesForOrigin(origin, currentBubbleYPos)
|
||||
local bubbleQueue = this.CharacterSortedMsg:Get(origin).Fifo
|
||||
local bubbleQueueSize = bubbleQueue:Size()
|
||||
local bubbleQueueData = bubbleQueue:GetData()
|
||||
if #bubbleQueueData <= 1 then return end
|
||||
|
||||
for index = (#bubbleQueueData - 1), 1, -1 do
|
||||
local value = bubbleQueueData[index]
|
||||
local bubble = value.RenderBubble
|
||||
if not bubble then return end
|
||||
local bubblePos = bubbleQueueSize - index + 1
|
||||
|
||||
if bubblePos > 1 then
|
||||
local tail = bubble:FindFirstChild("ChatBubbleTail")
|
||||
if tail then tail:Destroy() end
|
||||
local bubbleText = bubble:FindFirstChild("BubbleText")
|
||||
if bubbleText then bubbleText.TextTransparency = 0.5 end
|
||||
end
|
||||
|
||||
local udimValue = UDim2.new( bubble.Position.X.Scale, bubble.Position.X.Offset,
|
||||
1, currentBubbleYPos - bubble.Size.Y.Offset - CHAT_BUBBLE_TAIL_HEIGHT )
|
||||
bubble:TweenPosition(udimValue, Enum.EasingDirection.Out, Enum.EasingStyle.Bounce, 0.1, true)
|
||||
currentBubbleYPos = currentBubbleYPos - bubble.Size.Y.Offset - CHAT_BUBBLE_TAIL_HEIGHT
|
||||
end
|
||||
end
|
||||
|
||||
function this:DestroyBubble(bubbleQueue, bubbleToDestroy)
|
||||
if not bubbleQueue then return end
|
||||
if bubbleQueue:Empty() then return end
|
||||
|
||||
local bubble = bubbleQueue:Front().RenderBubble
|
||||
if not bubble then
|
||||
bubbleQueue:PopFront()
|
||||
return
|
||||
end
|
||||
|
||||
spawn(function()
|
||||
while bubbleQueue:Front().RenderBubble ~= bubbleToDestroy do
|
||||
wait()
|
||||
end
|
||||
|
||||
bubble = bubbleQueue:Front().RenderBubble
|
||||
|
||||
local timeBetween = 0
|
||||
local bubbleText = bubble:FindFirstChild("BubbleText")
|
||||
local bubbleTail = bubble:FindFirstChild("ChatBubbleTail")
|
||||
|
||||
while bubble and bubble.ImageTransparency < 1 do
|
||||
timeBetween = wait()
|
||||
if bubble then
|
||||
local fadeAmount = timeBetween * CHAT_BUBBLE_FADE_SPEED
|
||||
bubble.ImageTransparency = bubble.ImageTransparency + fadeAmount
|
||||
if bubbleText then bubbleText.TextTransparency = bubbleText.TextTransparency + fadeAmount end
|
||||
if bubbleTail then bubbleTail.ImageTransparency = bubbleTail.ImageTransparency + fadeAmount end
|
||||
end
|
||||
end
|
||||
|
||||
if bubble then
|
||||
bubble:Destroy()
|
||||
bubbleQueue:PopFront()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function this:CreateChatLineRender(instance, line, onlyCharacter, fifo)
|
||||
if not this.CharacterSortedMsg:Get(instance)["BillboardGui"] then
|
||||
this:CreateBillboardGuiHelper(instance, onlyCharacter)
|
||||
end
|
||||
|
||||
local billboardGui = this.CharacterSortedMsg:Get(instance)["BillboardGui"]
|
||||
local chatBubbleRender = this.ChatBubbleWithTail[line.BubbleColor]:Clone()
|
||||
chatBubbleRender.Visible = false
|
||||
local bubbleText = this:CreateBubbleText(line.Message)
|
||||
|
||||
bubbleText.Parent = chatBubbleRender
|
||||
chatBubbleRender.Parent = billboardGui.BillboardFrame
|
||||
|
||||
line.RenderBubble = chatBubbleRender
|
||||
|
||||
local currentTextBounds = TextService:GetTextSize(bubbleText.Text, CHAT_BUBBLE_FONT_SIZE_INT, CHAT_BUBBLE_FONT,
|
||||
Vector2.new(BILLBOARD_MAX_WIDTH, BILLBOARD_MAX_HEIGHT))
|
||||
local bubbleWidthScale = math.max((currentTextBounds.x + CHAT_BUBBLE_WIDTH_PADDING)/BILLBOARD_MAX_WIDTH, 0.1)
|
||||
local numOflines = (currentTextBounds.y/CHAT_BUBBLE_FONT_SIZE_INT)
|
||||
|
||||
-- prep chat bubble for tween
|
||||
chatBubbleRender.Size = UDim2.new(0,0,0,0)
|
||||
chatBubbleRender.Position = UDim2.new(0.5,0,1,0)
|
||||
|
||||
local newChatBubbleOffsetSizeY = numOflines * CHAT_BUBBLE_LINE_HEIGHT
|
||||
|
||||
chatBubbleRender:TweenSizeAndPosition(UDim2.new(bubbleWidthScale, 0, 0, newChatBubbleOffsetSizeY),
|
||||
UDim2.new( (1-bubbleWidthScale)/2, 0, 1, -newChatBubbleOffsetSizeY),
|
||||
Enum.EasingDirection.Out, Enum.EasingStyle.Elastic, 0.1, true,
|
||||
function() bubbleText.Visible = true end)
|
||||
|
||||
-- todo: remove when over max bubbles
|
||||
this:SetBillboardGuiLOD(billboardGui, line.Origin)
|
||||
this:UpdateChatLinesForOrigin(line.Origin, -newChatBubbleOffsetSizeY)
|
||||
|
||||
delay(line.BubbleDieDelay, function()
|
||||
this:DestroyBubble(fifo, chatBubbleRender)
|
||||
end)
|
||||
end
|
||||
|
||||
local testLabel = Instance.new('TextLabel')
|
||||
function isLabelTextAllowed(message)
|
||||
--There exists an internal filter that filters out some profanity. It does this silently if you try to set text of an object.
|
||||
--Here we check if the message is going to be filtered by applying it and comparing it.
|
||||
testLabel.Text = message
|
||||
return (testLabel.Text == message)
|
||||
end
|
||||
|
||||
function this:OnPlayerChatMessage(chatType, sourcePlayer, message, targetPlayer)
|
||||
if not this:BubbleChatEnabled() then return end
|
||||
|
||||
-- eliminate display of commands
|
||||
if string.sub(message, 1, 1) == '/' then return end
|
||||
|
||||
local localPlayer = PlayersService.LocalPlayer
|
||||
local fromOthers = localPlayer ~= nil and sourcePlayer ~= localPlayer
|
||||
|
||||
-- annihilate chats made by blocked or muted players
|
||||
if blockingUtility:IsPlayerBlockedByUserId(sourcePlayer.userId) or blockingUtility:IsPlayerMutedByUserId(sourcePlayer.userId) then return end
|
||||
|
||||
-- remove messages that are filtered from the default gui text filter
|
||||
if not isLabelTextAllowed(message) then return end
|
||||
|
||||
local luaChatType = ChatType.PLAYER_CHAT
|
||||
if chatType == Enum.PlayerChatType.Team then
|
||||
luaChatType = ChatType.PLAYER_TEAM_CHAT
|
||||
elseif chatType == Enum.PlayerChatType.All then
|
||||
luaChatType = ChatType.PLAYER_GAME_CHAT
|
||||
elseif chatType == Enum.PlayerChatType.Whisper then
|
||||
luaChatType = ChatType.PLAYER_WHISPER_CHAT
|
||||
end
|
||||
|
||||
local safeMessage = this:SanitizeChatLine(message)
|
||||
|
||||
local line = createPlayerChatLine(chatType, sourcePlayer, safeMessage, not fromOthers)
|
||||
|
||||
local fifo = this.CharacterSortedMsg:Get(line.Origin).Fifo
|
||||
fifo:PushBack(line)
|
||||
|
||||
if sourcePlayer then
|
||||
--Game chat (badges) won't show up here
|
||||
this:CreateChatLineRender(sourcePlayer.Character, line, true, fifo)
|
||||
end
|
||||
end
|
||||
|
||||
function this:OnGameChatMessage(origin, message, color)
|
||||
if not this:BubbleChatEnabled() then return end
|
||||
|
||||
local localPlayer = PlayersService.LocalPlayer
|
||||
local fromOthers = localPlayer ~= nil and (localPlayer.Character ~= origin)
|
||||
|
||||
local bubbleColor = BubbleColor.WHITE
|
||||
|
||||
if color == Enum.ChatColor.Blue then bubbleColor = BubbleColor.BLUE
|
||||
elseif color == Enum.ChatColor.Green then bubbleColor = BubbleColor.GREEN
|
||||
elseif color == Enum.ChatColor.Red then bubbleColor = BubbleColor.RED end
|
||||
|
||||
local safeMessage = this:SanitizeChatLine(message)
|
||||
local line = createGameChatLine(origin, safeMessage, not fromOthers, bubbleColor)
|
||||
|
||||
this.CharacterSortedMsg:Get(line.Origin).Fifo:PushBack(line)
|
||||
this:CreateChatLineRender(origin, line, false, this.CharacterSortedMsg:Get(line.Origin).Fifo)
|
||||
end
|
||||
|
||||
function this:BubbleChatEnabled()
|
||||
return PlayersService.BubbleChat
|
||||
end
|
||||
|
||||
function this:CameraChanged(prop)
|
||||
if prop == "CoordinateFrame" then
|
||||
this:CameraCFrameChanged()
|
||||
end
|
||||
end
|
||||
|
||||
-- setup to datamodel connections
|
||||
PlayersService.PlayerChatted:connect(function(chatType, player, message, targetPlayer) this:OnPlayerChatMessage(chatType, player, message, targetPlayer) end)
|
||||
ChatService.Chatted:connect(function(origin, message, color) this:OnGameChatMessage(origin, message, color) end)
|
||||
|
||||
local cameraChangedCon = nil
|
||||
if game.Workspace.CurrentCamera then
|
||||
cameraChangedCon = game.Workspace.CurrentCamera.Changed:connect(function(prop) this:CameraChanged(prop) end)
|
||||
end
|
||||
game.Workspace.Changed:connect(function(prop)
|
||||
if prop == "CurrentCamera" then
|
||||
if cameraChangedCon then cameraChangedCon:disconnect() end
|
||||
if game.Workspace.CurrentCamera then
|
||||
cameraChangedCon = game.Workspace.CurrentCamera.Changed:connect(function(prop) this:CameraChanged(prop) end)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
local isClient = false
|
||||
local success = pcall(function() isClient = game:GetService("RunService"):IsClient()end)
|
||||
|
||||
-- init only if we have a simulation going
|
||||
if isClient or not success then
|
||||
createChatOutput()
|
||||
end
|
||||
@@ -0,0 +1,267 @@
|
||||
-- ContextActionTouch.lua
|
||||
-- this script controls ui and firing of lua functions that are bound in ContextActionService for touch inputs
|
||||
-- Essentially a user can bind a lua function to a key code, input type (mousebutton1 etc.) and this
|
||||
|
||||
-- Variables
|
||||
local contextActionService = game:GetService("ContextActionService")
|
||||
local userInputService = game:GetService("UserInputService")
|
||||
local isTouchDevice = userInputService.TouchEnabled
|
||||
local functionTable = {}
|
||||
local buttonVector = {}
|
||||
local buttonScreenGui = nil
|
||||
local buttonFrame = nil
|
||||
|
||||
local ContextDownImage = "https://assetdelivery.roblox.com/v1/asset?id=97166756"
|
||||
local ContextUpImage = "https://assetdelivery.roblox.com/v1/asset?id=97166444"
|
||||
|
||||
local oldTouches = {}
|
||||
|
||||
local buttonPositionTable = {
|
||||
[1] = UDim2.new(0,123,0,70),
|
||||
[2] = UDim2.new(0,30,0,60),
|
||||
[3] = UDim2.new(0,180,0,160),
|
||||
[4] = UDim2.new(0,85,0,-25),
|
||||
[5] = UDim2.new(0,185,0,-25),
|
||||
[6] = UDim2.new(0,185,0,260),
|
||||
[7] = UDim2.new(0,216,0,65)
|
||||
}
|
||||
local maxButtons = #buttonPositionTable
|
||||
|
||||
-- Preload images
|
||||
game:GetService("ContentProvider"):Preload(ContextDownImage)
|
||||
game:GetService("ContentProvider"):Preload(ContextUpImage)
|
||||
|
||||
repeat wait() until game:GetService("Players").LocalPlayer
|
||||
|
||||
local localPlayer = game:GetService("Players").LocalPlayer
|
||||
|
||||
function createContextActionGui()
|
||||
if not buttonScreenGui and isTouchDevice then
|
||||
buttonScreenGui = Instance.new("ScreenGui")
|
||||
buttonScreenGui.Name = "ContextActionGui"
|
||||
|
||||
buttonFrame = Instance.new("Frame")
|
||||
buttonFrame.BackgroundTransparency = 1
|
||||
buttonFrame.Size = UDim2.new(0.3,0,0.5,0)
|
||||
buttonFrame.Position = UDim2.new(0.7,0,0.5,0)
|
||||
buttonFrame.Name = "ContextButtonFrame"
|
||||
buttonFrame.Parent = buttonScreenGui
|
||||
|
||||
buttonFrame.Visible = not userInputService.ModalEnabled
|
||||
userInputService.Changed:connect(function(property)
|
||||
if property == "ModalEnabled" then
|
||||
buttonFrame.Visible = not userInputService.ModalEnabled
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
-- functions
|
||||
function setButtonSizeAndPosition(object)
|
||||
local buttonSize = 55
|
||||
local xOffset = 10
|
||||
local yOffset = 95
|
||||
|
||||
-- todo: better way to determine mobile sized screens
|
||||
local onSmallScreen = (game:GetService("CoreGui").RobloxGui.AbsoluteSize.X < 600)
|
||||
if not onSmallScreen then
|
||||
buttonSize = 85
|
||||
xOffset = 40
|
||||
end
|
||||
|
||||
object.Size = UDim2.new(0,buttonSize,0,buttonSize)
|
||||
end
|
||||
|
||||
function contextButtonDown(button, inputObject, actionName)
|
||||
if inputObject.UserInputType == Enum.UserInputType.Touch then
|
||||
button.Image = ContextDownImage
|
||||
contextActionService:CallFunction(actionName, Enum.UserInputState.Begin, inputObject)
|
||||
end
|
||||
end
|
||||
|
||||
function contextButtonMoved(button, inputObject, actionName)
|
||||
if inputObject.UserInputType == Enum.UserInputType.Touch then
|
||||
button.Image = ContextDownImage
|
||||
contextActionService:CallFunction(actionName, Enum.UserInputState.Change, inputObject)
|
||||
end
|
||||
end
|
||||
|
||||
function contextButtonUp(button, inputObject, actionName)
|
||||
button.Image = ContextUpImage
|
||||
if inputObject.UserInputType == Enum.UserInputType.Touch and inputObject.UserInputState == Enum.UserInputState.End then
|
||||
contextActionService:CallFunction(actionName, Enum.UserInputState.End, inputObject)
|
||||
end
|
||||
end
|
||||
|
||||
function isSmallScreenDevice()
|
||||
return game:GetService("GuiService"):GetScreenResolution().y <= 320
|
||||
end
|
||||
|
||||
|
||||
function createNewButton(actionName, functionInfoTable)
|
||||
local contextButton = Instance.new("ImageButton")
|
||||
contextButton.Name = "ContextActionButton"
|
||||
contextButton.BackgroundTransparency = 1
|
||||
contextButton.Size = UDim2.new(0,90,0,90)
|
||||
contextButton.Active = true
|
||||
if isSmallScreenDevice() then
|
||||
contextButton.Size = UDim2.new(0,70,0,70)
|
||||
end
|
||||
contextButton.Image = ContextUpImage
|
||||
contextButton.Parent = buttonFrame
|
||||
|
||||
local currentButtonTouch = nil
|
||||
|
||||
userInputService.InputEnded:connect(function ( inputObject )
|
||||
oldTouches[inputObject] = nil
|
||||
end)
|
||||
contextButton.InputBegan:connect(function(inputObject)
|
||||
if oldTouches[inputObject] then return end
|
||||
|
||||
if inputObject.UserInputState == Enum.UserInputState.Begin and currentButtonTouch == nil then
|
||||
currentButtonTouch = inputObject
|
||||
contextButtonDown(contextButton, inputObject, actionName)
|
||||
end
|
||||
end)
|
||||
contextButton.InputChanged:connect(function(inputObject)
|
||||
if oldTouches[inputObject] then return end
|
||||
if currentButtonTouch ~= inputObject then return end
|
||||
|
||||
contextButtonMoved(contextButton, inputObject, actionName)
|
||||
end)
|
||||
contextButton.InputEnded:connect(function(inputObject)
|
||||
if oldTouches[inputObject] then return end
|
||||
if currentButtonTouch ~= inputObject then return end
|
||||
|
||||
currentButtonTouch = nil
|
||||
oldTouches[inputObject] = true
|
||||
contextButtonUp(contextButton, inputObject, actionName)
|
||||
end)
|
||||
|
||||
local actionIcon = Instance.new("ImageLabel")
|
||||
actionIcon.Name = "ActionIcon"
|
||||
actionIcon.Position = UDim2.new(0.175, 0, 0.175, 0)
|
||||
actionIcon.Size = UDim2.new(0.65, 0, 0.65, 0)
|
||||
actionIcon.BackgroundTransparency = 1
|
||||
if functionInfoTable["image"] and type(functionInfoTable["image"]) == "string" then
|
||||
actionIcon.Image = functionInfoTable["image"]
|
||||
end
|
||||
actionIcon.Parent = contextButton
|
||||
|
||||
local actionTitle = Instance.new("TextLabel")
|
||||
actionTitle.Name = "ActionTitle"
|
||||
actionTitle.Size = UDim2.new(1,0,1,0)
|
||||
actionTitle.BackgroundTransparency = 1
|
||||
actionTitle.Font = Enum.Font.SourceSansBold
|
||||
actionTitle.TextColor3 = Color3.new(1,1,1)
|
||||
actionTitle.TextStrokeTransparency = 0
|
||||
actionTitle.FontSize = Enum.FontSize.Size18
|
||||
actionTitle.TextWrapped = true
|
||||
actionTitle.Text = ""
|
||||
if functionInfoTable["title"] and type(functionInfoTable["title"]) == "string" then
|
||||
actionTitle.Text = functionInfoTable["title"]
|
||||
end
|
||||
actionTitle.Parent = contextButton
|
||||
|
||||
return contextButton
|
||||
end
|
||||
|
||||
function createButton( actionName, functionInfoTable )
|
||||
local button = createNewButton(actionName, functionInfoTable)
|
||||
|
||||
local position = nil
|
||||
for i = 1,#buttonVector do
|
||||
if buttonVector[i] == "empty" then
|
||||
position = i
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not position then
|
||||
position = #buttonVector + 1
|
||||
end
|
||||
|
||||
if position > maxButtons then
|
||||
return -- todo: let user know we have too many buttons already?
|
||||
end
|
||||
|
||||
buttonVector[position] = button
|
||||
functionTable[actionName]["button"] = button
|
||||
|
||||
button.Position = buttonPositionTable[position]
|
||||
button.Parent = buttonFrame
|
||||
|
||||
if buttonScreenGui and buttonScreenGui.Parent == nil then
|
||||
buttonScreenGui.Parent = localPlayer.PlayerGui
|
||||
end
|
||||
end
|
||||
|
||||
function removeAction(actionName)
|
||||
if not functionTable[actionName] then return end
|
||||
|
||||
local actionButton = functionTable[actionName]["button"]
|
||||
|
||||
if actionButton then
|
||||
actionButton.Parent = nil
|
||||
|
||||
for i = 1,#buttonVector do
|
||||
if buttonVector[i] == actionButton then
|
||||
buttonVector[i] = "empty"
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
actionButton:Destroy()
|
||||
end
|
||||
|
||||
functionTable[actionName] = nil
|
||||
end
|
||||
|
||||
function addAction(actionName,createTouchButton,functionInfoTable)
|
||||
if functionTable[actionName] then
|
||||
removeAction(actionName)
|
||||
end
|
||||
functionTable[actionName] = {functionInfoTable}
|
||||
if createTouchButton and isTouchDevice then
|
||||
createContextActionGui()
|
||||
createButton(actionName, functionInfoTable)
|
||||
end
|
||||
end
|
||||
|
||||
-- Connections
|
||||
contextActionService.BoundActionChanged:connect( function(actionName, changeName, changeTable)
|
||||
if functionTable[actionName] and changeTable then
|
||||
local button = functionTable[actionName]["button"]
|
||||
if button then
|
||||
if changeName == "image" then
|
||||
button.ActionIcon.Image = changeTable[changeName]
|
||||
elseif changeName == "title" then
|
||||
button.ActionTitle.Text = changeTable[changeName]
|
||||
elseif changeName == "description" then
|
||||
-- todo: add description to menu
|
||||
elseif changeName == "position" then
|
||||
button.Position = changeTable[changeName]
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
contextActionService.BoundActionAdded:connect( function(actionName, createTouchButton, functionInfoTable)
|
||||
addAction(actionName, createTouchButton, functionInfoTable)
|
||||
end)
|
||||
|
||||
contextActionService.BoundActionRemoved:connect( function(actionName, functionInfoTable)
|
||||
removeAction(actionName)
|
||||
end)
|
||||
|
||||
contextActionService.GetActionButtonEvent:connect( function(actionName)
|
||||
if functionTable[actionName] then
|
||||
contextActionService:FireActionButtonFoundSignal(actionName, functionTable[actionName]["button"])
|
||||
end
|
||||
end)
|
||||
|
||||
-- make sure any bound data before we setup connections is handled
|
||||
local boundActions = contextActionService:GetAllBoundActionInfo()
|
||||
for actionName, actionData in pairs(boundActions) do
|
||||
addAction(actionName,actionData["createTouchButton"],actionData)
|
||||
end
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
|
||||
local DeveloperConsoleModule;
|
||||
local function RequireDeveloperConsoleModule()
|
||||
if not DeveloperConsoleModule then
|
||||
DeveloperConsoleModule = require(game:GetService("CoreGui"):WaitForChild('RobloxGui').Modules.DeveloperConsoleModule)
|
||||
end
|
||||
end
|
||||
|
||||
local screenGui = script.Parent:FindFirstChild("ControlFrame") or script.Parent
|
||||
|
||||
local ToggleConsole = Instance.new('BindableFunction')
|
||||
ToggleConsole.Name = 'ToggleDevConsole'
|
||||
ToggleConsole.Parent = screenGui
|
||||
|
||||
local debounce = false
|
||||
|
||||
local developerConsole;
|
||||
function ToggleConsole.OnInvoke(duplicate)
|
||||
if debounce then
|
||||
return
|
||||
end
|
||||
debounce = true
|
||||
RequireDeveloperConsoleModule()
|
||||
if not developerConsole or duplicate == true then
|
||||
local permissions = DeveloperConsoleModule.GetPermissions()
|
||||
local messagesAndStats = DeveloperConsoleModule.GetMessagesAndStats(permissions)
|
||||
developerConsole = DeveloperConsoleModule.new(screenGui, permissions, messagesAndStats)
|
||||
developerConsole:SetVisible(true)
|
||||
else
|
||||
developerConsole:SetVisible(not developerConsole.Visible)
|
||||
end
|
||||
debounce = false
|
||||
end
|
||||
620
client/common/content/scripts/CoreScripts/2016/GamepadMenu.lua
Normal file
620
client/common/content/scripts/CoreScripts/2016/GamepadMenu.lua
Normal file
@@ -0,0 +1,620 @@
|
||||
--[[
|
||||
Filename: GamepadMenu.lua
|
||||
Written by: jeditkacheff
|
||||
Version 1.1
|
||||
Description: Controls the radial menu that appears when pressing menu button on gamepad
|
||||
--]]
|
||||
|
||||
--[[ SERVICES ]]
|
||||
local GuiService = game:GetService('GuiService')
|
||||
local CoreGuiService = game:GetService('CoreGui')
|
||||
local InputService = game:GetService('UserInputService')
|
||||
local ContextActionService = game:GetService('ContextActionService')
|
||||
local HttpService = game:GetService('HttpService')
|
||||
local StarterGui = game:GetService('StarterGui')
|
||||
local GuiRoot = CoreGuiService:WaitForChild('RobloxGui')
|
||||
--[[ END OF SERVICES ]]
|
||||
|
||||
--[[ MODULES ]]
|
||||
local tenFootInterface = require(GuiRoot.Modules.TenFootInterface)
|
||||
local utility = require(GuiRoot.Modules.Utility)
|
||||
|
||||
--[[ VARIABLES ]]
|
||||
local gamepadSettingsFrame = nil
|
||||
local isVisible = false
|
||||
local smallScreen = utility:IsSmallTouchScreen()
|
||||
local isTenFootInterface = tenFootInterface:IsEnabled()
|
||||
local radialButtons = {}
|
||||
local lastInputChangedCon = nil
|
||||
|
||||
local function getButtonForCoreGuiType(coreGuiType)
|
||||
if coreGuiType == Enum.CoreGuiType.All then
|
||||
return radialButtons
|
||||
else
|
||||
for button, table in pairs(radialButtons) do
|
||||
if table["CoreGuiType"] == coreGuiType then
|
||||
return button
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
local function getImagesForSlot(slot)
|
||||
if slot == 1 then return "ayaasset://textures/ui/Settings/Radial/Top.png", "ayaasset://textures/ui/Settings/Radial/TopSelected.png",
|
||||
"ayaasset://textures/ui/Settings/Radial/Menu.png",
|
||||
UDim2.new(0.5,-26,0,18), UDim2.new(0,52,0,41),
|
||||
UDim2.new(0,150,0,100), UDim2.new(0.5,-75,0,0)
|
||||
elseif slot == 2 then return "ayaasset://textures/ui/Settings/Radial/TopRight.png", "ayaasset://textures/ui/Settings/Radial/TopRightSelected.png",
|
||||
"ayaasset://textures/ui/Settings/Radial/PlayerList.png",
|
||||
UDim2.new(1,-90,0,90), UDim2.new(0,52,0,52),
|
||||
UDim2.new(0,108,0,150), UDim2.new(1,-110,0,50)
|
||||
elseif slot == 3 then return "ayaasset://textures/ui/Settings/Radial/BottomRight.png", "ayaasset://textures/ui/Settings/Radial/BottomRightSelected.png",
|
||||
"ayaasset://textures/ui/Settings/Radial/Alert.png",
|
||||
UDim2.new(1,-85,1,-150), UDim2.new(0,42,0,58),
|
||||
UDim2.new(0,120,0,150), UDim2.new(1,-120,1,-200)
|
||||
elseif slot == 4 then return "ayaasset://textures/ui/Settings/Radial/Bottom.png", "ayaasset://textures/ui/Settings/Radial/BottomSelected.png",
|
||||
"ayaasset://textures/ui/Settings/Radial/Leave.png",
|
||||
UDim2.new(0.5,-20,1,-62), UDim2.new(0,55,0,46),
|
||||
UDim2.new(0,150,0,100), UDim2.new(0.5,-75,1,-100)
|
||||
elseif slot == 5 then return "ayaasset://textures/ui/Settings/Radial/BottomLeft.png", "ayaasset://textures/ui/Settings/Radial/BottomLeftSelected.png",
|
||||
"ayaasset://textures/ui/Settings/Radial/Backpack.png",
|
||||
UDim2.new(0,40,1,-150), UDim2.new(0,44,0,56),
|
||||
UDim2.new(0,110,0,150), UDim2.new(0,0,0,205)
|
||||
elseif slot == 6 then return "ayaasset://textures/ui/Settings/Radial/TopLeft.png", "ayaasset://textures/ui/Settings/Radial/TopLeftSelected.png",
|
||||
"ayaasset://textures/ui/Settings/Radial/Chat.png",
|
||||
UDim2.new(0,35,0,100), UDim2.new(0,56,0,53),
|
||||
UDim2.new(0,110,0,150), UDim2.new(0,0,0,50)
|
||||
end
|
||||
|
||||
return "", "", UDim2.new(0,0,0,0), UDim2.new(0,0,0,0)
|
||||
end
|
||||
|
||||
local function setSelectedRadialButton(selectedObject)
|
||||
for button, buttonTable in pairs(radialButtons) do
|
||||
local isVisible = (button == selectedObject)
|
||||
button:FindFirstChild("Selected").Visible = isVisible
|
||||
button:FindFirstChild("RadialLabel").Visible = isVisible
|
||||
end
|
||||
end
|
||||
|
||||
local function activateSelectedRadialButton()
|
||||
for button, buttonTable in pairs(radialButtons) do
|
||||
if button:FindFirstChild("Selected").Visible then
|
||||
buttonTable["Function"]()
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
local function setButtonEnabled(button, enabled)
|
||||
if radialButtons[button]["Disabled"] == not enabled then return end
|
||||
|
||||
if button:FindFirstChild("Selected").Visible == true then
|
||||
setSelectedRadialButton(nil)
|
||||
end
|
||||
|
||||
if enabled then
|
||||
button.Image = string.gsub(button.Image, "ayaasset://textures/ui/Settings/Radial/Empty", "ayaasset://textures/ui/Settings/Radial/")
|
||||
button.ImageTransparency = 0
|
||||
button.RadialIcon.ImageTransparency = 0
|
||||
else
|
||||
button.Image = string.gsub(button.Image, "ayaasset://textures/ui/Settings/Radial/", "ayaasset://textures/ui/Settings/Radial/Empty")
|
||||
button.ImageTransparency = 0
|
||||
button.RadialIcon.ImageTransparency = 1
|
||||
end
|
||||
|
||||
radialButtons[button]["Disabled"] = not enabled
|
||||
end
|
||||
|
||||
local emptySelectedImageObject = utility:Create'ImageLabel'
|
||||
{
|
||||
BackgroundTransparency = 1,
|
||||
Size = UDim2.new(1,0,1,0),
|
||||
Image = ""
|
||||
};
|
||||
|
||||
local function createRadialButton(name, text, slot, disabled, coreGuiType, activateFunc)
|
||||
local slotImage, selectedSlotImage, slotIcon,
|
||||
slotIconPosition, slotIconSize, mouseFrameSize, mouseFramePos = getImagesForSlot(slot)
|
||||
|
||||
local radialButton = utility:Create'ImageButton'
|
||||
{
|
||||
Name = name,
|
||||
Position = UDim2.new(0,0,0,0),
|
||||
Size = UDim2.new(1,0,1,0),
|
||||
BackgroundTransparency = 1,
|
||||
Image = slotImage,
|
||||
ZIndex = 2,
|
||||
SelectionImageObject = emptySelectedImageObject,
|
||||
Parent = gamepadSettingsFrame
|
||||
};
|
||||
if disabled then
|
||||
radialButton.Image = string.gsub(radialButton.Image, "ayaasset://textures/ui/Settings/Radial/", "ayaasset://textures/ui/Settings/Radial/Empty")
|
||||
end
|
||||
|
||||
local selectedRadial = utility:Create'ImageLabel'
|
||||
{
|
||||
Name = "Selected",
|
||||
Position = UDim2.new(0,0,0,0),
|
||||
Size = UDim2.new(1,0,1,0),
|
||||
BackgroundTransparency = 1,
|
||||
Image = selectedSlotImage,
|
||||
ZIndex = 2,
|
||||
Visible = false,
|
||||
Parent = radialButton
|
||||
};
|
||||
|
||||
local radialIcon = utility:Create'ImageLabel'
|
||||
{
|
||||
Name = "RadialIcon",
|
||||
Position = slotIconPosition,
|
||||
Size = slotIconSize,
|
||||
BackgroundTransparency = 1,
|
||||
Image = slotIcon,
|
||||
ZIndex = 3,
|
||||
ImageTransparency = disabled and 1 or 0,
|
||||
Parent = radialButton
|
||||
};
|
||||
|
||||
local nameLabel = utility:Create'TextLabel'
|
||||
{
|
||||
|
||||
Size = UDim2.new(0,220,0,50),
|
||||
Position = UDim2.new(0.5, -110, 0.5, -25),
|
||||
BackgroundTransparency = 1,
|
||||
Text = text,
|
||||
Font = Enum.Font.SourceSansBold,
|
||||
FontSize = Enum.FontSize.Size14,
|
||||
TextColor3 = Color3.new(1,1,1),
|
||||
Name = "RadialLabel",
|
||||
Visible = false,
|
||||
ZIndex = 2,
|
||||
Parent = radialButton
|
||||
};
|
||||
if not smallScreen then
|
||||
nameLabel.FontSize = Enum.FontSize.Size36
|
||||
nameLabel.Size = UDim2.new(nameLabel.Size.X.Scale, nameLabel.Size.X.Offset, nameLabel.Size.Y.Scale, nameLabel.Size.Y.Offset + 4)
|
||||
end
|
||||
local nameBackgroundImage = utility:Create'ImageLabel'
|
||||
{
|
||||
Name = text .. "BackgroundImage",
|
||||
Size = UDim2.new(1,0,1,0),
|
||||
Position = UDim2.new(0,0,0,2),
|
||||
BackgroundTransparency = 1,
|
||||
Image = "ayaasset://textures/ui/Settings/Radial/RadialLabel@2x.png",
|
||||
ScaleType = Enum.ScaleType.Slice,
|
||||
SliceCenter = Rect.new(24,4,130,42),
|
||||
ZIndex = 2,
|
||||
Parent = nameLabel
|
||||
};
|
||||
|
||||
local mouseFrame = utility:Create'ImageButton'
|
||||
{
|
||||
Name = "MouseFrame",
|
||||
Position = mouseFramePos,
|
||||
Size = mouseFrameSize,
|
||||
ZIndex = 3,
|
||||
BackgroundTransparency = 1,
|
||||
SelectionImageObject = emptySelectedImageObject,
|
||||
Parent = radialButton
|
||||
};
|
||||
|
||||
mouseFrame.MouseEnter:connect(function()
|
||||
if not radialButtons[radialButton]["Disabled"] then
|
||||
setSelectedRadialButton(radialButton)
|
||||
end
|
||||
end)
|
||||
mouseFrame.MouseLeave:connect(function()
|
||||
setSelectedRadialButton(nil)
|
||||
end)
|
||||
|
||||
mouseFrame.MouseButton1Click:connect(function()
|
||||
if selectedRadial.Visible then
|
||||
activateFunc()
|
||||
end
|
||||
end)
|
||||
|
||||
radialButtons[radialButton] = {["Function"] = activateFunc, ["Disabled"] = disabled, ["CoreGuiType"] = coreGuiType}
|
||||
|
||||
return radialButton
|
||||
end
|
||||
|
||||
local function createGamepadMenuGui()
|
||||
gamepadSettingsFrame = utility:Create'Frame'
|
||||
{
|
||||
Name = "GamepadSettingsFrame",
|
||||
Position = UDim2.new(0.5,-51,0.5,-51),
|
||||
BackgroundTransparency = 1,
|
||||
BorderSizePixel = 0,
|
||||
Size = UDim2.new(0,102,0,102),
|
||||
Visible = false,
|
||||
Parent = GuiRoot
|
||||
};
|
||||
|
||||
---------------------------------
|
||||
-------- Settings Menu ----------
|
||||
local settingsFunc = function()
|
||||
toggleCoreGuiRadial(true)
|
||||
local MenuModule = require(GuiRoot.Modules.SettingsHub)
|
||||
MenuModule:SetVisibility(true, nil, nil, true)
|
||||
end
|
||||
local settingsRadial = createRadialButton("Settings", "Settings", 1, false, nil, settingsFunc)
|
||||
settingsRadial.Parent = gamepadSettingsFrame
|
||||
|
||||
---------------------------------
|
||||
-------- Player List ------------
|
||||
local playerListFunc = function()
|
||||
toggleCoreGuiRadial(true)
|
||||
local PlayerListModule = require(GuiRoot.Modules.PlayerlistModule)
|
||||
if not PlayerListModule:IsOpen() then
|
||||
PlayerListModule:ToggleVisibility()
|
||||
end
|
||||
end
|
||||
local playerListRadial = createRadialButton("PlayerList", "Player List", 2, not StarterGui:GetCoreGuiEnabled(Enum.CoreGuiType.PlayerList), Enum.CoreGuiType.PlayerList, playerListFunc)
|
||||
playerListRadial.Parent = gamepadSettingsFrame
|
||||
|
||||
---------------------------------
|
||||
-------- Notifications ----------
|
||||
local gamepadNotifications = Instance.new("BindableEvent")
|
||||
gamepadNotifications.Name = "GamepadNotifications"
|
||||
gamepadNotifications.Parent = script
|
||||
local notificationsFunc = function()
|
||||
toggleCoreGuiRadial()
|
||||
gamepadNotifications:Fire(true)
|
||||
end
|
||||
local notificationsRadial = createRadialButton("Notifications", "Notifications", 3, false, nil, notificationsFunc)
|
||||
if isTenFootInterface then
|
||||
setButtonEnabled(notificationsRadial, false)
|
||||
end
|
||||
notificationsRadial.Parent = gamepadSettingsFrame
|
||||
|
||||
---------------------------------
|
||||
---------- Leave Game -----------
|
||||
local leaveGameFunc = function()
|
||||
toggleCoreGuiRadial(true)
|
||||
local MenuModule = require(GuiRoot.Modules.SettingsHub)
|
||||
MenuModule:SetVisibility(true, false, require(GuiRoot.Modules.LeaveGame), true)
|
||||
end
|
||||
local leaveGameRadial = createRadialButton("LeaveGame", "Leave Game", 4, false, nil, leaveGameFunc)
|
||||
leaveGameRadial.Parent = gamepadSettingsFrame
|
||||
|
||||
---------------------------------
|
||||
---------- Backpack -------------
|
||||
local backpackFunc = function()
|
||||
toggleCoreGuiRadial(true)
|
||||
local BackpackModule = require(GuiRoot.Modules.BackpackScript)
|
||||
BackpackModule:OpenClose()
|
||||
end
|
||||
local backpackRadial = createRadialButton("Backpack", "Backpack", 5, not StarterGui:GetCoreGuiEnabled(Enum.CoreGuiType.Backpack), Enum.CoreGuiType.Backpack, backpackFunc)
|
||||
backpackRadial.Parent = gamepadSettingsFrame
|
||||
|
||||
---------------------------------
|
||||
------------ Chat ---------------
|
||||
local chatFunc = function()
|
||||
toggleCoreGuiRadial()
|
||||
local ChatModule = require(GuiRoot.Modules.Chat)
|
||||
ChatModule:ToggleVisibility()
|
||||
end
|
||||
local chatRadial = createRadialButton("Chat", "Chat", 6, not StarterGui:GetCoreGuiEnabled(Enum.CoreGuiType.Chat), Enum.CoreGuiType.Chat, chatFunc)
|
||||
if isTenFootInterface then
|
||||
setButtonEnabled(chatRadial, false)
|
||||
end
|
||||
chatRadial.Parent = gamepadSettingsFrame
|
||||
|
||||
|
||||
---------------------------------
|
||||
--------- Close Button ----------
|
||||
local closeHintImage = utility:Create'ImageLabel'
|
||||
{
|
||||
Name = "CloseHint",
|
||||
Position = UDim2.new(1,10,1,10),
|
||||
Size = UDim2.new(0,60,0,60),
|
||||
BackgroundTransparency = 1,
|
||||
Image = "ayaasset://textures/ui/Settings/Help/BButtonDark.png",
|
||||
Parent = gamepadSettingsFrame
|
||||
}
|
||||
if isTenFootInterface then
|
||||
closeHintImage.Image = "ayaasset://textures/ui/Settings/Help/BButtonDark@2x.png"
|
||||
closeHintImage.Size = UDim2.new(0,90,0,90)
|
||||
end
|
||||
|
||||
local closeHintText = utility:Create'TextLabel'
|
||||
{
|
||||
Name = "closeHintText",
|
||||
Position = UDim2.new(1,10,0.5,-12),
|
||||
Size = UDim2.new(0,43,0,24),
|
||||
Font = Enum.Font.SourceSansBold,
|
||||
FontSize = Enum.FontSize.Size24,
|
||||
BackgroundTransparency = 1,
|
||||
Text = "Back",
|
||||
TextColor3 = Color3.new(1,1,1),
|
||||
TextXAlignment = Enum.TextXAlignment.Left,
|
||||
Parent = closeHintImage
|
||||
}
|
||||
if isTenFootInterface then
|
||||
closeHintText.FontSize = Enum.FontSize.Size36
|
||||
end
|
||||
|
||||
GuiService:AddSelectionParent(HttpService:GenerateGUID(false), gamepadSettingsFrame)
|
||||
|
||||
gamepadSettingsFrame.Changed:connect(function(prop)
|
||||
if prop == "Visible" then
|
||||
if not gamepadSettingsFrame.Visible then
|
||||
unbindAllRadialActions()
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local function isCoreGuiDisabled()
|
||||
for _, enumItem in pairs(Enum.CoreGuiType:GetEnumItems()) do
|
||||
if StarterGui:GetCoreGuiEnabled(enumItem) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local function setupGamepadControls()
|
||||
local freezeControllerActionName = "doNothingAction"
|
||||
local radialSelectActionName = "RadialSelectAction"
|
||||
local thumbstick2RadialActionName = "Thumbstick2RadialAction"
|
||||
local radialCancelActionName = "RadialSelectCancel"
|
||||
local radialAcceptActionName = "RadialSelectAccept"
|
||||
local toggleMenuActionName = "RBXToggleMenuAction"
|
||||
|
||||
local noOpFunc = function() end
|
||||
local doGamepadMenuButton = nil
|
||||
|
||||
function unbindAllRadialActions()
|
||||
local success = pcall(function() GuiService.CoreGuiNavigationEnabled = true end)
|
||||
if not success then
|
||||
GuiService.GuiNavigationEnabled = true
|
||||
end
|
||||
|
||||
ContextActionService:UnbindCoreAction(radialSelectActionName)
|
||||
ContextActionService:UnbindCoreAction(radialCancelActionName)
|
||||
ContextActionService:UnbindCoreAction(radialAcceptActionName)
|
||||
ContextActionService:UnbindCoreAction(freezeControllerActionName)
|
||||
ContextActionService:UnbindCoreAction(thumbstick2RadialActionName)
|
||||
end
|
||||
|
||||
local radialButtonLayout = { PlayerList = {
|
||||
Range = { Begin = 36,
|
||||
End = 96
|
||||
}
|
||||
},
|
||||
Notifications = {
|
||||
Range = { Begin = 96,
|
||||
End = 156
|
||||
}
|
||||
},
|
||||
LeaveGame = {
|
||||
Range = { Begin = 156,
|
||||
End = 216
|
||||
}
|
||||
},
|
||||
Backpack = {
|
||||
Range = { Begin = 216,
|
||||
End = 276
|
||||
}
|
||||
},
|
||||
Chat = {
|
||||
Range = { Begin = 276,
|
||||
End = 336
|
||||
}
|
||||
},
|
||||
Settings = {
|
||||
Range = { Begin = 336,
|
||||
End = 36
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
local function getSelectedObjectFromAngle(angle, depth)
|
||||
local closest = nil
|
||||
local closestDistance = 30 -- threshold of 30 for selecting the closest radial button
|
||||
for radialKey, buttonLayout in pairs(radialButtonLayout) do
|
||||
if radialButtons[gamepadSettingsFrame[radialKey]]["Disabled"] == false then
|
||||
--Check for exact match
|
||||
if buttonLayout.Range.Begin < buttonLayout.Range.End then
|
||||
if angle > buttonLayout.Range.Begin and angle <= buttonLayout.Range.End then
|
||||
return gamepadSettingsFrame[radialKey]
|
||||
end
|
||||
else
|
||||
if angle > buttonLayout.Range.Begin or angle <= buttonLayout.Range.End then
|
||||
return gamepadSettingsFrame[radialKey]
|
||||
end
|
||||
end
|
||||
--Check if this is the closest button so far
|
||||
local distanceBegin = math.min(math.abs((buttonLayout.Range.Begin + 360) - angle), math.abs(buttonLayout.Range.Begin - angle))
|
||||
local distanceEnd = math.min(math.abs((buttonLayout.Range.End + 360) - angle), math.abs(buttonLayout.Range.End - angle))
|
||||
local distance = math.min(distanceBegin, distanceEnd)
|
||||
if distance < closestDistance then
|
||||
closestDistance = distance
|
||||
closest = gamepadSettingsFrame[radialKey]
|
||||
end
|
||||
end
|
||||
end
|
||||
return closest
|
||||
end
|
||||
|
||||
local radialSelect = function(name, state, input)
|
||||
local inputVector = Vector2.new(0,0)
|
||||
|
||||
if input.KeyCode == Enum.KeyCode.Thumbstick1 then
|
||||
inputVector = Vector2.new(input.Position.x, input.Position.y)
|
||||
end
|
||||
|
||||
local selectedObject = nil
|
||||
|
||||
if inputVector.magnitude > 0.8 then
|
||||
|
||||
local angle = math.atan2(inputVector.X, inputVector.Y) * 180 / math.pi
|
||||
if angle < 0 then
|
||||
angle = angle + 360
|
||||
end
|
||||
|
||||
selectedObject = getSelectedObjectFromAngle(angle)
|
||||
|
||||
setSelectedRadialButton(selectedObject)
|
||||
end
|
||||
end
|
||||
|
||||
local radialSelectAccept = function(name, state, input)
|
||||
if gamepadSettingsFrame.Visible and state == Enum.UserInputState.Begin then
|
||||
activateSelectedRadialButton()
|
||||
end
|
||||
end
|
||||
|
||||
local radialSelectCancel = function(name, state, input)
|
||||
if gamepadSettingsFrame.Visible and state == Enum.UserInputState.Begin then
|
||||
toggleCoreGuiRadial()
|
||||
end
|
||||
end
|
||||
|
||||
function setVisibility()
|
||||
local children = gamepadSettingsFrame:GetChildren()
|
||||
for i = 1, #children do
|
||||
if children[i]:FindFirstChild("RadialIcon") then
|
||||
children[i].RadialIcon.Visible = isVisible
|
||||
end
|
||||
if children[i]:FindFirstChild("RadialLabel") and not isVisible then
|
||||
children[i].RadialLabel.Visible = isVisible
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function setOverrideMouseIconBehavior()
|
||||
pcall(function()
|
||||
if InputService:GetLastInputType() == Enum.UserInputType.Gamepad1 then
|
||||
InputService.OverrideMouseIconBehavior = Enum.OverrideMouseIconBehavior.ForceHide
|
||||
else
|
||||
InputService.OverrideMouseIconBehavior = Enum.OverrideMouseIconBehavior.ForceShow
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function toggleCoreGuiRadial(goingToSettings)
|
||||
isVisible = not gamepadSettingsFrame.Visible
|
||||
|
||||
setVisibility()
|
||||
|
||||
if isVisible then
|
||||
setOverrideMouseIconBehavior()
|
||||
pcall(function() lastInputChangedCon = InputService.LastInputTypeChanged:connect(setOverrideMouseIconBehavior) end)
|
||||
|
||||
gamepadSettingsFrame.Visible = isVisible
|
||||
|
||||
local settingsChildren = gamepadSettingsFrame:GetChildren()
|
||||
for i = 1, #settingsChildren do
|
||||
if settingsChildren[i]:IsA("GuiButton") then
|
||||
utility:TweenProperty(settingsChildren[i], "ImageTransparency", 1, 0, 0.1, utility:GetEaseOutQuad(), nil)
|
||||
end
|
||||
end
|
||||
gamepadSettingsFrame:TweenSizeAndPosition(UDim2.new(0,408,0,408), UDim2.new(0.5,-204,0.5,-204),
|
||||
Enum.EasingDirection.Out, Enum.EasingStyle.Back, 0.18, true,
|
||||
function()
|
||||
setVisibility()
|
||||
end)
|
||||
else
|
||||
if lastInputChangedCon ~= nil then
|
||||
lastInputChangedCon:disconnect()
|
||||
lastInputChangedCon = nil
|
||||
end
|
||||
pcall(function() InputService.OverrideMouseIconBehavior = Enum.OverrideMouseIconBehavior.None end)
|
||||
|
||||
local settingsChildren = gamepadSettingsFrame:GetChildren()
|
||||
for i = 1, #settingsChildren do
|
||||
if settingsChildren[i]:IsA("GuiButton") then
|
||||
utility:TweenProperty(settingsChildren[i], "ImageTransparency", 0, 1, 0.1, utility:GetEaseOutQuad(), nil)
|
||||
end
|
||||
end
|
||||
gamepadSettingsFrame:TweenSizeAndPosition(UDim2.new(0,102,0,102), UDim2.new(0.5,-51,0.5,-51),
|
||||
Enum.EasingDirection.Out, Enum.EasingStyle.Sine, 0.1, true,
|
||||
function()
|
||||
if not goingToSettings and not isVisible then GuiService:SetMenuIsOpen(false) end
|
||||
gamepadSettingsFrame.Visible = isVisible
|
||||
end)
|
||||
end
|
||||
|
||||
if isVisible then
|
||||
setSelectedRadialButton(nil)
|
||||
|
||||
local success = pcall(function() GuiService.CoreGuiNavigationEnabled = false end)
|
||||
if not success then
|
||||
GuiService.GuiNavigationEnabled = false
|
||||
end
|
||||
|
||||
GuiService:SetMenuIsOpen(true)
|
||||
|
||||
ContextActionService:BindCoreAction(freezeControllerActionName, noOpFunc, false, Enum.UserInputType.Gamepad1)
|
||||
ContextActionService:BindCoreAction(radialAcceptActionName, radialSelectAccept, false, Enum.KeyCode.ButtonA)
|
||||
ContextActionService:BindCoreAction(radialCancelActionName, radialSelectCancel, false, Enum.KeyCode.ButtonB)
|
||||
ContextActionService:BindCoreAction(radialSelectActionName, radialSelect, false, Enum.KeyCode.Thumbstick1)
|
||||
ContextActionService:BindCoreAction(thumbstick2RadialActionName, noOpFunc, false, Enum.KeyCode.Thumbstick2)
|
||||
ContextActionService:BindCoreAction(toggleMenuActionName, doGamepadMenuButton, false, Enum.KeyCode.ButtonStart)
|
||||
else
|
||||
unbindAllRadialActions()
|
||||
end
|
||||
|
||||
return gamepadSettingsFrame.Visible
|
||||
end
|
||||
|
||||
doGamepadMenuButton = function(name, state, input)
|
||||
if state ~= Enum.UserInputState.Begin then return end
|
||||
|
||||
if not toggleCoreGuiRadial() then
|
||||
unbindAllRadialActions()
|
||||
end
|
||||
end
|
||||
|
||||
if InputService:GetGamepadConnected(Enum.UserInputType.Gamepad1) then
|
||||
createGamepadMenuGui()
|
||||
else
|
||||
InputService.GamepadConnected:connect(function(gamepadEnum)
|
||||
if gamepadEnum == Enum.UserInputType.Gamepad1 then
|
||||
createGamepadMenuGui()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local function setRadialButtonEnabled(coreGuiType, enabled)
|
||||
local returnValue = getButtonForCoreGuiType(coreGuiType)
|
||||
if not returnValue then return end
|
||||
|
||||
local buttonsToDisable = {}
|
||||
if type(returnValue) == "table" then
|
||||
for button, buttonTable in pairs(returnValue) do
|
||||
if buttonTable["CoreGuiType"] then
|
||||
if isTenFootInterface and buttonTable["CoreGuiType"] == Enum.CoreGuiType.Chat then
|
||||
else
|
||||
buttonsToDisable[#buttonsToDisable + 1] = button
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if isTenFootInterface and returnValue.Name == "Chat" then
|
||||
else
|
||||
buttonsToDisable[1] = returnValue
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, #buttonsToDisable do
|
||||
local button = buttonsToDisable[i]
|
||||
setButtonEnabled(button, enabled)
|
||||
end
|
||||
end
|
||||
StarterGui.CoreGuiChangedSignal:connect(setRadialButtonEnabled)
|
||||
|
||||
ContextActionService:BindCoreAction(toggleMenuActionName, doGamepadMenuButton, false, Enum.KeyCode.ButtonStart)
|
||||
end
|
||||
|
||||
-- hook up gamepad stuff
|
||||
setupGamepadControls()
|
||||
611
client/common/content/scripts/CoreScripts/2016/HealthScript.lua
Normal file
611
client/common/content/scripts/CoreScripts/2016/HealthScript.lua
Normal file
@@ -0,0 +1,611 @@
|
||||
--[[
|
||||
This script controls the gui the player sees in regards to his or her health.
|
||||
Can be turned with Game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Health,false)
|
||||
--]]
|
||||
|
||||
---------------------------------------------------------------------
|
||||
-- Initialize/Variables
|
||||
while not game do
|
||||
wait(1/60)
|
||||
end
|
||||
while not game:GetService("Players") do
|
||||
wait(1/60)
|
||||
end
|
||||
|
||||
local GameSettings = UserSettings().GameSettings
|
||||
|
||||
local currentHumanoid = nil
|
||||
|
||||
local LegacyHealthGui = nil
|
||||
local lastHealth = 100
|
||||
local lastHealth2 = 100
|
||||
local maxWidth = 0.96
|
||||
|
||||
local HealthGui = nil
|
||||
local lastHealth = 100
|
||||
local HealthPercentageForOverlay = 5
|
||||
local maxBarTweenTime = 0.3
|
||||
local greenColor = Color3.new(0.2, 1, 0.2)
|
||||
local redColor = Color3.new(1, 0.2, 0.2)
|
||||
local yellowColor = Color3.new(1, 1, 0.2)
|
||||
|
||||
local guiEnabled = false
|
||||
local healthChangedConnection = nil
|
||||
local humanoidDiedConnection = nil
|
||||
local characterAddedConnection = nil
|
||||
|
||||
local greenBarImage = "ayaasset://textures/ui/Health-BKG-Center.png"
|
||||
local greenBarImageLeft = "ayaasset://textures/ui/Health-BKG-Left-Cap.png"
|
||||
local greenBarImageRight = "ayaasset://textures/ui/Health-BKG-Right-Cap.png"
|
||||
local hurtOverlayImage = "ayaasset://textures/2015/HealthScript/hurtOverlayImage.png"
|
||||
|
||||
game:GetService("ContentProvider"):Preload(greenBarImage)
|
||||
game:GetService("ContentProvider"):Preload(hurtOverlayImage)
|
||||
|
||||
while not game:GetService("Players").LocalPlayer do
|
||||
wait(1/60)
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------
|
||||
-- Functions
|
||||
|
||||
local capHeight = 15
|
||||
local capWidth = 7
|
||||
|
||||
function CreateGui()
|
||||
if HealthGui and #HealthGui:GetChildren() > 0 then
|
||||
HealthGui.Parent = game:GetService("CoreGui").RobloxGui
|
||||
return
|
||||
end
|
||||
|
||||
local hurtOverlay = Instance.new("ImageLabel")
|
||||
hurtOverlay.Name = "HurtOverlay"
|
||||
hurtOverlay.BackgroundTransparency = 1
|
||||
hurtOverlay.Image = hurtOverlayImage
|
||||
hurtOverlay.Position = UDim2.new(-10,0,-10,0)
|
||||
hurtOverlay.Size = UDim2.new(20,0,20,0)
|
||||
hurtOverlay.Visible = false
|
||||
hurtOverlay.Parent = HealthGui
|
||||
|
||||
local healthFrame = Instance.new("Frame")
|
||||
healthFrame.Name = "HealthFrame"
|
||||
healthFrame.BackgroundTransparency = 1
|
||||
healthFrame.BackgroundColor3 = Color3.new(1,1,1)
|
||||
healthFrame.BorderColor3 = Color3.new(0,0,0)
|
||||
healthFrame.BorderSizePixel = 0
|
||||
healthFrame.Position = UDim2.new(0.5,-85,1,-20)
|
||||
healthFrame.Size = UDim2.new(0,170,0,capHeight)
|
||||
healthFrame.Parent = HealthGui
|
||||
|
||||
local healthBarBackCenter = Instance.new("ImageLabel")
|
||||
healthBarBackCenter.Name = "healthBarBackCenter"
|
||||
healthBarBackCenter.BackgroundTransparency = 1
|
||||
healthBarBackCenter.Image = greenBarImage
|
||||
healthBarBackCenter.Size = UDim2.new(1,-capWidth*2,1,0)
|
||||
healthBarBackCenter.Position = UDim2.new(0,capWidth,0,0)
|
||||
healthBarBackCenter.Parent = healthFrame
|
||||
healthBarBackCenter.ImageColor3 = Color3.new(1,1,1)
|
||||
|
||||
local healthBarBackLeft = Instance.new("ImageLabel")
|
||||
healthBarBackLeft.Name = "healthBarBackLeft"
|
||||
healthBarBackLeft.BackgroundTransparency = 1
|
||||
healthBarBackLeft.Image = greenBarImageLeft
|
||||
healthBarBackLeft.Size = UDim2.new(0,capWidth,1,0)
|
||||
healthBarBackLeft.Position = UDim2.new(0,0,0,0)
|
||||
healthBarBackLeft.Parent = healthFrame
|
||||
healthBarBackLeft.ImageColor3 = Color3.new(1,1,1)
|
||||
|
||||
local healthBarBackRight = Instance.new("ImageLabel")
|
||||
healthBarBackRight.Name = "healthBarBackRight"
|
||||
healthBarBackRight.BackgroundTransparency = 1
|
||||
healthBarBackRight.Image = greenBarImageRight
|
||||
healthBarBackRight.Size = UDim2.new(0,capWidth,1,0)
|
||||
healthBarBackRight.Position = UDim2.new(1,-capWidth,0,0)
|
||||
healthBarBackRight.Parent = healthFrame
|
||||
healthBarBackRight.ImageColor3 = Color3.new(1,1,1)
|
||||
|
||||
|
||||
local healthBar = Instance.new("Frame")
|
||||
healthBar.Name = "HealthBar"
|
||||
healthBar.BackgroundTransparency = 1
|
||||
healthBar.BackgroundColor3 = Color3.new(1,1,1)
|
||||
healthBar.BorderColor3 = Color3.new(0,0,0)
|
||||
healthBar.BorderSizePixel = 0
|
||||
healthBar.ClipsDescendants = true
|
||||
healthBar.Position = UDim2.new(0, 0, 0, 0)
|
||||
healthBar.Size = UDim2.new(1,0,1,0)
|
||||
healthBar.Parent = healthFrame
|
||||
|
||||
|
||||
local healthBarCenter = Instance.new("ImageLabel")
|
||||
healthBarCenter.Name = "healthBarCenter"
|
||||
healthBarCenter.BackgroundTransparency = 1
|
||||
healthBarCenter.Image = greenBarImage
|
||||
healthBarCenter.Size = UDim2.new(1,-capWidth*2,1,0)
|
||||
healthBarCenter.Position = UDim2.new(0,capWidth,0,0)
|
||||
healthBarCenter.Parent = healthBar
|
||||
healthBarCenter.ImageColor3 = greenColor
|
||||
|
||||
local healthBarLeft = Instance.new("ImageLabel")
|
||||
healthBarLeft.Name = "healthBarLeft"
|
||||
healthBarLeft.BackgroundTransparency = 1
|
||||
healthBarLeft.Image = greenBarImageLeft
|
||||
healthBarLeft.Size = UDim2.new(0,capWidth,1,0)
|
||||
healthBarLeft.Position = UDim2.new(0,0,0,0)
|
||||
healthBarLeft.Parent = healthBar
|
||||
healthBarLeft.ImageColor3 = greenColor
|
||||
|
||||
local healthBarRight = Instance.new("ImageLabel")
|
||||
healthBarRight.Name = "healthBarRight"
|
||||
healthBarRight.BackgroundTransparency = 1
|
||||
healthBarRight.Image = greenBarImageRight
|
||||
healthBarRight.Size = UDim2.new(0,capWidth,1,0)
|
||||
healthBarRight.Position = UDim2.new(1,-capWidth,0,0)
|
||||
healthBarRight.Parent = healthBar
|
||||
healthBarRight.ImageColor3 = greenColor
|
||||
|
||||
HealthGui.Parent = game:GetService("CoreGui").RobloxGui
|
||||
end
|
||||
|
||||
function UpdateGui(health)
|
||||
if not HealthGui then return end
|
||||
|
||||
local healthFrame = HealthGui:FindFirstChild("HealthFrame")
|
||||
if not healthFrame then return end
|
||||
|
||||
local healthBar = healthFrame:FindFirstChild("HealthBar")
|
||||
if not healthBar then return end
|
||||
|
||||
-- If more than 1/4 health, bar = green. Else, bar = red.
|
||||
local percentHealth = (health/currentHumanoid.MaxHealth)
|
||||
if percentHealth ~= percentHealth then
|
||||
percentHealth = 1
|
||||
healthBar.healthBarCenter.ImageColor3 = yellowColor
|
||||
healthBar.healthBarRight.ImageColor3 = yellowColor
|
||||
healthBar.healthBarLeft.ImageColor3 = yellowColor
|
||||
elseif percentHealth > 0.25 then
|
||||
healthBar.healthBarCenter.ImageColor3 = greenColor
|
||||
healthBar.healthBarRight.ImageColor3 = greenColor
|
||||
healthBar.healthBarLeft.ImageColor3 = greenColor
|
||||
else
|
||||
healthBar.healthBarCenter.ImageColor3 = redColor
|
||||
healthBar.healthBarRight.ImageColor3 = redColor
|
||||
healthBar.healthBarLeft.ImageColor3 = redColor
|
||||
end
|
||||
|
||||
local width = (health / currentHumanoid.MaxHealth)
|
||||
width = math.max(math.min(width,1),0) -- make sure width is between 0 and 1
|
||||
if width ~= width then width = 1 end
|
||||
|
||||
local healthDelta = lastHealth - health
|
||||
lastHealth = health
|
||||
|
||||
local percentOfTotalHealth = math.abs(healthDelta/currentHumanoid.MaxHealth)
|
||||
percentOfTotalHealth = math.max(math.min(percentOfTotalHealth,1),0) -- make sure percentOfTotalHealth is between 0 and 1
|
||||
if percentOfTotalHealth ~= percentOfTotalHealth then percentOfTotalHealth = 1 end
|
||||
|
||||
local newHealthSize = UDim2.new(width,0,1,0)
|
||||
|
||||
healthBar.Size = newHealthSize
|
||||
|
||||
local sizeX = healthBar.AbsoluteSize.X
|
||||
if sizeX < capWidth then
|
||||
healthBar.healthBarCenter.Visible = false
|
||||
healthBar.healthBarRight.Visible = false
|
||||
elseif sizeX < (2*capWidth + 1) then
|
||||
healthBar.healthBarCenter.Visible = true
|
||||
healthBar.healthBarCenter.Size = UDim2.new(0,sizeX - capWidth,1,0)
|
||||
healthBar.healthBarRight.Visible = false
|
||||
else
|
||||
healthBar.healthBarCenter.Visible = true
|
||||
healthBar.healthBarCenter.Size = UDim2.new(1,-capWidth*2,1,0)
|
||||
healthBar.healthBarRight.Visible = true
|
||||
end
|
||||
|
||||
local thresholdForHurtOverlay = currentHumanoid.MaxHealth * (HealthPercentageForOverlay/100)
|
||||
|
||||
if healthDelta >= thresholdForHurtOverlay and guiEnabled then
|
||||
AnimateHurtOverlay()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function AnimateHurtOverlay()
|
||||
if not HealthGui then return end
|
||||
|
||||
local overlay = HealthGui:FindFirstChild("HurtOverlay")
|
||||
if not overlay then return end
|
||||
|
||||
local newSize = UDim2.new(20, 0, 20, 0)
|
||||
local newPos = UDim2.new(-10, 0, -10, 0)
|
||||
|
||||
if overlay:IsDescendantOf(game) then
|
||||
-- stop any tweens on overlay
|
||||
overlay:TweenSizeAndPosition(newSize,newPos,Enum.EasingDirection.Out,Enum.EasingStyle.Linear,0,true,function()
|
||||
|
||||
-- show the gui
|
||||
overlay.Size = UDim2.new(1,0,1,0)
|
||||
overlay.Position = UDim2.new(0,0,0,0)
|
||||
overlay.Visible = true
|
||||
|
||||
-- now tween the hide
|
||||
if overlay:IsDescendantOf(game) then
|
||||
overlay:TweenSizeAndPosition(newSize,newPos,Enum.EasingDirection.Out,Enum.EasingStyle.Quad,10,false,function()
|
||||
overlay.Visible = false
|
||||
end)
|
||||
else
|
||||
overlay.Size = newSize
|
||||
overlay.Position = newPos
|
||||
end
|
||||
end)
|
||||
else
|
||||
overlay.Size = newSize
|
||||
overlay.Position = newPos
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function humanoidDied()
|
||||
UpdateGui(0)
|
||||
end
|
||||
|
||||
function disconnectPlayerConnections()
|
||||
if characterAddedConnection then characterAddedConnection:disconnect() end
|
||||
if humanoidDiedConnection then humanoidDiedConnection:disconnect() end
|
||||
if healthChangedConnection then healthChangedConnection:disconnect() end
|
||||
end
|
||||
|
||||
function newPlayerCharacter()
|
||||
disconnectPlayerConnections()
|
||||
|
||||
local version = GameSettings.VirtualVersion
|
||||
if version == Enum.VirtualVersion['2016'] or version == Enum.VirtualVersion['2015'] or version == Enum.VirtualVersion['2014'] then
|
||||
startGui()
|
||||
else
|
||||
startGuiLegacy()
|
||||
end
|
||||
end
|
||||
|
||||
function startGui()
|
||||
characterAddedConnection = game:GetService("Players").LocalPlayer.CharacterAdded:connect(newPlayerCharacter)
|
||||
|
||||
local character = game:GetService("Players").LocalPlayer.Character
|
||||
if not character then
|
||||
return
|
||||
end
|
||||
|
||||
currentHumanoid = character:WaitForChild("Humanoid")
|
||||
if not currentHumanoid then
|
||||
return
|
||||
end
|
||||
|
||||
if not game:GetService("StarterGui"):GetCoreGuiEnabled(Enum.CoreGuiType.Health) then
|
||||
return
|
||||
end
|
||||
|
||||
healthChangedConnection = currentHumanoid.HealthChanged:connect(UpdateGui)
|
||||
humanoidDiedConnection = currentHumanoid.Died:connect(humanoidDied)
|
||||
|
||||
UpdateGui(currentHumanoid.Health)
|
||||
|
||||
CreateGui()
|
||||
end
|
||||
|
||||
function CreateGuiLegacy()
|
||||
if LegacyHealthGui then LegacyHealthGui:Destroy() end
|
||||
|
||||
local tray = Instance.new("Frame")
|
||||
tray.Name = "HealthGui"
|
||||
tray.BackgroundColor3 = Color3.fromRGB(107, 50, 124)
|
||||
tray.BackgroundTransparency = 1
|
||||
tray.BorderColor3 = Color3.fromRGB(27, 42, 53)
|
||||
tray.BorderSizePixel = 1
|
||||
tray.Position = UDim2.new(0.5, -44, 1, -26)
|
||||
tray.Size = UDim2.new(0, 170, 0, 18)
|
||||
tray.SizeConstraint = Enum.SizeConstraint.RelativeYY
|
||||
tray.Visible = true
|
||||
tray.archivable = true
|
||||
tray.ZIndex = 1
|
||||
|
||||
local bkg = Instance.new("ImageLabel")
|
||||
bkg.Name = "bkg"
|
||||
bkg.Active = false
|
||||
bkg.BackgroundTransparency = 1
|
||||
bkg.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
|
||||
bkg.BorderColor3 = Color3.fromRGB(27, 42, 53)
|
||||
bkg.BorderSizePixel = 1
|
||||
bkg.Position = UDim2.new(0, 0, 0, 0)
|
||||
bkg.Image = "ayaasset://textures/ui/healthBarBkg.png"
|
||||
bkg.Size = UDim2.new(1, 0, 1, 0)
|
||||
bkg.SizeConstraint = Enum.SizeConstraint.RelativeXY
|
||||
bkg.Visible = true
|
||||
bkg.archivable = true
|
||||
bkg.ZIndex = 1
|
||||
bkg.Parent = tray
|
||||
|
||||
local bar2 = Instance.new("Frame")
|
||||
bar2.Name = "bar2"
|
||||
bar2.Active = false
|
||||
bar2.BackgroundTransparency = 1
|
||||
bar2.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
|
||||
bar2.BorderColor3 = Color3.fromRGB(27, 42, 53)
|
||||
bar2.BorderSizePixel = 0
|
||||
bar2.Position = UDim2.new(0.0189999994, 0, 0.100000001, 0)
|
||||
bar2.Size = UDim2.new(0.192000002, 0, 0.829999983, 0)
|
||||
bar2.SizeConstraint = Enum.SizeConstraint.RelativeXY
|
||||
bar2.Visible = true
|
||||
bar2.archivable = true
|
||||
bar2.ZIndex = 1
|
||||
bar2.Parent = tray
|
||||
|
||||
local bar = Instance.new("ImageLabel")
|
||||
bar.Name = "bar"
|
||||
bar.Active = false
|
||||
bar.BackgroundTransparency = 1
|
||||
bar.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
|
||||
bar.BorderColor3 = Color3.fromRGB(27, 42, 53)
|
||||
bar.BorderSizePixel = 1
|
||||
bar.Position = UDim2.new(0.0189999994, 0, 0.100000001, 0)
|
||||
bar.Image = "ayaasset://textures/ui/healthBarGreen.png"
|
||||
bar.Size = UDim2.new(0.959999979, 0, 0.829999983, 0)
|
||||
bar.SizeConstraint = Enum.SizeConstraint.RelativeXY
|
||||
bar.Visible = true
|
||||
bar.archivable = true
|
||||
bar.ZIndex = 1
|
||||
bar.Parent = tray
|
||||
|
||||
local label = Instance.new("ImageLabel")
|
||||
label.Name = "label"
|
||||
label.Active = false
|
||||
label.BackgroundTransparency = 1
|
||||
label.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
|
||||
label.BorderColor3 = Color3.fromRGB(27, 42, 53)
|
||||
label.BorderSizePixel = 0
|
||||
label.Position = UDim2.new(0.680000007, 0, 0.300000012, 0)
|
||||
label.Size = UDim2.new(0.25, 0, 0.349999994, 0)
|
||||
label.SizeConstraint = Enum.SizeConstraint.RelativeXY
|
||||
label.Visible = true
|
||||
label.archivable = true
|
||||
label.ZIndex = 1
|
||||
label.Parent = tray
|
||||
label.Image = "ayaasset://textures/ui/healthLabel.png"
|
||||
|
||||
local barRed = Instance.new("ImageLabel")
|
||||
barRed.Name = "barRed"
|
||||
barRed.Active = false
|
||||
barRed.BackgroundTransparency = 1
|
||||
barRed.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
|
||||
barRed.BorderColor3 = Color3.fromRGB(27, 42, 53)
|
||||
barRed.BorderSizePixel = 1
|
||||
barRed.Position = UDim2.new(0.0189999994, 0, 0.100000001, 0)
|
||||
barRed.Image = "ayaasset://textures/ui/healthBarRed.png"
|
||||
barRed.Size = UDim2.new(0, 0, 0, 0)
|
||||
barRed.SizeConstraint = Enum.SizeConstraint.RelativeXY
|
||||
barRed.Visible = true
|
||||
barRed.archivable = true
|
||||
barRed.ZIndex = 1
|
||||
barRed.Parent = tray
|
||||
|
||||
local hurtOverlay = Instance.new("ImageLabel")
|
||||
hurtOverlay.Name = "HurtOverlay"
|
||||
hurtOverlay.BackgroundTransparency = 1
|
||||
hurtOverlay.Image = "ayaasset://textures/ui/legacyHurtOverlay.png"
|
||||
hurtOverlay.Position = UDim2.new(10, 0, 0, 0)
|
||||
hurtOverlay.Size = UDim2.new(1, 0, 1.15, 30)
|
||||
hurtOverlay.Visible = false
|
||||
hurtOverlay.Parent = tray
|
||||
|
||||
LegacyHealthGui = tray
|
||||
LegacyHealthGui.Parent = game:GetService("CoreGui").RobloxGui
|
||||
end
|
||||
|
||||
function UpdateGUILegacy(health)
|
||||
local tray = LegacyHealthGui
|
||||
local width = (health / currentHumanoid.MaxHealth) * maxWidth
|
||||
local height = 0.83
|
||||
local lastX = tray.bar.Position.X.Scale
|
||||
local x = 0.019 + (maxWidth - width)
|
||||
local y = 0.1
|
||||
|
||||
tray.bar.Position = UDim2.new(x,0,y, 0)
|
||||
tray.bar.Size = UDim2.new(width, 0, height, 0)
|
||||
-- If more than 1/4 health, bar = green. Else, bar = red.
|
||||
if( (health / currentHumanoid.MaxHealth) > 0.25 ) then
|
||||
tray.barRed.Size = UDim2.new(0, 0, 0, 0)
|
||||
else
|
||||
tray.barRed.Position = tray.bar.Position
|
||||
tray.barRed.Size = tray.bar.Size
|
||||
tray.bar.Size = UDim2.new(0, 0, 0, 0)
|
||||
end
|
||||
|
||||
if ( (lastHealth - health) > (currentHumanoid.MaxHealth / 10) ) then
|
||||
lastHealth = health
|
||||
|
||||
if currentHumanoid.Health ~= currentHumanoid.MaxHealth then
|
||||
delay(0,function()
|
||||
AnimateHurtOverlay()
|
||||
end)
|
||||
delay(0,function()
|
||||
AnimateBarsLegacy(x, y, lastX, height)
|
||||
end)
|
||||
end
|
||||
else
|
||||
lastHealth = health
|
||||
end
|
||||
end
|
||||
|
||||
function AnimateHurtOverlay()
|
||||
-- Start:
|
||||
-- overlay.Position = UDim2.new(0, 0, 0, -22)
|
||||
-- overlay.Size = UDim2.new(1, 0, 1.15, 30)
|
||||
|
||||
-- Finish:
|
||||
-- overlay.Position = UDim2.new(-2, 0, -2, -22)
|
||||
-- overlay.Size = UDim2.new(4.5, 0, 4.65, 30)
|
||||
|
||||
overlay = LegacyHealthGui.HurtOverlay
|
||||
overlay.Position = UDim2.new(-2, 0, -2, -22)
|
||||
overlay.Size = UDim2.new(4.5, 0, 4.65, 30)
|
||||
-- Animate In, fast
|
||||
local i_total = 2
|
||||
local wiggle_total = 0
|
||||
local wiggle_i = 0.02
|
||||
for i=1,i_total do
|
||||
overlay.Position = UDim2.new( (-2 + (2 * (i/i_total)) + wiggle_total/2), 0, (-2 + (2 * (i/i_total)) + wiggle_total/2), -22 )
|
||||
overlay.Size = UDim2.new( (4.5 - (3.5 * (i/i_total)) + wiggle_total), 0, (4.65 - (3.5 * (i/i_total)) + wiggle_total), 30 )
|
||||
wait(0.01)
|
||||
end
|
||||
|
||||
i_total = 30
|
||||
|
||||
wait(0.03)
|
||||
|
||||
-- Animate Out, slow
|
||||
for i=1,i_total do
|
||||
if( math.abs(wiggle_total) > (wiggle_i * 3) ) then
|
||||
wiggle_i = -wiggle_i
|
||||
end
|
||||
wiggle_total = wiggle_total + wiggle_i
|
||||
overlay.Position = UDim2.new( (0 - (2 * (i/i_total)) + wiggle_total/2), 0, (0 - (2 * (i/i_total)) + wiggle_total/2), -22 )
|
||||
overlay.Size = UDim2.new( (1 + (3.5 * (i/i_total)) + wiggle_total), 0, (1.15 + (3.5 * (i/i_total)) + wiggle_total), 30 )
|
||||
wait(0.01)
|
||||
end
|
||||
|
||||
-- Hide after we're done
|
||||
overlay.Position = UDim2.new(10, 0, 0, 0)
|
||||
end
|
||||
|
||||
function AnimateBarsLegacy(x, y, lastX, height)
|
||||
local tray = LegacyHealthGui
|
||||
local width = math.abs(x - lastX)
|
||||
if( x > lastX ) then
|
||||
x = lastX
|
||||
end
|
||||
tray.bar2.Position = UDim2.new(x,0, y, 0)
|
||||
tray.bar2.Size = UDim2.new(width, 0, height, 0)
|
||||
tray.bar2.BackgroundTransparency = 0
|
||||
local GBchannels = 1
|
||||
local j = 0.2
|
||||
|
||||
local i_total = 30
|
||||
for i=1,i_total do
|
||||
-- Increment Values
|
||||
if (GBchannels < 0.2) then
|
||||
j = -j
|
||||
end
|
||||
GBchannels = GBchannels + j
|
||||
if (i > (i_total - 10)) then
|
||||
tray.bar2.BackgroundTransparency = tray.bar2.BackgroundTransparency + 0.1
|
||||
end
|
||||
tray.bar2.BackgroundColor3 = Color3.new(1, GBchannels, GBchannels)
|
||||
|
||||
wait(0.02)
|
||||
end
|
||||
end
|
||||
|
||||
function HealthChangedLegacy(health)
|
||||
UpdateGUILegacy(health)
|
||||
if ( (lastHealth2 - health) > (currentHumanoid.MaxHealth / 10) ) then
|
||||
lastHealth2 = health
|
||||
else
|
||||
lastHealth2 = health
|
||||
end
|
||||
end
|
||||
|
||||
function startGuiLegacy()
|
||||
characterAddedConnection = game:GetService("Players").LocalPlayer.CharacterAdded:connect(newPlayerCharacter)
|
||||
|
||||
local character = game:GetService("Players").LocalPlayer.Character
|
||||
if not character then
|
||||
return
|
||||
end
|
||||
|
||||
currentHumanoid = character:WaitForChild("Humanoid")
|
||||
if not currentHumanoid then
|
||||
return
|
||||
end
|
||||
|
||||
if not game:GetService("StarterGui"):GetCoreGuiEnabled(Enum.CoreGuiType.Health) then
|
||||
return
|
||||
end
|
||||
|
||||
healthChangedConnection = currentHumanoid.HealthChanged:connect(HealthChangedLegacy)
|
||||
humanoidDiedConnection = currentHumanoid.Died:connect(function() HealthChangedLegacy(0) end)
|
||||
|
||||
CreateGuiLegacy()
|
||||
end
|
||||
|
||||
|
||||
|
||||
---------------------------------------------------------------------
|
||||
-- Start Script
|
||||
|
||||
HealthGui = Instance.new("Frame")
|
||||
HealthGui.Name = "HealthGui"
|
||||
HealthGui.BackgroundTransparency = 1
|
||||
HealthGui.Size = UDim2.new(1,0,1,0)
|
||||
|
||||
game:GetService("StarterGui").CoreGuiChangedSignal:connect(function(coreGuiType,enabled)
|
||||
if coreGuiType == Enum.CoreGuiType.Health or coreGuiType == Enum.CoreGuiType.All then
|
||||
if guiEnabled and not enabled then
|
||||
if HealthGui then
|
||||
HealthGui.Parent = nil
|
||||
end
|
||||
|
||||
if LegacyHealthGui then
|
||||
LegacyHealthGui:Destroy()
|
||||
end
|
||||
|
||||
disconnectPlayerConnections()
|
||||
elseif not guiEnabled and enabled then
|
||||
startGui()
|
||||
end
|
||||
|
||||
guiEnabled = enabled
|
||||
end
|
||||
end)
|
||||
|
||||
if game:GetService("StarterGui"):GetCoreGuiEnabled(Enum.CoreGuiType.Health) and GameSettings.VirtualVersion ~= Enum.VirtualVersion['2016'] then
|
||||
guiEnabled = true
|
||||
startGui()
|
||||
end
|
||||
|
||||
--[[
|
||||
GameSettings.Changed:connect(function(prop)
|
||||
if prop ~= 'VirtualVersion' then return end
|
||||
|
||||
local enabled = GameSettings.VirtualVersion ~= Enum.VirtualVersion['2016']
|
||||
|
||||
if guiEnabled and not enabled then
|
||||
if HealthGui then
|
||||
HealthGui.Parent = nil
|
||||
end
|
||||
|
||||
if LegacyHealthGui then
|
||||
LegacyHealthGui:Destroy()
|
||||
end
|
||||
|
||||
disconnectPlayerConnections()
|
||||
elseif not guiEnabled and enabled then
|
||||
startGui()
|
||||
end
|
||||
|
||||
guiEnabled = enabled
|
||||
|
||||
local version = GameSettings.VirtualVersion
|
||||
|
||||
if guiEnabled and HealthGui and version ~= Enum.VirtualVersion['2016'] and version ~= Enum.VirtualVersion['2015'] and version ~= Enum.VirtualVersion['2014'] then
|
||||
if HealthGui then
|
||||
HealthGui.Parent = nil
|
||||
end
|
||||
disconnectPlayerConnections()
|
||||
startGuiLegacy()
|
||||
elseif guiEnabled and LegacyHealthGui and (version == Enum.VirtualVersion['2016'] or version == Enum.VirtualVersion['2015'] or version == Enum.VirtualVersion['2014']) then
|
||||
if LegacyHealthGui then
|
||||
LegacyHealthGui:Destroy()
|
||||
end
|
||||
disconnectPlayerConnections()
|
||||
startGui()
|
||||
end
|
||||
end)
|
||||
]]--
|
||||
@@ -0,0 +1,729 @@
|
||||
local PURPOSE_DATA = {
|
||||
[Enum.DialogPurpose.Quest] = {"ayaasset://textures/DialogQuest.png", Vector2.new(10, 34)},
|
||||
[Enum.DialogPurpose.Help] = {"ayaasset://textures/DialogHelp.png", Vector2.new(20, 35)},
|
||||
[Enum.DialogPurpose.Shop] = {"ayaasset://textures/ui/DialogShop.png", Vector2.new(22, 43)},
|
||||
}
|
||||
local TEXT_HEIGHT = 24 -- Pixel height of one row
|
||||
local FONT_SIZE = Enum.FontSize.Size24
|
||||
local BAR_THICKNESS = 6
|
||||
local STYLE_PADDING = 17
|
||||
local CHOICE_PADDING = 6 * 2 -- (Added to vertical height)
|
||||
local PROMPT_SIZE = Vector2.new(80, 90)
|
||||
local FRAME_WIDTH = 350
|
||||
|
||||
local WIDTH_BONUS = (STYLE_PADDING * 2) - BAR_THICKNESS
|
||||
local XPOS_OFFSET = -(STYLE_PADDING - BAR_THICKNESS)
|
||||
|
||||
local contextActionService = game:GetService("ContextActionService")
|
||||
local guiService = game:GetService("GuiService")
|
||||
local YPOS_OFFSET = -math.floor(STYLE_PADDING / 2)
|
||||
local usingGamepad = false
|
||||
|
||||
function setUsingGamepad(input, processed)
|
||||
if input.UserInputType == Enum.UserInputType.Gamepad1 or input.UserInputType == Enum.UserInputType.Gamepad2 or
|
||||
input.UserInputType == Enum.UserInputType.Gamepad3 or input.UserInputType == Enum.UserInputType.Gamepad4 then
|
||||
usingGamepad = true
|
||||
else
|
||||
usingGamepad = false
|
||||
end
|
||||
end
|
||||
|
||||
game:GetService("UserInputService").InputBegan:connect(setUsingGamepad)
|
||||
game:GetService("UserInputService").InputChanged:connect(setUsingGamepad)
|
||||
|
||||
function waitForProperty(instance, name)
|
||||
while not instance[name] do
|
||||
instance.Changed:wait()
|
||||
end
|
||||
end
|
||||
|
||||
function waitForChild(instance, name)
|
||||
while not instance:FindFirstChild(name) do
|
||||
instance.ChildAdded:wait()
|
||||
end
|
||||
end
|
||||
|
||||
local filteringEnabledFixFlagSuccess, filteringEnabledFixFlagValue = pcall(function() return settings():GetFFlag("FilteringEnabledDialogFix") end)
|
||||
local filterEnabledFixActive = (filteringEnabledFixFlagSuccess and filteringEnabledFixFlagValue)
|
||||
|
||||
local goodbyeChoiceActiveFlagSuccess, goodbyeChoiceActiveFlagValue = pcall(function() return settings():GetFFlag("GoodbyeChoiceActiveProperty") end)
|
||||
local goodbyeChoiceActiveFlag = (goodbyeChoiceActiveFlagSuccess and goodbyeChoiceActiveFlagValue)
|
||||
|
||||
local mainFrame
|
||||
local choices = {}
|
||||
local lastChoice
|
||||
local choiceMap = {}
|
||||
local currentConversationDialog
|
||||
local currentConversationPartner
|
||||
local currentAbortDialogScript
|
||||
|
||||
local coroutineMap = {}
|
||||
local currentDialogTimeoutCoroutine = nil
|
||||
|
||||
local tooFarAwayMessage = "You are too far away to chat!"
|
||||
local tooFarAwaySize = 300
|
||||
local characterWanderedOffMessage = "Chat ended because you walked away"
|
||||
local characterWanderedOffSize = 350
|
||||
local conversationTimedOut = "Chat ended because you didn't reply"
|
||||
local conversationTimedOutSize = 350
|
||||
|
||||
local RobloxReplicatedStorage = game:GetService('RobloxReplicatedStorage')
|
||||
local setDialogInUseEvent = RobloxReplicatedStorage:WaitForChild("SetDialogInUse")
|
||||
|
||||
local player
|
||||
local screenGui
|
||||
local chatNotificationGui
|
||||
local messageDialog
|
||||
local timeoutScript
|
||||
local reenableDialogScript
|
||||
local dialogMap = {}
|
||||
local dialogConnections = {}
|
||||
local touchControlGui = nil
|
||||
|
||||
local gui = nil
|
||||
waitForChild(game,"CoreGui")
|
||||
waitForChild(game:GetService("CoreGui"),"RobloxGui")
|
||||
|
||||
game:GetService("CoreGui").RobloxGui:WaitForChild("Modules"):WaitForChild("TenFootInterface")
|
||||
local isTenFootInterface = require(game:GetService("CoreGui").RobloxGui.Modules.TenFootInterface):IsEnabled()
|
||||
local utility = require(game:GetService("CoreGui").RobloxGui.Modules.Utility)
|
||||
local isSmallTouchScreen = utility:IsSmallTouchScreen()
|
||||
|
||||
if isTenFootInterface then
|
||||
FONT_SIZE = Enum.FontSize.Size36
|
||||
TEXT_HEIGHT = 36
|
||||
FRAME_WIDTH = 500
|
||||
elseif isSmallTouchScreen then
|
||||
FONT_SIZE = Enum.FontSize.Size14
|
||||
TEXT_HEIGHT = 14
|
||||
FRAME_WIDTH = 250
|
||||
end
|
||||
|
||||
if game:GetService("CoreGui").RobloxGui:FindFirstChild("ControlFrame") then
|
||||
gui = game:GetService("CoreGui").RobloxGui.ControlFrame
|
||||
else
|
||||
gui = game:GetService("CoreGui").RobloxGui
|
||||
end
|
||||
local touchEnabled = game:GetService("UserInputService").TouchEnabled
|
||||
|
||||
function currentTone()
|
||||
if currentConversationDialog then
|
||||
return currentConversationDialog.Tone
|
||||
else
|
||||
return Enum.DialogTone.Neutral
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function createChatNotificationGui()
|
||||
chatNotificationGui = Instance.new("BillboardGui")
|
||||
chatNotificationGui.Name = "ChatNotificationGui"
|
||||
|
||||
chatNotificationGui.ExtentsOffset = Vector3.new(0,1,0)
|
||||
chatNotificationGui.Size = UDim2.new(PROMPT_SIZE.X / 31.5, 0, PROMPT_SIZE.Y / 31.5, 0)
|
||||
chatNotificationGui.SizeOffset = Vector2.new(0,0)
|
||||
chatNotificationGui.StudsOffset = Vector3.new(0, 3.7, 0)
|
||||
chatNotificationGui.Enabled = true
|
||||
chatNotificationGui.RobloxLocked = true
|
||||
chatNotificationGui.Active = true
|
||||
|
||||
local button = Instance.new("ImageButton")
|
||||
button.Name = "Background"
|
||||
button.Active = false
|
||||
button.BackgroundTransparency = 1
|
||||
button.Position = UDim2.new(0, 0, 0, 0)
|
||||
button.Size = UDim2.new(1, 0, 1, 0)
|
||||
button.Image = ""
|
||||
button.RobloxLocked = true
|
||||
button.Parent = chatNotificationGui
|
||||
|
||||
local icon = Instance.new("ImageLabel")
|
||||
icon.Name = "Icon"
|
||||
icon.Position = UDim2.new(0, 0, 0, 0)
|
||||
icon.Size = UDim2.new(1, 0, 1, 0)
|
||||
icon.Image = ""
|
||||
icon.BackgroundTransparency = 1
|
||||
icon.RobloxLocked = true
|
||||
icon.Parent = button
|
||||
|
||||
local activationButton = Instance.new("ImageLabel")
|
||||
activationButton.Name = "ActivationButton"
|
||||
activationButton.Position = UDim2.new(-0.3, 0, -0.4, 0)
|
||||
activationButton.Size = UDim2.new(.8, 0, .8*(PROMPT_SIZE.X/PROMPT_SIZE.Y), 0)
|
||||
activationButton.Image = "ayaasset://textures/ui/Settings/Help/XButtonDark.png"
|
||||
activationButton.BackgroundTransparency = 1
|
||||
activationButton.Visible = false
|
||||
activationButton.RobloxLocked = true
|
||||
activationButton.Parent = button
|
||||
end
|
||||
|
||||
function getChatColor(tone)
|
||||
if tone == Enum.DialogTone.Neutral then
|
||||
return Enum.ChatColor.Blue
|
||||
elseif tone == Enum.DialogTone.Friendly then
|
||||
return Enum.ChatColor.Green
|
||||
elseif tone == Enum.DialogTone.Enemy then
|
||||
return Enum.ChatColor.Red
|
||||
end
|
||||
end
|
||||
|
||||
function styleChoices()
|
||||
for _, obj in pairs(choices) do
|
||||
obj.BackgroundTransparency = 1
|
||||
end
|
||||
lastChoice.BackgroundTransparency = 1
|
||||
end
|
||||
|
||||
function styleMainFrame(tone)
|
||||
if tone == Enum.DialogTone.Neutral then
|
||||
mainFrame.Style = Enum.FrameStyle.ChatBlue
|
||||
elseif tone == Enum.DialogTone.Friendly then
|
||||
mainFrame.Style = Enum.FrameStyle.ChatGreen
|
||||
elseif tone == Enum.DialogTone.Enemy then
|
||||
mainFrame.Style = Enum.FrameStyle.ChatRed
|
||||
end
|
||||
|
||||
styleChoices()
|
||||
end
|
||||
function setChatNotificationTone(gui, purpose, tone)
|
||||
if tone == Enum.DialogTone.Neutral then
|
||||
gui.Background.Image = "ayaasset://textures/ui/chatBubble_blue_notify_bkg.png"
|
||||
elseif tone == Enum.DialogTone.Friendly then
|
||||
gui.Background.Image = "ayaasset://textures/ui/chatBubble_green_notify_bkg.png"
|
||||
elseif tone == Enum.DialogTone.Enemy then
|
||||
gui.Background.Image = "ayaasset://textures/ui/chatBubble_red_notify_bkg.png"
|
||||
end
|
||||
|
||||
local newIcon, size = unpack(PURPOSE_DATA[purpose])
|
||||
local relativeSize = size / PROMPT_SIZE
|
||||
gui.Background.Icon.Size = UDim2.new(relativeSize.X, 0, relativeSize.Y, 0)
|
||||
gui.Background.Icon.Position = UDim2.new(0.5 - (relativeSize.X / 2), 0, 0.4 - (relativeSize.Y / 2), 0)
|
||||
gui.Background.Icon.Image = newIcon
|
||||
end
|
||||
|
||||
function createMessageDialog()
|
||||
messageDialog = Instance.new("Frame");
|
||||
messageDialog.Name = "DialogScriptMessage"
|
||||
messageDialog.Style = Enum.FrameStyle.Custom
|
||||
messageDialog.BackgroundTransparency = 0.5
|
||||
messageDialog.BackgroundColor3 = Color3.new(31/255, 31/255, 31/255)
|
||||
messageDialog.Visible = false
|
||||
|
||||
local text = Instance.new("TextLabel")
|
||||
text.Name = "Text"
|
||||
text.Position = UDim2.new(0,0,0,-1)
|
||||
text.Size = UDim2.new(1,0,1,0)
|
||||
text.FontSize = Enum.FontSize.Size14
|
||||
text.BackgroundTransparency = 1
|
||||
text.TextColor3 = Color3.new(1,1,1)
|
||||
text.RobloxLocked = true
|
||||
text.Parent = messageDialog
|
||||
end
|
||||
|
||||
function showMessage(msg, size)
|
||||
messageDialog.Text.Text = msg
|
||||
messageDialog.Size = UDim2.new(0,size,0,40)
|
||||
messageDialog.Position = UDim2.new(0.5, -size/2, 0.5, -40)
|
||||
messageDialog.Visible = true
|
||||
wait(2)
|
||||
messageDialog.Visible = false
|
||||
end
|
||||
|
||||
function variableDelay(str)
|
||||
local length = math.min(string.len(str), 100)
|
||||
wait(0.75 + ((length/75) * 1.5))
|
||||
end
|
||||
|
||||
function resetColor(frame)
|
||||
frame.BackgroundTransparency = 1
|
||||
end
|
||||
|
||||
function wanderDialog()
|
||||
mainFrame.Visible = false
|
||||
endDialog()
|
||||
showMessage(characterWanderedOffMessage, characterWanderedOffSize)
|
||||
end
|
||||
|
||||
function timeoutDialog()
|
||||
mainFrame.Visible = false
|
||||
endDialog()
|
||||
showMessage(conversationTimedOut, conversationTimedOutSize)
|
||||
end
|
||||
|
||||
function normalEndDialog()
|
||||
endDialog()
|
||||
end
|
||||
|
||||
function endDialog()
|
||||
if filterEnabledFixActive then
|
||||
if currentDialogTimeoutCoroutine then
|
||||
coroutineMap[currentDialogTimeoutCoroutine] = false
|
||||
currentDialogTimeoutCoroutine = nil
|
||||
end
|
||||
else
|
||||
if currentAbortDialogScript then
|
||||
currentAbortDialogScript:Destroy()
|
||||
currentAbortDialogScript = nil
|
||||
end
|
||||
end
|
||||
|
||||
local dialog = currentConversationDialog
|
||||
currentConversationDialog = nil
|
||||
if dialog and dialog.InUse then
|
||||
if filterEnabledFixActive then
|
||||
spawn(function()
|
||||
wait(5)
|
||||
setDialogInUseEvent:FireServer(dialog, false)
|
||||
end)
|
||||
else
|
||||
local reenableScript = reenableDialogScript:Clone()
|
||||
reenableScript.Archivable = false
|
||||
reenableScript.Disabled = false
|
||||
reenableScript.Parent = dialog
|
||||
end
|
||||
end
|
||||
|
||||
for dialog, gui in pairs(dialogMap) do
|
||||
if dialog and gui then
|
||||
gui.Enabled = not dialog.InUse
|
||||
end
|
||||
end
|
||||
|
||||
contextActionService:UnbindCoreAction("Nothing")
|
||||
currentConversationPartner = nil
|
||||
|
||||
if touchControlGui then
|
||||
touchControlGui.Visible = true
|
||||
end
|
||||
end
|
||||
|
||||
function sanitizeMessage(msg)
|
||||
if string.len(msg) == 0 then
|
||||
return "..."
|
||||
else
|
||||
return msg
|
||||
end
|
||||
end
|
||||
|
||||
function selectChoice(choice)
|
||||
renewKillswitch(currentConversationDialog)
|
||||
|
||||
--First hide the Gui
|
||||
mainFrame.Visible = false
|
||||
if choice == lastChoice then
|
||||
game:GetService("Chat"):Chat(game:GetService("Players").LocalPlayer.Character, lastChoice.UserPrompt.Text, getChatColor(currentTone()))
|
||||
|
||||
normalEndDialog()
|
||||
else
|
||||
local dialogChoice = choiceMap[choice]
|
||||
|
||||
game:GetService("Chat"):Chat(game:GetService("Players").LocalPlayer.Character, sanitizeMessage(dialogChoice.UserDialog), getChatColor(currentTone()))
|
||||
wait(1)
|
||||
currentConversationDialog:SignalDialogChoiceSelected(player, dialogChoice)
|
||||
game:GetService("Chat"):Chat(currentConversationPartner, sanitizeMessage(dialogChoice.ResponseDialog), getChatColor(currentTone()))
|
||||
|
||||
variableDelay(dialogChoice.ResponseDialog)
|
||||
presentDialogChoices(currentConversationPartner, dialogChoice:GetChildren(), dialogChoice)
|
||||
end
|
||||
end
|
||||
|
||||
function newChoice()
|
||||
local dummyFrame = Instance.new("Frame")
|
||||
dummyFrame.Visible = false
|
||||
|
||||
local frame = Instance.new("TextButton")
|
||||
frame.BackgroundColor3 = Color3.new(227/255, 227/255, 227/255)
|
||||
frame.BackgroundTransparency = 1
|
||||
frame.AutoButtonColor = false
|
||||
frame.BorderSizePixel = 0
|
||||
frame.Text = ""
|
||||
frame.MouseEnter:connect(function() frame.BackgroundTransparency = 0 end)
|
||||
frame.MouseLeave:connect(function() frame.BackgroundTransparency = 1 end)
|
||||
frame.SelectionImageObject = dummyFrame
|
||||
frame.MouseButton1Click:connect(function() selectChoice(frame) end)
|
||||
frame.RobloxLocked = true
|
||||
|
||||
local prompt = Instance.new("TextLabel")
|
||||
prompt.Name = "UserPrompt"
|
||||
prompt.BackgroundTransparency = 1
|
||||
prompt.Font = Enum.Font.SourceSans
|
||||
prompt.FontSize = FONT_SIZE
|
||||
prompt.Position = UDim2.new(0, 40, 0, 0)
|
||||
prompt.Size = UDim2.new(1, -32-40, 1, 0)
|
||||
prompt.TextXAlignment = Enum.TextXAlignment.Left
|
||||
prompt.TextYAlignment = Enum.TextYAlignment.Center
|
||||
prompt.TextWrap = true
|
||||
prompt.RobloxLocked = true
|
||||
prompt.Parent = frame
|
||||
|
||||
local selectionButton = Instance.new("ImageLabel")
|
||||
selectionButton.Name = "RBXchatDialogSelectionButton"
|
||||
selectionButton.Position = UDim2.new(0, 0, 0.5, -33/2)
|
||||
selectionButton.Size = UDim2.new(0, 33, 0, 33)
|
||||
selectionButton.Image = "ayaasset://textures/ui/Settings/Help/AButtonLightSmall.png"
|
||||
selectionButton.BackgroundTransparency = 1
|
||||
selectionButton.Visible = false
|
||||
selectionButton.RobloxLocked = true
|
||||
selectionButton.Parent = frame
|
||||
|
||||
return frame
|
||||
end
|
||||
function initialize(parent)
|
||||
choices[1] = newChoice()
|
||||
choices[2] = newChoice()
|
||||
choices[3] = newChoice()
|
||||
choices[4] = newChoice()
|
||||
|
||||
lastChoice = newChoice()
|
||||
lastChoice.UserPrompt.Text = "Goodbye!"
|
||||
lastChoice.Size = UDim2.new(1, WIDTH_BONUS, 0, TEXT_HEIGHT + CHOICE_PADDING)
|
||||
|
||||
mainFrame = Instance.new("Frame")
|
||||
mainFrame.Name = "UserDialogArea"
|
||||
mainFrame.Size = UDim2.new(0, FRAME_WIDTH, 0, 200)
|
||||
mainFrame.Style = Enum.FrameStyle.ChatBlue
|
||||
mainFrame.Visible = false
|
||||
|
||||
for n, obj in pairs(choices) do
|
||||
obj.RobloxLocked = true
|
||||
obj.Parent = mainFrame
|
||||
end
|
||||
|
||||
lastChoice.RobloxLocked = true
|
||||
lastChoice.Parent = mainFrame
|
||||
|
||||
mainFrame.RobloxLocked = true
|
||||
mainFrame.Parent = parent
|
||||
end
|
||||
|
||||
function presentDialogChoices(talkingPart, dialogChoices, parentDialog)
|
||||
if not currentConversationDialog then
|
||||
return
|
||||
end
|
||||
|
||||
currentConversationPartner = talkingPart
|
||||
sortedDialogChoices = {}
|
||||
for n, obj in pairs(dialogChoices) do
|
||||
if obj:IsA("DialogChoice") then
|
||||
table.insert(sortedDialogChoices, obj)
|
||||
end
|
||||
end
|
||||
table.sort(sortedDialogChoices, function(a,b) return a.Name < b.Name end)
|
||||
|
||||
if #sortedDialogChoices == 0 then
|
||||
normalEndDialog()
|
||||
return
|
||||
end
|
||||
|
||||
local pos = 1
|
||||
local yPosition = 0
|
||||
choiceMap = {}
|
||||
for n, obj in pairs(choices) do
|
||||
obj.Visible = false
|
||||
end
|
||||
|
||||
for n, obj in pairs(sortedDialogChoices) do
|
||||
if pos <= #choices then
|
||||
--3 lines is the maximum, set it to that temporarily
|
||||
choices[pos].Size = UDim2.new(1, WIDTH_BONUS, 0, TEXT_HEIGHT * 3)
|
||||
choices[pos].UserPrompt.Text = obj.UserDialog
|
||||
local height = (math.ceil(choices[pos].UserPrompt.TextBounds.Y / TEXT_HEIGHT) * TEXT_HEIGHT) + CHOICE_PADDING
|
||||
|
||||
choices[pos].Position = UDim2.new(0, XPOS_OFFSET, 0, YPOS_OFFSET + yPosition)
|
||||
choices[pos].Size = UDim2.new(1, WIDTH_BONUS, 0, height)
|
||||
choices[pos].Visible = true
|
||||
|
||||
choiceMap[choices[pos]] = obj
|
||||
|
||||
yPosition = yPosition + height + 1 -- The +1 makes highlights not overlap
|
||||
pos = pos + 1
|
||||
end
|
||||
end
|
||||
|
||||
lastChoice.Size = UDim2.new(1, WIDTH_BONUS, 0, TEXT_HEIGHT * 3)
|
||||
lastChoice.UserPrompt.Text = parentDialog.GoodbyeDialog == "" and "Goodbye!" or parentDialog.GoodbyeDialog
|
||||
local height = (math.ceil(lastChoice.UserPrompt.TextBounds.Y / TEXT_HEIGHT) * TEXT_HEIGHT) + CHOICE_PADDING
|
||||
lastChoice.Size = UDim2.new(1, WIDTH_BONUS, 0, height)
|
||||
lastChoice.Position = UDim2.new(0, XPOS_OFFSET, 0, YPOS_OFFSET + yPosition)
|
||||
lastChoice.Visible = true
|
||||
|
||||
if goodbyeChoiceActiveFlag and not parentDialog.GoodbyeChoiceActive then
|
||||
lastChoice.Visible = false
|
||||
mainFrame.Size = UDim2.new(0, FRAME_WIDTH, 0, yPosition + (STYLE_PADDING * 2) + (YPOS_OFFSET * 2))
|
||||
else
|
||||
mainFrame.Size = UDim2.new(0, FRAME_WIDTH, 0, yPosition + lastChoice.AbsoluteSize.Y + (STYLE_PADDING * 2) + (YPOS_OFFSET * 2))
|
||||
end
|
||||
|
||||
mainFrame.Position = UDim2.new(0,20,1.0, -mainFrame.Size.Y.Offset-20)
|
||||
if isSmallTouchScreen then
|
||||
local touchScreenGui = game.Players.LocalPlayer.PlayerGui:FindFirstChild("TouchGui")
|
||||
if touchScreenGui then
|
||||
touchControlGui = touchScreenGui:FindFirstChild("TouchControlFrame")
|
||||
if touchControlGui then
|
||||
touchControlGui.Visible = false
|
||||
end
|
||||
end
|
||||
mainFrame.Position = UDim2.new(0,10,1.0, -mainFrame.Size.Y.Offset)
|
||||
end
|
||||
styleMainFrame(currentTone())
|
||||
mainFrame.Visible = true
|
||||
|
||||
if usingGamepad then
|
||||
Game:GetService("GuiService").SelectedCoreObject = choices[1]
|
||||
end
|
||||
end
|
||||
|
||||
function doDialog(dialog)
|
||||
if dialog.InUse then
|
||||
return
|
||||
else
|
||||
dialog.InUse = true
|
||||
if filterEnabledFixActive then
|
||||
setDialogInUseEvent:FireServer(dialog, true)
|
||||
end
|
||||
end
|
||||
|
||||
currentConversationDialog = dialog
|
||||
game:GetService("Chat"):Chat(dialog.Parent, dialog.InitialPrompt, getChatColor(dialog.Tone))
|
||||
variableDelay(dialog.InitialPrompt)
|
||||
|
||||
presentDialogChoices(dialog.Parent, dialog:GetChildren(), dialog)
|
||||
end
|
||||
|
||||
function renewKillswitch(dialog)
|
||||
if filterEnabledFixActive then
|
||||
if currentDialogTimeoutCoroutine then
|
||||
coroutineMap[currentDialogTimeoutCoroutine] = false
|
||||
currentDialogTimeoutCoroutine = nil
|
||||
end
|
||||
else
|
||||
if currentAbortDialogScript then
|
||||
currentAbortDialogScript:Destroy()
|
||||
currentAbortDialogScript = nil
|
||||
end
|
||||
end
|
||||
|
||||
if filterEnabledFixActive then
|
||||
currentDialogTimeoutCoroutine = coroutine.create(function(thisCoroutine)
|
||||
wait(15)
|
||||
if thisCoroutine ~= nil then
|
||||
if coroutineMap[thisCoroutine] == nil then
|
||||
setDialogInUseEvent:FireServer(dialog, false)
|
||||
end
|
||||
coroutineMap[thisCoroutine] = nil
|
||||
end
|
||||
end)
|
||||
coroutine.resume(currentDialogTimeoutCoroutine, currentDialogTimeoutCoroutine)
|
||||
else
|
||||
currentAbortDialogScript = timeoutScript:Clone()
|
||||
currentAbortDialogScript.Archivable = false
|
||||
currentAbortDialogScript.Disabled = false
|
||||
currentAbortDialogScript.Parent = dialog
|
||||
end
|
||||
end
|
||||
|
||||
function checkForLeaveArea()
|
||||
while currentConversationDialog do
|
||||
if currentConversationDialog.Parent and (player:DistanceFromCharacter(currentConversationDialog.Parent.Position) >= currentConversationDialog.ConversationDistance) then
|
||||
wanderDialog()
|
||||
end
|
||||
wait(1)
|
||||
end
|
||||
end
|
||||
|
||||
function startDialog(dialog)
|
||||
if dialog.Parent and dialog.Parent:IsA("BasePart") then
|
||||
if player:DistanceFromCharacter(dialog.Parent.Position) >= dialog.ConversationDistance then
|
||||
showMessage(tooFarAwayMessage, tooFarAwaySize)
|
||||
return
|
||||
end
|
||||
|
||||
for dialog, gui in pairs(dialogMap) do
|
||||
if dialog and gui then
|
||||
gui.Enabled = false
|
||||
end
|
||||
end
|
||||
|
||||
contextActionService:BindCoreAction("Nothing", function() end, false, Enum.UserInputType.Gamepad1, Enum.UserInputType.Gamepad2, Enum.UserInputType.Gamepad3, Enum.UserInputType.Gamepad4)
|
||||
|
||||
renewKillswitch(dialog)
|
||||
|
||||
delay(1, checkForLeaveArea)
|
||||
doDialog(dialog)
|
||||
end
|
||||
end
|
||||
|
||||
function removeDialog(dialog)
|
||||
if dialogMap[dialog] then
|
||||
dialogMap[dialog]:Destroy()
|
||||
dialogMap[dialog] = nil
|
||||
end
|
||||
if dialogConnections[dialog] then
|
||||
dialogConnections[dialog]:disconnect()
|
||||
dialogConnections[dialog] = nil
|
||||
end
|
||||
end
|
||||
|
||||
function addDialog(dialog)
|
||||
if dialog.Parent then
|
||||
if dialog.Parent:IsA("BasePart") then
|
||||
local chatGui = chatNotificationGui:clone()
|
||||
chatGui.Enabled = not dialog.InUse
|
||||
chatGui.Adornee = dialog.Parent
|
||||
chatGui.RobloxLocked = true
|
||||
|
||||
chatGui.Parent = game:GetService("CoreGui")
|
||||
|
||||
chatGui.Background.MouseButton1Click:connect(function() startDialog(dialog) end)
|
||||
setChatNotificationTone(chatGui, dialog.Purpose, dialog.Tone)
|
||||
|
||||
dialogMap[dialog] = chatGui
|
||||
|
||||
dialogConnections[dialog] = dialog.Changed:connect(function(prop)
|
||||
if prop == "Parent" and dialog.Parent then
|
||||
--This handles the reparenting case, seperate from removal case
|
||||
removeDialog(dialog)
|
||||
addDialog(dialog)
|
||||
elseif prop == "InUse" then
|
||||
chatGui.Enabled = not currentConversationDialog and not dialog.InUse
|
||||
if dialog == currentConversationDialog then
|
||||
timeoutDialog()
|
||||
end
|
||||
elseif prop == "Tone" or prop == "Purpose" then
|
||||
setChatNotificationTone(chatGui, dialog.Purpose, dialog.Tone)
|
||||
end
|
||||
end)
|
||||
else -- still need to listen to parent changes even if current parent is not a BasePart
|
||||
dialogConnections[dialog] = dialog.Changed:connect(function(prop)
|
||||
if prop == "Parent" and dialog.Parent then
|
||||
--This handles the reparenting case, seperate from removal case
|
||||
removeDialog(dialog)
|
||||
addDialog(dialog)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function fetchScripts()
|
||||
local model = game:GetService("InsertService"):LoadPrivateAsset("ayaasset://avatar/scripts/dialogTimeout.rbxmx")
|
||||
if type(model) == "string" then -- load failed, lets try again
|
||||
wait(0.1)
|
||||
model = game:GetService("InsertService"):LoadPrivateAsset("ayaasset://avatar/scripts/dialogTimeout.rbxmx")
|
||||
end
|
||||
if type(model) == "string" then -- not going to work, lets bail
|
||||
return
|
||||
end
|
||||
|
||||
waitForChild(model,"TimeoutScript")
|
||||
timeoutScript = model.TimeoutScript
|
||||
waitForChild(model,"ReenableDialogScript")
|
||||
reenableDialogScript = model.ReenableDialogScript
|
||||
end
|
||||
|
||||
function onLoad()
|
||||
waitForProperty(game:GetService("Players"), "LocalPlayer")
|
||||
player = game:GetService("Players").LocalPlayer
|
||||
waitForProperty(player, "Character")
|
||||
|
||||
--print("Creating Guis")
|
||||
createChatNotificationGui()
|
||||
|
||||
--print("Creating MessageDialog")
|
||||
createMessageDialog()
|
||||
messageDialog.RobloxLocked = true
|
||||
messageDialog.Parent = gui
|
||||
|
||||
if not filterEnabledFixActive then
|
||||
fetchScripts()
|
||||
end
|
||||
|
||||
--print("Waiting for BottomLeftControl")
|
||||
waitForChild(gui, "BottomLeftControl")
|
||||
|
||||
--print("Initializing Frame")
|
||||
local frame = Instance.new("Frame")
|
||||
frame.Name = "DialogFrame"
|
||||
frame.Position = UDim2.new(0,0,0,0)
|
||||
frame.Size = UDim2.new(0,0,0,0)
|
||||
frame.BackgroundTransparency = 1
|
||||
frame.RobloxLocked = true
|
||||
game:GetService("GuiService"):AddSelectionParent("RBXDialogGroup", frame)
|
||||
|
||||
if (touchEnabled and not isSmallTouchScreen) then
|
||||
frame.Position = UDim2.new(0,20,0.5,0)
|
||||
frame.Size = UDim2.new(0.25,0,0.1,0)
|
||||
frame.Parent = gui
|
||||
elseif isSmallTouchScreen then
|
||||
frame.Position = UDim2.new(0,0,.9,-10)
|
||||
frame.Size = UDim2.new(0.25,0,0.1,0)
|
||||
frame.Parent = gui
|
||||
else
|
||||
frame.Parent = gui.BottomLeftControl
|
||||
end
|
||||
initialize(frame)
|
||||
|
||||
--print("Adding Dialogs")
|
||||
game:GetService("CollectionService").ItemAdded:connect(function(obj) if obj:IsA("Dialog") then addDialog(obj) end end)
|
||||
game:GetService("CollectionService").ItemRemoved:connect(function(obj) if obj:IsA("Dialog") then removeDialog(obj) end end)
|
||||
for i, obj in pairs(game:GetService("CollectionService"):GetCollection("Dialog")) do
|
||||
if obj:IsA("Dialog") then
|
||||
addDialog(obj)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local lastClosestDialog = nil
|
||||
local getClosestDialogToPosition = guiService.GetClosestDialogToPosition
|
||||
|
||||
game:GetService("RunService").Heartbeat:connect(function()
|
||||
local closestDistance = math.huge
|
||||
local closestDialog = nil
|
||||
if usingGamepad == true then
|
||||
if game.Players.LocalPlayer and game.Players.LocalPlayer.Character and game.Players.LocalPlayer.Character:FindFirstChild("HumanoidRootPart") then
|
||||
local characterPosition = game.Players.LocalPlayer.Character:FindFirstChild("HumanoidRootPart").Position
|
||||
closestDialog = getClosestDialogToPosition(guiService, characterPosition)
|
||||
end
|
||||
end
|
||||
|
||||
if closestDialog ~= lastClosestDialog then
|
||||
if dialogMap[lastClosestDialog] then
|
||||
dialogMap[lastClosestDialog].Background.ActivationButton.Visible = false
|
||||
end
|
||||
lastClosestDialog = closestDialog
|
||||
contextActionService:UnbindCoreAction("StartDialogAction")
|
||||
if closestDialog ~= nil then
|
||||
contextActionService:BindCoreAction("StartDialogAction",
|
||||
function(actionName, userInputState, inputObject)
|
||||
if userInputState == Enum.UserInputState.Begin then
|
||||
if closestDialog and closestDialog.Parent then
|
||||
startDialog(closestDialog)
|
||||
end
|
||||
end
|
||||
end,
|
||||
false,
|
||||
Enum.KeyCode.ButtonX)
|
||||
if dialogMap[closestDialog] then
|
||||
dialogMap[closestDialog].Background.ActivationButton.Visible = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local lastSelectedChoice = nil
|
||||
|
||||
guiService.Changed:connect(function(property)
|
||||
if property == "SelectedCoreObject" then
|
||||
if lastSelectedChoice and lastSelectedChoice:FindFirstChild("RBXchatDialogSelectionButton") then
|
||||
lastSelectedChoice:FindFirstChild("RBXchatDialogSelectionButton").Visible = false
|
||||
lastSelectedChoice.BackgroundTransparency = 1
|
||||
end
|
||||
lastSelectedChoice = guiService.SelectedCoreObject
|
||||
if lastSelectedChoice and lastSelectedChoice:FindFirstChild("RBXchatDialogSelectionButton") then
|
||||
lastSelectedChoice:FindFirstChild("RBXchatDialogSelectionButton").Visible = true
|
||||
lastSelectedChoice.BackgroundTransparency = 0
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
onLoad()
|
||||
@@ -0,0 +1,629 @@
|
||||
--[[
|
||||
Filename: NotificationScript2.lua
|
||||
Version 1.1
|
||||
Written by: jmargh
|
||||
Description: Handles notification gui for the following in game ROBLOX events
|
||||
Badge Awarded
|
||||
Player Points Awarded
|
||||
Friend Request Recieved/New Friend
|
||||
Graphics Quality Changed
|
||||
Teleports
|
||||
CreatePlaceInPlayerInventoryAsync
|
||||
--]]
|
||||
|
||||
--[[ Services ]]--
|
||||
local BadgeService = game:GetService('BadgeService')
|
||||
local GuiService = game:GetService('GuiService')
|
||||
local Players = game:GetService('Players')
|
||||
local PointsService = game:GetService('PointsService')
|
||||
local MarketplaceService = game:GetService('MarketplaceService')
|
||||
local TeleportService = game:GetService('TeleportService')
|
||||
local HttpService = game:GetService("HttpService")
|
||||
local ContextActionService = game:GetService("ContextActionService")
|
||||
local CoreGui = game:GetService("CoreGui")
|
||||
local RobloxGui = CoreGui:WaitForChild("RobloxGui")
|
||||
local Settings = UserSettings()
|
||||
local GameSettings = Settings.GameSettings
|
||||
|
||||
--[[ Fast Flags ]]--
|
||||
local getNotificationDisableSuccess, notificationsDisableActiveValue = pcall(function() return settings():GetFFlag("SetCoreDisableNotifications") end)
|
||||
local allowDisableNotifications = getNotificationDisableSuccess and notificationsDisableActiveValue
|
||||
|
||||
local getSendNotificationSuccess, sendNotificationActiveValue = pcall(function() return settings():GetFFlag("SetCoreSendNotifications") end)
|
||||
local allowSendNotifications = getSendNotificationSuccess and sendNotificationActiveValue
|
||||
|
||||
--[[ Script Variables ]]--
|
||||
local LocalPlayer = nil
|
||||
while not Players.LocalPlayer do
|
||||
wait()
|
||||
end
|
||||
LocalPlayer = Players.LocalPlayer
|
||||
local RbxGui = script.Parent
|
||||
local NotificationQueue = {}
|
||||
local OverflowQueue = {}
|
||||
local FriendRequestBlacklist = {}
|
||||
local CurrentGraphicsQualityLevel = GameSettings.SavedQualityLevel.Value
|
||||
local BindableEvent_SendNotification = Instance.new('BindableFunction')
|
||||
BindableEvent_SendNotification.Name = "SendNotification"
|
||||
BindableEvent_SendNotification.Parent = RbxGui
|
||||
local isPaused = false
|
||||
RobloxGui:WaitForChild("Modules"):WaitForChild("TenFootInterface")
|
||||
local isTenFootInterface = require(RobloxGui.Modules.TenFootInterface):IsEnabled()
|
||||
|
||||
local pointsNotificationsActive = true
|
||||
local badgesNotificationsActive = true
|
||||
|
||||
--[[ Constants ]]--
|
||||
local BG_TRANSPARENCY = 0.7
|
||||
local MAX_NOTIFICATIONS = 3
|
||||
local NOTIFICATION_Y_OFFSET = 64
|
||||
local IMAGE_SIZE = 48
|
||||
local EASE_DIR = Enum.EasingDirection.InOut
|
||||
local EASE_STYLE = Enum.EasingStyle.Sine
|
||||
local TWEEN_TIME = 0.35
|
||||
local DEFAULT_NOTIFICATION_DURATION = 5
|
||||
|
||||
--[[ Images ]]--
|
||||
local PLAYER_POINTS_IMG = 'ayaasset://textures/PlayerPoint.png'
|
||||
local BADGE_IMG = 'ayaasset://textures/2015/NotificationScript/BADGE_IMG.png'
|
||||
local FRIEND_IMAGE = 'http://www.roblox.com/thumbs/avatar.ashx?userId='
|
||||
|
||||
--[[ Gui Creation ]]--
|
||||
local function createFrame(name, size, position, bgt)
|
||||
local frame = Instance.new('Frame')
|
||||
frame.Name = name
|
||||
frame.Size = size
|
||||
frame.Position = position
|
||||
frame.BackgroundTransparency = bgt
|
||||
|
||||
return frame
|
||||
end
|
||||
|
||||
local function createTextButton(name, text, position)
|
||||
local button = Instance.new('TextButton')
|
||||
button.Name = name
|
||||
button.Size = UDim2.new(0.5, -2, 0.5, 0)
|
||||
button.Position = position
|
||||
button.BackgroundTransparency = BG_TRANSPARENCY
|
||||
button.BackgroundColor3 = Color3.new(0, 0, 0)
|
||||
button.Font = Enum.Font.SourceSansBold
|
||||
button.FontSize = Enum.FontSize.Size18
|
||||
button.TextColor3 = Color3.new(1, 1, 1)
|
||||
button.Text = text
|
||||
|
||||
return button
|
||||
end
|
||||
|
||||
local NotificationFrame = createFrame("NotificationFrame", UDim2.new(0, 200, 0.42, 0), UDim2.new(1, -204, 0.50, 0), 1)
|
||||
NotificationFrame.Parent = RbxGui
|
||||
|
||||
local DefaultNotifcation = createFrame("Notifcation", UDim2.new(1, 0, 0, NOTIFICATION_Y_OFFSET), UDim2.new(0, 0, 0, 0), BG_TRANSPARENCY)
|
||||
DefaultNotifcation.BackgroundColor3 = Color3.new(0, 0, 0)
|
||||
DefaultNotifcation.BorderSizePixel = 0
|
||||
|
||||
local NotificationTitle = Instance.new('TextLabel')
|
||||
NotificationTitle.Name = "NotificationTitle"
|
||||
NotificationTitle.Size = UDim2.new(0, 0, 0, 0)
|
||||
NotificationTitle.Position = UDim2.new(0.5, 0, 0.5, -12)
|
||||
NotificationTitle.BackgroundTransparency = 1
|
||||
NotificationTitle.Font = Enum.Font.SourceSansBold
|
||||
NotificationTitle.FontSize = Enum.FontSize.Size18
|
||||
NotificationTitle.TextColor3 = Color3.new(0.97, 0.97, 0.97)
|
||||
|
||||
local NotificationText = Instance.new('TextLabel')
|
||||
NotificationText.Name = "NotificationText"
|
||||
NotificationText.Size = UDim2.new(1, -20, 0, 28)
|
||||
NotificationText.Position = UDim2.new(0, 10, 0.5, 1)
|
||||
NotificationText.BackgroundTransparency = 1
|
||||
NotificationText.Font = Enum.Font.SourceSans
|
||||
NotificationText.FontSize = Enum.FontSize.Size14
|
||||
NotificationText.TextColor3 = Color3.new(0.92, 0.92, 0.92)
|
||||
NotificationText.TextWrap = true
|
||||
NotificationText.TextYAlignment = Enum.TextYAlignment.Top
|
||||
|
||||
local NotificationImage = Instance.new('ImageLabel')
|
||||
NotificationImage.Name = "NotificationImage"
|
||||
NotificationImage.Size = UDim2.new(0, IMAGE_SIZE, 0, IMAGE_SIZE)
|
||||
NotificationImage.Position = UDim2.new(0, 8, 0.5, -24)
|
||||
NotificationImage.BackgroundTransparency = 1
|
||||
NotificationImage.Image = ""
|
||||
|
||||
-- Would really like to get rid of this but some events still require this
|
||||
local PopupFrame = createFrame("PopupFrame", UDim2.new(0, 360, 0, 160), UDim2.new(0.5, -180, 0.5, -50), 0)
|
||||
PopupFrame.Style = Enum.FrameStyle.DropShadow
|
||||
PopupFrame.ZIndex = 4
|
||||
PopupFrame.Visible = false
|
||||
PopupFrame.Parent = RbxGui
|
||||
|
||||
local PopupAcceptButton = Instance.new('TextButton')
|
||||
PopupAcceptButton.Name = "PopupAcceptButton"
|
||||
PopupAcceptButton.Size = UDim2.new(0, 100, 0, 50)
|
||||
PopupAcceptButton.Position = UDim2.new(0.5, -102, 1, -58)
|
||||
PopupAcceptButton.Style = Enum.ButtonStyle.RobloxRoundButton
|
||||
PopupAcceptButton.Font = Enum.Font.SourceSansBold
|
||||
PopupAcceptButton.FontSize = Enum.FontSize.Size24
|
||||
PopupAcceptButton.TextColor3 = Color3.new(1, 1, 1)
|
||||
PopupAcceptButton.Text = "Accept"
|
||||
PopupAcceptButton.ZIndex = 5
|
||||
PopupAcceptButton.Parent = PopupFrame
|
||||
|
||||
local PopupDeclineButton = PopupAcceptButton:Clone()
|
||||
PopupDeclineButton.Name = "PopupDeclineButton"
|
||||
PopupDeclineButton.Position = UDim2.new(0.5, 2, 1, -58)
|
||||
PopupDeclineButton.Text = "Decline"
|
||||
PopupDeclineButton.Parent = PopupFrame
|
||||
|
||||
local PopupOKButton = PopupAcceptButton:Clone()
|
||||
PopupOKButton.Name = "PopupOKButton"
|
||||
PopupOKButton.Position = UDim2.new(0.5, -50, 1, -58)
|
||||
PopupOKButton.Text = "OK"
|
||||
PopupOKButton.Visible = false
|
||||
PopupOKButton.Parent = PopupFrame
|
||||
|
||||
local PopupText = Instance.new('TextLabel')
|
||||
PopupText.Name = "PopupText"
|
||||
PopupText.Size = UDim2.new(1, -16, 0.8, 0)
|
||||
PopupText.Position = UDim2.new(0, 8, 0, 8)
|
||||
PopupText.BackgroundTransparency = 1
|
||||
PopupText.Font = Enum.Font.SourceSansBold
|
||||
PopupText.FontSize = Enum.FontSize.Size36
|
||||
PopupText.TextColor3 = Color3.new(0.97, 0.97, 0.97)
|
||||
PopupText.TextWrap = true
|
||||
PopupText.ZIndex = 5
|
||||
PopupText.TextYAlignment = Enum.TextYAlignment.Top
|
||||
PopupText.Text = "This is a popup"
|
||||
PopupText.Parent = PopupFrame
|
||||
|
||||
--[[ Helper Functions ]]--
|
||||
local insertNotifcation = nil
|
||||
local removeNotification = nil
|
||||
--
|
||||
local function createNotification(title, text, image)
|
||||
local notificationFrame = DefaultNotifcation:Clone()
|
||||
notificationFrame.Position = UDim2.new(1, 4, 1, -NOTIFICATION_Y_OFFSET - 4)
|
||||
--
|
||||
local notificationTitle = NotificationTitle:Clone()
|
||||
notificationTitle.Text = title
|
||||
notificationTitle.Parent = notificationFrame
|
||||
|
||||
local notificationText = NotificationText:Clone()
|
||||
notificationText.Text = text
|
||||
notificationText.Parent = notificationFrame
|
||||
|
||||
if image and image ~= "" then
|
||||
local notificationImage = NotificationImage:Clone()
|
||||
notificationImage.Image = image
|
||||
notificationImage.Parent = notificationFrame
|
||||
--
|
||||
notificationTitle.Position = UDim2.new(0, NotificationImage.Size.X.Offset + 16, 0.5, -12)
|
||||
notificationTitle.TextXAlignment = Enum.TextXAlignment.Left
|
||||
--
|
||||
notificationText.Size = UDim2.new(1, -IMAGE_SIZE - 16, 0, 28)
|
||||
notificationText.Position = UDim2.new(0, IMAGE_SIZE + 16, 0.5, 1)
|
||||
notificationText.TextXAlignment = Enum.TextXAlignment.Left
|
||||
end
|
||||
|
||||
GuiService:AddSelectionParent(HttpService:GenerateGUID(false), notificationFrame)
|
||||
|
||||
return notificationFrame
|
||||
end
|
||||
|
||||
local function findNotification(notification)
|
||||
local index = nil
|
||||
for i = 1, #NotificationQueue do
|
||||
if NotificationQueue[i] == notification then
|
||||
return i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function updateNotifications()
|
||||
local pos = 1
|
||||
local yOffset = 0
|
||||
for i = #NotificationQueue, 1, -1 do
|
||||
local currentNotification = NotificationQueue[i]
|
||||
if currentNotification then
|
||||
local frame = currentNotification.Frame
|
||||
if frame and frame.Parent then
|
||||
local thisOffset = currentNotification.IsFriend and (NOTIFICATION_Y_OFFSET + 2) * 1.5 or NOTIFICATION_Y_OFFSET
|
||||
yOffset = yOffset + thisOffset
|
||||
frame:TweenPosition(UDim2.new(0, 0, 1, -yOffset - (pos * 4)), EASE_DIR, EASE_STYLE, TWEEN_TIME, true)
|
||||
pos = pos + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local lastTimeInserted = 0
|
||||
insertNotifcation = function(notification)
|
||||
spawn(function()
|
||||
while isPaused do wait() end
|
||||
notification.IsActive = true
|
||||
local size = #NotificationQueue
|
||||
if size == MAX_NOTIFICATIONS then
|
||||
OverflowQueue[#OverflowQueue + 1] = notification
|
||||
return
|
||||
end
|
||||
--
|
||||
NotificationQueue[size + 1] = notification
|
||||
notification.Frame.Parent = NotificationFrame
|
||||
delay(notification.Duration, function()
|
||||
removeNotification(notification)
|
||||
end)
|
||||
while tick() - lastTimeInserted < TWEEN_TIME do
|
||||
wait()
|
||||
end
|
||||
lastTimeInserted = tick()
|
||||
--
|
||||
updateNotifications()
|
||||
end)
|
||||
end
|
||||
|
||||
removeNotification = function(notification)
|
||||
if not notification then return end
|
||||
--
|
||||
local index = findNotification(notification)
|
||||
table.remove(NotificationQueue, index)
|
||||
local frame = notification.Frame
|
||||
if frame and frame.Parent then
|
||||
notification.IsActive = false
|
||||
spawn(function()
|
||||
while isPaused do wait() end
|
||||
|
||||
frame:TweenPosition(UDim2.new(1, 0, 1, frame.Position.Y.Offset), EASE_DIR, EASE_STYLE, TWEEN_TIME, true,
|
||||
function()
|
||||
frame:Destroy()
|
||||
notification = nil
|
||||
end)
|
||||
end)
|
||||
end
|
||||
if #OverflowQueue > 0 then
|
||||
local nextNofication = OverflowQueue[1]
|
||||
table.remove(OverflowQueue, 1)
|
||||
insertNotifcation(nextNofication)
|
||||
else
|
||||
updateNotifications()
|
||||
end
|
||||
end
|
||||
|
||||
local function sendNotifcation(title, text, image, duration, callback, button1Text, button2Text)
|
||||
local notification = {}
|
||||
local notificationFrame = createNotification(title, text, image)
|
||||
--
|
||||
|
||||
local button1 = nil
|
||||
if button1Text and button1Text ~= "" then
|
||||
notification.IsFriend = true -- Prevents other notifications overlapping the buttons
|
||||
button1 = createTextButton("Button1", button1Text, UDim2.new(0, 0, 1, 2))
|
||||
button1.Parent = notificationFrame
|
||||
local button1ClickedConnection = nil
|
||||
button1ClickedConnection = button1.MouseButton1Click:connect(function()
|
||||
if button1ClickedConnection then
|
||||
button1ClickedConnection:disconnect()
|
||||
button1ClickedConnection = nil
|
||||
removeNotification(notification)
|
||||
if callback and type(callback) ~= "function" then -- callback should be a bindable
|
||||
pcall(function() callback:Invoke(button1Text) end)
|
||||
elseif type(callback) == "function" then
|
||||
callback(button1Text)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
if button2Text and button2Text ~= "" then
|
||||
notification.IsFriend = true
|
||||
local button2 = createTextButton("Button1", button2Text, UDim2.new(0.5, 2, 1, 2))
|
||||
button2.Parent = notificationFrame
|
||||
local button2ClickedConnection = nil
|
||||
button2ClickedConnection = button2.MouseButton1Click:connect(function()
|
||||
if button2ClickedConnection then
|
||||
button2ClickedConnection:disconnect()
|
||||
button2ClickedConnection = nil
|
||||
removeNotification(notification)
|
||||
if callback and type(callback) ~= "function" then -- callback should be a bindable
|
||||
pcall(function() callback:Invoke(button2Text) end)
|
||||
elseif type(callback) == "function" then
|
||||
callback(button2Text)
|
||||
end
|
||||
end
|
||||
end)
|
||||
else
|
||||
-- Resize button1 to take up all the space under the notification if button2 doesn't exist
|
||||
if button1 then
|
||||
button1.Size = UDim2.new(1, -2, .5, 0)
|
||||
end
|
||||
end
|
||||
|
||||
notification.Frame = notificationFrame
|
||||
notification.Duration = duration
|
||||
insertNotifcation(notification)
|
||||
end
|
||||
BindableEvent_SendNotification.OnInvoke = function(title, text, image, duration, callback)
|
||||
sendNotifcation(title, text, image, duration, callback)
|
||||
end
|
||||
|
||||
-- New follower notification
|
||||
spawn(function()
|
||||
local RobloxReplicatedStorage = game:GetService('RobloxReplicatedStorage')
|
||||
local RemoteEvent_NewFollower = RobloxReplicatedStorage:WaitForChild('NewFollower')
|
||||
--
|
||||
RemoteEvent_NewFollower.OnClientEvent:connect(function(followerRbxPlayer)
|
||||
sendNotifcation("New Follower", followerRbxPlayer.Name.." is now following you!",
|
||||
FRIEND_IMAGE..followerRbxPlayer.userId.."&x=48&y=48", 5, function() end)
|
||||
end)
|
||||
end)
|
||||
|
||||
local function sendFriendNotification(fromPlayer)
|
||||
local notification = {}
|
||||
local notificationFrame = createNotification(fromPlayer.Name, "Sent you a friend request!",
|
||||
FRIEND_IMAGE..tostring(fromPlayer.userId).."&x=48&y=48")
|
||||
notificationFrame.Position = UDim2.new(1, 4, 1, -(NOTIFICATION_Y_OFFSET + 2) * 1.5 - 4)
|
||||
--
|
||||
local acceptButton = createTextButton("AcceptButton", "Accept", UDim2.new(0, 0, 1, 2))
|
||||
acceptButton.Parent = notificationFrame
|
||||
|
||||
local declineButton = createTextButton("DeclineButton", "Decline", UDim2.new(0.5, 2, 1, 2))
|
||||
declineButton.Parent = notificationFrame
|
||||
|
||||
acceptButton.MouseButton1Click:connect(function()
|
||||
if not notification.IsActive then return end
|
||||
if notification then
|
||||
removeNotification(notification)
|
||||
end
|
||||
LocalPlayer:RequestFriendship(fromPlayer)
|
||||
end)
|
||||
|
||||
declineButton.MouseButton1Click:connect(function()
|
||||
if not notification.IsActive then return end
|
||||
if notification then
|
||||
removeNotification(notification)
|
||||
end
|
||||
LocalPlayer:RevokeFriendship(fromPlayer)
|
||||
FriendRequestBlacklist[fromPlayer] = true
|
||||
end)
|
||||
|
||||
notification.Frame = notificationFrame
|
||||
notification.Duration = 8
|
||||
notification.IsFriend = true
|
||||
insertNotifcation(notification)
|
||||
end
|
||||
|
||||
--[[ Friend Notifications ]]--
|
||||
local function onFriendRequestEvent(fromPlayer, toPlayer, event)
|
||||
if fromPlayer ~= LocalPlayer and toPlayer ~= LocalPlayer then return end
|
||||
--
|
||||
if fromPlayer == LocalPlayer then
|
||||
if event == Enum.FriendRequestEvent.Accept then
|
||||
sendNotifcation("New Friend", "You are now friends with "..toPlayer.Name.."!",
|
||||
FRIEND_IMAGE..tostring(toPlayer.userId).."&x=48&y=48", DEFAULT_NOTIFICATION_DURATION, nil)
|
||||
end
|
||||
elseif toPlayer == LocalPlayer then
|
||||
if event == Enum.FriendRequestEvent.Issue then
|
||||
if FriendRequestBlacklist[fromPlayer] then return end
|
||||
sendFriendNotification(fromPlayer)
|
||||
elseif event == Enum.FriendRequestEvent.Accept then
|
||||
sendNotifcation("New Friend", "You are now friends with "..fromPlayer.Name.."!",
|
||||
FRIEND_IMAGE..tostring(fromPlayer.userId).."&x=48&y=48", DEFAULT_NOTIFICATION_DURATION, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Player Points Notifications ]]--
|
||||
local function onPointsAwarded(userId, pointsAwarded, userBalanceInGame, userTotalBalance)
|
||||
if pointsNotificationsActive and userId == LocalPlayer.userId then
|
||||
if pointsAwarded == 1 then
|
||||
sendNotifcation("Point Awarded", "You received "..tostring(pointsAwarded).." point!", PLAYER_POINTS_IMG, DEFAULT_NOTIFICATION_DURATION, nil)
|
||||
elseif pointsAwarded > 0 then
|
||||
sendNotifcation("Points Awarded", "You received "..tostring(pointsAwarded).." points!", PLAYER_POINTS_IMG, DEFAULT_NOTIFICATION_DURATION, nil)
|
||||
elseif pointsAwarded < 0 then
|
||||
sendNotifcation("Points Lost", "You lost "..tostring(-pointsAwarded).." points!", PLAYER_POINTS_IMG, DEFAULT_NOTIFICATION_DURATION, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Badge Notification ]]--
|
||||
local function onBadgeAwarded(message, userId, badgeId)
|
||||
if badgesNotificationsActive and userId == LocalPlayer.userId then
|
||||
sendNotifcation("Badge Awarded", message, BADGE_IMG, DEFAULT_NOTIFICATION_DURATION, nil)
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Graphics Changes Notification ]]--
|
||||
function onGameSettingsChanged(property, amount)
|
||||
if property == "SavedQualityLevel" then
|
||||
local level = GameSettings.SavedQualityLevel.Value + amount
|
||||
if level > 10 then
|
||||
level = 10
|
||||
elseif level < 1 then
|
||||
level = 1
|
||||
end
|
||||
-- value of 0 is automatic, we do not want to send a notification in that case
|
||||
if level > 0 and level ~= CurrentGraphicsQualityLevel then
|
||||
if level > CurrentGraphicsQualityLevel then
|
||||
sendNotifcation("Graphics Quality", "Increased to ("..tostring(level)..")", "", 2, nil)
|
||||
else
|
||||
sendNotifcation("Graphics Quality", "Decreased to ("..tostring(level)..")", "", 2, nil)
|
||||
end
|
||||
CurrentGraphicsQualityLevel = level
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Connections ]]--
|
||||
if not isTenFootInterface then
|
||||
Players.FriendRequestEvent:connect(onFriendRequestEvent)
|
||||
PointsService.PointsAwarded:connect(onPointsAwarded)
|
||||
BadgeService.BadgeAwarded:connect(onBadgeAwarded)
|
||||
--GameSettings.Changed:connect(onGameSettingsChanged)
|
||||
game.GraphicsQualityChangeRequest:connect(function(graphicsIncrease) --graphicsIncrease is a boolean
|
||||
onGameSettingsChanged("SavedQualityLevel", graphicsIncrease == true and 1 or -1)
|
||||
end)
|
||||
end
|
||||
|
||||
GuiService.SendCoreUiNotification = function(title, text)
|
||||
local notification = createNotification(title, text, "")
|
||||
notification.BackgroundTransparency = .5
|
||||
notification.Size = UDim2.new(.5, 0, .1, 0)
|
||||
notification.Position = UDim2.new(.25, 0, -0.1, 0)
|
||||
notification.NotificationTitle.FontSize = Enum.FontSize.Size36
|
||||
notification.NotificationText.FontSize = Enum.FontSize.Size24
|
||||
notification.Parent = RbxGui
|
||||
notification:TweenPosition(UDim2.new(.25, 0, 0, 0), EASE_DIR, EASE_STYLE, TWEEN_TIME, true)
|
||||
wait(5)
|
||||
if notification then
|
||||
notification:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Market Place Events ]]--
|
||||
-- This is used for when a player calls CreatePlaceInPlayerInventoryAsync
|
||||
local function onClientLuaDialogRequested(msg, accept, decline)
|
||||
PopupText.Text = msg
|
||||
--
|
||||
local acceptCn, declineCn = nil, nil
|
||||
local function disconnectCns()
|
||||
if acceptCn then acceptCn:disconnect() end
|
||||
if declineCn then declineCn:disconnect() end
|
||||
--
|
||||
GuiService:RemoveCenterDialog(PopupFrame)
|
||||
PopupFrame.Visible = false
|
||||
end
|
||||
|
||||
acceptCn = PopupAcceptButton.MouseButton1Click:connect(function()
|
||||
disconnectCns()
|
||||
MarketplaceService:SignalServerLuaDialogClosed(true)
|
||||
end)
|
||||
declineCn = PopupDeclineButton.MouseButton1Click:connect(function()
|
||||
disconnectCns()
|
||||
MarketplaceService:SignalServerLuaDialogClosed(false)
|
||||
end)
|
||||
|
||||
local centerDialogSuccess = pcall(
|
||||
function()
|
||||
GuiService:AddCenterDialog(PopupFrame, Enum.CenterDialogType.QuitDialog,
|
||||
function()
|
||||
PopupOKButton.Visible = false
|
||||
PopupAcceptButton.Visible = true
|
||||
PopupDeclineButton.Visible = true
|
||||
PopupAcceptButton.Text = accept
|
||||
PopupDeclineButton.Text = decline
|
||||
PopupFrame.Visible = true
|
||||
end,
|
||||
function()
|
||||
PopupFrame.Visible = false
|
||||
end)
|
||||
end)
|
||||
|
||||
if not centerDialogSuccess then
|
||||
PopupFrame.Visible = true
|
||||
PopupAcceptButton.Text = accept
|
||||
PopupDeclineButton.Text = decline
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
MarketplaceService.ClientLuaDialogRequested:connect(onClientLuaDialogRequested)
|
||||
|
||||
--[[ Developer customization API ]]--
|
||||
local function createDeveloperNotification(notificationTable)
|
||||
if type(notificationTable) == "table" then
|
||||
if type(notificationTable.Title) == "string" and type(notificationTable.Text) == "string" then
|
||||
local iconImage = (type(notificationTable.Icon) == "string" and notificationTable.Icon or "")
|
||||
local duration = (type(notificationTable.Duration) == "number" and notificationTable.Duration or DEFAULT_NOTIFICATION_DURATION)
|
||||
local success, bindable = pcall(function() return (notificationTable.Callback:IsA("BindableFunction") and notificationTable.Callback or nil) end)
|
||||
local button1Text = (type(notificationTable.Button1) == "string" and notificationTable.Button1 or "")
|
||||
local button2Text = (type(notificationTable.Button2) == "string" and notificationTable.Button2 or "")
|
||||
sendNotifcation(notificationTable.Title, notificationTable.Text, iconImage, duration, bindable, button1Text, button2Text)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if allowDisableNotifications then
|
||||
game:WaitForChild("StarterGui"):RegisterSetCore("PointsNotificationsActive", function(value) if type(value) == "boolean" then pointsNotificationsActive = value end end)
|
||||
game:WaitForChild("StarterGui"):RegisterSetCore("BadgesNotificationsActive", function(value) if type(value) == "boolean" then badgesNotificationsActive = value end end)
|
||||
else
|
||||
game:WaitForChild("StarterGui"):RegisterSetCore("PointsNotificationsActive", function() end)
|
||||
game:WaitForChild("StarterGui"):RegisterSetCore("BadgesNotificationsActive", function() end)
|
||||
end
|
||||
|
||||
game:WaitForChild("StarterGui"):RegisterGetCore("PointsNotificationsActive", function() return pointsNotificationsActive end)
|
||||
game:WaitForChild("StarterGui"):RegisterGetCore("BadgesNotificationsActive", function() return badgesNotificationsActive end)
|
||||
|
||||
if allowSendNotifications then
|
||||
game:WaitForChild("StarterGui"):RegisterSetCore("SendNotification", createDeveloperNotification)
|
||||
else
|
||||
game:WaitForChild("StarterGui"):RegisterSetCore("SendNotification", function() end)
|
||||
end
|
||||
|
||||
if not isTenFootInterface then
|
||||
local gamepadMenu = RobloxGui:WaitForChild("CoreScripts/GamepadMenu")
|
||||
local gamepadNotifications = gamepadMenu:FindFirstChild("GamepadNotifications")
|
||||
while not gamepadNotifications do
|
||||
wait()
|
||||
gamepadNotifications = gamepadMenu:FindFirstChild("GamepadNotifications")
|
||||
end
|
||||
|
||||
local leaveNotificationFunc = function(name, state, inputObject)
|
||||
if state ~= Enum.UserInputState.Begin then return end
|
||||
|
||||
if GuiService.SelectedCoreObject:IsDescendantOf(NotificationFrame) then
|
||||
GuiService.SelectedCoreObject = nil
|
||||
end
|
||||
|
||||
ContextActionService:UnbindCoreAction("LeaveNotificationSelection")
|
||||
end
|
||||
|
||||
gamepadNotifications.Event:connect(function(isSelected)
|
||||
if not isSelected then return end
|
||||
|
||||
isPaused = true
|
||||
local notifications = NotificationFrame:GetChildren()
|
||||
for i = 1, #notifications do
|
||||
local noteComponents = notifications[i]:GetChildren()
|
||||
for j = 1, #noteComponents do
|
||||
if noteComponents[j]:IsA("GuiButton") and noteComponents[j].Visible then
|
||||
GuiService.SelectedCoreObject = noteComponents[j]
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if GuiService.SelectedCoreObject then
|
||||
ContextActionService:BindCoreAction("LeaveNotificationSelection", leaveNotificationFunc, false, Enum.KeyCode.ButtonB)
|
||||
else
|
||||
isPaused = false
|
||||
local utility = require(RobloxGui.Modules.Utility)
|
||||
local okPressedFunc = function() end
|
||||
utility:ShowAlert("You have no notifications", "Ok", settingsHub, okPressedFunc, true)
|
||||
end
|
||||
end)
|
||||
|
||||
GuiService.Changed:connect(function(prop)
|
||||
if prop == "SelectedCoreObject" then
|
||||
if not GuiService.SelectedCoreObject or not GuiService.SelectedCoreObject:IsDescendantOf(NotificationFrame) then
|
||||
isPaused = false
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local UserInputService = game:GetService('UserInputService')
|
||||
local Platform = UserInputService:GetPlatform()
|
||||
local Modules = RobloxGui:FindFirstChild('Modules')
|
||||
if Platform == Enum.Platform.XBoxOne then
|
||||
-- Platform hook for controller connection events
|
||||
-- Displays overlay to user on controller connection lost
|
||||
local PlatformService = nil
|
||||
pcall(function() PlatformService = game:GetService('PlatformService') end)
|
||||
if PlatformService and Modules then
|
||||
local controllerStateManager = require(Modules:FindFirstChild('ControllerStateManager'))
|
||||
if controllerStateManager then
|
||||
controllerStateManager:Initialize()
|
||||
|
||||
-- retro check in case of controller disconnect while loading
|
||||
-- for now, gamepad1 is always mapped to the active user
|
||||
controllerStateManager:CheckUserConnected()
|
||||
end
|
||||
end
|
||||
end
|
||||
File diff suppressed because it is too large
Load Diff
1261
client/common/content/scripts/CoreScripts/2016/Topbar.lua
Normal file
1261
client/common/content/scripts/CoreScripts/2016/Topbar.lua
Normal file
File diff suppressed because it is too large
Load Diff
160
client/common/content/scripts/CoreScripts/2016/VehicleHud.lua
Normal file
160
client/common/content/scripts/CoreScripts/2016/VehicleHud.lua
Normal file
@@ -0,0 +1,160 @@
|
||||
--[[
|
||||
// Filename: VehicleHud.lua
|
||||
// Version 1.0
|
||||
// Written by: jmargh
|
||||
// Description: Implementation of the VehicleSeat HUD
|
||||
|
||||
// TODO:
|
||||
Once this is live and stable, move to PlayerScripts as module
|
||||
]]
|
||||
local RunService = game:GetService('RunService')
|
||||
local Players = game:GetService('Players')
|
||||
while not Players.LocalPlayer do
|
||||
wait()
|
||||
end
|
||||
local LocalPlayer = Players.LocalPlayer
|
||||
local RobloxGui = script.Parent
|
||||
local CurrentVehicleSeat = nil
|
||||
local VehicleSeatRenderCn = nil
|
||||
local VehicleSeatHUDChangedCn = nil
|
||||
|
||||
local RobloxGui = game:GetService("CoreGui"):WaitForChild("RobloxGui")
|
||||
RobloxGui:WaitForChild("Modules"):WaitForChild("TenFootInterface")
|
||||
local isTenFootInterface = require(RobloxGui.Modules.TenFootInterface):IsEnabled()
|
||||
|
||||
|
||||
--[[ Images ]]--
|
||||
local VEHICLE_HUD_BG = 'ayaasset://textures/ui/Vehicle/SpeedBarBKG.png'
|
||||
local SPEED_BAR_EMPTY = 'ayaasset://textures/ui/Vehicle/SpeedBarEmpty.png'
|
||||
local SPEED_BAR = 'ayaasset://textures/ui/Vehicle/SpeedBar.png'
|
||||
|
||||
--[[ Constants ]]--
|
||||
local BOTTOM_OFFSET = (isTenFootInterface and 100 or 70)
|
||||
|
||||
--[[ Gui Creation ]]--
|
||||
local function createImageLabel(name, size, position, image, parent)
|
||||
local imageLabel = Instance.new('ImageLabel')
|
||||
imageLabel.Name = name
|
||||
imageLabel.Size = size
|
||||
imageLabel.Position = position
|
||||
imageLabel.BackgroundTransparency = 1
|
||||
imageLabel.Image = image
|
||||
imageLabel.Parent = parent
|
||||
|
||||
return imageLabel
|
||||
end
|
||||
|
||||
local function createTextLabel(name, alignment, text, parent)
|
||||
local textLabel = Instance.new('TextLabel')
|
||||
textLabel.Name = name
|
||||
textLabel.Size = UDim2.new(1, -4, 0, (isTenFootInterface and 50 or 20))
|
||||
textLabel.Position = UDim2.new(0, 2, 0, (isTenFootInterface and -50 or -20))
|
||||
textLabel.BackgroundTransparency = 1
|
||||
textLabel.TextXAlignment = alignment
|
||||
textLabel.Font = Enum.Font.SourceSans
|
||||
textLabel.FontSize = (isTenFootInterface and Enum.FontSize.Size48 or Enum.FontSize.Size18)
|
||||
textLabel.TextColor3 = Color3.new(1, 1, 1)
|
||||
textLabel.TextStrokeTransparency = 0.5
|
||||
textLabel.TextStrokeColor3 = Color3.new(49/255, 49/255, 49/255)
|
||||
textLabel.Text = text
|
||||
textLabel.Parent = parent
|
||||
|
||||
return textLabel
|
||||
end
|
||||
|
||||
local VehicleHudFrame = Instance.new('Frame')
|
||||
VehicleHudFrame.Name = "VehicleHudFrame"
|
||||
VehicleHudFrame.Size = UDim2.new(0, (isTenFootInterface and 316 or 158), 0, (isTenFootInterface and 50 or 14))
|
||||
VehicleHudFrame.Position = UDim2.new(0.5, -(VehicleHudFrame.Size.X.Offset/2), 1, -BOTTOM_OFFSET - VehicleHudFrame.Size.Y.Offset)
|
||||
VehicleHudFrame.BackgroundTransparency = 1
|
||||
VehicleHudFrame.Visible = false
|
||||
VehicleHudFrame.Parent = RobloxGui
|
||||
|
||||
local speedBarClippingFrame = Instance.new("Frame")
|
||||
speedBarClippingFrame.Name = "SpeedBarClippingFrame"
|
||||
speedBarClippingFrame.Size = UDim2.new(0, 0, 0, (isTenFootInterface and 24 or 4))
|
||||
speedBarClippingFrame.Position = UDim2.new(0.5, (isTenFootInterface and -142 or -71), 0.5, (isTenFootInterface and -13 or -2))
|
||||
speedBarClippingFrame.BackgroundTransparency = 1
|
||||
speedBarClippingFrame.ClipsDescendants = true
|
||||
speedBarClippingFrame.Parent = VehicleHudFrame
|
||||
|
||||
local HudBG = createImageLabel("HudBG", UDim2.new(1, 0, 1, 0), UDim2.new(0, 0, 0, 1), VEHICLE_HUD_BG, VehicleHudFrame)
|
||||
local SpeedBG = createImageLabel("SpeedBG", UDim2.new(0, (isTenFootInterface and 284 or 142), 0, (isTenFootInterface and 24 or 4)), UDim2.new(0.5, (isTenFootInterface and -142 or -71), 0.5, (isTenFootInterface and -13 or -2)), SPEED_BAR_EMPTY, VehicleHudFrame)
|
||||
local SpeedBarImage = createImageLabel("SpeedBarImage", UDim2.new(0, (isTenFootInterface and 284 or 142), 1, 0), UDim2.new(0, 0, 0, 0), SPEED_BAR, speedBarClippingFrame)
|
||||
SpeedBarImage.ZIndex = 2
|
||||
|
||||
local SpeedLabel = createTextLabel("SpeedLabel", Enum.TextXAlignment.Left, "Speed", VehicleHudFrame)
|
||||
local SpeedText = createTextLabel("SpeedText", Enum.TextXAlignment.Right, "0", VehicleHudFrame)
|
||||
|
||||
--[[ Local Functions ]]--
|
||||
local function getHumanoid()
|
||||
local character = LocalPlayer and LocalPlayer.Character
|
||||
if character then
|
||||
for _,child in pairs(character:GetChildren()) do
|
||||
if child:IsA('Humanoid') then
|
||||
return child
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function onRenderStepped()
|
||||
if CurrentVehicleSeat then
|
||||
local speed = CurrentVehicleSeat.Velocity.magnitude
|
||||
SpeedText.Text = tostring(math.min(math.floor(speed), 9999))
|
||||
local drawSize = math.floor((speed / CurrentVehicleSeat.MaxSpeed) * SpeedBG.Size.X.Offset)
|
||||
drawSize = math.min(drawSize, SpeedBG.Size.X.Offset)
|
||||
speedBarClippingFrame.Size = UDim2.new(0, drawSize, 0, (isTenFootInterface and 24 or 4))
|
||||
end
|
||||
end
|
||||
|
||||
local function onVehicleSeatChanged(property)
|
||||
if property == "HeadsUpDisplay" then
|
||||
VehicleHudFrame.Visible = not VehicleHudFrame.Visible
|
||||
end
|
||||
end
|
||||
|
||||
local function onSeated(active, currentSeatPart)
|
||||
if active then
|
||||
-- TODO: Clean up when new API is live for a while
|
||||
if currentSeatPart and currentSeatPart:IsA('VehicleSeat') then
|
||||
CurrentVehicleSeat = currentSeatPart
|
||||
else
|
||||
local camSubject = workspace.CurrentCamera.CameraSubject
|
||||
if camSubject and camSubject:IsA('VehicleSeat') then
|
||||
CurrentVehicleSeat = camSubject
|
||||
end
|
||||
end
|
||||
if CurrentVehicleSeat then
|
||||
VehicleHudFrame.Visible = CurrentVehicleSeat.HeadsUpDisplay
|
||||
VehicleSeatRenderCn = RunService.RenderStepped:connect(onRenderStepped)
|
||||
VehicleSeatHUDChangedCn = CurrentVehicleSeat.Changed:connect(onVehicleSeatChanged)
|
||||
end
|
||||
else
|
||||
if CurrentVehicleSeat then
|
||||
VehicleHudFrame.Visible = false
|
||||
CurrentVehicleSeat = nil
|
||||
if VehicleSeatRenderCn then
|
||||
VehicleSeatRenderCn:disconnect()
|
||||
VehicleSeatRenderCn = nil
|
||||
end
|
||||
if VehicleSeatHUDChangedCn then
|
||||
VehicleSeatHUDChangedCn:disconnect()
|
||||
VehicleSeatHUDChangedCn = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function connectSeated()
|
||||
local humanoid = getHumanoid()
|
||||
while not humanoid do
|
||||
wait()
|
||||
humanoid = getHumanoid()
|
||||
end
|
||||
humanoid.Seated:connect(onSeated)
|
||||
end
|
||||
connectSeated()
|
||||
LocalPlayer.CharacterAdded:connect(function(character)
|
||||
connectSeated()
|
||||
end)
|
||||
Reference in New Issue
Block a user