How can I clean up this code?

How am I able to clean up this code? It’s like 400 lines long and it’s so messy and unreadable at this point. I have no idea what to change about it. I considered using external modules, but that wouldn’t really work.

Code:

-- TODO:

-- A module that creates hints with just a bit of customization and simple code.

---------- Variables ----------

local HS = { }
local DisallowedWhiteSpace = {"\n", "\r", "\t", "\v", "\f"}

--

local GuiService = game:GetService("GuiService")
local StarterGui = game:GetService("StarterGui")
local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
local TextService = game:GetService("TextService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

--

local DefaultThemeFolder = script:WaitForChild("DefaultTheme")
local ThemesFolder = script:WaitForChild("Themes")
local Assets = script:WaitForChild("Assets")
local Plugins = script:WaitForChild("Plugins")
local Signal = require(Plugins:FindFirstChild("Signal"))
local DefaultTheme = require(DefaultThemeFolder:WaitForChild("DefaultTheme"))
local HintsGui = Assets:FindFirstChild("Hints"):Clone()
local Player = Players.LocalPlayer
local PlayerGui = Player:WaitForChild("PlayerGui")

---------- Events & Properties ----------

local function argumentError(argument : string, functionName : string)
	argument = argument or "nil"
	functionName = functionName or "nil"
	error(string.format("The %s argument must be passed in the %s function.", argument, functionName))
end

local function invalidError(object : string, type : string)
	object = object or "nil"
	type = type or "nil"
	error(string.format("%s is not a valid %s.", object, type))
end

local function customError(msg : string, ...)
	error(string.format(msg, ...))
end

local function customError2(msg : string)
	error(msg)
end

local function onMenuOpenedConfig(isHintVisible : boolean)
	HintsGui.Enabled = isHintVisible
end

local function setHintProperties(self : any)
	if not self then
		argumentError("self", "setHintProperties")
	end
	
	self._.BackgroundColor3 = self.HintTheme.hintColor
	self._.UICorner.CornerRadius = self.HintTheme.hintCornerRadius
	self._.BorderUIStroke.Color = self.HintTheme.hintStrokeColor
	self._.BorderUIStroke.LineJoinMode = self.HintTheme.hintStrokeLineJoinMode
	self._.BorderUIStroke.Thickness = self.HintTheme.hintStrokeSize
	self._.TextColor3 = self.HintTheme.labelColor
	self._.TextUIStroke.Color = self.HintTheme.labelStrokeColor
	self._.TextUIStroke.LineJoinMode = self.HintTheme.labelStrokeLineJoinMode
	self._.TextUIStroke.Thickness = self.HintTheme.hintStrokeSize
	self._.Font = self.HintTheme.labelFont
	self._.ExtraPadding.PaddingLeft = self.HintTheme.labelPaddingLeft
	self._.ExtraPadding.PaddingRight = self.HintTheme.labelPaddingRight
	
	self.HintTransparency = self.HintTheme.hintTransparency
	self.LabelTransparency = self.HintTheme.labelTransparency
end

local function cancelHint(self : any)
	local type = self.AnimationType
	local label = self._
	
	if type == "Fade" then
		TweenService:Create(label, TweenInfo.new(self.TweenLength2, self.EasingStyle2, self.EasingDirection2), {Transparency = 1}):Play()
		TweenService:Create(label:WaitForChild("BorderUIStroke"), TweenInfo.new(self.TweenLength2, self.EasingStyle2, self.EasingDirection2), {Transparency = 1}):Play()
		TweenService:Create(label:WaitForChild("TextUIStroke"), TweenInfo.new(self.TweenLength2, self.EasingStyle2, self.EasingDirection2), {Transparency = 1}):Play()
			task.wait(self.TweenLength2)
			label:Destroy()
	elseif type == "None" then
		label.Transparency = 1
		label:WaitForChild("BorderUIStroke").Transparency = 1
		label:WaitForChild("BorderUIStroke").Transparency = 1
		label:Destroy()
	end
end

local function animateHint(self : any)
	local type = self.AnimationType
	local infiniteTime = self.InfiniteTime
	local label = self._
	label.Visible = true
	local hintCancelled = self.Cancelled
	if not self then
		argumentError("self", "animateHint")
	end
	if self.VisibleTime <= 1 then
		error("Max visible time cannot be 1 or under.")
	end
	
	if type == "Fade" then
		if self.InfiniteTime == true then
			HS.HintAdding:Fire(label)
			self.BroadcastRecieved:Fire()
			TweenService:Create(label, TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {TextTransparency = self.LabelTransparency}):Play()
			TweenService:Create(label, TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {BackgroundTransparency = self.HintTransparency}):Play()
			TweenService:Create(label:WaitForChild("BorderUIStroke"), TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {Transparency = self.HintTransparency}):Play()
			TweenService:Create(label:WaitForChild("TextUIStroke"), TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {Transparency = self.LabelTransparency}):Play()
		else
			HS.HintAdding:Fire(label)
			self.BroadcastRecieved:Fire()
			TweenService:Create(label, TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {TextTransparency = self.LabelTransparency}):Play()
			TweenService:Create(label, TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {BackgroundTransparency = self.HintTransparency}):Play()
			TweenService:Create(label:WaitForChild("BorderUIStroke"), TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {Transparency = self.HintTransparency}):Play()
			TweenService:Create(label:WaitForChild("TextUIStroke"), TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {Transparency = self.LabelTransparency}):Play()
			task.wait(self.VisibleTime + self.TweenLength1)
			if not hintCancelled then
				HS.HintRemoving:Fire(label)
				TweenService:Create(label, TweenInfo.new(self.TweenLength2, self.EasingStyle2, self.EasingDirection2), {Transparency = 1}):Play()
				TweenService:Create(label:WaitForChild("BorderUIStroke"), TweenInfo.new(self.TweenLength2, self.EasingStyle2, self.EasingDirection2), {Transparency = 1}):Play()
				TweenService:Create(label:WaitForChild("TextUIStroke"), TweenInfo.new(self.TweenLength2, self.EasingStyle2, self.EasingDirection2), {Transparency = 1}):Play()
				task.wait(self.TweenLength2)
				label:Destroy()
			elseif hintCancelled then
				return
			end
		end
	elseif type == "None" then
		if self.InfiniteTime == true then
			HS.HintAdding:Fire(label)
			self.BroadcastRecieved:Fire()
			label.TextTransparency = self.LabelTransparency
			label.BackgroundTransparency = self.HintTransparency
			label:WaitForChild("BorderUIStroke").Transparency = self.HintTransparency
			label:WaitForChild("BorderUIStroke").Transparency = self.LabelTransparency
		else
			HS.HintAdding:Fire(label)
			self.BroadcastRecieved:Fire()
			label.TextTransparency = self.LabelTransparency
			label.BackgroundTransparency = self.HintTransparency
			label:WaitForChild("BorderUIStroke").Transparency = self.HintTransparency
			label:WaitForChild("BorderUIStroke").Transparency = self.LabelTransparency
			task.wait(self.VisibleTime)
			if not hintCancelled then
				HS.HintRemoving:Fire(label)
				label.Transparency = 1
				label:WaitForChild("BorderUIStroke").Transparency = 1
				label:WaitForChild("BorderUIStroke").Transparency = 1
				label:Destroy()
			elseif hintCancelled then
				return
			end
		end
	end
end

HintsGui.Parent = PlayerGui
HintsGui.Archivable = false

--

HS.HintAdding = Signal.new()
HS.HintRemoving = Signal.new()

--

GuiService.MenuOpened:Connect(function()
	onMenuOpenedConfig(false)
end)

GuiService.MenuClosed:Connect(function()
	onMenuOpenedConfig(true)
end)

---------- Constructors ----------

function HS.new(xAlignment : "Left" | "Center" | "Right")
	local newClass = setmetatable({ }, {__index = HS})
	
	newClass._ = script.Assets:WaitForChild("HintMsg"):Clone()
	
	local HintsFrame = HintsGui.HintsFrame
	if xAlignment == "Right" then
		StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.PlayerList, false)
		newClass._.Parent = HintsFrame.RightFrame
		newClass.HintXAlignment = 3
	elseif xAlignment == "Center" then
		newClass._.Parent = HintsFrame.CenterFrame
		newClass.HintXAlignment = 2
	elseif xAlignment == "Left" then
		newClass._.Parent = HintsFrame.LeftFrame
		newClass.HintXAlignment = 1
	end
	
	newClass.HintXAlignment = 2
	newClass.HintTheme = DefaultTheme
	newClass.VisibleTime = 12
	newClass.HintTransparency = newClass.HintTheme.hintTransparency
	newClass.LabelTransparency = newClass.HintTheme.labelTransparency
	newClass.EasingDirection1 = Enum.EasingDirection.In
	newClass.EasingDirection2 = Enum.EasingDirection.Out
	newClass.EasingStyle1 = Enum.EasingStyle.Quad
	newClass.EasingStyle2 = Enum.EasingStyle.Quad
	newClass.TweenLength1 = 1
	newClass.TweenLength2 = 1
	newClass.Cancelled = false
	newClass.BroadcastCancelled = Signal.new()
	newClass.BroadcastRecieved = Signal.new()
	newClass.Broadcasted = Signal.new()
	newClass.InfiniteTime = false
	newClass.AnimationType = "Fade"
	newClass.EligibleToBeCancelled = false
	
	return newClass
