Infinite dialog logs, notes, role notify and more...
Key Required

Infinite dialog logs, notes, role notify and more...

Ace Attorneyskeeplskeepl 1.7K views 389 executesUpdated Apr 27, 2026
Unrated
00
Lua Script•1492 lines (46003 chars)
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local StarterGui = game:GetService("StarterGui")
local LocalPlayer = Players.LocalPlayer
local PlayerGui = LocalPlayer:WaitForChild("PlayerGui")

local Dialogue = PlayerGui:WaitForChild("Dialogue")
local Frame = Dialogue:WaitForChild("Frame")
local SourceLabel = Frame:WaitForChild("Label")
local Holder = Frame:WaitForChild("Holder")

local RoleRemote = ReplicatedStorage:WaitForChild("Remotes"):WaitForChild("RoleRemote")

local screenGui = Instance.new("ScreenGui")
screenGui.Name = "DialogueLogger"
screenGui.ResetOnSpawn = false
screenGui.DisplayOrder = 999999
screenGui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling
screenGui.Parent = PlayerGui

local isMinimized = false
local savedPosition = nil
local savedSize = nil
local currentTab = "dialogue"
local notesContent = ""
local draggingEnabled = true

local paraCopyIndex = 1
local lastParaCopyTime = 0
local PARA_COPY_TIMEOUT = 2

local markerRestoreId = 0
local isShowingMarker = false

local notifyMode = false
local selectedRoles = {}
local isMonitoring = false

local function styleButton(button)
	button.BackgroundColor3 = Color3.fromRGB(212, 190, 152)
	button.TextColor3 = Color3.fromRGB(40, 35, 25)

	local success = pcall(function()
		button.FontFace = Font.new("rbxasset://fonts/families/GothamSSm.json", Enum.FontWeight.Medium, Enum.FontStyle.Normal)
	end)

	if not success then
		button.Font = Enum.Font.GothamMedium
	end

	local corner = Instance.new("UICorner")
	corner.CornerRadius = UDim.new(0, 8)
	corner.Parent = button

	local outerBorderFrame = Instance.new("Frame")
	outerBorderFrame.Name = "OuterBorderFrame"
	outerBorderFrame.Size = UDim2.new(1, 0, 1, 0)
	outerBorderFrame.BackgroundTransparency = 1
	outerBorderFrame.ZIndex = button.ZIndex - 1
	outerBorderFrame.Parent = button

	local outerCorner = Instance.new("UICorner")
	outerCorner.CornerRadius = UDim.new(0, 8)
	outerCorner.Parent = outerBorderFrame

	local outerStroke = Instance.new("UIStroke")
	outerStroke.Name = "OuterStroke"
	outerStroke.Color = Color3.fromRGB(0, 0, 0)
	outerStroke.Thickness = 3
	outerStroke.Parent = outerBorderFrame

	local innerBorderFrame = Instance.new("Frame")
	innerBorderFrame.Name = "InnerBorderFrame"
	innerBorderFrame.Size = UDim2.new(1, 0, 1, 0)
	innerBorderFrame.BackgroundTransparency = 1
	innerBorderFrame.ZIndex = button.ZIndex + 1
	innerBorderFrame.Parent = button

	local innerCorner = Instance.new("UICorner")
	innerCorner.CornerRadius = UDim.new(0, 8)
	innerCorner.Parent = innerBorderFrame

	local innerStroke = Instance.new("UIStroke")
	innerStroke.Name = "InnerStroke"
	innerStroke.Color = Color3.fromRGB(144, 132, 78)
	innerStroke.Thickness = 1.5
	innerStroke.Parent = innerBorderFrame
end

local function styleTabButton(button)
	button.BackgroundColor3 = Color3.fromRGB(113, 96, 66)
	button.TextColor3 = Color3.fromRGB(212, 190, 152)
	button.TextStrokeColor3 = Color3.fromRGB(0, 0, 0)
	button.TextStrokeTransparency = 0

	local success = pcall(function()
		button.FontFace = Font.new("rbxasset://fonts/families/Merriweather.json", Enum.FontWeight.Medium, Enum.FontStyle.Normal)
	end)

	if not success then
		button.Font = Enum.Font.GothamMedium
	end

	local corner = Instance.new("UICorner")
	corner.CornerRadius = UDim.new(0, 8)
	corner.Parent = button

	local borderFrame = Instance.new("Frame")
	borderFrame.Name = "BorderFrame"
	borderFrame.Size = UDim2.new(1, 0, 1, 0)
	borderFrame.BackgroundTransparency = 1
	borderFrame.ZIndex = button.ZIndex + 1
	borderFrame.Parent = button

	local borderCorner = Instance.new("UICorner")
	borderCorner.CornerRadius = UDim.new(0, 8)
	borderCorner.Parent = borderFrame

	local stroke = Instance.new("UIStroke")
	stroke.Color = Color3.fromRGB(144, 132, 78)
	stroke.Thickness = 1.678
	stroke.Parent = borderFrame
end

local mainFrame = Instance.new("Frame")
mainFrame.Name = "MainFrame"
mainFrame.Size = UDim2.new(0, 320, 0, 220)
mainFrame.Position = UDim2.new(0, 20, 0.5, -110)
mainFrame.BackgroundColor3 = Color3.fromRGB(10, 34, 42)
mainFrame.BackgroundTransparency = 0.1
mainFrame.BorderSizePixel = 0
mainFrame.Active = true
mainFrame.Parent = screenGui

local corner = Instance.new("UICorner")
corner.CornerRadius = UDim.new(0, 8)
corner.Parent = mainFrame

local mainFrameStroke = Instance.new("UIStroke")
mainFrameStroke.Color = Color3.fromRGB(144, 132, 78)
mainFrameStroke.Thickness = 1.678
mainFrameStroke.Parent = mainFrame

local miniButton = Instance.new("ImageButton")
miniButton.Name = "MiniButton"
miniButton.Size = UDim2.new(0, 50, 0, 50)
miniButton.BackgroundColor3 = Color3.fromRGB(10, 34, 42)
miniButton.Image = "rbxassetid://18102124902"
miniButton.ImageColor3 = Color3.fromRGB(255, 255, 255)
miniButton.ScaleType = Enum.ScaleType.Fit
miniButton.Visible = false
miniButton.Active = true
miniButton.ZIndex = 10
miniButton.Parent = screenGui

local miniCorner = Instance.new("UICorner")
miniCorner.CornerRadius = UDim.new(0.5, 0)
miniCorner.Parent = miniButton

local miniOuterBorderFrame = Instance.new("Frame")
miniOuterBorderFrame.Name = "OuterBorderFrame"
miniOuterBorderFrame.Size = UDim2.new(1, 0, 1, 0)
miniOuterBorderFrame.BackgroundTransparency = 1
miniOuterBorderFrame.ZIndex = miniButton.ZIndex - 1
miniOuterBorderFrame.Parent = miniButton

local miniOuterBorderCorner = Instance.new("UICorner")
miniOuterBorderCorner.CornerRadius = UDim.new(0.5, 0)
miniOuterBorderCorner.Parent = miniOuterBorderFrame

