explore
key systems
new
docs
discord
search scripts
⌘K
explore
key systems
new
docs
discord
sign in
⌘↵
--
publishes from anywhere on this page
new paste
untitled.luau
empty
/ 512kb
open file
⌘O
explore
key systems
new
docs
sign in
fs-all-emotes-fe-all-exec-supported-copy.luau
1274 lines · 34kb
/ 512kb
open file
⌘O
--[[* *If you enjoy the script, please consider liking the post.* *It helps motivate me to release more open-source scripts* *and keep existing ones updated.* *MADE BY: [https://rscripts.net/@Yamis_Scripts]* *]] if not game:IsLoaded() then game.Loaded:Wait() end local StarterGui = game:GetService("StarterGui") local missing = {} if type(setclipboard) ~= "function" then table.insert(missing, "setclipboard") end if #missing > 0 then local executorName = "Unknown Executor" if type(identifyexecutor) == "function" then local ok, name = pcall(identifyexecutor) if ok and type(name) == "string" and name ~= "" then executorName = name end end local title = "[" .. executorName .. "]: Not Supported" local description = "Missing: " .. table.concat(missing, ", ") local notified = pcall(function() StarterGui:SetCore("SendNotification", { Title = title, Text = description, Duration = 8 }) end) if not notified then warn(title .. " - " .. description) end return end assert(game.PlaceId == 83645629621104, "This script targets Forsaken place 83645629621104") local function readAttribution() local encoded = string.reverse("f541ed9c6f187160a3e5bca5d24621775c91c7b0b82b4bd49d47b2552a4cd8009f5d595c513080b8cf86a0e615b5e3b513354f9ca63db1acd90fb28cef3469de3c584330df894114a8330c5e21c2998c349cbb4a1ee37eb2b5ab27fd76dc9d2b703b39998c1d71d2f4c77033f8c15be9f3280f39b609ecd2cdd7aac5") local length = #encoded / 2 assert(length == 124, "Attribution data missing") local bytes = table.create(length) local seed = (17 * 23 + 52) % 256 local fingerprint = 17 for index = 1, length do seed = (seed * 79 + 23) % 256 local offset = ((index - 1) * 17) % length * 2 + 1 local value = assert(tonumber(string.sub(encoded, offset, offset + 1), 16), "Invalid attribution data") local shifted = (value - (index * 29 + 51)) % 256 local rotation = (index * 3) % 8 local original = (bit32.rshift(shifted, rotation) + bit32.lshift(shifted, 8 - rotation)) % 256 local decoded = bit32.bxor(original, seed) bytes[index] = string.char(decoded) fingerprint = (fingerprint * 131 + decoded) % 2147483647 end assert(fingerprint == 1958912220, "Attribution data changed") local fields = string.split(table.concat(bytes), string.char(31)) assert(#fields == 7, "Attribution fields missing") return { credit = fields[1], url = fields[2], assets = fields[3], catalog = fields[4], screen = fields[5], overlay = fields[6], shutdown = fields[7], } end local attribution = readAttribution() local Players = game:GetService("Players") local ReplicatedStorage = game:GetService("ReplicatedStorage") local TextService = game:GetService("TextService") local UserInputService = game:GetService("UserInputService") local localPlayer = Players.LocalPlayer local playerGui = localPlayer:WaitForChild("PlayerGui", 8) local assets = ReplicatedStorage:WaitForChild(attribution.assets, 8) local emoteModules = assets and assets:WaitForChild(attribution.catalog, 8) assert(playerGui and emoteModules, "Missing PlayerGui or Assets.Emotes") local PALETTE = { background = Color3.fromRGB(21, 19, 21), list = Color3.fromRGB(15, 13, 15), raised = Color3.fromRGB(37, 31, 34), hover = Color3.fromRGB(53, 43, 47), border = Color3.fromRGB(78, 63, 67), muted = Color3.fromRGB(166, 153, 156), text = Color3.fromRGB(238, 232, 230), accent = Color3.fromRGB(197, 93, 94), accentDim = Color3.fromRGB(86, 38, 43), } type Emote = { name: string, moduleName: string, animationId: any, sfx: any, sfxProperties: any, serverEffects: boolean, } type WindowControls = { screen: ScreenGui?, copyLayer: ScreenGui?, safe: Frame?, window: Frame?, search: TextBox?, clear: TextButton?, list: ScrollingFrame?, listHolder: Frame?, empty: TextLabel?, count: TextLabel?, status: TextLabel?, auto: TextButton?, play: TextButton?, opener: TextButton?, } type PlaybackState = { alive: boolean, open: boolean, autoPlay: boolean, selected: Emote?, playing: Emote?, playToken: any, track: AnimationTrack?, animation: Animation?, sound: Sound?, playConnections: { RBXScriptConnection }, connections: { RBXScriptConnection }, rows: { [any]: (boolean) -> () }, rowInstances: { [any]: TextButton }, catalog: { Emote }, ui: WindowControls, } local state: PlaybackState = { alive = true, open = true, autoPlay = false, selected = nil, playing = nil, playToken = nil, track = nil, animation = nil, sound = nil, playConnections = {}, connections = {}, rows = {}, rowInstances = {}, catalog = {}, ui = {}, } local session = { unload = nil :: (() -> ())? } local function connect(signal: RBXScriptSignal, callback: (...any) -> ()) local connection = signal:Connect(callback) table.insert(state.connections, connection) return connection end local function make(className: string, properties: { [string]: any }, parent: Instance?): any local instance = Instance.new(className) for property, value in pairs(properties) do (instance :: any)[property] = value end instance.Parent = parent return instance end local function rounded(target, radius) make("UICorner", { CornerRadius = UDim.new(0, radius) }, target) end local function label(parent, properties) local defaults = { BackgroundTransparency = 1, TextColor3 = PALETTE.text, Font = Enum.Font.GothamMedium, TextSize = 14, TextXAlignment = Enum.TextXAlignment.Left, TextTruncate = Enum.TextTruncate.AtEnd, } for property, value in pairs(properties) do defaults[property] = value end return make("TextLabel", defaults, parent) end local function button(parent, properties) local defaults = { AutoButtonColor = false, BackgroundColor3 = PALETTE.raised, BorderSizePixel = 0, Font = Enum.Font.GothamBold, TextColor3 = PALETTE.text, TextSize = 12, Selectable = true, } for property, value in pairs(properties) do defaults[property] = value end local control = make("TextButton", defaults, parent) rounded(control, 6) return control end local function stopPlayback() local track = state.track state.playToken = nil state.track = nil state.playing = nil for _, connection in ipairs(state.playConnections) do connection:Disconnect() end table.clear(state.playConnections) if track then track:Stop(0.12) track:Destroy() end if state.sound then state.sound:Destroy() state.sound = nil end if state.animation then state.animation:Destroy() state.animation = nil end end function session.unload() if not state.alive then return end state.alive = false stopPlayback() for _, connection in ipairs(state.connections) do connection:Disconnect() end table.clear(state.connections) if state.ui.screen then state.ui.screen:Destroy() end if state.ui.copyLayer then state.ui.copyLayer:Destroy() end end local function readEmote(module: Instance): (Emote?, string?) if not module:IsA("ModuleScript") then return nil, "Expected ModuleScript" end local ok, config = pcall(require, module) if not ok then return nil, tostring(config) end if type(config) ~= "table" or type(config.DisplayName) ~= "string" or (type(config.AssetID) ~= "string" and type(config.AssetID) ~= "table") then return nil, "missing DisplayName or AssetID" end return { name = config.DisplayName, moduleName = module.Name, animationId = config.AssetID, sfx = config.SFX, sfxProperties = config.SFXProperties, serverEffects = type(config.CreatedServer) == "function" or type(config.DestroyedServer) == "function", }, nil end local function chooseAnimation(assetId: any): (string?, string?, number?, string?) if type(assetId) == "string" then return assetId, nil, nil, nil end if type(assetId) ~= "table" then return nil, nil, nil, nil end local choice = assetId local index = nil local variant = nil if #assetId > 0 then index = math.random(1, #assetId) choice = assetId[index] elseif type(assetId.Start) ~= "string" then local keys = {} for key, value in pairs(assetId) do if type(key) == "string" and type(value) == "string" then table.insert(keys, key) end end table.sort(keys) if #keys == 0 then return nil, nil, nil, nil end variant = keys[1] choice = assetId[variant] end if type(choice) == "string" then return choice, nil, index, variant end if type(choice) == "table" and type(choice.Start) == "string" then return choice.Start, if type(choice.Loop) == "string" then choice.Loop else nil, index, variant end return nil, nil, index, variant end local function chooseSound(sfx: any, index: number?, stage: string): string? if type(sfx) == "string" then return sfx end if type(sfx) ~= "table" then return nil end local sound = sfx[stage] if sound == nil then sound = if index then sfx[index] or sfx[1] else sfx[1] end if type(sound) == "table" then sound = sound[1] end return if type(sound) == "string" then sound else nil end local function setStatus(message) if state.alive and state.ui.status then state.ui.status.Text = message end end local function updateActions() local ui = state.ui local play = ui.play local auto = ui.auto if not (play and auto) then return end local selected = state.selected local isPlayable = selected ~= nil play.Interactable = isPlayable play.Text = if state.playing then "STOP" else "PLAY" play.BackgroundColor3 = if isPlayable then PALETTE.accentDim else PALETTE.raised play.TextColor3 = if isPlayable then PALETTE.text else PALETTE.muted auto.Text = if state.autoPlay then "AUTO PLAY EMOTE: ON" else "AUTO PLAY EMOTE: OFF" auto.BackgroundColor3 = if state.autoPlay then PALETTE.accentDim else PALETTE.raised auto.TextColor3 = if state.autoPlay then PALETTE.accent else PALETTE.text for emote, paint in pairs(state.rows) do paint(rawequal(emote, selected)) end end local function playSelected() local emote = state.selected if not emote then setStatus("Select an emote first") return end local startId, loopId, variantIndex, variantName = chooseAnimation(emote.animationId) if not startId then setStatus("Missing animation ID: " .. emote.name) return end stopPlayback() local token = {} state.playToken = token local character = localPlayer.Character if not character or not character:IsDescendantOf(workspace) then setStatus("Character not found") updateActions() return end local humanoid = character:FindFirstChildOfClass("Humanoid") if not humanoid or humanoid.Health <= 0 then setStatus("Animator not found") updateActions() return end local characterAnimator = humanoid:FindFirstChildOfClass("Animator") if not characterAnimator then setStatus("Animator not found") updateActions() return end local properties = if type(emote.sfxProperties) == "table" then emote.sfxProperties else {} local rootPart = character:FindFirstChild("HumanoidRootPart") local function playSound(stage: string) if not rootPart then return end local soundId = chooseSound(emote.sfx, variantIndex, stage) if state.sound and soundId == state.sound.SoundId then if stage == "Loop" and loopId then state.sound.Looped = true if not state.sound.Playing then state.sound:Play() end end return end if state.sound then state.sound:Destroy() state.sound = nil end if not soundId then return end local sound = make("Sound", { SoundId = soundId, Volume = if type(properties.Volume) == "number" then math.clamp(properties.Volume, 0, 2) else 0.5, Looped = if loopId then stage == "Loop" else properties.Looped == true, }, rootPart) state.sound = sound sound:Play() end local function playTrack(id: string, looped: boolean?): (AnimationTrack?, string?) local animation = make("Animation", { AnimationId = id }, nil) local okTrack, loaded = pcall(function() return characterAnimator:LoadAnimation(animation) end) if not okTrack then animation:Destroy() return nil, tostring(loaded) end if not state.alive or humanoid.Health <= 0 or localPlayer.Character ~= character or not rawequal(state.playToken, token) then loaded:Destroy() animation:Destroy() return nil, "character changed during load" end local oldTrack = state.track state.track = nil if oldTrack then oldTrack:Destroy() end if state.animation then state.animation:Destroy() end local track = loaded track.Priority = Enum.AnimationPriority.Action if looped ~= nil then track.Looped = looped end state.animation = animation state.track = track track:Play(0.12) return track, nil end local firstTrack, firstError = playTrack(startId, if loopId then false else nil) if not firstTrack then if rawequal(state.playToken, token) then stopPlayback() setStatus("Animation load failed: " .. emote.name .. ": " .. tostring(firstError)) updateActions() end return end state.playing = emote playSound("Start") local function endEmote() if state.playing == emote and rawequal(state.playToken, token) then stopPlayback() setStatus("Selected: " .. emote.name) updateActions() end end table.insert(state.playConnections, firstTrack.Stopped:Connect(function() if state.track ~= firstTrack then return end if not loopId then endEmote() return end local loopTrack, loopError = playTrack(loopId, true) if not loopTrack then if rawequal(state.playToken, token) then stopPlayback() setStatus("Animation load failed: " .. emote.name .. " loop: " .. tostring(loopError)) updateActions() end return end playSound("Loop") table.insert(state.playConnections, loopTrack.Stopped:Connect(endEmote)) end)) table.insert(state.playConnections, humanoid.Died:Connect(endEmote)) table.insert(state.playConnections, humanoid.Running:Connect(function(speed) if speed > 0.5 then endEmote() end end)) table.insert(state.playConnections, humanoid.StateChanged:Connect(function(_, nextState) if nextState == Enum.HumanoidStateType.Jumping or nextState == Enum.HumanoidStateType.Freefall then endEmote() end end)) local detail = if variantName then " (" .. variantName .. " clip)" else "" local effectsNote = if emote.serverEffects then " - server effects not included" else "" setStatus("Playing " .. emote.name .. detail .. effectsNote) updateActions() end local function selectEmote(emote: Emote) if rawequal(state.selected, emote) then if state.autoPlay then playSelected() end return end stopPlayback() state.selected = emote setStatus("Selected: " .. emote.name) updateActions() if state.autoPlay then playSelected() end end local function bindVisual(control, normal, hovered) local hasFocus = false local isHovering = false local isPressed = false local function paint() if control.Interactable == false then return end control.BackgroundColor3 = if isPressed or hasFocus or isHovering then hovered else normal() end connect(control.MouseEnter, function() isHovering = UserInputService:GetLastInputType() == Enum.UserInputType.MouseMovement paint() end) connect(control.MouseLeave, function() isHovering = false paint() end) connect(control.SelectionGained, function() hasFocus = true paint() end) connect(control.SelectionLost, function() hasFocus = false paint() end) connect(control.InputBegan, function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then isPressed = true paint() end end) connect(control.InputEnded, function(input) if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then isPressed = false paint() end end) return paint end local function createEmoteWindow() local screen = make("ScreenGui", { Name = attribution.screen, ResetOnSpawn = false, ScreenInsets = Enum.ScreenInsets.CoreUISafeInsets, ZIndexBehavior = Enum.ZIndexBehavior.Sibling, DisplayOrder = 40, }, playerGui) local shutdown = Instance.new("BindableEvent") shutdown.Name = attribution.shutdown shutdown.Parent = screen connect(shutdown.Event, function() if session.unload then session.unload() end end) state.ui.screen = screen local function mountAttributionLayer() local layer = make("ScreenGui", { Name = attribution.overlay, ResetOnSpawn = false, ScreenInsets = Enum.ScreenInsets.CoreUISafeInsets, ZIndexBehavior = Enum.ZIndexBehavior.Sibling, DisplayOrder = 42, }, playerGui) state.ui.copyLayer = layer connect(layer.Destroying, function() if state.alive and session.unload then state.ui.copyLayer = nil session.unload() end end) local hint = label(layer, { Name = "CopyConfirmation", Text = "Copied!", Font = Enum.Font.GothamBold, TextSize = 12, TextColor3 = PALETTE.text, TextXAlignment = Enum.TextXAlignment.Center, BackgroundTransparency = 0, BackgroundColor3 = PALETTE.accentDim, BorderSizePixel = 0, Size = UDim2.fromOffset(76, 28), Visible = false, }) make("UICorner", { CornerRadius = UDim.new(1, 0) }, hint) local creditText = attribution.credit local profileURL = attribution.url local measured = TextService:GetTextSize(creditText, 13, Enum.Font.GothamBold, Vector2.new(420, 26)) local width = math.ceil(measured.X) + 22 local hiddenX = width + 16 local notice = make("Frame", { Name = "OverlayCard", AnchorPoint = Vector2.new(1, 0), Position = UDim2.new(1, hiddenX, 0, 18), Size = UDim2.fromOffset(width, 40), BackgroundColor3 = PALETTE.raised, BorderSizePixel = 0, Active = false, ZIndex = 7, }, layer) rounded(notice, 7) make("UIStroke", { Color = PALETTE.border, Thickness = 1, ApplyStrokeMode = Enum.ApplyStrokeMode.Border, }, notice) local creditLabel = label(notice, { Text = creditText, Font = Enum.Font.GothamBold, TextSize = 13, TextColor3 = PALETTE.text, TextXAlignment = Enum.TextXAlignment.Center, Position = UDim2.fromOffset(11, 0), Size = UDim2.new(1, -22, 1, 0), ZIndex = 8, }) assert(creditLabel.Parent == notice and creditLabel.Text == creditText and notice:IsDescendantOf(layer), "Credit notification missing") local noticeExpired = false connect(notice.Destroying, function() if state.alive and not noticeExpired and session.unload then session.unload() end end) local tweenService = game:GetService("TweenService") local arrived = UDim2.new(1, -14, 0, 18) tweenService:Create(notice, TweenInfo.new(0.27, Enum.EasingStyle.Quint, Enum.EasingDirection.Out), { Position = arrived, }):Play() task.delay(4, function() if not state.alive or not notice.Parent then return end tweenService:Create(notice, TweenInfo.new(0.25, Enum.EasingStyle.Quad, Enum.EasingDirection.In), { Position = UDim2.new(1, hiddenX, 0, 18), }):Play() task.delay(0.28, function() noticeExpired = true if notice.Parent then notice:Destroy() end end) end) return layer, hint, profileURL end local copyLayer, copyHint, profileURL = mountAttributionLayer() state.ui.copyLayer = copyLayer local safe = make("Frame", { Name = "SafeArea", BackgroundTransparency = 1, Size = UDim2.fromScale(1, 1), Active = false, }, screen) local window = make("Frame", { Name = "EmoteWindow", AnchorPoint = Vector2.new(0.5, 0.5), Position = UDim2.fromScale(0.5, 0.5), Size = UDim2.fromScale(0.87, 0.87), BackgroundColor3 = PALETTE.background, BorderSizePixel = 0, Active = true, }, safe) rounded(window, 6) make("UISizeConstraint", { MinSize = Vector2.new(304, 240), MaxSize = Vector2.new(580, 530), }, window) make("UIStroke", { Color = PALETTE.border, Thickness = 1, ApplyStrokeMode = Enum.ApplyStrokeMode.Border, }, window) local header = make("Frame", { BackgroundTransparency = 1, Size = UDim2.new(1, 0, 0, 74), }, window) local title = label(header, { Text = "YS HUB - FORSAKEN EMOTES", Font = Enum.Font.GothamBold, TextSize = 20, Position = UDim2.fromOffset(16, 9), Size = UDim2.new(1, -32, 0, 25), Active = true, }) local subtitle = label(header, { Text = "Made by " .. profileURL, TextColor3 = PALETTE.muted, TextSize = 12, Position = UDim2.fromOffset(16, 41), Size = UDim2.new(1, -32, 0, 20), }) local copy = button(header, { Name = "CopyProfileLink", Text = "", BackgroundColor3 = PALETTE.background, Size = UDim2.fromOffset(26, 26), ZIndex = 3, }) make("ImageLabel", { Name = "CopyIcon", BackgroundTransparency = 1, Image = "rbxassetid://7733764083", ImageColor3 = PALETTE.muted, ScaleType = Enum.ScaleType.Fit, AnchorPoint = Vector2.new(0.5, 0.5), Position = UDim2.fromScale(0.5, 0.5), Size = UDim2.fromOffset(15, 15), ZIndex = 4, }, copy) local minimize = button(header, { Text = "MINIMIZE", Size = UDim2.fromOffset(96, 44), Modal = true, }) local unload = button(header, { Text = "UNLOAD", Size = UDim2.fromOffset(78, 44) }) local searchHolder = make("Frame", { BackgroundColor3 = PALETTE.raised, BorderSizePixel = 0, Position = UDim2.fromOffset(16, 78), Size = UDim2.new(1, -32, 0, 44), }, window) rounded(searchHolder, 6) local search = make("TextBox", { BackgroundTransparency = 1, ClearTextOnFocus = false, Font = Enum.Font.GothamMedium, TextSize = 14, TextColor3 = PALETTE.text, PlaceholderColor3 = PALETTE.muted, PlaceholderText = "Search emotes...", Text = "", TextXAlignment = Enum.TextXAlignment.Left, Position = UDim2.fromOffset(12, 0), Size = UDim2.new(1, -62, 1, 0), }, searchHolder) local clear = button(searchHolder, { Text = "", BackgroundColor3 = PALETTE.raised, Size = UDim2.fromOffset(44, 44), AnchorPoint = Vector2.new(1, 0.5), Position = UDim2.new(1, -1, 0.5, 0), Visible = false, }) for _, angle in { 45, -45 } do make("Frame", { AnchorPoint = Vector2.new(0.5, 0.5), Position = UDim2.fromScale(0.5, 0.5), Size = UDim2.fromOffset(14, 2), Rotation = angle, BackgroundColor3 = PALETTE.muted, BorderSizePixel = 0, Active = false, }, clear) end local status = label(window, { Text = "Loading emotes...", TextColor3 = PALETTE.muted, TextSize = 12, Position = UDim2.fromOffset(16, 130), Size = UDim2.new(1, -106, 0, 18), }) local count = label(window, { Text = "", TextColor3 = PALETTE.muted, TextSize = 12, TextXAlignment = Enum.TextXAlignment.Right, AnchorPoint = Vector2.new(1, 0), Position = UDim2.new(1, -16, 0, 130), Size = UDim2.fromOffset(90, 18), }) local listHolder = make("Frame", { BackgroundColor3 = PALETTE.list, BorderSizePixel = 0, Position = UDim2.fromOffset(16, 154), Size = UDim2.new(1, -32, 1, -216), }, window) rounded(listHolder, 6) local list = make("ScrollingFrame", { Name = "EmoteList", BackgroundTransparency = 1, BorderSizePixel = 0, Position = UDim2.fromOffset(4, 4), Size = UDim2.new(1, -8, 1, -8), CanvasSize = UDim2.new(), AutomaticCanvasSize = Enum.AutomaticSize.Y, ScrollBarThickness = 4, ScrollBarImageColor3 = PALETTE.border, ScrollingDirection = Enum.ScrollingDirection.Y, ClipsDescendants = true, }, listHolder) make("UIPadding", { PaddingTop = UDim.new(0, 8), PaddingBottom = UDim.new(0, 8), PaddingLeft = UDim.new(0, 8), PaddingRight = UDim.new(0, 8), }, list) make("UIListLayout", { Padding = UDim.new(0, 4), SortOrder = Enum.SortOrder.LayoutOrder, }, list) local empty = label(list, { Text = "No emotes match this search", TextColor3 = PALETTE.muted, Size = UDim2.new(1, 0, 0, 44), LayoutOrder = 100000, Visible = false, }) local footer = make("Frame", { BackgroundTransparency = 1, Size = UDim2.new(1, -32, 0, 44), AnchorPoint = Vector2.new(0, 1), Position = UDim2.new(0, 16, 1, -12), }, window) local auto = button(footer, { Text = "AUTO PLAY EMOTE: OFF", Size = UDim2.fromOffset(178, 44), }) local play = button(footer, { Text = "UNAVAILABLE", AnchorPoint = Vector2.new(1, 0), Position = UDim2.fromScale(1, 0), Size = UDim2.fromOffset(100, 44), Interactable = false, }) local opener = button(safe, { Name = "OpenEmoteWindow", Text = "OPEN", Size = UDim2.fromOffset(72, 44), AnchorPoint = Vector2.new(1, 0.5), Position = UDim2.new(1, -12, 0.43, 0), BackgroundColor3 = PALETTE.background, Visible = false, }) make("UIStroke", { Color = PALETTE.border, Thickness = 1, ApplyStrokeMode = Enum.ApplyStrokeMode.Border, }, opener) state.ui = { screen = screen, copyLayer = copyLayer, safe = safe, window = window, search = search, clear = clear, list = list, listHolder = listHolder, empty = empty, count = count, status = status, auto = auto, play = play, opener = opener, } local function arrange() local compact = window.AbsoluteSize.X < 470 local headerHeight = if compact then 112 else 74 header.Size = UDim2.new(1, 0, 0, headerHeight) title.TextSize = if compact then 16 else 20 title.Size = UDim2.new(1, if compact then -32 else -212, 0, 25) subtitle.TextSize = if compact then 11 else 12 local availableWidth = window.AbsoluteSize.X - (if compact then 32 else 212) local measuredWidth = TextService:GetTextSize( subtitle.Text, subtitle.TextSize, subtitle.Font, Vector2.new(2048, 20) ).X subtitle.Size = UDim2.fromOffset(math.min(measuredWidth, math.max(0, availableWidth - 30)), 20) subtitle.Position = UDim2.fromOffset(16, if compact then 36 else 41) copy.Position = UDim2.fromOffset(18 + subtitle.Size.X.Offset, if compact then 31 else 38) minimize.Position = UDim2.new(1, -190, 0, if compact then 66 else 9) unload.Position = UDim2.new(1, -90, 0, if compact then 66 else 9) searchHolder.Position = UDim2.fromOffset(16, headerHeight + 4) status.Position = UDim2.fromOffset(16, headerHeight + 54) count.Position = UDim2.new(1, -16, 0, headerHeight + 54) listHolder.Position = UDim2.fromOffset(16, headerHeight + 78) listHolder.Size = UDim2.new(1, -32, 1, -(headerHeight + 140)) end local function placeCopyHint() local relative = copy.AbsolutePosition - safe.AbsolutePosition local preferredX = relative.X + copy.AbsoluteSize.X + 8 local maxX = math.max(8, safe.AbsoluteSize.X - 84) local x = math.clamp(preferredX, 8, maxX) local y = relative.Y + (copy.AbsoluteSize.Y - 28) / 2 if x < preferredX then y = relative.Y - 34 end copyHint.Position = UDim2.fromOffset(x, math.clamp(y, 8, math.max(8, safe.AbsoluteSize.Y - 36))) end local copyTicket = 0 local function setOpen(isOpen) state.open = isOpen window.Visible = isOpen opener.Visible = not isOpen copyTicket += 1 copyHint.Visible = false if not isOpen and search:IsFocused() then search:ReleaseFocus() end end local function attachDrag(target: GuiObject, frame: GuiObject, anchor: Vector2) local capturedInput: InputObject? = nil local startPosition: Vector3? = nil local startFrame: Vector2? = nil connect(target.InputBegan, function(input) if input.UserInputType ~= Enum.UserInputType.MouseButton1 and input.UserInputType ~= Enum.UserInputType.Touch then return end capturedInput = input startPosition = input.Position startFrame = frame.AbsolutePosition - safe.AbsolutePosition end) connect(UserInputService.InputChanged, function(input) if not capturedInput or not startFrame or not startPosition then return end if input ~= capturedInput and not ( capturedInput.UserInputType == Enum.UserInputType.MouseButton1 and input.UserInputType == Enum.UserInputType.MouseMovement ) then return end local delta = input.Position - startPosition local size = frame.AbsoluteSize local safeSize = safe.AbsoluteSize local x = math.clamp(startFrame.X + delta.X, 8, math.max(8, safeSize.X - size.X - 8)) local y = math.clamp(startFrame.Y + delta.Y, 8, math.max(8, safeSize.Y - size.Y - 8)) frame.Position = UDim2.fromOffset(x + size.X * anchor.X, y + size.Y * anchor.Y) end) connect(UserInputService.InputEnded, function(input) if input == capturedInput then capturedInput = nil end end) end attachDrag(title, window, window.AnchorPoint) attachDrag(opener, opener, opener.AnchorPoint) connect(window:GetPropertyChangedSignal("AbsoluteSize"), arrange) connect(copy:GetPropertyChangedSignal("AbsolutePosition"), function() if copyHint.Visible then placeCopyHint() end end) arrange() connect(opener.Activated, function() setOpen(true) end) connect(minimize.Activated, function() setOpen(false) end) connect(unload.Activated, function() if session.unload then session.unload() end end) bindVisual(minimize, function() return PALETTE.raised end, PALETTE.hover) bindVisual(unload, function() return PALETTE.raised end, PALETTE.hover) bindVisual(copy, function() return PALETTE.background end, PALETTE.raised) bindVisual(clear, function() return PALETTE.raised end, PALETTE.hover) bindVisual(auto, function() return if state.autoPlay then PALETTE.accentDim else PALETTE.raised end, PALETTE.hover) bindVisual(play, function() return PALETTE.accentDim end, PALETTE.hover) bindVisual(opener, function() return PALETTE.background end, PALETTE.hover) connect(clear.Activated, function() search.Text = "" search:CaptureFocus() end) connect(copy.Activated, function() local clipboard = setclipboard if type(clipboard) ~= "function" then setStatus("Missing setclipboard") return end local copied, problem = pcall(function(): string clipboard(profileURL) return "" end) if not copied then setStatus("Clipboard write failed: " .. tostring(problem)) return end copyTicket += 1 local ticket = copyTicket placeCopyHint() copyHint.Visible = true task.delay(1.5, function() if state.alive and ticket == copyTicket then copyHint.Visible = false end end) end) connect(auto.Activated, function() state.autoPlay = not state.autoPlay updateActions() if state.autoPlay and state.selected then playSelected() end end) connect(play.Activated, function() if state.playing then stopPlayback() local selected = state.selected if selected then setStatus("Selected: " .. selected.name) end updateActions() else playSelected() end end) connect(UserInputService.InputBegan, function(input, gameProcessed) if gameProcessed or UserInputService:GetFocusedTextBox() then return end if input.KeyCode == Enum.KeyCode.RightShift then setOpen(not state.open) end end) connect(localPlayer.CharacterAdded, function() stopPlayback() if state.selected then setStatus("Selected: " .. state.selected.name) end updateActions() end) connect(screen.Destroying, function() if session.unload then session.unload() end end) local catalog = state.catalog local function filterCatalog() local query = string.lower(search.Text) local found = 0 for _, emote in ipairs(catalog) do local matches = string.find(string.lower(emote.name), query, 1, true) ~= nil state.rowInstances[emote].Visible = matches if matches then found += 1 end end count.Text = tostring(found) .. " / " .. tostring(#catalog) empty.Text = if #catalog == 0 then "Loading emotes..." else "No emotes match this search" empty.Visible = found == 0 clear.Visible = query ~= "" end local loadedModules = {} local loadingModules = {} local failedModules = {} local function registerModule(module: Instance) if not module:IsA("ModuleScript") then return end if string.sub(module.Name, 1, 1) == "!" or loadedModules[module] or loadingModules[module] then return end loadingModules[module] = true local emote, failure = readEmote(module) loadingModules[module] = nil if not state.alive or not module:IsDescendantOf(emoteModules) then return end if not emote then if not failedModules[module] then warn("[Emotes] " .. module.Name .. ": " .. tostring(failure)) failedModules[module] = true end return end loadedModules[module] = true table.insert(catalog, emote) local row = button(list, { Text = emote.name, Font = Enum.Font.GothamMedium, TextSize = 14, TextXAlignment = Enum.TextXAlignment.Left, TextTruncate = Enum.TextTruncate.AtEnd, Size = UDim2.new(1, 0, 0, 44), BackgroundColor3 = PALETTE.list, LayoutOrder = #catalog, }) state.rowInstances[emote] = row make("UIPadding", { PaddingLeft = UDim.new(0, 12), PaddingRight = UDim.new(0, 12) }, row) local isSelected = false local paint = bindVisual(row, function() return if isSelected then PALETTE.accentDim else PALETTE.list end, PALETTE.hover) state.rows[emote] = function(selected) isSelected = selected row.Font = if selected then Enum.Font.GothamBold else Enum.Font.GothamMedium row.TextColor3 = if selected then PALETTE.accent else PALETTE.text paint() end connect(row.Activated, function() selectEmote(emote) end) table.sort(catalog, function(left, right) local a, b = string.lower(left.name), string.lower(right.name) return if a == b then left.moduleName < right.moduleName else a < b end) for index, entry in ipairs(catalog) do state.rowInstances[entry].LayoutOrder = index end filterCatalog() end local function scanModules() if not state.alive then return end for _, module in ipairs(emoteModules:GetChildren()) do if not state.alive then break end registerModule(module) end end local function reportMissingModules() scanModules() if not state.alive then return end local expected = 0 for _, module in ipairs(emoteModules:GetChildren()) do if module:IsA("ModuleScript") and string.sub(module.Name, 1, 1) ~= "!" then expected += 1 end end if expected > #catalog then local missing = expected - #catalog warn("[Emotes] " .. tostring(missing) .. " modules failed to load") if not state.selected then setStatus(tostring(missing) .. " modules failed; check console") end end end connect(emoteModules.ChildAdded, function(module) task.defer(registerModule, module) end) connect(search:GetPropertyChangedSignal("Text"), filterCatalog) filterCatalog() setStatus("Select an emote") updateActions() task.spawn(scanModules) task.delay(3, scanModules) task.delay(8, reportMissingModules) end local previousWindow = playerGui:FindFirstChild(attribution.screen) if previousWindow then local shutdown = previousWindow:FindFirstChild(attribution.shutdown) if shutdown and shutdown:IsA("BindableEvent") then shutdown:Fire() else previousWindow:Destroy() end end local previousCopy = playerGui:FindFirstChild(attribution.overlay) if previousCopy then previousCopy:Destroy() end local created, problem = pcall(function(): string createEmoteWindow() return "" end) if not created then if session.unload then session.unload() end error("Window creation failed: " .. tostring(problem), 0) end