end

---------- Setting Methods ----------

function HS:setLabel(text : string)
	text = text or ""
	for k,v in ipairs(DisallowedWhiteSpace) do
		if string.find(text, v) then
			customError2("Whitespaces are not allowed.")
		end
	end
	local label = self._

	label.Text = text
end

function HS:setVisibleTime(isInfinite : boolean, time : number)
	time = time or 12
	isInfinite = isInfinite or false
	local label = self._
	
	self.InfiniteTime = isInfinite
	self.VisibleTime = time
end

function HS:setRichText(enabled : boolean)
	enabled = enabled or false
	local label = self._
	
	label.RichText = enabled
end

function HS:setTweenLength(length1 : number, length2 : number)
	length1 = length1 or 1
	length2 = length2 or 1
	
	self.TweenLength1 = length1
	self.TweenLength2 = length2
end

function HS:setTweenDirection(direction1 : Enum.EasingDirection, direction2 : Enum.EasingDirection)
	direction1 = direction1 or Enum.EasingDirection.In
	direction2 = direction2 or Enum.EasingDirection.Out
	
	self.EasingDirection1 = direction1
	self.EasingDirection2 = direction2
end

function HS:setTweenStyle(style1 : Enum.EasingStyle, style2 : Enum.EasingStyle)
	style1 = style1 or Enum.EasingStyle.Quad
	style2 = style2 or Enum.EasingStyle.Quad
	
	self.EasingStyle1 = style1
	self.EasingStyle2 = style2