local miniOuterStroke = Instance.new("UIStroke")
miniOuterStroke.Color = Color3.fromRGB(0, 0, 0)
miniOuterStroke.Thickness = 3
miniOuterStroke.Parent = miniOuterBorderFrame

local miniInnerFrame = Instance.new("Frame")
miniInnerFrame.Size = UDim2.new(1, 0, 1, 0)
miniInnerFrame.BackgroundTransparency = 1
miniInnerFrame.ZIndex = miniButton.ZIndex + 1
miniInnerFrame.Parent = miniButton

local miniInnerCorner = Instance.new("UICorner")
miniInnerCorner.CornerRadius = UDim.new(0.5, 0)
miniInnerCorner.Parent = miniInnerFrame

local miniInnerStroke = Instance.new("UIStroke")
miniInnerStroke.Color = Color3.fromRGB(144, 132, 78)
miniInnerStroke.Thickness = 1.5
miniInnerStroke.Parent = miniInnerFrame

local titleBar = Instance.new("Frame")
titleBar.Name = "TitleBar"
titleBar.Size = UDim2.new(1, 0, 0, 28)
titleBar.BackgroundColor3 = Color3.fromRGB(8, 28, 35)
titleBar.BackgroundTransparency = 0.3
titleBar.BorderSizePixel = 0
titleBar.ZIndex = 1
titleBar.Parent = mainFrame

local titleBarCorner = Instance.new("UICorner")
titleBarCorner.CornerRadius = UDim.new(0, 8)
titleBarCorner.Parent = titleBar

local tabsContainer = Instance.new("Frame")
tabsContainer.Name = "TabsContainer"
tabsContainer.Size = UDim2.new(1, -76, 1, 0)
tabsContainer.Position = UDim2.new(0, 6, 0, 0)
tabsContainer.BackgroundTransparency = 1
tabsContainer.Parent = titleBar

local tabLayout = Instance.new("UIListLayout")
tabLayout.FillDirection = Enum.FillDirection.Horizontal
tabLayout.HorizontalAlignment = Enum.HorizontalAlignment.Left
tabLayout.VerticalAlignment = Enum.VerticalAlignment.Center
tabLayout.Padding = UDim.new(0, 6)
tabLayout.Parent = tabsContainer

local dialogueTab = Instance.new("TextButton")
dialogueTab.Name = "DialogueTab"
dialogueTab.Size = UDim2.new(0, 60, 0, 18)
dialogueTab.Text = "Dialogue"
dialogueTab.AutoButtonColor = false
dialogueTab.Parent = tabsContainer
styleTabButton(dialogueTab)

local notesTab = Instance.new("TextButton")
notesTab.Name = "NotesTab"
notesTab.Size = UDim2.new(0, 45, 0, 18)
notesTab.Text = "Notes"
notesTab.AutoButtonColor = false
notesTab.Parent = tabsContainer
styleTabButton(notesTab)

local rolesTab = Instance.new("TextButton")
rolesTab.Name = "RolesTab"
rolesTab.Size = UDim2.new(0, 45, 0, 18)
rolesTab.Text = "Roles"
rolesTab.AutoButtonColor = false
rolesTab.Parent = tabsContainer
styleTabButton(rolesTab)

local dragToggleBtn = Instance.new("ImageButton")
dragToggleBtn.Name = "DragToggleBtn"
dragToggleBtn.Size = UDim2.new(0, 18, 0, 18)
dragToggleBtn.Position = UDim2.new(1, -48, 0, 5)
dragToggleBtn.BackgroundColor3 = Color3.fromRGB(113, 96, 66)
dragToggleBtn.Image = "rbxassetid://4830959937"
dragToggleBtn.ImageColor3 = Color3.fromRGB(0, 255, 100)
dragToggleBtn.ScaleType = Enum.ScaleType.Fit
dragToggleBtn.AutoButtonColor = true
dragToggleBtn.ZIndex = 5
dragToggleBtn.Parent = mainFrame

local dragToggleCorner = Instance.new("UICorner")
dragToggleCorner.CornerRadius = UDim.new(0, 4)
dragToggleCorner.Parent = dragToggleBtn

local dragToggleBorder = Instance.new("UIStroke")
dragToggleBorder.Color = Color3.fromRGB(144, 132, 78)
dragToggleBorder.Thickness = 1.5
dragToggleBorder.Parent = dragToggleBtn

local minimizeBtn = Instance.new("TextButton")
minimizeBtn.Name = "MinimizeBtn"
minimizeBtn.Size = UDim2.new(0, 18, 0, 18)
minimizeBtn.Position = UDim2.new(1, -26, 0, 5)
minimizeBtn.Text = "−"
minimizeBtn.TextSize = 14
minimizeBtn.ZIndex = 5
minimizeBtn.Parent = mainFrame
styleTabButton(minimizeBtn)

local dialogueContainer = Instance.new("Frame")
dialogueContainer.Name = "DialogueContainer"
dialogueContainer.Size = UDim2.new(1, 0, 1, -68)
dialogueContainer.Position = UDim2.new(0, 0, 0, 30)
dialogueContainer.BackgroundTransparency = 1
dialogueContainer.Visible = true
dialogueContainer.ZIndex = 1
dialogueContainer.Parent = mainFrame

local dialogueScroll = Instance.new("ScrollingFrame")
dialogueScroll.Name = "ContentScroll"
dialogueScroll.Size = UDim2.new(1, -16, 1, -8)
dialogueScroll.Position = UDim2.new(0, 8, 0, 4)
dialogueScroll.BackgroundColor3 = Color3.fromRGB(212, 190, 152)
dialogueScroll.BackgroundTransparency = 0
dialogueScroll.BorderSizePixel = 0
dialogueScroll.ScrollBarThickness = 6
dialogueScroll.ScrollingDirection = Enum.ScrollingDirection.Y
dialogueScroll.CanvasSize = UDim2.new(0, 0, 0, 0)
dialogueScroll.AutomaticCanvasSize = Enum.AutomaticSize.None
dialogueScroll.ZIndex = 1
dialogueScroll.ScrollingEnabled = true
dialogueScroll.ClipsDescendants = true
dialogueScroll.Active = true
dialogueScroll.Parent = dialogueContainer

local dialogueScrollCorner = Instance.new("UICorner")
dialogueScrollCorner.CornerRadius = UDim.new(0, 8)
dialogueScrollCorner.Parent = dialogueScroll

local dialogueScrollStroke = Instance.new("UIStroke")
dialogueScrollStroke.Color = Color3.fromRGB(144, 132, 78)
dialogueScrollStroke.Thickness = 1.678
dialogueScrollStroke.Parent = dialogueScroll

local contentContainer = Instance.new("Frame")
contentContainer.Name = "ContentContainer"
contentContainer.Size = UDim2.new(1, -8, 0, 0)
contentContainer.Position = UDim2.new(0, 4, 0, 4)
contentContainer.BackgroundTransparency = 1
contentContainer.Parent = dialogueScroll

local listLayout = Instance.new("UIListLayout")
listLayout.SortOrder = Enum.SortOrder.LayoutOrder
listLayout.Padding = UDim.new(0, 4)
listLayout.Parent = contentContainer

local pendingScrollToBottom = false
local BOTTOM_THRESHOLD = 5

