2013/yue/97188756.yue

1696 lines
40 KiB
Plaintext

import "macros" as { $ }
$load $FILE
--[[
//FileName: ChatScript.LUA
//Written by: Sorcus
//Description: Code for lua side chat on Mercury. Supports Scrolling.
//NOTE: If you find any bugs or inaccuracies PM Sorcus on Roblox or @Canavus on Twitter
]]
forceChatGUI = false
-- Utility functions + Globals
WaitForChild = (parent, childName) ->
until parent\FindFirstChild(childName)?
parent.ChildAdded\wait 0.03
parent[childName]
IsPhone = ->
cGui = Game\GetService "CoreGui"
rGui = WaitForChild cGui, "RobloxGui"
if rGui.AbsoluteSize.Y < 600
return true
false
-- 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
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
str\gsub "^%s*(.-)%s*$", "%1"
until Game.Players.LocalPlayer?
wait 0.03
Player = Game.Players.LocalPlayer
until Player.Character?
wait 0.03
Camera = Game.Workspace.CurrentCamera
-- Heliodex's basic New function (basically a simplified version of melt)
New = (className, name, props) ->
if not props? -- no name was provided
props = name
name = nil
obj = Instance.new className
obj.Name = name if name
local parent
for k, v in pairs props
if type(k) == "string"
if k == "Parent"
parent = v
else
obj[k] = v
elseif type(k) == "number" and type(v) == "userdata"
v.Parent = obj
obj.Parent = parent
obj
--
-- Services
CoreGuiService = Game\GetService "CoreGui"
PlayersService = Game\GetService "Players"
GuiService = Game\GetService "GuiService"
-- Lua Enums
Enums = {}
EnumName = {} -- used as unique key for enum name
CreateEnum = (enumName) ->
(t) ->
e = [EnumName]: enumName
for i, name in pairs t
item =
Name: name
Value: i
Enum: e
[EnumName]: enumName
<call>: (@, value) ->
value == @ or value == @Name or value == @Value
<tostring>: (@) ->
"Enum.#{@[EnumName]}.#{@Name}"
e[i] = e[name] = e[item] = item
Enums[enumName] = e
setmetatable e,
__call: (@, value) ->
@[value] or @[tonumber value]
__index:
GetEnumItems: (@) ->
t = {}
for i, item in pairs @
if type(i) == "number"
t[] = item
table.sort t, (a, b) -> a.Value < b.Value
t
__tostring: (@) ->
"Enum.#{@[EnumName]}"
---------------------------------------------------
------------------ Input class --------------------
Input =
Mouse: Player\GetMouse!
Speed: 0
Simulating: false
Configuration:
DefaultSpeed: 1
UserIsScrolling: false
---------------------------------------------------
------------------ Chat class --------------------
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', 'Mercury', 'RBAdam', 'Doughtless',
'Anaminus', 'Stravant', 'Cr3470r', 'CodeWriter', 'Games', 'AcesWayUpHigh', 'Phil'
}, --]]
Admins_List:
* "taskmanager"
* "Heliodex"
* "tako"
SafeChat_List:
"Use the Chat menu to talk to me.":
* "/sc0"
* true
"I can only see menu chats.":
* "/sc1"
* true
Hello:
Hi:
* "/sc2_0"
* true
"Hi there!": true
"Hi everyone": true
Howdy:
* "/sc2_1"
* true
"Howdy partner!": true
Greetings:
* "/sc2_2"
* true
"Greetings everyone": true
"Greetings Robloxians!": true
"Seasons greetings!": true
Welcome:
* "/sc2_3"
* true
"Welcome to my place": true
"Welcome to my barbeque": true
"Welcome to our base": true
"Hey there!":
* "/sc2_4"
* true
"What's up?":
* "/sc2_5"
* true
"How are you doing?": true
"How's it going?": true
"What's new?": true
"Good day":
* "/sc2_6"
* true
"Good morning": true
"Good evening": true
"Good afternoon": true
"Good night": true
Silly:
* "/sc2_7"
* true
"Waaaaaaaz up?!": true
"Hullo!": true
"Behold greatness, mortals!": true
"Pardon me, is this Sparta?": true
"THIS IS SPARTAAAA!": true
"Happy Holidays!":
* "/sc2_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 Mercury Day!": true
"Happy LOL Day!": true
* "/sc2"
Goodbye:
"Good Night":
* "/sc3_0"
* true
"Sweet dreams": true
"Go to sleep!": true
"Lights out!": true
Bedtime: true
"Going to bed now": true
Later:
* "/sc3_1"
* true
"See ya later": true
"Later gator!": true
"See you tomorrow": true
Bye:
* "/sc3_2"
* true
"Hasta la bye bye!": true
"I'll be right back":
* "/sc3_3"
* true
"I have to go":
* "/sc3_4"
* true
Farewell:
* "/sc3_5"
* true
"Take care": true
"Have a nice day": true
"Goodluck!": true
"Ta-ta for now!": true
Peace:
* "/sc3_6"
* true
"Peace out!": true
"Peace dudes!": true
"Rest in pieces!": true
Silly:
* "/sc3_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
* "/sc3"
Friend:
"Wanna be friends?":
* "/sc4_0"
* true
"Follow me":
* "/sc4_1"
* true
"Come to my place!": true
"Come to my base!": true
"Follow me, team!": true
"Follow me": true
"Your place is cool":
* "/sc4_2"
* true
"Your place is fun": true
"Your place is awesome": true
"Your place looks good": true
"This place is awesome!": true
"Thank you":
* "/sc4_3"
* true
"Thanks for playing": true
"Thanks for visiting": true
"Thanks for everything": true
"No, thank you": true
Thanx: true
"No problem":
* "/sc4_4"
* true
"Don't worry": true
"That's ok": true
np: true
"You are ...":
* "/sc4_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 ...":
* "/sc4_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:
* "/sc4_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
* "/sc4"
Questions:
"Who?":
* "/sc5_0"
* true
"Who wants to be my friend?": true
"Who wants to be on my team?": true
"Who made this brilliant game?": true
"What?":
* "/sc5_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?":
* "/sc5_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?":
* "/sc5_3"
* true
"Where do you want to go?": true
"Where are you going?": true
"Where am I?!": true
"Where did you go?": true
"How?":
* "/sc5_4"
* true
"How are you today?": true
"How did you make this cool place?": true
"LOLHOW?": true
"Can I...":
* "/sc5_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
* "/sc5"
Answers:
"You need help?":
* "/sc6_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 ...":
* "/sc6_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 ...":
* "/sc6_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:
* "/sc6_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:
* "/sc6_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:
* "/sc6_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":
* "/sc6_6"
* true
"Science Fiction": true
Animated:
Anime: true
Comedy: true
Romantic: true
Action: true
Fantasy: true
Music:
* "/sc6_7"
* true
Country: true
Jazz: true
Rap: true
"Hip-hop": true
Techno: true
Classical: true
Pop: true
Rock: true
Hobbies:
* "/sc6_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:
* "/sc6_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:
* "/sc6_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:
* "/sc6_11"
* true
Good: true
"Great!": true
"Not bad": true
Sad: true
Hyper: true
Chill: true
Happy: true
"Kind of mad": true
Boy:
* "/sc6_12"
* true
Girl:
* "/sc6_13"
* true
"I don't want to say boy or girl. Don't ask.":
* "/sc6_14"
* true
* "/sc6"
Game:
"Let's build":
* "/sc7_0"
* true
"Let's battle":
* "/sc7_1"
* true
"Nice one!":
* "/sc7_2"
* true
"So far so good":
* "/sc7_3"
* true
"Lucky shot!":
* "/sc7_4"
* true
"Oh man!":
* "/sc7_5"
* true
"I challenge you to a fight!":
* "/sc7_6"
* true
"Help me with this":
* "/sc7_7"
* true
"Let's go to your game":
* "/sc7_8"
* true
"Can you show me how do to that?":
* "/sc7_9"
* true
"Backflip!":
* "/sc7_10"
* true
"Frontflip!":
* "/sc7_11"
* true
"Dance!":
* "/sc7_12"
* true
"I'm on your side!":
* "/sc7_13"
* true
"Game Commands":
* "/sc7_14"
* true
regen: true
reset: true
go: true
fix: true
respawn: true
* "/sc7"
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
---------------------------------------------------
---------------------------------------------------
GetNameValue = (pName) ->
value = 0
for index = 1, #pName
cValue = string.byte string.sub pName, index, index
reverseIndex = #pName - index + 1
if #pName % 2 == 1
reverseIndex = reverseIndex - 1
if reverseIndex % 4 >= 2
cValue = -cValue
value = value + cValue
value % 8
Chat.ComputeChatColor = (pName) =>
@ChatColors[GetNameValue(pName) + 1].Color
-- This is context based scrolling
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
@MouseOnFrame = false
if @RenderFrame
@RenderFrame.MouseEnter\connect ->
character = Player.Character
torso = WaitForChild character, "Torso"
head = WaitForChild character, "Head"
if toggle
@MouseOnFrame = true
Camera.CameraType = "Scriptable"
-- Get relative position of camera and keep to it
Spawn ->
currentRelativePos = Camera.CoordinateFrame.p - torso.Position
while Chat.MouseOnFrame
Camera.CoordinateFrame = CFrame.new torso.Position + currentRelativePos, head.Position
wait 0.015
@RenderFrame.MouseLeave\connect ->
Camera.CameraType = "Custom"
@MouseOnFrame = false
-- TODO: Scrolling using Mouse wheel
-- Chat.OnScroll = (speed) =>
-- if @MouseOnFrame
-- --
-- end
-- end
-- Check if we are running on a touch device
Chat.IsTouchDevice ==>
touchEnabled = false
try
touchEnabled = Game\GetService"UserInputService".TouchEnabled
touchEnabled
-- Scrolling
-- Chat.ScrollQueue = (value) =>
-- for i = 1, #@MessageQueue
-- if @MessageQueue[i]
-- for _, label in pairs(@MessageQueue[i])
-- next = @MessageQueue[i].Next
-- previous = @MessageQueue[i].Previous
-- if label and label\IsA('TextLabel') or label\IsA('TextButton')
-- if value > 0 and previous and previous['Message']
-- label.Position = previous['Message'].Position
-- elseif value < 1 and next['Message']
-- label.Position = previous['Message'].Position
-- Handles the rendering of the text objects in their appropriate places
Chat.UpdateQueue = (field, diff) =>
-- Have to do some sort of correction here
for i = #@MessageQueue, 1, -1
if @MessageQueue[i]
for _, label in pairs @MessageQueue[i]
if label and type(label) ~= "table" and type(label) ~= "number"
if label\IsA"TextLabel" or label\IsA "TextButton"
if diff
label.Position = label.Position - UDim2.new(0, 0, diff, 0)
else
if field == @MessageQueue[i]
label.Position = UDim2.new(
@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 ->
wait 0.05
while label.TextTransparency >= 0
label.TextTransparency = label.TextTransparency - 0.2
wait 0.03
label.TextStrokeTransparency = if label == field["Message"]
0.8
else
1
else
label.Position = UDim2.new(
@Configuration.XScale,
0,
label.Position.Y.Scale - field["Message"].Size.Y.Scale,
0
)
if label.Position.Y.Scale < -0.01
-- NOTE: Remove this fix when Textbounds is fixed
label.Visible = false
label\Destroy!
Chat.CreateScrollBar ==>
-- Code for scrolling is in here, partially, but scroll bar drawing isn't drawn
-- TODO: Implement
-- For scrolling, to see if we hit the bounds so that we can stop it from scrolling anymore
Chat.CheckIfInBounds = (value) =>
if #Chat.MessageQueue < 3
return true
if value > 0 and
Chat.MessageQueue[1] and
Chat.MessageQueue[1]["Player"] and
Chat.MessageQueue[1]["Player"].Position.Y.Scale == 0
true
elseif value < 0 and
Chat.MessageQueue[1] and
Chat.MessageQueue[1]["Player"] and
Chat.MessageQueue[1]["Player"].Position.Y.Scale < 0
true
else
false
-- This is to precompute all playerName space strings
-- This is used to offset the message by exactly this + 2 spacestrings
Chat.ComputeSpaceString = (pLabel) =>
nString = " "
if not @TempSpaceLabel
@TempSpaceLabel = New "TextButton", "SpaceButton"
Size: UDim2.new 0, pLabel.AbsoluteSize.X, 0, pLabel.AbsoluteSize.Y
FontSize: @Configuration.FontSize
Parent: @RenderFrame
BackgroundTransparency: 1
Text: nString
else
@TempSpaceLabel.Text = nString
while @TempSpaceLabel.TextBounds.X < pLabel.TextBounds.X
nString ..= " "
@TempSpaceLabel.Text = nString
nString ..= " "
@CachedSpaceStrings_List[pLabel.Text] = nString
@TempSpaceLabel.Text = ""
nString
-- When the playerChatted event fires
-- The message is what the player chatted
Chat.UpdateChat = (cPlayer, message) =>
messageField =
Player: cPlayer
Message: message
if coroutine.status(Chat.MessageThread) == "dead"
--Chat.Messages_List = {}
table.insert Chat.Messages_List, messageField
Chat.MessageThread = coroutine.create ->
for i = 1, #Chat.Messages_List
field = Chat.Messages_List[i]
Chat\CreateMessage field["Player"], field["Message"]
Chat.Messages_List = {}
coroutine.resume Chat.MessageThread
else
table.insert Chat.Messages_List, messageField
-- Chat.RecalculateSpacing ==>
--[[for i = 1, #@MessageQueue
pLabel = @MessageQueue[i]['Player']
mLabel = @MessageQueue[i]['Message']
prevYScale = mLabel.Size.Y.Scale
prevText = mLabel.Text
mLabel.Text = prevText
heightField = mLabel.TextBounds.Y
mLabel.Size = UDim2.new(1, 0, heightField/@RenderFrame.AbsoluteSize.Y, 0)
pLabel.Size = mLabel.Size
diff = mLabel.Size.Y.Scale - prevYScale
Chat\UpdateQueue(@MessageQueue[i], diff)
end ]]
-- Chat.ApplyFilter = (str) =>
-- --[[for _, word in pair(@Filter_List)
-- if string.find(str, word)
-- str\gsub word, '@#$^'
-- ]]
-- NOTE: Temporarily disabled ring buffer to allow for chat to always wrap around
Chat.CreateMessage = (cPlayer, message) =>
local pName
if not cPlayer
pName = ""
else
pName = cPlayer.Name
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 #@MessageQueue > @Configuration.HistoryLength
--[[pLabel = @MessageQueue[#@MessageQueue]['Player']
mLabel = @MessageQueue[#@MessageQueue]['Message']
pLabel.Text = pName .. ':'
pLabel.Name = pName
local pColor
if cPlayer.Neutral
pLabel.TextColor3 = Chat\ComputeChatColor(pName)
else
pLabel.TextColor3 = cPlayer.TeamColor.Color
local nString
if not @CachedSpaceStrings_List[pName]
nString = Chat\ComputeSpaceString(pLabel)
else
nString = @CachedSpaceStrings_List[pName]
end
mLabel.Text = ""
mLabel.Name = pName .. " - message"
mLabel.Text = nString .. message;
mLabel.Parent = nil
mLabel.Parent = @RenderFrame
mLabel.Position = UDim2.new 0, 0, 1, 0;
pLabel.Position = UDim2.new 0, 0, 1, 0;]]
-- Reinserted at the beginning, ring buffer
@MessageQueue[#@MessageQueue] = nil
--else
-- Haven't hit the mark yet, so keep creating
pLabel = New "TextLabel", pName,
Text: pName .. ":"
-- TextColor3 = pColor
FontSize: Chat.Configuration.FontSize
TextXAlignment: Enum.TextXAlignment.Left
TextYAlignment: Enum.TextYAlignment.Top
Parent: @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
if cPlayer.Neutral
pLabel.TextColor3 = Chat\ComputeChatColor pName
else
pLabel.TextColor3 = cPlayer.TeamColor.Color
local nString
if not @CachedSpaceStrings_List[pName]
nString = Chat\ComputeSpaceString(pLabel)
else
nString = @CachedSpaceStrings_List[pName]
mLabel = New "TextLabel", "#{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: @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
pLabel.Text = ""
mLabel.TextColor3 = Color3.new 0, 0.4, 1.0
--end
for _, adminName in pairs @Admins_List
if string.lower(adminName) == string.lower pName
mLabel.TextColor3 = @Configuration.AdminMessageColor
pLabel.Visible = true
mLabel.Visible = true
-- This will give beautiful multilines as well
heightField = mLabel.TextBounds.Y
mLabel.Size = UDim2.new 1, 0, heightField / @RenderFrame.AbsoluteSize.Y, 0
pLabel.Size = mLabel.Size
queueField = {}
queueField["Player"] = pLabel
queueField["Message"] = mLabel
queueField["SpawnTime"] = tick! -- Used for identifying when to make the message invisible
table.insert @MessageQueue, 1, queueField
Chat\UpdateQueue queueField
Chat.ScreenSizeChanged ==>
wait!
while @Frame.AbsoluteSize.Y > 120
@Frame.Size = @Frame.Size - UDim2.new 0, 0, 0.005, 0
-- Chat\RecalculateSpacing!
Chat.FindButtonTree = (scButton, rootList) =>
list = {}
rootList = rootList or @SafeChatTree
for button, _ in pairs rootList
if button == scButton
list = rootList[button]
elseif type(rootList[button]) == "table"
list = Chat\FindButtonTree scButton, rootList[button]
return list
Chat.ToggleSafeChatMenu = (scButton) =>
list = Chat\FindButtonTree scButton, @SafeChatTree
if list
for button, _ in pairs list
if button\IsA"TextButton" or button\IsA "ImageButton"
button.Visible = not button.Visible
return true
return false
Chat.CreateSafeChatOptions = (list, rootButton) =>
text_List = {}
count = 0
text_List[rootButton] = {}
text_List[rootButton][1] = list[1]
rootButton = rootButton or @SafeChatButton
for msg, _ in pairs list
if type(msg) == "string"
chatText = New "TextButton", 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: @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"
text_List[rootButton][chatText] = Chat\CreateSafeChatOptions list[msg], chatText
-- else
-- --table.insert(text_List[chatText], true)
chatText.MouseEnter\connect ->
Chat\ToggleSafeChatMenu chatText
chatText.MouseLeave\connect ->
Chat\ToggleSafeChatMenu chatText
chatText.MouseButton1Click\connect ->
lList = Chat\FindButtonTree chatText
-- if lList
-- for i, v in pairs lList
try
PlayersService\Chat lList[1]
return text_List
Chat.CreateSafeChatGui ==>
@SafeChatFrame = New "Frame", "SafeChatFrame"
Size: UDim2.new 1, 0, 1, 0
Parent: @Gui
BackgroundTransparency: 1
* New "ImageButton", "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"
@SafeChatButton = @SafeChatFrame.SafeChatButton
-- safe chat button is the root of this tree
@SafeChatTree[@SafeChatButton] = Chat\CreateSafeChatOptions @SafeChat_List, @SafeChatButton
@SafeChatButton.MouseButton1Click\connect ->
Chat\ToggleSafeChatMenu @SafeChatButton
Chat.FocusOnChatBar ==>
if @ClickToChatButton
@ClickToChatButton.Visible = false
@GotFocus = true
if @Frame["Background"]
@Frame.Background.Visible = false
@ChatBar\CaptureFocus!
-- For touch devices we create a button instead
Chat.CreateTouchButton ==>
@ChatTouchFrame = New "Frame", "ChatTouchFrame"
Size: UDim2.new 0, 128, 0, 32
Position: UDim2.new 0, 88, 0, 0
BackgroundTransparency: 1
Parent: @Gui
* New "ImageButton", "ChatLabel"
Size: UDim2.new 0, 74, 0, 28
Position: UDim2.new 0, 0, 0, 0
BackgroundTransparency: 1
ZIndex: 2.0
* New "ImageLabel", "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"
@TapToChatLabel = @ChatTouchFrame.ChatLabel
@TouchLabelBackground = @ChatTouchFrame.Background
@ChatBar = New "TextBox", "ChatBar"
Size: UDim2.new 1, 0, 0.2, 0
Position: UDim2.new 0, 0, 0.8, 800
Text: ""
ZIndex: 1
BackgroundTransparency: 1
Parent: @Frame
TextXAlignment: Enum.TextXAlignment.Left
TextColor3: Color3.new 1, 1, 1
ClearTextOnFocus: false
@TapToChatLabel.MouseButton1Click\connect ->
@TapToChatLabel.Visible = false
--@ChatBar.Visible = true
--@Frame.Background.Visible = true
@ChatBar\CaptureFocus!
@GotFocus = true
if @TouchLabelBackground
@TouchLabelBackground.Visible = false
-- Non touch devices, create the bottom chat bar
Chat.CreateChatBar ==>
-- okay now we
local status, result = try
return GuiService.UseLuaChat
if forceChatGUI or (status and result)
@ClickToChatButton = New "TextButton", "ClickToChat"
Size: UDim2.new 1, 0, 0, 20
BackgroundTransparency: 1
ZIndex: 2.0
Parent: @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
@ChatBar = New "TextBox", "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: @Gui
TextXAlignment: Enum.TextXAlignment.Left
TextColor3: Color3.new 1, 1, 1
FontSize: Enum.FontSize.Size12
ClearTextOnFocus: false
-- 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 = try
GuiService\SetGlobalGuiInset 0, 0, 0, 20
if not success
GuiService\SetGlobalSizeOffsetPixel 0, -20
-- CHatHotKey is '/'
GuiService\AddSpecialKey Enum.SpecialKey.ChatHotkey
GuiService.SpecialKeyPressed\connect (key) ->
if key == Enum.SpecialKey.ChatHotkey
Chat\FocusOnChatBar!
@ClickToChatButton.MouseButton1Click\connect ->
Chat\FocusOnChatBar!
-- Create the initial Chat stuff
-- Done only once
Chat.CreateGui ==>
@Gui = WaitForChild CoreGuiService, "RobloxGui"
@Frame = New "Frame", "ChatFrame"
--Size: @Configuration.Size
Size: UDim2.new 0, 500, 0, 120
Position: UDim2.new 0, 0, 0, 5
BackgroundTransparency: 1
--ClipsDescendants: true
ZIndex: 0
Parent: @Gui
Active: false
* New "ImageLabel", "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
* New "Frame", "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
* New "Frame", "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 ->
wait 0.5
if IsPhone!
@Frame.Size = UDim2.new 0, 280, 0, 120
@RenderFrame = @Frame.ChatRenderFrame
if Chat\IsTouchDevice!
@Frame.Position = @Configuration.Position
@RenderFrame.Size = UDim2.new 1, 0, 1, 0
elseif @Frame.AbsoluteSize.Y > 120
Chat\ScreenSizeChanged!
@Gui.Changed\connect (property) ->
if property == "AbsoluteSize"
Chat\ScreenSizeChanged!
if forceChatGUI or Player.ChatMode == Enum.ChatMode.TextAndMenu
if Chat\IsTouchDevice!
Chat\CreateTouchButton!
else
Chat\CreateChatBar!
--Chat\CreateSafeChatGui!
if @ChatBar
@ChatBar.FocusLost\connect (enterPressed) ->
Chat.GotFocus = false
if Chat\IsTouchDevice!
@ChatBar.Visible = false
@TapToChatLabel.Visible = true
if @TouchLabelBackground
@TouchLabelBackground.Visible = true
if enterPressed and @ChatBar.Text ~= ""
cText = @ChatBar.Text
if string.sub(@ChatBar.Text, 1, 1) == "%"
cText = "(TEAM) #{string.sub cText, 2, #cText}"
try
PlayersService\TeamChat cText
else
try
PlayersService\Chat cText
if @ClickToChatButton
@ClickToChatButton.Visible = true
@ChatBar.Text = ""
Spawn ->
wait 5.0
if not Chat.GotFocus
Chat.Frame.Background.Visible = false
-- Scrolling function
-- Applies a speed(velocity) to have nice scrolling effect
Input.OnMouseScroll = =>
Spawn ->
-- How long should the speed last?
while Input.Speed ~= 0
if Input.Speed > 1
while Input.Speed > 0
Input.Speed = Input.Speed - 1
wait 0.25
elseif Input.Speed < 0
while Input.Speed < 0
Input.Speed = Input.Speed + 1
wait 0.25
wait 0.03
return if Chat\CheckIfInBounds Input.Speed
Chat\ScrollQueue!
Input.ApplySpeed = (value) =>
Input.Speed = Input.Speed + value
if not @Simulating
Input\OnMouseScroll!
Input.Initialize = =>
@Mouse.WheelBackward\connect ->
Input\ApplySpeed @Configuration.DefaultSpeed
@Mouse.WheelForward\connect ->
Input\ApplySpeed @Configuration.DefaultSpeed
Chat.FindMessageInSafeChat = (message, list) =>
foundMessage = false
for msg, _ in pairs list
if msg == message
return true
if type(list[msg]) == "table"
foundMessage = Chat\FindMessageInSafeChat message, list[msg]
if foundMessage
return true
foundMessage
-- Just a wrapper around our PlayerChatted event
Chat.PlayerChatted = (...) =>
args = { ... }
-- argCount = select("#", ...)
local player, message
-- This doesn't look very good, but what else to do?
if args[2]
player = args[2]
if args[3]
message = args[3]
if string.sub(message, 1, 1) == "%"
message = "(TEAM) #{string.sub message, 2, #message}"
if PlayersService.ClassicChat
if not (string.sub(message, 1, 3) == "/e " or string.sub(message, 1, 7) == "/emote ") and
(forceChatGUI or Player.ChatMode == Enum.ChatMode.TextAndMenu) or
(Player.ChatMode == Enum.ChatMode.Menu and string.sub(message, 1, 3) == "/sc") or
Chat\FindMessageInSafeChat message, @SafeChat_List
Chat\UpdateChat player, message
-- 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
Chat.CullThread ==>
while true
if #@MessageQueue > 0
for _, field in pairs(@MessageQueue)
if field["SpawnTime"] and
field["Player"] and
field["Message"] and
tick! - field["SpawnTime"] > @Configuration.LifeTime
field["Player"].Visible = false
field["Message"].Visible = false
wait 5.0
-- RobloxLock everything so users can't delete them(?)
Chat.LockAllFields = (gui) =>
children = gui\GetChildren!
for i = 1, #children
children[i].RobloxLocked = true
if #children[i]\GetChildren! > 0
Chat\LockAllFields children[i]
Chat.CoreGuiChanged = (coreGuiType, enabled) =>
if coreGuiType == Enum.CoreGuiType.Chat or coreGuiType == Enum.CoreGuiType.All
if @Frame
@Frame.Visible = enabled
if not Chat\IsTouchDevice! and @ChatBar
@ChatBar.Visible = enabled
GuiService\SetGlobalGuiInset 0, 0, 0, if enabled
20
else
0
-- Constructor
-- This function initializes everything
Chat.Initialize ==>
Chat\CreateGui!
try
Chat\CoreGuiChanged Enum.CoreGuiType.Chat, Game.StarterGui\GetCoreGuiEnabled Enum.CoreGuiType.Chat
Game.StarterGui.CoreGuiChangedSignal\connect (coreGuiType, enabled) ->
Chat\CoreGuiChanged coreGuiType, enabled
@EventListener = PlayersService.PlayerChatted\connect (...) ->
-- This event has 4 callback arguments
-- Enum.PlayerChatType.All, chatPlayer, message, targetPlayer
Chat\PlayerChatted ...
@MessageThread = coroutine.create ->
coroutine.resume @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 ->
Chat.EventListener\disconnect!
@EventListener = PlayersService.PlayerChatted\connect (...) ->
-- This event has 4 callback arguments
-- Enum.PlayerChatType.All, chatPlayer, message, targetPlayer
Chat\PlayerChatted ...
Spawn ->
Chat\CullThread!
@Frame.RobloxLocked = true
Chat\LockAllFields @Frame
@Frame.DescendantAdded\connect (descendant) ->
Chat\LockAllFields descendant
Chat\Initialize!