end

function HS:setTheme(theme : string)
	if ThemesFolder:FindFirstChild(theme) and ThemesFolder:FindFirstChild(theme):IsA("ModuleScript") then
		self.HintTheme = require(ThemesFolder:FindFirstChild(theme))
	else
		invalidError(theme, "theme")
	end
end

function HS:setTweenType(type : "Fade" | "None")
	self.AnimationType = type
end

---------- Getting Methods ----------

function HS:getLabel(): string
	return self._.Text
end

function HS:getLabelFont(returnAsString : boolean): Enum.Font | string
	if returnAsString then
		return self._.Font.Name
	else
		return self._.Font
	end
end

function HS:getCurrentHints(): {TextLabel}
	local hintsTable = {}
	for k,v in pairs(HintsGui.HintsFrame:GetDescendants()) do
		if v:IsA("TextLabel") and v.Name == "HintMsg" then
			table.insert(hintsTable, v)
		end
	end
	return hintsTable
end

function HS:getVisibleTime(): number
	return self.VisibleTime
end

function HS:getTweenLength(type : "1" | "2"): number
	if type == "1" then
		return self.TweenLength1
	else
		return self.TweenLength2
	end
end

function HS:getTweenDirection(type : "1" | "2"): Enum.EasingDirection
	if type == "1" then
		return self.EasingDirection1
	else
		return self.EasingDirection2
	end
end

function HS:getTweenStyle(type : "1" | "2"): Enum.EasingStyle
	if type == "1" then
		return self.EasingStyle1
	else
		return self.EasingStyle2
	end
end

function HS:getTweenType(type : "1" | "2"): "Fade" | "None"
	return self.AnimationType
end

function HS:getDestroyOnFinished(): boolean
	return self.DestroyOnFinished
end

function HS:getRichTextEnabled(): boolean
	return self._.RichText
end

function HS:getHintXAlignment(): number
	return self.HintXAlignment