listLayout:GetPropertyChangedSignal("AbsoluteContentSize"):Connect(function()
	local contentHeight = listLayout.AbsoluteContentSize.Y
	local newHeight = contentHeight + 8
	dialogueScroll.CanvasSize = UDim2.new(0, 0, 0, newHeight)
	contentContainer.Size = UDim2.new(1, -8, 0, contentHeight)
	
	if pendingScrollToBottom then
		pendingScrollToBottom = false
		task.defer(function()
			dialogueScroll.CanvasPosition = Vector2.new(0, newHeight)
		end)
	end
end)

local notesContainer = Instance.new("Frame")
notesContainer.Name = "NotesContainer"
notesContainer.Size = UDim2.new(1, 0, 1, -68)
notesContainer.Position = UDim2.new(0, 0, 0, 30)
notesContainer.BackgroundTransparency = 1
notesContainer.Visible = false
notesContainer.ZIndex = 1
notesContainer.Parent = mainFrame

local notesScroll = Instance.new("ScrollingFrame")
notesScroll.Name = "NotesScroll"
notesScroll.Size = UDim2.new(1, -16, 1, -8)
notesScroll.Position = UDim2.new(0, 8, 0, 4)
notesScroll.BackgroundColor3 = Color3.fromRGB(212, 190, 152)
notesScroll.BackgroundTransparency = 0
notesScroll.BorderSizePixel = 0
notesScroll.ScrollBarThickness = 6
notesScroll.ScrollingDirection = Enum.ScrollingDirection.Y
notesScroll.CanvasSize = UDim2.new(0, 0, 0, 0)
notesScroll.ZIndex = 1
notesScroll.ScrollingEnabled = true
notesScroll.ClipsDescendants = true
notesScroll.Parent = notesContainer

local notesScrollCorner = Instance.new("UICorner")
notesScrollCorner.CornerRadius = UDim.new(0, 8)
notesScrollCorner.Parent = notesScroll

local notesScrollStroke = Instance.new("UIStroke")
notesScrollStroke.Color = Color3.fromRGB(144, 132, 78)
notesScrollStroke.Thickness = 1.5
notesScrollStroke.Parent = notesScroll

local notesTextBox = Instance.new("TextBox")
notesTextBox.Name = "NotesInput"
notesTextBox.Size = UDim2.new(1, -8, 0, 50)
notesTextBox.Position = UDim2.new(0, 4, 0, 4)
notesTextBox.BackgroundTransparency = 1
notesTextBox.TextColor3 = Color3.fromRGB(50, 45, 35)
notesTextBox.Font = Enum.Font.Code
notesTextBox.TextSize = 12
notesTextBox.TextWrapped = true
notesTextBox.TextXAlignment = Enum.TextXAlignment.Left
notesTextBox.TextYAlignment = Enum.TextYAlignment.Top
notesTextBox.ClearTextOnFocus = false
notesTextBox.MultiLine = true
notesTextBox.Text = ""
notesTextBox.PlaceholderText = "Enter your notes here..."
notesTextBox.PlaceholderColor3 = Color3.fromRGB(120, 110, 90)
notesTextBox.TextTruncate = Enum.TextTruncate.None
notesTextBox.Parent = notesScroll

local isNotesFocused = false

local function updateNotesSizing()
	task.defer(function()
		local textBounds = notesTextBox.TextBounds
		local contentHeight = textBounds.Y + 20
		local viewportHeight = math.max(4, notesScroll.AbsoluteSize.Y - 8)
		
		if isNotesFocused then
			local targetHeight = math.max(50, contentHeight)
			notesTextBox.Size = UDim2.new(1, -8, 0, targetHeight)
		else
			notesTextBox.Size = UDim2.new(1, -8, 0, 9999)
		end
		
		local canvasHeight = math.max(viewportHeight, contentHeight + 12)
		notesScroll.CanvasSize = UDim2.new(0, 0, 0, canvasHeight)
	end)
end

notesTextBox:GetPropertyChangedSignal("Text"):Connect(function()
	if isNotesFocused then
		updateNotesSizing()
	end
end)

notesTextBox:GetPropertyChangedSignal("TextBounds"):Connect(function()
	if isNotesFocused then
		updateNotesSizing()
	end
end)

notesTextBox.Focused:Connect(function()
	isNotesFocused = true
	updateNotesSizing()
end)

notesTextBox.FocusLost:Connect(function()
	notesContent = notesTextBox.Text
	isNotesFocused = false
	updateNotesSizing()
	
	task.spawn(function()
		RunService.Heartbeat:Wait()
		RunService.Heartbeat:Wait()
		local maxScroll = math.max(0, notesScroll.CanvasSize.Y.Offset - notesScroll.AbsoluteSize.Y)
		notesScroll.CanvasPosition = Vector2.new(0, maxScroll)
	end)
end)

notesScroll:GetPropertyChangedSignal("AbsoluteSize"):Connect(updateNotesSizing)

local rolesContainer = Instance.new("Frame")
rolesContainer.Name = "RolesContainer"
rolesContainer.Size = UDim2.new(1, 0, 1, -68)
rolesContainer.Position = UDim2.new(0, 0, 0, 30)
rolesContainer.BackgroundTransparency = 1
rolesContainer.Visible = false
rolesContainer.ZIndex = 1
rolesContainer.Parent = mainFrame

local notifierPanel = Instance.new("Frame")
notifierPanel.Name = "NotifierPanel"
notifierPanel.Size = UDim2.new(1, -16, 0, 28)
notifierPanel.Position = UDim2.new(0, 8, 0, 0)
notifierPanel.BackgroundColor3 = Color3.fromRGB(12, 40, 50)
notifierPanel.BackgroundTransparency = 0.5
notifierPanel.BorderSizePixel = 0
notifierPanel.Visible = true
notifierPanel.ZIndex = 1
notifierPanel.Parent = rolesContainer

local notifierCorner = Instance.new("UICorner")
notifierCorner.CornerRadius = UDim.new(0, 8)
notifierCorner.Parent = notifierPanel

local notifierLayout = Instance.new("UIListLayout")
notifierLayout.FillDirection = Enum.FillDirection.Horizontal
notifierLayout.HorizontalAlignment = Enum.HorizontalAlignment.Center
notifierLayout.VerticalAlignment = Enum.VerticalAlignment.Center
notifierLayout.Padding = UDim.new(0, 6)
notifierLayout.Parent = notifierPanel

local selectNotifyBtn = Instance.new("TextButton")
selectNotifyBtn.Name = "SelectNotifyBtn"
selectNotifyBtn.Size = UDim2.new(0, 100, 0, 20)
selectNotifyBtn.Text = "Select to Notify"
selectNotifyBtn.AutoButtonColor = true
selectNotifyBtn.Parent = notifierPanel
styleButton(selectNotifyBtn)

local doneBtn = Instance.new("TextButton")
doneBtn.Name = "DoneBtn"
doneBtn.Size = UDim2.new(0, 50, 0, 20)
doneBtn.Text = "Done"
doneBtn.AutoButtonColor = false
doneBtn.Parent = notifierPanel
styleButton(doneBtn)

