diff --git a/public/asset/9 b/public/asset/9 index 82057c2..ec53dd7 100644 --- a/public/asset/9 +++ b/public/asset/9 @@ -9,7 +9,7 @@ -- Utility functions + Globals local function WaitForChild(parent, childName) while parent:FindFirstChild(childName) == nil do - parent.ChildAdded:wait(0.03) + wait() end return parent[childName] end @@ -18,30 +18,10 @@ local function typedef(obj) return obj end -local function IsPhone() - local cGui = Game:GetService('CoreGui') - local rGui = WaitForChild(cGui, 'RobloxGui') - if rGui.AbsoluteSize.Y < 600 then - return true - end - return false -end - --- Users can use enough white spaces to spoof chatting as other players --- This function removes trailing and leading white spaces --- AFAIK, there is no reason for spam white spaces -local function StringTrim(str) - -- %S is whitespaces - -- When we find the first non space character defined by ^%s - -- we yank out anything in between that and the end of the string - -- Everything else is replaced with %1 which is essentially nothing - return (str:gsub("^%s*(.-)%s*$", "%1")) -end - -while Game.Players.LocalPlayer == nil do wait(0.03) end +while Game.Players.LocalPlayer == nil do wait() end local Player = Game.Players.LocalPlayer -while Player.Character == nil do wait(0.03) end +while Player.Character == nil do wait() end local RbxUtility = LoadLibrary('RbxUtility') local Gui = typedef(RbxUtility) local Camera = Game.Workspace.CurrentCamera @@ -142,13 +122,12 @@ local Chat = { -- Stores all the values for configuring chat Configuration = { - FontSize = Enum.FontSize.Size12, -- 10 is good + FontSize = Enum.FontSize.Size10, -- 10 is good -- Also change this when you are changing the above, this is suboptimal but so is our interface to find FontSize - NumFontSize = 12, - HistoryLength = 20, -- stores up to 50 of the last chat messages for you to scroll through, + NumFontSize = 10, + HistoryLength = 50, -- stores up to 50 of the last chat messages for you to scroll through, Size = UDim2.new(0.38, 0, 0.20, 0), MessageColor = Color3.new(1, 1, 1), - AdminMessageColor = Color3.new(1, 215/255, 0), XScale = 0.025, LifeTime = 45, Position = UDim2.new(0, 2, 0.05, 0), @@ -163,15 +142,6 @@ local Chat = { MouseOnFrame = false, GotFocus = false, - Messages_List = {}, - MessageThread = nil, - - Admins_List = {'Sorcus', 'Shedletsky', 'Telamon', 'Tarabyte', 'StickMasterLuke', 'OnlyTwentyCharacters', 'FusRoblox', 'SolarCrane', - 'HotThoth', 'JediTkacheff', 'Builderman', 'Brighteyes', 'ReeseMcblox', 'GemLocker', 'GongfuTiger', 'Erik.Cassel', 'Matt Dusek', 'Keith', - 'Totbl', 'LordRugDump', 'David.Baszucki', 'Dbapostle', 'DaveYorkRBX', 'nJay', 'OstrichSized', 'TobotRobot', 'twberg', 'ROBLOX', 'RBAdam', 'Doughtless', - 'Anaminus', 'Stravant', 'Cr3470r', 'CodeWriter', 'Games', 'AcesWayUpHigh', 'Phil' - }, - SafeChat_List = { ['Use the Chat menu to talk to me.'] = {'/sc 0', true}, ['I can only see menu chats.'] = {'/sc 1', true}, @@ -444,8 +414,7 @@ local Chat = { } }, CreateEnum('SafeChat'){'Level1', 'Level2', 'Level3'}, - SafeChatTree = {}, - TempSpaceLabel = nil + SafeChatTree = {} } --------------------------------------------------- @@ -517,7 +486,7 @@ end -- Scrolling function Chat:ScrollQueue(value) - --[[for i = 1, #self.MessageQueue do + for i = 1, #self.MessageQueue do if self.MessageQueue[i] then for _, label in pairs(self.MessageQueue[i]) do local next = self.MessageQueue[i].Next @@ -531,43 +500,37 @@ function Chat:ScrollQueue(value) end end end - end ]] + end end -- Handles the rendering of the text objects in their appropriate places -function Chat:UpdateQueue(field, diff) - -- Have to do some sort of correction here +function Chat:UpdateQueue(field) + -- Have to do some sort of correction here for i = #self.MessageQueue, 1, -1 do if self.MessageQueue[i] then for _, label in pairs(self.MessageQueue[i]) do if label and type(label) ~= 'table' and type(label) ~= 'number' then - if label:IsA('TextLabel') or label:IsA('TextButton') then - if diff then - label.Position = label.Position - UDim2.new(0, 0, diff, 0) - else - if field == self.MessageQueue[i] then - label.Position = UDim2.new(self.Configuration.XScale, 0, label.Position.Y.Scale - field['Message'].Size.Y.Scale , 0) - -- Just to show up popping effect for the latest message in chat - Spawn(function() - wait(0.05) - while label.TextTransparency >= 0 do - label.TextTransparency = label.TextTransparency - 0.2 - wait(0.03) - end - if label == field['Message'] then - label.TextStrokeTransparency = 0.8 - else - label.TextStrokeTransparency = 1.0 - end - end) - else - label.Position = UDim2.new(self.Configuration.XScale, 0, label.Position.Y.Scale - field['Message'].Size.Y.Scale, 0) - end - if label.Position.Y.Scale < -0.01 then - -- NOTE: Remove this fix when Textbounds is fixed - label.Visible = false - label:Destroy() - end + if label:IsA('TextLabel') or label:IsA('TextButton') then + if self.SlotPositions_List[i] and self.MessageQueue[i] ~= field then + label.Position = self.SlotPositions_List[i][1] - UDim2.new(0, 0, field['Message'].Size.Y.Scale, 0) + label.Position = UDim2.new(self.Configuration.XScale, 0, label.Position.Y.Scale, 0) + else + label.Position = UDim2.new(self.Configuration.XScale, 0, label.Position.Y.Scale - field['Message'].Size.Y.Scale , 0) + end + if field == self.MessageQueue[i] then + -- Just to show up popping effect for the latest message in chat + Spawn(function() + wait(0.15) + while label.TextTransparency > 0 do + label.TextTransparency = label.TextTransparency - 0.2 + wait() + end + end) + end + if label.Position.Y.Scale < -0.05 or label.Position.Y.Scale > 1.0 then + label.TextTransparency = 1.0 + else + label.TextTransparency = 0.0 end end end @@ -576,11 +539,171 @@ function Chat:UpdateQueue(field, diff) end end +function Chat:InsertIntoQueue(field) + -- This is a ring buffer where insertions happen at the beginning + -- One optimization here would be to not copy the queue by reference + -- And reuse the same queue and do the insertion in place + -- But rendering code must be changed accordingly and this becomes rather hard to manage + -- plus the effects are minimal + -- TODO: Revist if this becomes a problem for optimization + local tmpQueue = self.MessageQueue + self.MessageQueue = {} + self.MessageQueue[1] = field + self.MessageQueue[1].Previous = tmpQueue[i] + self.MessageQueue[1].Next = nil + + self.SlotPositions_List = {} + self.SlotPositions_List[1] = {field.Position, field.Size} + + if tmpQueue[self.Configuration.HistoryLength] then + if tmpQueue[self.Configuration.HistoryLength]['Player'] then + tmpQueue[self.Configuration.HistoryLength]['Player']:Destroy() + end + if tmpQueue[self.Configuration.HistoryLength]['Message'] then + tmpQueue[self.Configuration.HistoryLength]['Message']:Destroy() + end + tmpQueue[self.Configuration.HistoryLength] = nil + end + + for i = 1, self.Configuration.HistoryLength - 1 do + if tmpQueue[i] and tmpQueue[i]['Player'] and tmpQueue[i]['Player'].Parent then + table.insert(self.MessageQueue, tmpQueue[i]) + self.MessageQueue[#self.MessageQueue].Previous = tmpQueue[i+1] or nil + self.MessageQueue[#self.MessageQueue].Next = tmpQueue[i-1] or nil + + self.SlotPositions_List[#self.MessageQueue] = {tmpQueue[i]['Message'].Position, tmpQueue[i]['Message'].Size} + end + end + -- Now, render the queue + Chat:UpdateQueue(field) +end + function Chat:CreateScrollBar() -- Code for scrolling is in here, partially, but scroll bar drawing isn't drawn -- TODO: Implement end +function Chat:FocusOnChatBar() + if self.ClickToChatButton then + self.ClickToChatButton.Visible = false + end + + self.GotFocus = true + if self.Frame['Background'] then + self.Frame.Background.Visible = false + end + self.ChatBar:CaptureFocus() +end + +-- For touch devices we create a button instead +function Chat:CreateTouchButton() + self.ChatTouchFrame = Gui.Create'Frame' + { + Name = 'ChatTouchFrame'; + Size = UDim2.new(0, 128, 0, 32); + Position = UDim2.new(0, 88, 0, 0); + BackgroundTransparency = 1.0; + Parent = self.Gui; + + Gui.Create'ImageButton' + { + Name = 'ChatLabel'; + Size = UDim2.new(0, 74, 0, 28); + Position = UDim2.new(0, 0, 0, 0); + BackgroundTransparency = 1.0; + ZIndex = 2.0; + }; + + Gui.Create'ImageLabel' + { + Name = 'Background'; + Size = UDim2.new(1, 0, 1, 0); + Position = UDim2.new(0, 0, 0, 0); + BackgroundTransparency = 1.0; + Image = 'http://morblox.us/asset/?id=97078724' + }; + } + self.TapToChatLabel = self.ChatTouchFrame.ChatLabel + self.TouchLabelBackground = self.ChatTouchFrame.Background + + self.ChatBar = Gui.Create'TextBox' + { + Name = 'ChatBar'; + Size = UDim2.new(1, 0, 0.2, 0); + Position = UDim2.new(0, 0, 0.8, 0); + Text = ""; + ZIndex = 1.0; + BackgroundTransparency = 1.0; + Parent = self.Frame; + TextXAlignment = Enum.TextXAlignment.Left; + TextColor3 = Color3.new(1, 1, 1); + ClearTextOnFocus = false; + }; + + self.TapToChatLabel.MouseButton1Click:connect(function() + self.TapToChatLabel.Visible = false + --self.ChatBar.Visible = true + self.Frame.Background.Visible = true + self.ChatBar:CaptureFocus() + self.GotFocus = true + if self.TouchLabelBackground then + self.TouchLabelBackground.Visible = false + end + end) +end + +-- Non touch devices, create the bottom chat bar +function Chat:CreateChatBar() + -- okay now we do + local status, result = pcall(function() return GuiService.UseLuaChat end) + if status and result then + self.ClickToChatButton = Gui.Create'TextButton' + { + Name = 'ClickToChat'; + Size = UDim2.new(1, 0, 0, 20); + BackgroundTransparency = 1.0; + ZIndex = 2.0; + Parent = self.Gui; + Text = "To chat click here or press \"/\" key"; + TextColor3 = Color3.new(1, 1, 0.9); + Position = UDim2.new(0, 0, 1, 0); + TextXAlignment = Enum.TextXAlignment.Left; + FontSize = Enum.FontSize.Size12; + } + + self.ChatBar = Gui.Create'TextBox' + { + Name = 'ChatBar'; + Size = UDim2.new(1, 0, 0, 20); + Position = UDim2.new(0, 0, 1, 0); + Text = ""; + ZIndex = 1.0; + BackgroundColor3 = Color3.new(0, 0, 0); + BackgroundTransparency = 0.25; + Parent = self.Gui; + TextXAlignment = Enum.TextXAlignment.Left; + TextColor3 = Color3.new(1, 1, 1); + FontSize = Enum.FontSize.Size12; + ClearTextOnFocus = false; + Text = ''; + }; + + -- Engine has code to offset the entire world, so if we do it by -20 pixels nothing gets in our chat's way + GuiService:SetGlobalSizeOffsetPixel(0, -20) + -- CHatHotKey is '/' + GuiService:AddSpecialKey(Enum.SpecialKey.ChatHotkey) + GuiService.SpecialKeyPressed:connect(function(key) + if key == Enum.SpecialKey.ChatHotkey then + Chat:FocusOnChatBar() + end + end) + + self.ClickToChatButton.MouseButton1Click:connect(function() + Chat:FocusOnChatBar() + end) + end +end + -- For scrolling, to see if we hit the bounds so that we can stop it from scrolling anymore function Chat:CheckIfInBounds(value) if #Chat.MessageQueue < 3 then @@ -600,109 +723,39 @@ end -- This is to precompute all playerName space strings -- This is used to offset the message by exactly this + 2 spacestrings function Chat:ComputeSpaceString(pLabel) + local tLabel = Gui.Create'TextButton' + { + Size = UDim2.new(0, pLabel.AbsoluteSize.X, 0, pLabel.AbsoluteSize.Y); + FontSize = self.Configuration.FontSize; + Parent = self.RenderFrame; + BackgroundTransparency = 1.0; + Text = nString; + }; local nString = " " - if not self.TempSpaceLabel then - self.TempSpaceLabel = Gui.Create'TextButton' - { - Size = UDim2.new(0, pLabel.AbsoluteSize.X, 0, pLabel.AbsoluteSize.Y); - FontSize = self.Configuration.FontSize; - Parent = self.RenderFrame; - BackgroundTransparency = 1.0; - Text = nString; - Name = 'SpaceButton' - }; - else - self.TempSpaceLabel.Text = nString - end - - while self.TempSpaceLabel.TextBounds.X < pLabel.TextBounds.X do + while tLabel.TextBounds.X < pLabel.TextBounds.X do nString = nString .. " " - self.TempSpaceLabel.Text = nString + tLabel.Text = nString end - nString = nString .. " " self.CachedSpaceStrings_List[pLabel.Text] = nString - self.TempSpaceLabel.Text = "" return nString end -- When the playerChatted event fires -- The message is what the player chatted -function Chat:UpdateChat(cPlayer, message) - local messageField = { - ['Player'] = cPlayer, - ['Message'] = message - } - if coroutine.status(Chat.MessageThread) == 'dead' then - --Chat.Messages_List = {} - table.insert(Chat.Messages_List, messageField) - Chat.MessageThread = coroutine.create(function() - for i = 1, #Chat.Messages_List do - local field = Chat.Messages_List[i] - Chat:CreateMessage(field['Player'], field['Message']) - end - Chat.Messages_List = {} - end) - coroutine.resume(Chat.MessageThread) - else - table.insert(Chat.Messages_List, messageField) - end -end - -function Chat:RecalculateSpacing() - --[[for i = 1, #self.MessageQueue do - local pLabel = self.MessageQueue[i]['Player'] - local mLabel = self.MessageQueue[i]['Message'] - - local prevYScale = mLabel.Size.Y.Scale - local prevText = mLabel.Text - mLabel.Text = prevText - - local heightField = mLabel.TextBounds.Y - - mLabel.Size = UDim2.new(1, 0, heightField/self.RenderFrame.AbsoluteSize.Y, 0) - pLabel.Size = mLabel.Size - - local diff = mLabel.Size.Y.Scale - prevYScale - - Chat:UpdateQueue(self.MessageQueue[i], diff) - end ]] -end - -function Chat:ApplyFilter(str) - --[[for _, word in pair(self.Filter_List) do - if string.find(str, word) then - str:gsub(word, '@#$^') - end - end ]] -end - --- NOTE: Temporarily disabled ring buffer to allow for chat to always wrap around -function Chat:CreateMessage(cPlayer, message) - local pName - if not cPlayer then - pName = '' - else - pName = cPlayer.Name - end - message = StringTrim(message) +function Chat:UpdateChat(cPlayer, message) + local pName = cPlayer.Name local pLabel local mLabel -- Our history stores upto 50 messages that is 100 textlabels -- If we ever hit the mark, which would be in every popular game btw -- we wrap around and reuse the labels if #self.MessageQueue > self.Configuration.HistoryLength then - --[[pLabel = self.MessageQueue[#self.MessageQueue]['Player'] + pLabel = self.MessageQueue[#self.MessageQueue]['Player'] mLabel = self.MessageQueue[#self.MessageQueue]['Message'] - pLabel.Text = pName .. ':' + pLabel.Text = pName pLabel.Name = pName - - local pColor - if cPlayer.Neutral then - pLabel.TextColor3 = Chat:ComputeChatColor(pName) - else - pLabel.TextColor3 = cPlayer.TeamColor.Color - end + pLabel.TextColor3 = Chat:ComputeChatColor(pName) local nString @@ -712,26 +765,18 @@ function Chat:CreateMessage(cPlayer, message) nString = self.CachedSpaceStrings_List[pName] end - mLabel.Text = "" mLabel.Name = pName .. " - message" mLabel.Text = nString .. message; - mLabel.Parent = nil - mLabel.Parent = self.RenderFrame - - mLabel.Position = UDim2.new(0, 0, 1, 0); - pLabel.Position = UDim2.new(0, 0, 1, 0);]] - -- Reinserted at the beginning, ring buffer self.MessageQueue[#self.MessageQueue] = nil - end - --else + else -- Haven't hit the mark yet, so keep creating - pLabel = Gui.Create'TextLabel' + pLabel = Gui.Create'TextButton' { Name = pName; Text = pName .. ":"; - TextColor3 = pColor; + TextColor3 = Chat:ComputeChatColor(pName); FontSize = Chat.Configuration.FontSize; TextXAlignment = Enum.TextXAlignment.Left; TextYAlignment = Enum.TextYAlignment.Top; @@ -742,16 +787,7 @@ function Chat:CreateMessage(cPlayer, message) TextTransparency = 1.0; Position = UDim2.new(0, 0, 1, 0); BorderSizePixel = 0.0; - TextStrokeColor3 = Color3.new(0.5, 0.5, 0.5); - TextStrokeTransparency = 0.75; - --Active = false; - }; - local pColor - if cPlayer.Neutral then - pLabel.TextColor3 = Chat:ComputeChatColor(pName) - else - pLabel.TextColor3 = cPlayer.TeamColor.Color - end + }; local nString @@ -761,49 +797,39 @@ function Chat:CreateMessage(cPlayer, message) nString = self.CachedSpaceStrings_List[pName] end - mLabel = Gui.Create'TextLabel' + mLabel = Gui.Create'TextButton' { Name = pName .. ' - message'; -- Max is 3 lines - Size = UDim2.new(1, 0, 0.5, 0); + Size = UDim2.new(1, 0, 0.5, 0); + Text = nString .. message; TextColor3 = Chat.Configuration.MessageColor; FontSize = Chat.Configuration.FontSize; TextXAlignment = Enum.TextXAlignment.Left; TextYAlignment = Enum.TextYAlignment.Top; - Text = ""; -- this is to stop when the engine reverts the swear words to default, which is button, ugh Parent = self.RenderFrame; TextWrapped = true; BackgroundTransparency = 1.0; TextTransparency = 1.0; Position = UDim2.new(0, 0, 1, 0); BorderSizePixel = 0.0; - TextStrokeColor3 = Color3.new(0, 0, 0); - --TextStrokeTransparency = 0.8; - --Active = false; }; - mLabel.Text = nString .. message; + end - if not pName then - pLabel.Text = '' - mLabel.TextColor3 = Color3.new(0, 0.4, 1.0) - end - --end + -- This is to find if we need to wrap the text around + -- Expensive, but works well and worthwhile + -- This will give beautiful multilines as well + local heightField = 0.1 * self.RenderFrame.AbsoluteSize.Y - for _, adminName in pairs(self.Admins_List) do - if string.lower(adminName) == string.lower(pName) then - mLabel.TextColor3 = self.Configuration.AdminMessageColor - end + while heightField < mLabel.TextBounds.Y do + heightField = heightField + 1 end pLabel.Visible = true mLabel.Visible = true - - -- This will give beautiful multilines as well - local heightField = mLabel.TextBounds.Y mLabel.Size = UDim2.new(1, 0, heightField/self.RenderFrame.AbsoluteSize.Y, 0) pLabel.Size = mLabel.Size - local yPixels = self.RenderFrame.AbsoluteSize.Y local yFieldSize = mLabel.TextBounds.Y @@ -812,18 +838,117 @@ function Chat:CreateMessage(cPlayer, message) queueField['Message'] = mLabel queueField['SpawnTime'] = tick() -- Used for identifying when to make the message invisible - table.insert(self.MessageQueue, 1, queueField) - Chat:UpdateQueue(queueField) + Chat:InsertIntoQueue(queueField) end -function Chat:ScreenSizeChanged() - wait() +function Chat:ScreenSizeChanged() while self.Frame.AbsoluteSize.Y > 120 do self.Frame.Size = self.Frame.Size - UDim2.new(0, 0, 0.005, 0) end - Chat:RecalculateSpacing() end +-- Create the initial Chat stuff +-- Done only once +function Chat:CreateGui() + self.Gui = WaitForChild(CoreGuiService, 'RobloxGui') + self.Frame = Gui.Create'Frame' + { + Name = 'ChatFrame'; + Size = self.Configuration.Size; + Position = UDim2.new(0, 0, 0, 5); + BackgroundTransparency = 1.0; + --ClipsDescendants = true; + ZIndex = 0.0; + Parent = self.Gui; + + Gui.Create'ImageLabel' + { + Name = 'Background'; + Image = 'http://morblox.us/asset/?id=97120937'; --96551212'; + Size = UDim2.new(1.3, 0, 1.64, 0); + Position = UDim2.new(0, 0, 0, 0); + BackgroundTransparency = 1.0; + ZIndex = 0.0; + Visible = false + }; + + Gui.Create'Frame' + { + Name = 'Border'; + Size = UDim2.new(1, 0, 0, 1); + Position = UDim2.new(0, 0, 0.8, 0); + BackgroundTransparency = 0.0; + BackgroundColor3 = Color3.new(236/255, 236/255, 236/255); + BorderSizePixel = 0.0; + Visible = false; + }; + + Gui.Create'Frame' + { + Name = 'ChatRenderFrame'; + Size = UDim2.new(1.02, 0, 1.01, 0); + Position = UDim2.new(0, 0, 0, 0); + BackgroundTransparency = 1.0; + ClipsDescendants = true; + ZIndex = 0.0; + Visible = false; + }; + }; + + + self.RenderFrame = self.Frame.ChatRenderFrame + if Chat:IsTouchDevice() then + self.Frame.Position = self.Configuration.Position; + self.RenderFrame.Size = UDim2.new(1, 0, 1, 0) + elseif self.Frame.AbsoluteSize.Y > 120 then + Chat:ScreenSizeChanged() + self.Gui.Changed:connect(function(property) + if property == 'AbsoluteSize' then + Chat:ScreenSizeChanged() + end + end) + end + + if Player.ChatMode == Enum.ChatMode.TextAndMenu then + if Chat:IsTouchDevice() then + Chat:CreateTouchButton() + else + Chat:CreateChatBar() + --Chat:CreateSafeChatGui() + end + + if self.ChatBar then + self.ChatBar.FocusLost:connect(function(enterPressed) + Chat.GotFocus = false + if Chat:IsTouchDevice() then + self.ChatBar.Visible = false + self.TapToChatLabel.Visible = true + + if self.TouchLabelBackground then + self.TouchLabelBackground.Visible = true + end + end + if enterPressed and self.ChatBar.Text ~= "" then + if PlayersService.ClassicChat then + pcall(function() PlayersService:Chat(self.ChatBar.Text) end) + elseif PlayersService.BubbleChat then + -- do nothing + end + if self.ClickToChatButton then + self.ClickToChatButton.Visible = true + end + self.ChatBar.Text = "" + end + Spawn(function() + wait(5.0) + if not Chat.GotFocus then + Chat.Frame.Background.Visible = false + end + end) + end) + end + end +end function Chat:FindButtonTree(scButton, rootList) local list = {} @@ -917,7 +1042,7 @@ function Chat:CreateSafeChatGui() Size = UDim2.new(0, 44, 0, 31); Position = UDim2.new(0, 1, 0.35, 0); BackgroundTransparency = 1.0; - Image = 'http://www.roblox.com/asset/?id=97080365'; + Image = 'http://morblox.us/asset/?id=97080365'; }; } @@ -928,249 +1053,7 @@ function Chat:CreateSafeChatGui() self.SafeChatButton.MouseButton1Click:connect(function() Chat:ToggleSafeChatMenu(self.SafeChatButton) end) -end - -function Chat:FocusOnChatBar() - if self.ClickToChatButton then - self.ClickToChatButton.Visible = false - end - - self.GotFocus = true - if self.Frame['Background'] then - self.Frame.Background.Visible = false - end - self.ChatBar:CaptureFocus() -end - --- For touch devices we create a button instead -function Chat:CreateTouchButton() - self.ChatTouchFrame = Gui.Create'Frame' - { - Name = 'ChatTouchFrame'; - Size = UDim2.new(0, 128, 0, 32); - Position = UDim2.new(0, 88, 0, 0); - BackgroundTransparency = 1.0; - Parent = self.Gui; - - Gui.Create'ImageButton' - { - Name = 'ChatLabel'; - Size = UDim2.new(0, 74, 0, 28); - Position = UDim2.new(0, 0, 0, 0); - BackgroundTransparency = 1.0; - ZIndex = 2.0; - }; - - Gui.Create'ImageLabel' - { - Name = 'Background'; - Size = UDim2.new(1, 0, 1, 0); - Position = UDim2.new(0, 0, 0, 0); - BackgroundTransparency = 1.0; - Image = 'http://www.roblox.com/asset/?id=97078724' - }; - } - self.TapToChatLabel = self.ChatTouchFrame.ChatLabel - self.TouchLabelBackground = self.ChatTouchFrame.Background - - self.ChatBar = Gui.Create'TextBox' - { - Name = 'ChatBar'; - Size = UDim2.new(1, 0, 0.2, 0); - Position = UDim2.new(0, 0, 0.8, 800); - Text = ""; - ZIndex = 1.0; - BackgroundTransparency = 1.0; - Parent = self.Frame; - TextXAlignment = Enum.TextXAlignment.Left; - TextColor3 = Color3.new(1, 1, 1); - ClearTextOnFocus = false; - }; - - self.TapToChatLabel.MouseButton1Click:connect(function() - self.TapToChatLabel.Visible = false - --self.ChatBar.Visible = true - --self.Frame.Background.Visible = true - self.ChatBar:CaptureFocus() - self.GotFocus = true - if self.TouchLabelBackground then - self.TouchLabelBackground.Visible = false - end - end) -end - --- Non touch devices, create the bottom chat bar -function Chat:CreateChatBar() - -- okay now we do - local status, result = pcall(function() return GuiService.UseLuaChat end) - if status and result then - self.ClickToChatButton = Gui.Create'TextButton' - { - Name = 'ClickToChat'; - Size = UDim2.new(1, 0, 0, 20); - BackgroundTransparency = 1.0; - ZIndex = 2.0; - Parent = self.Gui; - Text = "To chat click here or press \"/\" key"; - TextColor3 = Color3.new(1, 1, 0.9); - Position = UDim2.new(0, 0, 1, 0); - TextXAlignment = Enum.TextXAlignment.Left; - FontSize = Enum.FontSize.Size12; - } - - self.ChatBar = Gui.Create'TextBox' - { - Name = 'ChatBar'; - Size = UDim2.new(1, 0, 0, 20); - Position = UDim2.new(0, 0, 1, 0); - Text = ""; - ZIndex = 1.0; - BackgroundColor3 = Color3.new(0, 0, 0); - BackgroundTransparency = 0.25; - Parent = self.Gui; - TextXAlignment = Enum.TextXAlignment.Left; - TextColor3 = Color3.new(1, 1, 1); - FontSize = Enum.FontSize.Size12; - ClearTextOnFocus = false; - Text = ''; - }; - - -- Engine has code to offset the entire world, so if we do it by -20 pixels nothing gets in our chat's way - --GuiService:SetGlobalSizeOffsetPixel(0, -20) - local success, error = pcall(function() GuiService:SetGlobalGuiInset(0, 0, 0, 20) end) - if not success then - GuiService:SetGlobalSizeOffsetPixel(0, -20) - end - -- CHatHotKey is '/' - GuiService:AddSpecialKey(Enum.SpecialKey.ChatHotkey) - GuiService.SpecialKeyPressed:connect(function(key) - if key == Enum.SpecialKey.ChatHotkey then - Chat:FocusOnChatBar() - end - end) - - self.ClickToChatButton.MouseButton1Click:connect(function() - Chat:FocusOnChatBar() - end) - end -end - --- Create the initial Chat stuff --- Done only once -function Chat:CreateGui() - self.Gui = WaitForChild(CoreGuiService, 'RobloxGui') - self.Frame = Gui.Create'Frame' - { - Name = 'ChatFrame'; - --Size = self.Configuration.Size; - Size = UDim2.new(0, 500, 0, 120); - Position = UDim2.new(0, 0, 0, 5); - BackgroundTransparency = 1.0; - --ClipsDescendants = true; - ZIndex = 0.0; - Parent = self.Gui; - Active = false; - - Gui.Create'ImageLabel' - { - Name = 'Background'; - Image = 'http://www.roblox.com/asset/?id=97120937'; --96551212'; - Size = UDim2.new(1.3, 0, 1.64, 0); - Position = UDim2.new(0, 0, 0, 0); - BackgroundTransparency = 1.0; - ZIndex = 0.0; - Visible = false - }; - - Gui.Create'Frame' - { - Name = 'Border'; - Size = UDim2.new(1, 0, 0, 1); - Position = UDim2.new(0, 0, 0.8, 0); - BackgroundTransparency = 0.0; - BackgroundColor3 = Color3.new(236/255, 236/255, 236/255); - BorderSizePixel = 0.0; - Visible = false; - }; - - Gui.Create'Frame' - { - Name = 'ChatRenderFrame'; - Size = UDim2.new(1.02, 0, 1.01, 0); - Position = UDim2.new(0, 0, 0, 0); - BackgroundTransparency = 1.0; - --ClipsDescendants = true; - ZIndex = 0.0; - Active = false; - - }; - }; - - Spawn(function() - wait(0.5) - if IsPhone() then - self.Frame.Size = UDim2.new(0, 280, 0, 120) - end - end) - - self.RenderFrame = self.Frame.ChatRenderFrame - if Chat:IsTouchDevice() then - self.Frame.Position = self.Configuration.Position; - self.RenderFrame.Size = UDim2.new(1, 0, 1, 0) - elseif self.Frame.AbsoluteSize.Y > 120 then - Chat:ScreenSizeChanged() - self.Gui.Changed:connect(function(property) - if property == 'AbsoluteSize' then - Chat:ScreenSizeChanged() - end - end) - end - - if Player.ChatMode == Enum.ChatMode.TextAndMenu then - if Chat:IsTouchDevice() then - Chat:CreateTouchButton() - - else - Chat:CreateChatBar() - --Chat:CreateSafeChatGui() - end - - if self.ChatBar then - self.ChatBar.FocusLost:connect(function(enterPressed) - Chat.GotFocus = false - if Chat:IsTouchDevice() then - self.ChatBar.Visible = false - self.TapToChatLabel.Visible = true - - if self.TouchLabelBackground then - self.TouchLabelBackground.Visible = true - end - end - if enterPressed and self.ChatBar.Text ~= "" then - - local cText = self.ChatBar.Text - if string.sub(self.ChatBar.Text, 1, 1) == '%' then - cText = '(TEAM) ' .. string.sub(cText, 2, #cText) - pcall(function() PlayersService:TeamChat(cText) end) - else - pcall(function() PlayersService:Chat(cText) end) - end - - if self.ClickToChatButton then - self.ClickToChatButton.Visible = true - end - self.ChatBar.Text = "" - end - Spawn(function() - wait(5.0) - if not Chat.GotFocus then - Chat.Frame.Background.Visible = false - end - end) - end) - end - end end -- Scrolling function @@ -1190,7 +1073,7 @@ function Input:OnMouseScroll() wait(0.25) end end - wait(0.03) + wait() end end) if Chat:CheckIfInBounds(Input.Speed) then @@ -1233,7 +1116,7 @@ function Chat:FindMessageInSafeChat(message, list) end -- Just a wrapper around our PlayerChatted event -function Chat:PlayerChatted(...) +function Chat:PlayerChatted(...) local args = {...} local argCount = select('#', ...) local player @@ -1244,15 +1127,12 @@ function Chat:PlayerChatted(...) end if args[3] then message = args[3] - if string.sub(message, 1, 1) == '%' then - message = '(TEAM) ' .. string.sub(message, 2, #message) - end end if PlayersService.ClassicChat then if Player.ChatMode == Enum.ChatMode.TextAndMenu then Chat:UpdateChat(player, message) elseif Player.ChatMode == Enum.ChatMode.Menu and string.sub(message, 3) == '/sc' then - Chat:UpdateChat(player, message) + Chat:UpdateChat(player, message) else if Chat:FindMessageInSafeChat(message, self.SafeChat_List) then Chat:UpdateChat(player, message) @@ -1261,20 +1141,20 @@ function Chat:PlayerChatted(...) end end --- After Chat.Configuration.Lifetime seconds of existence, the labels become invisible +-- After 5 minutes of existence, the labels become invisible -- Runs only every 5 seconds and has to loop through 50 values -- Shouldn't be too expensive function Chat:CullThread() while true do if #self.MessageQueue > 0 then for _, field in pairs(self.MessageQueue) do - if field['SpawnTime'] and field['Player'] and field['Message'] and tick() - field['SpawnTime'] > self.Configuration.LifeTime then + if tick() - field['SpawnTime'] > self.Configuration.LifeTime and field['Player'] and field['Message'] then field['Player'].Visible = false field['Message'].Visible = false end end end - wait(5.0) + wait(5.0) end end @@ -1291,7 +1171,7 @@ end -- Constructor -- This function initializes everything -function Chat:Initialize() +function Chat:Initialize() Chat:CreateGui() self.EventListener = PlayersService.PlayerChatted:connect(function(...) -- This event has 4 callback arguments @@ -1300,15 +1180,11 @@ function Chat:Initialize() end) - self.MessageThread = coroutine.create(function() end) - coroutine.resume(self.MessageThread) - -- Initialize input for us Input:Initialize() -- Eww, everytime a player is added, you have to redo the connection -- Seems this is not automatic - -- NOTE: PlayerAdded only fires on the server, hence ChildAdded is used here - PlayersService.ChildAdded:connect(function() + Game.Players.ChildAdded:connect(function() Chat.EventListener:disconnect() self.EventListener = PlayersService.PlayerChatted:connect(function(...) -- This event has 4 callback arguments @@ -1334,6 +1210,3 @@ Chat:Initialize() - - -