end

function HS:getTheme(): ModuleScript
	return self.HintTheme
end

function HS:getEligibleToBeCancelled(): boolean 
	return self.EligibleToBeCancelled
end

function HS:getHintSize(): Vector2
	return self._.AbsoluteSize
end

function HS:getLabelPadding(): number
	return self._.ExtraPadding.PaddingLeft, self._.ExtraPadding.PaddingRight
end

---------- Broadcast Methods ----------

function HS:broadcastHintToClient(yieldThread : boolean)
	yieldThread = yieldThread or false
	local label = self._
	local EligibleToBeCancelled = self.EligibleToBeCancelled
	
	EligibleToBeCancelled = true
	
	setHintProperties(self)
	if yieldThread then
		self.Broadcasted:Fire()
		animateHint()
	else
		self.Broadcasted:Fire()
		task.spawn(function()
			animateHint(self)
		end)
	end
end

function HS:cancelBroadcast()
	local label = self._
	local broadcastCancelled = self.Cancelled
	
	self.BroadcastCancelled:Fire()
	cancelHint(self)
end

return HS

So there are a few things that can be done that could help.

In some of your if/else statements you’re running virtually the same code, so when you have a piece of code like this…

if type == "Fade" then
		if self.InfiniteTime == true then
			HS.HintAdding:Fire(label)
			self.BroadcastRecieved:Fire()
			TweenService:Create(label, TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {TextTransparency = self.LabelTransparency}):Play()
			TweenService:Create(label, TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {BackgroundTransparency = self.HintTransparency}):Play()
			TweenService:Create(label:WaitForChild("BorderUIStroke"), TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {Transparency = self.HintTransparency}):Play()
			TweenService:Create(label:WaitForChild("TextUIStroke"), TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {Transparency = self.LabelTransparency}):Play()
		else
			HS.HintAdding:Fire(label)
			self.BroadcastRecieved:Fire()
			TweenService:Create(label, TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {TextTransparency = self.LabelTransparency}):Play()
			TweenService:Create(label, TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {BackgroundTransparency = self.HintTransparency}):Play()
			TweenService:Create(label:WaitForChild("BorderUIStroke"), TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {Transparency = self.HintTransparency}):Play()
			TweenService:Create(label:WaitForChild("TextUIStroke"), TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {Transparency = self.LabelTransparency}):Play()
			task.wait(self.VisibleTime + self.TweenLength1)
			if not hintCancelled then
				HS.HintRemoving:Fire(label)
				TweenService:Create(label, TweenInfo.new(self.TweenLength2, self.EasingStyle2, self.EasingDirection2), {Transparency = 1}):Play()
				TweenService:Create(label:WaitForChild("BorderUIStroke"), TweenInfo.new(self.TweenLength2, self.EasingStyle2, self.EasingDirection2), {Transparency = 1}):Play()
				TweenService:Create(label:WaitForChild("TextUIStroke"), TweenInfo.new(self.TweenLength2, self.EasingStyle2, self.EasingDirection2), {Transparency = 1}):Play()
				task.wait(self.TweenLength2)
				label:Destroy()
			elseif hintCancelled then
				return
			end
		end
	elseif type == "None" then
		if self.InfiniteTime == true then
			HS.HintAdding:Fire(label)
			self.BroadcastRecieved:Fire()
			label.TextTransparency = self.LabelTransparency
			label.BackgroundTransparency = self.HintTransparency
			label:WaitForChild("BorderUIStroke").Transparency = self.HintTransparency
			label:WaitForChild("BorderUIStroke").Transparency = self.LabelTransparency
		else
			HS.HintAdding:Fire(label)
			self.BroadcastRecieved:Fire()
			label.TextTransparency = self.LabelTransparency
			label.BackgroundTransparency = self.HintTransparency
			label:WaitForChild("BorderUIStroke").Transparency = self.HintTransparency
			label:WaitForChild("BorderUIStroke").Transparency = self.LabelTransparency
			task.wait(self.VisibleTime)
			if not hintCancelled then
				HS.HintRemoving:Fire(label)
				label.Transparency = 1
				label:WaitForChild("BorderUIStroke").Transparency = 1
				label:WaitForChild("BorderUIStroke").Transparency = 1
				label:Destroy()
			elseif hintCancelled then
				return
			end
		end
	end