local rolesScroll = Instance.new("ScrollingFrame")
rolesScroll.Name = "RolesScroll"
rolesScroll.Size = UDim2.new(1, -16, 1, -8)
rolesScroll.Position = UDim2.new(0, 8, 0, 32)
rolesScroll.BackgroundColor3 = Color3.fromRGB(212, 190, 152)
rolesScroll.BackgroundTransparency = 0
rolesScroll.BorderSizePixel = 0
rolesScroll.ScrollBarThickness = 4
rolesScroll.ScrollingDirection = Enum.ScrollingDirection.Y
rolesScroll.CanvasSize = UDim2.new(0, 0, 0, 0)
rolesScroll.ZIndex = 1
rolesScroll.Parent = rolesContainer

local rolesScrollCorner = Instance.new("UICorner")
rolesScrollCorner.CornerRadius = UDim.new(0, 8)
rolesScrollCorner.Parent = rolesScroll

local rolesScrollStroke = Instance.new("UIStroke")
rolesScrollStroke.Color = Color3.fromRGB(144, 132, 78)
rolesScrollStroke.Thickness = 1.678
rolesScrollStroke.Parent = rolesScroll

local rolesGrid = Instance.new("Frame")
rolesGrid.Name = "RolesGrid"
rolesGrid.Size = UDim2.new(1, -12, 0, 0)
rolesGrid.Position = UDim2.new(0, 6, 0, 6)
rolesGrid.BackgroundTransparency = 1
rolesGrid.AutomaticSize = Enum.AutomaticSize.Y
rolesGrid.Parent = rolesScroll

local gridLayout = Instance.new("UIGridLayout")
gridLayout.CellSize = UDim2.new(0.5, -10, 0, 20)
gridLayout.CellPadding = UDim2.new(0, 12, 0, 12)
gridLayout.HorizontalAlignment = Enum.HorizontalAlignment.Center
gridLayout.VerticalAlignment = Enum.VerticalAlignment.Top
gridLayout.Parent = rolesGrid

gridLayout:GetPropertyChangedSignal("AbsoluteContentSize"):Connect(function()
	rolesScroll.CanvasSize = UDim2.new(0, 0, 0, gridLayout.AbsoluteContentSize.Y + 12)
end)

local ROLES = {
	{name = "Judge", display = "Judge"},
	{name = "Bailiff", display = "Bailiff"},
	{name = "Prosecutor", display = "Prosecutor"},
	{name = "Defense Attorney", display = "Defense Attorney"},
	{name = "Prosecutor Assistant", display = "Pros. Assistant"},
	{name = "Defense Assistant", display = "Def. Assistant"},
	{name = "Defendant", display = "Defendant"},
	{name = "Detective", display = "Detective"},
	{name = "Witness", display = "Witness"},
	{name = "Gallery", display = "Gallery"}
}

local roleButtons = {}

local function updateRoleButtons()
	local occupiedRoles = {}
	for _, player in ipairs(Players:GetPlayers()) do
		local playerRole = player:GetAttribute("Role")
		if playerRole then occupiedRoles[playerRole] = true end
	end

	for roleName, data in pairs(roleButtons) do
		local isOccupied = occupiedRoles[roleName] == true
		data.occupied = isOccupied

		if isMonitoring and selectedRoles[roleName] ~= nil then
			local wasInitiallyOccupied = selectedRoles[roleName]
			
			if wasInitiallyOccupied and not isOccupied then
				pcall(function()
					StarterGui:SetCore("SendNotification", {
						Title = "Role Available!",
						Text = data.displayName .. " is now unoccupied!",
						Duration = 5
					})
				end)
				selectedRoles[roleName] = nil
				if not next(selectedRoles) then isMonitoring = false end
				if data.innerStroke then
					data.innerStroke.Color = Color3.fromRGB(144, 132, 78)
				end
				task.delay(0.1, updateRoleButtons)
			elseif not wasInitiallyOccupied and isOccupied then
				pcall(function()
					StarterGui:SetCore("SendNotification", {
						Title = "Role Occupied!",
						Text = "Someone joined " .. data.displayName .. "!",
						Duration = 5
					})
				end)
				selectedRoles[roleName] = nil
				if not next(selectedRoles) then isMonitoring = false end
				if data.innerStroke then
					data.innerStroke.Color = Color3.fromRGB(144, 132, 78)
				end
				task.delay(0.1, updateRoleButtons)
			else
				if wasInitiallyOccupied then
					data.button.BackgroundColor3 = Color3.fromRGB(180, 160, 120)
					data.button.Text = data.displayName .. " (Waiting for free)"
				else
					data.button.BackgroundColor3 = Color3.fromRGB(180, 160, 120)
					data.button.Text = data.displayName .. " (Waiting for occupant)"
				end
			end
		else
			if notifyMode then
				if data.selected then
					data.button.BackgroundColor3 = Color3.fromRGB(200, 180, 140)
					data.button.Text = data.displayName .. " (Waiting)"
					if data.innerStroke then
						data.innerStroke.Color = Color3.fromRGB(255, 215, 0)
					end
				else
					data.button.BackgroundColor3 = isOccupied and Color3.fromRGB(160, 150, 130) or Color3.fromRGB(212, 190, 152)
					data.button.Text = isOccupied and data.displayName .. " (Taken)" or data.displayName
					if data.innerStroke then
						data.innerStroke.Color = Color3.fromRGB(144, 132, 78)
					end
				end
			else
				data.button.BackgroundColor3 = isOccupied and Color3.fromRGB(160, 150, 130) or Color3.fromRGB(212, 190, 152)
				data.button.Text = isOccupied and data.displayName .. " (Taken)" or data.displayName
				if data.innerStroke then
					data.innerStroke.Color = Color3.fromRGB(144, 132, 78)
				end
			end
		end
	end
end

for i, roleData in ipairs(ROLES) do
	local btnContainer = Instance.new("Frame")
	btnContainer.Name = roleData.name .. "Container"
	btnContainer.Size = UDim2.new(1, 0, 1, 0)
	btnContainer.BackgroundTransparency = 1
	btnContainer.LayoutOrder = i
	btnContainer.Parent = rolesGrid

	local btn = Instance.new("TextButton")
	btn.Name = roleData.name .. "Btn"
	btn.Size = UDim2.new(1, 0, 1, 0)
	btn.Text = roleData.display
	btn.TextWrapped = true
	btn.AutoButtonColor = true
	btn.Parent = btnContainer

	styleButton(btn)
	btn.TextSize = 9

	local innerStroke = btn:FindFirstChild("InnerBorderFrame") and btn.InnerBorderFrame:FindFirstChild("InnerStroke")

	roleButtons[roleData.name] = {
		container = btnContainer,
		button = btn,
		innerStroke = innerStroke,
		displayName = roleData.display,
		roleName = roleData.name,
		selected = false,
		occupied = false
	}

	btn.MouseButton1Click:Connect(function()
		local data = roleButtons[roleData.name]
		if notifyMode then
			if data.selected then
				data.selected = false
				selectedRoles[roleData.name] = nil
				if data.innerStroke then
					data.innerStroke.Color = Color3.fromRGB(144, 132, 78)
				end
				btn.BackgroundColor3 = Color3.fromRGB(212, 190, 152)
				btn.Text = data.occupied and data.displayName .. " (Taken)" or data.displayName
			else
				data.selected = true
				selectedRoles[roleData.name] = true
				if data.innerStroke then
					data.innerStroke.Color = Color3.fromRGB(255, 215, 0)
				end
				btn.BackgroundColor3 = Color3.fromRGB(200, 180, 140)
				btn.Text = data.displayName .. " (Waiting)"
			end

			local hasSelections = next(selectedRoles) ~= nil
			doneBtn.BackgroundColor3 = hasSelections and Color3.fromRGB(180, 160, 120) or Color3.fromRGB(212, 190, 152)
		else
			if not data.occupied then
				local success, result = pcall(function()
					return RoleRemote:InvokeServer("RoleSelect", roleData.name)
				end)
				if success then
					btn.BackgroundColor3 = Color3.fromRGB(150, 200, 150)
					btn.Text = "Selected!"
					task.wait(0.5)
					updateRoleButtons()
				else
					btn.BackgroundColor3 = Color3.fromRGB(200, 100, 100)
					btn.Text = "Error"
					task.wait(1)
					updateRoleButtons()
				end
			end
		end
	end)
