Advertisement
Finnegan5

Bubble chat

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