end

You could instead change it to something like this…

if type == "Fade" then
	HS.HintAdding:Fire(label)
	self.BroadcastRecieved:Fire()
	TweenService:Create(label, TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {TextTransparency = self.LabelTransparency}):Play()
	TweenService:Create(label, TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {BackgroundTransparency = self.HintTransparency}):Play()
	TweenService:Create(label:WaitForChild("BorderUIStroke"), TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {Transparency = self.HintTransparency}):Play()
	TweenService:Create(label:WaitForChild("TextUIStroke"), TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {Transparency = self.LabelTransparency}):Play()


	if self.InfiniteTime or hintCancelled then return end
	task.wait(self.VisibleTime + self.TweenLength1)
	HS.HintRemoving:Fire(label)
	TweenService:Create(label, TweenInfo.new(self.TweenLength2, self.EasingStyle2, self.EasingDirection2), {Transparency = 1}):Play()
	TweenService:Create(label:WaitForChild("BorderUIStroke"), TweenInfo.new(self.TweenLength2, self.EasingStyle2, self.EasingDirection2), {Transparency = 1}):Play()
	TweenService:Create(label:WaitForChild("TextUIStroke"), TweenInfo.new(self.TweenLength2, self.EasingStyle2, self.EasingDirection2), {Transparency = 1}):Play()
	task.wait(self.TweenLength2)
	label:Destroy() 
elseif type == "None" then
	HS.HintAdding:Fire(label)
	self.BroadcastRecieved:Fire()
	label.TextTransparency = self.LabelTransparency
	label.BackgroundTransparency = self.HintTransparency
	label:WaitForChild("BorderUIStroke").Transparency = self.HintTransparency
	label:WaitForChild("BorderUIStroke").Transparency = self.LabelTransparency

	if self.InfiniteTime or hintCancelled then return end
	task.wait(self.VisibleTime)

	HS.HintRemoving:Fire(label)
	label.Transparency = 1
	label:WaitForChild("BorderUIStroke").Transparency = 1
	label:WaitForChild("BorderUIStroke").Transparency = 1
	label:Destroy()
end 

it appeared that within the fade and none if statements, they both had a if statement that had checked if self.InfiniteTime was true, and had some details on what to do for both, but looking at the code the only real difference was if inf. time was false, and if hintCancelled was false, if either of these were falsethen the following code (in both fade and none) have a task.wait and some extra details to perform.

With the changes I put in here, we’re acknowledging that regardless of hintCancelled, and regardless of the InfiniteTime variable, we are going to do these first sets tweens (One note, is that if you’re tweening the same instance but different properties, you can specify all of the properties on one tween, you don’t need multiple tweens). From there, after we perform the first steps that we are going to do regardless of those two variables discussed, we will then place an if statement in which checks if either the InfiniteTime variable is true, or if hintCancelled is true, if either is true then it’s going to end the code, but if both are false, then it will proceed to finish the remainder of the code.

This method could allow you to clean up any other situations like this, that change allowed for about 20 lines of code to be reduced from 50.

Good luck!

Edit - Question regarding those tweens as well, are you basically setting their transparency back to original if the InfiniteTime and hintCancelled is false? If so there could be a little more that we can do to reduce that code!

3 Likes
-- TODO:

-- A module that creates hints with just a bit of customization and simple code.

---------- Variables ----------

local HS = { }
local DisallowedWhiteSpace = {"\n", "\r", "\t", "\v", "\f"}

--