end

selectNotifyBtn.MouseButton1Click:Connect(function()
	if not notifyMode then
		notifyMode = true
		selectedRoles = {}
		isMonitoring = false
		selectNotifyBtn.BackgroundColor3 = Color3.fromRGB(200, 180, 140)
		selectNotifyBtn.Text = "Cancel"
		for _, data in pairs(roleButtons) do
			data.selected = false
			if data.innerStroke then
				data.innerStroke.Color = Color3.fromRGB(144, 132, 78)
			end
		end
		updateRoleButtons()
		pcall(function()
			StarterGui:SetCore("SendNotification", {
				Title = "Role Notifier",
				Text = "Click any roles to get notified when they're free or when someone joins.",
				Duration = 5
			})
		end)
	else
		notifyMode = false
		selectedRoles = {}
		selectNotifyBtn.BackgroundColor3 = Color3.fromRGB(212, 190, 152)
		selectNotifyBtn.Text = "Select to Notify"
		doneBtn.BackgroundColor3 = Color3.fromRGB(212, 190, 152)
		for _, data in pairs(roleButtons) do
			if data.innerStroke then
				data.innerStroke.Color = Color3.fromRGB(144, 132, 78)
			end
		end
		updateRoleButtons()
	end
end)

doneBtn.MouseButton1Click:Connect(function()
	if notifyMode and next(selectedRoles) then
		notifyMode = false
		isMonitoring = true
		selectNotifyBtn.BackgroundColor3 = Color3.fromRGB(212, 190, 152)
		selectNotifyBtn.Text = "Select to Notify"
		doneBtn.BackgroundColor3 = Color3.fromRGB(212, 190, 152)

		local selectedList = {}
		
		for roleName, data in pairs(roleButtons) do
			if data.innerStroke then
				data.innerStroke.Color = Color3.fromRGB(144, 132, 78)
			end

			if data.selected then
				selectedRoles[roleName] = data.occupied
				table.insert(selectedList, data.displayName)
				
				data.button.BackgroundColor3 = Color3.fromRGB(180, 160, 120)
				if data.occupied then
					data.button.Text = data.displayName .. " (Waiting for free)"
				else
					data.button.Text = data.displayName .. " (Waiting for occupant)"
				end
			end
		end
		
		pcall(function()
			StarterGui:SetCore("SendNotification", {
				Title = "Monitoring Started",
				Text = "Watching for changes in: " .. table.concat(selectedList, ", "),
				Duration = 5
			})
		end)
		
		if not next(selectedRoles) then isMonitoring = false end
		updateRoleButtons()
	end
end)

local fullLog = ""
local entryCount = 0
local lastLoggedUsername = ""

local function copyToClipboard(text)
	if setclipboard then
		pcall(setclipboard, text)
		return true
	elseif syn and syn.write_clipboard then
		pcall(syn.write_clipboard, text)
		return true
	elseif toclipboard then
		pcall(toclipboard, text)
		return true
	end
	return false
end

local function createLogEntry(username, role, message)
	local currentCanvasHeight = dialogueScroll.CanvasSize.Y.Offset
	local currentScrollPos = dialogueScroll.CanvasPosition.Y
	local viewportHeight = dialogueScroll.AbsoluteSize.Y
	local isAtBottom = (currentScrollPos + viewportHeight) >= (currentCanvasHeight - BOTTOM_THRESHOLD)

	if isAtBottom then
		pendingScrollToBottom = true
	end

	entryCount = entryCount + 1

	local entryFrame = Instance.new("Frame")
	entryFrame.Name = "Entry_" .. entryCount
	entryFrame.Size = UDim2.new(1, 0, 0, 0)
	entryFrame.AutomaticSize = Enum.AutomaticSize.Y
	entryFrame.BackgroundColor3 = Color3.fromRGB(230, 220, 200)
	entryFrame.BackgroundTransparency = 0.2
	entryFrame.LayoutOrder = entryCount
	entryFrame.Active = true
	entryFrame.Parent = contentContainer

	local entryCorner = Instance.new("UICorner")
	entryCorner.CornerRadius = UDim.new(0, 8)
	entryCorner.Parent = entryFrame

	local header = Instance.new("TextLabel")
	header.Size = UDim2.new(1, -8, 0, 16)
	header.Position = UDim2.new(0, 4, 0, 3)
	header.BackgroundTransparency = 1
	header.TextColor3 = Color3.fromRGB(60, 50, 40)
	header.Font = Enum.Font.GothamBold
	header.TextSize = 10
	header.TextXAlignment = Enum.TextXAlignment.Left
	header.Text = string.format("[%s] (%s)", username or "Unknown", role or "Unknown")
	header.Parent = entryFrame

	local msgLabel = Instance.new("TextLabel")
	msgLabel.Name = "MessageLabel"
	msgLabel.Size = UDim2.new(1, -8, 0, 0)
	msgLabel.Position = UDim2.new(0, 4, 0, 19)
	msgLabel.BackgroundTransparency = 1
	msgLabel.TextColor3 = Color3.fromRGB(40, 35, 25)
	msgLabel.Font = Enum.Font.Code
	msgLabel.TextSize = 11
	msgLabel.TextWrapped = true
	msgLabel.TextXAlignment = Enum.TextXAlignment.Left
	msgLabel.TextYAlignment = Enum.TextYAlignment.Top
	msgLabel.AutomaticSize = Enum.AutomaticSize.Y
	msgLabel.Text = message or ""
	msgLabel.Parent = entryFrame

	local clickCount = 0
	local lastClickTime = 0
	local CLICK_THRESHOLD = 0.4
	local baseColor = entryFrame.BackgroundColor3

	entryFrame.InputBegan:Connect(function(input)
		if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
			local currentTime = tick()
			local timeSinceLastClick = currentTime - lastClickTime

			if timeSinceLastClick > CLICK_THRESHOLD then
				clickCount = 1
				baseColor = entryFrame.BackgroundColor3
			else
				clickCount = clickCount + 1
			end
			lastClickTime = currentTime

			if clickCount == 2 then
				local success = copyToClipboard(msgLabel.Text)
				local originalColor = baseColor

				if success then
					entryFrame.BackgroundColor3 = Color3.fromRGB(0, 200, 100)
				else
					entryFrame.BackgroundColor3 = Color3.fromRGB(200, 100, 100)
				end

				local feedbackLabel = Instance.new("TextLabel")
				feedbackLabel.Size = UDim2.new(0, 50, 0, 16)
				feedbackLabel.Position = UDim2.new(1, -55, 0, 2)
				feedbackLabel.BackgroundTransparency = 1
				feedbackLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
				feedbackLabel.Font = Enum.Font.GothamBold
				feedbackLabel.TextSize = 10
				feedbackLabel.Text = "Copied!"
				feedbackLabel.Parent = entryFrame

				task.delay(0.3, function()
					entryFrame.BackgroundColor3 = originalColor
					feedbackLabel:Destroy()
				end)
			end

			if clickCount == 3 then
				clickCount = 0

				local textToAdd = msgLabel.Text
				if #notesContent > 0 then
					notesContent = notesContent .. "\n\n" .. textToAdd
				else
					notesContent = textToAdd
				end

				if notesTextBox then
					notesTextBox.Text = notesContent
					if isNotesFocused then
						updateNotesSizing()
					else
						notesTextBox.Size = UDim2.new(1, -8, 0, 9999)
						updateNotesSizing()
					end
				end

				local originalColor = baseColor
				entryFrame.BackgroundColor3 = Color3.fromRGB(100, 150, 255)

				local feedbackLabel = Instance.new("TextLabel")
				feedbackLabel.Size = UDim2.new(0, 70, 0, 16)
				feedbackLabel.Position = UDim2.new(1, -75, 0, 2)
				feedbackLabel.BackgroundTransparency = 1
				feedbackLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
				feedbackLabel.Font = Enum.Font.GothamBold
				feedbackLabel.TextSize = 10
				feedbackLabel.Text = "To Notes!"
				feedbackLabel.Parent = entryFrame

				task.delay(0.3, function()
					entryFrame.BackgroundColor3 = originalColor
					feedbackLabel:Destroy()
				end)
			end
		end
	end)
