2013/97188756.lua

1801 lines
46 KiB
Lua

--[[
//FileName: ChatScript.LUA
//Written by: Sorcus
//Description: Code for lua side chat on ROBLOX. Supports Scrolling.
//NOTE: If you find any bugs or inaccuracies PM Sorcus on ROBLOX or @Canavus on Twitter
]]
local forceChatGUI = false
-- Utility functions + Globals
local function WaitForChild(parent, childName)
while parent:FindFirstChild(childName) == nil do
parent.ChildAdded:wait(0.03)
end
return parent[childName]
end
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
local Player = Game.Players.LocalPlayer
while Player.Character == nil do
wait(0.03)
end
local RbxUtility = LoadLibrary "RbxUtility"
local Gui = typedef(RbxUtility)
local Camera = Game.Workspace.CurrentCamera
-- Services
local CoreGuiService = Game:GetService "CoreGui"
local PlayersService = Game:GetService "Players"
local DebrisService = Game:GetService "Debris"
local GuiService = Game:GetService "GuiService"
-- Lua Enums
local Enums
do
Enums = {}
local EnumName = {} -- used as unique key for enum name
local enum_mt = {
__call = function(self, value)
return self[value] or self[tonumber(value)]
end,
__index = {
GetEnumItems = function(self)
local t = {}
for i, item in pairs(self) do
if type(i) == "number" then
t[#t + 1] = item
end
end
table.sort(t, function(a, b)
return a.Value < b.Value
end)
return t
end,
},
__tostring = function(self)
return "Enum." .. self[EnumName]
end,
}
local item_mt = {
__call = function(self, value)
return value == self or value == self.Name or value == self.Value
end,
__tostring = function(self)
return "Enum." .. self[EnumName] .. "." .. self.Name
end,
}
function CreateEnum(enumName)
return function(t)
local e = { [EnumName] = enumName }
for i, name in pairs(t) do
local item = setmetatable({ Name = name, Value = i, Enum = e, [EnumName] = enumName }, item_mt)
e[i] = item
e[name] = item
e[item] = item
end
Enums[enumName] = e
return setmetatable(e, enum_mt)
end
end
end
---------------------------------------------------
------------------ Input class --------------------
local Input = {
Mouse = Player:GetMouse(),
Speed = 0,
Simulating = false,
Configuration = {
DefaultSpeed = 1,
},
UserIsScrolling = false,
}
---------------------------------------------------
------------------ Chat class --------------------
local Chat = {
ChatColors = {
BrickColor.new "Bright red",
BrickColor.new "Bright blue",
BrickColor.new "Earth green",
BrickColor.new "Bright violet",
BrickColor.new "Bright orange",
BrickColor.new "Bright yellow",
BrickColor.new "Light reddish violet",
BrickColor.new "Brick yellow",
},
Gui = nil,
Frame = nil,
RenderFrame = nil,
TapToChatLabel = nil,
ClickToChatButton = nil,
ScrollingLock = false,
EventListener = nil,
-- This is actually a ring buffer
-- Meaning at hitting the historyLength it wraps around
-- Reuses the text objects, so chat atmost uses 100 text objects
MessageQueue = {},
-- Stores all the values for configuring chat
Configuration = {
FontSize = Enum.FontSize.Size12, -- 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,
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),
DefaultTweenSpeed = 0.15,
},
-- This could be redone by just using the previous and next fields of the Queue
-- But the iterators cause issues, will be optimized later
SlotPositions_List = {},
-- To precompute and store all player null strings since its an expensive process
CachedSpaceStrings_List = {},
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'
}, --]]
Admins_List = { "taskmanager", "Heliodex", "tako" },
SafeChat_List = {
["Use the Chat menu to talk to me."] = { "/sc 0", true },
["I can only see menu chats."] = { "/sc 1", true },
["Hello"] = {
["Hi"] = { "/sc 2_0", true, ["Hi there!"] = true, ["Hi everyone"] = true },
["Howdy"] = { "/sc 2_1", true, ["Howdy partner!"] = true },
["Greetings"] = {
"/sc 2_2",
true,
["Greetings everyone"] = true,
["Greetings Robloxians!"] = true,
["Seasons greetings!"] = true,
},
["Welcome"] = {
"/sc 2_3",
true,
["Welcome to my place"] = true,
["Welcome to my barbeque"] = true,
["Welcome to our base"] = true,
},
["Hey there!"] = { "/sc 2_4", true },
["What's up?"] = {
"/sc 2_5",
true,
["How are you doing?"] = true,
["How's it going?"] = true,
["What's new?"] = true,
},
["Good day"] = {
"/sc 2_6",
true,
["Good morning"] = true,
["Good evening"] = true,
["Good afternoon"] = true,
["Good night"] = true,
},
["Silly"] = {
"/sc 2_7",
true,
["Waaaaaaaz up?!"] = true,
["Hullo!"] = true,
["Behold greatness, mortals!"] = true,
["Pardon me, is this Sparta?"] = true,
["THIS IS SPARTAAAA!"] = true,
},
["Happy Holidays!"] = {
"/sc 2_8",
true,
["Happy New Year!"] = true,
["Happy Valentine's Day!"] = true,
["Beware the Ides of March!"] = true,
["Happy St. Patrick's Day!"] = true,
["Happy Easter!"] = true,
["Happy Earth Day!"] = true,
["Happy 4th of July!"] = true,
["Happy Thanksgiving!"] = true,
["Happy Halloween!"] = true,
["Happy Hanukkah!"] = true,
["Merry Christmas!"] = true,
["Happy May Day!"] = true,
["Happy Towel Day!"] = true,
["Happy ROBLOX Day!"] = true,
["Happy LOL Day!"] = true,
},
[1] = "/sc 2",
},
["Goodbye"] = {
["Good Night"] = {
"/sc 3_0",
true,
["Sweet dreams"] = true,
["Go to sleep!"] = true,
["Lights out!"] = true,
["Bedtime"] = true,
["Going to bed now"] = true,
},
["Later"] = {
"/sc 3_1",
true,
["See ya later"] = true,
["Later gator!"] = true,
["See you tomorrow"] = true,
},
["Bye"] = { "/sc 3_2", true, ["Hasta la bye bye!"] = true },
["I'll be right back"] = { "/sc 3_3", true },
["I have to go"] = { "/sc 3_4", true },
["Farewell"] = {
"/sc 3_5",
true,
["Take care"] = true,
["Have a nice day"] = true,
["Goodluck!"] = true,
["Ta-ta for now!"] = true,
},
["Peace"] = { "/sc 3_6", true, ["Peace out!"] = true, ["Peace dudes!"] = true, ["Rest in pieces!"] = true },
["Silly"] = {
"/sc 3_7",
true,
["To the batcave!"] = true,
["Over and out!"] = true,
["Happy trails!"] = true,
["I've got to book it!"] = true,
["Tootles!"] = true,
["Smell you later!"] = true,
["GG!"] = true,
["My house is on fire! gtg."] = true,
},
[1] = "/sc 3",
},
["Friend"] = {
["Wanna be friends?"] = { "/sc 4_0", true },
["Follow me"] = {
"/sc 4_1",
true,
["Come to my place!"] = true,
["Come to my base!"] = true,
["Follow me, team!"] = true,
["Follow me"] = true,
},
["Your place is cool"] = {
"/sc 4_2",
true,
["Your place is fun"] = true,
["Your place is awesome"] = true,
["Your place looks good"] = true,
["This place is awesome!"] = true,
},
["Thank you"] = {
"/sc 4_3",
true,
["Thanks for playing"] = true,
["Thanks for visiting"] = true,
["Thanks for everything"] = true,
["No, thank you"] = true,
["Thanx"] = true,
},
["No problem"] = { "/sc 4_4", true, ["Don't worry"] = true, ["That's ok"] = true, ["np"] = true },
["You are ..."] = {
"/sc 4_5",
true,
["You are great!"] = true,
["You are good!"] = true,
["You are cool!"] = true,
["You are funny!"] = true,
["You are silly!"] = true,
["You are awesome!"] = true,
["You are doing something I don't like, please stop"] = true,
},
["I like ..."] = {
"/sc 4_6",
true,
["I like your name"] = true,
["I like your shirt"] = true,
["I like your place"] = true,
["I like your style"] = true,
["I like you"] = true,
["I like items"] = true,
["I like money"] = true,
},
["Sorry"] = {
"/sc 4_7",
true,
["My bad!"] = true,
["I'm sorry"] = true,
["Whoops!"] = true,
["Please forgive me."] = true,
["I forgive you."] = true,
["I didn't mean to do that."] = true,
["Sorry, I'll stop now."] = true,
},
[1] = "/sc 4",
},
["Questions"] = {
["Who?"] = {
"/sc 5_0",
true,
["Who wants to be my friend?"] = true,
["Who wants to be on my team?"] = true,
["Who made this brilliant game?"] = true,
},
["What?"] = {
"/sc 5_1",
true,
["What is your favorite animal?"] = true,
["What is your favorite game?"] = true,
["What is your favorite movie?"] = true,
["What is your favorite TV show?"] = true,
["What is your favorite music?"] = true,
["What are your hobbies?"] = true,
["LOLWUT?"] = true,
},
["When?"] = {
"/sc 5_2",
true,
["When are you online?"] = true,
["When is the new version coming out?"] = true,
["When can we play again?"] = true,
["When will your place be done?"] = true,
},
["Where?"] = {
"/sc 5_3",
true,
["Where do you want to go?"] = true,
["Where are you going?"] = true,
["Where am I?!"] = true,
["Where did you go?"] = true,
},
["How?"] = {
"/sc 5_4",
true,
["How are you today?"] = true,
["How did you make this cool place?"] = true,
["LOLHOW?"] = true,
},
["Can I..."] = {
"/sc 5_5",
true,
["Can I have a tour?"] = true,
["Can I be on your team?"] = true,
["Can I be your friend?"] = true,
["Can I try something?"] = true,
["Can I have that please?"] = true,
["Can I have that back please?"] = true,
["Can I have borrow your hat?"] = true,
["Can I have borrow your gear?"] = true,
},
[1] = "/sc 5",
},
["Answers"] = {
["You need help?"] = {
"/sc 6_0",
true,
["Check out the news section"] = true,
["Check out the help section"] = true,
["Read the wiki!"] = true,
["All the answers are in the wiki!"] = true,
["I will help you with this."] = true,
},
["Some people ..."] = {
"/sc 6_1",
true,
["Me"] = true,
["Not me"] = true,
["You"] = true,
["All of us"] = true,
["Everyone but you"] = true,
["Builderman!"] = true,
["Telamon!"] = true,
["My team"] = true,
["My group"] = true,
["Mom"] = true,
["Dad"] = true,
["Sister"] = true,
["Brother"] = true,
["Cousin"] = true,
["Grandparent"] = true,
["Friend"] = true,
},
["Time ..."] = {
"/sc 6_2",
true,
["In the morning"] = true,
["In the afternoon"] = true,
["At night"] = true,
["Tomorrow"] = true,
["This week"] = true,
["This month"] = true,
["Sometime"] = true,
["Sometimes"] = true,
["Whenever you want"] = true,
["Never"] = true,
["After this"] = true,
["In 10 minutes"] = true,
["In a couple hours"] = true,
["In a couple days"] = true,
},
["Animals"] = {
"/sc 6_3",
true,
["Cats"] = { ["Lion"] = true, ["Tiger"] = true, ["Leopard"] = true, ["Cheetah"] = true },
["Dogs"] = {
["Wolves"] = true,
["Beagle"] = true,
["Collie"] = true,
["Dalmatian"] = true,
["Poodle"] = true,
["Spaniel"] = true,
["Shepherd"] = true,
["Terrier"] = true,
["Retriever"] = true,
},
["Horses"] = { ["Ponies"] = true, ["Stallions"] = true, ["Pwnyz"] = true },
["Reptiles"] = { ["Dinosaurs"] = true, ["Lizards"] = true, ["Snakes"] = true, ["Turtles!"] = true },
["Hamster"] = true,
["Monkey"] = true,
["Bears"] = true,
["Fish"] = {
["Goldfish"] = true,
["Sharks"] = true,
["Sea Bass"] = true,
["Halibut"] = true,
["Tropical Fish"] = true,
},
["Birds"] = {
["Eagles"] = true,
["Penguins"] = true,
["Parakeets"] = true,
["Owls"] = true,
["Hawks"] = true,
["Pidgeons"] = true,
},
["Elephants"] = true,
["Mythical Beasts"] = {
["Dragons"] = true,
["Unicorns"] = true,
["Sea Serpents"] = true,
["Sphinx"] = true,
["Cyclops"] = true,
["Minotaurs"] = true,
["Goblins"] = true,
["Honest Politicians"] = true,
["Ghosts"] = true,
["Scylla and Charybdis"] = true,
},
},
["Games"] = {
"/sc 6_4",
true,
["Action"] = true,
["Puzzle"] = true,
["Strategy"] = true,
["Racing"] = true,
["RPG"] = true,
["Obstacle Course"] = true,
["Tycoon"] = true,
["Roblox"] = {
["BrickBattle"] = true,
["Community Building"] = true,
["Roblox Minigames"] = true,
["Contest Place"] = true,
},
["Board games"] = {
["Chess"] = true,
["Checkers"] = true,
["Settlers of Catan"] = true,
["Tigris and Euphrates"] = true,
["El Grande"] = true,
["Stratego"] = true,
["Carcassonne"] = true,
},
},
["Sports"] = {
"/sc 6_5",
true,
["Hockey"] = true,
["Soccer"] = true,
["Football"] = true,
["Baseball"] = true,
["Basketball"] = true,
["Volleyball"] = true,
["Tennis"] = true,
["Sports team practice"] = true,
["Watersports"] = { ["Surfing"] = true, ["Swimming"] = true, ["Water Polo"] = true },
["Winter sports"] = {
["Skiing"] = true,
["Snowboarding"] = true,
["Sledding"] = true,
["Skating"] = true,
},
["Adventure"] = {
["Rock climbing"] = true,
["Hiking"] = true,
["Fishing"] = true,
["Horseback riding"] = true,
},
["Wacky"] = {
["Foosball"] = true,
["Calvinball"] = true,
["Croquet"] = true,
["Cricket"] = true,
["Dodgeball"] = true,
["Squash"] = true,
["Trampoline"] = true,
},
},
["Movies/TV"] = {
"/sc 6_6",
true,
["Science Fiction"] = true,
["Animated"] = { ["Anime"] = true },
["Comedy"] = true,
["Romantic"] = true,
["Action"] = true,
["Fantasy"] = true,
},
["Music"] = {
"/sc 6_7",
true,
["Country"] = true,
["Jazz"] = true,
["Rap"] = true,
["Hip-hop"] = true,
["Techno"] = true,
["Classical"] = true,
["Pop"] = true,
["Rock"] = true,
},
["Hobbies"] = {
"/sc 6_8",
true,
["Computers"] = {
["Building computers"] = true,
["Videogames"] = true,
["Coding"] = true,
["Hacking"] = true,
},
["The Internet"] = { ["lol. teh internets!"] = true, ["Watching vids"] = true },
["Dance"] = true,
["Gymnastics"] = true,
["Listening to music"] = true,
["Arts and crafts"] = true,
["Martial Arts"] = {
["Karate"] = true,
["Judo"] = true,
["Taikwon Do"] = true,
["Wushu"] = true,
["Street fighting"] = true,
},
["Music lessons"] = {
["Playing in my band"] = true,
["Playing piano"] = true,
["Playing guitar"] = true,
["Playing violin"] = true,
["Playing drums"] = true,
["Playing a weird instrument"] = true,
},
},
["Location"] = {
"/sc 6_9",
true,
["USA"] = {
["West"] = {
["Alaska"] = true,
["Arizona"] = true,
["California"] = true,
["Colorado"] = true,
["Hawaii"] = true,
["Idaho"] = true,
["Montana"] = true,
["Nevada"] = true,
["New Mexico"] = true,
["Oregon"] = true,
["Utah"] = true,
["Washington"] = true,
["Wyoming"] = true,
},
["South"] = {
["Alabama"] = true,
["Arkansas"] = true,
["Florida"] = true,
["Georgia"] = true,
["Kentucky"] = true,
["Louisiana"] = true,
["Mississippi"] = true,
["North Carolina"] = true,
["Oklahoma"] = true,
["South Carolina"] = true,
["Tennessee"] = true,
["Texas"] = true,
["Virginia"] = true,
["West Virginia"] = true,
},
["Northeast"] = {
["Connecticut"] = true,
["Delaware"] = true,
["Maine"] = true,
["Maryland"] = true,
["Massachusetts"] = true,
["New Hampshire"] = true,
["New Jersey"] = true,
["New York"] = true,
["Pennsylvania"] = true,
["Rhode Island"] = true,
["Vermont"] = true,
},
["Midwest"] = {
["Illinois"] = true,
["Indiana"] = true,
["Iowa"] = true,
["Kansas"] = true,
["Michigan"] = true,
["Minnesota"] = true,
["Missouri"] = true,
["Nebraska"] = true,
["North Dakota"] = true,
["Ohio"] = true,
["South Dakota"] = true,
["Wisconsin"] = true,
},
},
["Canada"] = {
["Alberta"] = true,
["British Columbia"] = true,
["Manitoba"] = true,
["New Brunswick"] = true,
["Newfoundland"] = true,
["Northwest Territories"] = true,
["Nova Scotia"] = true,
["Nunavut"] = true,
["Ontario"] = true,
["Prince Edward Island"] = true,
["Quebec"] = true,
["Saskatchewan"] = true,
["Yukon"] = true,
},
["Mexico"] = true,
["Central America"] = true,
["Europe"] = {
["France"] = true,
["Germany"] = true,
["Spain"] = true,
["Italy"] = true,
["Poland"] = true,
["Switzerland"] = true,
["Greece"] = true,
["Romania"] = true,
["Netherlands"] = true,
["Great Britain"] = {
["England"] = true,
["Scotland"] = true,
["Wales"] = true,
["Northern Ireland"] = true,
},
},
["Asia"] = {
["China"] = true,
["India"] = true,
["Japan"] = true,
["Korea"] = true,
["Russia"] = true,
["Vietnam"] = true,
},
["South America"] = { ["Argentina"] = true, ["Brazil"] = true },
["Africa"] = { ["Eygpt"] = true, ["Swaziland"] = true },
["Australia"] = true,
["Middle East"] = true,
["Antarctica"] = true,
["New Zealand"] = true,
},
["Age"] = {
"/sc 6_10",
true,
["Rugrat"] = true,
["Kid"] = true,
["Tween"] = true,
["Teen"] = true,
["Twenties"] = true,
["Old"] = true,
["Ancient"] = true,
["Mesozoic"] = true,
["I don't want to say my age. Don't ask."] = true,
},
["Mood"] = {
"/sc 6_11",
true,
["Good"] = true,
["Great!"] = true,
["Not bad"] = true,
["Sad"] = true,
["Hyper"] = true,
["Chill"] = true,
["Happy"] = true,
["Kind of mad"] = true,
},
["Boy"] = { "/sc 6_12", true },
["Girl"] = { "/sc 6_13", true },
["I don't want to say boy or girl. Don't ask."] = { "/sc 6_14", true },
[1] = "/sc 6",
},
["Game"] = {
["Let's build"] = { "/sc 7_0", true },
["Let's battle"] = { "/sc 7_1", true },
["Nice one!"] = { "/sc 7_2", true },
["So far so good"] = { "/sc 7_3", true },
["Lucky shot!"] = { "/sc 7_4", true },
["Oh man!"] = { "/sc 7_5", true },
["I challenge you to a fight!"] = { "/sc 7_6", true },
["Help me with this"] = { "/sc 7_7", true },
["Let's go to your game"] = { "/sc 7_8", true },
["Can you show me how do to that?"] = { "/sc 7_9", true },
["Backflip!"] = { "/sc 7_10", true },
["Frontflip!"] = { "/sc 7_11", true },
["Dance!"] = { "/sc 7_12", true },
["I'm on your side!"] = { "/sc 7_13", true },
["Game Commands"] = {
"/sc 7_14",
true,
["regen"] = true,
["reset"] = true,
["go"] = true,
["fix"] = true,
["respawn"] = true,
},
[1] = "/sc 7",
},
["Silly"] = {
["Muahahahaha!"] = true,
["all your base are belong to me!"] = true,
["GET OFF MAH LAWN"] = true,
["TEH EPIK DUCK IS COMING!!!"] = true,
["ROFL"] = true,
["1337"] = {
true,
["i r teh pwnz0r!"] = true,
["w00t!"] = true,
["z0mg h4x!"] = true,
["ub3rR0xXorzage!"] = true,
},
},
["Yes"] = {
["Absolutely!"] = true,
["Rock on!"] = true,
["Totally!"] = true,
["Juice!"] = true,
["Yay!"] = true,
["Yesh"] = true,
},
["No"] = {
["Ummm. No."] = true,
["..."] = true,
["Stop!"] = true,
["Go away!"] = true,
["Don't do that"] = true,
["Stop breaking the rules"] = true,
["I don't want to"] = true,
},
["Ok"] = {
["Well... ok"] = true,
["Sure"] = true,
},
["Uncertain"] = {
["Maybe"] = true,
["I don't know"] = true,
["idk"] = true,
["I can't decide"] = true,
["Hmm..."] = true,
},
[":-)"] = {
[":-("] = true,
[":D"] = true,
[":-O"] = true,
["lol"] = true,
["=D"] = true,
["D="] = true,
["XD"] = true,
[";D"] = true,
[";)"] = true,
["O_O"] = true,
["=)"] = true,
["@_@"] = true,
["&gt;_&lt;"] = true,
["T_T"] = true,
["^_^"] = true,
["<(0_0<) <(0_0)> (>0_0)> KIRBY DANCE"] = true,
[")';"] = true,
[":3"] = true,
},
["Ratings"] = {
["Rate it!"] = true,
["I give it a 1 out of 10"] = true,
["I give it a 2 out of 10"] = true,
["I give it a 3 out of 10"] = true,
["I give it a 4 out of 10"] = true,
["I give it a 5 out of 10"] = true,
["I give it a 6 out of 10"] = true,
["I give it a 7 out of 10"] = true,
["I give it a 8 out of 10"] = true,
["I give it a 9 out of 10"] = true,
["I give it a 10 out of 10!"] = true,
},
},
CreateEnum "SafeChat" { "Level1", "Level2", "Level3" },
SafeChatTree = {},
TempSpaceLabel = nil,
}
---------------------------------------------------
local function GetNameValue(pName)
local value = 0
for index = 1, #pName do
local cValue = string.byte(string.sub(pName, index, index))
local reverseIndex = #pName - index + 1
if #pName % 2 == 1 then
reverseIndex = reverseIndex - 1
end
if reverseIndex % 4 >= 2 then
cValue = -cValue
end
value = value + cValue
end
return value % 8
end
function Chat:ComputeChatColor(pName)
return self.ChatColors[GetNameValue(pName) + 1].Color
end
-- This is context based scrolling
function Chat:EnableScrolling(toggle)
-- Genius idea gone to fail, if we switch the camera type we can effectively lock the
-- camera and do no click scrolling
self.MouseOnFrame = false
if self.RenderFrame then
self.RenderFrame.MouseEnter:connect(function()
local character = Player.Character
local torso = WaitForChild(character, "Torso")
local humanoid = WaitForChild(character, "Humanoid")
local head = WaitForChild(character, "Head")
if toggle then
self.MouseOnFrame = true
Camera.CameraType = "Scriptable"
-- Get relative position of camera and keep to it
Spawn(function()
local currentRelativePos = Camera.CoordinateFrame.p - torso.Position
while Chat.MouseOnFrame do
Camera.CoordinateFrame = CFrame.new(torso.Position + currentRelativePos, head.Position)
wait(0.015)
end
end)
end
end)
self.RenderFrame.MouseLeave:connect(function()
Camera.CameraType = "Custom"
self.MouseOnFrame = false
end)
end
end
-- TODO: Scrolling using Mouse wheel
-- function Chat:OnScroll(speed)
-- if self.MouseOnFrame then
-- --
-- end
-- end
-- Check if we are running on a touch device
function Chat:IsTouchDevice()
local touchEnabled = false
pcall(function()
touchEnabled = Game:GetService("UserInputService").TouchEnabled
end)
return touchEnabled
end
-- Scrolling
-- function Chat:ScrollQueue(value)
-- --[[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
-- local previous = self.MessageQueue[i].Previous
-- if label and label:IsA('TextLabel') or label:IsA('TextButton') then
-- if value > 0 and previous and previous['Message'] then
-- label.Position = previous['Message'].Position
-- elseif value < 1 and next['Message'] then
-- label.Position = previous['Message'].Position
-- 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
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
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
end
end
end
end
end
end
end
function Chat:CreateScrollBar()
-- Code for scrolling is in here, partially, but scroll bar drawing isn't drawn
-- TODO: Implement
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
return true
end
if
value > 0
and Chat.MessageQueue[1]
and Chat.MessageQueue[1]["Player"]
and Chat.MessageQueue[1]["Player"].Position.Y.Scale == 0
then
return true
elseif
value < 0
and Chat.MessageQueue[1]
and Chat.MessageQueue[1]["Player"]
and Chat.MessageQueue[1]["Player"].Position.Y.Scale < 0
then
return true
else
return false
end
return false
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 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,
Text = nString,
Name = "SpaceButton",
}
else
self.TempSpaceLabel.Text = nString
end
while self.TempSpaceLabel.TextBounds.X < pLabel.TextBounds.X do
nString = nString .. " "
self.TempSpaceLabel.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)
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']
mLabel = self.MessageQueue[#self.MessageQueue]['Message']
pLabel.Text = pName .. ':'
pLabel.Name = pName
local pColor
if cPlayer.Neutral then
pLabel.TextColor3 = Chat:ComputeChatColor(pName)
else
pLabel.TextColor3 = cPlayer.TeamColor.Color
end
local nString
if not self.CachedSpaceStrings_List[pName] then
nString = Chat:ComputeSpaceString(pLabel)
else
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
-- Haven't hit the mark yet, so keep creating
pLabel = Gui.Create "TextLabel" {
Name = pName,
Text = pName .. ":",
TextColor3 = pColor,
FontSize = Chat.Configuration.FontSize,
TextXAlignment = Enum.TextXAlignment.Left,
TextYAlignment = Enum.TextYAlignment.Top,
Parent = self.RenderFrame,
TextWrapped = false,
Size = UDim2.new(1, 0, 0.1, 0),
BackgroundTransparency = 1,
TextTransparency = 1,
Position = UDim2.new(0, 0, 1, 0),
BorderSizePixel = 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
if not self.CachedSpaceStrings_List[pName] then
nString = Chat:ComputeSpaceString(pLabel)
else
nString = self.CachedSpaceStrings_List[pName]
end
mLabel = Gui.Create "TextLabel" {
Name = pName .. " - message",
-- Max is 3 lines
Size = UDim2.new(1, 0, 0.5, 0),
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,
TextTransparency = 1,
Position = UDim2.new(0, 0, 1, 0),
BorderSizePixel = 0,
TextStrokeColor3 = Color3.new(0, 0, 0),
--TextStrokeTransparency = 0.8;
--Active = false;
}
mLabel.Text = nString .. message
if not pName then
pLabel.Text = ""
mLabel.TextColor3 = Color3.new(0, 0.4, 1.0)
end
--end
for _, adminName in pairs(self.Admins_List) do
if string.lower(adminName) == string.lower(pName) then
mLabel.TextColor3 = self.Configuration.AdminMessageColor
end
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
local queueField = {}
queueField["Player"] = pLabel
queueField["Message"] = mLabel
queueField["SpawnTime"] = tick() -- Used for identifying when to make the message invisible
table.insert(self.MessageQueue, 1, queueField)
Chat:UpdateQueue(queueField)
end
function Chat:ScreenSizeChanged()
wait()
while self.Frame.AbsoluteSize.Y > 120 do
self.Frame.Size = self.Frame.Size - UDim2.new(0, 0, 0.005, 0)
end
Chat:RecalculateSpacing()
end
function Chat:FindButtonTree(scButton, rootList)
local list = {}
rootList = rootList or self.SafeChatTree
for button, _ in pairs(rootList) do
if button == scButton then
list = rootList[button]
elseif type(rootList[button]) == "table" then
list = Chat:FindButtonTree(scButton, rootList[button])
end
end
return list
end
function Chat:ToggleSafeChatMenu(scButton)
local list = Chat:FindButtonTree(scButton, self.SafeChatTree)
if list then
for button, _ in pairs(list) do
if button:IsA "TextButton" or button:IsA "ImageButton" then
button.Visible = not button.Visible
end
end
return true
end
return false
end
function Chat:CreateSafeChatOptions(list, rootButton)
local text_List = {}
level = level or 0
local count = 0
text_List[rootButton] = {}
text_List[rootButton][1] = list[1]
rootButton = rootButton or self.SafeChatButton
for msg, _ in pairs(list) do
if type(msg) == "string" then
local chatText = Gui.Create "TextButton" {
Name = msg,
Text = msg,
Size = UDim2.new(0, 100, 0, 20),
TextXAlignment = Enum.TextXAlignment.Center,
TextColor3 = Color3.new(0.2, 0.1, 0.1),
BackgroundTransparency = 0.5,
BackgroundColor3 = Color3.new(1, 1, 1),
Parent = self.SafeChatFrame,
Visible = false,
Position = UDim2.new(
0,
rootButton.Position.X.Scale + 105,
0,
rootButton.Position.Y.Scale - ((count - 3) * 100)
),
}
count = count + 1
if type(list[msg]) == "table" then
text_List[rootButton][chatText] = Chat:CreateSafeChatOptions(list[msg], chatText)
else
--table.insert(text_List[chatText], true)
end
chatText.MouseEnter:connect(function()
Chat:ToggleSafeChatMenu(chatText)
end)
chatText.MouseLeave:connect(function()
Chat:ToggleSafeChatMenu(chatText)
end)
chatText.MouseButton1Click:connect(function()
local lList = Chat:FindButtonTree(chatText)
if lList then
for i, v in pairs(lList) do
end
else
end
pcall(function()
PlayersService:Chat(lList[1])
end)
end)
end
end
return text_List
end
function Chat:CreateSafeChatGui()
self.SafeChatFrame = Gui.Create "Frame" {
Name = "SafeChatFrame",
Size = UDim2.new(1, 0, 1, 0),
Parent = self.Gui,
BackgroundTransparency = 1,
Gui.Create "ImageButton" {
Name = "SafeChatButton",
Size = UDim2.new(0, 44, 0, 31),
Position = UDim2.new(0, 1, 0.35, 0),
BackgroundTransparency = 1,
Image = "http://www.roblox.com/asset/?id=97080365",
},
}
self.SafeChatButton = self.SafeChatFrame.SafeChatButton
-- safe chat button is the root of this tree
self.SafeChatTree[self.SafeChatButton] = Chat:CreateSafeChatOptions(self.SafeChat_List, self.SafeChatButton)
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,
Parent = self.Gui,
Gui.Create "ImageButton" {
Name = "ChatLabel",
Size = UDim2.new(0, 74, 0, 28),
Position = UDim2.new(0, 0, 0, 0),
BackgroundTransparency = 1,
ZIndex = 2.0,
},
Gui.Create "ImageLabel" {
Name = "Background",
Size = UDim2.new(1, 0, 1, 0),
Position = UDim2.new(0, 0, 0, 0),
BackgroundTransparency = 1,
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,
BackgroundTransparency = 1,
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 forceChatGUI or (status and result) then
self.ClickToChatButton = Gui.Create "TextButton" {
Name = "ClickToChat",
Size = UDim2.new(1, 0, 0, 20),
BackgroundTransparency = 1,
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,
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,
--ClipsDescendants = true;
ZIndex = 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,
ZIndex = 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,
BackgroundColor3 = Color3.new(236 / 255, 236 / 255, 236 / 255),
BorderSizePixel = 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,
--ClipsDescendants = true;
ZIndex = 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 forceChatGUI or 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
-- Applies a speed(velocity) to have nice scrolling effect
function Input:OnMouseScroll()
Spawn(function()
-- How long should the speed last?
while Input.Speed ~= 0 do
if Input.Speed > 1 then
while Input.Speed > 0 do
Input.Speed = Input.Speed - 1
wait(0.25)
end
elseif Input.Speed < 0 then
while Input.Speed < 0 do
Input.Speed = Input.Speed + 1
wait(0.25)
end
end
wait(0.03)
end
end)
if Chat:CheckIfInBounds(Input.Speed) then
return
end
Chat:ScrollQueue()
end
function Input:ApplySpeed(value)
Input.Speed = Input.Speed + value
if not self.Simulating then
Input:OnMouseScroll()
end
end
function Input:Initialize()
self.Mouse.WheelBackward:connect(function()
Input:ApplySpeed(self.Configuration.DefaultSpeed)
end)
self.Mouse.WheelForward:connect(function()
Input:ApplySpeed(self.Configuration.DefaultSpeed)
end)
end
function Chat:FindMessageInSafeChat(message, list)
local foundMessage = false
for msg, _ in pairs(list) do
if msg == message then
return true
end
if type(list[msg]) == "table" then
foundMessage = Chat:FindMessageInSafeChat(message, list[msg])
if foundMessage then
return true
end
end
end
return foundMessage
end
-- Just a wrapper around our PlayerChatted event
function Chat:PlayerChatted(...)
local args = { ... }
local argCount = select("#", ...)
local player
local message
-- This doesn't look very good, but what else to do?
if args[2] then
player = args[2]
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 string.sub(message, 1, 3) == "/e " or string.sub(message, 1, 7) == "/emote " then
-- don't do anything right now
elseif forceChatGUI or Player.ChatMode == Enum.ChatMode.TextAndMenu then
Chat:UpdateChat(player, message)
elseif Player.ChatMode == Enum.ChatMode.Menu and string.sub(message, 1, 3) == "/sc" then
Chat:UpdateChat(player, message)
else
if Chat:FindMessageInSafeChat(message, self.SafeChat_List) then
Chat:UpdateChat(player, message)
end
end
end
end
-- After Chat.Configuration.Lifetime seconds 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
field["Player"].Visible = false
field["Message"].Visible = false
end
end
end
wait(5.0)
end
end
-- RobloxLock everything so users can't delete them(?)
function Chat:LockAllFields(gui)
local children = gui:GetChildren()
for i = 1, #children do
children[i].RobloxLocked = true
if #children[i]:GetChildren() > 0 then
Chat:LockAllFields(children[i])
end
end
end
function Chat:CoreGuiChanged(coreGuiType, enabled)
if coreGuiType == Enum.CoreGuiType.Chat or coreGuiType == Enum.CoreGuiType.All then
if self.Frame then
self.Frame.Visible = enabled
end
if not Chat:IsTouchDevice() and self.ChatBar then
self.ChatBar.Visible = enabled
if enabled then
GuiService:SetGlobalGuiInset(0, 0, 0, 20)
else
GuiService:SetGlobalGuiInset(0, 0, 0, 0)
end
end
end
end
-- Constructor
-- This function initializes everything
function Chat:Initialize()
Chat:CreateGui()
pcall(function()
Chat:CoreGuiChanged(Enum.CoreGuiType.Chat, Game.StarterGui:GetCoreGuiEnabled(Enum.CoreGuiType.Chat))
Game.StarterGui.CoreGuiChangedSignal:connect(function(coreGuiType, enabled)
Chat:CoreGuiChanged(coreGuiType, enabled)
end)
end)
self.EventListener = PlayersService.PlayerChatted:connect(function(...)
-- This event has 4 callback arguments
-- Enum.PlayerChatType.All, chatPlayer, message, targetPlayer
Chat:PlayerChatted(...)
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()
Chat.EventListener:disconnect()
self.EventListener = PlayersService.PlayerChatted:connect(function(...)
-- This event has 4 callback arguments
-- Enum.PlayerChatType.All, chatPlayer, message, targetPlayer
Chat:PlayerChatted(...)
end)
end)
Spawn(function()
Chat:CullThread()
end)
self.Frame.RobloxLocked = true
Chat:LockAllFields(self.Frame)
self.Frame.DescendantAdded:connect(function(descendant)
Chat:LockAllFields(descendant)
end)
end
Chat:Initialize()