local GuiService = game:GetService("GuiService")
local StarterGui = game:GetService("StarterGui")
local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
local TextService = game:GetService("TextService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

--

local DefaultThemeFolder = script:WaitForChild("DefaultTheme")
local ThemesFolder = script:WaitForChild("Themes")
local Assets = script:WaitForChild("Assets")
local Plugins = script:WaitForChild("Plugins")
local Signal = require(Plugins:FindFirstChild("Signal"))
local DefaultTheme = require(DefaultThemeFolder:WaitForChild("DefaultTheme"))
local HintsGui = Assets:FindFirstChild("Hints"):Clone()
local Player = Players.LocalPlayer
local PlayerGui = Player:WaitForChild("PlayerGui")

---------- Events & Properties ----------

local function argumentError(argument : string, functionName : string)
	argument = argument or "nil"
	functionName = functionName or "nil"
	error(string.format("The %s argument must be passed in the %s function.", argument, functionName))
end

local function invalidError(object : string, type : string)
	object = object or "nil"
	type = type or "nil"
	error(string.format("%s is not a valid %s.", object, type))
end

local function customError(msg : string, ...)
	error(string.format(msg, ...))
end

local function customError2(msg : string)
	error(msg)
end

local function onMenuOpenedConfig(isHintVisible : boolean)
	HintsGui.Enabled = isHintVisible
end

local function setHintProperties(self : any)
	if not self then
		argumentError("self", "setHintProperties")
	end
	
	self._.BackgroundColor3 = self.HintTheme.hintColor
	self._.UICorner.CornerRadius = self.HintTheme.hintCornerRadius
	self._.BorderUIStroke.Color = self.HintTheme.hintStrokeColor
	self._.BorderUIStroke.LineJoinMode = self.HintTheme.hintStrokeLineJoinMode
	self._.BorderUIStroke.Thickness = self.HintTheme.hintStrokeSize
	self._.TextColor3 = self.HintTheme.labelColor
	self._.TextUIStroke.Color = self.HintTheme.labelStrokeColor
	self._.TextUIStroke.LineJoinMode = self.HintTheme.labelStrokeLineJoinMode
	self._.TextUIStroke.Thickness = self.HintTheme.hintStrokeSize
	self._.Font = self.HintTheme.labelFont
	self._.ExtraPadding.PaddingLeft = self.HintTheme.labelPaddingLeft
	self._.ExtraPadding.PaddingRight = self.HintTheme.labelPaddingRight
	
	self.HintTransparency = self.HintTheme.hintTransparency
	self.LabelTransparency = self.HintTheme.labelTransparency
end

local function cancelHint(self : any)
	local type = self.AnimationType
	local label = self._
	
	if type == "Fade" then
		TweenService:Create(label, TweenInfo.new(self.TweenLength2, self.EasingStyle2, self.EasingDirection2), {Transparency = 1}):Play()
		TweenService:Create(label:WaitForChild("BorderUIStroke"), TweenInfo.new(self.TweenLength2, self.EasingStyle2, self.EasingDirection2), {Transparency = 1}):Play()
		TweenService:Create(label:WaitForChild("TextUIStroke"), TweenInfo.new(self.TweenLength2, self.EasingStyle2, self.EasingDirection2), {Transparency = 1}):Play()
			task.wait(self.TweenLength2)
			label:Destroy()
	elseif type == "None" then
		label.Transparency = 1
		label:WaitForChild("BorderUIStroke").Transparency = 1
		label:WaitForChild("BorderUIStroke").Transparency = 1
		label:Destroy()
	end
end

local function animateHint(self : any)
	local type = self.AnimationType
	local infiniteTime = self.InfiniteTime
	local label = self._
	label.Visible = true
	local hintCancelled = self.Cancelled
	if not self then
		argumentError("self", "animateHint")
	end
	if self.VisibleTime <= 1 then
		error("Max visible time cannot be 1 or under.")
	end
	
	if type == "Fade" then
		if self.InfiniteTime then
			HS.HintAdding:Fire(label)
			self.BroadcastRecieved:Fire()
			TweenService:Create(label, TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {TextTransparency = self.LabelTransparency}):Play()
			TweenService:Create(label, TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {BackgroundTransparency = self.HintTransparency}):Play()
			TweenService:Create(label:WaitForChild("BorderUIStroke"), TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {Transparency = self.HintTransparency}):Play()
			TweenService:Create(label:WaitForChild("TextUIStroke"), TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {Transparency = self.LabelTransparency}):Play()
		else
			HS.HintAdding:Fire(label)
			self.BroadcastRecieved:Fire()
			TweenService:Create(label, TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {TextTransparency = self.LabelTransparency}):Play()
			TweenService:Create(label, TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {BackgroundTransparency = self.HintTransparency}):Play()
			TweenService:Create(label:WaitForChild("BorderUIStroke"), TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {Transparency = self.HintTransparency}):Play()
			TweenService:Create(label:WaitForChild("TextUIStroke"), TweenInfo.new(self.TweenLength1, self.EasingStyle1, self.EasingDirection1), {Transparency = self.LabelTransparency}):Play()
			task.wait(self.VisibleTime + self.TweenLength1)
			if not hintCancelled then
				HS.HintRemoving:Fire(label)
				TweenService:Create(label, TweenInfo.new(self.TweenLength2, self.EasingStyle2, self.EasingDirection2), {Transparency = 1}):Play()
				TweenService:Create(label:WaitForChild("BorderUIStroke"), TweenInfo.new(self.TweenLength2, self.EasingStyle2, self.EasingDirection2), {Transparency = 1}):Play()
				TweenService:Create(label:WaitForChild("TextUIStroke"), TweenInfo.new(self.TweenLength2, self.EasingStyle2, self.EasingDirection2), {Transparency = 1}):Play()
				task.wait(self.TweenLength2)
				label:Destroy()
			elseif hintCancelled then
				return
			end
		end
	elseif type == "None" then
		if self.InfiniteTime then
			HS.HintAdding:Fire(label)
			self.BroadcastRecieved:Fire()
			label.TextTransparency = self.LabelTransparency
			label.BackgroundTransparency = self.HintTransparency
			label:WaitForChild("BorderUIStroke").Transparency = self.HintTransparency
			label:WaitForChild("BorderUIStroke").Transparency = self.LabelTransparency
		else
			HS.HintAdding:Fire(label)
			self.BroadcastRecieved:Fire()
			label.TextTransparency = self.LabelTransparency
			label.BackgroundTransparency = self.HintTransparency
			label:WaitForChild("BorderUIStroke").Transparency = self.HintTransparency
			label:WaitForChild("BorderUIStroke").Transparency = self.LabelTransparency
			task.wait(self.VisibleTime)
			if not hintCancelled then
				HS.HintRemoving:Fire(label)
				label.Transparency = 1
				label:WaitForChild("BorderUIStroke").Transparency = 1
				label:WaitForChild("BorderUIStroke").Transparency = 1
				label:Destroy()
			elseif hintCancelled then
				return
			end
		end
	end
end

HintsGui.Parent = PlayerGui
HintsGui.Archivable = false

--

HS.HintAdding = Signal.new()
HS.HintRemoving = Signal.new()

--

GuiService.MenuOpened:Connect(function()
	onMenuOpenedConfig(false)
end)

GuiService.MenuClosed:Connect(function()
	onMenuOpenedConfig(true)
end)

---------- Constructors ----------

function HS.new(xAlignment : "Left" | "Center" | "Right")
	local newClass = setmetatable({ }, {__index = HS})
	
	newClass._ = script.Assets:WaitForChild("HintMsg"):Clone()
	
	local HintsFrame = HintsGui.HintsFrame
		newClass.HintXAlignment = 2
	if xAlignment == "Right" then
		StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.PlayerList, false)
		newClass._.Parent = HintsFrame.RightFrame
		newClass.HintXAlignment = 3
	elseif xAlignment == "Center" then
		newClass._.Parent = HintsFrame.CenterFrame
		newClass.HintXAlignment = 2
	elseif xAlignment == "Left" then
		newClass._.Parent = HintsFrame.LeftFrame
		newClass.HintXAlignment = 1
	end
	
	newClass.HintTheme = DefaultTheme
	newClass.VisibleTime = 12
	newClass.HintTransparency = newClass.HintTheme.hintTransparency
	newClass.LabelTransparency = newClass.HintTheme.labelTransparency
	newClass.EasingDirection1 = Enum.EasingDirection.In
	newClass.EasingDirection2 = Enum.EasingDirection.Out
	newClass.EasingStyle1 = Enum.EasingStyle.Quad
	newClass.EasingStyle2 = Enum.EasingStyle.Quad
	newClass.TweenLength1 = 1
	newClass.TweenLength2 = 1
	newClass.Cancelled = false
	newClass.BroadcastCancelled = Signal.new()
	newClass.BroadcastRecieved = Signal.new()
	newClass.Broadcasted = Signal.new()
	newClass.InfiniteTime = false
	newClass.AnimationType = "Fade"
	newClass.EligibleToBeCancelled = false
	
	return newClass