end

local function isValidUsername(name)
	return name and name ~= "" and name ~= "Unknown"
end

local function captureDialogue(newContent)
	if not newContent or #newContent == 0 then return end
	
	RunService.Heartbeat:Wait()
	
	if SourceLabel.ContentText ~= newContent then
		return
	end

	local currentUsername = "Unknown"
	local currentRole = "Unknown"

	local usernameLabel = Holder:FindFirstChild("Username")
	local roleLabel = Holder:FindFirstChild("Role")

	if usernameLabel and usernameLabel:IsA("TextLabel") then
		currentUsername = usernameLabel.Text
	end
	if roleLabel and roleLabel:IsA("TextLabel") then
		currentRole = roleLabel.Text
	end

	if not isValidUsername(currentUsername) then
		local startTime = tick()
		repeat
			RunService.Heartbeat:Wait()
			if usernameLabel then
				currentUsername = usernameLabel.Text
			end
			if roleLabel then
				currentRole = roleLabel.Text
			end
		until isValidUsername(currentUsername) or (tick() - startTime) > 0.5
	end

	if currentUsername == lastLoggedUsername and lastLoggedUsername ~= "" then
		local startTime = tick()
		repeat
			RunService.Heartbeat:Wait()
			if usernameLabel then
				currentUsername = usernameLabel.Text
			end
			if roleLabel then
				currentRole = roleLabel.Text
			end
		until currentUsername ~= lastLoggedUsername or (tick() - startTime) > 0.5
	end

	lastLoggedUsername = currentUsername

	local logLine = string.format("[%s] (%s): %s", currentUsername, currentRole, newContent)
	if #fullLog == 0 then
		fullLog = logLine
	else
		fullLog = fullLog .. "\n\n" .. logLine
	end

	createLogEntry(currentUsername, currentRole, newContent)
end

SourceLabel:GetPropertyChangedSignal("ContentText"):Connect(function()
	local content = SourceLabel.ContentText
	if content and #content > 0 then
		task.spawn(function()
			captureDialogue(content)
		end)
	end
end)

local copyButton = Instance.new("TextButton")
copyButton.Name = "CopyAllBtn"
copyButton.Size = UDim2.new(0.6, -12, 0, 24)
copyButton.Position = UDim2.new(0, 8, 1, -32)
copyButton.Text = "Copy All"
copyButton.ZIndex = 2
copyButton.Parent = mainFrame
styleButton(copyButton)

local clearBtn = Instance.new("TextButton")
clearBtn.Name = "ClearBtn"
clearBtn.Size = UDim2.new(0.4, -16, 0, 24)
clearBtn.Position = UDim2.new(0.6, 8, 1, -32)
clearBtn.Text = "Clear"
clearBtn.ZIndex = 2
clearBtn.Parent = mainFrame
styleButton(clearBtn)

copyButton.MouseButton1Click:Connect(function()
	if currentTab == "dialogue" then
		if #fullLog == 0 then
			copyButton.Text = "No text!"
			copyButton.BackgroundColor3 = Color3.fromRGB(200, 100, 100)
			task.wait(1)
			copyButton.Text = "Copy All"
			copyButton.BackgroundColor3 = Color3.fromRGB(212, 190, 152)
			return
		end

		local copied = copyToClipboard(fullLog)

		if copied then
			copyButton.Text = "Copied!"
			copyButton.BackgroundColor3 = Color3.fromRGB(150, 200, 150)
		else
			copyButton.Text = "Failed"
			copyButton.BackgroundColor3 = Color3.fromRGB(200, 100, 100)
		end

		task.wait(1.5)
		copyButton.Text = "Copy All"
		copyButton.BackgroundColor3 = Color3.fromRGB(212, 190, 152)

	elseif currentTab == "notes" then
		local notesToCopy = notesTextBox.Text
		if #notesToCopy == 0 then
			copyButton.Text = "Empty!"
			copyButton.BackgroundColor3 = Color3.fromRGB(200, 100, 100)
			task.wait(1)
			copyButton.Text = "Copy All"
			copyButton.BackgroundColor3 = Color3.fromRGB(212, 190, 152)
			return
		end

		notesContent = notesToCopy
		local copied = copyToClipboard(notesToCopy)

		if copied then
			copyButton.Text = "Copied!"
			copyButton.BackgroundColor3 = Color3.fromRGB(150, 200, 150)
		else
			copyButton.Text = "Failed"
			copyButton.BackgroundColor3 = Color3.fromRGB(200, 100, 100)
		end

		task.wait(1.5)
		copyButton.Text = "Copy Notes"
		copyButton.BackgroundColor3 = Color3.fromRGB(212, 190, 152)
	end
end)

