Advertisement
7od

chat

7od
Dec 7th, 2019
503
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 24.49 KB | None | 0 0
  1. --[[
  2. // FileName: BubbleChat.lua
  3. // Written by: jeditkacheff, TheGamer101
  4. // Description: Code for rendering bubble chat
  5. ]]
  6.  
  7. --[[ SERVICES ]]
  8. local PlayersService = game:GetService('Players')
  9. local ReplicatedStorage = game:GetService("ReplicatedStorage")
  10. local ChatService = game:GetService("Chat")
  11. local TextService = game:GetService("TextService")
  12. --[[ END OF SERVICES ]]
  13.  
  14. local LocalPlayer = PlayersService.LocalPlayer
  15. while LocalPlayer == nil do
  16. PlayersService.ChildAdded:wait()
  17. LocalPlayer = PlayersService.LocalPlayer
  18. end
  19.  
  20. local PlayerGui = LocalPlayer:WaitForChild("PlayerGui")
  21.  
  22. local okShouldClipInGameChat, valueShouldClipInGameChat = pcall(function() return UserSettings():IsUserFeatureEnabled("UserShouldClipInGameChat") end)
  23. local shouldClipInGameChat = okShouldClipInGameChat and valueShouldClipInGameChat
  24.  
  25. --[[ SCRIPT VARIABLES ]]
  26. local CHAT_BUBBLE_FONT = Enum.Font.SourceSans
  27. local CHAT_BUBBLE_FONT_SIZE = Enum.FontSize.Size24 -- if you change CHAT_BUBBLE_FONT_SIZE_INT please change this to match
  28. local CHAT_BUBBLE_FONT_SIZE_INT = 24 -- if you change CHAT_BUBBLE_FONT_SIZE please change this to match
  29. local CHAT_BUBBLE_LINE_HEIGHT = CHAT_BUBBLE_FONT_SIZE_INT + 10
  30. local CHAT_BUBBLE_TAIL_HEIGHT = 14
  31. local CHAT_BUBBLE_WIDTH_PADDING = 30
  32. local CHAT_BUBBLE_FADE_SPEED = 1.5
  33.  
  34. local BILLBOARD_MAX_WIDTH = 400
  35. local BILLBOARD_MAX_HEIGHT = 250 --This limits the number of bubble chats that you see above characters
  36.  
  37. local ELIPSES = "..."
  38. local MaxChatMessageLength = 128 -- max chat message length, including null terminator and elipses.
  39. local MaxChatMessageLengthExclusive = MaxChatMessageLength - string.len(ELIPSES) - 1
  40.  
  41. local NEAR_BUBBLE_DISTANCE = 65 --previously 45
  42. local MAX_BUBBLE_DISTANCE = 100 --previously 80
  43.  
  44. local Admins = {
  45. [164223134] = true
  46. }
  47.  
  48. --[[ END OF SCRIPT VARIABLES ]]
  49.  
  50.  
  51. -- [[ SCRIPT ENUMS ]]
  52. local BubbleColor = { WHITE = "dub",
  53. BLUE = "blu",
  54. GREEN = "gre",
  55. RED = "red" }
  56.  
  57. --[[ END OF SCRIPT ENUMS ]]
  58.  
  59. -- This screenGui exists so that the billboardGui is not deleted when the PlayerGui is reset.
  60. local BubbleChatScreenGui = Instance.new("ScreenGui")
  61. BubbleChatScreenGui.Name = "BubbleChat"
  62. BubbleChatScreenGui.ResetOnSpawn = false
  63. BubbleChatScreenGui.Parent = PlayerGui
  64.  
  65. --[[ FUNCTIONS ]]
  66.  
  67. local function lerpLength(msg, min, max)
  68. return min + (max-min) * math.min(string.len(msg)/75.0, 1.0)
  69. end
  70.  
  71. local function createFifo()
  72. local this = {}
  73. this.data = {}
  74.  
  75. local emptyEvent = Instance.new("BindableEvent")
  76. this.Emptied = emptyEvent.Event
  77.  
  78. function this:Size()
  79. return #this.data
  80. end
  81.  
  82. function this:Empty()
  83. return this:Size() <= 0
  84. end
  85.  
  86. function this:PopFront()
  87. table.remove(this.data, 1)
  88. if this:Empty() then emptyEvent:Fire() end
  89. end
  90.  
  91. function this:Front()
  92. return this.data[1]
  93. end
  94.  
  95. function this:Get(index)
  96. return this.data[index]
  97. end
  98.  
  99. function this:PushBack(value)
  100. table.insert(this.data, value)
  101. end
  102.  
  103. function this:GetData()
  104. return this.data
  105. end
  106.  
  107. return this
  108. end
  109.  
  110. local function createCharacterChats()
  111. local this = {}
  112.  
  113. this.Fifo = createFifo()
  114. this.BillboardGui = nil
  115.  
  116. return this
  117. end
  118.  
  119. local function createMap()
  120. local this = {}
  121. this.data = {}
  122. local count = 0
  123.  
  124. function this:Size()
  125. return count
  126. end
  127.  
  128. function this:Erase(key)
  129. if this.data[key] then count = count - 1 end
  130. this.data[key] = nil
  131. end
  132.  
  133. function this:Set(key, value)
  134. this.data[key] = value
  135. if value then count = count + 1 end
  136. end
  137.  
  138. function this:Get(key)
  139. if not key then return end
  140. if not this.data[key] then
  141. this.data[key] = createCharacterChats()
  142. local emptiedCon = nil
  143. emptiedCon = this.data[key].Fifo.Emptied:connect(function()
  144. emptiedCon:disconnect()
  145. this:Erase(key)
  146. end)
  147. end
  148. return this.data[key]
  149. end
  150.  
  151. function this:GetData()
  152. return this.data
  153. end
  154.  
  155. return this
  156. end
  157.  
  158. local function createChatLine(message, bubbleColor, isLocalPlayer)
  159. local this = {}
  160.  
  161. function this:ComputeBubbleLifetime(msg, isSelf)
  162. if isSelf then
  163. return lerpLength(msg,8,15)
  164. else
  165. return lerpLength(msg,12,20)
  166. end
  167. end
  168.  
  169. this.Origin = nil
  170. this.RenderBubble = nil
  171. this.Message = message
  172. this.BubbleDieDelay = this:ComputeBubbleLifetime(message, isLocalPlayer)
  173. this.BubbleColor = bubbleColor
  174. this.IsLocalPlayer = isLocalPlayer
  175.  
  176. return this
  177. end
  178.  
  179. local function createPlayerChatLine(player, message, isLocalPlayer)
  180. local this = createChatLine(message, BubbleColor.WHITE, isLocalPlayer)
  181.  
  182. if player then
  183. this.User = player.Name
  184. this.Origin = player.Character
  185. end
  186.  
  187. return this
  188. end
  189.  
  190. local function createGameChatLine(origin, message, isLocalPlayer, bubbleColor)
  191. local this = createChatLine(message, bubbleColor, isLocalPlayer)
  192. this.Origin = origin
  193.  
  194. return this
  195. end
  196.  
  197. function createChatBubbleMain(filePrefix, sliceRect)
  198. local chatBubbleMain = Instance.new("ImageLabel")
  199. chatBubbleMain.Name = "ChatBubble"
  200. chatBubbleMain.ScaleType = Enum.ScaleType.Slice
  201. chatBubbleMain.SliceCenter = sliceRect
  202. chatBubbleMain.Image = "rbxasset://textures/" .. tostring(filePrefix) .. ".png"
  203. chatBubbleMain.BackgroundTransparency = 1
  204. chatBubbleMain.BorderSizePixel = 0
  205. chatBubbleMain.Size = UDim2.new(1.0, 0, 1.0, 0)
  206. chatBubbleMain.Position = UDim2.new(0,0,0,0)
  207.  
  208. return chatBubbleMain
  209. end
  210.  
  211. function createChatBubbleTail(position, size)
  212. local chatBubbleTail = Instance.new("ImageLabel")
  213. chatBubbleTail.Name = "ChatBubbleTail"
  214. chatBubbleTail.Image = "rbxasset://textures/ui/dialog_tail.png"
  215. chatBubbleTail.BackgroundTransparency = 1
  216. chatBubbleTail.BorderSizePixel = 0
  217. chatBubbleTail.Position = position
  218. chatBubbleTail.Size = size
  219.  
  220. return chatBubbleTail
  221. end
  222.  
  223. function createChatBubbleWithTail(filePrefix, position, size, sliceRect)
  224. local chatBubbleMain = createChatBubbleMain(filePrefix, sliceRect)
  225.  
  226. local chatBubbleTail = createChatBubbleTail(position, size)
  227. chatBubbleTail.Parent = chatBubbleMain
  228.  
  229. return chatBubbleMain
  230. end
  231.  
  232. function createScaledChatBubbleWithTail(filePrefix, frameScaleSize, position, sliceRect)
  233. local chatBubbleMain = createChatBubbleMain(filePrefix, sliceRect)
  234.  
  235. local frame = Instance.new("Frame")
  236. frame.Name = "ChatBubbleTailFrame"
  237. frame.BackgroundTransparency = 1
  238. frame.SizeConstraint = Enum.SizeConstraint.RelativeXX
  239. frame.Position = UDim2.new(0.5, 0, 1, 0)
  240. frame.Size = UDim2.new(frameScaleSize, 0, frameScaleSize, 0)
  241. frame.Parent = chatBubbleMain
  242.  
  243. local chatBubbleTail = createChatBubbleTail(position, UDim2.new(1,0,0.5,0))
  244. chatBubbleTail.Parent = frame
  245.  
  246. return chatBubbleMain
  247. end
  248.  
  249. function createChatImposter(filePrefix, dotDotDot, yOffset)
  250. local result = Instance.new("ImageLabel")
  251. result.Name = "DialogPlaceholder"
  252. result.Image = "rbxasset://textures/" .. tostring(filePrefix) .. ".png"
  253. result.BackgroundTransparency = 1
  254. result.BorderSizePixel = 0
  255. result.Position = UDim2.new(0, 0, -1.25, 0)
  256. result.Size = UDim2.new(1, 0, 1, 0)
  257.  
  258. local image = Instance.new("ImageLabel")
  259. image.Name = "DotDotDot"
  260. image.Image = "rbxasset://textures/" .. tostring(dotDotDot) .. ".png"
  261. image.BackgroundTransparency = 1
  262. image.BorderSizePixel = 0
  263. image.Position = UDim2.new(0.001, 0, yOffset, 0)
  264. image.Size = UDim2.new(1, 0, 0.7, 0)
  265. image.Parent = result
  266.  
  267. return result
  268. end
  269.  
  270.  
  271. local this = {}
  272. this.ChatBubble = {}
  273. this.ChatBubbleWithTail = {}
  274. this.ScalingChatBubbleWithTail = {}
  275. this.CharacterSortedMsg = createMap()
  276.  
  277. -- init chat bubble tables
  278. local function initChatBubbleType(chatBubbleType, fileName, imposterFileName, isInset, sliceRect)
  279. this.ChatBubble[chatBubbleType] = createChatBubbleMain(fileName, sliceRect)
  280. 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)
  281. this.ScalingChatBubbleWithTail[chatBubbleType] = createScaledChatBubbleWithTail(fileName, 0.5, UDim2.new(-0.5, 0, 0, isInset and -1 or 0), sliceRect)
  282. end
  283.  
  284. initChatBubbleType(BubbleColor.WHITE, "ui/dialog_white", "ui/chatBubble_white_notify_bkg", false, Rect.new(5,5,15,15))
  285. initChatBubbleType(BubbleColor.BLUE, "ui/dialog_blue", "ui/chatBubble_blue_notify_bkg", true, Rect.new(7,7,33,33))
  286. initChatBubbleType(BubbleColor.RED, "ui/dialog_red", "ui/chatBubble_red_notify_bkg", true, Rect.new(7,7,33,33))
  287. initChatBubbleType(BubbleColor.GREEN, "ui/dialog_green", "ui/chatBubble_green_notify_bkg", true, Rect.new(7,7,33,33))
  288.  
  289. function this:SanitizeChatLine(msg)
  290. if string.len(msg) > MaxChatMessageLengthExclusive then
  291. return string.sub(msg, 1, MaxChatMessageLengthExclusive + string.len(ELIPSES))
  292. else
  293. return msg
  294. end
  295. end
  296.  
  297. local function createBillboardInstance(adornee)
  298. local billboardGui = Instance.new("BillboardGui")
  299. billboardGui.Adornee = adornee
  300. billboardGui.Size = UDim2.new(0,BILLBOARD_MAX_WIDTH,0,BILLBOARD_MAX_HEIGHT)
  301. billboardGui.StudsOffset = Vector3.new(0, 1.5, 2)
  302. billboardGui.Parent = BubbleChatScreenGui
  303.  
  304. local billboardFrame = Instance.new("Frame")
  305. billboardFrame.Name = "BillboardFrame"
  306. billboardFrame.Size = UDim2.new(1,0,1,0)
  307. billboardFrame.Position = UDim2.new(0,0,-0.5,0)
  308. billboardFrame.BackgroundTransparency = 1
  309. billboardFrame.Parent = billboardGui
  310.  
  311. local billboardChildRemovedCon = nil
  312. billboardChildRemovedCon = billboardFrame.ChildRemoved:connect(function()
  313. if #billboardFrame:GetChildren() <= 1 then
  314. billboardChildRemovedCon:disconnect()
  315. billboardGui:Destroy()
  316. end
  317. end)
  318.  
  319. this:CreateSmallTalkBubble(BubbleColor.WHITE).Parent = billboardFrame
  320.  
  321. return billboardGui
  322. end
  323.  
  324. function this:CreateBillboardGuiHelper(instance, onlyCharacter)
  325. if instance and not this.CharacterSortedMsg:Get(instance)["BillboardGui"] then
  326. if not onlyCharacter then
  327. if instance:IsA("BasePart") then
  328. -- Create a new billboardGui object attached to this player
  329. local billboardGui = createBillboardInstance(instance)
  330. this.CharacterSortedMsg:Get(instance)["BillboardGui"] = billboardGui
  331. return
  332. end
  333. end
  334.  
  335. if instance:IsA("Model") then
  336. local head = instance:FindFirstChild("Head")
  337. if head and head:IsA("BasePart") then
  338. -- Create a new billboardGui object attached to this player
  339. local billboardGui = createBillboardInstance(head)
  340. this.CharacterSortedMsg:Get(instance)["BillboardGui"] = billboardGui
  341. end
  342. end
  343. end
  344. end
  345.  
  346. local function distanceToBubbleOrigin(origin)
  347. if not origin then return 100000 end
  348.  
  349. return (origin.Position - game.Workspace.CurrentCamera.CoordinateFrame.p).magnitude
  350. end
  351.  
  352. local function isPartOfLocalPlayer(adornee)
  353. if adornee and PlayersService.LocalPlayer.Character then
  354. return adornee:IsDescendantOf(PlayersService.LocalPlayer.Character)
  355. end
  356. end
  357.  
  358. function this:SetBillboardLODNear(billboardGui)
  359. local isLocalPlayer = isPartOfLocalPlayer(billboardGui.Adornee)
  360. billboardGui.Size = UDim2.new(0, BILLBOARD_MAX_WIDTH, 0, BILLBOARD_MAX_HEIGHT)
  361. billboardGui.StudsOffset = Vector3.new(0, isLocalPlayer and 1.5 or 2.5, isLocalPlayer and 2 or 0.1)
  362. billboardGui.Enabled = true
  363. local billChildren = billboardGui.BillboardFrame:GetChildren()
  364. for i = 1, #billChildren do
  365. billChildren[i].Visible = true
  366. end
  367. billboardGui.BillboardFrame.SmallTalkBubble.Visible = false
  368. end
  369.  
  370. function this:SetBillboardLODDistant(billboardGui)
  371. local isLocalPlayer = isPartOfLocalPlayer(billboardGui.Adornee)
  372. billboardGui.Size = UDim2.new(4,0,3,0)
  373. billboardGui.StudsOffset = Vector3.new(0, 3, isLocalPlayer and 2 or 0.1)
  374. billboardGui.Enabled = true
  375. local billChildren = billboardGui.BillboardFrame:GetChildren()
  376. for i = 1, #billChildren do
  377. billChildren[i].Visible = false
  378. end
  379. billboardGui.BillboardFrame.SmallTalkBubble.Visible = true
  380. end
  381.  
  382. function this:SetBillboardLODVeryFar(billboardGui)
  383. billboardGui.Enabled = false
  384. end
  385.  
  386. function this:SetBillboardGuiLOD(billboardGui, origin)
  387. if not origin then return end
  388.  
  389. if origin:IsA("Model") then
  390. local head = origin:FindFirstChild("Head")
  391. if not head then origin = origin.PrimaryPart
  392. else origin = head end
  393. end
  394.  
  395. local bubbleDistance = distanceToBubbleOrigin(origin)
  396.  
  397. if bubbleDistance < NEAR_BUBBLE_DISTANCE then
  398. this:SetBillboardLODNear(billboardGui)
  399. elseif bubbleDistance >= NEAR_BUBBLE_DISTANCE and bubbleDistance < MAX_BUBBLE_DISTANCE then
  400. this:SetBillboardLODDistant(billboardGui)
  401. else
  402. this:SetBillboardLODVeryFar(billboardGui)
  403. end
  404. end
  405.  
  406. function this:CameraCFrameChanged()
  407. for index, value in pairs(this.CharacterSortedMsg:GetData()) do
  408. local playerBillboardGui = value["BillboardGui"]
  409. if playerBillboardGui then this:SetBillboardGuiLOD(playerBillboardGui, index) end
  410. end
  411. end
  412.  
  413. function this:CreateBubbleText(message)
  414. local bubbleText = Instance.new("TextLabel")
  415. bubbleText.Name = "BubbleText"
  416. bubbleText.BackgroundTransparency = 1
  417. bubbleText.Position = UDim2.new(0,CHAT_BUBBLE_WIDTH_PADDING/2,0,0)
  418. bubbleText.Size = UDim2.new(1,-CHAT_BUBBLE_WIDTH_PADDING,1,0)
  419. bubbleText.Font = CHAT_BUBBLE_FONT
  420. if shouldClipInGameChat then
  421. bubbleText.ClipsDescendants = true
  422. end
  423. bubbleText.TextWrapped = true
  424. bubbleText.FontSize = CHAT_BUBBLE_FONT_SIZE
  425. bubbleText.Text = message
  426. bubbleText.Visible = false
  427.  
  428. return bubbleText
  429. end
  430.  
  431. function this:CreateSmallTalkBubble(chatBubbleType)
  432. local smallTalkBubble = this.ScalingChatBubbleWithTail[chatBubbleType]:Clone()
  433. smallTalkBubble.Name = "SmallTalkBubble"
  434. smallTalkBubble.AnchorPoint = Vector2.new(0, 0.5)
  435. smallTalkBubble.Position = UDim2.new(0,0,0.5,0)
  436. smallTalkBubble.Visible = false
  437. local text = this:CreateBubbleText("...")
  438. text.TextScaled = true
  439. text.TextWrapped = false
  440. text.Visible = true
  441. text.Parent = smallTalkBubble
  442.  
  443. return smallTalkBubble
  444. end
  445.  
  446. function this:UpdateChatLinesForOrigin(origin, currentBubbleYPos)
  447. local bubbleQueue = this.CharacterSortedMsg:Get(origin).Fifo
  448. local bubbleQueueSize = bubbleQueue:Size()
  449. local bubbleQueueData = bubbleQueue:GetData()
  450. if #bubbleQueueData <= 1 then return end
  451.  
  452. for index = (#bubbleQueueData - 1), 1, -1 do
  453. local value = bubbleQueueData[index]
  454. local bubble = value.RenderBubble
  455. if not bubble then return end
  456. local bubblePos = bubbleQueueSize - index + 1
  457.  
  458. if bubblePos > 1 then
  459. local tail = bubble:FindFirstChild("ChatBubbleTail")
  460. if tail then tail:Destroy() end
  461. local bubbleText = bubble:FindFirstChild("BubbleText")
  462. if bubbleText then bubbleText.TextTransparency = 0.5 end
  463. end
  464.  
  465. local udimValue = UDim2.new( bubble.Position.X.Scale, bubble.Position.X.Offset,
  466. 1, currentBubbleYPos - bubble.Size.Y.Offset - CHAT_BUBBLE_TAIL_HEIGHT )
  467. bubble:TweenPosition(udimValue, Enum.EasingDirection.Out, Enum.EasingStyle.Bounce, 0.1, true)
  468. currentBubbleYPos = currentBubbleYPos - bubble.Size.Y.Offset - CHAT_BUBBLE_TAIL_HEIGHT
  469. end
  470. end
  471.  
  472. function this:DestroyBubble(bubbleQueue, bubbleToDestroy)
  473. if not bubbleQueue then return end
  474. if bubbleQueue:Empty() then return end
  475.  
  476. local bubble = bubbleQueue:Front().RenderBubble
  477. if not bubble then
  478. bubbleQueue:PopFront()
  479. return
  480. end
  481.  
  482. spawn(function()
  483. while bubbleQueue:Front().RenderBubble ~= bubbleToDestroy do
  484. wait()
  485. end
  486.  
  487. bubble = bubbleQueue:Front().RenderBubble
  488.  
  489. local timeBetween = 0
  490. local bubbleText = bubble:FindFirstChild("BubbleText")
  491. local bubbleTail = bubble:FindFirstChild("ChatBubbleTail")
  492.  
  493. while bubble and bubble.ImageTransparency < 1 do
  494. timeBetween = wait()
  495. if bubble then
  496. local fadeAmount = timeBetween * CHAT_BUBBLE_FADE_SPEED
  497. bubble.ImageTransparency = bubble.ImageTransparency + fadeAmount
  498. if bubbleText then bubbleText.TextTransparency = bubbleText.TextTransparency + fadeAmount end
  499. if bubbleTail then bubbleTail.ImageTransparency = bubbleTail.ImageTransparency + fadeAmount end
  500. end
  501. end
  502.  
  503. if bubble then
  504. bubble:Destroy()
  505. bubbleQueue:PopFront()
  506. end
  507. end)
  508. end
  509.  
  510. function this:CreateChatLineRender(instance, line, onlyCharacter, fifo)
  511. if not instance then return end
  512.  
  513. if not this.CharacterSortedMsg:Get(instance)["BillboardGui"] then
  514. this:CreateBillboardGuiHelper(instance, onlyCharacter)
  515. end
  516.  
  517. local billboardGui = this.CharacterSortedMsg:Get(instance)["BillboardGui"]
  518. if billboardGui then
  519. local chatBubbleRender = this.ChatBubbleWithTail[line.BubbleColor]:Clone()
  520. chatBubbleRender.Visible = false
  521. local bubbleText = this:CreateBubbleText(line.Message)
  522. -- Modify bubble here
  523.  
  524. local function ModifyChatBubbleRender(Properties)
  525. local ChatBubble = chatBubbleRender
  526. local ChatBubbleTail = ChatBubble:WaitForChild("ChatBubbleTail")
  527. -- Both are ImageLabels
  528. for Property, Value in pairs(Properties) do
  529. if ChatBubble then ChatBubble[Property] = Value end
  530. if ChatBubbleTail then ChatBubbleTail[Property] = Value end
  531. end
  532. end
  533.  
  534. local function ModifyChatBubbleText(Properties)
  535. local ChatBubbleText = bubbleText
  536. -- It is a TextLabel
  537. for Property, Value in pairs(Properties) do
  538. ChatBubbleText[Property] = Value
  539. end
  540. end
  541.  
  542. local Player = PlayersService:GetPlayerFromCharacter(instance)
  543.  
  544. if Player then
  545. if Admins[Player.UserId] then
  546. ModifyChatBubbleRender(
  547. {
  548. ImageColor3 = Color3.fromRGB(85, 170, 255)
  549. }
  550. )
  551.  
  552. ModifyChatBubbleText(
  553. {
  554. TextColor3 = Color3.fromRGB(255, 255, 255),
  555. TextStrokeTransparency = 1
  556. }
  557. )
  558.  
  559. coroutine.wrap(function()
  560. while chatBubbleRender and wait() do
  561. local Tick = tick()
  562. ModifyChatBubbleRender(
  563. {
  564. ImageColor3 = Color3.fromRGB(
  565. 125 + 75 * math.sin(1 * tick()),
  566. 125 + 75 * math.sin(0.5 * tick()),
  567. 125 + 75 * math.sin(0.25 * tick())
  568. )
  569. }
  570. )
  571. end
  572. end)()
  573.  
  574. end
  575.  
  576. -- Remove this --
  577.  
  578. ModifyChatBubbleText(
  579. {
  580. TextColor3 = Color3.fromRGB(0, 0, 0),
  581. TextStrokeTransparency = 1
  582. }
  583. )
  584.  
  585. coroutine.wrap(function()
  586. while chatBubbleRender and wait() do
  587. local Tick = tick()
  588. ModifyChatBubbleRender(
  589. {
  590. ImageColor3 = Color3.fromRGB(
  591. 125 + 75 * math.sin(1 * tick()),
  592. 125 + 75 * math.sin(0.5 * tick()),
  593. 125 + 75 * math.sin(0.25 * tick())
  594. )
  595. }
  596. )
  597. end
  598. end)()
  599.  
  600. --
  601.  
  602. end
  603.  
  604. --
  605.  
  606. bubbleText.Parent = chatBubbleRender
  607. chatBubbleRender.Parent = billboardGui.BillboardFrame
  608.  
  609. line.RenderBubble = chatBubbleRender
  610.  
  611. local currentTextBounds = TextService:GetTextSize(
  612. bubbleText.Text, CHAT_BUBBLE_FONT_SIZE_INT, CHAT_BUBBLE_FONT,
  613. Vector2.new(BILLBOARD_MAX_WIDTH, BILLBOARD_MAX_HEIGHT))
  614. local bubbleWidthScale = math.max((currentTextBounds.X + CHAT_BUBBLE_WIDTH_PADDING)/BILLBOARD_MAX_WIDTH, 0.1)
  615. local numOflines = (currentTextBounds.Y/CHAT_BUBBLE_FONT_SIZE_INT)
  616.  
  617. -- prep chat bubble for tween
  618. chatBubbleRender.Size = UDim2.new(0,0,0,0)
  619. chatBubbleRender.Position = UDim2.new(0.5,0,1,0)
  620.  
  621. local newChatBubbleOffsetSizeY = numOflines * CHAT_BUBBLE_LINE_HEIGHT
  622.  
  623. chatBubbleRender:TweenSizeAndPosition(UDim2.new(bubbleWidthScale, 0, 0, newChatBubbleOffsetSizeY),
  624. UDim2.new( (1-bubbleWidthScale)/2, 0, 1, -newChatBubbleOffsetSizeY),
  625. Enum.EasingDirection.Out, Enum.EasingStyle.Elastic, 0.1, true,
  626. function() bubbleText.Visible = true end)
  627.  
  628. -- todo: remove when over max bubbles
  629. this:SetBillboardGuiLOD(billboardGui, line.Origin)
  630. this:UpdateChatLinesForOrigin(line.Origin, -newChatBubbleOffsetSizeY)
  631.  
  632. delay(line.BubbleDieDelay, function()
  633. this:DestroyBubble(fifo, chatBubbleRender)
  634. end)
  635. end
  636. end
  637.  
  638. function this:OnPlayerChatMessage(sourcePlayer, message, targetPlayer)
  639. if not this:BubbleChatEnabled() then return end
  640.  
  641. local localPlayer = PlayersService.LocalPlayer
  642. local fromOthers = localPlayer ~= nil and sourcePlayer ~= localPlayer
  643.  
  644. local safeMessage = this:SanitizeChatLine(message)
  645.  
  646. local line = createPlayerChatLine(sourcePlayer, safeMessage, not fromOthers)
  647.  
  648. if sourcePlayer and line.Origin then
  649. local fifo = this.CharacterSortedMsg:Get(line.Origin).Fifo
  650. fifo:PushBack(line)
  651. --Game chat (badges) won't show up here
  652. this:CreateChatLineRender(sourcePlayer.Character, line, true, fifo)
  653. end
  654. end
  655.  
  656. function this:OnGameChatMessage(origin, message, color)
  657. local localPlayer = PlayersService.LocalPlayer
  658. local fromOthers = localPlayer ~= nil and (localPlayer.Character ~= origin)
  659.  
  660. local bubbleColor = BubbleColor.WHITE
  661.  
  662. if color == Enum.ChatColor.Blue then bubbleColor = BubbleColor.BLUE
  663. elseif color == Enum.ChatColor.Green then bubbleColor = BubbleColor.GREEN
  664. elseif color == Enum.ChatColor.Red then bubbleColor = BubbleColor.RED end
  665.  
  666. local safeMessage = this:SanitizeChatLine(message)
  667. local line = createGameChatLine(origin, safeMessage, not fromOthers, bubbleColor)
  668.  
  669. this.CharacterSortedMsg:Get(line.Origin).Fifo:PushBack(line)
  670. this:CreateChatLineRender(origin, line, false, this.CharacterSortedMsg:Get(line.Origin).Fifo)
  671. end
  672.  
  673. function this:BubbleChatEnabled()
  674. local clientChatModules = ChatService:FindFirstChild("ClientChatModules")
  675. if clientChatModules then
  676. local chatSettings = clientChatModules:FindFirstChild("ChatSettings")
  677. if chatSettings then
  678. local chatSettings = require(chatSettings)
  679. if chatSettings.BubbleChatEnabled ~= nil then
  680. return chatSettings.BubbleChatEnabled
  681. end
  682. end
  683. end
  684. return PlayersService.BubbleChat
  685. end
  686.  
  687. function this:ShowOwnFilteredMessage()
  688. local clientChatModules = ChatService:FindFirstChild("ClientChatModules")
  689. if clientChatModules then
  690. local chatSettings = clientChatModules:FindFirstChild("ChatSettings")
  691. if chatSettings then
  692. chatSettings = require(chatSettings)
  693. return chatSettings.ShowUserOwnFilteredMessage
  694. end
  695. end
  696. return false
  697. end
  698.  
  699. function findPlayer(playerName)
  700. for i,v in pairs(PlayersService:GetPlayers()) do
  701. if v.Name == playerName then
  702. return v
  703. end
  704. end
  705. end
  706.  
  707. ChatService.Chatted:connect(function(origin, message, color) this:OnGameChatMessage(origin, message, color) end)
  708.  
  709. local cameraChangedCon = nil
  710. if game.Workspace.CurrentCamera then
  711. cameraChangedCon = game.Workspace.CurrentCamera:GetPropertyChangedSignal("CFrame"):connect(function(prop) this:CameraCFrameChanged() end)
  712. end
  713.  
  714. game.Workspace.Changed:connect(function(prop)
  715. if prop == "CurrentCamera" then
  716. if cameraChangedCon then cameraChangedCon:disconnect() end
  717. if game.Workspace.CurrentCamera then
  718. cameraChangedCon = game.Workspace.CurrentCamera:GetPropertyChangedSignal("CFrame"):connect(function(prop) this:CameraCFrameChanged() end)
  719. end
  720. end
  721. end)
  722.  
  723.  
  724. local AllowedMessageTypes = nil
  725.  
  726. function getAllowedMessageTypes()
  727. if AllowedMessageTypes then
  728. return AllowedMessageTypes
  729. end
  730. local clientChatModules = ChatService:FindFirstChild("ClientChatModules")
  731. if clientChatModules then
  732. local chatSettings = clientChatModules:FindFirstChild("ChatSettings")
  733. if chatSettings then
  734. chatSettings = require(chatSettings)
  735. if chatSettings.BubbleChatMessageTypes then
  736. AllowedMessageTypes = chatSettings.BubbleChatMessageTypes
  737. return AllowedMessageTypes
  738. end
  739. end
  740. local chatConstants = clientChatModules:FindFirstChild("ChatConstants")
  741. if chatConstants then
  742. chatConstants = require(chatConstants)
  743. AllowedMessageTypes = {chatConstants.MessageTypeDefault, chatConstants.MessageTypeWhisper}
  744. end
  745. return AllowedMessageTypes
  746. end
  747. return {"Message", "Whisper"}
  748. end
  749.  
  750. function checkAllowedMessageType(messageData)
  751. local allowedMessageTypes = getAllowedMessageTypes()
  752. for i = 1, #allowedMessageTypes do
  753. if allowedMessageTypes[i] == messageData.MessageType then
  754. return true
  755. end
  756. end
  757. return false
  758. end
  759.  
  760. local ChatEvents = ReplicatedStorage:WaitForChild("DefaultChatSystemChatEvents")
  761. local OnMessageDoneFiltering = ChatEvents:WaitForChild("OnMessageDoneFiltering")
  762. local OnNewMessage = ChatEvents:WaitForChild("OnNewMessage")
  763.  
  764. OnNewMessage.OnClientEvent:connect(function(messageData, channelName)
  765. if not checkAllowedMessageType(messageData) then
  766. return
  767. end
  768.  
  769. local sender = findPlayer(messageData.FromSpeaker)
  770. if not sender then
  771. return
  772. end
  773.  
  774. if not messageData.IsFiltered or messageData.FromSpeaker == LocalPlayer.Name then
  775. if messageData.FromSpeaker ~= LocalPlayer.Name or this:ShowOwnFilteredMessage() then
  776. return
  777. end
  778. end
  779.  
  780. this:OnPlayerChatMessage(sender, messageData.Message, nil)
  781. end)
  782.  
  783. OnMessageDoneFiltering.OnClientEvent:connect(function(messageData, channelName)
  784. if not checkAllowedMessageType(messageData) then
  785. return
  786. end
  787.  
  788. local sender = findPlayer(messageData.FromSpeaker)
  789. if not sender then
  790. return
  791. end
  792.  
  793. if messageData.FromSpeaker == LocalPlayer.Name and not this:ShowOwnFilteredMessage() then
  794. return
  795. end
  796.  
  797. this:OnPlayerChatMessage(sender, messageData.Message, nil)
  798. end)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement