SHOW:
|
|
- or go back to the newest paste.
| 1 | --game:GetService("StarterGui"):SetCoreGuiEnabled("Chat", false)
| |
| 2 | local NameColorDependsOnChatColor = true | |
| 3 | local StrokeTransparency = 0.5 -- Number 0 to 1. Lower stroke transparency is easier to read against colorful backgrounds. | |
| 4 | ||
| 5 | while not _G.PlayerListAPI do wait() end | |
| 6 | local PLAYERLIST_ADMINS, PLAYERLIST_CHATCOLORS, PLAYERLIST_ALIASES = _G.PlayerListAPI:GetChatData() | |
| 7 | ||
| 8 | local forceChatGUI = false | |
| 9 | ||
| 10 | -- Utility functions + Globals | |
| 11 | local function WaitForChild(parent, childName) | |
| 12 | while parent:FindFirstChild(childName) == nil do | |
| 13 | parent.ChildAdded:wait(0.03) | |
| 14 | end | |
| 15 | return parent[childName] | |
| 16 | end | |
| 17 | ||
| 18 | local function typedef(obj) | |
| 19 | return obj | |
| 20 | end | |
| 21 | ||
| 22 | local function IsPhone() | |
| 23 | local rGui = script.Parent | |
| 24 | if rGui.AbsoluteSize.Y < 600 then | |
| 25 | return true | |
| 26 | end | |
| 27 | return false | |
| 28 | end | |
| 29 | ||
| 30 | local export = {}
| |
| 31 | export.NameColorDependsOnChatColor = NameColorDependsOnChatColor | |
| 32 | ||
| 33 | export.SetNameColorDependsOnChatColor = function(self, b) | |
| 34 | self.NameColorDependsOnChatColor = b | |
| 35 | end | |
| 36 | ||
| 37 | -- Users can use enough white spaces to spoof chatting as other players | |
| 38 | -- This function removes trailing and leading white spaces | |
| 39 | -- AFAIK, there is no reason for spam white spaces | |
| 40 | local function StringTrim(str) | |
| 41 | -- %S is whitespaces | |
| 42 | -- When we find the first non space character defined by ^%s | |
| 43 | -- we yank out anything in between that and the end of the string | |
| 44 | -- Everything else is replaced with %1 which is essentially nothing | |
| 45 | return (str:gsub("^%s*(.-)%s*$", "%1"))
| |
| 46 | end | |
| 47 | ||
| 48 | while Game.Players.LocalPlayer == nil do wait(0.03) end | |
| 49 | ||
| 50 | local Player = Game.Players.LocalPlayer | |
| 51 | while Player.Character == nil do wait(0.03) end | |
| 52 | local RbxUtility = LoadLibrary('RbxUtility')
| |
| 53 | local Gui = typedef(RbxUtility) | |
| 54 | local Camera = Game.Workspace.CurrentCamera | |
| 55 | ||
| 56 | -- Services | |
| 57 | local CoreGuiService = Game:GetService('CoreGui')
| |
| 58 | local PlayersService = Game:GetService('Players')
| |
| 59 | local DebrisService= Game:GetService('Debris')
| |
| 60 | local GuiService = Game:GetService('GuiService')
| |
| 61 | ||
| 62 | -- Lua Enums | |
| 63 | local Enums do | |
| 64 | Enums = {}
| |
| 65 | local EnumName = {} -- used as unique key for enum name
| |
| 66 | local enum_mt = {
| |
| 67 | __call = function(self,value) | |
| 68 | return self[value] or self[tonumber(value)] | |
| 69 | end; | |
| 70 | __index = {
| |
| 71 | GetEnumItems = function(self) | |
| 72 | local t = {}
| |
| 73 | for i,item in pairs(self) do | |
| 74 | if type(i) == 'number' then | |
| 75 | t[#t+1] = item | |
| 76 | end | |
| 77 | end | |
| 78 | table.sort(t,function(a,b) return a.Value < b.Value end) | |
| 79 | return t | |
| 80 | end; | |
| 81 | }; | |
| 82 | __tostring = function(self) | |
| 83 | return "Enum." .. self[EnumName] | |
| 84 | end; | |
| 85 | } | |
| 86 | local item_mt = {
| |
| 87 | __call = function(self,value) | |
| 88 | return value == self or value == self.Name or value == self.Value | |
| 89 | end; | |
| 90 | __tostring = function(self) | |
| 91 | return "Enum." .. self[EnumName] .. "." .. self.Name | |
| 92 | end; | |
| 93 | } | |
| 94 | function CreateEnum(enumName) | |
| 95 | return function(t) | |
| 96 | local e = {[EnumName] = enumName}
| |
| 97 | for i,name in pairs(t) do | |
| 98 | local item = setmetatable({Name=name,Value=i,Enum=e,[EnumName]=enumName},item_mt)
| |
| 99 | e[i] = item | |
| 100 | e[name] = item | |
| 101 | e[item] = item | |
| 102 | end | |
| 103 | Enums[enumName] = e | |
| 104 | return setmetatable(e, enum_mt) | |
| 105 | end | |
| 106 | end | |
| 107 | end | |
| 108 | --------------------------------------------------- | |
| 109 | ------------------ Input class -------------------- | |
| 110 | local Input = {
| |
| 111 | Mouse = Player:GetMouse(), | |
| 112 | Speed = 0, | |
| 113 | Simulating = false, | |
| 114 | ||
| 115 | Configuration = {
| |
| 116 | DefaultSpeed = 1 | |
| 117 | }, | |
| 118 | UserIsScrolling = false | |
| 119 | } | |
| 120 | ||
| 121 | --------------------------------------------------- | |
| 122 | ------------------ Chat class -------------------- | |
| 123 | local Chat = {
| |
| 124 | ||
| 125 | ChatColors = {
| |
| 126 | BrickColor.new("Bright red"),
| |
| 127 | BrickColor.new("Bright blue"),
| |
| 128 | BrickColor.new("Earth green"),
| |
| 129 | BrickColor.new("Bright violet"),
| |
| 130 | BrickColor.new("Bright orange"),
| |
| 131 | BrickColor.new("Bright yellow"),
| |
| 132 | BrickColor.new("Light reddish violet"),
| |
| 133 | BrickColor.new("Brick yellow"),
| |
| 134 | }, | |
| 135 | ||
| 136 | Gui = nil, | |
| 137 | Frame = nil, | |
| 138 | RenderFrame = nil, | |
| 139 | TapToChatLabel = nil, | |
| 140 | ClickToChatButton = nil, | |
| 141 | ||
| 142 | ScrollingLock = false, | |
| 143 | EventListener = nil, | |
| 144 | ||
| 145 | -- This is actually a ring buffer | |
| 146 | -- Meaning at hitting the historyLength it wraps around | |
| 147 | -- Reuses the text objects, so chat atmost uses 100 text objects | |
| 148 | MessageQueue = {},
| |
| 149 | ||
| 150 | -- Stores all the values for configuring chat | |
| 151 | Configuration = {
| |
| 152 | FontSize = Enum.FontSize.Size12, -- 10 is good | |
| 153 | -- Also change this when you are changing the above, this is suboptimal but so is our interface to find FontSize | |
| 154 | NumFontSize = 12, | |
| 155 | HistoryLength = 20, -- stores up to 50 of the last chat messages for you to scroll through, | |
| 156 | Size = UDim2.new(0.38, 0, 0.20, 0), | |
| 157 | MessageColor = Color3.new(1, 1, 1), | |
| 158 | AdminMessageColor = Color3.new(1, 215/255, 0), | |
| 159 | XScale = 0.025, | |
| 160 | LifeTime = 45, | |
| 161 | Position = UDim2.new(0, 2, 0.05, 0), | |
| 162 | DefaultTweenSpeed = 0.15, | |
| 163 | }, | |
| 164 | ||
| 165 | -- This could be redone by just using the previous and next fields of the Queue | |
| 166 | -- But the iterators cause issues, will be optimized later | |
| 167 | SlotPositions_List = {},
| |
| 168 | -- To precompute and store all player null strings since its an expensive process | |
| 169 | CachedSpaceStrings_List = {},
| |
| 170 | MouseOnFrame = false, | |
| 171 | GotFocus = false, | |
| 172 | ||
| 173 | Messages_List = {},
| |
| 174 | MessageThread = nil, | |
| 175 | ||
| 176 | Admins_List = PLAYERLIST_ADMINS, | |
| 177 | ||
| 178 | SafeChat_List = {
| |
| 179 | ['Use the Chat menu to talk to me.'] = {'/sc 0', true},
| |
| 180 | ['I can only see menu chats.'] = {'/sc 1', true},
| |
| 181 | ['Hello'] = {
| |
| 182 | ['Hi'] = {'/sc 2_0', true, ['Hi there!'] = true, ['Hi everyone'] = true},
| |
| 183 | ['Howdy'] = {'/sc 2_1', true, ['Howdy partner!'] = true},
| |
| 184 | ['Greetings'] = {'/sc 2_2', true, ['Greetings everyone'] = true, ['Greetings Robloxians!'] = true, ['Seasons greetings!'] = true},
| |
| 185 | ['Welcome'] = {'/sc 2_3', true, ['Welcome to my place'] = true, ['Welcome to my barbeque'] = true, ['Welcome to our base'] = true},
| |
| 186 | ['Hey there!'] = {'/sc 2_4', true},
| |
| 187 | ['What\'s up?'] = {'/sc 2_5', true, ['How are you doing?'] = true, ['How\'s it going?'] = true, ['What\'s new?'] = true},
| |
| 188 | ['Good day'] = {'/sc 2_6', true, ['Good morning'] = true, ['Good evening'] = true, ['Good afternoon'] = true, ['Good night'] = true},
| |
| 189 | ['Silly'] = {'/sc 2_7', true, ['Waaaaaaaz up?!'] = true, ['Hullo!'] = true, ['Behold greatness, mortals!'] = true, ['Pardon me, is this Sparta?'] = true, ['THIS IS SPARTAAAA!'] = true},
| |
| 190 | ['Happy Holidays!'] = {'/sc 2_8', true, ['Happy New Year!'] = true,
| |
| 191 | ['Happy Valentine\'s Day!'] = true, | |
| 192 | ['Beware the Ides of March!'] = true, | |
| 193 | ['Happy St. Patrick\'s Day!'] = true, | |
| 194 | ['Happy Easter!'] = true, | |
| 195 | ['Happy Earth Day!'] = true, | |
| 196 | ['Happy 4th of July!'] = true, | |
| 197 | ['Happy Thanksgiving!'] = true, | |
| 198 | ['Happy Halloween!'] = true, | |
| 199 | ['Happy Hanukkah!'] = true, | |
| 200 | ['Merry Christmas!'] = true, | |
| 201 | ['Happy Halloween!'] = true, | |
| 202 | ['Happy Earth Day!'] = true, | |
| 203 | ['Happy May Day!'] = true, | |
| 204 | ['Happy Towel Day!'] = true, | |
| 205 | ['Happy ROBLOX Day!'] = true, | |
| 206 | ['Happy LOL Day!'] = true }, | |
| 207 | ||
| 208 | [1] = '/sc 2' | |
| 209 | }, | |
| 210 | ['Goodbye'] = {
| |
| 211 | ['Good Night']= {'/sc 3_0', true,
| |
| 212 | ['Sweet dreams'] = true, | |
| 213 | ['Go to sleep!'] = true, | |
| 214 | ['Lights out!'] = true, | |
| 215 | ['Bedtime'] = true, | |
| 216 | ['Going to bed now'] = true}, | |
| 217 | ||
| 218 | ['Later']= {'/sc 3_1', true,
| |
| 219 | ['See ya later'] = true, | |
| 220 | ['Later gator!'] = true, | |
| 221 | ['See you tomorrow'] = true}, | |
| 222 | ||
| 223 | ['Bye'] = {'/sc 3_2', true, ['Hasta la bye bye!'] = true},
| |
| 224 | ['I\'ll be right back'] = {'/sc 3_3', true},
| |
| 225 | ['I have to go'] = {'/sc 3_4', true},
| |
| 226 | ['Farewell'] = {'/sc 3_5', true, ['Take care'] = true, ['Have a nice day'] = true, ['Goodluck!'] = true, ['Ta-ta for now!'] = true},
| |
| 227 | ['Peace'] = {'/sc 3_6', true, ['Peace out!'] = true, ['Peace dudes!'] = true, ['Rest in pieces!'] = true},
| |
| 228 | ['Silly'] = {'/sc 3_7', true,
| |
| 229 | ['To the batcave!'] = true, | |
| 230 | ['Over and out!'] = true, | |
| 231 | ['Happy trails!'] = true, | |
| 232 | ['I\'ve got to book it!'] = true, | |
| 233 | ['Tootles!'] = true, | |
| 234 | ['Smell you later!'] = true, | |
| 235 | ['GG!'] = true, | |
| 236 | ['My house is on fire! gtg.'] = true}, | |
| 237 | [1] = '/sc 3' | |
| 238 | }, | |
| 239 | ['Friend'] ={
| |
| 240 | ['Wanna be friends?'] = {'/sc 4_0', true},
| |
| 241 | ['Follow me'] = {'/sc 4_1', true, ['Come to my place!'] = true, ['Come to my base!'] = true, ['Follow me, team!'] = true, ['Follow me'] = true},
| |
| 242 | ['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},
| |
| 243 | ['Thank you'] = {'/sc 4_3', true, ['Thanks for playing'] = true, ['Thanks for visiting'] = true, ['Thanks for everything'] = true, ['No, thank you'] = true, ['Thanx'] = true},
| |
| 244 | ['No problem'] = {'/sc 4_4', true, ['Don\'t worry'] = true, ['That\'s ok'] = true, ['np'] = true},
| |
| 245 | ['You are ...'] = {'/sc 4_5', true,
| |
| 246 | ['You are great!'] = true, | |
| 247 | ['You are good!'] = true, | |
| 248 | ['You are cool!'] = true, | |
| 249 | ['You are funny!'] = true, | |
| 250 | ['You are silly!'] = true, | |
| 251 | ['You are awesome!'] = true, | |
| 252 | ['You are doing something I don\'t like, please stop'] = true | |
| 253 | }, | |
| 254 | ['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,
| |
| 255 | ['I like you'] = true, ['I like items'] = true, ['I like money'] = true}, | |
| 256 | ['Sorry'] = {'/sc 4_7', true, ['My bad!'] = true, ['I\'m sorry'] = true, ['Whoops!'] = true, ['Please forgive me.'] = true, ['I forgive you.'] = true,
| |
| 257 | ['I didn\'t mean to do that.'] = true, ['Sorry, I\'ll stop now.'] = true}, | |
| 258 | [1] = '/sc 4' | |
| 259 | }, | |
| 260 | ['Questions'] = {
| |
| 261 | ['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},
| |
| 262 | ['What?'] = {'/sc 5_1', true, ['What is your favorite animal?'] = true, ['What is your favorite game?'] = true, ['What is your favorite movie?'] = true,
| |
| 263 | ['What is your favorite TV show?'] = true, ['What is your favorite music?'] = true, ['What are your hobbies?'] = true, ['LOLWUT?'] = true}, | |
| 264 | ['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},
| |
| 265 | ['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},
| |
| 266 | ['How?'] = {'/sc 5_4', true, ['How are you today?'] = true, ['How did you make this cool place?'] = true, ['LOLHOW?'] = true},
| |
| 267 | ['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,
| |
| 268 | ['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}, | |
| 269 | [1] = '/sc 5' | |
| 270 | }, | |
| 271 | ['Answers'] = {
| |
| 272 | ['You need help?'] = {'/sc 6_0', true, ['Check out the news section'] = true, ['Check out the help section'] = true, ['Read the wiki!'] = true,
| |
| 273 | ['All the answers are in the wiki!'] = true, ['I will help you with this.'] = true}, | |
| 274 | ['Some people ...'] = {'/sc 6_1', true, ['Me'] = true, ['Not me'] = true, ['You'] = true, ['All of us'] = true, ['Everyone but you'] = true, ['Builderman!'] = true,
| |
| 275 | ['Telamon!'] = true, ['My team'] = true, ['My group'] = true, ['Mom'] = true, ['Dad'] = true, ['Sister'] = true, ['Brother'] = true, ['Cousin'] = true, | |
| 276 | ['Grandparent'] = true, ['Friend'] = true}, | |
| 277 | ['Time ...'] = {'/sc 6_2', true, ['In the morning'] = true, ['In the afternoon'] = true, ['At night'] = true, ['Tomorrow'] = true, ['This week'] = true, ['This month'] = true,
| |
| 278 | ['Sometime'] = true, ['Sometimes'] = true, ['Whenever you want'] = true, ['Never'] = true, ['After this'] = true, ['In 10 minutes'] = true, ['In a couple hours'] = true, | |
| 279 | ['In a couple days'] = true}, | |
| 280 | ['Animals'] = {'/sc 6_3', true,
| |
| 281 | ['Cats'] = {['Lion'] = true, ['Tiger'] = true, ['Leopard'] = true, ['Cheetah'] = true},
| |
| 282 | ['Dogs'] = {['Wolves'] = true, ['Beagle'] = true, ['Collie'] = true, ['Dalmatian'] = true, ['Poodle'] = true, ['Spaniel'] = true,
| |
| 283 | ['Shepherd'] = true, ['Terrier'] = true, ['Retriever'] = true}, | |
| 284 | ['Horses'] = {['Ponies'] = true, ['Stallions'] = true, ['Pwnyz'] = true},
| |
| 285 | ['Reptiles'] = {['Dinosaurs'] = true, ['Lizards'] = true, ['Snakes'] = true, ['Turtles!'] = true},
| |
| 286 | ['Hamster'] = true, | |
| 287 | ['Monkey'] = true, | |
| 288 | ['Bears'] = true, | |
| 289 | ['Fish'] = {['Goldfish'] = true, ['Sharks'] = true, ['Sea Bass'] = true, ['Halibut'] = true, ['Tropical Fish'] = true},
| |
| 290 | ['Birds'] = {['Eagles'] = true, ['Penguins'] = true, ['Parakeets'] = true, ['Owls'] = true, ['Hawks'] = true, ['Pidgeons'] = true},
| |
| 291 | ['Elephants'] = true, | |
| 292 | ['Mythical Beasts'] = {['Dragons'] = true, ['Unicorns'] = true, ['Sea Serpents'] = true, ['Sphinx'] = true, ['Cyclops'] = true,
| |
| 293 | ['Minotaurs'] = true, ['Goblins'] = true, ['Honest Politicians'] = true, ['Ghosts'] = true, ['Scylla and Charybdis'] = true} | |
| 294 | }, | |
| 295 | ['Games'] = {'/sc 6_4', true,
| |
| 296 | ['Action'] = true, ['Puzzle'] = true, ['Strategy'] = true, ['Racing'] = true, ['RPG'] = true, ['Obstacle Course'] = true, ['Tycoon'] = true, | |
| 297 | ['Roblox'] = { ['BrickBattle'] = true, ['Community Building'] = true, ['Roblox Minigames'] = true, ['Contest Place'] = true},
| |
| 298 | ['Board games'] = { ['Chess'] = true, ['Checkers'] = true, ['Settlers of Catan'] = true, ['Tigris and Euphrates'] = true, ['El Grande'] = true,
| |
| 299 | ['Stratego'] = true, ['Carcassonne'] = true} | |
| 300 | }, | |
| 301 | ['Sports'] = {'/sc 6_5', true, ['Hockey'] = true, ['Soccer'] = true, ['Football'] = true, ['Baseball'] = true, ['Basketball'] = true,
| |
| 302 | ['Volleyball'] = true, ['Tennis'] = true, ['Sports team practice'] = true, | |
| 303 | ['Watersports'] = { ['Surfing'] = true,['Swimming'] = true, ['Water Polo'] = true},
| |
| 304 | ['Winter sports'] = { ['Skiing'] = true, ['Snowboarding'] = true, ['Sledding'] = true, ['Skating'] = true},
| |
| 305 | ['Adventure'] = {['Rock climbing'] = true, ['Hiking'] = true, ['Fishing'] = true, ['Horseback riding'] = true},
| |
| 306 | ['Wacky'] = {['Foosball'] = true, ['Calvinball'] = true, ['Croquet'] = true, ['Cricket'] = true, ['Dodgeball'] = true,
| |
| 307 | ['Squash'] = true, ['Trampoline'] = true} | |
| 308 | }, | |
| 309 | ['Movies/TV'] = {'/sc 6_6', true, ['Science Fiction'] = true, ['Animated'] = {['Anime'] = true}, ['Comedy'] = true, ['Romantic'] = true,
| |
| 310 | ['Action'] = true, ['Fantasy'] = true}, | |
| 311 | ['Music'] = {'/sc 6_7', true, ['Country'] = true, ['Jazz'] = true, ['Rap'] = true, ['Hip-hop'] = true, ['Techno'] = true, ['Classical'] = true,
| |
| 312 | ['Pop'] = true, ['Rock'] = true}, | |
| 313 | ['Hobbies'] = {'/sc 6_8', true,
| |
| 314 | ['Computers'] = { ['Building computers'] = true, ['Videogames'] = true, ['Coding'] = true, ['Hacking'] = true},
| |
| 315 | ['The Internet'] = { ['lol. teh internets!'] = true, ['Watching vids'] = true},
| |
| 316 | ['Dance'] = true, ['Gymnastics'] = true, ['Listening to music'] = true, ['Arts and crafts'] = true, | |
| 317 | ['Martial Arts'] = {['Karate'] = true, ['Judo'] = true, ['Taikwon Do'] = true, ['Wushu'] = true, ['Street fighting'] = true},
| |
| 318 | ['Music lessons'] = {['Playing in my band'] = true, ['Playing piano'] = true, ['Playing guitar'] = true,
| |
| 319 | ['Playing violin'] = true, ['Playing drums'] = true, ['Playing a weird instrument'] = true} | |
| 320 | }, | |
| 321 | ['Location'] = {'/sc 6_9', true,
| |
| 322 | ['USA'] = {
| |
| 323 | ['West'] = { ['Alaska'] = true, ['Arizona'] = true, ['California'] = true, ['Colorado'] = true, ['Hawaii'] = true,
| |
| 324 | ['Idaho'] = true, ['Montana'] = true, ['Nevada'] = true, ['New Mexico'] = true, ['Oregon'] = true, | |
| 325 | ['Utah'] = true, ['Washington'] = true, ['Wyoming'] = true | |
| 326 | }, | |
| 327 | ['South'] = { ['Alabama'] = true, ['Arkansas'] = true, ['Florida'] = true, ['Georgia'] = true, ['Kentucky'] = true,
| |
| 328 | ['Louisiana'] = true, ['Mississippi'] = true, ['North Carolina'] = true, ['Oklahoma'] = true, | |
| 329 | ['South Carolina'] = true, ['Tennessee'] = true, ['Texas'] = true, ['Virginia'] = true, ['West Virginia'] = true | |
| 330 | }, | |
| 331 | ['Northeast'] = {['Connecticut'] = true, ['Delaware'] = true, ['Maine'] = true, ['Maryland'] = true, ['Massachusetts'] = true,
| |
| 332 | ['New Hampshire'] = true, ['New Jersey'] = true, ['New York'] = true, ['Pennsylvania'] = true, ['Rhode Island'] = true, | |
| 333 | ['Vermont'] = true | |
| 334 | }, | |
| 335 | ['Midwest'] = {['Illinois'] = true, ['Indiana'] = true, ['Iowa'] = true, ['Kansas'] = true, ['Michigan'] = true, ['Minnesota'] = true,
| |
| 336 | ['Missouri'] = true, ['Nebraska'] = true, ['North Dakota'] = true, ['Ohio'] = true, ['South Dakota'] = true, ['Wisconsin'] = true} | |
| 337 | }, | |
| 338 | ['Canada'] = {['Alberta'] = true, ['British Columbia'] = true, ['Manitoba'] = true, ['New Brunswick'] = true, ['Newfoundland'] = true,
| |
| 339 | ['Northwest Territories'] = true, ['Nova Scotia'] = true, ['Nunavut'] = true, ['Ontario'] = true, ['Prince Edward Island'] = true, | |
| 340 | ['Quebec'] = true, ['Saskatchewan'] = true, ['Yukon'] = true}, | |
| 341 | ['Mexico'] = true, | |
| 342 | ['Central America'] = true, | |
| 343 | ['Europe'] = {['France'] = true, ['Germany'] = true, ['Spain'] = true, ['Italy'] = true, ['Poland'] = true, ['Switzerland'] = true,
| |
| 344 | ['Greece'] = true, ['Romania'] = true, ['Netherlands'] = true, | |
| 345 | ['Great Britain'] = {['England'] = true, ['Scotland'] = true, ['Wales'] = true, ['Northern Ireland'] = true}
| |
| 346 | }, | |
| 347 | ['Asia'] = { ['China'] = true, ['India'] = true, ['Japan'] = true, ['Korea'] = true, ['Russia'] = true, ['Vietnam'] = true},
| |
| 348 | ['South America'] = { ['Argentina'] = true, ['Brazil'] = true},
| |
| 349 | ['Africa'] = { ['Eygpt'] = true, ['Swaziland'] = true},
| |
| 350 | ['Australia'] = true, ['Middle East'] = true, ['Antarctica'] = true, ['New Zealand'] = true | |
| 351 | }, | |
| 352 | ['Age'] = {'/sc 6_10', true, ['Rugrat'] = true, ['Kid'] = true, ['Tween'] = true, ['Teen'] = true, ['Twenties'] = true,
| |
| 353 | ['Old'] = true, ['Ancient'] = true, ['Mesozoic'] = true, ['I don\'t want to say my age. Don\'t ask.'] = true}, | |
| 354 | ['Mood'] = {'/sc 6_11', true, ['Good'] = true, ['Great!'] = true, ['Not bad'] = true, ['Sad'] = true, ['Hyper'] = true,
| |
| 355 | ['Chill'] = true, ['Happy'] = true, ['Kind of mad'] = true}, | |
| 356 | ['Boy'] = {'/sc 6_12', true},
| |
| 357 | ['Girl'] = {'/sc 6_13', true},
| |
| 358 | ['I don\'t want to say boy or girl. Don\'t ask.'] = {'/sc 6_14', true},
| |
| 359 | [1] = '/sc 6' | |
| 360 | }, | |
| 361 | ['Game'] = {
| |
| 362 | ['Let\'s build'] = {'/sc 7_0', true},
| |
| 363 | ['Let\'s battle'] = {'/sc 7_1', true},
| |
| 364 | ['Nice one!'] = {'/sc 7_2', true},
| |
| 365 | ['So far so good'] = {'/sc 7_3', true},
| |
| 366 | ['Lucky shot!'] = {'/sc 7_4', true},
| |
| 367 | ['Oh man!'] = {'/sc 7_5', true},
| |
| 368 | ['I challenge you to a fight!'] = {'/sc 7_6', true},
| |
| 369 | ['Help me with this'] = {'/sc 7_7', true},
| |
| 370 | ['Let\'s go to your game'] = {'/sc 7_8', true},
| |
| 371 | ['Can you show me how do to that?'] = {'/sc 7_9', true},
| |
| 372 | ['Backflip!'] = {'/sc 7_10', true},
| |
| 373 | ['Frontflip!'] = {'/sc 7_11', true},
| |
| 374 | ['Dance!'] = {'/sc 7_12', true},
| |
| 375 | ['I\'m on your side!'] = {'/sc 7_13', true},
| |
| 376 | ['Game Commands'] = {'/sc 7_14', true, ['regen'] = true, ['reset'] = true, ['go'] = true, ['fix'] = true, ['respawn'] = true},
| |
| 377 | [1] = '/sc 7' | |
| 378 | }; | |
| 379 | ['Silly'] = {
| |
| 380 | ['Muahahahaha!'] = true, | |
| 381 | ['all your base are belong to me!'] = true, | |
| 382 | ['GET OFF MAH LAWN'] = true, | |
| 383 | ['TEH EPIK DUCK IS COMING!!!'] = true, | |
| 384 | ['ROFL'] = true, | |
| 385 | ['1337'] = {true, ['i r teh pwnz0r!'] = true, ['w00t!'] = true, ['z0mg h4x!'] = true, ['ub3rR0xXorzage!'] = true}
| |
| 386 | }, | |
| 387 | ['Yes'] = {
| |
| 388 | ['Absolutely!'] = true, | |
| 389 | ['Rock on!'] = true, | |
| 390 | ['Totally!'] = true, | |
| 391 | ['Juice!'] = true, | |
| 392 | ['Yay!'] = true, | |
| 393 | ['Yesh'] = true | |
| 394 | }, | |
| 395 | ['No'] = {
| |
| 396 | ['Ummm. No.'] = true, | |
| 397 | ['...'] = true, | |
| 398 | ['Stop!'] = true, | |
| 399 | ['Go away!'] = true, | |
| 400 | ['Don\'t do that'] = true, | |
| 401 | ['Stop breaking the rules'] = true, | |
| 402 | ['I don\'t want to'] = true | |
| 403 | }, | |
| 404 | ['Ok'] = {
| |
| 405 | ['Well... ok'] = true, | |
| 406 | ['Sure'] = true | |
| 407 | }, | |
| 408 | ['Uncertain'] = {
| |
| 409 | ['Maybe'] = true, | |
| 410 | ['I don\'t know'] = true, | |
| 411 | ['idk'] = true, | |
| 412 | ['I can\'t decide'] = true, | |
| 413 | ['Hmm...'] = true | |
| 414 | }, | |
| 415 | [':-)'] = {
| |
| 416 | [':-('] = true,
| |
| 417 | [':D'] = true, | |
| 418 | [':-O'] = true, | |
| 419 | ['lol'] = true, | |
| 420 | ['=D'] = true, | |
| 421 | ['D='] = true, | |
| 422 | ['XD'] = true, | |
| 423 | [';D'] = true, | |
| 424 | [';)'] = true, | |
| 425 | ['O_O'] = true, | |
| 426 | ['=)'] = true, | |
| 427 | ['@_@'] = true, | |
| 428 | ['>_<'] = true, | |
| 429 | ['T_T'] = true, | |
| 430 | ['^_^'] = true, | |
| 431 | ['<(0_0<) <(0_0)> (>0_0)> KIRBY DANCE'] = true, | |
| 432 | [')\';'] = true, | |
| 433 | [':3'] = true | |
| 434 | }, | |
| 435 | ['Ratings'] = {
| |
| 436 | ['Rate it!'] = true, | |
| 437 | ['I give it a 1 out of 10'] = true, | |
| 438 | ['I give it a 2 out of 10'] = true, | |
| 439 | ['I give it a 3 out of 10'] = true, | |
| 440 | ['I give it a 4 out of 10'] = true, | |
| 441 | ['I give it a 5 out of 10'] = true, | |
| 442 | ['I give it a 6 out of 10'] = true, | |
| 443 | ['I give it a 7 out of 10'] = true, | |
| 444 | ['I give it a 8 out of 10'] = true, | |
| 445 | ['I give it a 9 out of 10'] = true, | |
| 446 | ['I give it a 10 out of 10!'] = true, | |
| 447 | } | |
| 448 | }, | |
| 449 | CreateEnum('SafeChat'){'Level1', 'Level2', 'Level3'},
| |
| 450 | SafeChatTree = {},
| |
| 451 | TempSpaceLabel = nil | |
| 452 | } | |
| 453 | --------------------------------------------------- | |
| 454 | ||
| 455 | local function GetNameValue(pName) | |
| 456 | local value = 0 | |
| 457 | for index = 1, #pName do | |
| 458 | local cValue = string.byte(string.sub(pName, index, index)) | |
| 459 | local reverseIndex = #pName - index + 1 | |
| 460 | if #pName%2 == 1 then | |
| 461 | reverseIndex = reverseIndex - 1 | |
| 462 | end | |
| 463 | if reverseIndex%4 >= 2 then | |
| 464 | cValue = -cValue | |
| 465 | end | |
| 466 | value = value + cValue | |
| 467 | end | |
| 468 | return value%8 | |
| 469 | end | |
| 470 | ||
| 471 | function Chat:ComputeChatColor(pName) | |
| 472 | if export.NameColorDependsOnChatColor then | |
| 473 | return PLAYERLIST_CHATCOLORS[pName:lower()] or self.ChatColors[GetNameValue(pName) + 1].Color | |
| 474 | else | |
| 475 | return self.ChatColors[GetNameValue(pName) + 1].Color | |
| 476 | end | |
| 477 | end | |
| 478 | ||
| 479 | -- This is context based scrolling | |
| 480 | function Chat:EnableScrolling(toggle) | |
| 481 | -- Genius idea gone to fail, if we switch the camera type we can effectively lock the | |
| 482 | -- camera and do no click scrolling | |
| 483 | self.MouseOnFrame = false | |
| 484 | if self.RenderFrame then | |
| 485 | self.RenderFrame.MouseEnter:connect(function() | |
| 486 | local character = Player.Character | |
| 487 | local torso = WaitForChild(character, 'Torso') | |
| 488 | local humanoid = WaitForChild(character, 'Humanoid') | |
| 489 | local head = WaitForChild(character, 'Head') | |
| 490 | if toggle then | |
| 491 | self.MouseOnFrame = true | |
| 492 | Camera.CameraType = 'Scriptable' | |
| 493 | -- Get relative position of camera and keep to it | |
| 494 | Spawn(function() | |
| 495 | local currentRelativePos = Camera.CoordinateFrame.p - torso.Position | |
| 496 | while Chat.MouseOnFrame do | |
| 497 | Camera.CoordinateFrame = CFrame.new(torso.Position + currentRelativePos, head.Position) | |
| 498 | wait(0.015) | |
| 499 | end | |
| 500 | end) | |
| 501 | end | |
| 502 | end) | |
| 503 | ||
| 504 | self.RenderFrame.MouseLeave:connect(function() | |
| 505 | Camera.CameraType = 'Custom' | |
| 506 | self.MouseOnFrame = false | |
| 507 | end) | |
| 508 | end | |
| 509 | end | |
| 510 | ||
| 511 | -- TODO: Scrolling using Mouse wheel | |
| 512 | function Chat:OnScroll(speed) | |
| 513 | if self.MouseOnFrame then | |
| 514 | -- | |
| 515 | end | |
| 516 | end | |
| 517 | ||
| 518 | -- Check if we are running on a touch device | |
| 519 | function Chat:IsTouchDevice() | |
| 520 | local touchEnabled = false | |
| 521 | pcall(function() touchEnabled = Game:GetService('UserInputService').TouchEnabled end)
| |
| 522 | return touchEnabled | |
| 523 | end | |
| 524 | ||
| 525 | -- Scrolling | |
| 526 | function Chat:ScrollQueue(value) | |
| 527 | --[[for i = 1, #self.MessageQueue do | |
| 528 | if self.MessageQueue[i] then | |
| 529 | for _, label in pairs(self.MessageQueue[i]) do | |
| 530 | local next = self.MessageQueue[i].Next | |
| 531 | local previous = self.MessageQueue[i].Previous | |
| 532 | if label and label:IsA('TextLabel') or label:IsA('TextButton') then
| |
| 533 | if value > 0 and previous and previous['Message'] then | |
| 534 | label.Position = previous['Message'].Position | |
| 535 | elseif value < 1 and next['Message'] then | |
| 536 | label.Position = previous['Message'].Position | |
| 537 | end | |
| 538 | end | |
| 539 | end | |
| 540 | end | |
| 541 | end ]] | |
| 542 | end | |
| 543 | ||
| 544 | -- Handles the rendering of the text objects in their appropriate places | |
| 545 | function Chat:UpdateQueue(field, diff) | |
| 546 | -- Have to do some sort of correction here | |
| 547 | for i = #self.MessageQueue, 1, -1 do | |
| 548 | if self.MessageQueue[i] then | |
| 549 | for _, label in pairs(self.MessageQueue[i]) do | |
| 550 | if label and type(label) ~= 'table' and type(label) ~= 'number' then | |
| 551 | if label:IsA('TextLabel') or label:IsA('TextButton') then
| |
| 552 | if diff then | |
| 553 | label.Position = label.Position - UDim2.new(0, 0, diff, 0) | |
| 554 | else | |
| 555 | if field == self.MessageQueue[i] then | |
| 556 | label.Position = UDim2.new(self.Configuration.XScale, 0, label.Position.Y.Scale - field['Message'].Size.Y.Scale , 0) | |
| 557 | -- Just to show up popping effect for the latest message in chat | |
| 558 | coroutine.resume(coroutine.create(function() | |
| 559 | wait(0.05) | |
| 560 | ||
| 561 | local t = 0.1 | |
| 562 | local start = tick() | |
| 563 | ||
| 564 | while tick() - start < t do | |
| 565 | local alpha = (tick() - start) / t | |
| 566 | ||
| 567 | label.TextTransparency = 1-alpha | |
| 568 | wait() | |
| 569 | end | |
| 570 | label.TextTransparency = 0 | |
| 571 | ||
| 572 | if label == field['Message'] then | |
| 573 | label.TextStrokeTransparency = StrokeTransparency | |
| 574 | else | |
| 575 | label.TextStrokeTransparency = StrokeTransparency | |
| 576 | end | |
| 577 | end)) | |
| 578 | else | |
| 579 | label.Position = UDim2.new(self.Configuration.XScale, 0, label.Position.Y.Scale - field['Message'].Size.Y.Scale, 0) | |
| 580 | end | |
| 581 | if label.Position.Y.Scale < -0.01 then | |
| 582 | -- NOTE: Remove this fix when Textbounds is fixed | |
| 583 | label.Visible = false | |
| 584 | label:Destroy() | |
| 585 | end | |
| 586 | end | |
| 587 | end | |
| 588 | end | |
| 589 | end | |
| 590 | end | |
| 591 | end | |
| 592 | end | |
| 593 | ||
| 594 | function Chat:CreateScrollBar() | |
| 595 | -- Code for scrolling is in here, partially, but scroll bar drawing isn't drawn | |
| 596 | -- TODO: Implement | |
| 597 | end | |
| 598 | ||
| 599 | -- For scrolling, to see if we hit the bounds so that we can stop it from scrolling anymore | |
| 600 | function Chat:CheckIfInBounds(value) | |
| 601 | if #Chat.MessageQueue < 3 then | |
| 602 | return true | |
| 603 | end | |
| 604 | ||
| 605 | if value > 0 and Chat.MessageQueue[1] and Chat.MessageQueue[1]['Player'] and Chat.MessageQueue[1]['Player'].Position.Y.Scale == 0 then | |
| 606 | return true | |
| 607 | elseif value < 0 and Chat.MessageQueue[1] and Chat.MessageQueue[1]['Player'] and Chat.MessageQueue[1]['Player'].Position.Y.Scale < 0 then | |
| 608 | return true | |
| 609 | else | |
| 610 | return false | |
| 611 | end | |
| 612 | return false | |
| 613 | end | |
| 614 | ||
| 615 | -- This is to precompute all playerName space strings | |
| 616 | -- This is used to offset the message by exactly this + 2 spacestrings | |
| 617 | function Chat:ComputeSpaceString(pLabel) | |
| 618 | local nString = " " | |
| 619 | if not self.TempSpaceLabel then | |
| 620 | self.TempSpaceLabel = Gui.Create'TextButton' | |
| 621 | {
| |
| 622 | Size = UDim2.new(0, pLabel.AbsoluteSize.X, 0, pLabel.AbsoluteSize.Y); | |
| 623 | FontSize = self.Configuration.FontSize; | |
| 624 | Parent = self.RenderFrame; | |
| 625 | BackgroundTransparency = 1.0; | |
| 626 | Text = nString; | |
| 627 | Name = 'SpaceButton' | |
| 628 | }; | |
| 629 | else | |
| 630 | self.TempSpaceLabel.Text = nString | |
| 631 | end | |
| 632 | ||
| 633 | while self.TempSpaceLabel.TextBounds.X < pLabel.TextBounds.X do | |
| 634 | nString = nString .. " " | |
| 635 | self.TempSpaceLabel.Text = nString | |
| 636 | end | |
| 637 | nString = nString .. " " | |
| 638 | self.CachedSpaceStrings_List[pLabel.Text] = nString | |
| 639 | self.TempSpaceLabel.Text = "" | |
| 640 | return nString | |
| 641 | end | |
| 642 | ||
| 643 | -- When the playerChatted event fires | |
| 644 | -- The message is what the player chatted | |
| 645 | function Chat:UpdateChat(cPlayer, message) | |
| 646 | local messageField = {
| |
| 647 | ['Player'] = cPlayer, | |
| 648 | ['Message'] = message | |
| 649 | } | |
| 650 | if Chat.MessageThread == nil or coroutine.status(Chat.MessageThread) == 'dead' then | |
| 651 | --Chat.Messages_List = {}
| |
| 652 | table.insert(Chat.Messages_List, messageField) | |
| 653 | Chat.MessageThread = coroutine.create(function() | |
| 654 | for i = 1, #Chat.Messages_List do | |
| 655 | local field = Chat.Messages_List[i] | |
| 656 | Chat:CreateMessage(field['Player'], field['Message']) | |
| 657 | end | |
| 658 | Chat.Messages_List = {}
| |
| 659 | end) | |
| 660 | coroutine.resume(Chat.MessageThread) | |
| 661 | else | |
| 662 | table.insert(Chat.Messages_List, messageField) | |
| 663 | end | |
| 664 | end | |
| 665 | ||
| 666 | function Chat:RecalculateSpacing() | |
| 667 | --[[for i = 1, #self.MessageQueue do | |
| 668 | local pLabel = self.MessageQueue[i]['Player'] | |
| 669 | local mLabel = self.MessageQueue[i]['Message'] | |
| 670 | ||
| 671 | local prevYScale = mLabel.Size.Y.Scale | |
| 672 | local prevText = mLabel.Text | |
| 673 | mLabel.Text = prevText | |
| 674 | ||
| 675 | local heightField = mLabel.TextBounds.Y | |
| 676 | ||
| 677 | mLabel.Size = UDim2.new(1, 0, heightField/self.RenderFrame.AbsoluteSize.Y, 0) | |
| 678 | pLabel.Size = mLabel.Size | |
| 679 | ||
| 680 | local diff = mLabel.Size.Y.Scale - prevYScale | |
| 681 | ||
| 682 | Chat:UpdateQueue(self.MessageQueue[i], diff) | |
| 683 | end ]] | |
| 684 | end | |
| 685 | ||
| 686 | function Chat:ApplyFilter(str) | |
| 687 | --[[for _, word in pair(self.Filter_List) do | |
| 688 | if string.find(str, word) then | |
| 689 | str:gsub(word, '@#$^') | |
| 690 | end | |
| 691 | end ]] | |
| 692 | end | |
| 693 | ||
| 694 | export.SendChat = function(self, name, message, custom_color, do_not_add_to_history) | |
| 695 | local old_color = PLAYERLIST_CHATCOLORS[name:lower()] | |
| 696 | if custom_color ~= nil then | |
| 697 | PLAYERLIST_CHATCOLORS[name:lower()] = custom_color | |
| 698 | end | |
| 699 | print(old_color, PLAYERLIST_CHATCOLORS[name:lower()]) | |
| 700 | ||
| 701 | local player = game.Players:FindFirstChild(name) or {
| |
| 702 | Name = name, | |
| 703 | Neutral = true, | |
| 704 | TeamColor = Color3.new(1,1,1) | |
| 705 | } | |
| 706 | ||
| 707 | Chat:CreateMessage(player, message, do_not_add_to_history) | |
| 708 | -- if do_not_add_to_history ~= true then | |
| 709 | -- AddToChatHistory(player, message) | |
| 710 | -- end | |
| 711 | ||
| 712 | wait() | |
| 713 | PLAYERLIST_CHATCOLORS[name:lower()] = old_color or nil | |
| 714 | end | |
| 715 | ||
| 716 | -- NOTE: Temporarily disabled ring buffer to allow for chat to always wrap around | |
| 717 | function Chat:CreateMessage(cPlayer, message, do_not_add_to_history) | |
| 718 | if do_not_add_to_history ~= true then | |
| 719 | AddToChatHistory(cPlayer, message) | |
| 720 | end | |
| 721 | ||
| 722 | local pName | |
| 723 | if not cPlayer then | |
| 724 | pName = '' | |
| 725 | else | |
| 726 | pName = cPlayer.Name | |
| 727 | end | |
| 728 | message = StringTrim(message) | |
| 729 | local pLabel | |
| 730 | local mLabel | |
| 731 | -- Our history stores upto 50 messages that is 100 textlabels | |
| 732 | -- If we ever hit the mark, which would be in every popular game btw | |
| 733 | -- we wrap around and reuse the labels | |
| 734 | if #self.MessageQueue > self.Configuration.HistoryLength then | |
| 735 | --[[pLabel = self.MessageQueue[#self.MessageQueue]['Player'] | |
| 736 | mLabel = self.MessageQueue[#self.MessageQueue]['Message'] | |
| 737 | ||
| 738 | pLabel.Text = pName .. ':' | |
| 739 | pLabel.Name = pName | |
| 740 | ||
| 741 | local pColor | |
| 742 | if cPlayer.Neutral then | |
| 743 | pLabel.TextColor3 = Chat:ComputeChatColor(pName) | |
| 744 | else | |
| 745 | pLabel.TextColor3 = cPlayer.TeamColor.Color | |
| 746 | end | |
| 747 | ||
| 748 | local nString | |
| 749 | ||
| 750 | if not self.CachedSpaceStrings_List[pName] then | |
| 751 | nString = Chat:ComputeSpaceString(pLabel) | |
| 752 | else | |
| 753 | nString = self.CachedSpaceStrings_List[pName] | |
| 754 | end | |
| 755 | ||
| 756 | mLabel.Text = "" | |
| 757 | mLabel.Name = pName .. " - message" | |
| 758 | mLabel.Text = nString .. message; | |
| 759 | ||
| 760 | mLabel.Parent = nil | |
| 761 | mLabel.Parent = self.RenderFrame | |
| 762 | ||
| 763 | mLabel.Position = UDim2.new(0, 0, 1, 0); | |
| 764 | pLabel.Position = UDim2.new(0, 0, 1, 0);]] | |
| 765 | ||
| 766 | -- Reinserted at the beginning, ring buffer | |
| 767 | self.MessageQueue[#self.MessageQueue] = nil | |
| 768 | end | |
| 769 | --else | |
| 770 | -- Haven't hit the mark yet, so keep creating | |
| 771 | pLabel = Gui.Create'TextLabel' | |
| 772 | {
| |
| 773 | Name = pName; | |
| 774 | Text = (PLAYERLIST_ALIASES[pName:lower()] or pName) .. ":"; | |
| 775 | TextColor3 = PLAYERLIST_CHATCOLORS[pName:lower()] or pColor; | |
| 776 | FontSize = Chat.Configuration.FontSize; | |
| 777 | TextXAlignment = Enum.TextXAlignment.Left; | |
| 778 | TextYAlignment = Enum.TextYAlignment.Top; | |
| 779 | Parent = self.RenderFrame; | |
| 780 | TextWrapped = false; | |
| 781 | Size = UDim2.new(1, 0, 0.1, 0); | |
| 782 | BackgroundTransparency = 1.0; | |
| 783 | TextTransparency = 1.0; | |
| 784 | Position = UDim2.new(0, 0, 1, 0); | |
| 785 | BorderSizePixel = 0.0; | |
| 786 | TextStrokeColor3 = Color3.new(0, 0, 0); | |
| 787 | TextStrokeTransparency = StrokeTransparency; | |
| 788 | --Active = false; | |
| 789 | }; | |
| 790 | local pColor | |
| 791 | if cPlayer.Neutral then | |
| 792 | pLabel.TextColor3 = Chat:ComputeChatColor(pName) | |
| 793 | else | |
| 794 | pLabel.TextColor3 = cPlayer.TeamColor.Color | |
| 795 | end | |
| 796 | ||
| 797 | local nString | |
| 798 | ||
| 799 | if not self.CachedSpaceStrings_List[pName] then | |
| 800 | nString = Chat:ComputeSpaceString(pLabel) | |
| 801 | else | |
| 802 | nString = self.CachedSpaceStrings_List[pName] | |
| 803 | end | |
| 804 | ||
| 805 | mLabel = Gui.Create'TextLabel' | |
| 806 | {
| |
| 807 | Name = pName .. ' - message'; | |
| 808 | -- Max is 3 lines | |
| 809 | Size = UDim2.new(1, 0, 0.5, 0); | |
| 810 | TextColor3 = Chat.Configuration.MessageColor; | |
| 811 | FontSize = Chat.Configuration.FontSize; | |
| 812 | TextXAlignment = Enum.TextXAlignment.Left; | |
| 813 | TextYAlignment = Enum.TextYAlignment.Top; | |
| 814 | Text = ""; -- this is to stop when the engine reverts the swear words to default, which is button, ugh | |
| 815 | Parent = self.RenderFrame; | |
| 816 | TextWrapped = true; | |
| 817 | BackgroundTransparency = 1.0; | |
| 818 | TextTransparency = 1.0; | |
| 819 | Position = UDim2.new(0, 0, 1, 0); | |
| 820 | BorderSizePixel = 0.0; | |
| 821 | TextStrokeColor3 = Color3.new(0, 0, 0); | |
| 822 | --TextStrokeTransparency = 0.8; | |
| 823 | --Active = false; | |
| 824 | }; | |
| 825 | mLabel.Text = nString .. message; | |
| 826 | ||
| 827 | if not pName then | |
| 828 | pLabel.Text = '' | |
| 829 | mLabel.TextColor3 = Color3.new(0, 0.4, 1.0) | |
| 830 | end | |
| 831 | --end | |
| 832 | ||
| 833 | if self.Admins_List[pName:lower()] then | |
| 834 | mLabel.TextColor3 = PLAYERLIST_CHATCOLORS[pName:lower()] or self.Configuration.AdminMessageColor | |
| 835 | end | |
| 836 | ||
| 837 | pLabel.Visible = true | |
| 838 | mLabel.Visible = true | |
| 839 | ||
| 840 | -- This will give beautiful multilines as well | |
| 841 | local heightField = mLabel.TextBounds.Y | |
| 842 | ||
| 843 | mLabel.Size = UDim2.new(1, 0, heightField/self.RenderFrame.AbsoluteSize.Y, 0) | |
| 844 | pLabel.Size = mLabel.Size | |
| 845 | ||
| 846 | local yPixels = self.RenderFrame.AbsoluteSize.Y | |
| 847 | local yFieldSize = mLabel.TextBounds.Y | |
| 848 | ||
| 849 | local queueField = {}
| |
| 850 | queueField['Player'] = pLabel | |
| 851 | queueField['Message'] = mLabel | |
| 852 | queueField['SpawnTime'] = tick() -- Used for identifying when to make the message invisible | |
| 853 | ||
| 854 | table.insert(self.MessageQueue, 1, queueField) | |
| 855 | Chat:UpdateQueue(queueField) | |
| 856 | end | |
| 857 | ||
| 858 | function Chat:ScreenSizeChanged() | |
| 859 | wait() | |
| 860 | while self.Frame.AbsoluteSize.Y > 120 do | |
| 861 | self.Frame.Size = self.Frame.Size - UDim2.new(0, 0, 0.005, 0) | |
| 862 | end | |
| 863 | Chat:RecalculateSpacing() | |
| 864 | end | |
| 865 | ||
| 866 | ||
| 867 | function Chat:FindButtonTree(scButton, rootList) | |
| 868 | local list = {}
| |
| 869 | rootList = rootList or self.SafeChatTree | |
| 870 | for button, _ in pairs(rootList) do | |
| 871 | if button == scButton then | |
| 872 | list = rootList[button] | |
| 873 | elseif type(rootList[button]) == 'table' then | |
| 874 | list = Chat:FindButtonTree(scButton, rootList[button]) | |
| 875 | end | |
| 876 | end | |
| 877 | return list | |
| 878 | end | |
| 879 | ||
| 880 | function Chat:ToggleSafeChatMenu(scButton) | |
| 881 | local list = Chat:FindButtonTree(scButton, self.SafeChatTree) | |
| 882 | if list then | |
| 883 | for button, _ in pairs(list) do | |
| 884 | if button:IsA('TextButton') or button:IsA('ImageButton') then
| |
| 885 | button.Visible = not button.Visible | |
| 886 | end | |
| 887 | end | |
| 888 | return true | |
| 889 | end | |
| 890 | return false | |
| 891 | end | |
| 892 | ||
| 893 | function Chat:CreateSafeChatOptions(list, rootButton) | |
| 894 | local text_List = {}
| |
| 895 | level = level or 0 | |
| 896 | local count = 0 | |
| 897 | text_List[rootButton] = {}
| |
| 898 | text_List[rootButton][1] = list[1] | |
| 899 | rootButton = rootButton or self.SafeChatButton | |
| 900 | for msg, _ in pairs(list) do | |
| 901 | if type(msg) == 'string' then | |
| 902 | local chatText = Gui.Create'TextButton' | |
| 903 | {
| |
| 904 | Name = msg; | |
| 905 | Text = msg; | |
| 906 | Size = UDim2.new(0, 100, 0, 20); | |
| 907 | TextXAlignment = Enum.TextXAlignment.Center; | |
| 908 | TextColor3 = Color3.new(0.2, 0.1, 0.1); | |
| 909 | BackgroundTransparency = 0.5; | |
| 910 | BackgroundColor3 = Color3.new(1, 1, 1); | |
| 911 | Parent = self.SafeChatFrame; | |
| 912 | Visible = false; | |
| 913 | Position = UDim2.new(0, rootButton.Position.X.Scale + 105, 0, rootButton.Position.Y.Scale - ((count - 3) * 100)); | |
| 914 | }; | |
| 915 | ||
| 916 | count = count + 1 | |
| 917 | ||
| 918 | if type(list[msg]) == 'table' then | |
| 919 | text_List[rootButton][chatText] = Chat:CreateSafeChatOptions(list[msg], chatText) | |
| 920 | else | |
| 921 | --table.insert(text_List[chatText], true) | |
| 922 | end | |
| 923 | chatText.MouseEnter:connect(function() | |
| 924 | Chat:ToggleSafeChatMenu(chatText) | |
| 925 | end) | |
| 926 | ||
| 927 | chatText.MouseLeave:connect(function() | |
| 928 | Chat:ToggleSafeChatMenu(chatText) | |
| 929 | end) | |
| 930 | ||
| 931 | chatText.MouseButton1Click:connect(function() | |
| 932 | local lList = Chat:FindButtonTree(chatText) | |
| 933 | if lList then | |
| 934 | for i, v in pairs(lList) do | |
| 935 | end | |
| 936 | else | |
| 937 | end | |
| 938 | pcall(function() PlayersService:Chat(lList[1]) end) | |
| 939 | end) | |
| 940 | end | |
| 941 | end | |
| 942 | return text_List | |
| 943 | end | |
| 944 | ||
| 945 | function Chat:CreateSafeChatGui() | |
| 946 | self.SafeChatFrame = Gui.Create'Frame' | |
| 947 | {
| |
| 948 | Name = 'SafeChatFrame'; | |
| 949 | Size = UDim2.new(1, 0, 1, 0); | |
| 950 | Parent = self.Gui; | |
| 951 | BackgroundTransparency = 1.0; | |
| 952 | ||
| 953 | Gui.Create'ImageButton' | |
| 954 | {
| |
| 955 | Name = 'SafeChatButton'; | |
| 956 | Size = UDim2.new(0, 44, 0, 31); | |
| 957 | Position = UDim2.new(0, 1, 0.35, 0); | |
| 958 | BackgroundTransparency = 1.0; | |
| 959 | Image = 'http://www.roblox.com/asset/?id=97080365'; | |
| 960 | }; | |
| 961 | } | |
| 962 | ||
| 963 | self.SafeChatButton = self.SafeChatFrame.SafeChatButton | |
| 964 | -- safe chat button is the root of this tree | |
| 965 | self.SafeChatTree[self.SafeChatButton] = Chat:CreateSafeChatOptions(self.SafeChat_List, self.SafeChatButton) | |
| 966 | ||
| 967 | self.SafeChatButton.MouseButton1Click:connect(function() | |
| 968 | Chat:ToggleSafeChatMenu(self.SafeChatButton) | |
| 969 | end) | |
| 970 | end | |
| 971 | ||
| 972 | ||
| 973 | function Chat:FocusOnChatBar() | |
| 974 | if self.ClickToChatButton then | |
| 975 | self.ClickToChatButton.Visible = false | |
| 976 | end | |
| 977 | ||
| 978 | self.GotFocus = true | |
| 979 | if self.Frame['Background'] then | |
| 980 | self.Frame.Background.Visible = false | |
| 981 | end | |
| 982 | self.ChatBar:CaptureFocus() | |
| 983 | end | |
| 984 | ||
| 985 | -- For touch devices we create a button instead | |
| 986 | function Chat:CreateTouchButton() | |
| 987 | self.ChatTouchFrame = Gui.Create'Frame' | |
| 988 | {
| |
| 989 | Name = 'ChatTouchFrame'; | |
| 990 | Size = UDim2.new(0, 128, 0, 32); | |
| 991 | Position = UDim2.new(0, 88, 0, 0); | |
| 992 | BackgroundTransparency = 1.0; | |
| 993 | Parent = self.Gui; | |
| 994 | ||
| 995 | Gui.Create'ImageButton' | |
| 996 | {
| |
| 997 | Name = 'ChatLabel'; | |
| 998 | Size = UDim2.new(0, 74, 0, 28); | |
| 999 | Position = UDim2.new(0, 0, 0, 0); | |
| 1000 | BackgroundTransparency = 1.0; | |
| 1001 | ZIndex = 2.0; | |
| 1002 | }; | |
| 1003 | Gui.Create'ImageLabel' | |
| 1004 | {
| |
| 1005 | Name = 'Background'; | |
| 1006 | Size = UDim2.new(1, 0, 1, 0); | |
| 1007 | Position = UDim2.new(0, 0, 0, 0); | |
| 1008 | BackgroundTransparency = 1.0; | |
| 1009 | Image = 'http://www.roblox.com/asset/?id=97078724' | |
| 1010 | }; | |
| 1011 | ||
| 1012 | } | |
| 1013 | self.TapToChatLabel = self.ChatTouchFrame.ChatLabel | |
| 1014 | self.TouchLabelBackground = self.ChatTouchFrame.Background | |
| 1015 | ||
| 1016 | self.ChatBar = Gui.Create'TextBox' | |
| 1017 | {
| |
| 1018 | Name = 'ChatBar'; | |
| 1019 | Size = UDim2.new(1, 0, 0.2, 0); | |
| 1020 | Position = UDim2.new(0, 0, 0.8, 800); | |
| 1021 | Text = ""; | |
| 1022 | ZIndex = 1.0; | |
| 1023 | BackgroundTransparency = 1.0; | |
| 1024 | Parent = self.Frame; | |
| 1025 | TextXAlignment = Enum.TextXAlignment.Left; | |
| 1026 | TextColor3 = Color3.new(1, 1, 1); | |
| 1027 | ClearTextOnFocus = false; | |
| 1028 | }; | |
| 1029 | ||
| 1030 | self.TapToChatLabel.MouseButton1Click:connect(function() | |
| 1031 | self.TapToChatLabel.Visible = false | |
| 1032 | --self.ChatBar.Visible = true | |
| 1033 | --self.Frame.Background.Visible = true | |
| 1034 | self.ChatBar:CaptureFocus() | |
| 1035 | self.GotFocus = true | |
| 1036 | if self.TouchLabelBackground then | |
| 1037 | self.TouchLabelBackground.Visible = false | |
| 1038 | end | |
| 1039 | end) | |
| 1040 | end | |
| 1041 | ||
| 1042 | -- Non touch devices, create the bottom chat bar | |
| 1043 | function Chat:CreateChatBar() | |
| 1044 | -- okay now we do | |
| 1045 | -- local status, result = pcall(function() return GuiService.UseLuaChat end) | |
| 1046 | -- if forceChatGUI or (status and result) then | |
| 1047 | -- self.ClickToChatButton = Gui.Create'TextButton' | |
| 1048 | -- {
| |
| 1049 | -- Name = 'ClickToChat'; | |
| 1050 | -- Size = UDim2.new(1, 0, 0, 20); | |
| 1051 | -- BackgroundTransparency = 1.0; | |
| 1052 | -- ZIndex = 2.0; | |
| 1053 | -- Parent = self.Gui; | |
| 1054 | -- Text = "To chat click here or press \"/\" key"; | |
| 1055 | -- TextColor3 = Color3.new(1, 1, 0.9); | |
| 1056 | -- Position = UDim2.new(0, 0, 1, 0); | |
| 1057 | -- TextXAlignment = Enum.TextXAlignment.Left; | |
| 1058 | -- FontSize = Enum.FontSize.Size12; | |
| 1059 | -- } | |
| 1060 | -- | |
| 1061 | -- self.ChatBar = Gui.Create'TextBox' | |
| 1062 | -- {
| |
| 1063 | -- Name = 'ChatBar'; | |
| 1064 | -- Size = UDim2.new(1, 0, 0, 20); | |
| 1065 | -- Position = UDim2.new(0, 0, 1, 0); | |
| 1066 | -- Text = ""; | |
| 1067 | -- ZIndex = 1.0; | |
| 1068 | -- BackgroundColor3 = Color3.new(0, 0, 0); | |
| 1069 | -- BackgroundTransparency = 0.25; | |
| 1070 | -- Parent = self.Gui; | |
| 1071 | -- TextXAlignment = Enum.TextXAlignment.Left; | |
| 1072 | -- TextColor3 = Color3.new(1, 1, 1); | |
| 1073 | -- FontSize = Enum.FontSize.Size12; | |
| 1074 | -- ClearTextOnFocus = false; | |
| 1075 | -- Text = ''; | |
| 1076 | -- }; | |
| 1077 | -- | |
| 1078 | -- -- Engine has code to offset the entire world, so if we do it by -20 pixels nothing gets in our chat's way | |
| 1079 | -- --GuiService:SetGlobalSizeOffsetPixel(0, -20) | |
| 1080 | -- local success, error = pcall(function() GuiService:SetGlobalGuiInset(0, 0, 0, 20) end) | |
| 1081 | -- if not success then | |
| 1082 | -- GuiService:SetGlobalSizeOffsetPixel(0, -20) | |
| 1083 | -- end | |
| 1084 | -- -- CHatHotKey is '/' | |
| 1085 | -- GuiService:AddSpecialKey(Enum.SpecialKey.ChatHotkey) | |
| 1086 | -- GuiService.SpecialKeyPressed:connect(function(key) | |
| 1087 | -- if key == Enum.SpecialKey.ChatHotkey then | |
| 1088 | -- Chat:FocusOnChatBar() | |
| 1089 | -- end | |
| 1090 | -- end) | |
| 1091 | -- | |
| 1092 | -- self.ClickToChatButton.MouseButton1Click:connect(function() | |
| 1093 | -- Chat:FocusOnChatBar() | |
| 1094 | -- end) | |
| 1095 | -- end | |
| 1096 | end | |
| 1097 | ||
| 1098 | -- Create the initial Chat stuff | |
| 1099 | -- Done only once | |
| 1100 | function Chat:CreateGui() | |
| 1101 | self.Gui = script.Parent | |
| 1102 | self.Frame = Gui.Create'Frame' | |
| 1103 | {
| |
| 1104 | Name = 'ChatFrame'; | |
| 1105 | --Size = self.Configuration.Size; | |
| 1106 | Size = UDim2.new(0, 500, 0, 120); | |
| 1107 | Position = UDim2.new(0, 0, 0, 5); | |
| 1108 | BackgroundTransparency = 1.0; | |
| 1109 | --ClipsDescendants = true; | |
| 1110 | ZIndex = 0.0; | |
| 1111 | Parent = self.Gui; | |
| 1112 | Active = false; | |
| 1113 | ||
| 1114 | Gui.Create'ImageLabel' | |
| 1115 | {
| |
| 1116 | Name = 'Background'; | |
| 1117 | Image = 'http://www.roblox.com/asset/?id=97120937'; --96551212'; | |
| 1118 | Size = UDim2.new(1.3, 0, 1.64, 0); | |
| 1119 | Position = UDim2.new(0, 0, 0, 0); | |
| 1120 | BackgroundTransparency = 1.0; | |
| 1121 | ZIndex = 0.0; | |
| 1122 | Visible = false | |
| 1123 | }; | |
| 1124 | ||
| 1125 | Gui.Create'Frame' | |
| 1126 | {
| |
| 1127 | Name = 'Border'; | |
| 1128 | Size = UDim2.new(1, 0, 0, 1); | |
| 1129 | Position = UDim2.new(0, 0, 0.8, 0); | |
| 1130 | BackgroundTransparency = 0.0; | |
| 1131 | BackgroundColor3 = Color3.new(236/255, 236/255, 236/255); | |
| 1132 | BorderSizePixel = 0.0; | |
| 1133 | Visible = false; | |
| 1134 | }; | |
| 1135 | ||
| 1136 | Gui.Create'Frame' | |
| 1137 | {
| |
| 1138 | Name = 'ChatRenderFrame'; | |
| 1139 | Size = UDim2.new(1.02, 0, 1.01, 0); | |
| 1140 | Position = UDim2.new(0, 0, 0, 0); | |
| 1141 | BackgroundTransparency = 1.0; | |
| 1142 | --ClipsDescendants = true; | |
| 1143 | ZIndex = 0.0; | |
| 1144 | Active = false; | |
| 1145 | ||
| 1146 | }; | |
| 1147 | }; | |
| 1148 | ||
| 1149 | Spawn(function() | |
| 1150 | wait(0.5) | |
| 1151 | if IsPhone() then | |
| 1152 | self.Frame.Size = UDim2.new(0, 280, 0, 120) | |
| 1153 | end | |
| 1154 | end) | |
| 1155 | ||
| 1156 | self.RenderFrame = self.Frame.ChatRenderFrame | |
| 1157 | if Chat:IsTouchDevice() then | |
| 1158 | self.Frame.Position = self.Configuration.Position; | |
| 1159 | self.RenderFrame.Size = UDim2.new(1, 0, 1, 0) | |
| 1160 | elseif self.Frame.AbsoluteSize.Y > 120 then | |
| 1161 | Chat:ScreenSizeChanged() | |
| 1162 | self.Gui.Changed:connect(function(property) | |
| 1163 | if property == 'AbsoluteSize' then | |
| 1164 | Chat:ScreenSizeChanged() | |
| 1165 | end | |
| 1166 | end) | |
| 1167 | end | |
| 1168 | ||
| 1169 | if forceChatGUI or true then | |
| 1170 | if Chat:IsTouchDevice() then | |
| 1171 | Chat:CreateTouchButton() | |
| 1172 | else | |
| 1173 | Chat:CreateChatBar() | |
| 1174 | --Chat:CreateSafeChatGui() | |
| 1175 | end | |
| 1176 | ||
| 1177 | if self.ChatBar then | |
| 1178 | self.ChatBar.FocusLost:connect(function(enterPressed) | |
| 1179 | Chat.GotFocus = false | |
| 1180 | if Chat:IsTouchDevice() then | |
| 1181 | self.ChatBar.Visible = false | |
| 1182 | self.TapToChatLabel.Visible = true | |
| 1183 | ||
| 1184 | if self.TouchLabelBackground then | |
| 1185 | self.TouchLabelBackground.Visible = true | |
| 1186 | end | |
| 1187 | end | |
| 1188 | if enterPressed and self.ChatBar.Text ~= "" then | |
| 1189 | ||
| 1190 | local cText = self.ChatBar.Text | |
| 1191 | if string.sub(self.ChatBar.Text, 1, 1) == '%' then | |
| 1192 | cText = '(TEAM) ' .. string.sub(cText, 2, #cText) | |
| 1193 | pcall(function() PlayersService:TeamChat(cText) end) | |
| 1194 | else | |
| 1195 | pcall(function() PlayersService:Chat(cText) end) | |
| 1196 | end | |
| 1197 | ||
| 1198 | if self.ClickToChatButton then | |
| 1199 | self.ClickToChatButton.Visible = true | |
| 1200 | end | |
| 1201 | self.ChatBar.Text = "" | |
| 1202 | end | |
| 1203 | Spawn(function() | |
| 1204 | wait(5.0) | |
| 1205 | if not Chat.GotFocus then | |
| 1206 | Chat.Frame.Background.Visible = false | |
| 1207 | end | |
| 1208 | end) | |
| 1209 | end) | |
| 1210 | end | |
| 1211 | end | |
| 1212 | end | |
| 1213 | ||
| 1214 | -- Scrolling function | |
| 1215 | -- Applies a speed(velocity) to have nice scrolling effect | |
| 1216 | function Input:OnMouseScroll() | |
| 1217 | Spawn(function() | |
| 1218 | -- How long should the speed last? | |
| 1219 | while Input.Speed ~=0 do | |
| 1220 | if Input.Speed > 1 then | |
| 1221 | while Input.Speed > 0 do | |
| 1222 | Input.Speed = Input.Speed - 1 | |
| 1223 | wait(0.25) | |
| 1224 | end | |
| 1225 | elseif Input.Speed < 0 then | |
| 1226 | while Input.Speed < 0 do | |
| 1227 | Input.Speed = Input.Speed + 1 | |
| 1228 | wait(0.25) | |
| 1229 | end | |
| 1230 | end | |
| 1231 | wait(0.03) | |
| 1232 | end | |
| 1233 | end) | |
| 1234 | if Chat:CheckIfInBounds(Input.Speed) then | |
| 1235 | return | |
| 1236 | end | |
| 1237 | Chat:ScrollQueue() | |
| 1238 | end | |
| 1239 | ||
| 1240 | function Input:ApplySpeed(value) | |
| 1241 | Input.Speed = Input.Speed + value | |
| 1242 | if not self.Simulating then | |
| 1243 | Input:OnMouseScroll() | |
| 1244 | end | |
| 1245 | end | |
| 1246 | ||
| 1247 | function Input:Initialize() | |
| 1248 | self.Mouse.WheelBackward:connect(function() | |
| 1249 | Input:ApplySpeed(self.Configuration.DefaultSpeed) | |
| 1250 | end) | |
| 1251 | ||
| 1252 | self.Mouse.WheelForward:connect(function() | |
| 1253 | Input:ApplySpeed(self.Configuration.DefaultSpeed) | |
| 1254 | end) | |
| 1255 | end | |
| 1256 | ||
| 1257 | function Chat:FindMessageInSafeChat(message, list) | |
| 1258 | local foundMessage = false | |
| 1259 | for msg, _ in pairs(list) do | |
| 1260 | if msg == message then | |
| 1261 | return true | |
| 1262 | end | |
| 1263 | if type(list[msg]) == 'table' then | |
| 1264 | foundMessage = Chat:FindMessageInSafeChat(message, list[msg]) | |
| 1265 | if foundMessage then | |
| 1266 | return true | |
| 1267 | end | |
| 1268 | end | |
| 1269 | end | |
| 1270 | return foundMessage | |
| 1271 | end | |
| 1272 | ||
| 1273 | -- Just a wrapper around our PlayerChatted event | |
| 1274 | function Chat:PlayerChatted(...) | |
| 1275 | local args = {...}
| |
| 1276 | local argCount = select('#', ...)
| |
| 1277 | local player | |
| 1278 | local message | |
| 1279 | -- This doesn't look very good, but what else to do? | |
| 1280 | if args[2] then | |
| 1281 | player = args[2] | |
| 1282 | end | |
| 1283 | if args[3] then | |
| 1284 | message = args[3] | |
| 1285 | if string.sub(message, 1, 1) == '%' then | |
| 1286 | message = '(TEAM) ' .. string.sub(message, 2, #message) | |
| 1287 | end | |
| 1288 | end | |
| 1289 | ||
| 1290 | -- if PlayersService.ClassicChat then | |
| 1291 | if string.sub(message, 1, 3) == '/e ' or string.sub(message, 1, 7) == '/emote ' then | |
| 1292 | -- don't do anything right now | |
| 1293 | elseif forceChatGUI or true then | |
| 1294 | Chat:UpdateChat(player, message) | |
| 1295 | elseif true and string.sub(message, 1, 3) == '/sc' then | |
| 1296 | Chat:UpdateChat(player, message) | |
| 1297 | else | |
| 1298 | if Chat:FindMessageInSafeChat(message, self.SafeChat_List) then | |
| 1299 | Chat:UpdateChat(player, message) | |
| 1300 | end | |
| 1301 | end | |
| 1302 | -- end | |
| 1303 | end | |
| 1304 | ||
| 1305 | -- After Chat.Configuration.Lifetime seconds of existence, the labels become invisible | |
| 1306 | -- Runs only every 5 seconds and has to loop through 50 values | |
| 1307 | -- Shouldn't be too expensive | |
| 1308 | function Chat:CullThread() | |
| 1309 | while true do | |
| 1310 | if #self.MessageQueue > 0 then | |
| 1311 | for _, field in pairs(self.MessageQueue) do | |
| 1312 | if field['SpawnTime'] and field['Player'] and field['Message'] and tick() - field['SpawnTime'] > self.Configuration.LifeTime then | |
| 1313 | field['Player'].Visible = false | |
| 1314 | field['Message'].Visible = false | |
| 1315 | end | |
| 1316 | end | |
| 1317 | end | |
| 1318 | wait(5.0) | |
| 1319 | end | |
| 1320 | end | |
| 1321 | ||
| 1322 | -- RobloxLock everything so users can't delete them(?) | |
| 1323 | function Chat:LockAllFields(gui) | |
| 1324 | local children = gui:GetChildren() | |
| 1325 | for i = 1, #children do | |
| 1326 | children[i].RobloxLocked = true | |
| 1327 | if #children[i]:GetChildren() > 0 then | |
| 1328 | Chat:LockAllFields(children[i]) | |
| 1329 | end | |
| 1330 | end | |
| 1331 | end | |
| 1332 | ||
| 1333 | function Chat:CoreGuiChanged(coreGuiType,enabled) | |
| 1334 | if coreGuiType == Enum.CoreGuiType.Chat or coreGuiType == Enum.CoreGuiType.All then | |
| 1335 | if self.Frame then self.Frame.Visible = enabled end | |
| 1336 | ||
| 1337 | if not Chat:IsTouchDevice() and self.ChatBar then | |
| 1338 | self.ChatBar.Visible = enabled | |
| 1339 | if enabled then | |
| 1340 | GuiService:SetGlobalGuiInset(0, 0, 0, 20) | |
| 1341 | else | |
| 1342 | GuiService:SetGlobalGuiInset(0, 0, 0, 0) | |
| 1343 | end | |
| 1344 | end | |
| 1345 | end | |
| 1346 | end | |
| 1347 | ||
| 1348 | _G.ChatHistory = _G.ChatHistory or {}
| |
| 1349 | function RunChatHistory(max) | |
| 1350 | for i=#_G.ChatHistory-max, #_G.ChatHistory do | |
| 1351 | local player, message = unpack(_G.ChatHistory[i] or {})
| |
| 1352 | ||
| 1353 | if player ~= nil and message ~= nil then | |
| 1354 | export:SendChat(player.Name, message, nil, true) | |
| 1355 | end | |
| 1356 | ||
| 1357 | end | |
| 1358 | end | |
| 1359 | ||
| 1360 | function AddToChatHistory(player, message) | |
| 1361 | table.insert(_G.ChatHistory, {player, message})
| |
| 1362 | end | |
| 1363 | ||
| 1364 | -- Constructor | |
| 1365 | -- This function initializes everything | |
| 1366 | function Chat:Initialize() | |
| 1367 | ||
| 1368 | Chat:CreateGui() | |
| 1369 | ||
| 1370 | function PlayerChatted(...) | |
| 1371 | Chat:PlayerChatted(...) | |
| 1372 | end | |
| 1373 | ||
| 1374 | function OnPlayer(p) | |
| 1375 | if p:IsA 'Player' then | |
| 1376 | p.Chatted:connect(function(chat) | |
| 1377 | PlayerChatted( | |
| 1378 | Enum.PlayerChatType.All, | |
| 1379 | p, | |
| 1380 | chat, | |
| 1381 | nil | |
| 1382 | ) | |
| 1383 | end) | |
| 1384 | end | |
| 1385 | end | |
| 1386 | ||
| 1387 | for _,p in pairs(game.Players:GetPlayers()) do | |
| 1388 | OnPlayer(p) | |
| 1389 | end | |
| 1390 | ||
| 1391 | game.Players.ChildAdded:connect(OnPlayer) | |
| 1392 | ||
| 1393 | self.EventListener = script.ChildAdded:connect(function(...) | |
| 1394 | -- This event has 4 callback arguments | |
| 1395 | -- Enum.PlayerChatType.All, chatPlayer, message, targetPlayer | |
| 1396 | -- Chat:PlayerChatted(...) | |
| 1397 | ||
| 1398 | end) | |
| 1399 | ||
| 1400 | -- Initialize input for us | |
| 1401 | -- Input:Initialize() | |
| 1402 | -- Eww, everytime a player is added, you have to redo the connection | |
| 1403 | -- Seems this is not automatic | |
| 1404 | -- -- NOTE: PlayerAdded only fires on the server, hence ChildAdded is used here | |
| 1405 | -- PlayersService.ChildAdded:connect(function() | |
| 1406 | -- Chat.EventListener:disconnect() | |
| 1407 | -- self.EventListener = PlayersService.PlayerChatted:connect(function(...) | |
| 1408 | -- -- This event has 4 callback arguments | |
| 1409 | -- -- Enum.PlayerChatType.All, chatPlayer, message, targetPlayer | |
| 1410 | -- Chat:PlayerChatted(...) | |
| 1411 | -- end) | |
| 1412 | -- end) | |
| 1413 | ||
| 1414 | Spawn(function() | |
| 1415 | Chat:CullThread() | |
| 1416 | end) | |
| 1417 | ||
| 1418 | -- Chat:LockAllFields(self.Frame) | |
| 1419 | -- self.Frame.DescendantAdded:connect(function(descendant) | |
| 1420 | ---- Chat:LockAllFields(descendant) | |
| 1421 | -- end) | |
| 1422 | end | |
| 1423 | ||
| 1424 | Chat:Initialize() | |
| 1425 | ||
| 1426 | RunChatHistory(10) | |
| 1427 | ||
| 1428 | _G.ChatAPI = export |