clearBtn.MouseButton1Click:Connect(function()
	if currentTab == "dialogue" then
		fullLog = ""
		entryCount = 0
		lastLoggedUsername = ""

		for _, child in ipairs(contentContainer:GetChildren()) do
			if child:IsA("Frame") then
				child:Destroy()
			end
		end

		dialogueScroll.CanvasSize = UDim2.new(0, 0, 0, 0)
		dialogueScroll.CanvasPosition = Vector2.new(0, 0)
		contentContainer.Size = UDim2.new(1, -8, 0, 0)

	elseif currentTab == "notes" then
		local currentTime = tick()
		
		if currentTime - lastParaCopyTime > PARA_COPY_TIMEOUT then
			paraCopyIndex = 1
			isShowingMarker = false
			markerRestoreId = markerRestoreId + 1
		end
		
		if isShowingMarker then
			local currentText = notesTextBox.Text
			local cleanText = currentText:gsub("▶ ", ""):gsub(" ◀", "")
			notesTextBox.Text = cleanText
			isShowingMarker = false
			markerRestoreId = markerRestoreId + 1
		end
		
		local text = notesTextBox.Text
		
		local paragraphs = {}
		for _, para in ipairs(string.split(text, "\n\n")) do
			if para:match("%S") then
				table.insert(paragraphs, para)
			end
		end
		
		if #paragraphs == 0 then
			clearBtn.Text = "Empty!"
			clearBtn.BackgroundColor3 = Color3.fromRGB(200, 100, 100)
			task.wait(0.5)
			clearBtn.Text = "Copy Para"
			clearBtn.BackgroundColor3 = Color3.fromRGB(212, 190, 152)
			return
		end
		
		if paraCopyIndex > #paragraphs then
			paraCopyIndex = 1
		end
		
		local paraText = paragraphs[paraCopyIndex]
		
		local copied = copyToClipboard(paraText)
		
		if copied then
			markerRestoreId = markerRestoreId + 1
			local myRestoreId = markerRestoreId
			isShowingMarker = true
			
			local prefix = "▶ "
			local suffix = " ◀"
			
			local modifiedText = ""
			for i, para in ipairs(paragraphs) do
				if i == paraCopyIndex then
					modifiedText = modifiedText .. prefix .. para .. suffix
				else
					modifiedText = modifiedText .. para
				end
				
				if i < #paragraphs then
					modifiedText = modifiedText .. "\n\n"
				end
			end
			
			notesTextBox.Text = modifiedText
			
			task.defer(function()
				local fullHeight = notesTextBox.TextBounds.Y
				local viewportHeight = notesScroll.AbsoluteSize.Y
				
				if fullHeight > viewportHeight then
					local targetY = ((paraCopyIndex - 1) / #paragraphs) * fullHeight
					targetY = math.max(0, targetY - viewportHeight/2 + 25)
					notesScroll.CanvasPosition = Vector2.new(0, targetY)
				end
			end)
			
			clearBtn.Text = "Para #" .. paraCopyIndex .. "!"
			clearBtn.BackgroundColor3 = Color3.fromRGB(150, 200, 150)
			
			local thisClickTime = currentTime
			lastParaCopyTime = thisClickTime
			
			task.delay(0.3, function()
				if markerRestoreId == myRestoreId then
					notesTextBox.Text = text
					isShowingMarker = false
				end
			end)
			
			task.delay(PARA_COPY_TIMEOUT, function()
				if lastParaCopyTime == thisClickTime then
					paraCopyIndex = 1
					if currentTab == "notes" then
						clearBtn.Text = "Copy Para"
						clearBtn.BackgroundColor3 = Color3.fromRGB(212, 190, 152)
					end
				end
			end)
			
			paraCopyIndex = paraCopyIndex + 1
		else
			clearBtn.Text = "Failed"
			clearBtn.BackgroundColor3 = Color3.fromRGB(200, 100, 100)
			task.wait(0.5)
			clearBtn.Text = "Copy Para"
			clearBtn.BackgroundColor3 = Color3.fromRGB(212, 190, 152)
		end
	end
end)

local function setActiveTab(tab)
	currentTab = tab
	dialogueContainer.Visible = (tab == "dialogue")
	notesContainer.Visible = (tab == "notes")
	rolesContainer.Visible = (tab == "roles")
	
	dialogueTab.BackgroundColor3 = (tab == "dialogue") and Color3.fromRGB(140, 120, 80) or Color3.fromRGB(113, 96, 66)
	notesTab.BackgroundColor3 = (tab == "notes") and Color3.fromRGB(140, 120, 80) or Color3.fromRGB(113, 96, 66)
	rolesTab.BackgroundColor3 = (tab == "roles") and Color3.fromRGB(140, 120, 80) or Color3.fromRGB(113, 96, 66)
	
	copyButton.Visible = (tab ~= "roles")
	clearBtn.Visible = (tab ~= "roles")
	
	if tab == "dialogue" then
		clearBtn.Text = "Clear"
		clearBtn.BackgroundColor3 = Color3.fromRGB(212, 190, 152)
	elseif tab == "notes" then
		if tick() - lastParaCopyTime > PARA_COPY_TIMEOUT then
			paraCopyIndex = 1
		end
		clearBtn.Text = "Copy Para"
		clearBtn.BackgroundColor3 = Color3.fromRGB(212, 190, 152)
	end

	if tab == "notes" then
		notesTextBox.Text = notesContent
		if isNotesFocused then
			updateNotesSizing()
		else
			notesTextBox.Size = UDim2.new(1, -8, 0, 9999)
			updateNotesSizing()
		end
	elseif tab == "roles" then
		updateRoleButtons()
	end
end

dialogueTab.MouseButton1Click:Connect(function() setActiveTab("dialogue") end)
notesTab.MouseButton1Click:Connect(function() setActiveTab("notes") end)
rolesTab.MouseButton1Click:Connect(function() setActiveTab("roles") end)

local function applyMinimize()
	if isMinimized then return end
	isMinimized = true

	savedPosition = mainFrame.Position
	savedSize = mainFrame.Size

	miniButton.Position = savedPosition
	mainFrame.Visible = false
	miniButton.Visible = true
end

local function restoreFromMinimized()
	if not isMinimized then return end
	isMinimized = false

	if savedPosition then
		mainFrame.Position = savedPosition
	end
	if savedSize then
		mainFrame.Size = savedSize
	end

	miniButton.Visible = false
	mainFrame.Visible = true
end

minimizeBtn.MouseButton1Click:Connect(applyMinimize)
miniButton.MouseButton1Click:Connect(restoreFromMinimized)

dragToggleBtn.MouseButton1Click:Connect(function()
	draggingEnabled = not draggingEnabled
	
	if draggingEnabled then
		dragToggleBtn.ImageColor3 = Color3.fromRGB(0, 255, 100)
		dragToggleBtn.BackgroundColor3 = Color3.fromRGB(113, 96, 66)
	else
		dragToggleBtn.ImageColor3 = Color3.fromRGB(255, 50, 50)
		dragToggleBtn.BackgroundColor3 = Color3.fromRGB(80, 60, 50)
	end
end)

local dragObject = nil
local dragStartPos = nil
local frameStartPos = nil
local isActuallyDragging = false

titleBar.InputBegan:Connect(function(input)
	if not draggingEnabled then return end
	
	if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
		local mousePos = input.Position
		local barPos = titleBar.AbsolutePosition
		local barSize = titleBar.AbsoluteSize
		
		local safeZoneBottom = barPos.Y + (barSize.Y * 0.7)
		
		if mousePos.Y > safeZoneBottom then
			return
		end
		
		dragObject = mainFrame
		dragStartPos = input.Position
		frameStartPos = mainFrame.Position
		isActuallyDragging = false
	end
end)

miniButton.InputBegan:Connect(function(input)
	if not draggingEnabled then return end
	
	if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
		dragObject = miniButton
		dragStartPos = input.Position
		frameStartPos = miniButton.Position
		isActuallyDragging = false
	end
end)

UserInputService.InputChanged:Connect(function(input)
	if dragObject and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then
		if not UserInputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton1) then
			dragObject = nil
			isActuallyDragging = false
			return
		end
		
		if dragObject == mainFrame then
			local mousePos = input.Position
			local barPos = titleBar.AbsolutePosition
			local barSize = titleBar.AbsoluteSize
			
			if mousePos.Y > barPos.Y + barSize.Y then
				dragObject = nil
				isActuallyDragging = false
				return
			end
		end
		
		local delta = input.Position - dragStartPos
		
		if not isActuallyDragging then
			if delta.Magnitude < 5 then
				return
			else
				isActuallyDragging = true
			end
		end
		
		dragObject.Position = UDim2.new(
			frameStartPos.X.Scale,
			frameStartPos.X.Offset + delta.X,
			frameStartPos.Y.Scale,
			frameStartPos.Y.Offset + delta.Y
		)
	end
end)