end

---------- Setting Methods ----------

function HS:setLabel(text : string)
	text = text or ""
	for k,v in ipairs(DisallowedWhiteSpace) do
		if string.find(text, v) then
			customError2("Whitespaces are not allowed.")
		end
	end
	local label = self._

	label.Text = text
end

function HS:setVisibleTime(isInfinite : boolean, time : number)
	time = time or 12
	isInfinite = isInfinite or false
	local label = self._
	
	self.InfiniteTime = isInfinite
	self.VisibleTime = time
end

function HS:setRichText(enabled : boolean)
	enabled = enabled or false
	local label = self._
	
	label.RichText = enabled
end

function HS:setTweenLength(length1 : number, length2 : number)
	length1 = length1 or 1
	length2 = length2 or 1
	
	self.TweenLength1 = length1
	self.TweenLength2 = length2
end

function HS:setTweenDirection(direction1 : Enum.EasingDirection, direction2 : Enum.EasingDirection)
	direction1 = direction1 or Enum.EasingDirection.In
	direction2 = direction2 or Enum.EasingDirection.Out
	
	self.EasingDirection1 = direction1
	self.EasingDirection2 = direction2
end

function HS:setTweenStyle(style1 : Enum.EasingStyle, style2 : Enum.EasingStyle)
	style1 = style1 or Enum.EasingStyle.Quad
	style2 = style2 or Enum.EasingStyle.Quad
	
	self.EasingStyle1 = style1
	self.EasingStyle2 = style2