UserInputService.InputEnded:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
		dragObject = nil
		isActuallyDragging = false
	end
end)

local resizeHandle = Instance.new("ImageButton")
resizeHandle.Name = "ResizeHandle"
resizeHandle.Size = UDim2.new(0, 24, 0, 24)
resizeHandle.Position = UDim2.new(1, -28, 1, -28)
resizeHandle.BackgroundColor3 = Color3.fromRGB(212, 190, 152)
resizeHandle.BackgroundTransparency = 1
resizeHandle.Image = "rbxassetid://6153965696"
resizeHandle.ImageColor3 = Color3.fromRGB(40, 35, 25)
resizeHandle.ImageTransparency = 1
resizeHandle.ScaleType = Enum.ScaleType.Fit
resizeHandle.AutoButtonColor = false
resizeHandle.ZIndex = 10
resizeHandle.Parent = mainFrame

local resizeCorner = Instance.new("UICorner")
resizeCorner.CornerRadius = UDim.new(0, 8)
resizeCorner.Parent = resizeHandle

local resizeOuterStroke = Instance.new("UIStroke")
resizeOuterStroke.Color = Color3.fromRGB(0, 0, 0)
resizeOuterStroke.Thickness = 1.5
resizeOuterStroke.Transparency = 1
resizeOuterStroke.Parent = resizeHandle

local resizeInnerFrame = Instance.new("Frame")
resizeInnerFrame.Size = UDim2.new(1, 0, 1, 0)
resizeInnerFrame.BackgroundTransparency = 1
resizeInnerFrame.ZIndex = resizeHandle.ZIndex + 1
resizeInnerFrame.Parent = resizeHandle

local resizeInnerCorner = Instance.new("UICorner")
resizeInnerCorner.CornerRadius = UDim.new(0, 8)
resizeInnerCorner.Parent = resizeInnerFrame

local resizeInnerStroke = Instance.new("UIStroke")
resizeInnerStroke.Color = Color3.fromRGB(144, 132, 78)
resizeInnerStroke.Thickness = 1
resizeInnerStroke.Transparency = 1
resizeInnerStroke.Parent = resizeInnerFrame

local isResizing = false
local resizeStartPos = nil
local resizeStartSize = nil

resizeHandle.MouseEnter:Connect(function()
	resizeHandle.BackgroundTransparency = 0.3
	resizeHandle.ImageTransparency = 0
	resizeOuterStroke.Transparency = 0
	resizeInnerStroke.Transparency = 0
end)

resizeHandle.MouseLeave:Connect(function()
	if not isResizing then
		resizeHandle.BackgroundTransparency = 1
		resizeHandle.ImageTransparency = 1
		resizeOuterStroke.Transparency = 1
		resizeInnerStroke.Transparency = 1
	end
end)

resizeHandle.InputBegan:Connect(function(input)
	if not draggingEnabled then return end
	
	if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
		isResizing = true
		resizeStartPos = input.Position
		resizeStartSize = mainFrame.AbsoluteSize
	end
end)

UserInputService.InputChanged:Connect(function(input)
	if isResizing and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) then
		local delta = input.Position - resizeStartPos
		local newWidth = math.max(250, resizeStartSize.X + delta.X)
		local newHeight = math.max(150, resizeStartSize.Y + delta.Y)
		mainFrame.Size = UDim2.new(0, newWidth, 0, newHeight)
	end
end)

UserInputService.InputEnded:Connect(function(input)
	if isResizing and (input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch) then
		isResizing = false
		if draggingEnabled then
			resizeHandle.BackgroundTransparency = 1
			resizeHandle.ImageTransparency = 1
			resizeOuterStroke.Transparency = 1
			resizeInnerStroke.Transparency = 1
		end
	end
end)

RunService.Heartbeat:Connect(function()
	if currentTab == "roles" or isMonitoring then updateRoleButtons() end
end)

Players.PlayerAdded:Connect(function()
	if currentTab == "roles" or isMonitoring then updateRoleButtons() end
end)

Players.PlayerRemoving:Connect(function()
	if currentTab == "roles" or isMonitoring then
		task.wait(0.1)
		updateRoleButtons()
	end
end)

miniButton.Position = UDim2.new(0, 20, 0.5, -25)

if SourceLabel.ContentText and #SourceLabel.ContentText > 0 then
	task.spawn(function()
		captureDialogue(SourceLabel.ContentText)
	end)
end

dialogueTab.BackgroundColor3 = Color3.fromRGB(140, 120, 80)
notesTab.BackgroundColor3 = Color3.fromRGB(113, 96, 66)
rolesTab.BackgroundColor3 = Color3.fromRGB(113, 96, 66)

copyButton.Visible = true
clearBtn.Visible = true

task.defer(function()
	updateRoleButtons()
	updateNotesSizing()
end)

Features & Information

Is this script necessary? No, but I felt like making one for this game so here it is. :p FEATURES: • Infinite Dialog Logs: Logs all visible dialog (not chat) to the script, it will log indefinitely so be sure to manually clear when it starts to lag • Copy Messages: You can copy everything (all dialog) by clicking the copy button, if you want to copy individual messages, simply double click on that dialog block in the script's UI • Notes: You can write notes in the script's UI without the need of an external notes app, if you want to quickly transfer a message to your notes, triple click on the dialog block in the dialog history tab and it will be in your notes. You can also copy all of your notes content or if you only want to copy a specific paragraph, click on the "copy para" button, if you press it while its green it will copy the next paragraph and so on • Role Switching: You can quickly switch between roles in the role selection tab (there's a bug where you won't get the role abilities of the role you switched to when you switch via this script, I'm not sure how to fix that yet) • Role Notify: Select the roles you want the script to monitor and it will tell you when that role is unoccupied (if it's occupied) or when that role is occupied (if it's already unoccupied) note that it will only notify you once • Other: You can resize the UI by dragging at the bottom right corner of the UI. You can also minimize the UI by clicking on the button at the top right corner of the UI. You can lock UI dragging and resizing by clicking on the lock button next to the minimize button (prevents you from accidentally dragging the UI)
#open source

Community Comments (0)

No comments yet for this script.