end

function HS:setTheme(theme : string)
	if ThemesFolder:FindFirstChild(theme) and ThemesFolder:FindFirstChild(theme):IsA("ModuleScript") then
		self.HintTheme = require(ThemesFolder:FindFirstChild(theme))
	else
		invalidError(theme, "theme")
	end
end

function HS:setTweenType(type : "Fade" | "None")
	self.AnimationType = type
end

---------- Getting Methods ----------

function HS:getLabel(): string
	return self._.Text
end

function HS:getLabelFont(returnAsString : boolean): Enum.Font | string
	if returnAsString then
		return self._.Font.Name
	else
		return self._.Font
	end
end

function HS:getCurrentHints(): {TextLabel}
	local hintsTable = {}
	for k,v in pairs(HintsGui.HintsFrame:GetDescendants()) do
		if v:IsA("TextLabel") and v.Name == "HintMsg" then
			table.insert(hintsTable, v)
		end
	end
	return hintsTable
end

function HS:getVisibleTime(): number
	return self.VisibleTime
end

function HS:getTweenLength(type : "1" | "2"): number
	if type == "1" then
		return self.TweenLength1
	else
		return self.TweenLength2
	end
end

function HS:getTweenDirection(type : "1" | "2"): Enum.EasingDirection
	if type == "1" then
		return self.EasingDirection1
	else
		return self.EasingDirection2
	end
end

function HS:getTweenStyle(type : "1" | "2"): Enum.EasingStyle
	if type == "1" then
		return self.EasingStyle1
	else
		return self.EasingStyle2
	end
end

function HS:getTweenType(type : "1" | "2"): "Fade" | "None"
	return self.AnimationType
end

function HS:getDestroyOnFinished(): boolean
	return self.DestroyOnFinished
end

function HS:getRichTextEnabled(): boolean
	return self._.RichText
end

function HS:getHintXAlignment(): number
	return self.HintXAlignment
end

function HS:getTheme(): ModuleScript
	return self.HintTheme
end

function HS:getEligibleToBeCancelled(): boolean 
	return self.EligibleToBeCancelled
end

function HS:getHintSize(): Vector2
	return self._.AbsoluteSize
end

function HS:getLabelPadding(): number
	return self._.ExtraPadding.PaddingLeft, self._.ExtraPadding.PaddingRight
end

---------- Broadcast Methods ----------

function HS:broadcastHintToClient(yieldThread : boolean)
	yieldThread = yieldThread or false
	local label = self._
	local EligibleToBeCancelled = self.EligibleToBeCancelled
	
	EligibleToBeCancelled = true
	Nonsense text here.
	
	setHintProperties(self)
	if yieldThread then
		self.Broadcasted:Fire()
		animateHint()
	else
		self.Broadcasted:Fire()
		task.spawn(function()
			animateHint(self)
		end)
	end
end

function HS:cancelBroadcast()
	local label = self._
	local broadcastCancelled = self.Cancelled
	
	self.BroadcastCancelled:Fire()
	cancelHint(self)
end

return HS

Found glitch in HS.new.