-- Moonware ☾
-- Made by n_e_r_v_y with love
local UIS = game:GetService("UserInputService")
local TS = game:GetService("TweenService")
local RS = game:GetService("RunService")
local Stats = game:GetService("Stats")
local Players = game:GetService("Players")
local Lighting = game:GetService("Lighting")
local HttpService = game:GetService("HttpService")
local SoundService = game:GetService("SoundService")
local AssetService = game:GetService("AssetService")
local ContentProvider = game:GetService("ContentProvider")
local TextChatService = game:GetService("TextChatService")
local player = Players.LocalPlayer
local camera = workspace.CurrentCamera
local pg = player:WaitForChild("PlayerGui")
for _, n in ipairs({"OwoClient","OwoOverlays","OwoPrompt","OwoNotify","OwoFriendChat","OwoCrosshair","OwoScreenFX","OwoPicker"}) do
local o = pg:FindFirstChild(n); if o then o:Destroy() end
end
for _, o in ipairs(Lighting:GetChildren()) do if o.Name:sub(1,3) == "Owo" then o:Destroy() end end
do
local f = workspace:FindFirstChild("OwoFX"); if f then f:Destroy() end
local rpf = workspace:FindFirstChild("OwoRipples"); if rpf then rpf:Destroy() end
local olf = workspace:FindFirstChild("OwoOutlines"); if olf then olf:Destroy() end
local trf = workspace:FindFirstChild("OwoTrail"); if trf then trf:Destroy() end
local pdf = workspace:FindFirstChild("OwoPuddles"); if pdf then pdf:Destroy() end
local snf = workspace:FindFirstChild("OwoSnowFloor"); if snf then snf:Destroy() end
local m = SoundService:FindFirstChild("OwoMusic"); if m then m:Destroy() end
local u = SoundService:FindFirstChild("OwoUISounds"); if u then u:Destroy() end
end
-- ══════════════════════════════════════════════════════════════
-- CORE TABLES
-- ══════════════════════════════════════════════════════════════
local TR = { Window=0, Title=0, Sidebar=0, Content=0, Card=0, Overlay=0, Notify=0 }
local T = {
Bg=Color3.fromRGB(7,8,11), Panel=Color3.fromRGB(10,11,15), Sidebar=Color3.fromRGB(8,9,13),
Card=Color3.fromRGB(17,19,24), Hover=Color3.fromRGB(25,28,35), Text=Color3.fromRGB(240,242,248),
Dim=Color3.fromRGB(151,158,172), Muted=Color3.fromRGB(105,113,129), Line=Color3.fromRGB(34,38,48),
Accent=Color3.fromRGB(200,204,218), Accent2=Color3.fromRGB(143,151,170),
On=Color3.fromRGB(200,204,218), Off=Color3.fromRGB(38,42,52), Bad=Color3.fromRGB(240,100,110),
}
local PRESETS = {
Gray={Bg=Color3.fromRGB(7,8,11),Panel=Color3.fromRGB(10,11,15),Sidebar=Color3.fromRGB(8,9,13),Card=Color3.fromRGB(17,19,24),Hover=Color3.fromRGB(25,28,35),Line=Color3.fromRGB(34,38,48),Accent=Color3.fromRGB(200,204,218),Accent2=Color3.fromRGB(143,151,170)},
Teal={Bg=Color3.fromRGB(8,18,18),Panel=Color3.fromRGB(12,24,24),Sidebar=Color3.fromRGB(14,26,26),Card=Color3.fromRGB(18,36,34),Hover=Color3.fromRGB(26,50,46),Line=Color3.fromRGB(32,62,56),Accent=Color3.fromRGB(80,235,185),Accent2=Color3.fromRGB(40,190,150)},
Novoline={Bg=Color3.fromRGB(13,13,17),Panel=Color3.fromRGB(16,16,22),Sidebar=Color3.fromRGB(18,18,24),Card=Color3.fromRGB(22,22,30),Hover=Color3.fromRGB(30,30,40),Line=Color3.fromRGB(38,38,48),Accent=Color3.fromRGB(167,139,250),Accent2=Color3.fromRGB(99,102,241)},
Blue={Bg=Color3.fromRGB(10,14,22),Panel=Color3.fromRGB(14,20,30),Sidebar=Color3.fromRGB(16,22,34),Card=Color3.fromRGB(20,28,42),Hover=Color3.fromRGB(28,38,56),Line=Color3.fromRGB(34,46,66),Accent=Color3.fromRGB(80,160,255),Accent2=Color3.fromRGB(50,110,220)},
Red={Bg=Color3.fromRGB(18,10,12),Panel=Color3.fromRGB(24,14,18),Sidebar=Color3.fromRGB(26,16,20),Card=Color3.fromRGB(36,20,26),Hover=Color3.fromRGB(48,28,34),Line=Color3.fromRGB(58,34,42),Accent=Color3.fromRGB(255,90,110),Accent2=Color3.fromRGB(210,50,70)},
Violet={Bg=Color3.fromRGB(16,10,26),Panel=Color3.fromRGB(22,14,36),Sidebar=Color3.fromRGB(24,16,38),Card=Color3.fromRGB(32,22,48),Hover=Color3.fromRGB(44,30,62),Line=Color3.fromRGB(54,38,76),Accent=Color3.fromRGB(190,130,255),Accent2=Color3.fromRGB(140,80,230)},
Pink={Bg=Color3.fromRGB(20,10,16),Panel=Color3.fromRGB(28,14,22),Sidebar=Color3.fromRGB(30,16,24),Card=Color3.fromRGB(42,22,32),Hover=Color3.fromRGB(56,30,42),Line=Color3.fromRGB(68,38,52),Accent=Color3.fromRGB(255,130,190),Accent2=Color3.fromRGB(230,80,150)},
Green={Bg=Color3.fromRGB(10,18,12),Panel=Color3.fromRGB(14,24,16),Sidebar=Color3.fromRGB(16,26,18),Card=Color3.fromRGB(22,36,26),Hover=Color3.fromRGB(30,48,34),Line=Color3.fromRGB(36,58,40),Accent=Color3.fromRGB(120,220,150),Accent2=Color3.fromRGB(70,180,110)},
Cyan={Bg=Color3.fromRGB(8,16,20),Panel=Color3.fromRGB(12,22,28),Sidebar=Color3.fromRGB(14,24,30),Card=Color3.fromRGB(18,34,42),Hover=Color3.fromRGB(26,46,56),Line=Color3.fromRGB(32,56,68),Accent=Color3.fromRGB(80,220,240),Accent2=Color3.fromRGB(50,170,200)},
Orange={Bg=Color3.fromRGB(20,12,6),Panel=Color3.fromRGB(28,18,10),Sidebar=Color3.fromRGB(30,20,12),Card=Color3.fromRGB(42,26,16),Hover=Color3.fromRGB(56,36,22),Line=Color3.fromRGB(68,44,28),Accent=Color3.fromRGB(255,150,70),Accent2=Color3.fromRGB(230,110,40)},
Dark={Bg=Color3.fromRGB(6,6,8),Panel=Color3.fromRGB(10,10,14),Sidebar=Color3.fromRGB(12,12,16),Card=Color3.fromRGB(18,18,24),Hover=Color3.fromRGB(26,26,34),Line=Color3.fromRGB(34,34,42),Accent=Color3.fromRGB(230,230,240),Accent2=Color3.fromRGB(180,180,200)},
}
local PRESET_ORDER = {"Gray","Teal","Novoline","Blue","Red","Violet","Pink","Green","Cyan","Orange","Dark"}
local ThemeRefs = {}
local GlassGrads, GlassStrokes = {}, {}
local Glass = { on=false, style="Frosted", clarity=62, blur=10, shine=0.55, tint=0, refraction=2.4, worldBlur=true, anim=true, applying=false }
local UI = { opacity=0, cards={}, n=0, isOpen=false }
local Fn, Wx = {}, {}
local overlays = {}
local overlayShines = {}
local profilePfpTargets = {}
local Keybinds, ToggleReg, SliderReg = {}, {}, {}
local FILE_OK = (typeof(writefile)=="function" and typeof(readfile)=="function")
-- Resolve a Creator Store decal to its linked texture when possible. Some
-- ImageLabels accept the asset ID directly, while decal container IDs can
-- require the Texture value from the Decal instance.
local ROBLOX_ICON_TEXTURE_CACHE = {}
local function resolveRobloxIconTexture(assetId)
local id = tostring(assetId)
if ROBLOX_ICON_TEXTURE_CACHE[id] ~= nil then
return ROBLOX_ICON_TEXTURE_CACHE[id] ~= false and ROBLOX_ICON_TEXTURE_CACHE[id] or nil
end
local resolved = nil
local ok, objects = pcall(function()
return game:GetObjects("rbxassetid://" .. id)
end)
if ok and type(objects) == "table" then
for _, root in ipairs(objects) do
local candidate = nil
pcall(function()
if root:IsA("Decal") or root:IsA("Texture") then
candidate = root
else
candidate = root:FindFirstChildWhichIsA("Decal", true)
if not candidate then candidate = root:FindFirstChildWhichIsA("Texture", true) end
end
end)
if candidate then
local texture = nil
pcall(function() texture = candidate.Texture end)
if type(texture) == "string" and texture ~= "" then
resolved = texture
break
end
end
end
for _, root in ipairs(objects) do
pcall(function() root:Destroy() end)
end
end
ROBLOX_ICON_TEXTURE_CACHE[id] = resolved or false
return resolved
end
-- Shared loader for Creator Store icons.
-- Creator Store URLs identify decal assets; the official Roblox thumbnail URI
-- is tried first, then the direct asset URI and finally the resolved texture.
-- The fallback remains visible until ContentProvider confirms a successful load.
local function applyRobloxAssetIcon(image, assetId, fallback)
if not image or not assetId then return end
if fallback then fallback.Visible = true end
image.Visible = false
task.spawn(function()
local id = tostring(assetId):match("%d+") or tostring(assetId)
local sources = {
"rbxthumb://type=Asset&id=" .. id .. "&w=420&h=420",
"rbxassetid://" .. id,
}
local texture = resolveRobloxIconTexture(id)
if texture and texture ~= "" then
table.insert(sources, 2, texture)
end
for _, source in ipairs(sources) do
if not image.Parent then return end
image.Image = source
image.ImageTransparency = 0
local fetched = false
pcall(function()
ContentProvider:PreloadAsync({image}, function(_, status)
if status == Enum.AssetFetchStatus.Success then
fetched = true
end
end)
end)
local deadline = os.clock() + 9
local loaded = false
repeat
if not image.Parent then return end
if fetched or image.IsLoaded then
loaded = true
break
end
task.wait(0.1)
until os.clock() >= deadline
if loaded then
image.Visible = true
if fallback and fallback.Parent then fallback.Visible = false end
return
end
end
if image.Parent then image.Visible = false end
if fallback and fallback.Parent then fallback.Visible = true end
warn("[Moonware] Icon " .. id .. " did not load. The asset may be unavailable to this experience or Roblox may be blocking its thumbnail.")
end)
end
-- ══════════════════════════════════════════════════════════════
-- SMOOTHNESS ENGINE
-- ══════════════════════════════════════════════════════════════
local Smooth = { level=1.0, colorSpeed=4.0, effectSpeed=7.0 }
local function slerp(a, b, dt, speed)
return a + (b - a) * (1 - math.exp(-dt * (speed or 8) * Smooth.level))
end
local function slerpC(a, b, dt, speed)
return a:Lerp(b, 1 - math.exp(-dt * (speed or 8) * Smooth.level))
end
local function sdur(t) return t / math.max(Smooth.level, 0.1) end
-- Smoothed effect state
local sBloom, sTint, sVignette, sChroma, sRetro = 0, 0, 0, 0, 0
local sEffectColor = Color3.fromRGB(100, 200, 255)
local feat = {
visualStyles = {}, visualColors = {}, homeHoverReveal=false,
fly=false, flySpeed=55, flyAccel=12, flyDamping=10, flyVerticalBoost=1.3, flyPitchAmount=0.85,
noclip=false, infJump=false,
walkSpeed=16, jumpPower=50, freeCam=false, freeCamSpeed=60, fullbright=false,
glow=false, trail=false, trailStyle="Foggy", neon=false, sparkle=false, fire=false,
jumpRing=false, landRing=false, halo=false, wings=false, wingsStyle="Crystal", crown=false,
rain=false, snow=false, fog=false, fogDensity=0.35, thunder=false, fireflies=false,
cubes=false, cubeCount=6, cubeRadius=4.5, cubeSpeed=1.2, ambient=false,
ghost=false, ghostInterval=0.12,
playerTransparency=false, playerTransparencyLevel=0,
tint=false, tintStrength=60, bloom=false, vignette=false,
rainbowChar=false, rainbowSpeed=0.5,
auraRing=false, auraRingSize=3.2,
orbitOrbs=false, orbitOrbCount=6, orbitOrbRadius=2.6, orbitOrbSpeed=1.6, orbitOrbSize=0.4,
lightningAura=false, lightningRate=8,
fireFootsteps=false,
butterflies=false, butterflyCount=10,
meteorShower=false, meteorRate=3,
chromaticAberration=false, chromaticStrength=0.6, depthOfField=false,
retroFilter=false, retroStrength=0.7, vhsFilter=false, glitchFilter=false,
screenShake=false, shakeAmount=0.5, sprintFov=false, sprintFovBoost=15,
cameraRoll=false, cameraRollAmount=6,
espEnabled=false, espNames=true, espHealth=true, espDistance=true, espChams=false,
espTeamCheck=false, espMaxDist=500,
combatTargetLock=false, combatAimbot=false, combatSilentAura=false,
combatTeamCheck=true, combatWallCheck=true, combatAimFov=260, combatMaxDistance=500,
combatAuraWalkSpeed=300, combatAuraRadius=2.5, combatAuraFlyHeight=1,
crosshair=false, crosshairStyle="cross", crosshairSize=8, crosshairThickness=2,
crosshairGap=4, crosshairDot=true, crosshairOutline=true, crosshairColorHex="#FFFFFF",
-- Startup UI audio defaults match the supplied settings screen: volume 100, pitch 1.25.
uiSounds=true, uiSoundVolume=90, uiSoundPitch=1.4, uiSoundId="17582213219",
mommyMode=false, customSkyboxId="",
profilePfpId="", -- optional custom Roblox decal/image ID for sidebar and status bar
lyricsInStatusBar=true, smoothLyricsTransition=true, lyricsTransitionDuration=0.6,
lyrics3d=false,
motionBlur=false, motionBlurStrength=1.0,
reflective=false, reflectiveStrength=0.5,
fpsBoost=false,
realistic=false, realisticStrength=1.0,
uiBackground=false, uiBackgroundId="", uiBackgroundTransparency=0.3, overlayShine=false, guiShine=false,
smoothCamera=false, smoothCameraStrength=0.5,
potionsLayout=1, editAnywhere=false,
stretch=false, stretchAmount=0.75,
rainPuddles=false, puddleCount=22, puddleSize=3.5, snowFloor=false, snowRadius=50, snowDepth=0.18,
knifeModel="butterfly", butterflyKnifeSkin="Default", karambitSkin="Default", handOut=true, handEditMode=false, handOffsetX=0.82, handOffsetY=-0.04, handOffsetZ=0.43, handScale=0.4, echoHand=false, fogHand=false,
santaHat=false, santaTransparency=0.35, cape=false, capeLength=4.2, pickaxe=false, pickaxeSkin="Candy Cane", selfChams=false, selfChamsFill=0.55, selfChamsStyle="Foggy", espChamsStyle="Foggy",
charOutline=false, worldOutline=false, outlineRadius=70, outlineThick=0.05, outlineColorHex="#000000", rainRipples=false, rippleRate=28, rippleRadius=45, rippleSize=1.6,
}
local Music = { playing=false, volume=0.5, looped=true, id=nil, name="Nothing playing", artist="" }
local Lyrics = { lines={}, offset=0, auto=true, key=nil, sbKey=nil, barKey=nil, airScale=1.6 }
local Lib = { list={}, file="owo_music.json" }
local Friends = { list={}, favourites={}, chats={}, activeChat=nil, file="owo_friends.json", RELAY_URL="", lastPoll=0 }
Fn.Friends = Friends
local req = (typeof(request)=="function" and request) or (typeof(http_request)=="function" and http_request)
or (typeof(syn)=="table" and syn.request) or (typeof(http)=="table" and http.request) or nil
-- ══════════════════════════════════════════════════════════════
-- HELPERS
-- ══════════════════════════════════════════════════════════════
local RB, RM, RS_ = 14, 10, 7
local EFFECT_COLOR = Color3.fromRGB(100, 200, 255)
local function visualColor(kind)
return (feat.visualColors and feat.visualColors[kind]) or EFFECT_COLOR
end
local ON_ACCENT = Color3.fromRGB(30, 30, 35)
local dragBlockers = {}
local function regRef(i, p, k) ThemeRefs[#ThemeRefs+1] = {inst=i, prop=p, key=k} end
local function applyTheme()
local keep = {}
for _, r in ipairs(ThemeRefs) do
if r.inst and r.inst:IsDescendantOf(game) then
keep[#keep+1] = r
local v = T[r.key]; if v then pcall(function() r.inst[r.prop] = v end) end
end
end
ThemeRefs = keep
if Glass.refreshAll then Glass.refreshAll() end
end
local function new(c, p) local i = Instance.new(c); for k, v in pairs(p or {}) do i[k] = v end; return i end
local function corner(i, r) local c = Instance.new("UICorner"); c.CornerRadius = UDim.new(0, r or RS_); c.Parent = i; return c end
-- A native crescent built from two rounded Frames. Unlike a decal/ImageLabel,
-- this mark renders without asset permissions, thumbnail APIs or font glyphs.
local function moonMark(parent, size, position, tint, cutoutColor, cutoutTransparency, zIndex, name, layoutOrder)
local z = zIndex or 1
local host = new("Frame", {
Name = name or "MoonwareCrescent", Size = UDim2.new(0, size, 0, size),
Position = position or UDim2.new(0, 0, 0, 0), BackgroundTransparency = 1,
BorderSizePixel = 0, ZIndex = z, LayoutOrder = layoutOrder or 0, Parent = parent
})
local outer = new("Frame", {
Name = "MoonOuter", AnchorPoint = Vector2.new(0.5, 0.5),
Position = UDim2.new(0.46, 0, 0.54, 0), Size = UDim2.new(0.78, 0, 0.78, 0),
BackgroundColor3 = tint or T.Text, BackgroundTransparency = 0,
BorderSizePixel = 0, ZIndex = z + 1, Parent = host
})
corner(outer, size)
local cutout = new("Frame", {
Name = "MoonCutout", AnchorPoint = Vector2.new(0.5, 0.5),
Position = UDim2.new(0.70, 0, 0.31, 0), Size = UDim2.new(0.74, 0, 0.74, 0),
BackgroundColor3 = cutoutColor or T.Card,
BackgroundTransparency = cutoutTransparency or 0,
BorderSizePixel = 0, ZIndex = z + 2, Parent = host
})
corner(cutout, size)
return host, outer, cutout
end
local function gradient(i, c1, c2, rot) local g = Instance.new("UIGradient"); g.Color = ColorSequence.new(c1, c2); g.Rotation = rot or 0; g.Parent = i; return g end
local function moonwareLogo(parent, size, position, tint, fallbackColor, fallbackTransparency, zIndex, name)
local host = new("Frame", {
Name=(name or "MoonwareLogo") .. "Host", Size=UDim2.new(0,size,0,size),
Position=position or UDim2.new(), BackgroundTransparency=1,
BorderSizePixel=0, ZIndex=zIndex or 1, Parent=parent
})
local fallback = moonMark(host, size*0.76, UDim2.new(0.12,0,0.12,0), tint or T.Text,
fallbackColor or T.Card, fallbackTransparency or 0, (zIndex or 1)+1, (name or "MoonwareLogo") .. "Fallback")
local image = new("ImageLabel", {
Name=(name or "MoonwareLogo") .. "Image", Size=UDim2.fromScale(1,1),
BackgroundTransparency=1, Image="", ImageColor3=Color3.new(1,1,1),
ScaleType=Enum.ScaleType.Fit, Visible=false, ZIndex=(zIndex or 1)+3, Parent=host
})
applyRobloxAssetIcon(image, "88265765726960", fallback)
return host, image, fallback
end
local function tween(o, t, p, style, dir)
local info = TweenInfo.new(sdur(t), style or Enum.EasingStyle.Quint, dir or Enum.EasingDirection.Out)
local x = TS:Create(o, info, p); x:Play(); return x
end
local function hexToColor(h)
h = tostring(h or ""):gsub("#",""):gsub("%s","")
if #h ~= 6 or not h:match("^%x%x%x%x%x%x$") then return nil end
return Color3.fromRGB(tonumber(h:sub(1,2),16), tonumber(h:sub(3,4),16), tonumber(h:sub(5,6),16))
end
local function colorToHex(c) return string.format("#%02X%02X%02X", math.floor(c.R*255+0.5), math.floor(c.G*255+0.5), math.floor(c.B*255+0.5)) end
local function stroke(p, t, tr, c, skip)
local s = Instance.new("UIStroke"); s.Color = c or T.Line; s.Thickness = t or 1
s.Transparency = tr or 0.6; s.ApplyStrokeMode = Enum.ApplyStrokeMode.Border; s.Parent = p
if not skip then
if not c or c == T.Line then regRef(s, "Color", "Line") end
local g = Instance.new("UIGradient"); g.Rotation = 45
g.Transparency = NumberSequence.new({NumberSequenceKeypoint.new(0,0),NumberSequenceKeypoint.new(0.35,0.8),NumberSequenceKeypoint.new(0.65,0.8),NumberSequenceKeypoint.new(1,0.05)})
g.Enabled = Glass.on; g.Parent = s
GlassStrokes[#GlassStrokes+1] = {s=s, g=g, o=s.Transparency}
if Glass.on then s.Transparency = 0.2 end
end
return s
end
local function addSheen(f)
local g = Instance.new("UIGradient"); g.Name="OwoGlass"; g.Rotation=35
g.Color = ColorSequence.new(Color3.fromRGB(255,255,255), Color3.fromRGB(205,218,245))
g.Transparency = NumberSequence.new({NumberSequenceKeypoint.new(0,0),NumberSequenceKeypoint.new(0.5,0.12),NumberSequenceKeypoint.new(1,0.3)})
g.Enabled = Glass.on; g.Parent = f; GlassGrads[#GlassGrads+1] = g
end
local function regCard(f) table.insert(UI.cards, f); addSheen(f); UI.n += 1 end
-- gate(): optional function that must return true before a drag may start (widget edit mode)
-- onClick(): optional function called on a click without movement
local function drag(f, h, gate, onClick)
h = h or f
local d, s, sp, moved
local function isPress(i) return i.UserInputType == Enum.UserInputType.MouseButton1 or i.UserInputType == Enum.UserInputType.Touch end
h.InputBegan:Connect(function(i)
if isPress(i) then
if gate and not gate() then return end
local blocker = dragBlockers[f]
if blocker and blocker(i.Position) then return end
d = true; moved = false; s = i.Position; sp = f.Position
if Fn.dragState then Fn.dragState(f, true) end
end
end)
UIS.InputChanged:Connect(function(i)
if d and (i.UserInputType == Enum.UserInputType.MouseMovement or i.UserInputType == Enum.UserInputType.Touch) then
local dd = i.Position - s
if not moved and dd.Magnitude > 4 then moved = true end
if moved or not onClick then
f.Position = UDim2.new(sp.X.Scale, sp.X.Offset + dd.X, sp.Y.Scale, sp.Y.Offset + dd.Y)
end
end
end)
UIS.InputEnded:Connect(function(i)
if d and isPress(i) then
d = false
if Fn.dragState then Fn.dragState(f, false) end
if onClick and not moved then pcall(onClick) end
end
end)
end
local glassBlur = new("BlurEffect", {Name="OwoGlassBlur", Size=0, Enabled=false, Parent=Lighting})
Fn.dragState = function() end
Fn.syncGlass = function() end
-- ══════════════════════════════════════════════════════════════
-- UI SOUNDS
-- ══════════════════════════════════════════════════════════════
local CHIME = "rbxasset://sounds/electronicpingshort.wav"
-- Each sound is a soft chime/arpeggio: notes = {pitch ratio, delay in seconds, relative volume}.
-- Ratios follow a major chord (1, 1.26, 1.5, 2), so everything stays in tune.
local UISounds = {
enabled=true, volume=0.9, pitch=1.4, customId="rbxassetid://17582213219",
mommyMode=false, mommyOpenId="rbxassetid://101081718281945", mommyClickId="rbxassetid://117959044259240",
pools={}, lastPlayed={}, normalPitch=1.4,
defs = {
hover = {id=CHIME, base=1.9, v=0.020, notes={{1.0,0,1}}},
click = {id=CHIME, base=1.25, v=0.090, notes={{1.5,0,1},{2.0,0.035,0.6}}},
toggleOn = {id=CHIME, base=1.0, v=0.085, notes={{1.0,0,1},{1.26,0.055,0.9},{1.5,0.11,0.8}}},
toggleOff = {id=CHIME, base=1.0, v=0.075, notes={{1.5,0,0.9},{1.0,0.065,0.8}}},
menuOpen = {id=CHIME, base=0.9, v=0.085, notes={{1.0,0,1},{1.26,0.06,0.9},{1.5,0.12,0.8},{2.0,0.18,0.7}}},
menuClose = {id=CHIME, base=0.9, v=0.075, notes={{2.0,0,0.8},{1.5,0.06,0.8},{1.0,0.12,0.9}}},
tabSwitch = {id=CHIME, base=1.3, v=0.060, notes={{1.26,0,1}}},
slider = {id=CHIME, base=2.2, v=0.012, notes={{1.0,0,1}}},
notify = {id=CHIME, base=1.0, v=0.100, notes={{1.5,0,1},{2.0,0.10,0.9}}},
error = {id=CHIME, base=0.7, v=0.090, notes={{1.0,0,1},{0.84,0.09,1}}},
sparkle = {id=CHIME, base=2.2, v=0.015, notes={{1.0,0,1}}},
},
rateLimits={ hover=1/14, slider=1/24, click=1/20, sparkle=1/20, tabSwitch=1/12 },
layered={},
}
do
UISounds.folder = new("Folder", {Name="OwoUISounds", Parent=SoundService})
for name, def in pairs(UISounds.defs) do
local pool = {}
for i = 1, #def.notes * 2 do
pool[i] = new("Sound", {Name=name.."_"..i, SoundId=UISounds.customId or def.id, Volume=0, PlaybackSpeed=1, Parent=UISounds.folder})
end
UISounds.pools[name] = {pool=pool, idx=1}
end
end
local function playUiSound(name, volMul)
if not UISounds.enabled then return end
local def = UISounds.defs[name]; if not def then return end
local rl = UISounds.rateLimits[name]
if rl then
local now = os.clock()
if UISounds.lastPlayed[name] and now - UISounds.lastPlayed[name] < rl then return end
UISounds.lastPlayed[name] = now
end
local entry = UISounds.pools[name]; if not entry then return end
local notes = (UISounds.mommyMode and (name == "click" or name == "menuOpen")) and {{1.0,0,1}} or (UISounds.customId and {{1.0,0,1}} or def.notes)
for _, n in ipairs(notes) do
local s = entry.pool[entry.idx]; entry.idx = entry.idx % #entry.pool + 1
local function go()
if UISounds.mommyMode then
if name == "menuOpen" then s.SoundId = UISounds.mommyOpenId
elseif name == "click" then s.SoundId = UISounds.mommyClickId
else s.SoundId = UISounds.customId or def.id end
else
s.SoundId = UISounds.customId or def.id
end
s.Volume = math.min(def.v * (UISounds.customId and 3.5 or 1) * n[3] * (volMul or 1) * UISounds.volume, 1)
s.PlaybackSpeed = (UISounds.mommyMode and 1 or (UISounds.customId and 1 or def.base * n[1])) * UISounds.pitch
s.TimePosition = 0; s:Play()
end
if n[2] > 0 then task.delay(n[2], go) else go() end
end
end
local function playUiSoundLayered(name)
playUiSound(name)
if UISounds.layered[name] then task.delay(0.025, function() playUiSound("sparkle", 0.5) end) end
end
Fn.playUiSound = playUiSound
Fn.playUiSoundLayered = playUiSoundLayered
-- Mommy Mode routes every GUI pointer click through the custom click sound.
local mommyGuiClickService = game:GetService("GuiService")
UIS.InputBegan:Connect(function(input)
if not UISounds.enabled or not UISounds.mommyMode then return end
if input.UserInputType ~= Enum.UserInputType.MouseButton1 and input.UserInputType ~= Enum.UserInputType.Touch then return end
local hits = mommyGuiClickService:GetGuiObjectsAtPosition(input.Position.X, input.Position.Y)
if hits and #hits > 0 then playUiSound("click") end
end)
Fn.setUiSoundId = function(newId)
newId = tostring(newId or ""):gsub("%s","")
local custom = nil
if newId ~= "" then
if not (newId:match("^rbxassetid://%d+$") or newId:match("^%d+$")) then return end
custom = newId:match("^rbxassetid://") and newId or ("rbxassetid://" .. newId)
end
UISounds.customId = custom
feat.uiSoundId = custom and (custom:gsub("rbxassetid://","")) or ""
for name, entry in pairs(UISounds.pools) do
local id = custom or UISounds.defs[name].id
for _, s in ipairs(entry.pool) do s.SoundId = id end
end
end
-- ══════════════════════════════════════════════════════════════
-- HOVER FX (eased colour, soft lift, accent stroke, press-down)
-- ══════════════════════════════════════════════════════════════
local Hover = { items = {}, inset = game:GetService("GuiService") }
-- Hover is driven by ONE render loop that reads the mouse position and eases a 0..1 value per
-- item. Nothing depends on MouseEnter/MouseLeave (which lag, skip and leave stuck highlights
-- when the mouse moves fast), so entering AND leaving are always smooth and never stick.
function Hover.add(obj, apply, opts)
opts = opts or {}
local item = {obj=obj, apply=apply, a=0, over=false, inSpeed=opts.inSpeed or 18, outSpeed=opts.outSpeed or 12}
Hover.items[#Hover.items+1] = item
obj.Destroying:Connect(function() item.dead = true end)
return item
end
local function hoverVisible(obj, mouse)
local a = obj
while a and a ~= game do
if a:IsA("GuiObject") then
if not a.Visible then return false end
if a:IsA("ScrollingFrame") then
local p, sz = a.AbsolutePosition, a.AbsoluteSize
if mouse.X < p.X or mouse.Y < p.Y or mouse.X > p.X + sz.X or mouse.Y > p.Y + sz.Y then return false end
end
elseif a:IsA("ScreenGui") and not a.Enabled then
return false
end
a = a.Parent
end
return true
end
RS.RenderStepped:Connect(function(dt)
local mouse = UIS:GetMouseLocation() - Hover.inset:GetGuiInset()
local pressed = UIS:IsMouseButtonPressed(Enum.UserInputType.MouseButton1)
local list = Hover.items
for i = #list, 1, -1 do
local it = list[i]
local obj = it.obj
if it.dead or not obj.Parent then
table.remove(list, i)
else
local want = false
if UI.isOpen then
local p, sz = obj.AbsolutePosition, obj.AbsoluteSize
if sz.X > 0 and mouse.X >= p.X and mouse.Y >= p.Y and mouse.X <= p.X + sz.X and mouse.Y <= p.Y + sz.Y
and hoverVisible(obj, mouse) then want = true end
end
if want and not it.over then playUiSound("hover") end
it.over = want
if want or it.a > 0.001 then
it.a = slerp(it.a, want and 1 or 0, dt, want and it.inSpeed or it.outSpeed)
it.press = slerp(it.press or 0, (want and pressed) and 1 or 0, dt, 30)
if it.a < 0.002 and not want then it.a = 0; it.press = 0; it.settled = false end
it.apply(it.a, it.press)
it.wasActive = true
elseif it.wasActive then
it.wasActive = false
it.apply(0, 0)
end
end
end
end)
local function hoverFx(obj, opts)
-- Colour / border / accent bar only. No size changes, so neighbouring cards never move.
opts = opts or {}
local base, hover = opts.base or "Card", opts.hover or "Hover"
local st = obj:FindFirstChildOfClass("UIStroke")
local st0, stc0 = st and st.Transparency or 0.55, nil
local bar = new("Frame", {
Name="OwoHoverBar", AnchorPoint=Vector2.new(0,0.5), Position=UDim2.new(0,0,0.5,0),
Size=UDim2.new(0,3,0,0), BackgroundColor3=T.Accent, BackgroundTransparency=0.1,
BorderSizePixel=0, ZIndex=6, Active=false, Parent=obj
})
corner(bar, 2); regRef(bar, "BackgroundColor3", "Accent")
local resting = true
Hover.add(obj, function(a, press)
if a <= 0 then
if not resting then
resting = true
obj.BackgroundColor3 = T[base]
bar.Size = UDim2.new(0,3,0,0)
if st then st.Transparency = st0; st.Color = T.Line end
end
return
end
if resting then resting = false; if st then st0 = st.Transparency end end
local c = T[base]:Lerp(T[hover], a)
if press > 0 then c = c:Lerp(T.Accent, 0.10 * press) end
obj.BackgroundColor3 = c
bar.Size = UDim2.new(0, 3, 0, math.floor(obj.AbsoluteSize.Y * 0.5 * a + 0.5))
if st then
st.Transparency = st0 + (math.max(st0 - 0.28, 0.12) - st0) * a
st.Color = T.Line:Lerp(T.Accent2, a)
end
end)
end
-- ══════════════════════════════════════════════════════════════
-- LIQUID GLASS v2
-- Layered frost + specular gloss + a rim light that follows your cursor,
-- plus a real blur of the world behind the menu.
-- ══════════════════════════════════════════════════════════════
do
local G = {panels = {}}
Glass.G = G
local clamp, exp = math.clamp, math.exp
local function kp(t, v) return NumberSequenceKeypoint.new(t, clamp(v, 0, 1)) end
Glass.styles = {
Frosted = {clarity=62, blur=10, shine=0.55, tint=0.00},
Clear = {clarity=88, blur=4, shine=0.80, tint=0.00},
Tinted = {clarity=70, blur=8, shine=0.50, tint=0.40},
Crystal = {clarity=80, blur=14, shine=1.00, tint=0.12},
Midnight = {clarity=42, blur=12, shine=0.35, tint=0.20},
}
Glass.styleOrder = {"Frosted","Clear","Tinted","Crystal","Midnight"}
Glass.winT = function() return 0.25 + (clamp(Glass.clarity, 30, 100) - 30) / 70 * 0.55 end
function G.decorate(f, opts)
opts = opts or {}
if G.panels[f] then return G.panels[f] end
local cr = f:FindFirstChildOfClass("UICorner")
local function rc(o) if cr then new("UICorner", {CornerRadius=cr.CornerRadius, Parent=o}) end end
local frost = new("Frame", {Name="OwoGlassFrost", Size=UDim2.fromScale(1,1), BackgroundColor3=Color3.new(1,1,1), BorderSizePixel=0, ZIndex=0, Visible=false, Parent=f}); rc(frost)
local fg = new("UIGradient", {Rotation=90, Parent=frost})
local gloss = new("Frame", {Name="OwoGlassGloss", Position=UDim2.new(0,1,0,1), Size=UDim2.new(1,-2,0.5,0), BackgroundColor3=Color3.new(1,1,1), BorderSizePixel=0, ZIndex=0, Visible=false, Parent=f}); rc(gloss)
local gg = new("UIGradient", {Rotation=90, Parent=gloss})
local rim = new("Frame", {Name="OwoGlassRim", Size=UDim2.fromScale(1,1), BackgroundTransparency=1, BorderSizePixel=0, ZIndex=400, Visible=false, Parent=f}); rc(rim)
local st = new("UIStroke", {Color=Color3.new(1,1,1), Thickness=1.5, ApplyStrokeMode=Enum.ApplyStrokeMode.Border, Parent=rim})
local rg = new("UIGradient", {Rotation=45, Parent=st})
local P = {f=f, frost=frost, fg=fg, gloss=gloss, gg=gg, rim=rim, stroke=st, rg=rg, vx=0.7, vy=0.7, always=opts.always, small=opts.small}
G.panels[f] = P
f.Destroying:Connect(function() G.panels[f] = nil end)
return P
end
local function refresh(P)
if not P.f.Parent then G.panels[P.f] = nil; return end
local on = (Glass.on or P.always) and not P.f:GetAttribute("LBare")
P.frost.Visible, P.gloss.Visible, P.rim.Visible = on, on, on
if not on then return end
local s, tint = Glass.shine, Glass.tint
local k = P.small and 0.7 or 1
P.frost.BackgroundColor3 = Color3.new(1,1,1):Lerp(T.Accent, tint)
P.fg.Transparency = NumberSequence.new({kp(0, 1-0.20*s*k), kp(0.55, 1-0.035*s*k), kp(1, 1-0.10*s*k)})
P.gg.Transparency = NumberSequence.new({kp(0, 1-0.30*s*k), kp(1, 1)})
P.stroke.Thickness = 0.7 + Glass.refraction * 0.35
P.rg.Color = ColorSequence.new(Color3.new(1,1,1):Lerp(T.Accent, tint*0.6))
local bright = clamp(0.05 + (1-s)*0.4, 0, 0.7)
P.rg.Transparency = NumberSequence.new({kp(0, bright), kp(0.3, 0.93), kp(0.7, 0.93), kp(1, bright+0.1)})
if P.always then P.f.BackgroundTransparency = Glass.winT() end
end
function G.refreshAll() for _, P in pairs(G.panels) do refresh(P) end end
Glass.refreshAll = G.refreshAll
local t0, blurSize = os.clock(), 0
RS.RenderStepped:Connect(function(dt)
local m = UIS:GetMouseLocation()
local tnow = os.clock() - t0
for f, P in pairs(G.panels) do
if (Glass.on or P.always) and f.Parent and f.Visible then
local abs = f.AbsoluteSize
if abs.X > 0 then
local c = f.AbsolutePosition + abs / 2
local dx, dy = m.X - c.X, m.Y - c.Y
local len = math.sqrt(dx*dx + dy*dy)
local tx, ty = 0.7, 0.7
if Glass.anim and len > 1 then tx, ty = dx/len, dy/len end
local a = 1 - exp(-dt * (Glass.anim and 7 or 12))
P.vx += (tx - P.vx) * a; P.vy += (ty - P.vy) * a
local rot = math.deg(math.atan2(P.vy, P.vx))
if Glass.anim then rot += 10 * math.sin(tnow * 0.8 + abs.X * 0.01) end
P.rg.Rotation = rot
end
end
end
local target = (Glass.on and Glass.worldBlur and UI.isOpen) and Glass.blur or 0
blurSize = blurSize + (target - blurSize) * (1 - exp(-dt * 8))
glassBlur.Size = blurSize
glassBlur.Enabled = blurSize > 0.1
end)
end
-- ══════════════════════════════════════════════════════════════
-- NOTIFICATIONS
-- ══════════════════════════════════════════════════════════════
local notify
do
local ng = new("ScreenGui", {Name="OwoNotify",ResetOnSpawn=false,IgnoreGuiInset=true,ZIndexBehavior=Enum.ZIndexBehavior.Sibling,Parent=pg})
local holder = new("Frame", {Size=UDim2.new(0,280,0.6,0),Position=UDim2.new(1,-300,0,20),BackgroundTransparency=1,Parent=ng})
new("UIListLayout", {Padding=UDim.new(0,6),SortOrder=Enum.SortOrder.LayoutOrder,Parent=holder})
local order = 0
notify = function(title, msg, good)
order += 1
playUiSoundLayered(good == false and "error" or "notify")
local wrap = new("Frame", {Size=UDim2.new(1,0,0,56),BackgroundTransparency=1,LayoutOrder=order,Parent=holder})
local c = new("Frame", {Size=UDim2.new(1,0,1,0),Position=UDim2.new(0,46,0,0),BackgroundColor3=T.Card,BackgroundTransparency=1,BorderSizePixel=0,Parent=wrap})
corner(c, RM); stroke(c, 1, 0.7, T.Line, true)
local bad = (good == false)
local bar = new("Frame", {Size=UDim2.new(0,3,1,-16),Position=UDim2.new(0,6,0,8),BackgroundColor3=(bad and T.Bad or T.Accent),BorderSizePixel=0,Parent=c})
corner(bar, 2); gradient(bar, (bad and T.Bad or T.Accent), (bad and T.Bad or T.Accent2), 90)
-- Original Moonware decal in notifications, with a native crescent
-- fallback if Roblox blocks the image for this experience.
local notifyFallback, notifyMoonOuter, notifyMoonCutout = moonMark(
c, 24, UDim2.new(0,14,0.5,-12), T.Text, T.Card, 1, 4, "MoonwareNotificationFallback"
)
local notifyLogo = new("ImageLabel", {
Name="MoonwareNotificationLogo", Size=UDim2.new(0,24,0,24),
Position=UDim2.new(0,14,0.5,-12), BackgroundTransparency=1,
Image="", ImageColor3=Color3.new(1,1,1), ScaleType=Enum.ScaleType.Fit,
Visible=false, ZIndex=7, Parent=c
})
applyRobloxAssetIcon(notifyLogo, "88265765726960", notifyFallback)
notifyMoonOuter.BackgroundTransparency = 1
local tL = new("TextLabel", {BackgroundTransparency=1,Position=UDim2.new(0,48,0,10),Size=UDim2.new(1,-56,0,16),Font=Enum.Font.GothamBold,Text=title,TextColor3=T.Text,TextSize=12,TextTransparency=1,TextXAlignment=Enum.TextXAlignment.Left,Parent=c})
local mL = new("TextLabel", {BackgroundTransparency=1,Position=UDim2.new(0,48,0,28),Size=UDim2.new(1,-56,0,20),Font=Enum.Font.Gotham,Text=msg,TextColor3=T.Dim,TextSize=11,TextTransparency=1,TextXAlignment=Enum.TextXAlignment.Left,TextTruncate=Enum.TextTruncate.AtEnd,Parent=c})
tween(c, 0.3, {BackgroundTransparency=TR.Notify, Position=UDim2.new(0,0,0,0)}, Enum.EasingStyle.Back)
tween(notifyMoonOuter, 0.3, {BackgroundTransparency=0})
tween(notifyMoonCutout, 0.3, {BackgroundTransparency=TR.Notify})
tween(tL, 0.3, {TextTransparency=0}); tween(mL, 0.3, {TextTransparency=0})
task.delay(2.8, function()
tween(c, 0.22, {BackgroundTransparency=1, Position=UDim2.new(0,46,0,0)})
tween(notifyMoonOuter, 0.22, {BackgroundTransparency=1})
tween(notifyMoonCutout, 0.22, {BackgroundTransparency=1})
tween(notifyLogo, 0.22, {ImageTransparency=1})
tween(tL, 0.22, {TextTransparency=1}); tween(mL, 0.22, {TextTransparency=1})
task.wait(0.26); wrap:Destroy()
end)
end
end
-- ══════════════════════════════════════════════════════════════
-- KEYBINDS
-- ══════════════════════════════════════════════════════════════
local openKeyPrompt
do
local promptGui = new("ScreenGui", {Name="OwoPrompt",ResetOnSpawn=false,IgnoreGuiInset=true,ZIndexBehavior=Enum.ZIndexBehavior.Sibling,Parent=pg})
openKeyPrompt = function(name)
for _, c in ipairs(promptGui:GetChildren()) do c:Destroy() end
local bg = new("Frame", {Size=UDim2.new(1,0,1,0),BackgroundColor3=Color3.new(0,0,0),BackgroundTransparency=0.5,BorderSizePixel=0,ZIndex=100,Parent=promptGui})
local box = new("Frame", {Size=UDim2.new(0,340,0,120),Position=UDim2.new(0.5,-170,0.5,-60),BackgroundColor3=T.Panel,BackgroundTransparency=0.05,BorderSizePixel=0,ZIndex=101,Parent=bg})
corner(box, RB); stroke(box, 1, 0.5, T.Line, true)
new("Frame",{Size=UDim2.new(1,0,0,3),BackgroundColor3=T.Accent,BorderSizePixel=0,ZIndex=102,Parent=box})
new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,0,0,20),Size=UDim2.new(1,0,0,22),Font=Enum.Font.GothamBold,Text="PRESS A KEY",TextColor3=T.Text,TextSize=14,ZIndex=102,Parent=box})
new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,0,0,48),Size=UDim2.new(1,0,0,18),Font=Enum.Font.GothamMedium,Text=name,TextColor3=T.Accent,TextSize=12,ZIndex=102,Parent=box})
new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,0,0,78),Size=UDim2.new(1,0,0,16),Font=Enum.Font.Gotham,Text="ESC cancel • BACKSPACE clear",TextColor3=T.Muted,TextSize=10,ZIndex=102,Parent=box})
local cn
cn = UIS.InputBegan:Connect(function(i, gp)
if i.KeyCode == Enum.KeyCode.Escape then cn:Disconnect(); bg:Destroy()
elseif i.KeyCode == Enum.KeyCode.Backspace then
if Keybinds[name] then Keybinds[name].key = nil end
cn:Disconnect(); bg:Destroy(); notify("Keybind", name.." cleared")
elseif not gp and i.KeyCode ~= Enum.KeyCode.Unknown then
if Keybinds[name] then Keybinds[name].key = i.KeyCode end
cn:Disconnect(); bg:Destroy(); notify("Keybind", name.." → "..i.KeyCode.Name)
end
end)
end
UIS.InputBegan:Connect(function(i, gp)
if gp then return end
if i.KeyCode == Enum.KeyCode.RightShift then return end
for _, k in pairs(Keybinds) do
if k.key and i.KeyCode == k.key then
if k.isToggle then k.setState(not k.getState())
elseif k.fire then pcall(k.fire) end
break
end
end
end)
end
-- ══════════════════════════════════════════════════════════════
-- MOVEMENT
-- ══════════════════════════════════════════════════════════════
do
local flyBV, flyVel = nil, Vector3.zero
Fn.startFly = function()
local char = player.Character
local hrp = char and char:FindFirstChild("HumanoidRootPart")
if not hrp then notify("Fly","Character not ready",false); return end
feat.fly = true; flyVel = Vector3.zero
if flyBV then flyBV:Destroy() end
flyBV = new("BodyVelocity", {MaxForce=Vector3.new(1e5,1e5,1e5), Velocity=Vector3.zero, P=1250, Parent=hrp})
local hum = char:FindFirstChildOfClass("Humanoid")
if hum then hum.PlatformStand = true end
notify("Fly","ON")
end
Fn.stopFly = function()
feat.fly = false
if flyBV then flyBV:Destroy(); flyBV = nil end
local char = player.Character
local hum = char and char:FindFirstChildOfClass("Humanoid")
if hum then hum.PlatformStand = false end
flyVel = Vector3.zero
notify("Fly","OFF",false)
end
player.CharacterAdded:Connect(function() if feat.fly then task.wait(0.5); Fn.startFly() end end)
RS.Heartbeat:Connect(function(dt)
if not flyBV then return end
local char = player.Character
local hrp = char and char:FindFirstChild("HumanoidRootPart")
if not hrp then flyBV:Destroy(); flyBV = nil; return end
if flyBV.Parent ~= hrp then flyBV.Parent = hrp end
local cf = camera.CFrame
local camLook = cf.LookVector
if camLook.Magnitude > 0.01 then
camLook = camLook.Unit
local clamped = Vector3.new(camLook.X, math.clamp(camLook.Y, -feat.flyPitchAmount, feat.flyPitchAmount), camLook.Z)
if clamped.Magnitude > 0.01 then hrp.CFrame = CFrame.new(hrp.Position, hrp.Position + clamped) end
end
local look, right = cf.LookVector, cf.RightVector
local input = Vector3.zero
if UIS:IsKeyDown(Enum.KeyCode.W) then input += look end
if UIS:IsKeyDown(Enum.KeyCode.S) then input -= look end
if UIS:IsKeyDown(Enum.KeyCode.A) then input -= right end
if UIS:IsKeyDown(Enum.KeyCode.D) then input += right end
if UIS:IsKeyDown(Enum.KeyCode.Space) then input += Vector3.new(0,1,0)*feat.flyVerticalBoost end
if UIS:IsKeyDown(Enum.KeyCode.LeftControl) then input -= Vector3.new(0,1,0)*feat.flyVerticalBoost end
if input.Magnitude > 1 then input = input.Unit end
local targetVel = input * feat.flySpeed
local rate = (input.Magnitude > 0.05) and feat.flyAccel or feat.flyDamping
flyVel = flyVel:Lerp(targetVel, math.clamp(rate*dt, 0, 1))
flyBV.Velocity = flyVel
end)
RS.Stepped:Connect(function()
if not feat.noclip then return end
local c = player.Character; if not c then return end
for _, p in ipairs(c:GetDescendants()) do if p:IsA("BasePart") and p.CanCollide then p.CanCollide = false end end
end)
UIS.JumpRequest:Connect(function()
if feat.infJump then
local h = player.Character and player.Character:FindFirstChildOfClass("Humanoid")
if h then h:ChangeState(Enum.HumanoidStateType.Jumping) end
end
end)
end
-- ══════════════════════════════════════════════════════════════
-- FREE CAM
-- ══════════════════════════════════════════════════════════════
do
local fcConn, fcYaw, fcPitch = nil, 0, 0
local fcPos = Vector3.zero
local fcSaved = {anchored=false, walkSpeed=16, jumpPower=50}
local function freeze()
local char = player.Character; if not char then return end
local hrp = char:FindFirstChild("HumanoidRootPart"); local hum = char:FindFirstChildOfClass("Humanoid")
if hrp then fcSaved.anchored = hrp.Anchored; hrp.AssemblyLinearVelocity = Vector3.zero; hrp.AssemblyAngularVelocity = Vector3.zero; hrp.Anchored = true end
if hum then fcSaved.walkSpeed = hum.WalkSpeed; fcSaved.jumpPower = hum.JumpPower; hum.WalkSpeed = 0; hum.JumpPower = 0; hum.AutoRotate = false end
end
local function unfreeze()
local char = player.Character; if not char then return end
local hrp = char:FindFirstChild("HumanoidRootPart"); local hum = char:FindFirstChildOfClass("Humanoid")
if hrp then hrp.Anchored = fcSaved.anchored end
if hum then hum.WalkSpeed = feat.walkSpeed or fcSaved.walkSpeed; hum.JumpPower = feat.jumpPower or fcSaved.jumpPower; hum.AutoRotate = true end
end
Fn.startFreeCam = function()
local kb = Keybinds["FreeCam"]
if not (kb and kb.key) then notify("Free Cam","Set a keybind first",false); return false end
local x, y = camera.CFrame:ToEulerAnglesYXZ(); fcYaw, fcPitch = y, x
fcPos = camera.CFrame.Position
camera.CameraType = Enum.CameraType.Scriptable
feat.freeCam = true
UIS.MouseBehavior = Enum.MouseBehavior.LockCenter
freeze()
fcConn = RS.RenderStepped:Connect(function(dt)
local d = Vector3.zero
local cf = CFrame.new(fcPos) * CFrame.Angles(0, fcYaw, 0)
if UIS:IsKeyDown(Enum.KeyCode.W) then d += cf.LookVector end
if UIS:IsKeyDown(Enum.KeyCode.S) then d -= cf.LookVector end
if UIS:IsKeyDown(Enum.KeyCode.A) then d -= cf.RightVector end
if UIS:IsKeyDown(Enum.KeyCode.D) then d += cf.RightVector end
if UIS:IsKeyDown(Enum.KeyCode.Space) then d += Vector3.new(0,1,0) end
if UIS:IsKeyDown(Enum.KeyCode.LeftControl) then d -= Vector3.new(0,1,0) end
if d.Magnitude > 0 then fcPos += d.Unit * feat.freeCamSpeed * dt end
camera.CFrame = CFrame.new(fcPos) * CFrame.Angles(0, fcYaw, 0) * CFrame.Angles(fcPitch, 0, 0)
end)
notify("Free Cam","ON — press your keybind to exit")
return true
end
Fn.stopFreeCam = function()
feat.freeCam = false
if fcConn then fcConn:Disconnect(); fcConn = nil end
camera.CameraType = Enum.CameraType.Custom
UIS.MouseBehavior = Enum.MouseBehavior.Default
unfreeze()
notify("Free Cam","OFF",false)
end
UIS.InputChanged:Connect(function(i)
if not fcConn then return end
if i.UserInputType == Enum.UserInputType.MouseMovement then
fcYaw = fcYaw - math.rad(i.Delta.X)*1.5
fcPitch = math.clamp(fcPitch - math.rad(i.Delta.Y)*1.5, math.rad(-89), math.rad(89))
end
end)
player.CharacterAdded:Connect(function() if feat.freeCam then task.wait(0.6); if feat.freeCam then freeze() end end end)
end
-- ══════════════════════════════════════════════════════════════
-- CAMERA FX (smoothed)
-- ══════════════════════════════════════════════════════════════
do
local shakeOff, shakeDecay, baseRoll = CFrame.new(), 0, 0
local sFovAdd = 0
local smoothedCF = camera.CFrame
Fn.triggerShake = function(amount)
if not feat.screenShake then return end
local style = feat.visualStyles.screenShake or "Default"
local mult = style == "Impact Punch" and 1.55 or (style == "Micro Jitter" and 0.35 or (style == "Roll Wave" and 0.75 or 1))
shakeDecay = math.max(shakeDecay, amount * feat.shakeAmount * mult)
end
RS.RenderStepped:Connect(function(dt)
if shakeDecay > 0.001 then
local shakeStyle = feat.visualStyles.screenShake or "Default"
local s = shakeDecay * (shakeStyle == "Micro Jitter" and 0.22 or 0.6)
local roll = shakeStyle == "Roll Wave" and math.sin(os.clock()*18)*shakeDecay*0.035 or (math.random()-0.5)*shakeDecay*0.08
shakeOff = CFrame.new((math.random()-0.5)*s, (math.random()-0.5)*s, 0) * CFrame.Angles((math.random()-0.5)*shakeDecay*0.05, (math.random()-0.5)*shakeDecay*0.05, roll)
shakeDecay = shakeDecay * math.clamp(1 - dt*(shakeStyle == "Impact Punch" and 12 or 8), 0, 1)
else shakeOff = CFrame.new(); shakeDecay = 0 end
local hum = player.Character and player.Character:FindFirstChildOfClass("Humanoid")
local hrp = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
local sprinting = false
if hum and hrp and hum.MoveDirection.Magnitude > 0.1 then
local v = hrp.AssemblyLinearVelocity
if Vector3.new(v.X, 0, v.Z).Magnitude > feat.walkSpeed * 0.9 then sprinting = true end
end
local tb = (feat.sprintFov and sprinting) and feat.sprintFovBoost or 0
sFovAdd = slerp(sFovAdd, tb, dt, 4)
local roll = 0
if feat.cameraRoll and hum then roll = hum.MoveDirection:Dot(camera.CFrame.RightVector) * math.rad(feat.cameraRollAmount) end
baseRoll = slerp(baseRoll, roll, dt, 6)
if feat.sprintFov then camera.FieldOfView = math.clamp(70 + sFovAdd, 20, 120) end
if (feat.screenShake and shakeDecay > 0) or feat.cameraRoll then
camera.CFrame = camera.CFrame * shakeOff * CFrame.Angles(0, 0, baseRoll)
end
-- Smooth camera motion
if feat.smoothCamera and not feat.freeCam then
local cur = camera.CFrame
local target = cur
smoothedCF = smoothedCF:Lerp(target, 1 - math.exp(-dt * 20 * feat.smoothCameraStrength * Smooth.level))
camera.CFrame = smoothedCF
else
smoothedCF = camera.CFrame
end
end)
end
-- ══════════════════════════════════════════════════════════════
-- STRETCHED RESOLUTION (4:3 look)
-- Squashes the camera vertically so everything looks wider, like stretched res.
-- 0.75 = 4:3 on a 16:9 screen, 0.71 = 5:4, 0.90 = 16:10
-- ══════════════════════════════════════════════════════════════
do
pcall(function() RS:UnbindFromRenderStep("OwoStretch") end)
RS:BindToRenderStep("OwoStretch", Enum.RenderPriority.Camera.Value + 50, function()
if not feat.stretch then return end
local cam = workspace.CurrentCamera
local k = math.clamp(feat.stretchAmount or 0.75, 0.3, 1)
cam.CFrame = cam.CFrame * CFrame.new(0, 0, 0, 1, 0, 0, 0, k, 0, 0, 0, 1)
end)
end
-- ══════════════════════════════════════════════════════════════
-- VFX
-- ══════════════════════════════════════════════════════════════
do
local vfxObj = {}
local function clearVfx()
for _, o in pairs(vfxObj) do
if typeof(o) == "Instance" then pcall(function() o:Destroy() end)
elseif typeof(o) == "RBXScriptConnection" then pcall(function() o:Disconnect() end) end
end
vfxObj = {}
end
-- flat glowing shockwave ring (used by jump / landing circles)
local function shock(pos, col, size, thick, life, style)
style = style or "Double Shockwave"
local p = new("Part",{Anchored=true,CanCollide=false,CanQuery=false,CanTouch=false,CastShadow=false,Transparency=1,Size=Vector3.new(size*0.2,0.05,size*0.2),CFrame=CFrame.new(pos),Parent=workspace})
local sg = new("SurfaceGui",{Face=Enum.NormalId.Top,SizingMode=Enum.SurfaceGuiSizingMode.FixedSize,CanvasSize=Vector2.new(220,220),LightInfluence=0,AlwaysOnTop=false,Brightness=2.2,Parent=p})
local ringScales = style == "Hex Pulse" and {1,0.64} or (style == "Star Burst" and {1,0.56} or (style == "Runic Burst" and {1,0.78,0.48} or {1,0.74,0.48}))
for i, sc in ipairs(ringScales) do
local fr = new("Frame",{AnchorPoint=Vector2.new(0.5,0.5),Position=UDim2.fromScale(0.5,0.5),Size=UDim2.fromScale(sc*0.97,sc*0.97),BackgroundTransparency=1,BorderSizePixel=0,Rotation=style=="Hex Pulse" and 30 or 0,Parent=sg})
new("UICorner",{CornerRadius=UDim.new(style=="Hex Pulse" and 0.08 or 0.5,0),Parent=fr})
local st = new("UIStroke",{Thickness=thick*(i==1 and 1 or 0.55),Color=(i==1) and col:Lerp(Color3.new(1,1,1),0.35) or col,Transparency=0.05+(i-1)*0.12,Parent=fr})
TS:Create(st, TweenInfo.new(sdur(life), Enum.EasingStyle.Quad, Enum.EasingDirection.In, 0, false, (i-1)*0.05), {Transparency=1}):Play()
end
if style == "Hex Pulse" then
for i=1,6 do
local angle=(i-1)*60
local a=math.rad(angle)
local edge=new("Frame",{AnchorPoint=Vector2.new(0.5,0.5),Position=UDim2.fromScale(0.5+math.cos(a)*0.29,0.5+math.sin(a)*0.29),Size=UDim2.new(0.28,0,0,3),Rotation=angle+30,BackgroundColor3=col,BorderSizePixel=0,Parent=sg})
TS:Create(edge,TweenInfo.new(sdur(life),Enum.EasingStyle.Quad,Enum.EasingDirection.Out),{BackgroundTransparency=1,Size=UDim2.new(0.34,0,0,1)}):Play()
end
elseif style == "Star Burst" or style == "Runic Burst" then
local spokes = style == "Star Burst" and 12 or 8
for i=1,spokes do
local a = (i-1)/spokes*math.pi*2
local len = style == "Star Burst" and 0.22 or 0.15
local x,y = 0.5+math.cos(a)*0.34,0.5+math.sin(a)*0.34
local ray = new("Frame",{AnchorPoint=Vector2.new(0.5,0.5),Position=UDim2.fromScale(x,y),Size=UDim2.new(len,0,0,style=="Star Burst" and 3 or 2),Rotation=math.deg(a),BackgroundColor3=col:Lerp(Color3.new(1,1,1),0.4),BorderSizePixel=0,Parent=sg})
TS:Create(ray,TweenInfo.new(sdur(life),Enum.EasingStyle.Quad,Enum.EasingDirection.Out),{BackgroundTransparency=1,Size=UDim2.new(len*1.3,0,0,1)}):Play()
end
end
TS:Create(p, TweenInfo.new(sdur(life), Enum.EasingStyle.Quint, Enum.EasingDirection.Out), {Size=Vector3.new(size,0.05,size)}):Play()
task.delay(life + 0.2, function() p:Destroy() end)
end
local function burst(pos, col, count, flat)
local p = new("Part",{Anchored=true,CanCollide=false,CanQuery=false,CanTouch=false,CastShadow=false,Transparency=1,Size=Vector3.new(1,1,1),CFrame=CFrame.new(pos),Parent=workspace})
local pe = new("ParticleEmitter",{Texture="rbxassetid://243098098",Rate=0,Lifetime=NumberRange.new(0.4,0.9),Speed=NumberRange.new(flat and 12 or 6, flat and 24 or 14),SpreadAngle=Vector2.new(flat and 88 or 30, flat and 88 or 30),EmissionDirection=Enum.NormalId.Top,Drag=flat and 4 or 1,Acceleration=Vector3.new(0,flat and -4 or -14,0),Color=ColorSequence.new(Color3.new(1,1,1),col),Size=NumberSequence.new({NumberSequenceKeypoint.new(0,0.55),NumberSequenceKeypoint.new(1,0)}),Transparency=NumberSequence.new({NumberSequenceKeypoint.new(0,0.05),NumberSequenceKeypoint.new(1,1)}),LightEmission=1,Rotation=NumberRange.new(0,360),RotSpeed=NumberRange.new(-120,120),Parent=p})
pe:Emit(count)
task.delay(1.4, function() p:Destroy() end)
end
local neonSaved = {}
local neonConn = nil
Fn.applyNeonBody = function()
local char = player.Character; if not char then return end
if feat.neon then
local style = feat.visualStyles.neonBody or "Neon Shell"
local material = style == "Forcefield" and Enum.Material.ForceField or (style == "Glass Prism" and Enum.Material.Glass or (style == "Metallic Glow" and Enum.Material.Metal or Enum.Material.Neon))
for _, p in ipairs(char:GetDescendants()) do
if p:IsA("BasePart") then
if neonSaved[p] == nil then neonSaved[p] = {Material=p.Material,Color=p.Color} end
p.Material = material
p.Color = visualColor("neonBody"):Lerp(Color3.new(1,1,1), style == "Glass Prism" and 0.45 or (style == "Metallic Glow" and 0.18 or 0))
end
end
else
for p, saved in pairs(neonSaved) do
if p and p.Parent then p.Material = saved.Material; p.Color = saved.Color end
end
table.clear(neonSaved)
end
end
local function hookNeon(char)
if neonConn then neonConn:Disconnect(); neonConn = nil end
if not char then return end
Fn.applyNeonBody()
neonConn = char.DescendantAdded:Connect(function() if feat.neon then task.defer(Fn.applyNeonBody) end end)
end
local function applyTrans(p)
if not p:IsA("BasePart") or p.Name == "HumanoidRootPart" then return end
local alpha = feat.playerTransparency and feat.playerTransparencyLevel/100 or 0
local style = feat.visualStyles.playerTrans or "Ghost Fade"
if feat.playerTransparency and style == "Glass Skin" then alpha = math.max(alpha,0.42)
elseif feat.playerTransparency and style == "Phantom" then alpha = math.max(alpha,0.72)
elseif feat.playerTransparency and style == "Outline Silhouette" then alpha = math.min(alpha,0.12) end
p.LocalTransparencyModifier = math.clamp(alpha,0,0.95)
end
Fn.applyPlayerTransparency = function()
local c = player.Character; if not c then return end
for _, d in ipairs(c:GetDescendants()) do applyTrans(d) end
local style = feat.visualStyles.playerTrans or "Ghost Fade"
if feat.playerTransparency and style == "Outline Silhouette" then
if not vfxObj.playerTransHighlight or not vfxObj.playerTransHighlight.Parent then
vfxObj.playerTransHighlight = new("Highlight",{Name="OwoPlayerTransparencyOutline",FillTransparency=1,OutlineColor=visualColor("playerTrans"):Lerp(Color3.new(1,1,1),0.3),OutlineTransparency=0.02,DepthMode=Enum.HighlightDepthMode.AlwaysOnTop,Parent=c})
end
elseif vfxObj.playerTransHighlight then
vfxObj.playerTransHighlight:Destroy(); vfxObj.playerTransHighlight=nil
end
end
local function hookTrans(char)
if not char then return end
Fn.applyPlayerTransparency()
char.DescendantAdded:Connect(function(d) task.defer(function() applyTrans(d) end) end)
end
local rainbowOrig, rainbowConn = {}, nil
Fn.applyRainbowChar = function()
local char = player.Character; if not char then return end
if not feat.rainbowChar then
for p, col in pairs(rainbowOrig) do if p and p.Parent then p.Color = col end end
table.clear(rainbowOrig)
if rainbowConn then rainbowConn:Disconnect(); rainbowConn = nil end
return
end
for _, p in ipairs(char:GetDescendants()) do if p:IsA("BasePart") and rainbowOrig[p] == nil then rainbowOrig[p] = p.Color end end
if not rainbowConn then
local t = 0
rainbowConn = RS.Heartbeat:Connect(function(dt)
if not feat.rainbowChar then return end
t += dt * feat.rainbowSpeed
local c = player.Character; if not c then return end
for _, p in ipairs(c:GetDescendants()) do
if p:IsA("BasePart") and p.Name ~= "HumanoidRootPart" then
local style = feat.visualStyles.rainbowChar or "Rainbow Wave"
local hue
if style == "Hue Bands" then hue = (math.floor((t + p.Position.Y*0.08)*5)/5) % 1
elseif style == "Prism Pulse" then hue = (t*1.7 + math.abs(p.Position.Y)*0.14) % 1
elseif style == "Color Drift" then hue = (t*0.42 + p.Position.Y*0.025) % 1
else hue = (t + (p.Position.X + p.Position.Z)*0.05) % 1 end
local sat = style == "Color Drift" and 0.62 or 0.92
p.Color = Color3.fromHSV(hue, sat, style == "Prism Pulse" and (0.8+0.2*math.sin(t*4)) or 1)
end
end
end)
end
end
-- AURA RING: a rotating magic circle on the ground with rising sparks
local auraPart, auraConn = nil, nil
local function dashSeq(n)
local k = {}
for j = 0, n - 1 do
local a = j / n
k[#k+1] = NumberSequenceKeypoint.new(a, 0)
k[#k+1] = NumberSequenceKeypoint.new(a + 0.5 / n, 0)
k[#k+1] = NumberSequenceKeypoint.new(a + 0.56 / n, 1)
end
k[#k+1] = NumberSequenceKeypoint.new(1, 1)
return NumberSequence.new(k)
end
Fn.rebuildAuraRing = function()
if auraPart then auraPart:Destroy(); auraPart = nil end
if auraConn then auraConn:Disconnect(); auraConn = nil end
if not feat.auraRing then return end
local auraStyle = feat.visualStyles.aura or "Arcane Sigil"
local D = feat.auraRingSize * 1.7
auraPart = new("Part", {Name="OwoAuraRing", Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Transparency=1, Size=Vector3.new(D, 0.05, D), Parent=workspace})
local sg = new("SurfaceGui", {Face=Enum.NormalId.Top, SizingMode=Enum.SurfaceGuiSizingMode.FixedSize, CanvasSize=Vector2.new(300, 300), LightInfluence=0, AlwaysOnTop=false, Brightness=2.2, Parent=auraPart})
local cfg = {{1.0, 6, 14, 6, 0.9}, {0.8, 4, 10, 4, -1.3}, {0.6, 3, 8, 3, 1.8}, {0.36, 2, 5, 2, -2.4}}
if auraStyle == "Solar Star" then cfg = {{1.0,12,8,4,0.65},{0.77,8,6,3,-0.9},{0.42,4,4,2,1.45}}
elseif auraStyle == "Void Spiral" then cfg = {{1.0,3,10,4,-1.7},{0.68,2,7,3,2.2},{0.32,1,4,2,-2.8}}
elseif auraStyle == "Tech Grid" then cfg = {{1.0,16,8,4,0.35},{0.72,12,6,3,-0.6},{0.44,8,4,2,0.95}} end
local rings = {}
for i, c in ipairs(cfg) do
local fr = new("Frame", {AnchorPoint=Vector2.new(0.5,0.5), Position=UDim2.fromScale(0.5,0.5), Size=UDim2.fromScale(c[1]*0.97, c[1]*0.97), BackgroundTransparency=1, BorderSizePixel=0, Parent=sg})
new("UICorner", {CornerRadius=UDim.new(0.5,0), Parent=fr})
local st = new("UIStroke", {Thickness=c[3], Color=visualColor("aura"):Lerp(Color3.new(1,1,1), i == 1 and 0.4 or 0.15), Transparency=0, Parent=fr})
local g = new("UIGradient", {Transparency=dashSeq(c[2]), Parent=st})
rings[i] = {g=g, st=st, speed=c[5]}
end
local glyphs = {}
if auraStyle == "Solar Star" then
for i=1,8 do
local ray = new("Frame",{AnchorPoint=Vector2.new(0.5,0.5),Position=UDim2.fromScale(0.5,0.5),Size=UDim2.fromScale(0.018,0.56),BackgroundColor3=visualColor("aura"):Lerp(Color3.new(1,1,1),0.3),BackgroundTransparency=0.12,BorderSizePixel=0,Rotation=(i-1)*22.5,Parent=sg})
glyphs[#glyphs+1] = {frame=ray,base=(i-1)*22.5,spin=(i%2==0 and -1 or 1)*20}
end
elseif auraStyle == "Tech Grid" then
for _,rot in ipairs({0,45}) do
local sq = new("Frame",{AnchorPoint=Vector2.new(0.5,0.5),Position=UDim2.fromScale(0.5,0.5),Size=UDim2.fromScale(rot==0 and 0.5 or 0.64,rot==0 and 0.5 or 0.64),BackgroundTransparency=1,BorderSizePixel=0,Rotation=rot,Parent=sg})
new("UIStroke",{Thickness=2,Color=visualColor("aura"),Transparency=0.12,Parent=sq})
end
for i=1,4 do
local line = new("Frame",{AnchorPoint=Vector2.new(0.5,0.5),Position=UDim2.fromScale(0.5,0.5),Size=UDim2.new(0.74,0,0,2),BackgroundColor3=visualColor("aura"),BackgroundTransparency=0.2,BorderSizePixel=0,Rotation=(i-1)*45,Parent=sg})
glyphs[#glyphs+1] = {frame=line,base=(i-1)*45,spin=0}
end
elseif auraStyle == "Void Spiral" then
for i=1,11 do
local dot = new("Frame",{AnchorPoint=Vector2.new(0.5,0.5),Position=UDim2.fromScale(0.5,0.5),Size=UDim2.fromOffset(math.max(3,9-i*0.45),math.max(3,9-i*0.45)),BackgroundColor3=visualColor("aura"):Lerp(Color3.new(1,1,1),i/14),BackgroundTransparency=0.05+i*0.035,BorderSizePixel=0,Parent=sg})
new("UICorner",{CornerRadius=UDim.new(1,0),Parent=dot})
glyphs[#glyphs+1] = {frame=dot,index=i,spiral=true}
end
end
local glowSize = auraStyle == "Solar Star" and 0.13 or (auraStyle == "Tech Grid" and 0.09 or 0.22)
local glow = new("Frame", {AnchorPoint=Vector2.new(0.5,0.5), Position=UDim2.fromScale(0.5,0.5), Size=UDim2.fromScale(glowSize,glowSize), BackgroundColor3=visualColor("aura"), BackgroundTransparency=0.55, BorderSizePixel=0, Parent=sg})
if auraStyle ~= "Tech Grid" then new("UICorner", {CornerRadius=UDim.new(0.5,0), Parent=glow}) end
new("ParticleEmitter", {Texture="rbxassetid://243098098", Rate=16, Lifetime=NumberRange.new(1.2,2), Speed=NumberRange.new(1.5,3.5), SpreadAngle=Vector2.new(12,12), EmissionDirection=Enum.NormalId.Top, Color=ColorSequence.new(visualColor("aura"):Lerp(Color3.new(1,1,1),0.4), visualColor("aura")), Size=NumberSequence.new({NumberSequenceKeypoint.new(0,0.28),NumberSequenceKeypoint.new(1,0)}), Transparency=NumberSequence.new({NumberSequenceKeypoint.new(0,0.1),NumberSequenceKeypoint.new(1,1)}), LightEmission=1, Parent=auraPart})
local t, groundY, accR = 0, nil, 0
local rp = RaycastParams.new(); rp.FilterType = Enum.RaycastFilterType.Exclude
auraConn = RS.RenderStepped:Connect(function(dt)
t += dt
local char = player.Character; local hrp = char and char:FindFirstChild("HumanoidRootPart")
if not hrp or not auraPart then return end
accR += dt
if accR > 0.12 or not groundY then
accR = 0
rp.FilterDescendantsInstances = {char, auraPart}
local hit = workspace:Raycast(hrp.Position, Vector3.new(0, -12, 0), rp)
groundY = hit and (hit.Position.Y + 0.06) or (hrp.Position.Y - 2.8)
end
local pulse = 1 + math.sin(t * 2.6) * 0.05
auraPart.Size = Vector3.new(D * pulse, 0.05, D * pulse)
local cy = (auraPart.Position.Y ~= 0) and auraPart.Position.Y or groundY
cy = cy + (groundY - cy) * math.clamp(dt * 14, 0, 1)
auraPart.CFrame = CFrame.new(hrp.Position.X, cy, hrp.Position.Z)
for _, r in ipairs(rings) do
r.g.Rotation = (t * r.speed * 57.3) % 360
r.st.Color = visualColor("aura"):Lerp(Color3.new(1,1,1), 0.18 + 0.12 * math.sin(t * 3))
end
for _, g in ipairs(glyphs) do
if g.spiral then
local a = t*1.35 + g.index*0.72
local radius = 0.04 + (g.index/12)*0.36
g.frame.Position = UDim2.fromScale(0.5+math.cos(a)*radius,0.5+math.sin(a)*radius)
else g.frame.Rotation = g.base + t*g.spin end
g.frame.BackgroundColor3 = visualColor("aura"):Lerp(Color3.new(1,1,1),0.2+0.15*math.sin(t*3+ (g.index or 0)))
end
glow.BackgroundColor3 = visualColor("aura")
glow.BackgroundTransparency = 0.5 + math.sin(t * 4) * 0.12
end)
end
local orbs, orbsConn = {}, nil
Fn.rebuildOrbs = function()
for _, o in ipairs(orbs) do o:Destroy() end
orbs = {}
if orbsConn then orbsConn:Disconnect(); orbsConn = nil end
if not feat.orbitOrbs then return end
local orbStyle = feat.visualStyles.orbs or "Orbit Spheres"
for i = 1, feat.orbitOrbCount do
local shape = (orbStyle == "Orbit Spheres") and Enum.PartType.Ball or ((orbStyle == "Orbit Runes") and Enum.PartType.Cylinder or Enum.PartType.Block)
local material = (orbStyle == "Orbit Diamonds") and Enum.Material.Glass or Enum.Material.Neon
local size = feat.orbitOrbSize
local partSize = orbStyle == "Orbit Runes" and Vector3.new(size*0.22,size*1.75,size*1.75) or Vector3.new(size,size,size)
local orb = new("Part", {Name="OwoOrbitVisual", Shape=shape, Size=partSize, Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Material=material, Transparency=orbStyle=="Orbit Shards" and 0.12 or 0, Color=visualColor("orbs"), Parent=workspace})
if orbStyle == "Orbit Shards" then orb.Size = Vector3.new(size*0.65,size*1.8,size*0.65) end
orbs[i] = orb
end
local t = 0
orbsConn = RS.RenderStepped:Connect(function(dt)
t += dt * feat.orbitOrbSpeed
local char = player.Character; local hrp = char and char:FindFirstChild("HumanoidRootPart")
if not hrp then return end
local n = #orbs
for i, o in ipairs(orbs) do
if not o.Parent then continue end
local angle = t + (i-1)/n * math.pi * 2
local h = math.sin(t*2 + i) * 0.5
local pos = hrp.Position + Vector3.new(math.cos(angle)*feat.orbitOrbRadius, h, math.sin(angle)*feat.orbitOrbRadius)
local style = feat.visualStyles.orbs or "Orbit Spheres"
if style == "Orbit Diamonds" then
o.CFrame = CFrame.new(pos) * CFrame.Angles(angle*0.8, angle, math.rad(45)+angle*0.6)
elseif style == "Orbit Runes" then
o.CFrame = CFrame.new(pos) * CFrame.Angles(angle, angle*0.6, math.rad(90)+angle*0.7)
elseif style == "Orbit Shards" then
o.CFrame = CFrame.new(pos) * CFrame.Angles(angle*1.8, angle*0.7, angle*1.2)
else
o.CFrame = CFrame.new(pos) * CFrame.Angles(angle*0.5, angle, angle*0.3)
end
o.Color = visualColor("orbs")
end
end)
end
local lightConn, lightAcc = nil, 0
Fn.rebuildLightning = function()
if lightConn then lightConn:Disconnect(); lightConn = nil end
if not feat.lightningAura then return end
lightAcc = 0
lightConn = RS.Heartbeat:Connect(function(dt)
lightAcc += dt
if lightAcc < 1/feat.lightningRate then return end
lightAcc = 0
local char = player.Character; local hrp = char and char:FindFirstChild("HumanoidRootPart")
if not hrp then return end
local style = feat.visualStyles.lightning or "Forked Arc"
local paths = {}
local function makePath(startPos, endPos, count, spread)
local pts = {startPos}
for n=1,count-1 do
local k = n/count
pts[#pts+1] = startPos:Lerp(endPos,k) + Vector3.new((math.random()-0.5)*spread,(math.random()-0.5)*spread,(math.random()-0.5)*spread)
end
pts[#pts+1] = endPos
paths[#paths+1] = pts
end
if style == "Spiral Coil" then
local center = hrp.Position
local pts = {}
local phase = math.random()*math.pi*2
for i=0,9 do
local a = phase + i/9*math.pi*3.5
pts[#pts+1] = center + Vector3.new(math.cos(a)*(0.55+i*0.13),-1.5+i*0.34,math.sin(a)*(0.55+i*0.13))
end
paths[#paths+1] = pts
elseif style == "Ground Strike" then
local top = hrp.Position + Vector3.new(math.random(-3,3),math.random(3,6),math.random(-3,3))
local ground = hrp.Position + Vector3.new(math.random(-2,2),-2.6,math.random(-2,2))
makePath(top,ground,7,1.15)
elseif style == "Burst Web" then
for j=1,4 do
local startPos = hrp.Position + Vector3.new(math.random(-1,1),math.random(-1,2),math.random(-1,1))
local endPos = hrp.Position + Vector3.new(math.random(-3,3),math.random(-2,2),math.random(-3,3))
makePath(startPos,endPos,4,0.8)
end
else
local startPos = hrp.Position + Vector3.new(math.random(-2,2),math.random(-2,2),math.random(-2,2))
local endPos = hrp.Position + Vector3.new(math.random(-2,2),math.random(-2,2),math.random(-2,2))
makePath(startPos,endPos,6,1.8)
if math.random() < 0.75 then
local branchFrom = paths[1][math.random(2,#paths[1]-1)]
makePath(branchFrom, branchFrom + Vector3.new(math.random(-2,2),math.random(-2,2),math.random(-2,2)),3,0.7)
end
end
for _, path in ipairs(paths) do
for i=1,#path-1 do
local from,to = path[i],path[i+1]
local diff = to-from; local len = diff.Magnitude
if len > 0.05 then
local thick = style == "Burst Web" and 0.075 or (style == "Ground Strike" and 0.14 or 0.105)
local seg = new("Part",{Name="OwoLightningSegment",Anchored=true,CanCollide=false,CanQuery=false,CanTouch=false,CastShadow=false,Material=Enum.Material.Neon,Color=visualColor("lightning"),Size=Vector3.new(thick,thick,len),CFrame=CFrame.lookAt((from+to)*0.5,to),Transparency=0.04,Parent=workspace})
TS:Create(seg,TweenInfo.new(sdur(style == "Spiral Coil" and 0.28 or 0.18)),{Transparency=1,Size=Vector3.new(0.015,0.015,len)}):Play()
task.delay(style == "Spiral Coil" and 0.31 or 0.21,function() if seg then seg:Destroy() end end)
end
end
end
end)
end
local lastPos, footConn = nil, nil
Fn.rebuildFireFootsteps = function()
if footConn then footConn:Disconnect(); footConn = nil end
if not feat.fireFootsteps then return end
lastPos = nil
footConn = RS.Heartbeat:Connect(function()
local char = player.Character; local hrp = char and char:FindFirstChild("HumanoidRootPart"); local hum = char and char:FindFirstChildOfClass("Humanoid")
if not hrp or not hum then lastPos = nil; return end
if hum.MoveDirection.Magnitude < 0.1 then lastPos = hrp.Position; return end
if not lastPos then lastPos = hrp.Position; return end
if (hrp.Position - lastPos).Magnitude < 0.8 then return end
lastPos = hrp.Position
local style = feat.visualStyles.footsteps or "Ember Prints"
local em = new("Part", {Name="OwoFootstepFX",Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Transparency=1, Size=Vector3.new(1,1,1), CFrame=hrp.CFrame*CFrame.new(0,-2.6,0), Parent=workspace})
local rate, speed, spread, size = 12, NumberRange.new(2,5), Vector2.new(35,35), 0.8
if style == "Rune Marks" then rate,speed,spread,size = 5,NumberRange.new(0.1,0.6),Vector2.new(8,8),0.38
elseif style == "Shock Puffs" then rate,speed,spread,size = 22,NumberRange.new(4,8),Vector2.new(70,70),1.25
elseif style == "Spark Trails" then rate,speed,spread,size = 26,NumberRange.new(0.3,2.2),Vector2.new(18,18),0.42 end
local pe = new("ParticleEmitter", {Texture="rbxassetid://243098098", Rate=0, Lifetime=style=="Rune Marks" and NumberRange.new(0.8,1.3) or NumberRange.new(0.4,0.8), Speed=speed, SpreadAngle=spread, EmissionDirection=Enum.NormalId.Top, Color=ColorSequence.new({ColorSequenceKeypoint.new(0,Color3.fromRGB(255,240,180)),ColorSequenceKeypoint.new(0.4,visualColor("footsteps")),ColorSequenceKeypoint.new(1,Color3.fromRGB(20,20,20))}), Size=NumberSequence.new({NumberSequenceKeypoint.new(0,size),NumberSequenceKeypoint.new(1,0)}), Transparency=NumberSequence.new({NumberSequenceKeypoint.new(0,0.1),NumberSequenceKeypoint.new(1,1)}), LightEmission=1, Parent=em})
pe:Emit(style=="Ember Prints" and 12 or (style=="Shock Puffs" and 20 or 9))
if style == "Rune Marks" then
local sg = new("SurfaceGui",{Face=Enum.NormalId.Bottom,SizingMode=Enum.SurfaceGuiSizingMode.FixedSize,CanvasSize=Vector2.new(100,100),LightInfluence=0,Brightness=2,Parent=em})
local ring = new("Frame",{AnchorPoint=Vector2.new(0.5,0.5),Position=UDim2.fromScale(0.5,0.5),Size=UDim2.fromScale(0.72,0.72),BackgroundTransparency=1,BorderSizePixel=0,Parent=sg})
new("UICorner",{CornerRadius=UDim.new(1,0),Parent=ring}); new("UIStroke",{Color=visualColor("footsteps"),Thickness=3,Transparency=0.1,Parent=ring})
for i=1,4 do new("Frame",{AnchorPoint=Vector2.new(0.5,0.5),Position=UDim2.fromScale(0.5,0.5),Size=UDim2.new(0.8,0,0,2),Rotation=(i-1)*45,BackgroundColor3=visualColor("footsteps"),BorderSizePixel=0,Parent=sg}) end
elseif style == "Shock Puffs" then
local puff = new("Part",{Shape=Enum.PartType.Ball,Anchored=true,CanCollide=false,CanQuery=false,CanTouch=false,CastShadow=false,Material=Enum.Material.Neon,Color=visualColor("footsteps"),Transparency=0.55,Size=Vector3.new(0.2,0.2,0.2),CFrame=em.CFrame,Parent=workspace})
TS:Create(puff,TweenInfo.new(0.45),{Size=Vector3.new(2.8,0.35,2.8),Transparency=1}):Play(); task.delay(0.5,function() if puff then puff:Destroy() end end)
end
task.delay(style=="Rune Marks" and 1.4 or 1, function() if em then em:Destroy() end end)
end)
end
Fn.rebuildVFX = function()
clearVfx()
local char = player.Character; if not char then return end
local hrp = char:FindFirstChild("HumanoidRootPart"); local hum = char:FindFirstChildOfClass("Humanoid")
if not hrp or not hum then return end
local EC = EFFECT_COLOR
Fn.applyNeonBody(); Fn.applyPlayerTransparency(); Fn.applyRainbowChar()
Fn.rebuildAuraRing(); Fn.rebuildOrbs(); Fn.rebuildLightning(); Fn.rebuildFireFootsteps()
if feat.glow then
EC = visualColor("glow")
local style = feat.visualStyles.glow or "Soft Halo"
local fill, outline, range, brightness = 0.5, 0, 20, 3
if style == "Double Rim" then fill, outline, range, brightness = 0.82, 0.02, 28, 4.5
elseif style == "Pulse Glow" then fill, outline, range, brightness = 0.35, 0.12, 14, 2.2
elseif style == "Outline Glow" then fill, outline, range, brightness = 1, 0, 18, 2.5 end
vfxObj.g1 = new("Highlight",{FillColor=EC,FillTransparency=fill,OutlineColor=EC,OutlineTransparency=outline,Parent=char})
vfxObj.g2 = new("PointLight",{Color=EC,Range=range,Brightness=brightness,Parent=hrp})
if style == "Double Rim" then
vfxObj.glowRim = new("Highlight",{Name="OwoSecondaryGlowRim",FillTransparency=1,OutlineColor=EC:Lerp(Color3.new(1,1,1),0.6),OutlineTransparency=0.25,DepthMode=Enum.HighlightDepthMode.AlwaysOnTop,Parent=char})
elseif style == "Pulse Glow" then
vfxObj.glowPulseAtt = new("Attachment",{Position=Vector3.new(0,0,0),Parent=hrp})
vfxObj.glowPulse = new("ParticleEmitter",{Rate=8,Texture="rbxassetid://243098098",Lifetime=NumberRange.new(0.5,0.9),Speed=NumberRange.new(0.1,0.6),SpreadAngle=Vector2.new(180,180),Size=NumberSequence.new({NumberSequenceKeypoint.new(0,0.2),NumberSequenceKeypoint.new(0.5,1.5),NumberSequenceKeypoint.new(1,0)}),Transparency=NumberSequence.new({NumberSequenceKeypoint.new(0,0.65),NumberSequenceKeypoint.new(1,1)}),Color=ColorSequence.new(EC),LightEmission=1,Parent=vfxObj.glowPulseAtt})
end
end
if feat.trail then
EC = visualColor("trail")
-- Vertical glowing curtain behind you (feet -> head), soft edges, glowing orbs near the floor
local function kp(t, v) return NumberSequenceKeypoint.new(t, v) end
local trailStyle = feat.trailStyle or "Foggy"
local trailColor = EC
if trailStyle == "Aurora" then trailColor = Color3.fromRGB(100, 255, 210)
elseif trailStyle == "Fire" then trailColor = Color3.fromRGB(255, 105, 35)
elseif trailStyle == "Stardust" then trailColor = Color3.fromRGB(190, 160, 255)
elseif trailStyle == "Hearts" then trailColor = Color3.fromRGB(255, 105, 175)
elseif trailStyle == "Neon" then trailColor = Color3.fromRGB(80, 240, 255)
elseif trailStyle == "Afterimages" then trailColor = Color3.fromRGB(210, 220, 255)
elseif trailStyle == "Divine Rush" then trailColor = Color3.fromRGB(255, 184, 75) end
trailColor = feat.visualColors.trail or trailColor
-- Each preset changes the trail silhouette, not just its color.
local soft = trailColor:Lerp(Color3.new(1, 1, 1), trailStyle == "Afterimages" and 0.65 or 0.3)
local topPos, bottomPos = Vector3.new(0, 1.7, 0.2), Vector3.new(0, -2.8, 0.2)
local life, mainWidth, glowWidth, mainRate, sparkRate = 1.9, 1, 0.55, 14, 22
local faceCamera, spread = false, Vector2.new(180,180)
if trailStyle == "Aurora" then
topPos, bottomPos = Vector3.new(0, 2.2, 0.65), Vector3.new(0, -3.2, 0.65)
life, mainWidth, glowWidth, mainRate, sparkRate, faceCamera = 2.8, 1.45, 0.25, 7, 5, true
elseif trailStyle == "Fire" then
topPos, bottomPos = Vector3.new(0, 0.7, -0.25), Vector3.new(0, -3.4, -0.25)
life, mainWidth, glowWidth, mainRate, sparkRate, spread = 1.15, 1.25, 0.8, 38, 48, Vector2.new(55,55)
elseif trailStyle == "Stardust" then
topPos, bottomPos = Vector3.new(0, 2.6, 0.1), Vector3.new(0, -3.5, 0.1)
life, mainWidth, glowWidth, mainRate, sparkRate = 3.4, 0.65, 0.2, 34, 42
elseif trailStyle == "Hearts" then
topPos, bottomPos = Vector3.new(0, 1.2, 0.1), Vector3.new(0, -2.1, 0.1)
life, mainWidth, glowWidth, mainRate, sparkRate, spread = 1.7, 0.5, 0.15, 7, 3, Vector2.new(90,90)
elseif trailStyle == "Neon" then
topPos, bottomPos = Vector3.new(0, 1.9, 0.35), Vector3.new(0, -3.0, 0.35)
life, mainWidth, glowWidth, mainRate, sparkRate, faceCamera = 1.25, 1.8, 1.1, 4, 2, true
elseif trailStyle == "Afterimages" then
topPos, bottomPos = Vector3.new(0, 2.5, 0.8), Vector3.new(0, -3.8, 0.8)
life, mainWidth, glowWidth, mainRate, sparkRate, faceCamera = 3.2, 1.35, 0.1, 2, 1, true
elseif trailStyle == "Divine Rush" then
topPos, bottomPos = Vector3.new(0, 1.9, 0.35), Vector3.new(0, -3.1, 0.35)
life, mainWidth, glowWidth, mainRate, sparkRate, faceCamera, spread = 2.4, 0.7, 0.25, 4, 38, true, Vector2.new(35,35)
end
-- Foggy intentionally matches the original script: a full-height soft curtain.
-- Other presets hide the shared curtain and use their own thinner silhouettes.
if trailStyle == "Foggy" then
mainWidth, glowWidth = 1, 1
faceCamera = false
else
mainWidth, glowWidth = 0.001, 0.001
end
local a0 = new("Attachment",{Name="OwoTrailTop",Position=topPos,Parent=hrp})
local a1 = new("Attachment",{Name="OwoTrailBottom",Position=bottomPos,Parent=hrp})
vfxObj.tA0, vfxObj.tA1 = a0, a1
vfxObj.trail = new("Trail",{Attachment0=a0,Attachment1=a1,Lifetime=life,MinLength=0.05,FaceCamera=faceCamera,LightEmission=0.55,LightInfluence=0,
Color=ColorSequence.new({ColorSequenceKeypoint.new(0,soft),ColorSequenceKeypoint.new(0.5,trailColor),ColorSequenceKeypoint.new(1,trailColor:Lerp(Color3.new(1,1,1),0.15))}),
Transparency=NumberSequence.new({kp(0,0.5),kp(0.45,0.68),kp(1,1)}),
WidthScale=trailStyle == "Foggy" and NumberSequence.new({kp(0,1),kp(1,1)}) or NumberSequence.new({kp(0,mainWidth),kp(0.55,mainWidth*0.72),kp(1,0)}),Parent=hrp})
-- brighter glow strip along the bottom edge
local b0 = new("Attachment",{Position=Vector3.new(0, -1.4, 0.2),Parent=hrp})
local b1 = new("Attachment",{Position=Vector3.new(0, -2.8, 0.2),Parent=hrp})
vfxObj.tB0, vfxObj.tB1 = b0, b1
vfxObj.trailGlow = new("Trail",{Attachment0=b0,Attachment1=b1,Lifetime=trailStyle == "Foggy" and 1.3 or math.max(0.6,life*0.68),MinLength=0.05,FaceCamera=faceCamera,LightEmission=0.9,LightInfluence=0,
Color=ColorSequence.new(Color3.new(1,1,1),soft),
Transparency=NumberSequence.new({kp(0,0.45),kp(0.6,0.8),kp(1,1)}),
WidthScale=trailStyle == "Foggy" and NumberSequence.new({kp(0,1),kp(1,1)}) or NumberSequence.new({kp(0,glowWidth),kp(1,0)}),Parent=hrp})
-- Foggy keeps the original floor-level drifting orbs; the other presets
-- emit their accent particles from the TOP and send them DOWNWARD.
local particleY = trailStyle == "Foggy" and -2.5 or math.max(1.7, topPos.Y)
local sa = new("Attachment",{Name="OwoTrailParticleOrigin",Position=Vector3.new(0, particleY, 0.3),Parent=hrp})
vfxObj.tSA = sa
vfxObj.trailOrbs = new("ParticleEmitter",{Texture="rbxassetid://243098098",Rate=(trailStyle == "Foggy" and 14 or 0),Lifetime=NumberRange.new(0.8,1.6),Speed=NumberRange.new(0.2,1.2),SpreadAngle=trailStyle == "Foggy" and Vector2.new(180,180) or spread,EmissionDirection=trailStyle == "Foggy" and Enum.NormalId.Back or Enum.NormalId.Bottom,
Color=ColorSequence.new(Color3.new(1,1,1),soft),Size=trailStyle == "Foggy" and NumberSequence.new({kp(0,0.7),kp(0.4,1.0),kp(1,0)}) or NumberSequence.new({kp(0,0.28),kp(0.4,0.46),kp(1,0)}),Transparency=NumberSequence.new({kp(0,0.45),kp(1,1)}),
LightEmission=1,Acceleration=trailStyle == "Foggy" and Vector3.new(0,0.5,0) or Vector3.new(0,-3,0),Parent=sa})
vfxObj.trailSpark = new("ParticleEmitter",{Texture="rbxassetid://243098098",Rate=(trailStyle == "Foggy" and 22 or 0),Lifetime=NumberRange.new(0.9,1.8),Speed=NumberRange.new(trailStyle == "Fire" and 3 or 0.3,trailStyle == "Fire" and 7 or 2),SpreadAngle=trailStyle == "Foggy" and Vector2.new(180,180) or spread,EmissionDirection=trailStyle == "Foggy" and Enum.NormalId.Top or Enum.NormalId.Bottom,
Color=ColorSequence.new(Color3.new(1,1,1),trailColor),Size=trailStyle == "Foggy" and NumberSequence.new({kp(0,0.1),kp(0.3,0.36),kp(1,0)}) or NumberSequence.new({kp(0,0.06),kp(0.3,0.20),kp(1,0)}),Transparency=NumberSequence.new({kp(0,0.1),kp(1,1)}),
LightEmission=1,Rotation=NumberRange.new(0,360),RotSpeed=NumberRange.new(-60,60),Acceleration=trailStyle == "Foggy" and Vector3.new(0,1,0) or Vector3.new(0,-4,0),Parent=sa})
if trailStyle == "Aurora" or trailStyle == "Neon" or trailStyle == "Afterimages" then
-- Broad parallel ribbons give these presets a different silhouette.
for i, x in ipairs({-0.72, 0.72}) do
local r0 = new("Attachment", {Position=Vector3.new(x, 1.4, 0.55), Parent=hrp})
local r1 = new("Attachment", {Position=Vector3.new(x*1.35, -3.0, 0.55), Parent=hrp})
vfxObj["variantRibbonA0_"..i], vfxObj["variantRibbonA1_"..i] = r0, r1
vfxObj["variantRibbon_"..i] = new("Trail", {
Attachment0=r0, Attachment1=r1, Lifetime=life*0.85, FaceCamera=true,
LightEmission=trailStyle == "Neon" and 1 or 0.65, LightInfluence=0,
Color=ColorSequence.new(soft, trailColor),
Transparency=NumberSequence.new({kp(0, trailStyle == "Afterimages" and 0.78 or 0.28), kp(1,1)}),
WidthScale=NumberSequence.new({kp(0, trailStyle == "Neon" and 0.28 or 0.15), kp(1,0)}), Parent=hrp
})
end
elseif trailStyle == "Stardust" then
-- A constellation of small orbiting motes rather than a solid curtain.
vfxObj.stardustMotes = new("ParticleEmitter", {
Texture="rbxassetid://243098098", Rate=42, Lifetime=NumberRange.new(1.2,2.4),
Speed=NumberRange.new(0.1,1.1), SpreadAngle=Vector2.new(180,180), EmissionDirection=Enum.NormalId.Bottom,
Acceleration=Vector3.new(0,-2,0), Shape=Enum.ParticleEmitterShape.Sphere, ShapeStyle=Enum.ParticleEmitterShapeStyle.Surface,
Color=ColorSequence.new(Color3.fromRGB(255,255,255), trailColor),
Size=NumberSequence.new({kp(0,0.12),kp(0.25,0.28),kp(1,0)}),
Transparency=NumberSequence.new({kp(0,0.05),kp(1,1)}), LightEmission=1,
Rotation=NumberRange.new(0,360), RotSpeed=NumberRange.new(-90,90), Parent=sa
})
elseif trailStyle == "Hearts" then
-- Gentle rising bursts create a floating, decorative trail.
vfxObj.heartFloat = new("ParticleEmitter", {
Texture="rbxassetid://243098098", Rate=8, Lifetime=NumberRange.new(1.3,2.1),
Speed=NumberRange.new(0.4,1.4), SpreadAngle=Vector2.new(35,35),
EmissionDirection=Enum.NormalId.Bottom, Acceleration=Vector3.new(0,-2.5,0),
Color=ColorSequence.new(trailColor, soft),
Size=NumberSequence.new({kp(0,0.12),kp(0.35,0.25),kp(1,0)}),
Transparency=NumberSequence.new({kp(0,0.05),kp(1,1)}), LightEmission=0.8, Parent=sa
})
elseif trailStyle == "Fire" then
-- Narrow upward tongues and fast embers instead of a wide ribbon.
vfxObj.fireTongues = new("ParticleEmitter", {
Texture="rbxassetid://243098098", Rate=34, Lifetime=NumberRange.new(0.25,0.65),
Speed=NumberRange.new(3,7), SpreadAngle=Vector2.new(22,22),
EmissionDirection=Enum.NormalId.Bottom, Acceleration=Vector3.new(0,-5,0),
Color=ColorSequence.new({ColorSequenceKeypoint.new(0,Color3.new(1,1,1)),ColorSequenceKeypoint.new(0.35,trailColor),ColorSequenceKeypoint.new(1,Color3.fromRGB(120,25,5))}),
Size=NumberSequence.new({kp(0,0.28),kp(0.45,0.18),kp(1,0)}),
Transparency=NumberSequence.new({kp(0,0.08),kp(1,1)}), LightEmission=1, Parent=sa
})
end
-- GEOMETRY PASS: each preset gets its own ribbon layout, not just a tint.
-- These strips use different start/end offsets so their silhouettes differ in motion.
local function addDesignRibbon(index, startPos, endPos, width, lifetime, colorA, colorB, alpha, emission)
local aa = new("Attachment", {Name="OwoDesignTrailA"..index, Position=startPos, Parent=hrp})
local ab = new("Attachment", {Name="OwoDesignTrailB"..index, Position=endPos, Parent=hrp})
vfxObj["designTrailA"..index], vfxObj["designTrailB"..index] = aa, ab
local tr = new("Trail", {
Name="OwoDesignTrail"..index, Attachment0=aa, Attachment1=ab,
Lifetime=lifetime, MinLength=0.025, FaceCamera=true,
LightEmission=emission or 0.8, LightInfluence=0,
Color=ColorSequence.new(colorA, colorB),
Transparency=NumberSequence.new({kp(0,alpha),kp(0.55,math.min(alpha+0.18,0.92)),kp(1,1)}),
WidthScale=NumberSequence.new({kp(0,width*0.52),kp(0.34,width*0.40),kp(1,0)}), Parent=hrp
})
vfxObj["designTrail"..index] = tr
end
if trailStyle == "Foggy" then
-- Deliberately no extra side strips: Foggy is the original script's
-- full-height, soft cyan/selected-color curtain with bottom glow + motes.
elseif trailStyle == "Aurora" then
-- Five long, soft ribbons fan outward like flowing fabric; no center curtain.
for i=-2,2 do
addDesignRibbon(10+i, Vector3.new(i*0.27,1.7,0.42), Vector3.new(i*0.78,-3.2,0.68), 0.34+(2-math.abs(i))*0.16, 2.8, soft, trailColor, 0.34, 0.72)
end
elseif trailStyle == "Fire" then
-- Four short, sharply divergent streaks plus fast upward ember tongues.
addDesignRibbon(21, Vector3.new(-0.72,-0.05,0.05), Vector3.new(-1.25,-3.0,0.25), 0.38, 0.72, Color3.new(1,1,1), trailColor, 0.2, 1)
addDesignRibbon(22, Vector3.new(0.72,-0.05,0.05), Vector3.new(1.25,-3.0,0.25), 0.38, 0.72, Color3.new(1,1,1), trailColor, 0.2, 1)
addDesignRibbon(23, Vector3.new(-0.2,0.55,-0.1), Vector3.new(0.3,-2.6,-0.1), 0.22, 0.55, trailColor, Color3.fromRGB(105,24,7), 0.3, 1)
addDesignRibbon(24, Vector3.new(0.2,0.35,-0.15), Vector3.new(-0.35,-2.4,-0.15), 0.2, 0.5, Color3.new(1,1,1), trailColor, 0.3, 1)
elseif trailStyle == "Stardust" then
-- Five hair-thin constellation paths with isolated orbiting motes, not a ribbon.
for i=-2,2 do
addDesignRibbon(30+i, Vector3.new(i*0.3,1.2,0.15), Vector3.new(i*0.62,-3.3,0.55), 0.10+(2-math.abs(i))*0.035, 3.5, Color3.new(1,1,1), trailColor, 0.5, 1)
end
elseif trailStyle == "Hearts" then
-- A delicate open V shape with rising, slow particles; the center stays empty.
addDesignRibbon(41, Vector3.new(-0.08,0.5,0.25), Vector3.new(-1.12,-2.25,0.45), 0.34, 1.8, Color3.new(1,1,1), trailColor, 0.36, 0.8)
addDesignRibbon(42, Vector3.new(0.08,0.5,0.25), Vector3.new(1.12,-2.25,0.45), 0.34, 1.8, Color3.new(1,1,1), trailColor, 0.36, 0.8)
elseif trailStyle == "Neon" then
-- Thin, rigid parallel laser rails with diagonal crossbars; all soft particles are off.
for i=-1,1 do
addDesignRibbon(50+i, Vector3.new(i*0.44,1.6,0.45), Vector3.new(i*0.52,-3.0,0.45), 0.22, 1.3, Color3.new(1,1,1), trailColor, 0.12, 1)
end
addDesignRibbon(54, Vector3.new(-0.85,0.2,0.15), Vector3.new(0.12,-2.5,0.15), 0.13, 1.1, trailColor, Color3.new(1,1,1), 0.16, 1)
addDesignRibbon(55, Vector3.new(0.85,0.2,0.15), Vector3.new(-0.12,-2.5,0.15), 0.13, 1.1, trailColor, Color3.new(1,1,1), 0.16, 1)
elseif trailStyle == "Afterimages" then
-- The main visual is the cloned fading character silhouette in the Afterimages loop;
-- keep only faint offset rails as an optional motion accent.
for i=-1,1 do
addDesignRibbon(60+i, Vector3.new(i*0.66,2.2,0.75), Vector3.new(i*1.05,-3.7,0.95), 0.55, 3.4, soft, trailColor, 0.79, 0.28)
end
end
-- Divine Rush: six narrow, angular gold/white speed streaks plus fast sparks.
-- Unlike the other presets, its design is a speed-line burst rather than a plume.
if trailStyle == "Divine Rush" then
local gold = feat.visualColors.trail or Color3.fromRGB(255, 174, 55)
local white = feat.visualColors.trail and trailColor:Lerp(Color3.new(1,1,1),0.48) or Color3.fromRGB(255, 248, 218)
local streaks = {
{Vector3.new(-1.05, 1.45, 0.35), Vector3.new(-1.35, -2.7, 0.35), 0.52},
{Vector3.new( 1.05, 1.45, 0.35), Vector3.new( 1.35, -2.7, 0.35), 0.52},
{Vector3.new(-0.55, 0.9, 0.15), Vector3.new(-0.8, -2.5, 0.15), 0.28},
{Vector3.new( 0.55, 0.9, 0.15), Vector3.new( 0.8, -2.5, 0.15), 0.28},
{Vector3.new(-0.25, 1.8, -0.15), Vector3.new(-0.45, -2.3, -0.15), 0.18},
{Vector3.new( 0.25, 1.8, -0.15), Vector3.new( 0.45, -2.3, -0.15), 0.18},
}
for i, spec in ipairs(streaks) do
local at0 = new("Attachment", {Position=spec[1], Parent=hrp})
local at1 = new("Attachment", {Position=spec[2], Parent=hrp})
vfxObj["divineA0_"..i], vfxObj["divineA1_"..i] = at0, at1
local core = (i == 3 or i == 4 or i == 5 or i == 6) and white or gold
vfxObj["divineTrail_"..i] = new("Trail", {
Attachment0=at0, Attachment1=at1, Lifetime=2.4, MinLength=0.03,
FaceCamera=true, LightEmission=1, LightInfluence=0,
Color=ColorSequence.new({ColorSequenceKeypoint.new(0, white), ColorSequenceKeypoint.new(0.35, core), ColorSequenceKeypoint.new(1, gold)}),
Transparency=NumberSequence.new({kp(0,0.08), kp(0.72,0.28), kp(1,1)}),
WidthScale=NumberSequence.new({kp(0,spec[3]*0.55), kp(0.25,spec[3]*0.38), kp(1,0)}),
Parent=hrp
})
end
-- Extra high-energy flecks around the lower edge of the streak.
vfxObj.divineParticles = new("ParticleEmitter", {
Texture="rbxassetid://243098098", Rate=38, Lifetime=NumberRange.new(0.35,0.9),
Speed=NumberRange.new(5,13), SpreadAngle=Vector2.new(35,35),
EmissionDirection=Enum.NormalId.Bottom, Acceleration=Vector3.new(0,-5,0),
Color=ColorSequence.new({ColorSequenceKeypoint.new(0, white), ColorSequenceKeypoint.new(0.45, gold), ColorSequenceKeypoint.new(1, Color3.fromRGB(255,110,25))}),
Size=NumberSequence.new({kp(0,0.22), kp(0.35,0.48), kp(1,0)}),
Transparency=NumberSequence.new({kp(0,0.02), kp(1,1)}),
LightEmission=1, Rotation=NumberRange.new(0,360), RotSpeed=NumberRange.new(-140,140),
Parent=sa
})
end
end
if feat.fire then
EC = visualColor("fire")
local style = feat.visualStyles.fire or "Flame Pillars"
local rate, life, speed, spread, accel = 60, NumberRange.new(0.5,1), NumberRange.new(3,6), Vector2.new(15,15), Vector3.new(0,2,0)
if style == "Ember Swarm" then rate,life,speed,spread,accel = 95,NumberRange.new(0.35,0.85),NumberRange.new(0.5,4),Vector2.new(180,180),Vector3.new(0,0.8,0)
elseif style == "Fire Spiral" then rate,life,speed,spread,accel = 38,NumberRange.new(0.8,1.5),NumberRange.new(2,4),Vector2.new(45,45),Vector3.new(0,3,0)
elseif style == "Inferno Burst" then rate,life,speed,spread,accel = 24,NumberRange.new(0.25,0.55),NumberRange.new(8,14),Vector2.new(180,180),Vector3.new(0,-1,0) end
vfxObj.fire = new("ParticleEmitter",{Texture="rbxassetid://243098098",Rate=rate,Lifetime=life,Speed=speed,SpreadAngle=spread,Shape=style=="Fire Spiral" and Enum.ParticleEmitterShape.Cylinder or Enum.ParticleEmitterShape.Sphere,ShapeStyle=Enum.ParticleEmitterShapeStyle.Volume,Acceleration=accel,EmissionDirection=Enum.NormalId.Top,Color=ColorSequence.new({ColorSequenceKeypoint.new(0,Color3.new(math.min(EC.R+0.3,1),math.min(EC.G+0.3,1),math.min(EC.B+0.3,1))),ColorSequenceKeypoint.new(0.4,EC),ColorSequenceKeypoint.new(1,Color3.new(EC.R*0.3,EC.G*0.3,EC.B*0.3))}),Size=NumberSequence.new({NumberSequenceKeypoint.new(0,style=="Flame Pillars" and 1 or 0.6),NumberSequenceKeypoint.new(0.45,style=="Inferno Burst" and 0.45 or 0.85),NumberSequenceKeypoint.new(1,0)}),Transparency=NumberSequence.new({NumberSequenceKeypoint.new(0,0.1),NumberSequenceKeypoint.new(1,1)}),LightEmission=1,RotSpeed=NumberRange.new(-80,80),Parent=hrp})
end
if feat.sparkle then
EC = visualColor("sparkle")
local style = feat.visualStyles.sparkle or "Starfall"
local rate,life,speed,spread = 25,NumberRange.new(1.2,2.2),NumberRange.new(0,0.5),Vector2.new(180,180)
if style == "Orbiting Dust" then rate,life,speed,spread = 48,NumberRange.new(2.4,4.2),NumberRange.new(0.05,0.25),Vector2.new(35,35)
elseif style == "Pulse Stars" then rate,life,speed,spread = 12,NumberRange.new(0.55,0.95),NumberRange.new(1,2),Vector2.new(180,180)
elseif style == "Crystal Shards" then rate,life,speed,spread = 18,NumberRange.new(0.8,1.5),NumberRange.new(0.2,1.8),Vector2.new(80,80) end
vfxObj.sparkle = new("ParticleEmitter",{Texture="rbxassetid://243098098",Rate=rate,Lifetime=life,Speed=speed,SpreadAngle=spread,Shape=style=="Orbiting Dust" and Enum.ParticleEmitterShape.Sphere or Enum.ParticleEmitterShape.Box,ShapeStyle=Enum.ParticleEmitterShapeStyle.Volume,Color=ColorSequence.new({ColorSequenceKeypoint.new(0,EC:Lerp(Color3.new(1,1,1),0.4)),ColorSequenceKeypoint.new(1,EC)}),Size=NumberSequence.new({NumberSequenceKeypoint.new(0,style=="Crystal Shards" and 0.5 or 0.3),NumberSequenceKeypoint.new(0.4,style=="Pulse Stars" and 1.2 or 0.7),NumberSequenceKeypoint.new(1,0)}),Transparency=NumberSequence.new({NumberSequenceKeypoint.new(0,0),NumberSequenceKeypoint.new(1,1)}),LightEmission=1,Rotation=NumberRange.new(0,360),RotSpeed=NumberRange.new(style=="Crystal Shards" and -180 or -50,style=="Crystal Shards" and 180 or 50),Parent=hrp})
end
if feat.halo then
EC = visualColor("halo")
local anchor = char:FindFirstChild("Head") or hrp
local model = new("Model",{Name="OwoHalo",Parent=workspace})
local haloStyle = feat.visualStyles.halo or "Orbit Halo"
local R, SEG = (haloStyle == "Solar Crown" and 1.18 or 1.05), (haloStyle == "Broken Halo" and 32 or 40)
local layers = {
{0.16, 0.09, 0.0, EC:Lerp(Color3.new(1,1,1), 0.25)},
{0.42, 0.04, 0.72, EC},
{0.8, 0.03, 0.88, EC},
}
if haloStyle == "Double Halo" then layers[#layers+1] = {0.95,0.025,0.55,EC:Lerp(Color3.new(1,1,1),0.35)}
elseif haloStyle == "Solar Crown" then layers = {{0.15,0.11,0,Color3.fromRGB(255,240,175)},{0.6,0.045,0.12,EC},{0.96,0.025,0.48,Color3.fromRGB(255,195,75)}} end
local parts, locals, core = {}, {}, {}
for li, L in ipairs(layers) do
for i = 1, SEG do
local th = i / SEG * math.pi * 2
local pt = new("Part",{Anchored=true,CanCollide=false,CanQuery=false,CanTouch=false,CastShadow=false,Material=Enum.Material.Neon,Color=L[4],Transparency=L[3],Size=Vector3.new(math.pi*2*R/SEG*1.12, L[2], L[1]),Parent=model})
parts[#parts+1] = pt
local plane = CFrame.new()
if haloStyle == "Double Halo" then plane = CFrame.Angles(math.rad(li*14),0,math.rad((li%2==0 and 1 or -1)*18))
elseif haloStyle == "Broken Halo" then plane = CFrame.Angles(math.rad(8),0,math.rad(10))
elseif haloStyle == "Solar Crown" then plane = CFrame.Angles(math.rad(24),0,math.rad(6)) end
locals[#locals+1] = plane * CFrame.Angles(0, th, 0) * CFrame.new(0, haloStyle=="Solar Crown" and (li-2)*0.12 or 0, -R)
if haloStyle == "Broken Halo" and (i % 8 == 0 or i % 8 == 1) then pt.Transparency = 1 end
if li == 1 then core[#core+1] = {p=pt, th=th} end
end
end
local att = new("Attachment",{Parent=anchor})
vfxObj.haloSpark = new("ParticleEmitter",{Texture="rbxassetid://243098098",Rate=5,Lifetime=NumberRange.new(0.8,1.3),Speed=NumberRange.new(0.2,0.5),SpreadAngle=Vector2.new(60,60),EmissionDirection=Enum.NormalId.Top,Color=ColorSequence.new(EC),Size=NumberSequence.new({NumberSequenceKeypoint.new(0,0.18),NumberSequenceKeypoint.new(1,0)}),Transparency=NumberSequence.new({NumberSequenceKeypoint.new(0,0.2),NumberSequenceKeypoint.new(1,1)}),LightEmission=1,Parent=att})
vfxObj.haloAtt = att
vfxObj.haloLight = new("PointLight",{Color=EC,Range=9,Brightness=2.2,Parent=anchor})
vfxObj.halo = model
local cfs, t = table.create(#parts), 0
vfxObj.haloC = RS.RenderStepped:Connect(function(dt)
if not anchor.Parent then return end
t += dt
local yOff = (anchor == hrp and 3.4 or anchor.Size.Y * 0.5 + 0.75) + math.sin(t * 2) * 0.08
local base = anchor.CFrame * CFrame.new(0, yOff, 0.15) * CFrame.Angles(math.rad(-14), t * 0.5, 0)
for i, lc in ipairs(locals) do cfs[i] = base * lc end
workspace:BulkMoveTo(parts, cfs, Enum.BulkMoveMode.FireCFrameChanged)
for _, c in ipairs(core) do c.p.Transparency = 0.25 - 0.25 * math.max(math.cos(c.th - t * 2.2), 0) ^ 6 end
end)
end
if feat.wings then
EC = visualColor("wings")
local wingStyle = feat.wingsStyle or "Crystal"
local model = new("Model",{Name="OwoWings_"..wingStyle:gsub("%s",""),Parent=workspace})
local ice = EC
if wingStyle == "Angel" then ice = Color3.fromRGB(255, 250, 235)
elseif wingStyle == "Butterfly" then ice = Color3.fromRGB(255, 115, 205)
elseif wingStyle == "Dark Angel" then ice = Color3.fromRGB(35, 25, 52)
elseif wingStyle == "Neon" then ice = Color3.fromRGB(70, 245, 255)
elseif wingStyle == "Fairy" then ice = Color3.fromRGB(170, 255, 220) end
local parts, locals = {}, {}
local function addWingPart(part, side, localCF)
part.Anchored = true; part.CanCollide = false; part.CanQuery = false; part.CanTouch = false; part.CastShadow = false
part.Parent = model
parts[#parts+1] = part
locals[#locals+1] = {side, localCF}
end
local function plate(side, pos, size, color, material, transparency, rot, shape)
local part = new("Part", {
Name="WingPlate", Shape=shape or Enum.PartType.Block, Size=size,
Material=material or Enum.Material.Glass, Color=color or ice,
Transparency=transparency == nil and 0.2 or transparency,
Reflectance=material == Enum.Material.Glass and 0.12 or 0,
})
addWingPart(part, side, CFrame.new(pos) * (rot or CFrame.new()))
return part
end
local function shard(side, angleDeg, length, y, depth, color, width)
local a = math.rad(angleDeg)
local direction = Vector3.new(side * math.cos(a), math.sin(a), depth).Unit
local look = (Vector3.new(0,0,1) - direction * direction:Dot(Vector3.new(0,0,1))).Unit
local vz = -direction
local vy = vz:Cross(look)
local frame = CFrame.fromMatrix(direction * (length*0.5) + Vector3.new(0,y,0), look, vy, vz)
local w = width or (0.16 + length*0.045)
for _, half in ipairs({CFrame.new(0,w*0.5,0), CFrame.new(0,-w*0.5,0)*CFrame.Angles(0,0,math.pi)}) do
local mat = wingStyle == "Neon" and Enum.Material.Neon or Enum.Material.Glass
local part = new("WedgePart", {Name="WingShard", Size=Vector3.new(0.08,w,length), Material=mat, Color=color or ice, Transparency=wingStyle=="Neon" and 0.08 or 0.22, Reflectance=0.18})
addWingPart(part, side, frame * half)
end
end
for _, side in ipairs({-1,1}) do
if wingStyle == "Butterfly" then
-- Four broad, rounded lobes per side with visible spots and vein lines.
local rot = side * 0.32
plate(side, Vector3.new(side*1.12,0.62,0.08), Vector3.new(1.22,1.68,0.16), ice, Enum.Material.Glass, 0.12, CFrame.Angles(0,0,rot), Enum.PartType.Ball)
plate(side, Vector3.new(side*1.00,-0.68,0.10), Vector3.new(0.98,1.25,0.14), ice:Lerp(Color3.fromRGB(255,225,250),0.25), Enum.Material.Glass, 0.16, CFrame.Angles(0,0,-rot*1.2), Enum.PartType.Ball)
plate(side, Vector3.new(side*1.23,0.68,-0.025), Vector3.new(0.43,0.55,0.08), Color3.fromRGB(255,240,190), Enum.Material.Neon, 0.08, CFrame.Angles(0,0,rot), Enum.PartType.Ball)
plate(side, Vector3.new(side*1.04,-0.70,-0.01), Vector3.new(0.30,0.38,0.07), Color3.fromRGB(110,70,180), Enum.Material.Neon, 0.12, CFrame.Angles(0,0,-rot), Enum.PartType.Ball)
for _, pair in ipairs({{0.1,0.95},{0.18,0.25},{0.05,-0.42},{-0.15,-0.95}}) do
local x = side * (0.3 + math.abs(pair[1])*0.95)
local y = pair[2]*0.62
local from = Vector3.new(side*0.23,0.02, -0.04)
local to = Vector3.new(x,y,-0.04)
local mid = (from+to)*0.5
local line = new("Part", {Name="WingVein", Size=Vector3.new(0.025,0.025,(to-from).Magnitude), Material=Enum.Material.Neon, Color=Color3.fromRGB(255,245,220), Transparency=0.15, CFrame=CFrame.lookAt(mid,to)})
addWingPart(line,side,CFrame.new(mid)*CFrame.lookAt(Vector3.zero,to-from))
end
elseif wingStyle == "Moth" then
-- Wide moth wings with scalloped lobes and bright eyespots; much broader than butterfly.
for j, lobe in ipairs({{0.95,0.78,1.18,1.28},{1.42,0.28,1.05,1.15},{1.36,-0.55,0.95,0.96},{0.83,-0.94,0.82,0.70}}) do
local x,y,w,h = lobe[1],lobe[2],lobe[3],lobe[4]
plate(side,Vector3.new(side*x,y,0.04),Vector3.new(w,h,0.13),j%2==0 and ice:Lerp(Color3.fromRGB(255,225,170),0.22) or ice,Enum.Material.SmoothPlastic,0.10,CFrame.Angles(0,0,math.rad(side*(18-j*3))),Enum.PartType.Ball)
plate(side,Vector3.new(side*(x+0.12),y+0.08,-0.045),Vector3.new(w*0.24,h*0.24,0.06),Color3.fromRGB(255,230,155),Enum.Material.Neon,0.06,CFrame.Angles(0,0,math.rad(side*18)),Enum.PartType.Ball)
plate(side,Vector3.new(side*(x+0.12),y+0.08,-0.09),Vector3.new(w*0.12,h*0.12,0.035),Color3.fromRGB(30,35,65),Enum.Material.Neon,0.02,nil,Enum.PartType.Ball)
end
elseif wingStyle == "Dragon" then
-- Bat/dragon wing: long finger spars with membrane panels between them.
local root = Vector3.new(side*0.25,0,0.13)
local tips = {Vector3.new(side*1.0,1.65,0.12),Vector3.new(side*2.0,1.18,0.12),Vector3.new(side*2.35,0.1,0.12),Vector3.new(side*2.0,-1.05,0.12),Vector3.new(side*1.05,-1.32,0.12)}
for j=1,#tips do
local a,b = (j==1 and root or tips[j-1]), tips[j]
local d=b-a; local mid=(a+b)*0.5
local spar=new("Part",{Name="DragonSpar",Size=Vector3.new(0.11,0.11,d.Magnitude),Material=Enum.Material.Slate,Color=ice,Transparency=0.02})
addWingPart(spar,side,CFrame.new(mid)*CFrame.lookAt(Vector3.zero,d))
if j>1 then
local prev=tips[j-1]
local center=Vector3.new(side*(0.6+j*0.24), (prev.Y+b.Y)*0.5,0.20)
plate(side,center,Vector3.new(0.68,0.92,0.06),ice,Enum.Material.Glass,0.45,CFrame.Angles(0,0,math.rad(side*(j%2==0 and 25 or -25))),Enum.PartType.Ball)
end
end
elseif wingStyle == "Mechanical" then
-- Mechanical fan: stacked metal plates, glowing joints, and rigid turbine vanes.
for j=1,7 do
local angle=math.rad(68-(j-1)*22)
local len=1.15+(j%3)*0.38
local x=side*(0.45+(j-1)*0.22); local y=0.65-(j-1)*0.24
plate(side,Vector3.new(x,y,0.08),Vector3.new(0.22,len,0.18),j%2==0 and Color3.fromRGB(90,115,135) or ice,Enum.Material.Metal,0.03,CFrame.Angles(0,0,-angle),Enum.PartType.Block)
local joint=plate(side,Vector3.new(x,y,-0.04),Vector3.new(0.15,0.15,0.08),Color3.fromRGB(90,245,255),Enum.Material.Neon,0.02,nil,Enum.PartType.Ball)
end
for j=1,4 do
local a=Vector3.new(side*0.25,0.05,0.03)
local b=Vector3.new(side*(0.65+j*0.38),1.15-j*0.55,0.03)
local d=b-a; local rod=new("Part",{Name="MechanicalWingRail",Size=Vector3.new(0.09,0.09,d.Magnitude),Material=Enum.Material.Neon,Color=ice,Transparency=0.02})
addWingPart(rod,side,CFrame.new((a+b)*0.5)*CFrame.lookAt(Vector3.zero,d))
end
elseif wingStyle == "Void" then
-- Dark crescent feathers form a ragged, hollow-looking silhouette.
local voidColors={Color3.fromRGB(13,10,28),Color3.fromRGB(42,18,72),Color3.fromRGB(83,45,135)}
for j=1,8 do
local angle=82-(j-1)*20
local len=1.45+(j%3)*0.45
local y=0.88-(j-1)*0.23
shard(side,angle,len,y,0.12+(j%2)*0.12,voidColors[(j-1)%#voidColors+1],0.24)
end
plate(side,Vector3.new(side*0.9,0.1,-0.02),Vector3.new(0.14,1.5,0.08),Color3.fromRGB(155,85,255),Enum.Material.Neon,0.03,CFrame.Angles(0,0,math.rad(side*16)),Enum.PartType.Block)
elseif wingStyle == "Angel" then
-- Layered feather blades plus soft rounded feather tips; visibly feathery rather than crystal spikes.
for i=1,9 do
local y = 1.05 - (i-1)*0.27
local len = 1.05 + math.sin(i/9*math.pi)*0.65
local x = side*(0.38 + (i-1)*0.13)
local angle = math.rad(side*(30 + i*5))
plate(side, Vector3.new(x,y,0.08), Vector3.new(0.28,len,0.16), ice:Lerp(Color3.new(1,1,1),0.22), Enum.Material.SmoothPlastic, 0.05, CFrame.Angles(0,0,-angle), Enum.PartType.Ball)
shard(side, 75-(i-1)*17, len*0.72, y-0.1, 0.12, ice, 0.12)
end
-- A top pair of long pinion feathers gives the silhouette a high arch.
shard(side,66,3.15,0.65,0.02,Color3.fromRGB(255,255,245),0.2)
shard(side,44,2.55,0.2,0.02,ice,0.17)
elseif wingStyle == "Dark Angel" then
-- Jagged overlapping black feathers, with longer torn outer tips.
for i=1,10 do
local y = 1.2-(i-1)*0.24
local len = (i<4 and 2.15 or 1.15) + (i%3)*0.22
shard(side, 83-(i-1)*15, len, y, 0.16+(i%2)*0.12, i%2==0 and Color3.fromRGB(80,62,115) or ice, 0.22)
plate(side,Vector3.new(side*(0.55+(i-1)*0.105),y-0.12,0.18),Vector3.new(0.16,len*0.62,0.10),Color3.fromRGB(16,13,24),Enum.Material.Slate,0.08,CFrame.Angles(0,0,math.rad(side*(25+i*4))),Enum.PartType.Block)
end
shard(side,88,3.5,0.9,0.28,Color3.fromRGB(20,15,28),0.19)
shard(side,-48,2.5,-0.5,0.25,Color3.fromRGB(20,15,28),0.18)
elseif wingStyle == "Fairy" then
-- Two tiers of small translucent oval wings, not a scaled recolor of the crystal set.
for _, lobe in ipairs({{0.62,0.82,0.86,0.42},{0.52,-0.05,0.72,0.48},{1.05,0.30,0.65,-0.36},{0.86,-0.52,0.52,-0.42}}) do
local x,y,w,h = lobe[1],lobe[2],lobe[3],lobe[4]
plate(side,Vector3.new(side*x,y,0.02),Vector3.new(w,math.abs(h)*1.9,0.12),ice,Enum.Material.Glass,0.36,CFrame.Angles(0,0,math.rad(side*(h>0 and 24 or -24))),Enum.PartType.Ball)
plate(side,Vector3.new(side*(x+0.04),y, -0.055),Vector3.new(w*0.18,math.abs(h)*1.15,0.045),Color3.fromRGB(255,255,255),Enum.Material.Neon,0.20,CFrame.Angles(0,0,math.rad(side*(h>0 and 24 or -24))),Enum.PartType.Ball)
end
elseif wingStyle == "Neon" then
-- Angular wireframe wing with a few translucent facet panels.
local pts = {Vector3.new(side*0.22,0.08,0.08),Vector3.new(side*1.0,1.05,0.08),Vector3.new(side*2.25,1.32,0.08),Vector3.new(side*2.0,0.25,0.08),Vector3.new(side*1.82,-0.72,0.08),Vector3.new(side*0.72,-1.05,0.08),Vector3.new(side*0.22,0.08,0.08)}
for i=1,#pts-1 do
local a,b=pts[i],pts[i+1]; local len=(b-a).Magnitude; local mid=(a+b)*0.5
local rod=new("Part",{Name="NeonWingFrame",Size=Vector3.new(0.075,0.075,len),Material=Enum.Material.Neon,Color=ice,Transparency=0.02})
addWingPart(rod,side,CFrame.new(mid)*CFrame.lookAt(Vector3.zero,b-a))
end
plate(side,Vector3.new(side*1.2,0.15,0.12),Vector3.new(1.1,1.55,0.08),ice,Enum.Material.Neon,0.72,CFrame.Angles(0,0,math.rad(side*25)),Enum.PartType.Ball)
shard(side,70,2.4,0.5,0.15,ice,0.09)
else
-- Crystal: asymmetric, faceted shards with a clear spike silhouette.
local crystal = {{83,2.7,0.12},{64,3.5,0.18},{44,4.4,0.24},{24,4.8,0.30},{5,4.1,0.34},{-16,3.2,0.36},{-38,2.35,0.38}}
for i,sp in ipairs(crystal) do
shard(side,sp[1],sp[2],0.25-(i-1)*0.13,sp[3],i%2==0 and ice:Lerp(Color3.new(1,1,1),0.22) or ice,0.18+sp[2]*0.035)
end
-- A second slim facet along the outer edge makes the crystal appear cut, not feathered.
shard(side,58,3.0,-0.05,0.02,Color3.fromRGB(235,250,255),0.07)
end
end
if feat.visualColors.wings then
for _, wingPart in ipairs(model:GetDescendants()) do
if wingPart:IsA("BasePart") then wingPart.Color = feat.visualColors.wings end
end
end
vfxObj.wingHl = new("Highlight",{FillColor=visualColor("wings"),FillTransparency=0.72,OutlineColor=visualColor("wings"):Lerp(Color3.new(1,1,1),0.3),OutlineTransparency=0.15,DepthMode=Enum.HighlightDepthMode.Occluded,Adornee=model,Parent=model})
vfxObj.wingLight = new("PointLight",{Color=ice,Range=10,Brightness=1.6,Parent=hrp})
vfxObj.wingModel = model
local cfs, t = table.create(#parts), 0
vfxObj.wingC = RS.RenderStepped:Connect(function(dt)
if not hrp.Parent then return end
local air = hum:GetState() == Enum.HumanoidStateType.Freefall
t += dt * (air and 7 or 2.4)
local flap = math.rad(14 + math.sin(t) * (air and 16 or 9))
local base = hrp.CFrame * CFrame.new(0, 0.85, 0.62)
local wl = base * CFrame.new(-0.3, 0, 0) * CFrame.Angles(0, flap, 0)
local wr = base * CFrame.new(0.3, 0, 0) * CFrame.Angles(0, -flap, 0)
for i, lc in ipairs(locals) do cfs[i] = (lc[1] < 0 and wl or wr) * lc[2] end
workspace:BulkMoveTo(parts, cfs, Enum.BulkMoveMode.FireCFrameChanged)
end)
end
local head = char:FindFirstChild("Head")
if feat.crown and head then
EC = visualColor("crown")
local model = new("Model",{Name="OwoCrown",Parent=workspace})
local top = EC:Lerp(Color3.new(1, 1, 1), 0.45)
local R = math.clamp(head.Size.Z * 0.66, 0.6, 1.05)
local crownStyle = feat.visualStyles.crown or "Royal Points"
local SEG, PEAKS = 36, (crownStyle == "Triple Crown" and 3 or (crownStyle == "Jagged Crown" and 9 or (crownStyle == "Halo Circlet" and 0 or 4)))
local seg = math.pi * 2 * R / SEG * (crownStyle == "Halo Circlet" and 1.35 or 1.08)
local parts, angs = {}, {}
for i = 1, SEG do
local p = new("Part",{Anchored=true,CanCollide=false,CanQuery=false,CanTouch=false,CastShadow=false,Transparency=1,Size=Vector3.new(seg,1,0.02),Parent=model})
for _, face in ipairs({Enum.NormalId.Front, Enum.NormalId.Back}) do
local sg = new("SurfaceGui",{Face=face,SizingMode=Enum.SurfaceGuiSizingMode.FixedSize,CanvasSize=Vector2.new(16,96),LightInfluence=0,Brightness=2.5,AlwaysOnTop=false,Parent=p})
local f = new("Frame",{Size=UDim2.fromScale(1,1),BackgroundColor3=Color3.new(1,1,1),BorderSizePixel=0,Parent=sg})
new("UIGradient",{Rotation=90,
Color=ColorSequence.new({ColorSequenceKeypoint.new(0,top),ColorSequenceKeypoint.new(0.35,EC),ColorSequenceKeypoint.new(1,EC)}),
Transparency=NumberSequence.new({NumberSequenceKeypoint.new(0,0.55),NumberSequenceKeypoint.new(0.1,0.12),NumberSequenceKeypoint.new(0.45,0.5),NumberSequenceKeypoint.new(1,1)}),
Parent=f})
end
parts[i] = p
angs[i] = (i - 0.5) / SEG * math.pi * 2
end
local att = new("Attachment",{Parent=head})
vfxObj.crownSpark = new("ParticleEmitter",{Texture="rbxassetid://243098098",Rate=6,Lifetime=NumberRange.new(0.8,1.4),Speed=NumberRange.new(0.3,0.8),SpreadAngle=Vector2.new(25,25),EmissionDirection=Enum.NormalId.Top,Color=ColorSequence.new(EC),Size=NumberSequence.new({NumberSequenceKeypoint.new(0,0.2),NumberSequenceKeypoint.new(1,0)}),Transparency=NumberSequence.new({NumberSequenceKeypoint.new(0,0.3),NumberSequenceKeypoint.new(1,1)}),LightEmission=1,Parent=att})
vfxObj.crownAtt = att
vfxObj.crownLight = new("PointLight",{Color=EC,Range=8,Brightness=2,Parent=head})
vfxObj.crownModel = model
local cfs, t = table.create(SEG), 0
vfxObj.crownC = RS.RenderStepped:Connect(function(dt)
if not head.Parent then return end
t += dt
local base = head.CFrame * CFrame.new(0, head.Size.Y * 0.5 - 0.3, 0)
for i, p in ipairs(parts) do
local th = angs[i]
local h
if crownStyle == "Halo Circlet" then h = 0.34 + 0.04*math.sin(th*8+t*1.5)
elseif crownStyle == "Jagged Crown" then h = 0.62 + 0.7*(0.5+0.5*math.cos(th*PEAKS)) + 0.1*math.sin(th*13+t*1.7)
else h = 0.68 + 0.62 * (0.5 + 0.5 * math.cos(th * PEAKS + t * 0.9)) + 0.04 * math.sin(th * 7 - t * 1.7) end
p.Size = Vector3.new(seg, h, 0.02)
cfs[i] = base * CFrame.Angles(0, th, 0) * CFrame.new(0, h * 0.5, -R)
end
workspace:BulkMoveTo(parts, cfs, Enum.BulkMoveMode.FireCFrameChanged)
end)
end
if feat.jumpRing then
EC = visualColor("jumpRing")
vfxObj.jr = hum.StateChanged:Connect(function(_, ns)
if ns == Enum.HumanoidStateType.Jumping then
local h = char:FindFirstChild("HumanoidRootPart"); if not h then return end
local fp = h.Position - Vector3.new(0, 2.65, 0)
shock(fp, EC, 6.5, 6, 0.55, feat.visualStyles.jumpRing or "Double Shockwave")
burst(fp, EC, 14, false)
Fn.triggerShake(1.5)
end
end)
end
if feat.landRing then
EC = visualColor("landRing")
local wasAir = false
vfxObj.lr = hum.StateChanged:Connect(function(_, ns)
if ns == Enum.HumanoidStateType.Freefall then wasAir = true
elseif ns == Enum.HumanoidStateType.Landed and wasAir then
wasAir = false
local h = char:FindFirstChild("HumanoidRootPart"); if not h then return end
local fp = h.Position - Vector3.new(0, 2.65, 0)
local landStyle = feat.visualStyles.landRing or "Double Shockwave"
shock(fp, EC, 11, 8, 0.75, landStyle)
task.delay(0.08, function() shock(fp, EC, 7, 5, 0.6, landStyle) end)
burst(fp, EC, 28, true)
Fn.triggerShake(3.5)
end
end)
end
-- SANTA HAT (smooth, built from spheres - not blocky)
if feat.santaHat and head then
EC = visualColor("santaHat")
local model = new("Model",{Name="OwoSantaHat",Parent=char})
vfxObj.santaModel = model
local function weldPart(part, cf)
part.Anchored = false; part.CanCollide = false; part.CanQuery = false; part.CanTouch = false; part.CastShadow = false; part.Massless = true; part.Transparency = feat.santaTransparency
part.Parent = model
local w = Instance.new("Weld"); w.Part0 = head; w.Part1 = part; w.C0 = cf; w.Parent = part
end
local hatStyle = feat.visualStyles.santaHat or "Classic"
local R = math.clamp(math.max(head.Size.Y, head.Size.Z) * 0.6, 0.55, 0.9)
local base = CFrame.new(0, head.Size.Y * 0.5 - 0.12, 0.02) * CFrame.Angles(math.rad(hatStyle == "Long Flop" and -18 or -10), 0, math.rad(hatStyle == "Long Flop" and 17 or 5))
local red = hatStyle == "Frosted" and Color3.fromRGB(215,235,255) or (hatStyle == "Candy Trim" and Color3.fromRGB(205,25,42) or EC)
local white = Color3.fromRGB(250,248,242)
local hatMat = hatStyle == "Frosted" and Enum.Material.Glass or (hatStyle == "Candy Trim" and Enum.Material.SmoothPlastic or Enum.Material.SmoothPlastic)
local N = hatStyle == "Long Flop" and 24 or 16
local bendY = hatStyle == "Long Flop" and 1.65 or 1.0
local bendZ = hatStyle == "Long Flop" and 1.5 or 0.95
for i = 0, N do
local t = i / N
local r = R * (1.03 - 0.86 * t ^ 0.9)
local pos = Vector3.new(0, 0.06 + t * bendY - t ^ 3 * (bendY * 0.35), t ^ 2 * bendZ)
local bandColor = (hatStyle == "Candy Trim" and math.floor(t*8)%2 == 1) and white or red
weldPart(new("Part",{Shape=Enum.PartType.Ball,Size=Vector3.new(r*2,r*2,r*2),Material=hatMat,Color=bandColor,Transparency=hatStyle == "Frosted" and 0.08 or 0}), base * CFrame.new(pos))
end
weldPart(new("Part",{Shape=Enum.PartType.Cylinder,Size=Vector3.new(0.26,R*2.05,R*2.05),Material=hatStyle == "Frosted" and Enum.Material.Glass or Enum.Material.SmoothPlastic,Color=white}), base * CFrame.new(0, 0.02, 0) * CFrame.Angles(0, 0, math.rad(90)))
local FUR = hatStyle == "Candy Trim" and 28 or 20
for i = 1, FUR do
local th = i / FUR * math.pi * 2
local furColor = (hatStyle == "Candy Trim" and i%2==0) and red or white
weldPart(new("Part",{Shape=Enum.PartType.Ball,Size=Vector3.new(0.34,0.34,0.34),Material=Enum.Material.SmoothPlastic,Color=furColor}), base * CFrame.new(math.cos(th) * R * 1.0, 0.02, math.sin(th) * R * 1.0))
end
local tip = Vector3.new(0, 0.06 + bendY - bendY * 0.35, bendZ)
weldPart(new("Part",{Shape=Enum.PartType.Ball,Size=hatStyle == "Long Flop" and Vector3.new(0.34,0.34,0.34) or Vector3.new(0.46,0.46,0.46),Material=hatMat,Color=white}), base * CFrame.new(tip))
for _, o in ipairs({Vector3.new(0.17,0.05,0.1), Vector3.new(-0.17,0.05,0.1), Vector3.new(0,0.14,-0.12), Vector3.new(0,-0.12,0.12)}) do
weldPart(new("Part",{Shape=Enum.PartType.Ball,Size=Vector3.new(0.26,0.26,0.26),Material=Enum.Material.SmoothPlastic,Color=white}), base * CFrame.new(tip + o))
end
end
-- MOONWARE CAPE (black, with ☾ on the back, swings with your movement)
if feat.cape then
EC = visualColor("cape")
local capeStyle = feat.visualStyles.cape or "Royal Cape"
local N = capeStyle == "Hologram Cape" and 10 or 8
local LEN = math.clamp(feat.capeLength or 4.2, 2.5, 6.5)
if capeStyle == "Short Mantle" then LEN = math.min(LEN,2.8) elseif capeStyle == "Wing Cape" then LEN = math.min(LEN+0.4,5.2) end
local segL = LEN / N
local model = new("Model",{Name="OwoCape",Parent=workspace})
vfxObj.capeModel = model
local parts, cfs = {}, {}
for i = 1, N do
local taper = (i - 1) / math.max(N - 1,1)
local wdt = 2.1 * (1 + 0.2 * taper)
if capeStyle == "Short Mantle" then wdt = 1.8*(1+0.08*taper)
elseif capeStyle == "Wing Cape" then wdt = 1.55 + math.sin(taper*math.pi)*1.55
elseif capeStyle == "Hologram Cape" then wdt = 2.0 + 0.45*math.sin(taper*math.pi*3) end
local mat = capeStyle == "Hologram Cape" and Enum.Material.ForceField or (capeStyle == "Wing Cape" and Enum.Material.SmoothPlastic or Enum.Material.Fabric)
local col = feat.visualColors.cape or (capeStyle == "Hologram Cape" and EC:Lerp(Color3.new(1,1,1),0.5) or (capeStyle == "Royal Cape" and Color3.fromRGB(18,10,34) or Color3.fromRGB(10,10,12)))
parts[i] = new("Part",{Anchored=true,CanCollide=false,CanQuery=false,CanTouch=false,CastShadow=false,Material=mat,Color=col,Transparency=capeStyle=="Hologram Cape" and 0.38 or 0,Size=Vector3.new(wdt,segL+0.03,0.06),Parent=model})
end
local emblem = new("Part",{Anchored=true,CanCollide=false,CanQuery=false,CanTouch=false,CastShadow=false,Transparency=1,Size=Vector3.new(1.5,0.9,0.02),Parent=model})
local sgc = new("SurfaceGui",{Face=Enum.NormalId.Back,SizingMode=Enum.SurfaceGuiSizingMode.FixedSize,CanvasSize=Vector2.new(300,180),LightInfluence=0,Brightness=1.4,Parent=emblem})
moonwareLogo(sgc, 112, UDim2.new(0.5,-56,0.5,-56), Color3.fromRGB(255,215,125), col, 0, 2, "CapeMoonwareMark")
local hem = new("Part",{Anchored=true,CanCollide=false,CanQuery=false,CanTouch=false,CastShadow=false,Material=Enum.Material.Neon,Color=capeStyle=="Royal Cape" and Color3.fromRGB(255,196,80) or EC,Transparency=capeStyle=="Hologram Cape" and 0.25 or 0,Size=Vector3.new(capeStyle=="Wing Cape" and 3.2 or (capeStyle=="Short Mantle" and 1.9 or 2.5),0.07,0.09),Parent=model})
local collar = new("Part",{Anchored=true,CanCollide=false,CanQuery=false,CanTouch=false,CastShadow=false,Material=Enum.Material.Neon,Color=EC,Size=Vector3.new(2.1,0.07,0.1),Parent=model})
parts[#parts+1] = emblem; parts[#parts+1] = hem; parts[#parts+1] = collar
local ang = table.create(N, 0.1)
local t = 0
vfxObj.capeC = RS.RenderStepped:Connect(function(dt)
if not hrp.Parent then return end
t += dt
local v = hrp.AssemblyLinearVelocity
local vf = v:Dot(hrp.CFrame.LookVector)
local vy = v.Y
local target = math.clamp(vf * 0.024, -0.15, 1.0) + math.clamp(-vy * 0.012, -0.25, 0.7)
target = math.clamp(target, 0.0, 1.3)
local sp = math.clamp(v.Magnitude * 0.05, 0, 1.5)
for i = 1, N do
local k = i / N
local want = 0.09 + target * (0.5 + 0.75 * k) + math.sin(t * (3 + sp * 3) - k * 2.4) * 0.06 * (0.3 + target)
ang[i] += (want - ang[i]) * (1 - math.exp(-dt * (15 - 8 * k)))
end
local rootCF = hrp.CFrame * CFrame.new(0, 0.95, 0.56)
local pos = rootCF.Position
local rot = rootCF - rootCF.Position
for i = 1, N do
local o = rot * CFrame.Angles(-ang[i], 0, math.sin(t * 1.7 + i * 0.5) * 0.015 * i)
cfs[i] = CFrame.new(pos) * o * CFrame.new(0, -segL * 0.5, 0)
pos = (cfs[i] * CFrame.new(0, -segL * 0.5, 0)).Position
end
cfs[N+1] = cfs[3] * CFrame.new(0, 0, 0.04)
cfs[N+2] = cfs[N] * CFrame.new(0, -segL * 0.5, 0)
cfs[N+3] = cfs[1] * CFrame.new(0, segL * 0.5, 0)
workspace:BulkMoveTo(parts, cfs, Enum.BulkMoveMode.FireCFrameChanged)
end)
end
-- BACK PICKAXE COSMETIC: welded to the character, purely decorative.
-- Right-click the toggle to switch skins; Candy Cane is the default.
if feat.pickaxe then
local skin = feat.visualStyles.pickaxe or feat.pickaxeSkin or "Candy Cane"
local model = new("Model", {Name="OwoBackPickaxe", Parent=char})
vfxObj.pickaxeModel = model
local custom = feat.visualColors.pickaxe
local candyRed = custom or Color3.fromRGB(218, 28, 52)
local candyWhite = Color3.fromRGB(255, 249, 235)
local shaftColor = Color3.fromRGB(95, 53, 31)
local headColor = Color3.fromRGB(105, 115, 129)
local accentColor = Color3.fromRGB(255, 205, 95)
local mat = Enum.Material.SmoothPlastic
if skin == "Golden" then
shaftColor, headColor, accentColor = Color3.fromRGB(130, 79, 24), custom or Color3.fromRGB(255, 190, 42), Color3.fromRGB(255, 235, 135)
mat = Enum.Material.Metal
elseif skin == "Crystal" then
shaftColor, headColor, accentColor = Color3.fromRGB(30, 48, 80), custom or Color3.fromRGB(98, 218, 255), Color3.fromRGB(210, 250, 255)
mat = Enum.Material.Glass
elseif skin == "Candy Cane" then
shaftColor, headColor, accentColor = candyRed, candyWhite, Color3.fromRGB(255, 219, 122)
else
shaftColor, headColor, accentColor = Color3.fromRGB(112, 73, 47), custom or Color3.fromRGB(100, 112, 126), Color3.fromRGB(180, 190, 200)
mat = Enum.Material.Metal
end
-- +Z is the back of a standard Roblox character.
local base = CFrame.new(-0.12, 0.12, 0.66) * CFrame.Angles(0, 0, math.rad(-27))
local function part(name, size, color, localCF, material, shape, transparency)
local props = {
Name=name, Size=size, Color=color, Material=material or mat,
CFrame=hrp.CFrame * localCF, Anchored=false, CanCollide=false,
CanQuery=false, CanTouch=false, CastShadow=false, Massless=true,
Transparency=transparency or 0, Parent=model
}
if shape then props.Shape=shape end
local obj = new("Part", props)
new("Weld", {Name="OwoPickaxeWeld", Part0=hrp, Part1=obj, C0=localCF, C1=CFrame.new(), Parent=obj})
return obj
end
local function rod(name, a, b, thick, color, material)
local d = b-a
if d.Magnitude < 0.02 then return end
local cf = base * CFrame.lookAt((a+b)*0.5, b)
return part(name, Vector3.new(thick, thick, d.Magnitude), color, cf, material or mat)
end
if skin == "Candy Cane" then
-- Candy cane has a tall striped shaft and a hooked, candy-cane silhouette.
for i=1,10 do
local y0 = -1.13 + (i-1)*0.225
local y1 = y0 + 0.235
rod("CandyCaneShaftBand"..i, Vector3.new(0,y0,0), Vector3.new(0,y1,0), 0.17, i%2==0 and candyWhite or candyRed, Enum.Material.SmoothPlastic)
end
local curve = {
Vector3.new(-1.00,1.02,0), Vector3.new(-0.88,1.28,0),
Vector3.new(-0.64,1.43,0), Vector3.new(-0.38,1.42,0),
Vector3.new(-0.17,1.25,0), Vector3.new(-0.05,1.02,0),
Vector3.new(0.16,0.94,0), Vector3.new(0.42,1.00,0),
Vector3.new(0.67,1.17,0), Vector3.new(0.91,1.36,0),
Vector3.new(1.02,1.31,0)
}
for i=1,#curve-1 do
rod("CandyCaneHeadStripe"..i, curve[i], curve[i+1], 0.23, i%2==0 and candyWhite or candyRed, Enum.Material.SmoothPlastic)
end
part("CandyCaneTipLeft", Vector3.new(0.22,0.22,0.22), candyWhite, base*CFrame.new(-1.0,1.02,0), Enum.Material.SmoothPlastic, Enum.PartType.Ball)
part("CandyCaneTipRight", Vector3.new(0.20,0.20,0.20), candyWhite, base*CFrame.new(1.02,1.31,0), Enum.Material.SmoothPlastic, Enum.PartType.Ball)
part("CandyCaneGoldCollar", Vector3.new(0.27,0.20,0.22), accentColor, base*CFrame.new(0,-0.82,0), Enum.Material.Metal)
for i=1,3 do part("CandyCaneCandyGem"..i, Vector3.new(0.09,0.09,0.09), accentColor, base*CFrame.new(0.02,0.42+(i*0.18),-0.10), Enum.Material.Neon, Enum.PartType.Ball) end
elseif skin == "Classic Iron" then
-- Traditional pickaxe: a long timber haft and a sharply hooked metal head.
part("IronWoodHaft", Vector3.new(0.19,2.58,0.19), shaftColor, base*CFrame.new(0,0,0), Enum.Material.Wood)
part("IronLowerGrip", Vector3.new(0.25,0.52,0.24), Color3.fromRGB(63,43,32), base*CFrame.new(0,-0.78,-0.015), Enum.Material.SmoothPlastic)
part("IronPommel", Vector3.new(0.27,0.22,0.24), Color3.fromRGB(78,84,91), base*CFrame.new(0,-1.28,0), Enum.Material.Metal, Enum.PartType.Ball)
-- Uneven hooked ends create a recognisable old mining pick silhouette.
rod("IronHeadSpine", Vector3.new(-0.88,1.03,0), Vector3.new(0.80,1.03,0), 0.24, headColor, Enum.Material.Metal)
rod("IronLeftHookA", Vector3.new(-0.88,1.03,0), Vector3.new(-1.13,1.31,0), 0.22, headColor, Enum.Material.Metal)
rod("IronLeftHookB", Vector3.new(-1.13,1.31,0), Vector3.new(-0.94,1.53,0), 0.17, accentColor, Enum.Material.Metal)
rod("IronRightBeakA", Vector3.new(0.72,1.03,0), Vector3.new(1.03,0.85,0), 0.23, headColor, Enum.Material.Metal)
rod("IronRightBeakB", Vector3.new(1.03,0.85,0), Vector3.new(1.20,0.55,0), 0.14, accentColor, Enum.Material.Metal)
part("IronHeadSocket", Vector3.new(0.34,0.32,0.28), Color3.fromRGB(185,193,202), base*CFrame.new(0,1.02,-0.015), Enum.Material.Metal, Enum.PartType.Ball)
for i=1,3 do part("IronRivet"..i, Vector3.new(0.075,0.075,0.075), Color3.fromRGB(210,215,220), base*CFrame.new(-0.12+(i-1)*0.12,0.96,-0.17), Enum.Material.Metal, Enum.PartType.Ball) end
elseif skin == "Golden" then
-- Royal double-bladed head with flared wings, crown teeth, and inset jewels.
part("GoldenShaft", Vector3.new(0.17,2.48,0.17), shaftColor, base*CFrame.new(0,0,0), Enum.Material.Metal)
for i=1,4 do part("GoldenShaftRing"..i, Vector3.new(0.25,0.10,0.25), accentColor, base*CFrame.new(0,-0.70+(i*0.36),0), Enum.Material.Metal, Enum.PartType.Cylinder) end
part("GoldenHeadCore", Vector3.new(0.33,0.40,0.30), accentColor, base*CFrame.new(0,1.08,0), Enum.Material.Metal, Enum.PartType.Ball)
part("GoldenLeftWing", Vector3.new(0.92,0.25,0.30), headColor, base*CFrame.new(-0.62,1.10,0)*CFrame.Angles(0,0,math.rad(-18)), Enum.Material.Metal, Enum.PartType.Wedge)
part("GoldenRightWing", Vector3.new(0.92,0.25,0.30), headColor, base*CFrame.new(0.62,1.10,0)*CFrame.Angles(0,0,math.rad(198)), Enum.Material.Metal, Enum.PartType.Wedge)
part("GoldenLeftSpike", Vector3.new(0.38,0.54,0.28), accentColor, base*CFrame.new(-1.05,1.18,0)*CFrame.Angles(0,0,math.rad(-28)), Enum.Material.Metal, Enum.PartType.Wedge)
part("GoldenRightSpike", Vector3.new(0.38,0.54,0.28), accentColor, base*CFrame.new(1.05,1.18,0)*CFrame.Angles(0,0,math.rad(208)), Enum.Material.Metal, Enum.PartType.Wedge)
part("GoldenCrownTooth", Vector3.new(0.28,0.40,0.24), accentColor, base*CFrame.new(0,1.42,0), Enum.Material.Metal, Enum.PartType.Wedge)
part("GoldenSunGem", Vector3.new(0.32,0.32,0.20), Color3.fromRGB(255,255,200), base*CFrame.new(0,1.08,-0.18), Enum.Material.Neon, Enum.PartType.Ball)
part("GoldenBackGem", Vector3.new(0.20,0.20,0.18), Color3.fromRGB(255,126,36), base*CFrame.new(0,1.08,0.18), Enum.Material.Neon, Enum.PartType.Ball)
elseif skin == "Crystal" then
-- Asymmetric crystal cluster: no straight metal bar, just jagged translucent facets.
part("CrystalObsidianShaft", Vector3.new(0.17,2.52,0.17), shaftColor, base*CFrame.new(0,0,0), Enum.Material.Slate)
part("CrystalGrip", Vector3.new(0.24,0.58,0.22), Color3.fromRGB(30,72,92), base*CFrame.new(0,-0.73,0), Enum.Material.Slate)
part("CrystalMainShard", Vector3.new(0.46,0.92,0.28), headColor, base*CFrame.new(-0.42,1.22,0)*CFrame.Angles(0,0,math.rad(28)), Enum.Material.Glass, Enum.PartType.Wedge, 0.08)
part("CrystalOuterShard", Vector3.new(0.38,0.70,0.25), accentColor, base*CFrame.new(-0.80,1.12,0.015)*CFrame.Angles(0,0,math.rad(-28)), Enum.Material.Glass, Enum.PartType.Wedge, 0.10)
part("CrystalLongBeak", Vector3.new(0.48,0.86,0.27), headColor, base*CFrame.new(0.42,1.17,0)*CFrame.Angles(0,0,math.rad(145)), Enum.Material.Glass, Enum.PartType.Wedge, 0.06)
part("CrystalTipShard", Vector3.new(0.26,0.58,0.22), accentColor, base*CFrame.new(0.82,1.43,0.02)*CFrame.Angles(0,0,math.rad(20)), Enum.Material.Glass, Enum.PartType.Wedge, 0.08)
part("CrystalLowerShard", Vector3.new(0.27,0.43,0.22), headColor, base*CFrame.new(0.02,0.86,-0.06)*CFrame.Angles(0,0,math.rad(180)), Enum.Material.Glass, Enum.PartType.Wedge, 0.12)
part("CrystalCore", Vector3.new(0.25,0.25,0.25), Color3.fromRGB(235,255,255), base*CFrame.new(0,1.06,-0.18), Enum.Material.Neon, Enum.PartType.Ball)
part("CrystalFloatingFacet1", Vector3.new(0.18,0.32,0.18), accentColor, base*CFrame.new(-1.12,1.48,-0.03)*CFrame.Angles(0,0,math.rad(34)), Enum.Material.Neon, Enum.PartType.Wedge, 0.10)
part("CrystalFloatingFacet2", Vector3.new(0.16,0.27,0.16), headColor, base*CFrame.new(0.98,0.78,-0.02)*CFrame.Angles(0,0,math.rad(155)), Enum.Material.Glass, Enum.PartType.Wedge, 0.08)
elseif skin == "Inferno" then
-- Black volcanic haft with a sawtooth flame head and ember-red inner blade.
shaftColor, headColor, accentColor = Color3.fromRGB(38,28,32), custom or Color3.fromRGB(67,61,70), Color3.fromRGB(255,91,22)
part("InfernoObsidianShaft", Vector3.new(0.18,2.54,0.18), shaftColor, base*CFrame.new(0,0,0), Enum.Material.Slate)
part("InfernoGrip", Vector3.new(0.25,0.62,0.24), Color3.fromRGB(92,32,23), base*CFrame.new(0,-0.72,0), Enum.Material.CorrodedMetal)
rod("InfernoSpine", Vector3.new(-0.76,0.98,0), Vector3.new(0.72,0.98,0), 0.24, headColor, Enum.Material.Slate)
part("InfernoLeftFlame", Vector3.new(0.62,0.78,0.25), accentColor, base*CFrame.new(-0.76,1.26,0)*CFrame.Angles(0,0,math.rad(-32)), Enum.Material.Neon, Enum.PartType.Wedge)
part("InfernoCenterFlame", Vector3.new(0.40,0.88,0.22), Color3.fromRGB(255,174,36), base*CFrame.new(-0.20,1.30,-0.03)*CFrame.Angles(0,0,math.rad(12)), Enum.Material.Neon, Enum.PartType.Wedge)
part("InfernoRightFang", Vector3.new(0.60,0.72,0.26), headColor, base*CFrame.new(0.63,1.20,0)*CFrame.Angles(0,0,math.rad(150)), Enum.Material.CorrodedMetal, Enum.PartType.Wedge)
part("InfernoCore", Vector3.new(0.28,0.28,0.22), Color3.fromRGB(255,220,70), base*CFrame.new(0,1.0,-0.13), Enum.Material.Neon, Enum.PartType.Ball)
elseif skin == "Void" then
-- Crescent silhouette, dark haft, and a purple centre orb.
shaftColor, headColor, accentColor = Color3.fromRGB(30,24,49), custom or Color3.fromRGB(83,55,132), Color3.fromRGB(192,104,255)
part("VoidShaft", Vector3.new(0.17,2.55,0.17), shaftColor, base*CFrame.new(0,0,0), Enum.Material.Metal)
part("VoidGrip", Vector3.new(0.24,0.55,0.23), Color3.fromRGB(54,39,80), base*CFrame.new(0,-0.76,0), Enum.Material.SmoothPlastic)
local crescent = {Vector3.new(-1.10,0.86,0),Vector3.new(-1.03,1.20,0),Vector3.new(-0.80,1.48,0),Vector3.new(-0.45,1.62,0),Vector3.new(-0.10,1.52,0),Vector3.new(0.18,1.30,0),Vector3.new(0.35,1.05,0)}
for i=1,#crescent-1 do rod("VoidCrescentArc"..i,crescent[i],crescent[i+1],0.20,i%2==0 and accentColor or headColor,Enum.Material.Neon) end
part("VoidOuterSpike", Vector3.new(0.35,0.70,0.22), headColor, base*CFrame.new(-1.08,0.98,0)*CFrame.Angles(0,0,math.rad(-25)), Enum.Material.Metal, Enum.PartType.Wedge)
part("VoidOrb", Vector3.new(0.34,0.34,0.30), accentColor, base*CFrame.new(0,1.02,-0.15), Enum.Material.Neon, Enum.PartType.Ball)
part("VoidPommel", Vector3.new(0.23,0.23,0.23), accentColor, base*CFrame.new(0,-1.30,0), Enum.Material.Neon, Enum.PartType.Ball)
elseif skin == "Frostbite" then
-- Snowflake/ice axe with three angular ice prongs and an icy blue core.
shaftColor, headColor, accentColor = Color3.fromRGB(65,105,135), custom or Color3.fromRGB(141,226,255), Color3.fromRGB(238,252,255)
part("FrostShaft", Vector3.new(0.17,2.50,0.17), shaftColor, base*CFrame.new(0,0,0), Enum.Material.Ice)
part("FrostGrip", Vector3.new(0.24,0.50,0.23), Color3.fromRGB(105,184,210), base*CFrame.new(0,-0.74,0), Enum.Material.Glass, nil, 0.15)
rod("FrostCrossbar", Vector3.new(-0.84,1.02,0), Vector3.new(0.84,1.02,0), 0.17, headColor, Enum.Material.Ice)
part("FrostLeftBlade", Vector3.new(0.46,0.68,0.22), headColor, base*CFrame.new(-0.80,1.17,0)*CFrame.Angles(0,0,math.rad(-38)), Enum.Material.Ice, Enum.PartType.Wedge, 0.05)
part("FrostRightBlade", Vector3.new(0.46,0.68,0.22), headColor, base*CFrame.new(0.80,1.17,0)*CFrame.Angles(0,0,math.rad(142)), Enum.Material.Ice, Enum.PartType.Wedge, 0.05)
part("FrostTopSpike", Vector3.new(0.28,0.48,0.20), accentColor, base*CFrame.new(0,1.36,0), Enum.Material.Ice, Enum.PartType.Wedge, 0.02)
part("FrostSideSpikeL", Vector3.new(0.22,0.36,0.18), accentColor, base*CFrame.new(-1.10,1.03,0)*CFrame.Angles(0,0,math.rad(20)), Enum.Material.Glass, Enum.PartType.Wedge, 0.08)
part("FrostSideSpikeR", Vector3.new(0.22,0.36,0.18), accentColor, base*CFrame.new(1.10,1.03,0)*CFrame.Angles(0,0,math.rad(160)), Enum.Material.Glass, Enum.PartType.Wedge, 0.08)
part("FrostCore", Vector3.new(0.25,0.25,0.20), Color3.fromRGB(255,255,255), base*CFrame.new(0,1.02,-0.16), Enum.Material.Neon, Enum.PartType.Ball)
else
-- Safe fallback if an older saved value is encountered.
part("IronWoodHaft", Vector3.new(0.19,2.58,0.19), shaftColor, base*CFrame.new(0,0,0), Enum.Material.Wood)
rod("IronHeadSpine", Vector3.new(-0.88,1.03,0), Vector3.new(0.80,1.03,0), 0.24, headColor, Enum.Material.Metal)
rod("IronLeftHook", Vector3.new(-0.88,1.03,0), Vector3.new(-1.12,1.40,0), 0.21, headColor, Enum.Material.Metal)
rod("IronRightBeak", Vector3.new(0.80,1.03,0), Vector3.new(1.10,0.70,0), 0.18, accentColor, Enum.Material.Metal)
part("IronHeadSocket", Vector3.new(0.30,0.30,0.28), Color3.fromRGB(190,198,205), base*CFrame.new(0,1.02,-0.015), Enum.Material.Metal, Enum.PartType.Ball)
end
end
-- MY CHAMS (own character only, works without ESP)
if feat.selfChams then
EC = visualColor("self")
local styles = {
Foggy={fill=math.max(feat.selfChamsFill,0.72),outline=0.12},
Solid={fill=0.05,outline=0}, Glass={fill=0.84,outline=0.08},
Outline={fill=1,outline=0}, Neon={fill=0.28,outline=0},
Ghost={fill=0.48,outline=0.35}, Soft={fill=0.62,outline=0.5},
}
local style = styles[feat.selfChamsStyle] or styles.Foggy
vfxObj.selfCh = new("Highlight",{Name="OwoSelfChams",FillColor=visualColor("self"),FillTransparency=style.fill,OutlineColor=visualColor("self"):Lerp(Color3.new(1,1,1),0.45),OutlineTransparency=style.outline,DepthMode=Enum.HighlightDepthMode.AlwaysOnTop,Parent=char})
end
-- CHARACTER OUTLINE: each preset changes line weight, depth behavior, or layered edge structure.
if feat.charOutline then
EC = visualColor("charOutline")
local oc = feat.visualColors.charOutline or hexToColor(feat.outlineColorHex) or Color3.new(0,0,0)
local outlineStyle = feat.visualStyles.charOutline or "Fine Edge"
local trans = outlineStyle == "Soft Edge" and 0.52 or (outlineStyle == "Fine Edge" and 0.12 or 0)
vfxObj.charOut = new("Highlight",{Name="OwoCharOutline",FillTransparency=1,OutlineColor=oc,OutlineTransparency=trans,DepthMode=outlineStyle=="Bold Edge" and Enum.HighlightDepthMode.AlwaysOnTop or Enum.HighlightDepthMode.Occluded,Parent=char})
if outlineStyle == "Double Edge" then
vfxObj.charOut2 = new("Highlight",{Name="OwoCharOutlineInner",FillTransparency=1,OutlineColor=oc:Lerp(Color3.new(1,1,1),0.72),OutlineTransparency=0.28,DepthMode=Enum.HighlightDepthMode.AlwaysOnTop,Parent=char})
elseif outlineStyle == "Bold Edge" then
local edgeIndex = 0
for _, part in ipairs(char:GetDescendants()) do
if part:IsA("BasePart") and part.Name ~= "HumanoidRootPart" then
edgeIndex += 1
vfxObj["charEdgeBox"..edgeIndex] = new("SelectionBox",{Name="OwoBoldEdge",Adornee=part,Color3=oc,LineThickness=0.07,SurfaceTransparency=1,Parent=char})
end
end
end
end
end
-- AFTERIMAGES: use the same visual language and presets as Echo Hand.
-- The moving character leaves one or more part-based silhouettes which fade like the hand echoes.
local ghostFx = new("Folder", {Name="OwoAfterimages", Parent=workspace})
local ghostLast = 0
local function spawnGhost(char)
local ghostStyle = feat.visualStyles.ghost or "Soft Echo"
local copies = ghostStyle == "Stacked Echo" and 2 or 1
local life = ghostStyle == "Long Echo" and 0.78 or (ghostStyle == "Wire Echo" and 0.24 or 0.38)
for copy = 1, copies do
local ok, c = pcall(function() return char:Clone() end)
if not ok or not c then continue end
local parts = {}
local ghostColor = visualColor("ghost")
local col = ghostStyle == "Wire Echo" and ghostColor
or ghostColor:Lerp(Color3.new(1,1,1), ghostStyle == "Long Echo" and 0.58 or 0.3)
for _, d in ipairs(c:GetDescendants()) do
if d:IsA("BasePart") then
d.Anchored = true
d.CanCollide = false; d.CanQuery = false; d.CanTouch = false; d.CastShadow = false
d.Material = ghostStyle == "Wire Echo" and Enum.Material.Neon or Enum.Material.ForceField
d.Color = col
if d.Name == "HumanoidRootPart" then
d.Transparency = 1
else
d.Transparency = ghostStyle == "Long Echo" and 0.2 or (ghostStyle == "Wire Echo" and 0.5 or 0.35)
parts[#parts+1] = d
end
elseif d:IsA("Script") or d:IsA("LocalScript") or d:IsA("Decal") or d:IsA("Texture")
or d:IsA("Humanoid") or d:IsA("Sound") or d:IsA("BillboardGui")
or d:IsA("ParticleEmitter") or d:IsA("Trail") or d:IsA("Light")
or d:IsA("Highlight") or d:IsA("Beam") or d:IsA("SurfaceAppearance") or d:IsA("SurfaceGui") then
d:Destroy()
end
end
c.Parent = ghostFx
if copy == 2 then
-- A second offset silhouette gives Stacked Echo a true layered shape, not just another tint.
pcall(function() c:PivotTo(c:GetPivot() * CFrame.new(-0.12, 0.035, 0.06)) end)
end
for _, part in ipairs(parts) do
local sz = part.Size
local growth = ghostStyle == "Stacked Echo" and 1.035 or 1.06
TS:Create(part, TweenInfo.new(sdur(life), Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {
Transparency = 1, Size = sz * growth
}):Play()
end
task.delay(life + 0.08, function() if c and c.Parent then c:Destroy() end end)
end
end
RS.Heartbeat:Connect(function(dt)
local trailAfterimages = feat.trail and feat.trailStyle == "Afterimages"
if not feat.ghost and not trailAfterimages then return end
local char = player.Character; local hrp = char and char:FindFirstChild("HumanoidRootPart")
if not hrp then return end
local now = tick()
if now - ghostLast >= feat.ghostInterval then
local v = hrp.AssemblyLinearVelocity
if Vector3.new(v.X, 0, v.Z).Magnitude > 3 then ghostLast = now; spawnGhost(char) end
end
end)
if player.Character then task.spawn(Fn.rebuildVFX) end
player.CharacterAdded:Connect(function(c) task.wait(0.5); Fn.rebuildVFX(); hookNeon(c); hookTrans(c) end)
if player.Character then hookNeon(player.Character); hookTrans(player.Character) end
end
-- ══════════════════════════════════════════════════════════════
-- ESP / CHAMS
-- ══════════════════════════════════════════════════════════════
do
local espFolder = new("Folder", {Name="OwoESP", Parent=workspace})
local espData = {}
local function createEspFor(plr)
if plr == player or espData[plr] then return end
local char = plr.Character
local head = char and char:FindFirstChild("Head")
if not head then return end
local data = {}
local bb = new("BillboardGui", {Adornee=head, Size=UDim2.new(0,140,0,48), StudsOffsetWorldSpace=Vector3.new(0,2.8,0), AlwaysOnTop=true, LightInfluence=0, MaxDistance=feat.espMaxDist, Parent=head})
local bg = new("Frame", {Size=UDim2.new(1,0,1,0), BackgroundColor3=Color3.new(0,0,0), BackgroundTransparency=0.5, BorderSizePixel=0, Parent=bb}); corner(bg, 6)
data.bgFrame = bg
data.layoutStroke = new("UIStroke", {Color=EFFECT_COLOR, Thickness=1, Transparency=1, Parent=bg})
data.nameLbl = new("TextLabel", {Size=UDim2.new(1,-6,0,18), Position=UDim2.new(0,3,0,2), BackgroundTransparency=1, Font=Enum.Font.GothamBold, Text=plr.Name, TextColor3=Color3.new(1,1,1), TextSize=12, TextStrokeTransparency=0.3, Parent=bg})
data.distLbl = new("TextLabel", {Size=UDim2.new(1,-6,0,14), Position=UDim2.new(0,3,0,20), BackgroundTransparency=1, Font=Enum.Font.Gotham, Text="", TextColor3=Color3.fromRGB(200,200,200), TextSize=10, TextStrokeTransparency=0.4, Parent=bg})
local healthBg = new("Frame", {Size=UDim2.new(1,-6,0,4), Position=UDim2.new(0,3,1,-8), BackgroundColor3=Color3.fromRGB(30,30,30), BorderSizePixel=0, Parent=bg}); corner(healthBg, 2)
data.healthBar = new("Frame", {Size=UDim2.new(1,0,1,0), BackgroundColor3=Color3.fromRGB(80,220,120), BorderSizePixel=0, Parent=healthBg}); corner(data.healthBar, 2)
data.billboard = bb
if feat.espChams then
local styles = {
Foggy={fill=0.78,outline=0.12}, Solid={fill=0.05,outline=0},
Glass={fill=0.84,outline=0.08}, Outline={fill=1,outline=0},
Neon={fill=0.28,outline=0}, Ghost={fill=0.48,outline=0.35},
Soft={fill=0.62,outline=0.5},
}
local style = styles[feat.espChamsStyle] or styles.Foggy
data.highlight = new("Highlight", {FillColor=visualColor("espChams"), FillTransparency=style.fill, OutlineColor=visualColor("espChams"), OutlineTransparency=style.outline, Adornee=char, Parent=espFolder})
end
espData[plr] = data
end
local function destroyEspFor(plr)
local data = espData[plr]; if not data then return end
for _, obj in pairs(data) do if typeof(obj) == "Instance" then obj:Destroy() end end
espData[plr] = nil
end
Fn.espData = espData
Fn.refreshEsp = function()
local styles = {
Foggy={fill=0.78,outline=0.12}, Solid={fill=0.05,outline=0},
Glass={fill=0.84,outline=0.08}, Outline={fill=1,outline=0},
Neon={fill=0.28,outline=0}, Ghost={fill=0.48,outline=0.35},
Soft={fill=0.62,outline=0.5},
}
local style = styles[feat.espChamsStyle] or styles.Foggy
for plr, data in pairs(espData) do
local layout = feat.visualStyles.espLayout or "Detailed"
local nameStyle = feat.visualStyles.espNames or "Detailed"
local healthStyle = feat.visualStyles.espHealth or "Detailed"
local distStyle = feat.visualStyles.espDistance or "Detailed"
if data.billboard then
data.billboard.Enabled = feat.espEnabled and (feat.espNames or feat.espHealth or feat.espDistance)
data.billboard.Size = layout == "Compact" and UDim2.new(0,112,0,34) or (layout == "Minimal" and UDim2.new(0,92,0,22) or (layout == "Outlined" and UDim2.new(0,166,0,52) or UDim2.new(0,140,0,48)))
data.billboard.StudsOffsetWorldSpace = Vector3.new(0, layout == "Minimal" and 2.25 or (layout == "Compact" and 2.55 or 2.8), 0)
end
if data.bgFrame then
data.bgFrame.BackgroundTransparency = layout == "Minimal" and 1 or (layout == "Compact" and 0.68 or (layout == "Outlined" and 0.82 or 0.5))
data.bgFrame.BackgroundColor3 = layout == "Outlined" and Color3.fromRGB(8,12,22) or Color3.new(0,0,0)
end
if data.layoutStroke then
data.layoutStroke.Color = visualColor("espNames")
data.layoutStroke.Transparency = layout == "Outlined" and 0.08 or 1
data.layoutStroke.Thickness = layout == "Outlined" and 1.5 or 1
end
if data.nameLbl then
data.nameLbl.Visible = feat.espNames
data.nameLbl.TextSize = nameStyle == "Compact" and 10 or (nameStyle == "Minimal" and 9 or (nameStyle == "Outlined" and 13 or 12))
data.nameLbl.TextStrokeTransparency = nameStyle == "Minimal" and 1 or (nameStyle == "Outlined" and 0.05 or 0.3)
data.nameLbl.TextColor3 = feat.visualColors.espNames or (nameStyle == "Minimal" and Color3.fromRGB(225,235,245) or Color3.new(1,1,1))
data.nameLbl.Font = nameStyle == "Compact" and Enum.Font.Gotham or Enum.Font.GothamBold
end
if data.distLbl then
data.distLbl.Visible = feat.espDistance
data.distLbl.TextSize = distStyle == "Compact" and 8 or (distStyle == "Minimal" and 9 or (distStyle == "Outlined" and 11 or 10))
data.distLbl.TextStrokeTransparency = distStyle == "Outlined" and 0.05 or (distStyle == "Minimal" and 1 or 0.4)
data.distLbl.TextColor3 = feat.visualColors.espDistance or T.Text
end
if data.healthBg then
data.healthBg.Size = UDim2.new(1,-6,0,healthStyle == "Compact" and 3 or (healthStyle == "Detailed" and 5 or 4))
data.healthBg.BackgroundColor3 = healthStyle == "Minimal" and Color3.fromRGB(65,65,70) or Color3.fromRGB(30,30,30)
end
if data.healthBar then data.healthBar.Parent.Visible = feat.espHealth end
if feat.espChams and not data.highlight then
local ch = plr.Character
if ch then
data.highlight = new("Highlight", {FillColor=visualColor("espChams"), FillTransparency=style.fill, OutlineColor=visualColor("espChams"), OutlineTransparency=style.outline, Adornee=ch, Parent=espFolder})
end
elseif not feat.espChams and data.highlight then
data.highlight:Destroy()
data.highlight = nil
end
if data.highlight then
data.highlight.Enabled = feat.espEnabled and feat.espChams
data.highlight.FillTransparency = style.fill
data.highlight.OutlineTransparency = style.outline
end
end
end
local function onPlayerAdded(plr)
plr.CharacterAdded:Connect(function() task.wait(1); destroyEspFor(plr); if feat.espEnabled then createEspFor(plr) end end)
if plr.Character and feat.espEnabled then createEspFor(plr) end
end
for _, plr in ipairs(Players:GetPlayers()) do onPlayerAdded(plr) end
Players.PlayerAdded:Connect(onPlayerAdded)
Players.PlayerRemoving:Connect(destroyEspFor)
Fn.setEspEnabled = function(on)
if on then for _, plr in ipairs(Players:GetPlayers()) do if plr ~= player then createEspFor(plr) end end
else for plr in pairs(espData) do destroyEspFor(plr) end end
Fn.refreshEsp()
end
RS.RenderStepped:Connect(function()
if not feat.espEnabled then return end
local myHrp = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
if not myHrp then return end
local myPos = myHrp.Position
for plr, data in pairs(espData) do
local char = plr.Character
local head = char and char:FindFirstChild("Head")
local hum = char and char:FindFirstChildOfClass("Humanoid")
if not head or not hum then
if data.billboard then data.billboard.Enabled = false end
else
local d = (head.Position - myPos).Magnitude
local visible = d <= feat.espMaxDist
if feat.espTeamCheck and plr.Team == player.Team then visible = false end
if data.billboard then data.billboard.Enabled = visible and (feat.espNames or feat.espHealth or feat.espDistance) end
if data.distLbl then
local ds = feat.visualStyles.espDistance or "Detailed"
data.distLbl.Text = ds == "Minimal" and string.format("%d", math.floor(d)) or (ds == "Compact" and string.format("%d st", math.floor(d)) or string.format("DIST %d studs", math.floor(d)))
end
if data.healthBar then
local hp = math.clamp(hum.Health/math.max(hum.MaxHealth,1), 0, 1)
data.healthBar.Size = UDim2.new(hp, 0, 1, 0)
data.healthBar.BackgroundColor3 = feat.visualColors.espHealth or (hp > 0.6 and Color3.fromRGB(80,220,120) or (hp > 0.3 and Color3.fromRGB(240,200,80) or Color3.fromRGB(240,80,90)))
end
if data.highlight then data.highlight.Enabled = visible and feat.espChams end
end
end
end)
end
-- ══════════════════════════════════════════════════════════════
-- CROSSHAIR
-- ══════════════════════════════════════════════════════════════
do
local chGui = new("ScreenGui", {Name="OwoCrosshair", ResetOnSpawn=false, IgnoreGuiInset=true, Parent=pg})
local chFrame = new("Frame", {Size=UDim2.new(0,0,0,0), Position=UDim2.new(0.5,0,0.5,0), AnchorPoint=Vector2.new(0.5,0.5), BackgroundTransparency=1, Parent=chGui, Visible=false})
local chParts = {}
local function mkPart(w, h) return new("Frame", {Size=UDim2.new(0,w,0,h), BackgroundColor3=Color3.new(1,1,1), BorderSizePixel=0, AnchorPoint=Vector2.new(0.5,0.5), Parent=chFrame}) end
Fn.rebuildCrosshair = function()
for _, p in ipairs(chParts) do p:Destroy() end
chParts = {}
chFrame.Visible = feat.crosshair
if not feat.crosshair then return end
local c = feat.visualColors.crosshair or hexToColor(feat.crosshairColorHex) or Color3.new(1,1,1)
local dotC = feat.visualColors.crosshairDot or c
local outlineC = feat.visualColors.crosshairOutline or c
local s, t, g = feat.crosshairSize, feat.crosshairThickness, feat.crosshairGap
if feat.crosshairStyle == "cross" then
local up = mkPart(t, s); up.Position = UDim2.new(0.5,0,0.5,-g-s/2); up.BackgroundColor3 = c; chParts[#chParts+1] = up
local dn = mkPart(t, s); dn.Position = UDim2.new(0.5,0,0.5,g+s/2); dn.BackgroundColor3 = c; chParts[#chParts+1] = dn
local lf = mkPart(s, t); lf.Position = UDim2.new(0.5,-g-s/2,0.5,0); lf.BackgroundColor3 = c; chParts[#chParts+1] = lf
local rt = mkPart(s, t); rt.Position = UDim2.new(0.5,g+s/2,0.5,0); rt.BackgroundColor3 = c; chParts[#chParts+1] = rt
elseif feat.crosshairStyle == "dot" then
local d = mkPart(t*2, t*2); d.Position = UDim2.new(0.5,0,0.5,0); d.BackgroundColor3 = c; chParts[#chParts+1] = d
elseif feat.crosshairStyle == "x" then
for i = 1, 2 do
local l = mkPart(t, s*1.4); l.Position = UDim2.new(0.5,0,0.5,0); l.Rotation = i==1 and 45 or -45; l.BackgroundColor3 = c; chParts[#chParts+1] = l
end
elseif feat.crosshairStyle == "circle" then
for i = 1, 8 do
local angle = (i-1)/8 * math.pi * 2
local b = mkPart(t, s*0.4)
b.Position = UDim2.new(0.5, math.cos(angle)*(g+s*0.2), 0.5, math.sin(angle)*(g+s*0.2))
b.Rotation = math.deg(angle); b.BackgroundColor3 = c; chParts[#chParts+1] = b
end
end
-- Center-dot variants change the actual glyph, not simply its color.
if feat.crosshairDot and feat.crosshairStyle ~= "dot" then
local dotStyle = feat.visualStyles.crosshairDot or "Tiny Dot"
if dotStyle == "Ring Dot" then
local d = mkPart(t*3, t*3); d.Position = UDim2.new(0.5,0,0.5,0)
d.BackgroundTransparency = 1; d.BackgroundColor3 = dotC
new("UICorner", {CornerRadius=UDim.new(1,0), Parent=d})
new("UIStroke", {Color=dotC, Thickness=math.max(1,t), Transparency=0.05, Parent=d})
chParts[#chParts+1] = d
elseif dotStyle == "Star Center" then
for i=1,4 do
local d=mkPart(math.max(2,t), math.max(4,t*2.8)); d.Position=UDim2.new(0.5,0,0.5,0)
d.Rotation=(i-1)*45; d.BackgroundColor3=dotC; chParts[#chParts+1]=d
end
elseif dotStyle == "Diamond Center" then
local d=mkPart(math.max(3,t*2),math.max(3,t*2)); d.Position=UDim2.new(0.5,0,0.5,0)
d.Rotation=45; d.BackgroundColor3=dotC; chParts[#chParts+1]=d
else
local d = mkPart(math.max(2,t), math.max(2,t)); d.Position = UDim2.new(0.5,0,0.5,0)
d.BackgroundColor3 = dotC; new("UICorner", {CornerRadius=UDim.new(1,0), Parent=d}); chParts[#chParts+1] = d
end
end
if feat.crosshairOutline then
local outlineStyle = feat.visualStyles.crosshairOutline or "Thin Edge"
for _, p in ipairs(chParts) do
if outlineStyle == "Glow Edge" then
new("UIStroke", {Color=outlineC, Thickness=3, Transparency=0.2, Parent=p})
new("UIStroke", {Color=Color3.new(0,0,0), Thickness=1, Transparency=0.12, Parent=p})
elseif outlineStyle == "Double Edge" then
new("UIStroke", {Color=outlineC, Thickness=3, Transparency=0.05, Parent=p})
new("UIStroke", {Color=Color3.new(0,0,0), Thickness=1, Transparency=0.05, Parent=p})
else
new("UIStroke", {Color=outlineC, Thickness=outlineStyle == "Bold Edge" and 3 or 1, Transparency=outlineStyle == "Bold Edge" and 0.05 or 0.3, Parent=p})
end
end
end
end
end
-- ══════════════════════════════════════════════════════════════
-- SCREEN FILTERS
-- ══════════════════════════════════════════════════════════════
do
local scGui = new("ScreenGui", {Name="OwoScreenFX", ResetOnSpawn=false, IgnoreGuiInset=true, ZIndexBehavior=Enum.ZIndexBehavior.Sibling, Parent=pg})
local scanlines = new("Frame", {Size=UDim2.new(1,0,1,0), BackgroundTransparency=1, Visible=false, ZIndex=50, Parent=scGui})
for i = 0, 60 do
new("Frame", {Size=UDim2.new(1,0,0,1), Position=UDim2.new(0,0,i/60,0), BackgroundColor3=Color3.new(0,0,0), BackgroundTransparency=0.85, BorderSizePixel=0, Parent=scanlines})
end
local vhsOverlay = new("Frame", {Size=UDim2.new(1,0,1,0), BackgroundColor3=Color3.fromRGB(80,0,80), BackgroundTransparency=0.9, Visible=false, ZIndex=51, Parent=scGui})
local glitchOverlay = new("Frame", {Size=UDim2.new(1,0,1,0), BackgroundColor3=Color3.fromRGB(0,255,255), BackgroundTransparency=0.95, Visible=false, ZIndex=52, Parent=scGui})
local ca = new("ColorCorrectionEffect", {Name="OwoChromatic", Enabled=false, Parent=Lighting})
local dof = new("DepthOfFieldEffect", {Name="OwoDOF", Enabled=false, Parent=Lighting})
local retro = new("ColorCorrectionEffect", {Name="OwoRetro", Enabled=false, Parent=Lighting})
Fn.applyScreenFilters = function()
ca.Enabled = feat.chromaticAberration
dof.Enabled = feat.depthOfField
if dof.Enabled then
local ds = feat.visualStyles.dof or "Portrait Focus"
if ds == "Dream Bokeh" then dof.NearIntensity, dof.FarIntensity, dof.FocusDistance, dof.InFocusRadius = 0.7, 0.55, 18, 12
elseif ds == "Cinematic" then dof.NearIntensity, dof.FarIntensity, dof.FocusDistance, dof.InFocusRadius = 0.35, 0.45, 28, 20
elseif ds == "Deep Focus" then dof.NearIntensity, dof.FarIntensity, dof.FocusDistance, dof.InFocusRadius = 0.08, 0.12, 60, 80
else dof.NearIntensity, dof.FarIntensity, dof.FocusDistance, dof.InFocusRadius = 0.5, 0.3, 20, 25 end
end
retro.Enabled = feat.retroFilter
scanlines.Visible = feat.vhsFilter or feat.glitchFilter
vhsOverlay.Visible = feat.vhsFilter
glitchOverlay.Visible = feat.glitchFilter
local vhsStyle = feat.visualStyles.vhs or "Tape Lines"
vhsOverlay.BackgroundColor3 = feat.visualColors.vhs or (vhsStyle == "Blue Tape" and Color3.fromRGB(0,45,110) or (vhsStyle == "Warm Tape" and Color3.fromRGB(120,45,10) or Color3.fromRGB(80,0,80)))
scanlines.BackgroundTransparency = vhsStyle == "Dense Scanlines" and 0.68 or (vhsStyle == "Clean Tape" and 0.94 or 1)
if feat.chromaticAberration then
local style = feat.visualStyles.chroma or "Subtle"
local mult = style == "Cinematic" and 1.35 or (style == "Dream" and 0.75 or (style == "Intense" and 2.2 or 1))
ca.TintColor = feat.visualColors.chroma or (style == "Dream" and Color3.fromRGB(220,235,255) or Color3.new(1,1,1))
ca.Saturation = feat.chromaticStrength*0.5*mult; ca.Contrast = feat.chromaticStrength*0.15*mult
end
if feat.retroFilter then
local k = feat.retroStrength
local style = feat.visualStyles.retro or "Cinematic"
retro.TintColor = feat.visualColors.retro or (style == "Dream" and Color3.fromRGB(210,220,255) or (style == "Intense" and Color3.fromRGB(255,185,120) or Color3.fromRGB(255,220,150)))
retro.Saturation = (style == "Subtle" and -0.15 or -0.4)*k; retro.Contrast = (style == "Intense" and 0.5 or 0.25)*k; retro.Brightness = -0.03*k
end
end
local glitchAcc = 0
RS.RenderStepped:Connect(function(dt)
if not feat.glitchFilter then return end
glitchAcc += dt
if glitchAcc > 0.05 then
glitchAcc = 0
if math.random() < 0.25 then
local glitchStyle = feat.visualStyles.glitch or "RGB Tear"
if feat.visualColors.glitch then glitchOverlay.BackgroundColor3 = feat.visualColors.glitch
elseif glitchStyle == "RGB Tear" then glitchOverlay.BackgroundColor3 = Color3.fromRGB(math.random(0,255), math.random(0,255), math.random(0,255))
elseif glitchStyle == "Red Shift" then glitchOverlay.BackgroundColor3 = Color3.fromRGB(255,25,45)
elseif glitchStyle == "Blue Shift" then glitchOverlay.BackgroundColor3 = Color3.fromRGB(20,80,255)
else glitchOverlay.BackgroundColor3 = Color3.fromRGB(255,255,255) end
glitchOverlay.BackgroundTransparency = (glitchStyle == "Hard Flash" and 0.72 or (0.85 + math.random()*0.1))
glitchOverlay.Position = UDim2.new(math.random(-3,3)/100, 0, 0, 0)
else
glitchOverlay.BackgroundTransparency = 1
glitchOverlay.Position = UDim2.new(0,0,0,0)
end
end
if feat.vhsFilter then vhsOverlay.Position = UDim2.new(math.sin(tick()*20)*0.002, 0, 0, 0) end
end)
end
-- Premium-only visual subsystem removed. Standard Visuals effects remain below.
-- ══════════════════════════════════════════════════════════════
-- MOTION BLUR
-- ══════════════════════════════════════════════════════════════
do
local mb = new("BlurEffect", {Name="OwoMotionBlur", Size=0, Enabled=false, Parent=Lighting})
local lastCF = camera.CFrame
local smoothSize = 0
RS.RenderStepped:Connect(function(dt)
if not feat.motionBlur then
smoothSize = slerp(smoothSize, 0, dt, 12)
mb.Size = smoothSize
if mb.Enabled and smoothSize < 0.05 then mb.Enabled = false end
lastCF = camera.CFrame
return
end
mb.Enabled = true
local cur = camera.CFrame
local dp = (cur.Position - lastCF.Position).Magnitude
local da = (cur.LookVector - lastCF.LookVector).Magnitude
lastCF = cur
local speed = dp / math.max(dt, 1/120)
local rotSpeed = da / math.max(dt, 1/120)
local blurStyle = feat.visualStyles.motionBlur or "Default"
local blurMult = blurStyle == "Directional Streak" and 1.6 or (blurStyle == "Soft Cinematic" and 0.62 or (blurStyle == "Heavy Smear" and 2.1 or 1))
local target = math.clamp((speed * 0.12 + rotSpeed * 2.0) * feat.motionBlurStrength * blurMult, 0, 20)
smoothSize = slerp(smoothSize, target, dt, 8)
mb.Size = smoothSize
end)
end
-- ══════════════════════════════════════════════════════════════
-- GLOSSY (WET LOOK)
-- Flat/big surfaces (floors, roofs, water) get strong mirror reflections, walls a softer sheen,
-- and the sky reflection gets stronger. Original values are restored when switched off.
-- ══════════════════════════════════════════════════════════════
do
local saved, conn = {}, nil
local savedEnv = nil
local function skipPart(p)
if not p:IsA("BasePart") then return true end
if p:IsA("Terrain") then return true end
if player.Character and p:IsDescendantOf(player.Character) then return true end
local a = p
while a and a ~= workspace do
if a.Name and a.Name:sub(1,3) == "Owo" then return true end
a = a.Parent
end
return false
end
local function want(p)
local style = feat.visualStyles.reflective or "Polished"
local flat = math.abs(p.CFrame.UpVector.Y) > 0.9
local big = math.clamp(math.max(p.Size.X, p.Size.Z) / 14, 0.25, 1)
local r = flat and (0.3 + 0.7 * big) or 0.26
if style == "Wet Glass" then r = flat and 1 or 0.58
elseif style == "Chrome" then r = 0.95
elseif style == "Soft Satin" then r = flat and 0.34 or 0.12 end
return math.clamp(math.max(saved[p] or 0, feat.reflectiveStrength * r), 0, 1)
end
local function applyTo(p)
if skipPart(p) then return end
if saved[p] == nil then saved[p] = p.Reflectance end
pcall(function() p.Reflectance = want(p) end)
end
local function applyEnv()
if not savedEnv then
local terr = workspace:FindFirstChildOfClass("Terrain")
savedEnv = {spec = Lighting.EnvironmentSpecularScale, wr = terr and terr.WaterReflectance}
end
local style = feat.visualStyles.reflective or "Polished"
local env = style == "Chrome" and 1 or (style == "Wet Glass" and 0.88 or (style == "Soft Satin" and 0.32 or 0.68))
local water = style == "Wet Glass" and 1 or (style == "Chrome" and 0.9 or (style == "Soft Satin" and 0.28 or 0.72))
Lighting.EnvironmentSpecularScale = math.clamp(env * (0.35 + feat.reflectiveStrength * 0.65), 0, 1)
local terr = workspace:FindFirstChildOfClass("Terrain")
if terr then terr.WaterReflectance = math.clamp(water * (0.35 + feat.reflectiveStrength * 0.65), 0, 1) end
end
local function clearAll()
for p, r in pairs(saved) do
if p and p.Parent then pcall(function() p.Reflectance = r end) end
end
table.clear(saved)
if conn then conn:Disconnect(); conn = nil end
if savedEnv then
Lighting.EnvironmentSpecularScale = savedEnv.spec
local terr = workspace:FindFirstChildOfClass("Terrain")
if terr and savedEnv.wr then terr.WaterReflectance = savedEnv.wr end
savedEnv = nil
end
end
Fn.applyReflective = function()
if not feat.reflective then clearAll(); return end
applyEnv()
for _, d in ipairs(workspace:GetDescendants()) do applyTo(d) end
if not conn then
conn = workspace.DescendantAdded:Connect(function(d)
if feat.reflective then task.defer(function() applyTo(d) end) end
end)
end
end
Fn.setReflectiveStrength = function(v)
feat.reflectiveStrength = v
if feat.reflective then
applyEnv()
for p in pairs(saved) do
if p and p.Parent then pcall(function() p.Reflectance = want(p) end) end
end
end
end
end
-- ══════════════════════════════════════════════════════════════
-- FPS BOOST
-- ══════════════════════════════════════════════════════════════
do
local savedDecals = {}
local savedSA = {}
local savedMeshTex = {}
local conn = nil
local function isCharacter(p) return player.Character and p:IsDescendantOf(player.Character) end
local function isOwo(p)
local a = p
while a and a ~= workspace do
if a.Name and a.Name:sub(1, 3) == "Owo" then return true end
a = a.Parent
end
return false
end
local function stripPart(p)
if isCharacter(p) or isOwo(p) then return end
for _, c in ipairs(p:GetChildren()) do
if c:IsA("Decal") or c:IsA("Texture") then
if savedDecals[c] == nil then savedDecals[c] = c.Transparency end
c.Transparency = 1
elseif c:IsA("SurfaceAppearance") then
savedSA[p] = savedSA[p] or {}
table.insert(savedSA[p], c:Clone())
c:Destroy()
end
end
if p:IsA("MeshPart") and p.TextureID ~= "" then
if savedMeshTex[p] == nil then savedMeshTex[p] = p.TextureID end
p.TextureID = ""
end
local sm = p:FindFirstChildOfClass("SpecialMesh")
if sm and sm.TextureId ~= "" then
if savedMeshTex[sm] == nil then savedMeshTex[sm] = sm.TextureId end
sm.TextureId = ""
end
end
local function restoreAll()
for d, t in pairs(savedDecals) do
if d and d.Parent then pcall(function() d.Transparency = t end) end
end
table.clear(savedDecals)
for parent, list in pairs(savedSA) do
if parent and parent.Parent then
for _, sa in ipairs(list) do pcall(function() sa.Parent = parent end) end
end
end
table.clear(savedSA)
for inst, id in pairs(savedMeshTex) do
if inst and inst.Parent then
if inst:IsA("MeshPart") then
pcall(function() inst.TextureID = id end)
else
pcall(function() inst.TextureId = id end)
end
end
end
table.clear(savedMeshTex)
if conn then conn:Disconnect(); conn = nil end
end
Fn.applyFpsBoost = function()
if not feat.fpsBoost then restoreAll(); return end
for _, d in ipairs(workspace:GetDescendants()) do
if d:IsA("BasePart") then stripPart(d) end
end
if not conn then
conn = workspace.DescendantAdded:Connect(function(d)
if feat.fpsBoost and d:IsA("BasePart") then task.defer(function() stripPart(d) end) end
end)
end
end
end
-- ══════════════════════════════════════════════════════════════
-- REALISTIC SHADER
-- Time-of-day aware grading: golden hour warms up, night turns cool, soft bloom,
-- gentle sun rays, atmospheric haze, subtle depth of field and sharper soft shadows.
-- ══════════════════════════════════════════════════════════════
do
local cc = new("ColorCorrectionEffect", {Name="OwoRealistic", Enabled=false, Parent=Lighting})
local bl = new("BloomEffect", {Name="OwoRealisticBloom", Enabled=false, Parent=Lighting})
local sr = new("SunRaysEffect", {Name="OwoRealisticRays", Enabled=false, Parent=Lighting})
local df = new("DepthOfFieldEffect", {Name="OwoRealisticDOF", Enabled=false, Parent=Lighting})
local atmo = nil
local savedL = nil
local sR = 0
local WARM, COOL = Color3.fromRGB(255, 208, 160), Color3.fromRGB(165, 190, 255)
Fn.setRealisticStrength = function(v) feat.realisticStrength = v end
local function ensureAtmo()
if atmo and atmo.Parent then return end
local existing = Lighting:FindFirstChildOfClass("Atmosphere")
if existing and existing.Name ~= "OwoRealisticAtmo" then atmo = nil return end
atmo = new("Atmosphere", {Name="OwoRealisticAtmo", Density=0, Offset=0.2, Color=Color3.fromRGB(199,215,235), Decay=Color3.fromRGB(106,112,125), Glare=0, Haze=0, Parent=Lighting})
end
RS.RenderStepped:Connect(function(dt)
local target = feat.realistic and 1 or 0
sR = slerp(sR, target, dt, 5)
local on = sR > 0.01
cc.Enabled = on; bl.Enabled = on; sr.Enabled = on; df.Enabled = on
if on and not savedL then
savedL = {shadow = Lighting.ShadowSoftness, spec = Lighting.EnvironmentSpecularScale, diff = Lighting.EnvironmentDiffuseScale}
ensureAtmo()
end
if not on then
if savedL then
Lighting.ShadowSoftness = savedL.shadow; Lighting.EnvironmentSpecularScale = savedL.spec; Lighting.EnvironmentDiffuseScale = savedL.diff
savedL = nil
end
if atmo then atmo.Density = 0; atmo.Haze = 0 end
return
end
local k = (feat.realisticStrength or 1) * sR
local ct = Lighting.ClockTime
local golden = math.max(math.clamp(1 - math.abs(ct - 18) / 2.3, 0, 1), math.clamp(1 - math.abs(ct - 6.2) / 2, 0, 1))
local night = (ct < 5 or ct > 19.6) and 1 or 0
local style = feat.visualStyles.realistic or "Natural"
local warmGain = style == "Cinematic" and 0.95 or (style == "Soft" and 0.2 or 0.68)
local nightGain = style == "High Detail" and 0.28 or 0.55
local tint = Color3.new(1, 1, 1):Lerp(WARM, golden * warmGain):Lerp(COOL, night * nightGain)
cc.TintColor = Color3.new(1, 1, 1):Lerp(tint, k)
cc.Contrast = (style == "High Detail" and 0.28 or (style == "Cinematic" and 0.2 or (style == "Soft" and 0.06 or 0.14))) * k
cc.Saturation = (style == "Cinematic" and 0.18 or (style == "Soft" and -0.08 or (0.22 - night * 0.12))) * k
cc.Brightness = (style == "Soft" and 0.035 or (0.02 - night * 0.02)) * k
bl.Intensity = (style == "Soft" and 0.3 or (style == "Cinematic" and 0.6 or (0.45 + golden * 0.35))) * k
bl.Size = style == "High Detail" and 14 or (style == "Soft" and 32 or (style == "Cinematic" and 28 or 22))
bl.Threshold = style == "Cinematic" and 0.8 or (style == "High Detail" and 1.3 or 0.92)
sr.Intensity = (style == "High Detail" and 0.13 or 0.07) * k * (1 - night)
sr.Spread = style == "Cinematic" and 0.35 or 0.5
df.NearIntensity = 0
df.FarIntensity = (style == "Cinematic" and 0.18 or (style == "High Detail" and 0.02 or 0.12)) * k
df.FocusDistance = 80
df.InFocusRadius = style == "Soft" and 70 or (style == "Cinematic" and 36 or 45)
Lighting.ShadowSoftness = math.clamp(0.3 * k + (savedL and savedL.shadow or 0.2) * (1 - k), 0, 1)
Lighting.EnvironmentDiffuseScale = math.clamp((savedL and savedL.diff or 0) * (1 - k) + 1 * k, 0, 1)
if atmo and atmo.Parent then
atmo.Density = (style == "Cinematic" and 0.24 or (style == "Soft" and 0.07 or 0.2)) * k
atmo.Haze = (style == "Cinematic" and 2.0 or (style == "High Detail" and 0.35 or 1.1)) * k
atmo.Color = Color3.fromRGB(199, 215, 235):Lerp(WARM, golden * (style == "Cinematic" and 0.85 or 0.6)):Lerp(COOL, night * 0.5)
end
end)
end
-- ══════════════════════════════════════════════════════════════
-- LIGHTING
-- ══════════════════════════════════════════════════════════════
do
local savedLight = nil
Fn.saveLight = function()
if savedLight then return end
savedLight = {ClockTime=Lighting.ClockTime,Brightness=Lighting.Brightness,Ambient=Lighting.Ambient,OutdoorAmbient=Lighting.OutdoorAmbient,FogColor=Lighting.FogColor,FogStart=Lighting.FogStart,FogEnd=Lighting.FogEnd,GlobalShadows=Lighting.GlobalShadows}
end
Fn.applyFB = function()
if feat.fullbright then
local style = feat.visualStyles.fullbright or "Studio Bright"
if style == "Warm Day" then
Lighting.Ambient=Color3.fromRGB(255,224,188); Lighting.OutdoorAmbient=Color3.fromRGB(255,206,160); Lighting.Brightness=2.4; Lighting.GlobalShadows=true
elseif style == "Cool Night" then
Lighting.Ambient=Color3.fromRGB(185,210,255); Lighting.OutdoorAmbient=Color3.fromRGB(140,170,235); Lighting.Brightness=2.1; Lighting.GlobalShadows=false
elseif style == "Flat White" then
Lighting.Ambient=Color3.new(1,1,1); Lighting.OutdoorAmbient=Color3.new(1,1,1); Lighting.Brightness=3.4; Lighting.GlobalShadows=false
else
Lighting.Ambient=Color3.fromRGB(235,242,255); Lighting.OutdoorAmbient=Color3.fromRGB(225,235,255); Lighting.Brightness=2.8; Lighting.GlobalShadows=false
end
else
Lighting.Ambient = Color3.fromRGB(70,70,70); Lighting.OutdoorAmbient = Color3.fromRGB(128,128,128)
Lighting.Brightness = 2; Lighting.GlobalShadows = true
end
end
Fn.setDay = function() Fn.saveLight(); TS:Create(Lighting,TweenInfo.new(sdur(0.5)),{ClockTime=12,Brightness=2}):Play(); Lighting.Ambient = Color3.fromRGB(90,90,90); Lighting.OutdoorAmbient = Color3.fromRGB(130,130,130); Lighting.FogColor = Color3.fromRGB(192,192,192); Lighting.FogEnd = 1e5; Lighting.GlobalShadows = true; notify("Time","Day") end
Fn.setNight = function() Fn.saveLight(); TS:Create(Lighting,TweenInfo.new(sdur(0.5)),{ClockTime=0,Brightness=0.5}):Play(); Lighting.Ambient = Color3.fromRGB(20,25,45); Lighting.OutdoorAmbient = Color3.fromRGB(40,50,80); Lighting.FogColor = Color3.fromRGB(15,20,35); Lighting.FogEnd = 400; Lighting.GlobalShadows = true; notify("Time","Night") end
Fn.setSunset = function() Fn.saveLight(); TS:Create(Lighting,TweenInfo.new(sdur(0.5)),{ClockTime=17.5,Brightness=2}):Play(); Lighting.Ambient = Color3.fromRGB(110,70,50); Lighting.OutdoorAmbient = Color3.fromRGB(200,120,80); Lighting.FogColor = Color3.fromRGB(255,150,100); Lighting.FogEnd = 600; Lighting.GlobalShadows = true; notify("Time","Sunset") end
Fn.restoreLight = function()
if not savedLight then notify("Time","Nothing to restore",false); return end
TS:Create(Lighting,TweenInfo.new(sdur(0.5)),{ClockTime=savedLight.ClockTime,Brightness=savedLight.Brightness}):Play()
Lighting.Ambient=savedLight.Ambient; Lighting.OutdoorAmbient=savedLight.OutdoorAmbient
Lighting.FogColor=savedLight.FogColor; Lighting.FogStart=savedLight.FogStart
Lighting.FogEnd=savedLight.FogEnd; Lighting.GlobalShadows=savedLight.GlobalShadows
notify("Time","Restored",false)
end
end
-- ══════════════════════════════════════════════════════════════
-- WIDGET EDIT MODE (widgets can only be moved / resized / re-styled while the chat is open)
-- ══════════════════════════════════════════════════════════════
local Edit = { focused=false, last=-10, on=false, listeners={} }
do
local function chatFocused()
local ok, v = pcall(function() return TextChatService.ChatInputBarConfiguration.IsFocused end)
if ok and v == true then return true end
local okb, tb = pcall(function() return UIS:GetFocusedTextBox() end)
if okb and tb and tb.Name == "ChatBar" then return true end
return false
end
-- chat loses focus the moment you click a widget, so a short grace period keeps edit mode alive for that click
Fn.canEdit = function() return feat.editAnywhere or Edit.focused or (os.clock() - Edit.last) < 0.35 end
RS.RenderStepped:Connect(function()
local f = chatFocused()
if f then Edit.last = os.clock() end
Edit.focused = f
local on = Fn.canEdit()
if on ~= Edit.on then
Edit.on = on
for _, fn in ipairs(Edit.listeners) do pcall(fn, on) end
end
end)
end
-- ══════════════════════════════════════════════════════════════
-- OVERLAYS
-- ══════════════════════════════════════════════════════════════
do
local ovGui = new("ScreenGui", {Name="OwoOverlays",ResetOnSpawn=false,IgnoreGuiInset=true,ZIndexBehavior=Enum.ZIndexBehavior.Sibling,Parent=pg})
UI.ovGui = ovGui
UI.defaultPos = {}
local function mkOv(name, sz, pos, bare, onClick)
local f = new("Frame",{Size=sz,Position=pos,BackgroundColor3=T.Card,BackgroundTransparency=bare and 1 or TR.Overlay,BorderSizePixel=0,Visible=false,Active=false,ClipsDescendants=true,ZIndex=30,Parent=ovGui})
corner(f, bare and 12 or RM)
if bare then
f:SetAttribute("Bare", true)
else
local s = stroke(f, 1, 0.6, T.Line, true); regRef(s, "Color", "Line"); s.Name = "OwoLine"
regRef(f, "BackgroundColor3", "Card"); addSheen(f)
Glass.G.decorate(f, {small=true})
end
-- A soft moving gloss layer. It stays hidden until Overlay Shine is enabled.
local shine = new("Frame", {
Name="OwoOverlayShine", AnchorPoint=Vector2.new(0.5,0.5),
Size=UDim2.new(0.34,0,1.8,0), Position=UDim2.new(-0.5,0,0.5,0),
Rotation=18, BackgroundColor3=Color3.new(1,1,1), BackgroundTransparency=0.78,
BorderSizePixel=0, Visible=false, Active=false, ZIndex=80, Parent=f
})
local shineGrad = new("UIGradient", {Rotation=0, Transparency=NumberSequence.new({
NumberSequenceKeypoint.new(0,1), NumberSequenceKeypoint.new(0.35,0.96),
NumberSequenceKeypoint.new(0.5,0.52), NumberSequenceKeypoint.new(0.65,0.96),
NumberSequenceKeypoint.new(1,1)
}), Parent=shine})
overlayShines[name] = {owner=f, frame=shine, gradient=shineGrad}
local es = new("UIStroke",{Name="OwoEdit",Color=T.Accent,Thickness=1.5,Transparency=0.1,ApplyStrokeMode=Enum.ApplyStrokeMode.Border,Enabled=false,Parent=f})
regRef(es, "Color", "Accent")
drag(f, f, function() return Fn.canEdit() end, onClick or function() if Fn.cycleLayout then Fn.cycleLayout(name) end end)
overlays[name] = f; UI.defaultPos[name] = pos
return f
end
-- One combined status-bar widget. The brand badge and info strip look
-- like two separate capsules, but share this one draggable parent frame.
mkOv("statusBar", UDim2.new(0,520,0,36), UDim2.new(0.5,-260,0,2), true)
overlays.statusBar.Visible = false
mkOv("fps", UDim2.new(0,110,0,34), UDim2.new(1,-130,0,14))
mkOv("coords", UDim2.new(0,214,0,30), UDim2.new(0.5,-107,0,176))
mkOv("ping", UDim2.new(0,110,0,34), UDim2.new(1,-130,0,54))
mkOv("keybinds", UDim2.new(0,190,0,60), UDim2.new(1,-210,0.5,-60))
mkOv("musicHud", UDim2.new(0,290,0,104), UDim2.new(0.5,-145,0,58))
mkOv("speed", UDim2.new(0,130,0,52), UDim2.new(0,20,1,-130))
mkOv("lyrics", UDim2.new(0,560,0,38), UDim2.new(0.5,-280,0,12))
mkOv("keystrokes", UDim2.new(0,148,0,96), UDim2.new(0,20,0,50))
mkOv("mousestrokes",UDim2.new(0,140,0,106), UDim2.new(0,20,0,160))
mkOv("potions", UDim2.new(0,200,0,71), UDim2.new(0,20,0.5,-40), true, function() if Fn.potionsCycle then Fn.potionsCycle() end end)
-- Keep the shine motion in one lightweight render loop for every overlay.
RS.RenderStepped:Connect(function()
local phase = (os.clock() % 3.4) / 3.4
for _, item in pairs(overlayShines) do
local on = feat.overlayShine and item.owner.Parent ~= nil and item.owner.Visible
item.frame.Visible = on
if on then
item.frame.Position = UDim2.new(-0.42 + phase * 1.84, 0, 0.5, 0)
end
end
end)
-- edit-mode hint pill
local hint = new("Frame",{Size=UDim2.new(0,430,0,28),Position=UDim2.new(0.5,-215,0,8),BackgroundColor3=T.Card,BackgroundTransparency=0.15,BorderSizePixel=0,Visible=false,ZIndex=60,Parent=ovGui})
corner(hint, 14); regRef(hint, "BackgroundColor3", "Card")
local hs = stroke(hint, 1, 0.3, T.Accent, true); regRef(hs, "Color", "Accent")
local hl = new("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(1,0,1,0),Font=Enum.Font.GothamMedium,Text="EDIT MODE • drag logo + status bar together as one widget • click = next layout • corner = resize",TextColor3=T.Text,TextSize=11,ZIndex=61,Parent=hint})
regRef(hl, "TextColor3", "Text")
table.insert(Edit.listeners, function(on)
for _, f in pairs(overlays) do
f.Active = on
local es = f:FindFirstChild("OwoEdit"); if es then es.Enabled = on end
end
hint.Visible = on
end)
do
local sb = overlays.statusBar
-- The parent is transparent and owns movement/toggling for both pieces.
-- This keeps the old visual: a separate logo badge beside a long dark strip.
sb.Size = UDim2.new(0,560,0,42)
sb.Position = UDim2.new(0.5,-280,0,2)
sb.BackgroundTransparency = 1
sb.ClipsDescendants = false
sb.Active = true
local badge = new("Frame", {
Name="StatusBarMoonwareLogo", Size=UDim2.new(0,42,0,42),
Position=UDim2.new(0,0,0,0), BackgroundColor3=Color3.fromRGB(9,11,15),
BackgroundTransparency=0.025, BorderSizePixel=0, ClipsDescendants=true,
ZIndex=35, Parent=sb
})
corner(badge, 21)
local badgeStroke = stroke(badge, 1, 0.20, Color3.fromRGB(43,49,60), true)
badgeStroke.Thickness = 1
-- Original Moonware decal, in its own visual badge. It is NOT a
-- separate overlay: moving the parent moves logo and status strip together.
do
local fallback = moonMark(
badge, 30, UDim2.new(0.5,-15,0.5,-15), T.Text,
badge.BackgroundColor3, 1, 42, "MoonwareLogoFallback"
)
local image = new("ImageLabel", {
Name="MoonwareOriginalDecal", Size=UDim2.new(1,-8,1,-8),
Position=UDim2.new(0,4,0,4), BackgroundTransparency=1,
Image="", ImageColor3=Color3.new(1,1,1),
ScaleType=Enum.ScaleType.Fit, Visible=false, ZIndex=38, Parent=badge
})
applyRobloxAssetIcon(image, "88265765726960", fallback)
end
local bar = new("Frame", {
Name="StatusBarInfoPill", Position=UDim2.new(0,44,0,0),
Size=UDim2.new(1,-44,1,0), BackgroundColor3=Color3.fromRGB(16,17,22),
BackgroundTransparency=0.025, BorderSizePixel=0, ClipsDescendants=true,
Active=false, ZIndex=31, Parent=sb
})
corner(bar, 21)
local barStroke = stroke(bar, 1, 0.20, Color3.fromRGB(39,45,56), true)
barStroke.Thickness = 1
local normalLayer = new("Frame", {
Position=UDim2.new(0,0,0,0), Size=UDim2.new(1,0,1,0),
BackgroundTransparency=1, ZIndex=31, Parent=bar
})
local layout = new("Frame",{Size=UDim2.new(1,0,1,0),BackgroundTransparency=1,ZIndex=31,Parent=normalLayer})
new("UIListLayout",{
FillDirection=Enum.FillDirection.Horizontal,
HorizontalAlignment=Enum.HorizontalAlignment.Center,
VerticalAlignment=Enum.VerticalAlignment.Center,
Padding=UDim.new(0,7), SortOrder=Enum.SortOrder.LayoutOrder, Parent=layout
})
new("UIPadding",{PaddingLeft=UDim.new(0,7),PaddingRight=UDim.new(0,9),Parent=layout})
local function makeStatusText(name, size, order, initial, textSize)
return new("TextLabel",{
Name=name,BackgroundTransparency=1,Size=UDim2.new(0,size,0,20),
Font=Enum.Font.GothamMedium,Text=initial,TextColor3=T.Text,
TextSize=textSize or 10,TextXAlignment=Enum.TextXAlignment.Left,
TextTruncate=Enum.TextTruncate.AtEnd,LayoutOrder=order,ZIndex=33,Parent=layout
})
end
local function makePlayerIcon(order)
local holder = new("Frame",{
Name="StatusBarPlayerIcon",Size=UDim2.new(0,20,0,20),BackgroundTransparency=1,
LayoutOrder=order,ZIndex=33,Parent=layout
})
local fallback = new("Frame",{
Name="StatusBarPlayerFallback",Size=UDim2.new(1,0,1,0),BackgroundTransparency=1,
ZIndex=34,Parent=holder
})
local head = new("Frame",{
Size=UDim2.new(0,6,0,6),Position=UDim2.new(0.5,-3,0,1),
BackgroundColor3=T.Text,BorderSizePixel=0,ZIndex=35,Parent=fallback
})
corner(head, 4)
local shoulders = new("Frame",{
Size=UDim2.new(0,14,0,8),Position=UDim2.new(0.5,-7,0,9),
BackgroundColor3=T.Text,BorderSizePixel=0,ZIndex=35,Parent=fallback
})
corner(shoulders, 5)
regRef(head,"BackgroundColor3","Text"); regRef(shoulders,"BackgroundColor3","Text")
return holder, head, shoulders, fallback
end
local function makeClockIcon(order)
local holder = new("Frame",{
Name="StatusBarClockIcon",Size=UDim2.new(0,14,0,14),BackgroundTransparency=1,
LayoutOrder=order,ZIndex=33,Parent=layout
})
local ring = new("Frame",{
Size=UDim2.new(0,12,0,12),Position=UDim2.new(0,1,0,1),
BackgroundTransparency=1,BorderSizePixel=0,ZIndex=34,Parent=holder
})
corner(ring, 7)
local outline = new("UIStroke",{Color=T.Text,Thickness=1.15,Transparency=0.08,Parent=ring})
regRef(outline,"Color","Text")
local minute = new("Frame",{
Size=UDim2.new(0,1,0,4),Position=UDim2.new(0.5,-0.5,0,2),
BackgroundColor3=T.Text,BorderSizePixel=0,ZIndex=35,Parent=ring
})
local hour = new("Frame",{
Size=UDim2.new(0,4,0,1),Position=UDim2.new(0.5,0,0.5,0),
BackgroundColor3=T.Text,BorderSizePixel=0,ZIndex=35,Parent=ring
})
local center = new("Frame",{
Size=UDim2.new(0,2,0,2),Position=UDim2.new(0.5,-1,0.5,-1),
BackgroundColor3=T.Text,BorderSizePixel=0,ZIndex=36,Parent=ring
})
corner(minute,1); corner(hour,1); corner(center,2)
regRef(minute,"BackgroundColor3","Text"); regRef(hour,"BackgroundColor3","Text"); regRef(center,"BackgroundColor3","Text")
return holder, outline, minute, hour, center
end
local function makeSep(order)
return new("Frame",{
Size=UDim2.new(0,1,0,18),BackgroundColor3=Color3.fromRGB(52,55,64),
BackgroundTransparency=0.28,BorderSizePixel=0,LayoutOrder=order,ZIndex=33,Parent=layout
})
end
local function makeDot(order)
local d = new("Frame",{
Size=UDim2.new(0,5,0,5),BackgroundColor3=Color3.fromRGB(76,145,255),
BorderSizePixel=0,LayoutOrder=order,ZIndex=33,Parent=layout
})
corner(d,3)
return d
end
-- Reuse the selected Moonware profile picture in the info strip.
local playerIcon, playerHead, playerShoulders, playerFallback = makePlayerIcon(1)
local statusPfpImage = new("ImageLabel",{
Name="StatusBarProfilePicture",Size=UDim2.new(1,0,1,0),Position=UDim2.new(0,0,0,0),
BackgroundTransparency=1,Image="",ImageColor3=Color3.new(1,1,1),
ScaleType=Enum.ScaleType.Crop,Visible=false,ZIndex=37,Parent=playerIcon
})
corner(statusPfpImage, 10)
table.insert(profilePfpTargets, {image=statusPfpImage, fallback=playerFallback})
local nameLbl = makeStatusText("StatusBarPlayerName", 68, 2, player.DisplayName or player.Name, 10)
local sep1 = makeSep(3)
local timeIcon, clockOutline, clockMinute, clockHour, clockCenter = makeClockIcon(4)
local timeLbl = makeStatusText("StatusBarClock", 42, 5, "00:00", 10)
local sep2 = makeSep(6)
local fpsDot = makeDot(7)
local fpsLbl = makeStatusText("StatusBarFPS", 46, 8, "0 FPS", 10)
local sep3 = makeSep(9)
local pingDot = makeDot(10)
local pingLbl = makeStatusText("StatusBarPing", 48, 11, "0 MS", 10)
regRef(nameLbl,"TextColor3","Text")
regRef(timeLbl,"TextColor3","Text")
regRef(fpsLbl,"TextColor3","Text")
regRef(pingLbl,"TextColor3","Text")
-- Tiny animated equalizer at the start of the lyric pill, matching the reference.
local eqBars = {}
for i = 1, 3 do
local eb = new("Frame", {
Name="StatusBarWaveBar"..i, Size=UDim2.new(0,2,0,8),
Position=UDim2.new(0,14+(i-1)*5,0.5,-4), BackgroundColor3=Color3.fromRGB(245,246,249),
BorderSizePixel=0, ZIndex=37, Parent=bar
})
corner(eb, 2)
new("UIStroke", {Color=Color3.fromRGB(112,116,126), Thickness=0.7, Transparency=0.22, Parent=eb})
eqBars[i] = eb
end
local lyricClip = new("Frame", {
Name="StatusBarLyricsClip", Size=UDim2.new(1,-56,1,0), Position=UDim2.new(0,42,0,0),
BackgroundTransparency=1, BorderSizePixel=0, ClipsDescendants=true, ZIndex=36, Parent=bar
})
local lyricLbl = new("TextLabel", {
Name="StatusBarLyricsText", Size=UDim2.new(0,120,0,22), Position=UDim2.new(0,0,0.5,-11),
BackgroundTransparency=1, Font=Enum.Font.GothamMedium, Text="",
RichText=true, TextColor3=T.Text, TextSize=13,
TextStrokeColor3=Color3.fromRGB(112,116,126), TextStrokeTransparency=0.38,
TextTruncate=Enum.TextTruncate.None, TextXAlignment=Enum.TextXAlignment.Left,
TextYAlignment=Enum.TextYAlignment.Center, TextTransparency=1,
AutomaticSize=Enum.AutomaticSize.None, ZIndex=38, Parent=lyricClip
})
local lyricLineShown, lyricLineText, lyricActiveWord = nil, nil, nil
local lyricLineStart = 0
local lyricCurrentX = nil
local lyricMetrics = nil
local lyricTextService = game:GetService("TextService")
local function lyricWordWidth(word)
local ok, bounds = pcall(function()
return lyricTextService:GetTextSize(word, 13, Enum.Font.GothamMedium, Vector2.new(4000, 24))
end)
return ok and bounds.X or (#word * 7)
end
local function showSmoothStatusLyric(line, activeWord, lineIndex, wordProgress, dt)
local words = line.words or {}
if #words == 0 then return end
activeWord = math.clamp(activeWord or 1, 1, #words)
wordProgress = math.clamp(wordProgress or 0, 0, 1)
local lineText = line.text or table.concat(words, " ")
local changedLine = lyricLineShown ~= lineIndex or lyricLineText ~= lineText
if changedLine then
lyricLineShown, lyricLineText, lyricActiveWord = lineIndex, lineText, nil
lyricLineStart = os.clock()
lyricMetrics = {widths={}, centers={}, total=0}
for i, word in ipairs(words) do
local ww = lyricWordWidth(word)
lyricMetrics.widths[i] = ww
lyricMetrics.centers[i] = lyricMetrics.total + ww * 0.5
lyricMetrics.total += ww
if i < #words then lyricMetrics.total += lyricWordWidth(" ") end
end
lyricLbl.Size = UDim2.new(0, math.max(24, math.ceil(lyricMetrics.total + 8)), 0, 22)
lyricCurrentX = nil
lyricLbl.Position = UDim2.new(0, math.max(80, lyricClip.AbsoluteSize.X) + 14, 0.5, -11)
end
if lyricActiveWord ~= activeWord then
lyricActiveWord = activeWord
local parts = {}
for i, word in ipairs(words) do
local safe = tostring(word):gsub("&", "&"):gsub("<", "<"):gsub(">", ">")
if i < activeWord then
parts[#parts+1] = ''..safe..''
elseif i == activeWord then
parts[#parts+1] = ''..safe..''
else
parts[#parts+1] = ''..safe..''
end
end
lyricLbl.Text = table.concat(parts, " ")
end
local viewW = math.max(80, lyricClip.AbsoluteSize.X)
local centerNow = lyricMetrics.centers[activeWord] or 0
local centerNext = lyricMetrics.centers[math.min(activeWord + 1, #words)] or centerNow
local center = centerNow + (centerNext - centerNow) * (activeWord < #words and wordProgress or 0)
local maxLeft = math.min(0, viewW - lyricMetrics.total - 8)
local targetX = math.floor(math.clamp(viewW * 0.43 - center, maxLeft, 0))
local elapsed = os.clock() - lyricLineStart
local enter = math.clamp(elapsed / 0.46, 0, 1)
local ease = 1 - (1 - enter) * (1 - enter) * (1 - enter)
local startX = viewW + 14
local animatedTarget = startX + (targetX - startX) * ease
if lyricCurrentX == nil then lyricCurrentX = startX end
local blend = changedLine and 1 or (1 - math.exp(-math.max(dt or 1/60, 1/240) * 15))
if changedLine then
lyricCurrentX = animatedTarget
else
lyricCurrentX = lyricCurrentX + (targetX - lyricCurrentX) * blend
end
lyricLbl.Position = UDim2.new(0, math.floor(lyricCurrentX), 0.5, -11)
end
Fn.showSmoothStatusLyric = showSmoothStatusLyric
Fn.statusBarEqBars = eqBars
local normalEls = {
{inst=playerHead,prop="BackgroundTransparency",orig=playerHead.BackgroundTransparency},
{inst=playerShoulders,prop="BackgroundTransparency",orig=playerShoulders.BackgroundTransparency},
{inst=statusPfpImage,prop="ImageTransparency",orig=statusPfpImage.ImageTransparency},
{inst=clockOutline,prop="Transparency",orig=clockOutline.Transparency},
{inst=clockMinute,prop="BackgroundTransparency",orig=clockMinute.BackgroundTransparency},
{inst=clockHour,prop="BackgroundTransparency",orig=clockHour.BackgroundTransparency},
{inst=clockCenter,prop="BackgroundTransparency",orig=clockCenter.BackgroundTransparency},
{inst=nameLbl,prop="TextTransparency",orig=nameLbl.TextTransparency},
{inst=timeLbl,prop="TextTransparency",orig=timeLbl.TextTransparency},
{inst=fpsLbl,prop="TextTransparency",orig=fpsLbl.TextTransparency},
{inst=pingLbl,prop="TextTransparency",orig=pingLbl.TextTransparency},
{inst=fpsDot,prop="BackgroundTransparency",orig=fpsDot.BackgroundTransparency},
{inst=pingDot,prop="BackgroundTransparency",orig=pingDot.BackgroundTransparency},
{inst=sep1,prop="BackgroundTransparency",orig=sep1.BackgroundTransparency},
{inst=sep2,prop="BackgroundTransparency",orig=sep2.BackgroundTransparency},
{inst=sep3,prop="BackgroundTransparency",orig=sep3.BackgroundTransparency},
}
local sbMode = "normal"
Fn.setSbMode = function(mode, animate)
if sbMode == mode then return end
sbMode = mode
local dur = (animate and feat.smoothLyricsTransition) and feat.lyricsTransitionDuration or 0
local info = TweenInfo.new(sdur(dur), Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
if mode == "lyrics" then
for _, el in ipairs(normalEls) do pcall(function() TS:Create(el.inst, info, {[el.prop]=1}):Play() end) end
TS:Create(lyricLbl, info, {TextTransparency=0}):Play()
else
for _, el in ipairs(normalEls) do pcall(function() TS:Create(el.inst, info, {[el.prop]=el.orig}):Play() end) end
TS:Create(lyricLbl, info, {TextTransparency=1}):Play()
end
end
Fn.sbLyricLbl = lyricLbl
local fpsBox = new("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(1,0,1,0),Font=Enum.Font.GothamBold,Text="0 fps",TextColor3=T.Text,TextSize=13,Parent=overlays.fps})
local pingBox = new("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(1,0,1,0),Font=Enum.Font.GothamBold,Text="0 ms",TextColor3=T.Text,TextSize=13,Parent=overlays.ping})
regRef(fpsBox,"TextColor3","Text"); regRef(pingBox,"TextColor3","Text")
local fps, ping, frames, lastSec = 0, 0, 0, tick()
RS.RenderStepped:Connect(function()
frames += 1
if tick() - lastSec >= 1 then
fps = frames; frames = 0; lastSec = tick()
local ok, p = pcall(function() return Stats.Network.ServerStatsItem["Data Ping"]:GetValue() end)
if ok and type(p) == "number" then ping = math.max(0, math.floor(p + 0.5)) end
end
end)
local function localClock()
local ok, value = pcall(function() return DateTime.now():FormatLocalTime("HH:mm", "en-us") end)
if ok and type(value) == "string" then return value end
return os.date("%H:%M")
end
task.spawn(function()
while sb.Parent do
task.wait(0.5)
if sb.Visible then
nameLbl.Text = player.DisplayName or player.Name
timeLbl.Text = localClock()
fpsLbl.Text = tostring(fps) .. " FPS"
pingLbl.Text = tostring(ping) .. " MS"
end
if overlays.fps.Visible then fpsBox.Text = fps .. " fps" end
if overlays.ping.Visible then pingBox.Text = ping .. " ms" end
end
end)
end
local lyLbl
do
lyLbl = new("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(1,-24,1,0),Position=UDim2.new(0,12,0,0),Font=Enum.Font.GothamMedium,Text="",RichText=true,TextColor3=T.Text,TextSize=16,TextStrokeColor3=Color3.fromRGB(112,116,126),TextStrokeTransparency=0.38,TextTruncate=Enum.TextTruncate.AtEnd,Parent=overlays.lyrics})
regRef(lyLbl,"TextColor3","Text")
end
-- KEYSTROKES
do
local ks = overlays.keystrokes
local keyFrames = {}
local ksScale = new("UIScale", {Name = "KSScale", Scale = 1, Parent = ks})
local function mkKey(name, label, x, y, w, h)
local key = new("Frame", {
Size = UDim2.new(0, w, 0, h),
Position = UDim2.new(0, x, 0, y),
BackgroundColor3 = T.Card, BackgroundTransparency = 0.2,
BorderSizePixel = 0, Parent = ks,
})
corner(key, 5)
local s = stroke(key, 1, 0.5, T.Line, true)
local lbl = new("TextLabel", {
BackgroundTransparency = 1, Size = UDim2.new(1, 0, 1, 0),
Font = Enum.Font.GothamBold, Text = label,
TextColor3 = T.Dim, TextSize = 11, Parent = key,
})
regRef(key, "BackgroundColor3", "Card"); regRef(lbl, "TextColor3", "Dim")
keyFrames[name] = { frame = key, label = lbl, stroke = s, pressed = false }
end
mkKey("W", "W", 51, 6, 38, 26)
mkKey("A", "A", 9, 34, 38, 26)
mkKey("S", "S", 51, 34, 38, 26)
mkKey("D", "D", 93, 34, 38, 26)
mkKey("Space", "SPACE", 8, 62, 124, 20)
local grip = new("TextButton", {
Size = UDim2.new(0, 18, 0, 18), Position = UDim2.new(1, -18, 1, -18),
BackgroundTransparency = 1, Text = "", AutoButtonColor = false, ZIndex = 60, Visible = false, Parent = ks,
})
table.insert(Edit.listeners, function(on) grip.Visible = on end)
for i = 1, 2 do
new("Frame", {Size = UDim2.new(0, 9, 0, 1), Position = UDim2.new(0, 5 + (i-1)*3, 0, 13 - (i-1)*3), BackgroundColor3 = T.Muted, BackgroundTransparency = 0.4, BorderSizePixel = 0, Rotation = 45, ZIndex = 61, Parent = grip})
end
dragBlockers[ks] = function(pos)
local gp, gs = grip.AbsolutePosition, grip.AbsoluteSize
return pos.X >= gp.X and pos.X <= gp.X + gs.X and pos.Y >= gp.Y and pos.Y <= gp.Y + gs.Y
end
local ksDrag, ksStart, ksStartScale = false, nil, 1
grip.InputBegan:Connect(function(i)
if not Fn.canEdit() then return end
if i.UserInputType == Enum.UserInputType.MouseButton1 or i.UserInputType == Enum.UserInputType.Touch then
ksDrag = true; ksStart = i.Position; ksStartScale = ksScale.Scale
end
end)
UIS.InputChanged:Connect(function(i)
if ksDrag and (i.UserInputType == Enum.UserInputType.MouseMovement or i.UserInputType == Enum.UserInputType.Touch) then
local dx = i.Position.X - ksStart.X
local dy = i.Position.Y - ksStart.Y
ksScale.Scale = math.clamp(ksStartScale + ((dx + dy) * 0.5) / 140, 0.5, 3)
end
end)
UIS.InputEnded:Connect(function(i)
if ksDrag and (i.UserInputType == Enum.UserInputType.MouseButton1 or i.UserInputType == Enum.UserInputType.Touch) then ksDrag = false end
end)
local state = { W=false, A=false, S=false, D=false, Space=false }
local function refresh(name)
local kf = keyFrames[name]; if not kf then return end
local on = state[name]
if kf.pressed == on then return end
kf.pressed = on
if on then
tween(kf.frame, 0.12, {BackgroundColor3 = T.Accent, BackgroundTransparency = 0}, Enum.EasingStyle.Back)
tween(kf.label, 0.12, {TextColor3 = ON_ACCENT}, Enum.EasingStyle.Back)
kf.stroke.Color = T.Accent; kf.stroke.Transparency = 0.2
else
tween(kf.frame, 0.16, {BackgroundColor3 = T.Card, BackgroundTransparency = 0.2})
tween(kf.label, 0.16, {TextColor3 = T.Dim})
kf.stroke.Color = T.Line; kf.stroke.Transparency = 0.5
end
end
UIS.InputBegan:Connect(function(i, gp)
if gp then return end
local c = i.KeyCode
if c == Enum.KeyCode.W then state.W = true; refresh("W")
elseif c == Enum.KeyCode.A then state.A = true; refresh("A")
elseif c == Enum.KeyCode.S then state.S = true; refresh("S")
elseif c == Enum.KeyCode.D then state.D = true; refresh("D")
elseif c == Enum.KeyCode.Space then state.Space = true; refresh("Space")
end
end)
UIS.InputEnded:Connect(function(i)
local c = i.KeyCode
if c == Enum.KeyCode.W then state.W = false; refresh("W")
elseif c == Enum.KeyCode.A then state.A = false; refresh("A")
elseif c == Enum.KeyCode.S then state.S = false; refresh("S")
elseif c == Enum.KeyCode.D then state.D = false; refresh("D")
elseif c == Enum.KeyCode.Space then state.Space = false; refresh("Space")
end
end)
end
-- MOUSESTROKES
do
local ms = overlays.mousestrokes
local btnFrames = {}
local msScale = new("UIScale", {Name = "MSScale", Scale = 1, Parent = ms})
local function mkBtn(name, label, x, y, w, h)
local b = new("Frame", {
Size = UDim2.new(0, w, 0, h),
Position = UDim2.new(0, x, 0, y),
BackgroundColor3 = T.Card, BackgroundTransparency = 0.2,
BorderSizePixel = 0, Parent = ms,
})
corner(b, 5)
local s = stroke(b, 1, 0.5, T.Line, true)
local lbl = new("TextLabel", {
BackgroundTransparency = 1, Size = UDim2.new(1, 0, 1, 0),
Font = Enum.Font.GothamBold, Text = label,
TextColor3 = T.Dim, TextSize = 11, Parent = b,
})
regRef(b, "BackgroundColor3", "Card"); regRef(lbl, "TextColor3", "Dim")
btnFrames[name] = { frame = b, label = lbl, stroke = s, pressed = false }
end
mkBtn("LMB", "LMB", 8, 6, 60, 24)
mkBtn("RMB", "RMB", 72, 6, 60, 24)
local mouseBox = new("Frame", {
Size = UDim2.new(0, 124, 0, 52), Position = UDim2.new(0, 8, 0, 38),
BackgroundColor3 = T.Bg, BackgroundTransparency = 0.35,
BorderSizePixel = 0, Parent = ms,
})
corner(mouseBox, 5); stroke(mouseBox, 1, 0.5, T.Line, true)
regRef(mouseBox, "BackgroundColor3", "Bg")
local mouseLbl = new("TextLabel", {
BackgroundTransparency = 1, Position = UDim2.new(0, 6, 0, 3), Size = UDim2.new(1, -12, 0, 12),
Font = Enum.Font.Gotham, Text = "MOUSE", TextColor3 = T.Muted, TextSize = 9,
TextXAlignment = Enum.TextXAlignment.Left, Parent = mouseBox,
})
regRef(mouseLbl, "TextColor3", "Muted")
local mouseDot = new("Frame", {
Size = UDim2.new(0, 8, 0, 8), Position = UDim2.new(0.5, -4, 0.5, -4),
BackgroundColor3 = T.Accent, BorderSizePixel = 0, Parent = mouseBox,
})
corner(mouseDot, 4); regRef(mouseDot, "BackgroundColor3", "Accent")
local grip = new("TextButton", {
Size = UDim2.new(0, 18, 0, 18), Position = UDim2.new(1, -18, 1, -18),
BackgroundTransparency = 1, Text = "", AutoButtonColor = false, ZIndex = 60, Visible = false, Parent = ms,
})
table.insert(Edit.listeners, function(on) grip.Visible = on end)
for i = 1, 2 do
new("Frame", {Size = UDim2.new(0, 9, 0, 1), Position = UDim2.new(0, 5 + (i-1)*3, 0, 13 - (i-1)*3), BackgroundColor3 = T.Muted, BackgroundTransparency = 0.4, BorderSizePixel = 0, Rotation = 45, ZIndex = 61, Parent = grip})
end
dragBlockers[ms] = function(pos)
local gp, gs = grip.AbsolutePosition, grip.AbsoluteSize
return pos.X >= gp.X and pos.X <= gp.X + gs.X and pos.Y >= gp.Y and pos.Y <= gp.Y + gs.Y
end
local msDrag, msStart, msStartScale = false, nil, 1
grip.InputBegan:Connect(function(i)
if not Fn.canEdit() then return end
if i.UserInputType == Enum.UserInputType.MouseButton1 or i.UserInputType == Enum.UserInputType.Touch then
msDrag = true; msStart = i.Position; msStartScale = msScale.Scale
end
end)
UIS.InputChanged:Connect(function(i)
if msDrag and (i.UserInputType == Enum.UserInputType.MouseMovement or i.UserInputType == Enum.UserInputType.Touch) then
local dx = i.Position.X - msStart.X
local dy = i.Position.Y - msStart.Y
msScale.Scale = math.clamp(msStartScale + ((dx + dy) * 0.5) / 140, 0.5, 3)
end
end)
UIS.InputEnded:Connect(function(i)
if msDrag and (i.UserInputType == Enum.UserInputType.MouseButton1 or i.UserInputType == Enum.UserInputType.Touch) then msDrag = false end
end)
local state = { LMB = false, RMB = false }
local function refresh(name)
local bf = btnFrames[name]; if not bf then return end
local on = state[name]
if bf.pressed == on then return end
bf.pressed = on
if on then
tween(bf.frame, 0.12, {BackgroundColor3 = T.Accent, BackgroundTransparency = 0}, Enum.EasingStyle.Back)
tween(bf.label, 0.12, {TextColor3 = ON_ACCENT}, Enum.EasingStyle.Back)
bf.stroke.Color = T.Accent; bf.stroke.Transparency = 0.2
else
tween(bf.frame, 0.16, {BackgroundColor3 = T.Card, BackgroundTransparency = 0.2})
tween(bf.label, 0.16, {TextColor3 = T.Dim})
bf.stroke.Color = T.Line; bf.stroke.Transparency = 0.5
end
end
UIS.InputBegan:Connect(function(i)
if i.UserInputType == Enum.UserInputType.MouseButton1 then state.LMB = true; refresh("LMB") end
if i.UserInputType == Enum.UserInputType.MouseButton2 then state.RMB = true; refresh("RMB") end
end)
UIS.InputEnded:Connect(function(i)
if i.UserInputType == Enum.UserInputType.MouseButton1 then state.LMB = false; refresh("LMB") end
if i.UserInputType == Enum.UserInputType.MouseButton2 then state.RMB = false; refresh("RMB") end
end)
local mx, my = 0, 0
local lastMousePos = nil
UIS.InputChanged:Connect(function(i)
if i.UserInputType ~= Enum.UserInputType.MouseMovement then return end
local dX, dY = i.Delta.X, i.Delta.Y
if lastMousePos then
local pX = i.Position.X - lastMousePos.X
local pY = i.Position.Y - lastMousePos.Y
if pX*pX + pY*pY > dX*dX + dY*dY then dX, dY = pX, pY end
end
lastMousePos = i.Position
mx = mx + dX; my = my + dY
end)
local smx, smy = 0, 0
RS.RenderStepped:Connect(function(dt)
mx = mx * math.exp(-dt * 8)
my = my * math.exp(-dt * 8)
smx = slerp(smx, mx, dt, 22)
smy = slerp(smy, my, dt, 22)
if not ms.Visible then return end
local dx = math.clamp(smx, -50, 50)
local dy = math.clamp(smy, -18, 18)
mouseDot.Position = UDim2.new(0.5, dx - 4, 0.5, dy - 4)
end)
end
local coordsLbl, spVal, spBar
do
local c = overlays.coords
local dia = new("Frame",{Size=UDim2.new(0,9,0,9),Position=UDim2.new(0,14,0.5,-4),BackgroundColor3=T.Accent,BorderSizePixel=0,Rotation=45,Parent=c}); corner(dia,2); regRef(dia,"BackgroundColor3","Accent")
coordsLbl = new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,34,0,0),Size=UDim2.new(1,-40,1,0),Font=Enum.Font.GothamMedium,Text="x 0 y 0 z 0",TextColor3=T.Text,TextSize=12,RichText=true,TextXAlignment=Enum.TextXAlignment.Left,Parent=c}); regRef(coordsLbl,"TextColor3","Text")
local s = overlays.speed
local ic = new("Frame",{Size=UDim2.new(0,11,0,9),Position=UDim2.new(0,10,0,9),BackgroundColor3=T.Accent,BorderSizePixel=0,Parent=s}); corner(ic,3); regRef(ic,"BackgroundColor3","Accent")
local st = new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,28,0,4),Size=UDim2.new(1,-34,0,18),Font=Enum.Font.GothamBold,Text="Speed",TextColor3=T.Text,TextSize=11,TextXAlignment=Enum.TextXAlignment.Left,Parent=s}); regRef(st,"TextColor3","Text")
spVal = new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,10,0,24),Size=UDim2.new(1,-20,0,14),Font=Enum.Font.Gotham,Text="0,00 bps",TextColor3=T.Dim,TextSize=11,TextXAlignment=Enum.TextXAlignment.Left,Parent=s}); regRef(spVal,"TextColor3","Dim")
local bg = new("Frame",{Position=UDim2.new(0,10,1,-9),Size=UDim2.new(1,-20,0,2),BackgroundColor3=T.Line,BackgroundTransparency=0.3,BorderSizePixel=0,Parent=s})
spBar = new("Frame",{Size=UDim2.new(0,0,1,0),BackgroundColor3=T.Accent,BorderSizePixel=0,Parent=bg}); regRef(spBar,"BackgroundColor3","Accent")
end
-- ══════════ KEYBINDS overlay: 2 layouts (List / Pills) that morph smoothly ══════════
do
local kb = overlays.keybinds
local TextService = game:GetService("TextService")
local W1 = 214
local SHORT = {RightShift="RShift",LeftShift="LShift",LeftControl="LCtrl",RightControl="RCtrl",LeftAlt="LAlt",RightAlt="RAlt",Backquote="Grave",Return="Enter",Backspace="Bksp"}
local function txtW(str, size, font)
local ok, v = pcall(function() return TextService:GetTextSize(str, size, font, Vector2.new(400, 50)).X end)
return ok and v or (#str * size * 0.55)
end
local function pillBg(parent)
local f = new("Frame",{BackgroundColor3=T.Card,BackgroundTransparency=1,BorderSizePixel=0,Parent=parent}); corner(f, 9)
return f
end
local hIconBg = pillBg(kb); regRef(hIconBg, "BackgroundColor3", "Card")
local hIcon = new("TextLabel",{BackgroundTransparency=1,Size=UDim2.fromScale(1,1),Font=Enum.Font.GothamBold,Text="⌨",TextColor3=T.Accent,TextSize=15,Parent=hIconBg}); regRef(hIcon, "TextColor3", "Accent")
local hTitleBg = pillBg(kb); regRef(hTitleBg, "BackgroundColor3", "Card")
local hTitle = new("TextLabel",{BackgroundTransparency=1,Size=UDim2.fromScale(1,1),Font=Enum.Font.GothamBold,Text="Keybinds",TextColor3=T.Text,TextSize=13,TextXAlignment=Enum.TextXAlignment.Left,Parent=hTitleBg}); regRef(hTitle, "TextColor3", "Text")
local emptyLbl = new("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(0,150,0,18),Font=Enum.Font.Gotham,Text="No keybinds set",TextColor3=T.Muted,TextSize=11,TextXAlignment=Enum.TextXAlignment.Left,Parent=kb}); regRef(emptyLbl, "TextColor3", "Muted")
local rowsHolder = new("Frame",{BackgroundTransparency=1,Size=UDim2.fromScale(1,1),Parent=kb})
local rowObjs, list = {}, {}
local function apply(animate)
local st = feat.layout_keybinds or 1
if st < 1 or st > 2 then st = 1 end
local n = #list
local function mv(o, props, dur)
if animate then tween(o, dur or 0.34, props, Enum.EasingStyle.Quint, Enum.EasingDirection.Out)
else for k, v in pairs(props) do o[k] = v end end
end
local bare = (st == 2)
kb:SetAttribute("LBare", bare)
local ln = kb:FindFirstChild("OwoLine")
if ln then mv(ln, {Transparency = bare and 1 or 0.6}, 0.25) end
mv(kb, {BackgroundTransparency = bare and 1 or TR.Overlay}, 0.25)
if Glass.refreshAll then Glass.refreshAll() end
emptyLbl.Visible = (n == 0)
local keyTint = T.Accent:Lerp(T.Bg, 0.62)
if st == 1 then
mv(hIconBg, {Position=UDim2.new(0,12,0,9), Size=UDim2.new(0,22,0,22), BackgroundTransparency=1})
mv(hTitleBg, {Position=UDim2.new(0,38,0,9), Size=UDim2.new(0,W1-50,0,22), BackgroundTransparency=1})
mv(hTitle, {Position=UDim2.new(0,0,0,0)})
emptyLbl.Position = UDim2.new(0,14,0,40)
for i, ro in ipairs(rowObjs) do
local y = 40 + (i-1)*24
local kw = math.max(32, ro.kw + 16)
mv(ro.nameBg, {Position=UDim2.new(0,14,0,y), Size=UDim2.new(0,W1-kw-34,0,20), BackgroundTransparency=1})
mv(ro.nameLbl, {Position=UDim2.new(0,0,0,0)})
mv(ro.keyBg, {Position=UDim2.new(0,W1-12-kw,0,y+1), Size=UDim2.new(0,kw,0,18), BackgroundTransparency=0.3, BackgroundColor3=keyTint})
mv(ro.keyLbl, {TextColor3=T.Accent})
end
mv(kb, {Size=UDim2.new(0,W1,0,40 + math.max(n,1)*24 + 8)})
else
local maxW, rowW = 0, {}
for i, ro in ipairs(rowObjs) do
local nw = math.max(64, ro.nw + 24)
local kw = math.max(36, ro.kw + 20)
rowW[i] = {nw, kw}
maxW = math.max(maxW, nw + 6 + kw)
end
local W2 = math.max(150, maxW)
mv(hIconBg, {Position=UDim2.new(0,0,0,0), Size=UDim2.new(0,28,0,28), BackgroundTransparency=0.1})
mv(hTitleBg, {Position=UDim2.new(0,34,0,0), Size=UDim2.new(0,W2-34,0,28), BackgroundTransparency=0.1})
mv(hTitle, {Position=UDim2.new(0,12,0,0)})
emptyLbl.Position = UDim2.new(0,4,0,36)
for i, ro in ipairs(rowObjs) do
local y = 36 + (i-1)*32
local nw, kw = rowW[i][1], rowW[i][2]
mv(ro.nameBg, {Position=UDim2.new(0,0,0,y), Size=UDim2.new(0,nw,0,26), BackgroundTransparency=0.1})
mv(ro.nameLbl, {Position=UDim2.new(0,12,0,0)})
mv(ro.keyBg, {Position=UDim2.new(0,nw+6,0,y), Size=UDim2.new(0,kw,0,26), BackgroundTransparency=0.1, BackgroundColor3=T.Card})
mv(ro.keyLbl, {TextColor3=T.Text})
end
mv(kb, {Size=UDim2.new(0,W2,0,36 + math.max(n,1)*32 - 6)})
end
end
Fn.refreshKb = function()
for _, ro in ipairs(rowObjs) do ro.nameBg:Destroy(); ro.keyBg:Destroy() end
rowObjs, list = {}, {}
for _, k in pairs(Keybinds) do if k.key then list[#list+1] = k end end
table.sort(list, function(a, b) return (a.label or "") < (b.label or "") end)
for i, k in ipairs(list) do
local nm = SHORT[k.key.Name] or k.key.Name
local lab = k.label or "?"
local nameBg = pillBg(rowsHolder); regRef(nameBg, "BackgroundColor3", "Card")
local nameLbl = new("TextLabel",{BackgroundTransparency=1,Size=UDim2.fromScale(1,1),Font=Enum.Font.GothamMedium,Text=lab,TextColor3=T.Dim,TextSize=12,TextXAlignment=Enum.TextXAlignment.Left,TextTruncate=Enum.TextTruncate.AtEnd,Parent=nameBg})
local keyBg = pillBg(rowsHolder)
local keyLbl = new("TextLabel",{BackgroundTransparency=1,Size=UDim2.fromScale(1,1),Font=Enum.Font.GothamBold,Text=nm,TextColor3=T.Text,TextSize=11,Parent=keyBg})
rowObjs[i] = {k=k, nameBg=nameBg, nameLbl=nameLbl, keyBg=keyBg, keyLbl=keyLbl, nw=txtW(lab, 12, Enum.Font.GothamMedium), kw=txtW(nm, 11, Enum.Font.GothamBold)}
end
apply(false)
end
Fn.kbApply = apply
Fn.kbCycle = function()
feat.layout_keybinds = ((feat.layout_keybinds or 1) % 2) + 1
apply(true)
notify("Keybinds", "Layout: " .. (feat.layout_keybinds == 1 and "List" or "Pills"))
end
-- enabled binds light up (accent in List, bright in Pills)
task.spawn(function()
while true do
task.wait(0.25)
if kb.Visible then
local st = feat.layout_keybinds or 1
for _, ro in ipairs(rowObjs) do
local on = ro.k.isToggle and ro.k.getState and ro.k.getState()
if st == 1 then ro.nameLbl.TextColor3 = on and T.Accent or T.Dim
else ro.nameLbl.TextColor3 = on and T.Text or T.Muted end
end
end
end
end)
end
local mhTitle, mhSub, coverImg, playIcon, pauseIcon, mhFill
do
local mh = overlays.musicHud
local cover = new("Frame",{Size=UDim2.new(0,78,0,78),Position=UDim2.new(0,12,0,13),BackgroundColor3=Color3.new(1,1,1),BorderSizePixel=0,Parent=mh}); corner(cover,10)
local coverG = gradient(cover,T.Accent,T.Accent2,45)
new("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(1,0,1,0),Font=Enum.Font.GothamBold,Text="♪",TextColor3=ON_ACCENT,TextSize=32,Parent=cover})
coverImg = new("ImageLabel",{Size=UDim2.new(1,0,1,0),BackgroundTransparency=1,Image="",ScaleType=Enum.ScaleType.Crop,Parent=cover}); corner(coverImg,10)
mhTitle = new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,102,0,12),Size=UDim2.new(1,-114,0,20),Font=Enum.Font.GothamBold,Text="Nothing playing",TextColor3=T.Text,TextSize=14,TextXAlignment=Enum.TextXAlignment.Left,TextTruncate=Enum.TextTruncate.AtEnd,Parent=mh}); regRef(mhTitle,"TextColor3","Text")
mhSub = new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,102,0,32),Size=UDim2.new(1,-114,0,16),Font=Enum.Font.Gotham,Text="Pick a song",TextColor3=T.Dim,TextSize=11,TextXAlignment=Enum.TextXAlignment.Left,Parent=mh}); regRef(mhSub,"TextColor3","Dim")
local function ctrl(x, txt)
local b = new("TextButton",{Size=UDim2.new(0,30,0,28),Position=UDim2.new(0,x,0,52),BackgroundTransparency=1,Text=txt,Font=Enum.Font.GothamBold,TextColor3=T.Text,TextSize=20,AutoButtonColor=false,Parent=mh})
regRef(b,"TextColor3","Text"); return b
end
local prev = ctrl(122,"‹‹"); local play = ctrl(166,""); local nxt = ctrl(210,"››")
playIcon = new("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(1,0,1,0),Font=Enum.Font.GothamBold,Text="▶",TextColor3=T.Text,TextSize=16,Parent=play}); regRef(playIcon,"TextColor3","Text")
pauseIcon = new("Frame",{BackgroundTransparency=1,Size=UDim2.new(1,0,1,0),Visible=false,Parent=play})
for _, x in ipairs({7,17}) do
local bar = new("Frame",{Size=UDim2.new(0,5,0,14),Position=UDim2.new(0,x,0.5,-7),BackgroundColor3=T.Text,BorderSizePixel=0,Parent=pauseIcon}); corner(bar,2); regRef(bar,"BackgroundColor3","Text")
end
prev.MouseButton1Click:Connect(function() Music.prev() end)
play.MouseButton1Click:Connect(function() Music.toggle() end)
nxt.MouseButton1Click:Connect(function() Music.next() end)
local track = new("Frame",{Position=UDim2.new(0,102,0,88),Size=UDim2.new(1,-114,0,4),BackgroundColor3=T.Line,BackgroundTransparency=0.2,BorderSizePixel=0,Parent=mh}); corner(track,2)
mhFill = new("Frame",{Size=UDim2.new(0,0,1,0),BackgroundColor3=T.Accent,BorderSizePixel=0,Parent=track}); corner(mhFill,2)
local fillG = gradient(mhFill,T.Accent,T.Accent2,0)
track.InputBegan:Connect(function(i)
if i.UserInputType == Enum.UserInputType.MouseButton1 and Music.sound and Music.sound.TimeLength > 0 then
local rel = math.clamp((i.Position.X - track.AbsolutePosition.X) / track.AbsoluteSize.X, 0, 1)
Music.sound.TimePosition = rel * Music.sound.TimeLength
end
end)
Fn.updateHud = function()
coverG.Color = ColorSequence.new(T.Accent, T.Accent2)
fillG.Color = ColorSequence.new(T.Accent, T.Accent2)
mhTitle.Text = Music.name
mhSub.Text = Music.artist ~= "" and Music.artist or (Music.id and ("ID "..Music.id)) or "Pick a song"
coverImg.Image = Music.id and ("rbxthumb://type=Asset&id="..Music.id.."&w=150&h=150") or ""
playIcon.Visible = not Music.playing
pauseIcon.Visible = Music.playing
if UI.nowLbl then UI.nowLbl.Text = Music.name end
if Fn.potionsRebuild then Fn.potionsRebuild() end
end
end
-- ══════════ POTIONS (active effects) ══════════
-- Pills glide smoothly between 4 layouts. Click it in edit mode (chat open).
do
local pw = overlays.potions
local ROMAN = {"I","II","III","IV","V","VI","VII","VIII","IX","X"}
local STYLES = {"Classic","Mirror","Swap","Inline"}
local RH, GP, W = 30, 5, 200
local head = new("Frame",{Size=UDim2.new(1,0,0,32),BackgroundColor3=T.Card,BackgroundTransparency=0.1,BorderSizePixel=0,Parent=pw})
corner(head, 11); regRef(head, "BackgroundColor3", "Card")
local ttl = new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,14,0,0),Size=UDim2.new(1,-50,1,0),Font=Enum.Font.GothamBold,Text="Potions",TextColor3=T.Text,TextSize=14,TextXAlignment=Enum.TextXAlignment.Left,Parent=head})
regRef(ttl, "TextColor3", "Text")
local flask = new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(1,-34,0,0),Size=UDim2.new(0,24,1,0),Font=Enum.Font.GothamBold,Text="⚗",TextColor3=T.Accent,TextSize=16,Parent=head})
regRef(flask, "TextColor3", "Accent")
local rows = new("Frame",{BackgroundTransparency=1,Position=UDim2.new(0,0,0,32+GP),Size=UDim2.new(1,0,1,-(32+GP)),Parent=pw})
local since, rowObjs, shownKey, shownLayout = {}, {}, "", 0
local function effects()
local out, alive = {}, {}
local now = os.clock()
local char = player.Character
local hum = char and char:FindFirstChildOfClass("Humanoid")
local function add(id, name, icon, timed)
alive[id] = true
local t = "inf"
if timed then
since[id] = since[id] or now
local e = math.floor(now - since[id])
t = string.format("%d:%02d", e // 60, e % 60)
end
out[#out+1] = {id=id, name=name, icon=icon, time=t}
end
if hum then
if hum.WalkSpeed > 17 then add("speed", "Speed "..ROMAN[math.clamp(math.floor(hum.WalkSpeed/16), 1, 10)], "⚡", false) end
local jp = hum.UseJumpPower and hum.JumpPower or hum.JumpHeight * 7
if jp > 55 then add("jump", "Jump Boost "..ROMAN[math.clamp(math.floor(jp/50), 1, 10)], "⬆", false) end
if hum.Health > 0 and hum.Health < hum.MaxHealth then add("regen", "Regeneration", "❤", false) end
end
if feat.fly then add("fly", "Flight", "🕊", true) end
if feat.noclip then add("noclip", "Phasing", "👻", true) end
if feat.infJump then add("infjump", "Leaping", "🦘", true) end
if feat.fullbright then add("fb", "Night Vision", "👁", true) end
if feat.glow then add("glow", "Glowing", "✨", true) end
if feat.neon then add("neon", "Neon Body", "💡", true) end
if feat.rainbowChar then add("rainbow", "Rainbow", "🌈", true) end
if feat.ghost then add("ghost", "Afterimage", "👤", true) end
if feat.playerTransparency and feat.playerTransparencyLevel >= 60 then add("invis", "Invisibility", "◌", true) end
if feat.freeCam then add("freecam", "Spectator", "🎥", true) end
for id in pairs(since) do if not alive[id] then since[id] = nil end end
return out
end
local function keyOf(list)
local k = {}
for _, e in ipairs(list) do k[#k+1] = e.id .. e.name end
return table.concat(k, "|")
end
local function mkPill(txt, bold, col, colKey)
local p = new("Frame",{BackgroundColor3=T.Card,BackgroundTransparency=1,BorderSizePixel=0,Size=UDim2.new(0,RH,0,RH),Parent=rows})
corner(p, 10); regRef(p, "BackgroundColor3", "Card")
local l = new("TextLabel",{BackgroundTransparency=1,Size=UDim2.fromScale(1,1),Font=bold and Enum.Font.GothamBold or Enum.Font.GothamMedium,Text=txt,TextColor3=col,TextTransparency=1,TextSize=13,TextTruncate=Enum.TextTruncate.AtEnd,Parent=p})
regRef(l, "TextColor3", colKey)
return p, l
end
local function createRow(e)
local ro = {fresh=true, e=e}
ro.inBg = new("Frame",{BackgroundColor3=T.Card,BackgroundTransparency=1,BorderSizePixel=0,Size=UDim2.new(0,W,0,RH),Parent=rows})
corner(ro.inBg, 10); regRef(ro.inBg, "BackgroundColor3", "Card")
ro.iconBg, ro.iconLbl = mkPill(e.icon, true, T.Text, "Text"); ro.iconLbl.TextSize = 15
ro.nameBg, ro.nameLbl = mkPill(e.name, false, T.Text, "Text")
ro.timeBg, ro.timeLbl = mkPill(e.time, true, T.Accent, "Accent")
return ro
end
local function place(ro, idx, st, animate)
local animP = animate and not ro.fresh
local animT = animate or ro.fresh
local function mvP(o, props) if animP then tween(o, 0.36, props, Enum.EasingStyle.Quint, Enum.EasingDirection.Out) else for k, v in pairs(props) do o[k] = v end end end
local function mvT(o, props) if animT then tween(o, 0.3, props) else for k, v in pairs(props) do o[k] = v end end end
local y = (idx-1)*(RH+GP)
local ix, iw, nx, nw, tx, tw
if st == 1 then ix,iw,nx,nw,tx,tw = 0,RH,RH+GP,112,RH+GP+112+GP,48
elseif st == 2 then tx,tw,ix,iw,nx,nw = 0,48,48+GP,RH,48+GP+RH+GP,112
elseif st == 3 then nx,nw,ix,iw,tx,tw = 0,112,112+GP,RH,112+GP+RH+GP,48
else ix,iw,nx,nw,tx,tw = 6,26,34,112,150,44 end
local inline = (st == 4)
local pillT = inline and 1 or 0.1
mvP(ro.inBg, {Position=UDim2.new(0,0,0,y)})
mvT(ro.inBg, {BackgroundTransparency = inline and 0.1 or 1})
mvP(ro.iconBg, {Position=UDim2.new(0,ix,0,y), Size=UDim2.new(0,iw,0,RH)}); mvT(ro.iconBg, {BackgroundTransparency=pillT})
mvP(ro.nameBg, {Position=UDim2.new(0,nx,0,y), Size=UDim2.new(0,nw,0,RH)}); mvT(ro.nameBg, {BackgroundTransparency=pillT})
mvP(ro.timeBg, {Position=UDim2.new(0,tx,0,y), Size=UDim2.new(0,tw,0,RH)}); mvT(ro.timeBg, {BackgroundTransparency=pillT})
ro.iconLbl.Text = ro.e.icon
ro.nameLbl.Text = inline and ("• " .. ro.e.name .. " •") or ro.e.name
ro.timeLbl.Text = ro.e.time
if ro.fresh then
ro.fresh = false
for _, l in ipairs({ro.iconLbl, ro.nameLbl, ro.timeLbl}) do tween(l, 0.3, {TextTransparency=0}) end
end
end
local function fadeOut(ro)
for _, o in ipairs({ro.inBg, ro.iconBg, ro.nameBg, ro.timeBg}) do tween(o, 0.2, {BackgroundTransparency=1}) end
for _, l in ipairs({ro.iconLbl, ro.nameLbl, ro.timeLbl}) do tween(l, 0.2, {TextTransparency=1}) end
task.delay(0.3, function() for _, o in ipairs({ro.inBg, ro.iconBg, ro.nameBg, ro.timeBg}) do o:Destroy() end end)
end
local function sync(animate)
local real = effects()
shownKey = keyOf(real)
local list = real
if #list == 0 then list = {{id="none", name="No effects", icon="∅", time="—"}} end
local st = feat.potionsLayout or 1
if st < 1 or st > #STYLES then st = 1 end
shownLayout = st
local keep = {}
for i, e in ipairs(list) do
keep[e.id] = true
local ro = rowObjs[e.id]
if not ro then ro = createRow(e); rowObjs[e.id] = ro end
ro.e = e
place(ro, i, st, animate)
end
for id, ro in pairs(rowObjs) do
if not keep[id] then fadeOut(ro); rowObjs[id] = nil end
end
local sz = UDim2.new(0, W, 0, 32 + GP + #list*(RH+GP) - GP)
if animate then tween(pw, 0.3, {Size=sz}, Enum.EasingStyle.Quint, Enum.EasingDirection.Out) else pw.Size = sz end
end
Fn.potionsRebuild = function() sync(false) end
Fn.potionsCycle = function()
feat.potionsLayout = ((feat.potionsLayout or 1) % #STYLES) + 1
sync(true)
notify("Potions", "Layout: " .. STYLES[feat.potionsLayout])
end
task.spawn(function()
while true do
task.wait(0.3)
if pw.Visible then
local list = effects()
if keyOf(list) ~= shownKey or (feat.potionsLayout or 1) ~= shownLayout then sync(true)
else for _, e in ipairs(list) do local ro = rowObjs[e.id]; if ro then ro.e = e; ro.timeLbl.Text = e.time end end end
end
end
end)
sync(false)
end
-- ══════════ WIDGET LAYOUTS (click any widget in edit mode to cycle) ══════════
-- Default -> Compact -> Large -> Bare (no background, text only). Everything morphs smoothly.
-- Keybinds (List / Pills) and Potions (4 pill layouts) have their own special layouts.
do
local LAYOUTS = {"Default", "Compact", "Large", "Bare"}
local SCALES = {1, 0.82, 1.22, 1}
local RADII = {RM, 6, 14, 12}
local LABELS = {statusBar="Status Bar", fps="FPS", coords="Coordinates", ping="Ping", keybinds="Keybinds", musicHud="Music HUD", speed="Speed", lyrics="Lyrics Bar", keystrokes="Keystrokes", mousestrokes="Mousestrokes"}
local txtOrig = setmetatable({}, {__mode = "k"})
for name in pairs(overlays) do if name ~= "potions" then feat["layout_" .. name] = 1 end end
Fn.LAYOUT_NAMES = LAYOUTS
Fn.applyLayout = function(name, animate)
local f = overlays[name]
if not f or name == "potions" then return end
if name == "keybinds" then if Fn.kbApply then Fn.kbApply(animate) end return end
local idx = feat["layout_" .. name] or 1
if idx < 1 or idx > #LAYOUTS then idx = 1 end
local function mv(o, props, dur)
if animate then TS:Create(o, TweenInfo.new(sdur(dur or 0.3), Enum.EasingStyle.Quint, Enum.EasingDirection.Out), props):Play()
else for k, v in pairs(props) do o[k] = v end end
end
local us = f:FindFirstChildOfClass("UIScale") or new("UIScale", {Name = "OwoLayoutScale", Parent = f})
mv(us, {Scale = SCALES[idx]})
local rad = RADII[idx]
local c = f:FindFirstChildOfClass("UICorner"); if c then mv(c, {CornerRadius = UDim.new(0, rad)}) end
for _, n in ipairs({"OwoGlassFrost", "OwoGlassGloss", "OwoGlassRim"}) do
local l = f:FindFirstChild(n)
local lc = l and l:FindFirstChildOfClass("UICorner")
if lc then lc.CornerRadius = UDim.new(0, rad) end
end
local bare = (idx == 4)
f:SetAttribute("LBare", bare)
local ln = f:FindFirstChild("OwoLine"); if ln then mv(ln, {Transparency = bare and 1 or 0.6}, 0.25) end
mv(f, {BackgroundTransparency = bare and 1 or TR.Overlay}, 0.25)
for _, d in ipairs(f:GetDescendants()) do
if d:IsA("TextLabel") or d:IsA("TextButton") then
if bare then
if txtOrig[d] == nil then txtOrig[d] = {d.TextStrokeTransparency, d.TextStrokeColor3} end
d.TextStrokeColor3 = Color3.new(0, 0, 0)
mv(d, {TextStrokeTransparency = 0.45}, 0.25)
elseif txtOrig[d] then
d.TextStrokeColor3 = txtOrig[d][2]
mv(d, {TextStrokeTransparency = txtOrig[d][1]}, 0.25)
txtOrig[d] = nil
end
end
end
if Glass.refreshAll then Glass.refreshAll() end
end
Fn.applyAllLayouts = function()
for name in pairs(overlays) do
if name ~= "potions" then Fn.applyLayout(name, false) end
end
if Fn.potionsRebuild then Fn.potionsRebuild() end
end
Fn.cycleLayout = function(name)
if name == "potions" then if Fn.potionsCycle then Fn.potionsCycle() end return end
if name == "keybinds" then if Fn.kbCycle then Fn.kbCycle() end return end
if not overlays[name] then return end
feat["layout_" .. name] = ((feat["layout_" .. name] or 1) % #LAYOUTS) + 1
Fn.applyLayout(name, true)
notify(LABELS[name] or name, "Layout: " .. LAYOUTS[feat["layout_" .. name]])
end
Fn.resetLayout = function(name)
if name == "potions" then feat.potionsLayout = 1; if Fn.potionsRebuild then Fn.potionsRebuild() end return end
feat["layout_" .. name] = 1; Fn.applyLayout(name, true)
end
end
local statusEqClock = 0
RS.RenderStepped:Connect(function(dt)
statusEqClock += dt
if Fn.statusBarEqBars then
local playing = Music.sound and Music.sound.IsPlaying
for i, eb in ipairs(Fn.statusBarEqBars) do
if eb and eb.Parent then
local wave = playing and (0.25 + 0.75 * math.abs(math.sin(statusEqClock * (7.5 + i * 1.8) + i * 1.4))) or 0.22
local h = 4 + wave * 10
eb.Size = UDim2.new(0,2,0,h)
eb.Position = UDim2.new(0,14+(i-1)*5,0.5,-h*0.5)
eb.BackgroundTransparency = playing and 0.02 or 0.30
end
end
end
local hrp = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
if overlays.coords.Visible and hrp then
local p = hrp.Position; local dh = colorToHex(T.Dim)
coordsLbl.Text = string.format('x %d y %d z %d', dh, math.floor(p.X+0.5), dh, math.floor(p.Y+0.5), dh, math.floor(p.Z+0.5))
end
if overlays.speed.Visible then
local v = hrp and hrp.AssemblyLinearVelocity or Vector3.zero
UI.spd = slerp(UI.spd or 0, Vector3.new(v.X,0,v.Z).Magnitude, dt, 10)
spVal.Text = (string.format("%.2f", UI.spd):gsub("%.", ",")) .. " bps"
spBar.Size = UDim2.new(math.clamp(UI.spd/60, 0, 1), 0, 1, 0)
end
if overlays.musicHud.Visible then
local len = Music.sound and Music.sound.TimeLength or 0
mhFill.Size = UDim2.new(len > 0 and math.clamp(Music.sound.TimePosition/len, 0, 1) or 0, 0, 1, 0)
end
if overlays.statusBar.Visible and Fn.setSbMode and Fn.sbLyricLbl then
-- Keep the currently selected line visible while paused too.
local active = feat.lyricsInStatusBar and #Lyrics.lines > 0
if active then
Fn.setSbMode("lyrics", true)
local pos = (Music.sound and Music.sound.TimePosition or 0) + Lyrics.offset
local idx = 0
for i = 1, #Lyrics.lines do if Lyrics.lines[i].t <= pos then idx = i else break end end
if idx == 0 then idx = 1 end
if idx > 0 then
local L = Lyrics.lines[idx]
local t1 = Lyrics.lines[idx+1] and Lyrics.lines[idx+1].t or (L.t+4)
local dur = math.clamp(t1-L.t, 0.5, 6)*0.85
local f = math.clamp((pos-L.t)/dur, 0, 1)
local widx = #L.words
for i = 1, #L.words do if f <= L.cum[i] then widx = i; break end end
local prevProgress = (widx > 1 and Lyrics.lines[idx].cum[widx-1]) or 0
local thisProgress = Lyrics.lines[idx].cum[widx] or 1
local wordProgress = thisProgress > prevProgress and math.clamp((f-prevProgress)/(thisProgress-prevProgress),0,1) or 0
local key = idx*1000+widx
Lyrics.sbKey = key
if Fn.showSmoothStatusLyric then Fn.showSmoothStatusLyric(L, widx, idx, wordProgress, dt) end
else
Fn.sbLyricLbl.Text = '♪'
end
else
Fn.setSbMode("normal", true)
end
end
if overlays.lyrics.Visible and lyLbl then
local lines = Lyrics.lines
if #lines == 0 then
if Lyrics.barKey ~= "none" then Lyrics.barKey = "none"; lyLbl.Text = '♪ no lyrics loaded' end
else
local pos = (Music.sound and Music.sound.TimePosition or 0) + Lyrics.offset
local idx = 0
for i = 1, #lines do if lines[i].t <= pos then idx = i else break end end
if idx == 0 then idx = 1 end
if idx == 0 then
if Lyrics.barKey ~= "pre" then Lyrics.barKey = "pre"; lyLbl.Text = '♪' end
else
local L = lines[idx]
local t1 = lines[idx+1] and lines[idx+1].t or (L.t+4)
local dur = math.clamp(t1-L.t, 0.5, 6)*0.85
local f = math.clamp((pos-L.t)/dur, 0, 1)
local widx = #L.words
for i = 1, #L.words do if f <= L.cum[i] then widx = i; break end end
local key = idx*1000+widx
if Lyrics.barKey ~= key then
Lyrics.barKey = key
local dimc = "#8C93A6"
local parts = {}
for i, w in ipairs(L.words) do
w = w:gsub("&","&"):gsub("<","<"):gsub(">",">")
if i < widx then parts[#parts+1] = ''..w..''
elseif i == widx then parts[#parts+1] = ''..w..''
else parts[#parts+1] = ''..w..'' end
end
lyLbl.Text = table.concat(parts, " ")
end
end
end
end
end)
end
-- ══════════════════════════════════════════════════════════════
-- 3D LYRICS
-- ══════════════════════════════════════════════════════════════
do
local A = {}; Lyrics.A = A
local FONT = Font.new("rbxasset://fonts/families/GothamSSm.json", Enum.FontWeight.Heavy, Enum.FontStyle.Italic)
local function esc(c) return (c:gsub("&","&"):gsub("<","<"):gsub(">",">")) end
local function build()
A.part = new("Part", {Name="OwoLyrics3D", Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Transparency=1, Size=Vector3.new(16,3,0.05), Parent=workspace.CurrentCamera})
A.sg = new("SurfaceGui", {Face=Enum.NormalId.Front, Adornee=A.part, SizingMode=Enum.SurfaceGuiSizingMode.PixelsPerStud, PixelsPerStud=60, LightInfluence=0, AlwaysOnTop=false, Enabled=false, Parent=A.part})
A.holder = new("Frame", {BackgroundTransparency=1, Size=UDim2.fromScale(1,1), Parent=A.sg})
A.scale = new("UIScale", {Scale=1, Parent=A.holder})
A.shadow = new("TextLabel", {BackgroundTransparency=1, Size=UDim2.fromScale(1,1), Position=UDim2.fromOffset(4,6), FontFace=FONT, TextScaled=true, RichText=true, Text="", TextColor3=Color3.new(0,0,0), TextTransparency=0.55, ZIndex=1, Parent=A.holder})
A.lbl = new("TextLabel", {BackgroundTransparency=1, Size=UDim2.fromScale(1,1), FontFace=FONT, TextScaled=true, RichText=true, Text="", TextColor3=Color3.new(1,1,1), ZIndex=2, Parent=A.holder})
A.glow = new("UIStroke", {Color=T.Accent, Thickness=3, Transparency=0.6, Parent=A.lbl})
new("UITextSizeConstraint", {MaxTextSize=130, Parent=A.lbl}); new("UITextSizeConstraint", {MaxTextSize=130, Parent=A.shadow})
end
local function hide() if A.sg then A.sg.Enabled = false end; A.idx, A.pos = nil, nil end
local function pickSpot(cam, hrp)
local vp = cam.ViewportSize; local ps = cam:WorldToViewportPoint(hrp.Position)
local pr = RaycastParams.new(); pr.FilterType = Enum.RaycastFilterType.Exclude; pr.FilterDescendantsInstances = {player.Character, A.part}
for _ = 1, 16 do
local sx = vp.X*(0.28+math.random()*0.44); local sy = vp.Y*(0.14+math.random()*0.36)
if ps.Z <= 0 or (Vector2.new(sx,sy)-Vector2.new(ps.X,ps.Y)).Magnitude > vp.Y*0.25 then
local ray = cam:ViewportPointToRay(sx,sy); local dist = 16+math.random()*10
local hit = workspace:Raycast(ray.Origin, ray.Direction*dist, pr)
if hit then dist = (hit.Position-ray.Origin).Magnitude-2 end
if dist >= 9 then return ray.Origin + ray.Direction*dist end
end
end
local cf = cam.CFrame
return cf.Position + cf.LookVector*18 + cf.UpVector*5 + cf.RightVector*(math.random()<0.5 and -6 or 6)
end
local function respawn(cam, hrp)
A.pos = pickSpot(cam, hrp)
A.tilt = CFrame.Angles(0, math.rad((math.random()<0.5 and -1 or 1)*(8+math.random()*14)), math.rad((math.random()-0.5)*8))
A.lost, A.bob = 0, math.random()*6
A.scale.Scale = 0.6
TS:Create(A.scale, TweenInfo.new(sdur(0.4), Enum.EasingStyle.Back, Enum.EasingDirection.Out), {Scale=1}):Play()
end
RS.RenderStepped:Connect(function(dt)
if not feat.lyrics3d then if A.sg and A.sg.Enabled then hide() end return end
local char = player.Character; local hrp = char and char:FindFirstChild("HumanoidRootPart")
if not hrp or #Lyrics.lines == 0 or not (Music.sound and Music.sound.IsPlaying) then hide() return end
local pos = Music.sound.TimePosition + Lyrics.offset
local idx = 0
for i = 1, #Lyrics.lines do if Lyrics.lines[i].t <= pos then idx = i else break end end
if idx == 0 then hide() return end
if not A.part or not A.part.Parent then build() end
local L = Lyrics.lines[idx]
local t1 = Lyrics.lines[idx+1] and Lyrics.lines[idx+1].t or (L.t+4)
if A.idx ~= idx then
A.idx, A.key = idx, nil; A.chars = {}
local str = string.upper(table.concat(L.words," "))
if not pcall(function() for _, c in utf8.codes(str) do A.chars[#A.chars+1] = utf8.char(c) end end) then
A.chars = {}; for i = 1, #str do A.chars[i] = str:sub(i,i) end
end
respawn(workspace.CurrentCamera, hrp)
end
local n = #A.chars
local reveal = math.clamp((pos-L.t)/math.max(math.min(t1-L.t,6)*0.55, 0.2), 0, 1)
local nf = reveal*n; local shown = math.floor(nf); local frac = nf-shown
local key = shown*8+math.floor(frac*8)
if A.key ~= key then
A.key = key
local done = {}
for i = 1, shown do done[i] = esc(A.chars[i]) end
local solid = table.concat(done)
local nxt = A.chars[shown+1]
A.lbl.Text = nxt and (solid..string.format('%s', 1-frac, esc(nxt))) or solid
A.shadow.Text = solid
end
local fade = 1 - math.clamp((t1-pos)/0.3, 0, 1)
A.lbl.TextTransparency = fade
A.shadow.TextTransparency = 0.55+0.45*fade
A.glow.Transparency = 0.6+0.4*fade; A.glow.Color = T.Accent
local cam = workspace.CurrentCamera; local camPos = cam.CFrame.Position
local sp, onScreen = cam:WorldToViewportPoint(A.pos)
local ps = cam:WorldToViewportPoint(hrp.Position)
local bad = not onScreen or sp.Z < 5 or (A.pos-camPos).Magnitude > 50 or (ps.Z > 0 and (Vector2.new(sp.X,sp.Y)-Vector2.new(ps.X,ps.Y)).Magnitude < cam.ViewportSize.Y*0.15)
A.chk = (A.chk or 0) + dt
if not bad and A.chk > 0.25 then
A.chk = 0
local pr = RaycastParams.new(); pr.FilterType = Enum.RaycastFilterType.Exclude; pr.FilterDescendantsInstances = {player.Character, A.part}
if workspace:Raycast(camPos, A.pos-camPos, pr) then bad = true end
end
A.lost = bad and (A.lost+dt) or 0
if A.lost > 0.4 then respawn(cam, hrp) end
local s = Lyrics.airScale
A.part.Size = Vector3.new(10*s, 1.9*s, 0.05)
local p = A.pos + Vector3.new(0, math.sin(os.clock()*1.4+A.bob)*0.25, 0)
A.part.CFrame = CFrame.lookAt(p, camPos) * A.tilt
A.sg.Enabled = true
end)
end
-- ══════════════════════════════════════════════════════════════
-- MUSIC ENGINE
-- ══════════════════════════════════════════════════════════════
do
Music.sound = new("Sound",{Name="OwoMusic",Volume=Music.volume,Looped=true,Parent=SoundService})
local function mkLine(t, text)
local words, cum, total = {}, {}, 0
for w in text:gmatch("%S+") do words[#words+1] = w; total = total + #w + 1 end
local acc = 0
for i, w in ipairs(words) do acc = acc + #w + 1; cum[i] = acc/math.max(total,1) end
return {t=t, text=text, words=words, cum=cum}
end
-- Parses standard LRC ([mm:ss.xx]), centisecond LRC ([mm:ss:xx]),
-- angle-bracket timestamps, and untimed plain text pasted by the user.
Lyrics.parse = function(raw)
raw = tostring(raw or "")
raw = raw:gsub("^\239\187\191", ""):gsub("\r\n", "\n"):gsub("\r", "\n")
local syncedLines, plainLines = {}, {}
local function readStamp(text)
local mm, ss, frac, nextPos
mm, ss, frac, nextPos = text:match("^%s*%[(%d+):(%d+)%.(%d+)%]()")
if not mm then
mm, ss, frac, nextPos = text:match("^%s*%[(%d+):(%d+):(%d+)%]()")
end
if not mm then
mm, ss, nextPos = text:match("^%s*%[(%d+):(%d+)%]()")
frac = nil
end
if not mm then
mm, ss, frac, nextPos = text:match("^%s*<(%d+):(%d+)%.(%d+)%>()")
end
if not mm then
mm, ss, frac, nextPos = text:match("^%s*<(%d+):(%d+):(%d+)%>()")
end
if not mm then
mm, ss, nextPos = text:match("^%s*<(%d+):(%d+)%>()")
frac = nil
end
if not mm then return nil end
local minutes = tonumber(mm) or 0
local seconds = tonumber(ss) or 0
if seconds >= 60 then return nil end
local fraction = 0
if frac and frac ~= "" then
fraction = (tonumber(frac) or 0) / (10 ^ #frac)
end
return minutes * 60 + seconds + fraction, nextPos
end
for rawLine in raw:gmatch("[^\n]+") do
local rest = rawLine
local stamps = {}
while true do
local stamp, nextPos = readStamp(rest)
if not stamp or not nextPos then break end
stamps[#stamps + 1] = stamp
rest = rest:sub(nextPos)
end
rest = rest:gsub("^%s+", ""):gsub("%s+$", "")
-- Ignore common LRC metadata headers such as [ar:], [ti:], [al:], [by:].
local isMetadata = rest:match("^%[%a[%w_]*:") ~= nil
if #stamps > 0 then
if rest ~= "" then
for _, stamp in ipairs(stamps) do
syncedLines[#syncedLines + 1] = mkLine(stamp, rest)
end
end
elseif rest ~= "" and not isMetadata then
plainLines[#plainLines + 1] = rest
end
end
if #syncedLines > 0 then
table.sort(syncedLines, function(a, b) return a.t < b.t end)
return syncedLines
end
if #plainLines == 0 then return {} end
local duration = 0
if Music.sound then
pcall(function() duration = tonumber(Music.sound.TimeLength) or 0 end)
end
-- If Roblox has not reported the audio duration yet, use 3 seconds per line.
local total = duration > 1 and duration or math.max(#plainLines * 3, 1)
local parsed = {}
for i, lineText in ipairs(plainLines) do
parsed[#parsed + 1] = mkLine((i - 1) * total / math.max(#plainLines, 1), lineText)
end
return parsed
end
Lyrics.fetch = function(query, quiet)
if not req then if not quiet then notify("Lyrics","No HTTP",false) end return end
local q = tostring(query or ""):gsub("%b()"," "):gsub("%b[]"," "):gsub("_"," "):gsub("%s+"," "):gsub("^%s+",""):gsub("%s+$","")
if q == "" then return end
task.spawn(function()
if not quiet then notify("Lyrics","Searching: "..q) end
local ok, res = pcall(req,{Url="https://lrclib.net/api/search?q="..HttpService:UrlEncode(q),Method="GET"})
if not ok or type(res) ~= "table" or not res.Body then notify("Lyrics","Request failed",false); return end
local ok2, data = pcall(function() return HttpService:JSONDecode(res.Body) end)
if not ok2 or type(data) ~= "table" or #data == 0 then notify("Lyrics","No lyrics found",false); return end
local pick
for _, it in ipairs(data) do if type(it.syncedLyrics) == "string" and #it.syncedLyrics > 0 then pick = it.syncedLyrics; break end end
if not pick then for _, it in ipairs(data) do if type(it.plainLyrics) == "string" and #it.plainLyrics > 0 then pick = it.plainLyrics; break end end end
if not pick then notify("Lyrics","No lyrics found",false); return end
local lines = Lyrics.parse(pick)
if #lines == 0 then notify("Lyrics","Could not read",false); return end
Lyrics.lines = lines; Lyrics.key = nil; Lyrics.sbKey = nil; Lyrics.barKey = nil
notify("Lyrics","Loaded ".. #lines .." lines")
end)
end
Lyrics.loadText = function(text)
local lines = Lyrics.parse(text)
if #lines == 0 then notify("Lyrics","Nothing to load",false); return end
Lyrics.lines = lines; Lyrics.key = nil; Lyrics.sbKey = nil; Lyrics.barKey = nil
notify("Lyrics","Loaded ".. #lines .." lines")
end
Lyrics.clear = function() Lyrics.lines = {}; Lyrics.key = nil; Lyrics.sbKey = nil; Lyrics.barKey = nil end
Lib.save = function()
if not FILE_OK then return end
local ok, e = pcall(function() return HttpService:JSONEncode(Lib.list) end)
if ok then pcall(writefile, Lib.file, e) end
end
Lib.load = function()
if not FILE_OK then return end
local function tryLoad(p)
local ok, ex = pcall(isfile, p); if not (ok and ex) then return nil end
local ok2, raw = pcall(readfile, p); if not ok2 then return nil end
local ok3, d = pcall(function() return HttpService:JSONDecode(raw) end)
if ok3 and type(d) == "table" then return d end
return nil
end
local d = tryLoad(Lib.file) or tryLoad("shyclient_music.json")
if d then Lib.list = d end
end
Lib.add = function(id, name, artist)
local clean = tostring(id or ""):gsub("rbxassetid://",""):gsub("%D","")
if clean == "" then notify("Library","Enter a valid audio ID",false); return end
name = tostring(name or ""):gsub("^%s+",""):gsub("%s+$","")
if name == "" then name = "Song "..(#Lib.list+1) end
for _, e in ipairs(Lib.list) do
if e.id == clean then
e.name = name; if artist and artist ~= "" then e.artist = artist end
Lib.save(); if Lib.refresh then Lib.refresh() end
notify("Library","Updated: "..name); return
end
end
Lib.list[#Lib.list+1] = {id=clean, name=name, artist=artist or ""}
Lib.save(); if Lib.refresh then Lib.refresh() end
notify("Library","Saved: "..name)
end
Lib.remove = function(i)
local e = Lib.list[i]; if not e then return end
table.remove(Lib.list, i)
Lib.save(); if Lib.refresh then Lib.refresh() end
notify("Library","Deleted: "..e.name,false)
end
Lib.load()
Music.play = function(id, name, artist)
local clean = tostring(id or ""):gsub("rbxassetid://",""):gsub("%D","")
if clean == "" then notify("Music","Enter a valid audio ID",false); return end
Music.id = clean
Music.name = (name and name ~= "") and name or ("Audio "..clean)
Music.artist = artist or ""
Music.sound.SoundId = "rbxassetid://"..clean
Music.sound.TimePosition = 0
Music.sound:Play(); Music.playing = true
Lyrics.clear()
notify("Music","Playing: "..Music.name)
if Fn.updateHud then Fn.updateHud() end
if Lyrics.auto then
if Music.name:match("^Audio%s+%d+$") then
notify("Lyrics", "Add the song title and artist in Music to find matching lyrics", false)
else
Lyrics.fetch((Music.artist ~= "" and (Music.artist.." ") or "")..Music.name, true)
end
end
task.delay(4, function() if Music.id == clean and Music.sound.TimeLength == 0 then notify("Music","Could not load (private ID?)",false) end end)
end
Music.toggle = function()
if not Music.id then notify("Music","Nothing loaded",false); return end
if Music.playing then Music.sound:Pause(); Music.playing = false
else Music.sound:Resume(); Music.playing = true end
if Fn.updateHud then Fn.updateHud() end
end
Music.stop = function() Music.sound:Stop(); Music.playing = false; if Fn.updateHud then Fn.updateHud() end end
local function step(dir)
if #Lib.list == 0 then notify("Music","Save a song first",false); return end
local cur = 0
for i, e in ipairs(Lib.list) do if e.id == Music.id then cur = i; break end end
local e = Lib.list[((cur-1+dir) % #Lib.list)+1]
Music.play(e.id, e.name, e.artist)
end
Music.next = function() step(1) end
Music.prev = function() step(-1) end
Music.sound.Ended:Connect(function() if not Music.looped then step(1) end end)
end
-- ══════════════════════════════════════════════════════════════
-- FRIENDS + CHAT
-- ══════════════════════════════════════════════════════════════
do
Friends.save = function()
if not FILE_OK then return end
local favList = {}
for id, v in pairs(Friends.favourites) do if v then favList[#favList+1] = id end end
local ok, s = pcall(function() return HttpService:JSONEncode({favourites=favList, chats=Friends.chats}) end)
if ok then pcall(writefile, Friends.file, s) end
end
Friends.load = function()
if not FILE_OK then return end
local function tryLoad(p)
local ok, ex = pcall(isfile,p); if not (ok and ex) then return nil end
local ok2, raw = pcall(readfile,p); if not ok2 then return nil end
local ok3, d = pcall(function() return HttpService:JSONDecode(raw) end)
if ok3 and type(d) == "table" then return d end
return nil
end
local d = tryLoad(Friends.file) or tryLoad("shyclient_friends.json")
if d then
if type(d.favourites) == "table" then for _, id in ipairs(d.favourites) do Friends.favourites[id] = true end end
if type(d.chats) == "table" then Friends.chats = d.chats end
end
end
Friends.load()
Friends.isFavourite = function(id) return Friends.favourites[id] == true end
Friends.toggleFavourite = function(id)
if Friends.favourites[id] then Friends.favourites[id] = nil else Friends.favourites[id] = true end
Friends.save()
if Friends.refreshList then Friends.refreshList() end
end
Friends.refresh = function(cb)
task.spawn(function()
local out = {}
local ok, pages = pcall(function() return Players:GetFriendsAsync(player.UserId) end)
if ok and pages then
while true do
for _, f in ipairs(pages:GetCurrentPage()) do
out[#out+1] = {userId=f.Id, username=f.Username, displayName=f.DisplayName, isOnline=f.IsOnline, isFavourite=Friends.isFavourite(f.Id)}
end
if pages.IsFinished then break end
if not pcall(function() pages:AdvanceToNextPageAsync() end) then break end
end
end
table.sort(out, function(a,b)
if a.isFavourite ~= b.isFavourite then return a.isFavourite end
if a.isOnline ~= b.isOnline then return a.isOnline end
return (a.displayName or a.username):lower() < (b.displayName or b.username):lower()
end)
Friends.list = out
if cb then cb() end
if Friends.refreshList then Friends.refreshList() end
end)
end
Friends.getChat = function(id) Friends.chats[id] = Friends.chats[id] or {}; return Friends.chats[id] end
Friends.addMessage = function(id, from, text, ts)
local chat = Friends.getChat(id); chat[#chat+1] = {from=from, text=text, time=ts or os.time()}
Friends.save()
if Friends.activeChat == id and Friends.renderChat then Friends.renderChat() end
end
Friends.sendToPeer = function(id, text)
Friends.addMessage(id, "me", text)
if Friends.RELAY_URL == "" or not req then return end
task.spawn(function()
pcall(req,{Url=Friends.RELAY_URL.."/send",Method="POST",Headers={["Content-Type"]="application/json"},Body=HttpService:JSONEncode({from=player.UserId, fromName=player.Name, to=id, text=text, ts=os.time()})})
end)
end
local chatGui = new("ScreenGui",{Name="OwoFriendChat",ResetOnSpawn=false,IgnoreGuiInset=true,ZIndexBehavior=Enum.ZIndexBehavior.Sibling,Parent=pg,DisplayOrder=5})
local win = new("Frame",{Name="ChatWin",Size=UDim2.new(0,380,0,420),Position=UDim2.new(1,-400,0.5,-210),BackgroundColor3=T.Panel,BackgroundTransparency=TR.Window,BorderSizePixel=0,Visible=false,Active=true,Parent=chatGui})
corner(win,RB); local wst = stroke(win,1,0.5,T.Line,true); regRef(wst,"Color","Line"); regRef(win,"BackgroundColor3","Panel"); addSheen(win)
Glass.G.decorate(win)
Friends.panel = win
local header = new("Frame",{Size=UDim2.new(1,0,0,44),BackgroundTransparency=1,Parent=win})
local title = new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,16,0,0),Size=UDim2.new(1,-80,1,0),Font=Enum.Font.GothamBold,Text="Chat",TextColor3=T.Text,TextSize=14,TextXAlignment=Enum.TextXAlignment.Left,Parent=header}); regRef(title,"TextColor3","Text")
local closeBtn = new("TextButton",{Size=UDim2.new(0,26,0,26),Position=UDim2.new(1,-34,0.5,-13),BackgroundColor3=T.Card,BackgroundTransparency=0.2,Text="×",Font=Enum.Font.GothamBold,TextColor3=T.Text,TextSize=16,BorderSizePixel=0,AutoButtonColor=false,Parent=header}); corner(closeBtn,7); stroke(closeBtn,1,0.55,T.Line)
drag(win, header)
local scroller = new("ScrollingFrame",{Position=UDim2.new(0,0,0,44),Size=UDim2.new(1,0,1,-104),BackgroundTransparency=1,BorderSizePixel=0,ScrollBarThickness=3,ScrollBarImageColor3=T.Muted,CanvasSize=UDim2.new(0,0,0,0),AutomaticCanvasSize=Enum.AutomaticSize.Y,Parent=win})
new("UIListLayout",{Padding=UDim.new(0,6),SortOrder=Enum.SortOrder.LayoutOrder,Parent=scroller})
new("UIPadding",{PaddingTop=UDim.new(0,6),PaddingBottom=UDim.new(0,6),PaddingLeft=UDim.new(0,10),PaddingRight=UDim.new(0,10),Parent=scroller})
local input = new("TextBox",{Position=UDim2.new(0,10,1,-52),Size=UDim2.new(1,-74,0,42),BackgroundColor3=T.Bg,BackgroundTransparency=0.3,Font=Enum.Font.GothamMedium,Text="",PlaceholderText="Message...",TextColor3=T.Text,PlaceholderColor3=T.Muted,TextSize=12,BorderSizePixel=0,ClearTextOnFocus=false,TextXAlignment=Enum.TextXAlignment.Left,Parent=win}); corner(input,10); stroke(input,1,0.55,T.Line)
regRef(input,"BackgroundColor3","Bg"); regRef(input,"TextColor3","Text")
local sendBtn = new("TextButton",{Position=UDim2.new(1,-58,1,-52),Size=UDim2.new(0,48,0,42),BackgroundColor3=Color3.new(1,1,1),Text="Send",Font=Enum.Font.GothamBold,TextColor3=ON_ACCENT,TextSize=11,BorderSizePixel=0,AutoButtonColor=false,Parent=win}); corner(sendBtn,10); gradient(sendBtn,T.Accent,T.Accent2,0)
Friends.renderChat = function()
for _, c in ipairs(scroller:GetChildren()) do if c:IsA("Frame") or c:IsA("TextLabel") then c:Destroy() end end
local uid = Friends.activeChat; if not uid then return end
local entry; for _, f in ipairs(Friends.list) do if f.userId == uid then entry = f; break end end
title.Text = entry and (entry.displayName.." @"..entry.username) or ("User "..tostring(uid))
for i, m in ipairs(Friends.getChat(uid)) do
local mine = m.from == "me"
local row = new("Frame",{Size=UDim2.new(1,0,0,40),BackgroundTransparency=1,LayoutOrder=i,Parent=scroller})
local bubble = new("Frame",{Size=UDim2.new(0.72,0,1,0),Position=mine and UDim2.new(0.28,0,0,0) or UDim2.new(0,0,0,0),BackgroundColor3=mine and T.Accent or T.Card,BackgroundTransparency=0.15,BorderSizePixel=0,Parent=row}); corner(bubble,10); stroke(bubble,1,0.55,T.Line)
new("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(1,-16,1,-14),Position=UDim2.new(0,8,0,6),Font=Enum.Font.Gotham,Text=tostring(m.text),TextColor3=mine and ON_ACCENT or T.Text,TextSize=12,TextWrapped=true,TextXAlignment=Enum.TextXAlignment.Left,TextYAlignment=Enum.TextYAlignment.Top,Parent=bubble})
new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,8,1,-12),Size=UDim2.new(1,-16,0,12),Font=Enum.Font.Gotham,Text=os.date("%H:%M", m.time),TextColor3=T.Muted,TextSize=9,TextXAlignment=Enum.TextXAlignment.Right,Parent=bubble})
end
task.defer(function() scroller.CanvasPosition = Vector2.new(0, math.max(0, scroller.AbsoluteCanvasSize.Y - scroller.AbsoluteSize.Y)) end)
end
Friends.openChat = function(id) Friends.activeChat = id; win.Visible = true; Friends.renderChat(); input:CaptureFocus() end
closeBtn.MouseButton1Click:Connect(function() win.Visible = false end)
local function doSend()
local t = input.Text:gsub("^%s+",""):gsub("%s+$","")
if t == "" or not Friends.activeChat then return end
input.Text = ""; Friends.sendToPeer(Friends.activeChat, t)
end
sendBtn.MouseButton1Click:Connect(doSend)
input.FocusLost:Connect(function(enter) if enter then doSend() end end)
end
-- ══════════════════════════════════════════════════════════════
-- WORLD FX (smoothed)
-- ══════════════════════════════════════════════════════════════
do
local fx = new("Folder", {Name="OwoFX", Parent=workspace})
local function emitterPart(name, size)
return new("Part", {Name=name,Anchored=true,CanCollide=false,CanQuery=false,CanTouch=false,CastShadow=false,Transparency=1,Size=size,Parent=fx})
end
local sky = emitterPart("Sky", Vector3.new(110, 1, 110))
local vol = emitterPart("Vol", Vector3.new(80, 30, 80))
local rainE, snowE, flyE, atmo
local tintCC = new("ColorCorrectionEffect", {Name="OwoTint", Enabled=false, Parent=Lighting})
local stormCC = new("ColorCorrectionEffect", {Name="OwoStormTone", Enabled=false, Brightness=-0.08, Contrast=0.12, Saturation=-0.18, TintColor=Color3.fromRGB(190,205,225), Parent=Lighting})
local stormClouds
local function applyThunderWeather()
if feat.thunder then
local terrain = workspace:FindFirstChildOfClass("Terrain")
if terrain and not stormClouds then
stormClouds = new("Clouds", {Name="OwoThunderClouds", Cover=0.82, Density=0.78, Color=Color3.fromRGB(105,115,135), Parent=terrain})
end
stormCC.Enabled = true
else
stormCC.Enabled = false
if stormClouds then stormClouds:Destroy(); stormClouds = nil end
end
end
Wx.thunder = applyThunderWeather
local bloomE = new("BloomEffect", {Name="OwoBloom", Enabled=false, Intensity=0, Size=28, Threshold=0.85, Parent=Lighting})
local cubes, amb = {}, {}
local vig = {}
do
local function edge(size, pos, rot)
local f = new("Frame", {Size=size, Position=pos, BackgroundColor3=Color3.fromRGB(0,10,10), BorderSizePixel=0, Visible=false, ZIndex=1, Parent=UI.ovGui})
local g = Instance.new("UIGradient")
g.Rotation = rot
g.Transparency = NumberSequence.new({NumberSequenceKeypoint.new(0, 0.2), NumberSequenceKeypoint.new(1, 1)})
g.Parent = f
vig[#vig+1] = f
end
edge(UDim2.new(1,0,0.3,0), UDim2.new(0,0,0,0), 90)
edge(UDim2.new(1,0,0.3,0), UDim2.new(0,0,0.7,0), 270)
edge(UDim2.new(0.22,0,1,0), UDim2.new(0,0,0,0), 0)
edge(UDim2.new(0.22,0,1,0), UDim2.new(0.78,0,0,0), 180)
end
Wx.rain = function()
if rainE then rainE:Destroy(); rainE = nil end
if not feat.rain then return end
local style = feat.visualStyles.rain or "Downpour"
local rate, speed, spread, slant = 900, 105, 2, -8
if style == "Drizzle" then rate, speed, spread, slant = 350, 65, 8, -2
elseif style == "Slanted Storm" then rate, speed, spread, slant = 1100, 125, 12, -32
elseif style == "Meteoric" then rate, speed, spread, slant = 500, 145, 3, -18 end
rainE = new("ParticleEmitter", {Rate=rate, Lifetime=NumberRange.new(0.55, 0.65), Speed=NumberRange.new(speed*0.9, speed*1.05), EmissionDirection=Enum.NormalId.Bottom, SpreadAngle=Vector2.new(spread, spread), Orientation=Enum.ParticleOrientation.VelocityParallel, Size=NumberSequence.new(style == "Drizzle" and 0.22 or 0.5), Squash=NumberSequence.new(style == "Meteoric" and -1 or -3), Transparency=NumberSequence.new(0.45), Color=ColorSequence.new(visualColor("rain"):Lerp(Color3.new(1,1,1), 0.3)), LightEmission=style == "Meteoric" and 0.9 or 0.25, Acceleration=Vector3.new(slant, 0, 0), Parent=sky})
end
Wx.snow = function()
if snowE then snowE:Destroy(); snowE = nil end
if not feat.snow then return end
local style = feat.visualStyles.snow or "Flurries"
local rate, speed, spread, size, drift = 350, 6.5, 25, 0.35, 3
if style == "Blizzard" then rate, speed, spread, size, drift = 800, 14, 75, 0.24, 18
elseif style == "Soft Drift" then rate, speed, spread, size, drift = 180, 2.5, 45, 0.48, 1
elseif style == "Sparkling" then rate, speed, spread, size, drift = 300, 4, 30, 0.55, 2 end
snowE = new("ParticleEmitter", {Rate=rate, Lifetime=NumberRange.new(7, 9), Speed=NumberRange.new(speed*0.75, speed*1.2), EmissionDirection=Enum.NormalId.Bottom, SpreadAngle=Vector2.new(spread, spread), Size=NumberSequence.new(size), Transparency=NumberSequence.new(0.15), Color=ColorSequence.new(visualColor("snow"):Lerp(Color3.new(1,1,1), 0.35)), LightEmission=style == "Sparkling" and 1 or 0.4, Acceleration=Vector3.new(drift, 0, drift*0.65), Rotation=NumberRange.new(0, 360), RotSpeed=NumberRange.new(-40, 40), Parent=sky})
end
Wx.fog = function()
if atmo then atmo:Destroy(); atmo = nil end
if feat.fog then
local style = feat.visualStyles.fog or "Low Mist"
local density, haze, glare, offset = feat.fogDensity, 2, 0, 0.25
if style == "Dense Fog" then density, haze = math.max(density, 0.65), 5
elseif style == "Rolling Haze" then density, haze, offset = math.max(density, 0.28), 8, -0.1
elseif style == "Dreamy Glow" then density, haze, glare, offset = math.max(density, 0.2), 3, 1.2, 0.4 end
atmo = new("Atmosphere", {Name="OwoFog", Density=density, Offset=offset, Color=visualColor("fog"):Lerp(Color3.new(1,1,1), 0.55), Decay=visualColor("fog"):Lerp(Color3.new(0,0,0), 0.45), Glare=glare, Haze=haze, Parent=Lighting})
end
end
Wx.fogDensity = function(v) if atmo then atmo.Density = v end end
Wx.fireflies = function()
if flyE then flyE:Destroy(); flyE = nil end
if not feat.fireflies then return end
local style = feat.visualStyles.fireflies or "Float"
local rate, lifetime, speed, spread, accel = 18, NumberRange.new(5,8), NumberRange.new(0.5,1.5), Vector2.new(180,180), Vector3.new(0,0.4,0)
if style == "Swirl" then rate, lifetime, speed, spread, accel = 35, NumberRange.new(3,5), NumberRange.new(1.2,2.8), Vector2.new(90,90), Vector3.new(2,0.2,-2)
elseif style == "Burst" then rate, lifetime, speed, spread, accel = 8, NumberRange.new(1,2), NumberRange.new(5,10), Vector2.new(180,180), Vector3.new(0,-1,0)
elseif style == "Drift" then rate, lifetime, speed, spread, accel = 12, NumberRange.new(8,12), NumberRange.new(0.1,0.5), Vector2.new(180,180), Vector3.new(0,0.08,0) end
flyE = new("ParticleEmitter", {Rate=rate, Lifetime=lifetime, Speed=speed, EmissionDirection=Enum.NormalId.Top, SpreadAngle=spread, Shape=style=="Swirl" and Enum.ParticleEmitterShape.Cylinder or Enum.ParticleEmitterShape.Sphere, ShapeStyle=Enum.ParticleEmitterShapeStyle.Volume, Size=NumberSequence.new({NumberSequenceKeypoint.new(0,0), NumberSequenceKeypoint.new(0.3,style=="Burst" and 0.45 or 0.28), NumberSequenceKeypoint.new(1,0)}), Transparency=NumberSequence.new({NumberSequenceKeypoint.new(0,1), NumberSequenceKeypoint.new(0.2,0.1), NumberSequenceKeypoint.new(0.8,0.1), NumberSequenceKeypoint.new(1,1)}), Color=ColorSequence.new(visualColor("fireflies")), LightEmission=1, Acceleration=accel, Rotation=NumberRange.new(0,360), RotSpeed=NumberRange.new(-80,80), Parent=vol})
end
local function mkCube(size, transp, style)
style = style or "Cubes"
local shape = style == "Soft Orbs" and Enum.PartType.Ball or (style == "Wireframe" and Enum.PartType.Block or Enum.PartType.Block)
local part = new("Part", {Name="OwoFloatingGeometry",Anchored=true,CanCollide=false,CanQuery=false,CanTouch=false,CastShadow=false,Material=style=="Soft Orbs" and Enum.Material.ForceField or (style=="Diamonds" and Enum.Material.Glass or Enum.Material.Neon),Shape=shape,Size=Vector3.new(size,size,size),Color=visualColor("cubes"),Transparency=style=="Wireframe" and 1 or transp,Parent=fx})
if style == "Wireframe" then
local box = new("SelectionBox", {Name="OwoWireframe", Adornee=part, Color3=visualColor("cubes"), LineThickness=0.035, SurfaceTransparency=1, Parent=part})
end
return part
end
Wx.cubes = function()
for _, p in ipairs(cubes) do p:Destroy() end
cubes = {}
local style = feat.visualStyles.cubes or "Cubes"
if feat.cubes then for i = 1, feat.cubeCount do cubes[i] = mkCube(0.7, 0.2, style) end end
end
Wx.ambient = function()
for _, e in ipairs(amb) do e.part:Destroy() end
amb = {}
local style = feat.visualStyles.ambient or "Cubes"
if feat.ambient then
local hrp = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
local base = hrp and hrp.Position or camera.CFrame.Position
for i = 1, 28 do
amb[i] = {part=mkCube(0.3 + math.random() * 0.6, 0.35, style), pos=base + Vector3.new(math.random(-45,45), math.random(-6,18), math.random(-45,45)), s=0.6 + math.random() * 1.2, ph=math.random() * 6.28}
end
end
end
Wx.color = function()
for _, p in ipairs(cubes) do p.Color = visualColor("cubes") end
for _, e in ipairs(amb) do e.part.Color = visualColor("ambient") end
if feat.fireflies then Wx.fireflies() end
if feat.rain then Wx.rain() end
if feat.snow then Wx.snow() end
if feat.fog then Wx.fog() end
for _, f in ipairs(vig) do f.BackgroundColor3 = visualColor("vignette"):Lerp(Color3.new(0,0,0), 0.85) end
end
Wx.all = function() Wx.rain(); Wx.snow(); Wx.fog(); Wx.fireflies(); Wx.cubes(); Wx.ambient() end
local t0 = tick()
RS.RenderStepped:Connect(function(dt)
camera = workspace.CurrentCamera or camera
local cp = camera.CFrame.Position
sky.CFrame = CFrame.new(cp + Vector3.new(0, 45, 0))
vol.CFrame = CFrame.new(cp)
-- Smooth effect transitions
sBloom = slerp(sBloom, feat.bloom and 1 or 0, dt, Smooth.effectSpeed)
sTint = slerp(sTint, feat.tint and 1 or 0, dt, Smooth.effectSpeed)
sVignette = slerp(sVignette, feat.vignette and 1 or 0, dt, Smooth.effectSpeed)
sChroma = slerp(sChroma, feat.chromaticAberration and 1 or 0, dt, Smooth.effectSpeed)
sRetro = slerp(sRetro, feat.retroFilter and 1 or 0, dt, Smooth.effectSpeed)
sEffectColor = slerpC(sEffectColor, visualColor("tint"), dt, Smooth.colorSpeed)
-- Apply bloom smoothly
bloomE.Enabled = sBloom > 0.01
local bloomStyle = feat.visualStyles.bloom or "Soft Bloom"
if bloomStyle == "Lens Glow" then bloomE.Intensity, bloomE.Size, bloomE.Threshold = 1.25*sBloom, 56, 0.68
elseif bloomStyle == "Dream Bloom" then bloomE.Intensity, bloomE.Size, bloomE.Threshold = 0.95*sBloom, 48, 1.15
elseif bloomStyle == "Hard Glow" then bloomE.Intensity, bloomE.Size, bloomE.Threshold = 1.8*sBloom, 18, 0.62
else bloomE.Intensity, bloomE.Size, bloomE.Threshold = 0.55*sBloom, 34, 0.92 end
-- Apply tint smoothly
tintCC.Enabled = sTint > 0.01
if sTint > 0.01 then
local k = feat.tintStrength / 100
local tintStyle = feat.visualStyles.tint or "Soft Wash"
local weight = tintStyle == "Cinematic" and 0.9 or (tintStyle == "Dream Glass" and 0.55 or (tintStyle == "High Contrast" and 0.72 or 0.42))
tintCC.TintColor = Color3.new(1,1,1):Lerp(sEffectColor, k * weight)
tintCC.Saturation = (tintStyle == "High Contrast" and -0.18 or (tintStyle == "Dream Glass" and 0.28 or 0.15)) * k * sTint
tintCC.Contrast = (tintStyle == "High Contrast" and 0.28 or (tintStyle == "Cinematic" and 0.13 or 0.08)) * k * sTint
tintCC.Brightness = (tintStyle == "Dream Glass" and 0.04 or -0.03) * k * sTint
end
-- Apply vignette smoothly
local vigStyle = feat.visualStyles.vignette or "Soft Corners"
for i, f in ipairs(vig) do
f.Visible = sVignette > 0.01
f.BackgroundColor3 = visualColor("vignette"):Lerp(Color3.new(0,0,0),0.85)
if vigStyle == "Cinema Bars" then
f.Visible = sVignette > 0.01 and i <= 2
f.Size = UDim2.new(1,0,0.13,0); f.Position = UDim2.new(0,0,i==1 and 0 or 0.87,0)
elseif vigStyle == "Dark Frame" then
if i <= 2 then f.Size=UDim2.new(1,0,0.4,0); f.Position=UDim2.new(0,0,i==1 and 0 or 0.6,0)
else f.Size=UDim2.new(0.31,0,1,0); f.Position=UDim2.new(i==3 and 0 or 0.69,0,0,0) end
elseif vigStyle == "Focus Tunnel" then
if i <= 2 then f.Size=UDim2.new(1,0,0.28,0); f.Position=UDim2.new(0,0,i==1 and 0 or 0.72,0)
else f.Size=UDim2.new(0.29,0,1,0); f.Position=UDim2.new(i==3 and 0 or 0.71,0,0,0) end
else
if i <= 2 then f.Size=UDim2.new(1,0,0.3,0); f.Position=UDim2.new(0,0,i==1 and 0 or 0.7,0)
else f.Size=UDim2.new(0.22,0,1,0); f.Position=UDim2.new(i==3 and 0 or 0.78,0,0,0) end
end
if f:FindFirstChildOfClass("UIGradient") then
local edgeStrength = vigStyle == "Dark Frame" and 0 or (vigStyle == "Focus Tunnel" and 0.08 or 0.2)
f.UIGradient.Transparency = NumberSequence.new({NumberSequenceKeypoint.new(0, edgeStrength + (1 - sVignette) * 0.8), NumberSequenceKeypoint.new(1, 1)})
end
end
local now = tick() - t0
local hrp = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
if not hrp then return end
if feat.cubes then
local n = #cubes
for i, c in ipairs(cubes) do
local a = now * feat.cubeSpeed + (i / math.max(n, 1)) * math.pi * 2
local r = feat.cubeRadius
c.CFrame = CFrame.new(hrp.Position + Vector3.new(math.cos(a) * r, 0.8 + math.sin(now * 2 + i) * 0.9, math.sin(a) * r)) * CFrame.Angles(now + i, now * 1.3, i)
end
end
if feat.ambient then
for _, e in ipairs(amb) do
e.pos = e.pos + Vector3.new(math.sin(now * 0.3 + e.ph) * 0.4 * dt, 0.3 * dt, math.cos(now * 0.25 + e.ph) * 0.4 * dt)
if (e.pos - hrp.Position).Magnitude > 55 or e.pos.Y > hrp.Position.Y + 35 then
e.pos = hrp.Position + Vector3.new(math.random(-45,45), math.random(-6,4), math.random(-45,45))
end
e.part.CFrame = CFrame.new(e.pos + Vector3.new(0, math.sin(now * e.s + e.ph) * 1.2, 0)) * CFrame.Angles(now * e.s, now * e.s * 0.7, e.ph)
end
end
end)
local lightningFolder = new("Folder", {Name="OwoThunderbolts", Parent=workspace})
-- Optional custom thunder VFX asset. Scripts are stripped from the asset before use.
local thunderVfxTemplate
local thunderVfxLoadAttempted = false
local function getThunderVfxTemplate()
if thunderVfxLoadAttempted then return thunderVfxTemplate end
thunderVfxLoadAttempted = true
local ok, objects = pcall(function()
return game:GetObjects("rbxassetid://15443804434")
end)
if ok and type(objects) == "table" and objects[1] then
local asset = objects[1]
for _, descendant in ipairs(asset:GetDescendants()) do
if descendant:IsA("Script") or descendant:IsA("LocalScript") or descendant:IsA("ModuleScript") then
descendant:Destroy()
end
end
if asset:IsA("Model") or asset:IsA("BasePart") or asset:IsA("Folder") then
thunderVfxTemplate = asset
else
asset:Destroy()
end
end
return thunderVfxTemplate
end
local function spawnThunderVfx(hrp)
local template = getThunderVfxTemplate()
if not template then return false end
local clone = template:Clone()
for _, descendant in ipairs(clone:GetDescendants()) do
if descendant:IsA("BasePart") then
descendant.Anchored = true
descendant.CanCollide = false
descendant.CanTouch = false
descendant.CanQuery = false
end
end
if clone:IsA("BasePart") then
clone.Anchored = true
clone.CanCollide = false
clone.CanTouch = false
clone.CanQuery = false
end
clone.Parent = lightningFolder
local look = camera.CFrame.LookVector
local right = camera.CFrame.RightVector
local spawnPosition = hrp.Position + look * math.random(85, 125)
+ right * math.random(-35, 35) + Vector3.new(0, math.random(38, 58), 0)
local targetPosition = hrp.Position + look * math.random(75, 115)
+ right * math.random(-28, 28) + Vector3.new(0, math.random(-5, 12), 0)
local targetCFrame = CFrame.lookAt(spawnPosition, targetPosition)
pcall(function()
if clone:IsA("Model") then
clone:PivotTo(targetCFrame)
elseif clone:IsA("BasePart") then
clone.CFrame = targetCFrame
elseif clone:IsA("Folder") then
for _, item in ipairs(clone:GetChildren()) do
if item:IsA("Model") then item:PivotTo(targetCFrame)
elseif item:IsA("BasePart") then item.CFrame = targetCFrame end
end
end
end)
task.delay(5, function()
if clone and clone.Parent then clone:Destroy() end
end)
return true
end
local function createWorldLightning()
local character = player.Character
local hrp = character and character:FindFirstChild("HumanoidRootPart")
if not hrp then return end
if spawnThunderVfx(hrp) then return end
local style = feat.visualStyles.thunder or "Double Flash"
local boltColor = style == "Violet Storm" and Color3.fromRGB(175,135,255) or visualColor("thunder")
local thickness = style == "Soft Glow" and 0.22 or 0.38
local look = camera.CFrame.LookVector
local right = camera.CFrame.RightVector
local distance = math.random(105, 145)
local origin = hrp.Position + look * distance + right * math.random(-42,42) + Vector3.new(0, math.random(48,72), 0)
local ground = origin + Vector3.new(math.random(-24,24), -math.random(42,62), math.random(-24,24))
local points = {origin}
local steps = 7
for i = 1, steps - 1 do
local a = i / steps
points[#points+1] = origin:Lerp(ground,a) + Vector3.new(math.random(-13,13), math.random(-5,5), math.random(-13,13))
end
points[#points+1] = ground
local firstPart
for i = 1, #points - 1 do
local from, to = points[i], points[i+1]
local delta = to - from
local length = delta.Magnitude
local segment = new("Part", {
Name="OwoLightningBolt", Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false,
CastShadow=false, Material=Enum.Material.Neon, Color=boltColor,
Size=Vector3.new(thickness,length,thickness),
CFrame=CFrame.lookAt((from+to)*0.5,to) * CFrame.Angles(math.rad(90),0,0),
Transparency=style == "Soft Glow" and 0.18 or 0.04, Parent=lightningFolder
})
firstPart = firstPart or segment
task.delay(0.22, function() if segment and segment.Parent then segment:Destroy() end end)
end
if firstPart then
local light = new("PointLight", {Color=boltColor, Brightness=style == "Soft Glow" and 1.5 or 3.5, Range=style == "Soft Glow" and 35 or 58, Shadows=false, Parent=firstPart})
task.delay(0.16,function() if light and light.Parent then light:Destroy() end end)
end
end
task.spawn(function()
while true do
task.wait(math.random(8, 15))
if feat.thunder then
local style = feat.visualStyles.thunder or "Double Flash"
local count = style == "Rapid Burst" and 3 or (style == "Soft Glow" and 1 or 2)
for strike = 1, count do
if not feat.thunder then break end
createWorldLightning()
if strike < count then task.wait(style == "Rapid Burst" and 0.22 or 0.55) end
end
end
end
end)
player.CharacterAdded:Connect(function() task.wait(1); if feat.ambient then Wx.ambient() end end)
end
-- ══════════════════════════════════════════════════════════════
-- RAIN RIPPLES (drops hit the ground / water and send out rings)
-- ══════════════════════════════════════════════════════════════
do
local folder = new("Folder", {Name="OwoRipples", Parent=workspace})
local POOL = 90
local pool, active = {}, {}
local rp = RaycastParams.new(); rp.FilterType = Enum.RaycastFilterType.Exclude; rp.IgnoreWater = false
local function mk()
local p = new("Part", {Name="Ripple", Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Transparency=1, Size=Vector3.new(1, 0.05, 1)})
local sg = new("SurfaceGui", {Face=Enum.NormalId.Top, SizingMode=Enum.SurfaceGuiSizingMode.FixedSize, CanvasSize=Vector2.new(160, 160), LightInfluence=0, AlwaysOnTop=false, Brightness=1.5, Parent=p})
local st, frames, corners = {}, {}, {}
for i, sc in ipairs({1, 0.66, 0.34}) do
local fr = new("Frame", {AnchorPoint=Vector2.new(0.5, 0.5), Position=UDim2.fromScale(0.5, 0.5), Size=UDim2.fromScale(sc * 0.96, sc * 0.96), BackgroundTransparency=1, BorderSizePixel=0, Parent=sg})
frames[i] = fr
corners[i] = new("UICorner", {CornerRadius=UDim.new(0.5, 0), Parent=fr})
st[i] = new("UIStroke", {Thickness=i==1 and 6 or 4, Color=Color3.new(1, 1, 1), Transparency=1, Parent=fr})
end
return {part=p, st=st, frames=frames, corners=corners, age=0, life=1, size=1}
end
local acc = 0
RS.RenderStepped:Connect(function(dt)
for i = #active, 1, -1 do
local r = active[i]
r.age += dt
local k = r.age / r.life
if k >= 1 then
r.part.Parent = nil
pool[#pool+1] = r
table.remove(active, i)
else
local e = 1 - (1 - k) * (1 - k)
local s = r.size * (0.2 + 0.8 * e)
r.part.Size = Vector3.new(s, 0.05, s)
local tr = 0.15 + 0.85 * k ^ 1.3
local rippleStyle = feat.visualStyles.ripples or "Twin Rings"
r.st[1].Transparency = tr
r.st[2].Transparency = rippleStyle == "Twin Rings" and math.min(1,tr+0.25) or math.min(1,tr+0.12)
r.st[3].Transparency = rippleStyle == "Twin Rings" and 1 or ((rippleStyle == "Ripple Bloom" or rippleStyle == "Shock Rings" or rippleStyle == "Wide Waves") and math.min(1,tr+0.35) or 1)
for j=1,3 do
local isShock = rippleStyle == "Shock Rings"
r.frames[j].Rotation = isShock and 45 or 0
r.corners[j].CornerRadius = UDim.new(isShock and 0.08 or 0.5,0)
r.st[j].Thickness = rippleStyle == "Wide Waves" and ({9,6,3})[j] or ({6,4,3})[j]
if rippleStyle == "Ripple Bloom" then
r.frames[j].Size = UDim2.fromScale(({1,0.72,0.43})[j] * (0.92 + 0.08 * math.sin(r.age*8+j)), ({1,0.72,0.43})[j] * (0.92 + 0.08 * math.sin(r.age*8+j)))
else
r.frames[j].Size = UDim2.fromScale(({1,0.66,0.34})[j] * 0.96, ({1,0.66,0.34})[j] * 0.96)
end
end
end
end
if not feat.rainRipples then acc = 0; return end
acc = math.min(acc + dt * feat.rippleRate, 6)
local cam = workspace.CurrentCamera
while acc >= 1 do
acc -= 1
if #active >= POOL then break end
local base = cam.CFrame.Position
local ang, rad = math.random() * math.pi * 2, math.sqrt(math.random()) * feat.rippleRadius
local origin = Vector3.new(base.X + math.cos(ang) * rad, base.Y + 40, base.Z + math.sin(ang) * rad)
rp.FilterDescendantsInstances = {player.Character, folder}
local hit = workspace:Raycast(origin, Vector3.new(0, -140, 0), rp)
if hit and hit.Normal.Y > 0.7 then
local r = table.remove(pool) or mk()
r.age, r.life = 0, 0.8 + math.random() * 0.7
r.size = feat.rippleSize * (0.7 + math.random() * 0.8)
local col = Color3.new(1, 1, 1):Lerp(visualColor("ripples"), 0.25)
r.st[1].Color = col; r.st[2].Color = col
r.part.Size = Vector3.new(r.size * 0.2, 0.05, r.size * 0.2)
r.part.CFrame = CFrame.new(hit.Position + Vector3.new(0, 0.04, 0))
r.part.Parent = folder
active[#active+1] = r
end
end
end)
end
-- ══════════════════════════════════════════════════════════════
-- WORLD OUTLINES (draws edges around parts near you, every corner)
-- ══════════════════════════════════════════════════════════════
do
local folder = new("Folder", {Name="OwoOutlines", Parent=workspace})
local MAXB = 160
local boxes, used = {}, 0
local op = OverlapParams.new(); op.FilterType = Enum.RaycastFilterType.Exclude
local acc = 0
local function isOwo(p)
local a = p
while a and a ~= workspace do
if a.Name and a.Name:sub(1, 3) == "Owo" then return true end
a = a.Parent
end
return false
end
local function getBox(i)
local b = boxes[i]
if not b then
b = new("SelectionBox", {LineThickness=0.05, SurfaceTransparency=1, Color3=Color3.new(0,0,0), Parent=folder})
boxes[i] = b
end
return b
end
RS.Heartbeat:Connect(function(dt)
if not feat.worldOutline then
if used > 0 then
for i = 1, used do
if boxes[i] then boxes[i].Adornee = nil end
if boxes[MAXB+i] then boxes[MAXB+i].Adornee = nil end
end
used = 0
end
return
end
acc += dt
if acc < 0.3 then return end
acc = 0
local cam = workspace.CurrentCamera
local cp = cam.CFrame.Position
op.FilterDescendantsInstances = {player.Character, folder}
local parts = workspace:GetPartBoundsInRadius(cp, feat.outlineRadius, op)
local cand = {}
for _, p in ipairs(parts) do
if p:IsA("BasePart") and not p:IsA("Terrain") and p.Transparency < 0.95 and p.Size.Magnitude > 1.4 and not isOwo(p) then
cand[#cand+1] = {p = p, d = (p.Position - cp).Magnitude}
end
end
table.sort(cand, function(a, b) return a.d < b.d end)
local col = feat.visualColors.worldOutline or hexToColor(feat.outlineColorHex) or Color3.new(0, 0, 0)
local outlineStyle = feat.visualStyles.worldOutline or "Fine Edge"
local n = math.min(#cand, MAXB)
for i = 1, n do
local b = getBox(i)
b.Adornee = cand[i].p
b.Color3 = outlineStyle == "Soft Edge" and col:Lerp(Color3.new(1,1,1),0.5) or col
b.LineThickness = outlineStyle == "Bold Edge" and math.max(feat.outlineThick,0.09) or (outlineStyle == "Fine Edge" and math.min(feat.outlineThick,0.025) or feat.outlineThick)
b.SurfaceTransparency = outlineStyle == "Soft Edge" and 0.98 or 1
if outlineStyle == "Double Edge" then
local b2 = getBox(MAXB+i)
b2.Adornee = cand[i].p; b2.Color3 = col:Lerp(Color3.new(1,1,1),0.72)
b2.LineThickness = math.max(0.015,feat.outlineThick*0.42); b2.SurfaceTransparency = 1
elseif boxes[MAXB+i] then boxes[MAXB+i].Adornee = nil end
end
for i = n + 1, used do
if boxes[i] then boxes[i].Adornee = nil end
if boxes[MAXB+i] then boxes[MAXB+i].Adornee = nil end
end
used = n
end)
end
-- ══════════════════════════════════════════════════════════════
-- RAIN PUDDLES (glossy water puddles that grow on flat ground around you)
-- ══════════════════════════════════════════════════════════════
do
local folder = new("Folder", {Name="OwoPuddles", Parent=workspace})
local list = {}
local rp = RaycastParams.new(); rp.FilterType = Enum.RaycastFilterType.Exclude
local acc = 0
local function mk()
local style = feat.visualStyles.puddles or "Mirror Pools"
local shape = style == "Hex Pools" and Enum.PartType.Block or (style == "Neon Circles" and Enum.PartType.Cylinder or Enum.PartType.Cylinder)
local p = new("Part", {Name="Puddle", Shape=shape, Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false,
Material=style == "Neon Circles" and Enum.Material.Neon or Enum.Material.Glass, Reflectance=style=="Mirror Pools" and 0.95 or (style=="Soft Pools" and 0.25 or 0.5), Transparency=style=="Neon Circles" and 0.2 or (style=="Soft Pools" and 0.48 or 0.3), Size=Vector3.new(0.05, 0.1, 0.1)})
return {part=p, alive=false, g=0, d1=1, d2=1}
end
local function place(pd)
local base = workspace.CurrentCamera.CFrame.Position
local ang, rad = math.random() * math.pi * 2, 6 + math.sqrt(math.random()) * 44
local origin = Vector3.new(base.X + math.cos(ang) * rad, base.Y + 30, base.Z + math.sin(ang) * rad)
rp.FilterDescendantsInstances = {player.Character, folder}
local hit = workspace:Raycast(origin, Vector3.new(0, -120, 0), rp)
if not hit or hit.Normal.Y < 0.92 or hit.Material == Enum.Material.Water then return end
pd.d1 = feat.puddleSize * (0.7 + math.random() * 0.9)
pd.d2 = pd.d1 * (0.55 + math.random() * 0.45)
pd.g = 0
pd.part.CFrame = CFrame.new(hit.Position + Vector3.new(0, 0.035, 0)) * CFrame.Angles(0, math.random() * math.pi * 2, 0) * CFrame.Angles(0, 0, math.pi / 2)
local puddleStyle = feat.visualStyles.puddles or "Mirror Pools"
pd.part.Color = puddleStyle == "Neon Circles" and visualColor("puddles") or (puddleStyle == "Soft Pools" and Color3.fromRGB(145,175,205) or Color3.fromRGB(34,52,78):Lerp(visualColor("puddles"),0.12))
pd.part.Material = puddleStyle == "Neon Circles" and Enum.Material.Neon or Enum.Material.Glass
pd.part.Reflectance = puddleStyle == "Mirror Pools" and 0.95 or (puddleStyle == "Soft Pools" and 0.25 or 0.5)
pd.part.Transparency = puddleStyle == "Neon Circles" and 0.2 or (puddleStyle == "Soft Pools" and 0.48 or 0.3)
pd.part.Size = Vector3.new(0.05, 0.1, 0.1)
pd.part.Parent = folder
pd.alive = true
end
RS.Heartbeat:Connect(function(dt)
local want = feat.rainPuddles and math.floor(feat.puddleCount) or 0
while #list < want do list[#list+1] = mk() end
acc += dt
local doTick = acc >= 0.3
if doTick then acc = 0 end
local tries = 0
local cp = workspace.CurrentCamera.CFrame.Position
for i = #list, 1, -1 do
local pd = list[i]
if i > want then pd.shrink = true end
if pd.alive then
local puddleStyle = feat.visualStyles.puddles or "Mirror Pools"
pd.part.Shape = puddleStyle == "Hex Pools" and Enum.PartType.Block or Enum.PartType.Cylinder
pd.part.Material = puddleStyle == "Neon Circles" and Enum.Material.Neon or (puddleStyle == "Soft Pools" and Enum.Material.SmoothPlastic or Enum.Material.Glass)
pd.part.Color = puddleStyle == "Neon Circles" and visualColor("puddles") or (puddleStyle == "Soft Pools" and Color3.fromRGB(145,175,205) or Color3.fromRGB(34,52,78):Lerp(visualColor("puddles"),0.12))
pd.part.Reflectance = puddleStyle == "Mirror Pools" and 0.95 or (puddleStyle == "Soft Pools" and 0.12 or (puddleStyle == "Neon Circles" and 0.25 or 0.5))
pd.part.Transparency = puddleStyle == "Neon Circles" and 0.2 or (puddleStyle == "Soft Pools" and 0.48 or 0.3)
if doTick and not pd.shrink and (pd.part.Position - cp).Magnitude > 62 then pd.shrink = true end
pd.g = math.clamp(pd.g + (pd.shrink and -dt * 1.2 or dt * 0.7), 0, 1)
local e = 1 - (1 - pd.g) * (1 - pd.g)
pd.part.Size = Vector3.new(0.05, pd.d1 * e + 0.01, pd.d2 * e + 0.01)
if pd.shrink and pd.g <= 0 then pd.part:Destroy(); table.remove(list, i) end
elseif pd.shrink then
pd.part:Destroy(); table.remove(list, i)
elseif doTick and tries < 4 then
tries += 1
place(pd)
end
end
end)
end
-- ══════════════════════════════════════════════════════════════
-- SNOW ON THE FLOOR (white snow patches settle on every flat surface near you)
-- ══════════════════════════════════════════════════════════════
do
local folder = new("Folder", {Name="OwoSnowFloor", Parent=workspace})
local cells, count = {}, 0
local CELL = 4
local rp = RaycastParams.new(); rp.FilterType = Enum.RaycastFilterType.Exclude
local acc = 0
local lastSnowStyle = nil
local lastSnowColor = nil
RS.Heartbeat:Connect(function(dt)
local currentSnowStyle = feat.visualStyles.snowFloor or "Powder Patches"
local currentSnowColorKey = feat.visualColors.snowFloor
if currentSnowStyle ~= lastSnowStyle or currentSnowColorKey ~= lastSnowColor then
lastSnowStyle = currentSnowStyle
lastSnowColor = currentSnowColorKey
for _, c in pairs(cells) do
local part = c.part
if part and part.Parent then
part.Shape = currentSnowStyle == "Hex Snow" and Enum.PartType.Block or (currentSnowStyle == "Crystal Flakes" and Enum.PartType.Ball or Enum.PartType.Cylinder)
part.Material = currentSnowStyle == "Frost Rings" and Enum.Material.Glass or (currentSnowStyle == "Crystal Flakes" and Enum.Material.Neon or Enum.Material.Snow)
part.Color = feat.visualColors.snowFloor or (currentSnowStyle == "Crystal Flakes" and Color3.fromRGB(170,225,255) or Color3.fromRGB(248,250,255))
part.Transparency = currentSnowStyle == "Frost Rings" and 0.42 or (currentSnowStyle == "Crystal Flakes" and 0.18 or 0)
end
end
end
if not feat.snowFloor then
if count > 0 then
for key, c in pairs(cells) do
local part = c.part
TS:Create(part, TweenInfo.new(0.8), {Size = Vector3.new(0.02, 0.1, 0.1)}):Play()
task.delay(0.9, function() part:Destroy() end)
cells[key] = nil
end
count = 0
end
return
end
acc += dt
if acc < 0.2 then return end
acc = 0
local cp = workspace.CurrentCamera.CFrame.Position
local R = feat.snowRadius
rp.FilterDescendantsInstances = {player.Character, folder}
for _ = 1, 16 do
if count >= 700 then break end
local ang, rad = math.random() * math.pi * 2, math.sqrt(math.random()) * R
local x, z = cp.X + math.cos(ang) * rad, cp.Z + math.sin(ang) * rad
local cx, cz = math.floor(x / CELL), math.floor(z / CELL)
local key = cx .. "," .. cz
if not cells[key] then
local origin = Vector3.new(cx * CELL + CELL * 0.5, cp.Y + 35, cz * CELL + CELL * 0.5)
local hit = workspace:Raycast(origin, Vector3.new(0, -140, 0), rp)
if hit and hit.Normal.Y > 0.7 and hit.Material ~= Enum.Material.Water then
local d = CELL * (1.5 + math.random() * 0.5)
local depth = feat.snowDepth
local pos = hit.Position + hit.Normal * (depth * 0.5 + math.random() * 0.03)
local snowStyle = feat.visualStyles.snowFloor or "Powder Patches"
local snowShape = snowStyle == "Hex Snow" and Enum.PartType.Block or (snowStyle == "Crystal Flakes" and Enum.PartType.Ball or Enum.PartType.Cylinder)
local snowMat = snowStyle == "Frost Rings" and Enum.Material.Glass or Enum.Material.Snow
local snowColor = feat.visualColors.snowFloor or (snowStyle == "Crystal Flakes" and Color3.fromRGB(190,235,255) or Color3.fromRGB(248,250,255))
local part = new("Part", {Name="Snow", Shape=snowShape, Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false,
Material=snowMat, Color=snowColor, Transparency=snowStyle=="Frost Rings" and 0.42 or (snowStyle=="Crystal Flakes" and 0.18 or 0), Size=Vector3.new(0.02, 0.1, 0.1),
CFrame=CFrame.lookAt(pos, pos + hit.Normal) * CFrame.Angles(0, math.pi / 2, 0), Parent=folder})
local targetSize = snowStyle == "Crystal Flakes" and Vector3.new(depth*0.35,d*0.62,d*0.62) or (snowStyle == "Frost Rings" and Vector3.new(depth*0.25,d,d) or Vector3.new(depth,d,d))
TS:Create(part, TweenInfo.new(1.4, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {Size = targetSize}):Play()
cells[key] = {part = part}; count += 1
end
end
end
for key, c in pairs(cells) do
if (c.part.Position - cp).Magnitude > R + 12 then
c.part:Destroy(); cells[key] = nil; count -= 1
end
end
end)
end
-- ══════════════════════════════════════════════════════════════
-- KNIFE INSPECT + VIEWMODEL HAND (reference-timed inspect, steel-default Karambit)
-- First-person cosmetic viewmodel: restrained clip-point butterfly blade, parallel gently bowed handles,
-- curved karambit, three inspect phases per model, and locomotion/camera-reactive arm sway.
-- Keep one blocky forearm only; no extra modeled fingers.
-- ══════════════════════════════════════════════════════════════
do
-- A previously executed copy can leave a camera-relative knife model behind. Disconnect
-- its render loop and destroy its model before creating this one, so there is never a stale
-- floating knife competing with the current hand-attached model.
local knifeRuntime = _G
pcall(function()
if type(getgenv) == "function" then knifeRuntime = getgenv() end
end)
pcall(function()
local oldConnection = knifeRuntime.__OWO_KNIFE_RENDER
if oldConnection then oldConnection:Disconnect() end
end)
pcall(function()
local oldViewmodel = knifeRuntime.__OWO_KNIFE_VM
if oldViewmodel then oldViewmodel:Destroy() end
end)
pcall(function()
for _, existing in ipairs(workspace:GetDescendants()) do
if existing.Name == "OwoKnifeVM" then existing:Destroy() end
end
end)
local vm = new("Model", {Name="OwoKnifeVM"})
pcall(function() knifeRuntime.__OWO_KNIFE_VM = vm end)
local root = new("Part", {Name="Root", Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Transparency=1, Size=Vector3.new(0.2,0.2,0.2), Parent=vm})
local STEEL = Color3.fromRGB(207, 212, 219)
local DARK = Color3.fromRGB(24, 24, 28)
-- Build a true crescent strip in the local XY plane. Every segment follows the arc tangent,
-- with its width perpendicular to the curve and thickness along Z; this avoids the flat,
-- floating-looking ribbon caused by keeping every segment's width vertical.
local function buildArc(parent, n, totalDeg, radius, w0, w1, thick, color, mat)
local items = {}
local total = math.rad(totalDeg)
for i = 1, n do
local a0, a1 = (i - 1) / n * total, i / n * total
local p0 = Vector3.new(math.sin(a0) * radius, (1 - math.cos(a0)) * radius, 0)
local p1 = Vector3.new(math.sin(a1) * radius, (1 - math.cos(a1)) * radius, 0)
local mid, dir = (p0 + p1) * 0.5, (p1 - p0)
local segLen = math.max(dir.Magnitude * 1.10, 0.02)
local w = w0 + (w1 - w0) * ((i - 0.5) / n)
local part = new("WedgePart", {Material=mat, Color=color, Size=Vector3.new(segLen, w, thick), Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Parent=parent})
local tangentAngle = math.atan2(dir.Y, dir.X)
items[i] = {part = part, rest = CFrame.new(mid) * CFrame.Angles(0, 0, tangentAngle)}
end
return items
end
local function applyArc(items, worldPivot, modelScale, zOffset)
modelScale = modelScale or 1
zOffset = zOffset or 0
for _, it in ipairs(items) do
local rotationOnly = it.rest - it.rest.Position
local p = it.rest.Position * modelScale + Vector3.new(0, 0, zOffset * modelScale)
it.part.CFrame = worldPivot * CFrame.new(p) * rotationOnly
end
end
-- Curved blade strip defined by a centerline and tapered width. The segment's long axis
-- follows the centerline tangent, so the silhouette reads as a real curved blade instead
-- of a stack of sideways wedges.
local function buildCurvedStrip(parent, n, curveFn, widthFn, thick, color, mat, namePrefix)
local items = {}
for i = 1, n do
local t0, t1 = (i - 1) / n, i / n
local x0, y0 = curveFn(t0)
local x1, y1 = curveFn(t1)
local midT = (t0 + t1) * 0.5
local mx, my = curveFn(midT)
local dx, dy = x1 - x0, y1 - y0
local segLen = math.max(Vector2.new(dx, dy).Magnitude * 1.18, 0.014)
local tangentAngle = math.atan2(dy, dx)
local w = math.max(0.0025, widthFn(midT))
local part = new("Part", {Name=(namePrefix or "CurvedBlade")..i, Material=mat, Color=color,
Size=Vector3.new(segLen, w, thick), Anchored=true, CanCollide=false, CanQuery=false,
CanTouch=false, CastShadow=false, Parent=parent})
items[i] = {part=part, rest=CFrame.new(mx, my, 0) * CFrame.Angles(0, 0, tangentAngle)}
end
return items
end
-- ───── Butterfly knife: continuous tapered clip-point blade + twin pivoting scales ─────
-- Dense overlapping blade sections produce a smoother curved silhouette using native Parts.
local bfly = {}
do
local g = new("Model", {Name="Butterfly", Parent=vm})
bfly.bladeSections, bfly.spineSegments, bfly.edgeSegments, bfly.fullerSegments = {}, {}, {}, {}
local bladeN = 79
local BLADE_LEN = 1.00
local function butterflyBladeCurve(t)
-- Reference clip silhouette: mostly straight clip-point blade, with a restrained
-- belly sweep. Avoid the exaggerated S/scimitar curve that made the model look wrong.
return 0.038 * math.sin(math.pi * t) + 0.012 * t - 0.006 * t * t
end
local function butterflyBladeSlope(t)
return 0.038 * math.pi * math.cos(math.pi * t) + 0.012 - 0.012 * t
end
for i = 1, bladeN do
local t = (i - 1) / (bladeN - 1)
local x = 0.035 + BLADE_LEN * t
local width
if t < 0.16 then
width = 0.058 + 0.066 * (t / 0.16)
elseif t < 0.62 then
local q = (t - 0.16) / 0.46
width = 0.124 - 0.008 * q + 0.004 * math.sin(q * math.pi)
else
width = math.max(0.0025, 0.116 * (((1 - t) / 0.38) ^ 0.94))
end
local cy = butterflyBladeCurve(t)
local angle = math.atan2(butterflyBladeSlope(t), BLADE_LEN)
local part = new("Part", {Name="BladeSection"..i, Material=Enum.Material.Metal, Color=STEEL,
Size=Vector3.new(0.022, width, 0.030), Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Parent=g})
bfly.bladeSections[i] = {part=part, x=x, y=cy, width=width, angle=angle}
local spine = new("Part", {Name="SpineLine"..i, Material=Enum.Material.Metal, Color=Color3.fromRGB(139,147,158),
Size=Vector3.new(0.030, 0.007, 0.004), Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Parent=g})
bfly.spineSegments[i] = {part=spine, x=x, y=cy + width * 0.405, angle=angle, z=0.018}
local edge = new("Part", {Name="CuttingBevel"..i, Material=Enum.Material.Metal, Color=Color3.fromRGB(181,187,195),
Size=Vector3.new(0.030, 0.008, 0.004), Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Parent=g})
bfly.edgeSegments[i] = {part=edge, x=x, y=cy - width * 0.405, angle=angle, z=0.019}
local fuller = new("Part", {Name="BladeFuller"..i, Material=Enum.Material.Metal, Color=Color3.fromRGB(89,96,107),
Size=Vector3.new(0.030, math.min(0.009, width * 0.075), 0.003), Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Parent=g})
bfly.fullerSegments[i] = {part=fuller, x=x, y=cy + width * 0.045, angle=angle, z=0.020}
end
bfly.tip = new("WedgePart", {Name="ClipPointTip", Material=Enum.Material.Metal, Color=STEEL,
Size=Vector3.new(0.092,0.046,0.030), Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Parent=g})
bfly.handles, bfly.wraps, bfly.inlays, bfly.rails, bfly.endCaps, bfly.screws = {}, {}, {}, {}, {}, {}
-- Each handle follows a bowed centerline from the hinge toward the butt. Segmenting the
-- shell gives it a real curved silhouette instead of the old straight rectangular bar.
local HANDLE_LEN = 0.82
local HANDLE_BOW = 0.045
local HANDLE_SEGMENTS = 30
local function handleCurve(u)
u = math.clamp(u, 0, 1)
local x = -HANDLE_LEN * u
-- Slight, smooth handle bow like the reference. The two scales stay parallel;
-- opposite S-curves were the source of the corkscrew-looking handles.
local y = HANDLE_BOW * (math.sin(math.pi * u) ^ 2) + 0.016 * u
local dy = HANDLE_BOW * math.pi * math.sin(2 * math.pi * u) + 0.016
return x, y, math.atan2(dy, -HANDLE_LEN)
end
local function handleUFromX(x)
return math.clamp((0.035 - x) / HANDLE_LEN, 0, 1)
end
for side = 1, 2 do
local z = side == 1 and -0.052 or 0.052
local outerZ = side == 1 and -0.030 or 0.030
local curved = {}
for segIndex = 1, HANDLE_SEGMENTS do
local u = (segIndex - 0.5) / HANDLE_SEGMENTS
local _, _, angle = handleCurve(u)
local segLen = HANDLE_LEN / HANDLE_SEGMENTS * 1.12
local seg = new("Part", {Name="ButterflyHandle"..side.."_Curve"..segIndex, Material=Enum.Material.SmoothPlastic, Color=DARK,
Size=Vector3.new(segLen,0.082,0.052), Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Parent=g})
curved[#curved+1] = seg
end
bfly.handles[side] = {part=curved[1], segments=curved, z=z}
-- Short grip inlays follow the bow instead of bridging it with a straight plate.
for panelIndex = 1, 7 do
local u = 0.15 + (panelIndex-1) * 0.105
local panel = new("Part", {Name="HandleGripInsert"..side.."_"..panelIndex, Material=Enum.Material.SmoothPlastic, Color=Color3.fromRGB(87,88,94),
Size=Vector3.new(0.084,0.046,0.008), Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Parent=g})
bfly.inlays[#bfly.inlays+1] = {part=panel, side=side, u=u, zOffset=outerZ}
end
-- Metal rails are also segmented and curve with the handle shell.
for railIndex, railY in ipairs({-0.043,0.043}) do
for segIndex = 1, 8 do
local u = 0.13 + (segIndex-1) * 0.105
local rail = new("Part", {Name="HandleRail"..side.."_"..railIndex.."_"..segIndex, Material=Enum.Material.Metal, Color=Color3.fromRGB(105,108,114),
Size=Vector3.new(0.074,0.008,0.009), Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Parent=g})
bfly.rails[#bfly.rails+1] = {part=rail, side=side, u=u, y=railY, zOffset=outerZ * 0.92}
end
end
-- Rounded ends follow the same centerline as the curved shell.
for _, capX in ipairs({-0.795,-0.018}) do
local cap = new("Part", {Name="RoundedHandleEnd"..side, Shape=Enum.PartType.Ball, Material=Enum.Material.SmoothPlastic, Color=DARK,
Size=Vector3.new(0.105,0.105,0.065), Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Parent=g})
bfly.endCaps[#bfly.endCaps+1] = {part=cap, side=side, x=capX, z=z}
end
for _, screwX in ipairs({-0.68,-0.45,-0.23}) do
local screw = new("Part", {Name="HandleScrew"..side, Shape=Enum.PartType.Cylinder, Material=Enum.Material.Metal, Color=Color3.fromRGB(153,157,164),
Size=Vector3.new(0.026,0.010,0.026), Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Parent=g})
bfly.screws[#bfly.screws+1] = {part=screw, side=side, x=screwX, zOffset=outerZ}
end
for j = 1, 4 do
local band = new("Part", {Name="HandleWrap"..side.."_"..j, Material=Enum.Material.SmoothPlastic, Color=DARK,
Size=Vector3.new(0.026,0.112,0.075), Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Parent=g})
bfly.wraps[#bfly.wraps+1] = {part=band, side=side, z=z, x=-0.70+(j-1)*0.15}
end
local bolt = new("Part", {Name="PivotBolt"..side, Shape=Enum.PartType.Cylinder, Material=Enum.Material.Metal, Color=Color3.fromRGB(150,150,156),
Size=Vector3.new(0.060,0.018,0.060), Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Parent=g})
bfly.handles[side].bolt = bolt
end
bfly.model = g
end
local function placeButterfly(pivot, modelScale, handleAngles, faceSign, bladeAngleDeg)
local sc = modelScale or 1
handleAngles = handleAngles or {0, 0}
faceSign = faceSign or 1
bladeAngleDeg = bladeAngleDeg or 0
local HANDLE_LEN, HANDLE_BOW = 0.82, 0.045
-- Rotate blade/edge details around the hinge only. The model root remains anchored
-- to the held handle, which prevents the entire cosmetic from flying away from the hand.
local bladeHinge = 0.035 * sc
local bladeTransform = CFrame.new(bladeHinge, 0, 0)
* CFrame.Angles(0, 0, math.rad(bladeAngleDeg))
* CFrame.new(-bladeHinge, 0, 0)
local function handlePoint(side, u)
u = math.clamp(u, 0, 1)
local x = -HANDLE_LEN * u
local curve = HANDLE_BOW * (math.sin(math.pi * u) ^ 2) + 0.016 * u
local slope = HANDLE_BOW * math.pi * math.sin(2 * math.pi * u) + 0.016
-- Parallel bowed handles; separate them only slightly in-plane and in depth.
local y = curve + (side == 1 and -0.020 or 0.020)
local ang = math.atan2(slope, -HANDLE_LEN)
return x, y, ang
end
for _, item in ipairs(bfly.bladeSections) do
item.part.CFrame = pivot * bladeTransform * CFrame.new(item.x*sc, item.y*sc, 0) * CFrame.Angles(0,0,item.angle)
end
for _, item in ipairs(bfly.spineSegments) do
item.part.CFrame = pivot * bladeTransform * CFrame.new(item.x*sc, item.y*sc, item.z*sc*faceSign) * CFrame.Angles(0,0,item.angle)
end
for _, item in ipairs(bfly.edgeSegments) do
item.part.CFrame = pivot * bladeTransform * CFrame.new(item.x*sc, item.y*sc, item.z*sc*faceSign) * CFrame.Angles(0,0,item.angle)
end
for _, item in ipairs(bfly.fullerSegments) do
item.part.CFrame = pivot * bladeTransform * CFrame.new(item.x*sc, item.y*sc, item.z*sc*faceSign) * CFrame.Angles(0,0,item.angle)
end
bfly.tip.CFrame = pivot * bladeTransform * CFrame.new(1.048*sc, 0.006*sc, 0) * CFrame.Angles(0,0,math.rad(-4))
for index, h in ipairs(bfly.handles) do
local hinge = CFrame.new(0.035*sc, 0, h.z*sc)
local flick = CFrame.Angles(0, 0, handleAngles[index] or 0)
for segIndex, handlePart in ipairs(h.segments or {h.part}) do
local u = (segIndex - 0.5) / #h.segments
local x, y, angle = handlePoint(index, u)
local segLen = HANDLE_LEN / #h.segments * 1.12
handlePart.Size = Vector3.new(segLen*sc, 0.082*sc, 0.052*sc)
handlePart.CFrame = pivot * hinge * flick * CFrame.new(x*sc, y*sc, 0) * CFrame.Angles(0,0,angle)
end
h.bolt.CFrame = pivot * CFrame.new(0.035*sc, 0, h.z*1.14*sc) * CFrame.Angles(math.rad(90),0,0)
end
for _, item in ipairs(bfly.wraps) do
local hinge = CFrame.new(0.035*sc, 0, item.z*sc)
local flick = CFrame.Angles(0, 0, handleAngles[item.side] or 0)
local u = math.clamp((0.035-item.x)/HANDLE_LEN, 0, 1)
local _, y, angle = handlePoint(item.side, u)
item.part.CFrame = pivot * hinge * flick * CFrame.new((item.x-0.035)*sc, y*sc, 0) * CFrame.Angles(0,0,angle)
end
for _, item in ipairs(bfly.inlays) do
local hinge = CFrame.new(0.035*sc, 0, bfly.handles[item.side].z*sc)
local flick = CFrame.Angles(0, 0, handleAngles[item.side] or 0)
local x, y, angle = handlePoint(item.side, item.u)
item.part.CFrame = pivot * hinge * flick * CFrame.new(x*sc, y*sc, 0) * CFrame.Angles(0,0,angle) * CFrame.new(0,0,item.zOffset*sc)
end
for _, item in ipairs(bfly.rails) do
local hinge = CFrame.new(0.035*sc, 0, bfly.handles[item.side].z*sc)
local flick = CFrame.Angles(0, 0, handleAngles[item.side] or 0)
local x, y, angle = handlePoint(item.side, item.u)
item.part.CFrame = pivot * hinge * flick * CFrame.new(x*sc, y*sc, 0) * CFrame.Angles(0,0,angle) * CFrame.new(0,item.y*sc,item.zOffset*sc)
end
for _, item in ipairs(bfly.endCaps) do
local hinge = CFrame.new(0.035*sc, 0, bfly.handles[item.side].z*sc)
local flick = CFrame.Angles(0, 0, handleAngles[item.side] or 0)
local u = math.clamp((0.035-item.x)/HANDLE_LEN, 0, 1)
local _, y, angle = handlePoint(item.side, u)
item.part.CFrame = pivot * hinge * flick * CFrame.new((item.x-0.035)*sc, y*sc, 0) * CFrame.Angles(0,0,angle)
end
for _, item in ipairs(bfly.screws) do
local hinge = CFrame.new(0.035*sc, 0, bfly.handles[item.side].z*sc)
local flick = CFrame.Angles(0, 0, handleAngles[item.side] or 0)
local u = math.clamp((0.035-item.x)/HANDLE_LEN, 0, 1)
local _, y, angle = handlePoint(item.side, u)
item.part.CFrame = pivot * hinge * flick * CFrame.new((item.x-0.035)*sc, y*sc, 0) * CFrame.Angles(0,0,angle) * CFrame.new(0,0,item.zOffset*sc) * CFrame.Angles(math.rad(90),0,0)
end
end
-- ───── Karambit: broad hooked crescent, sculpted grip, and a real open finger ring ─────
local kbt = {}
do
local g = new("Model", {Name="Karambit", Parent=vm})
-- CS-inspired karambit silhouette: the blade sweeps left-and-up away from the grip,
-- then hooks slightly at the tip. The broad crescent tapers to a narrow point.
local function karambitCurve(t)
-- Reference silhouette: the belly sweeps down-left in a broad crescent, then
-- the fine tip curls back up instead of reading as a straight diagonal blade.
local x = -1.12*t + 0.12*math.sin(math.pi*t) - 0.035*math.sin(2*math.pi*t)
local y = -0.29*math.sin(math.pi*t) + 0.23*t
return x, y
end
local function karambitBladeWidth(t)
if t < 0.22 then
return 0.18 + 0.11*(t/0.22)
elseif t < 0.56 then
return 0.32 + 0.018*math.sin(((t-0.22)/0.34)*math.pi)
end
return math.max(0.0025, 0.315*(((1-t)/0.44)^0.75))
end
kbt.arc = buildCurvedStrip(g, 72, karambitCurve, karambitBladeWidth, 0.044, STEEL, Enum.Material.Metal, "KarambitBladeSection")
kbt.bevel = buildCurvedStrip(g, 72, karambitCurve, function(t) return karambitBladeWidth(t)*0.56 end,
0.010, Color3.fromRGB(160,166,176), Enum.Material.Metal, "KarambitBevel")
kbt.edge = buildCurvedStrip(g, 72, karambitCurve, function(t) return math.max(0.003, karambitBladeWidth(t)*0.12) end,
0.007, Color3.fromRGB(178,184,194), Enum.Material.Metal, "KarambitEdge")
kbt.handleSegments = {}
-- Segmented molded handle: each section changes width slightly to suggest the
-- scalloped finger-groove contour shown in the reference, without adding hand fingers.
for j = 1, 25 do
local u = (j - 0.5) / 25
local grooveWave = math.sin(u * math.pi * 5)
local shellWidth = 0.16 + 0.038 * grooveWave
local section = new("Part", {Name="KarambitHandleMold"..j, Material=Enum.Material.Fabric, Color=DARK,
Size=Vector3.new(0.030, shellWidth, 0.094), Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Parent=g})
kbt.handleSegments[j] = {part=section, u=u}
end
kbt.handle = kbt.handleSegments[1].part -- compatibility alias for skin/style passes
kbt.gripPanel = new("Part", {Name="KarambitGripPanel", Material=Enum.Material.SmoothPlastic, Color=Color3.fromRGB(53,53,58), Size=Vector3.new(0.34,0.073,0.009), Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Parent=g})
kbt.grooves = {}
for j = 1, 4 do
local groove = new("Part", {Name="GripGroove"..j, Shape=Enum.PartType.Ball, Material=Enum.Material.SmoothPlastic, Color=Color3.fromRGB(26,26,29),
Size=Vector3.new(0.070,0.055,0.012), Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Parent=g})
kbt.grooves[j] = groove
end
-- Individually placed tangential bars create a smooth-looking open finger ring, not a solid disk.
kbt.ringSegments = {}
for j = 1, 24 do
local seg = new("Part", {Name="RingRimSegment"..j, Material=Enum.Material.Metal,
Color=Color3.fromRGB(150,150,156), Size=Vector3.new(0.058,0.034,0.040), Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Parent=g})
kbt.ringSegments[j] = seg
end
kbt.wraps = {}
for j = 1, 5 do
local band = new("Part", {Name="GripWrap"..j, Material=Enum.Material.SmoothPlastic, Color=DARK,
Size=Vector3.new(0.025,0.12,0.1), Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Parent=g})
kbt.wraps[j] = band
end
kbt.model = g
end
local function placeKarambit(pivot, modelScale, faceSign)
local sc = modelScale or 1
faceSign = faceSign or 1
applyArc(kbt.arc, pivot, sc)
applyArc(kbt.bevel, pivot, sc, 0.023 * faceSign)
applyArc(kbt.edge, pivot, sc, 0.028 * faceSign)
-- Grip and ring sit on the +X side of the blade root. After the forearm's slight
-- clockwise cant plus this local angle, the ring sits above/right while the crescent
-- sweeps left and slightly down, matching the provided first-person clip.
for _, item in ipairs(kbt.handleSegments) do
local x = 0.055 + item.u * 0.49
local y = 0.012 * math.sin(item.u * math.pi * 2)
local tangent = math.atan2(0.012 * math.pi * 2 * math.cos(item.u * math.pi * 2), 0.49)
item.part.CFrame = pivot * CFrame.new(x * sc, y * sc, 0) * CFrame.Angles(0, 0, tangent)
end
kbt.gripPanel.CFrame = pivot * CFrame.new(0.30 * sc, 0.006 * sc, 0.053 * sc * faceSign)
for j, groove in ipairs(kbt.grooves) do
local x = 0.155 + (j-1)*0.086
local y = 0.010 + 0.010 * math.sin((j/5)*math.pi)
groove.CFrame = pivot * CFrame.new(x * sc, y * sc, 0.060 * sc * faceSign)
end
for j, seg in ipairs(kbt.ringSegments) do
local a = (j-1) / #kbt.ringSegments * math.pi * 2
local radius = 0.122
local cx, cy = 0.565 + math.cos(a)*radius, math.sin(a)*radius
-- Segmented open ring sits beyond the butt of the handle; it isn't a filled disk.
seg.CFrame = pivot * CFrame.new(cx * sc, cy * sc, 0) * CFrame.Angles(0,0,a + math.pi/2)
end
for j, band in ipairs(kbt.wraps) do
band.CFrame = pivot * CFrame.new((0.46-(j-1)*0.08) * sc, 0, 0.061 * sc * faceSign)
end
end
-- ───── Simple viewmodel hand/forearm body (no separate finger geometry) ─────
-- Keep the existing single-piece hand/forearm; only the knives are redesigned.
local hand = {details = {}}
-- Broad blocky forearm sized for the requested Minecraft-like lower-right first-person pose.
-- With the Hand Size default of 0.40 this renders as a long, thick arm that exits the bottom/right edge.
local HAND_BASE_SIZE = Vector3.new(4.0, 0.90, 0.42)
local HAND_SKIN = Color3.fromRGB(216,178,140)
do
local g = new("Model", {Name="Hand", Parent=vm})
hand.part = new("Part", {Name="ForearmViewmodel", Material=Enum.Material.SmoothPlastic, Color=HAND_SKIN,
Size=HAND_BASE_SIZE, Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Parent=g})
hand.model = g
end
-- Keep the knife meshes proportional to the edited hand. The originals are recorded once,
-- then both models are scaled from those originals (never repeatedly scaled from scaled sizes).
local knifeBaseSizes = {}
for _, knifeModel in ipairs({bfly.model, kbt.model}) do
for _, inst in ipairs(knifeModel:GetDescendants()) do
if inst:IsA("BasePart") then knifeBaseSizes[inst] = inst.Size end
end
end
local appliedKnifeScale = nil
local function applyKnifeScale(scale)
scale = math.clamp(tonumber(scale) or 0.82, 0.35, 2.25)
if appliedKnifeScale and math.abs(appliedKnifeScale - scale) < 0.001 then return end
appliedKnifeScale = scale
for part, baseSize in pairs(knifeBaseSizes) do
if part then part.Size = baseSize * scale end
end
end
local function skinColor(char)
if not char then return Color3.fromRGB(216,178,140) end
local head = char:FindFirstChild("Head")
if head and head:IsA("BasePart") then return head.Color end
local bc = char:FindFirstChild("Body Colors")
if bc then
local ok, c = pcall(function() return bc.RightArmColor3 end)
if ok and typeof(c) == "Color3" then return c end
end
local hum = char:FindFirstChildOfClass("Humanoid")
local p = (hum and hum.RigType == Enum.HumanoidRigType.R15) and char:FindFirstChild("RightHand") or char:FindFirstChild("Right Arm")
if p and p:IsA("BasePart") then return p.Color end
return Color3.fromRGB(216,178,140)
end
local function refreshHandColor()
local c = player.Character and skinColor(player.Character)
if c then
hand.part.Color = c
for _, detail in ipairs(hand.details) do
if detail.part and detail.part.Parent and not detail.shade then detail.part.Color = c end
end
end
end
player.CharacterAdded:Connect(function() task.wait(0.4); refreshHandColor() end)
task.spawn(refreshHandColor)
local insp = { active = false, t = 0, dur = 1.90 }
-- Butterfly inspect: restore the broad traveling sweep from the earlier version, but use
-- a restrained camera-relative path and separate whole-prop, blade-hinge, and free-handle
-- tracks. This avoids the previous bug where the blade-hinge angle was accidentally used
-- as the whole-model roll, making the animation look like a small hinge wobble.
-- Row format: normalized time, hand XYZ, hand pitch/yaw/roll (deg), prop XYZ (studs),
-- prop pitch/yaw/roll (deg), blade hinge angle (deg), free-handle angle (deg).
-- Poses follow the reference beats: lift, outward/left sweep, edge-on travel, reverse sweep,
-- and a catch back at the resting grip.
local butterflyInspectKeys = {
{0.000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0.065, 0.01, 0.034, -0.008, -2, -2, 6, -0.04, 0.09, -0.08, -8, -10, 18, 32, 55},
{0.130, 0.008, 0.06, -0.016, -4, -6, 12, -0.25, 0.11, -0.16, 4, -20, 62, 92, 118},
{0.205, -0.012, 0.067, -0.022, -5, -10, 16, -0.54, 0.08, -0.27, 9, -32, 115, 148, 192},
{0.285, -0.03, 0.05, -0.023, -4, -13, 14, -0.82, 0.03, -0.4, 8, -22, 175, 205, 258},
{0.370, -0.038, 0.026, -0.019, -1, -10, 9, -1.06, -0.01, -0.52, 2, -4, 240, 265, 325},
{0.465, -0.024, 0.008, -0.012, 1, -5, 4, -1.22, -0.02, -0.6, -8, 24, 300, 325, 405},
{0.560, 0.002, -0.006, -0.004, 2, 1, -3, -1.13, -0.02, -0.55, -12, 56, 365, 382, 478},
{0.655, 0.022, 0, 0.002, 1, 4, -4, -0.86, -0.01, -0.43, -7, 76, 430, 445, 535},
{0.745, 0.024, 0.025, 0.002, -1, 3, 0, -0.55, 0.02, -0.3, 2, 66, 500, 505, 592},
{0.825, 0.014, 0.041, 0, -1, 1, 2, -0.29, 0.03, -0.16, 5, 42, 585, 565, 650},
{0.910, 0.004, 0.02, 0, 0, 0, 1, -0.09, 0.01, -0.05, 2, 14, 675, 620, 700},
{0.965, 0, 0.004, 0, 0, 0, 0, -0.015, 0.002, -0.008, 0, 2, 710, 360, 720},
{1.000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 720, 360, 720},
}
-- Karambit has a separate, calmer inspect path and a steel/charcoal default finish.
local karambitInspectKeys = {
{0.000, 0.000,0.000,0.000, 0, 0, 0, 0,0,0, 0, 0, 0, 0},
{0.055, 0.010,0.022,0.000, -2, -3, 4, 0,0,0, -3, 7, -16,0},
{0.120, 0.018,0.036,0.000, -4, -7, 8, 0,0,0, -5, 14, -32,0},
{0.210, -0.016,0.054,0.000, -5,-10, 13, 0,0,0, 1, 18, -48,0},
{0.300, -0.026,0.036,0.000, -3, -6, 9, 0,0,0, 2, 8, -26,0},
{0.390, -0.010,0.012,0.000, -1, -2, 3, 0,0,0, 0, 0, 0,0},
{0.610, 0.000,0.000,0.000, 0, 0, 0, 0,0,0, 0, 0, 0,0},
{0.700, -0.025,0.008,0.000, 2, 5, -8, 0,0,0, 6, 18, -24,0},
{0.800, -0.050,-0.006,0.000, 4, 10,-16,0,0,0, 13, 54, 22,0},
{0.880, -0.035,-0.004,0.000, 3, 7,-12,0,0,0, 8, 37, 78,0},
{0.945, -0.010,0.010,0.000, 1, 2, -4, 0,0,0, 2, 10, 30,0},
{1.000, 0.000,0.000,0.000, 0, 0, 0, 0,0,0, 0, 0, 0,0},
}
local function sampleKnifeInspect(progress, isButterfly)
local keys = isButterfly and butterflyInspectKeys or karambitInspectKeys
progress = math.clamp(progress, 0, 1)
for i = 1, #keys - 1 do
local a, b = keys[i], keys[i + 1]
if progress <= b[1] then
local span = math.max(b[1] - a[1], 1e-4)
local u = math.clamp((progress - a[1]) / span, 0, 1)
-- Smooth Hermite interpolation follows the clip's rapid pose changes without
-- pausing at every sample. Angle values remain unwrapped to preserve rollover direction.
local prev = keys[math.max(1, i - 1)]
local nxt = keys[math.min(#keys, i + 2)]
local t0, t1, t2, t3 = prev[1], a[1], b[1], nxt[1]
local u2, u3 = u*u, u*u*u
local h00, h10 = 2*u3 - 3*u2 + 1, u3 - 2*u2 + u
local h01, h11 = -2*u3 + 3*u2, u3 - u2
local out = {}
for column = 2, #a do
local p1, p2 = a[column], b[column]
local m1 = (i == 1) and (p2-p1)/math.max(t2-t1, 1e-4)
or (b[column] - prev[column]) / math.max(t2-t0, 1e-4)
local m2 = (i + 1 >= #keys) and (p2-p1)/math.max(t2-t1, 1e-4)
or (nxt[column] - p1) / math.max(t3-t1, 1e-4)
local spanT = t2 - t1
out[column - 1] = h00*p1 + h10*spanT*m1 + h01*p2 + h11*spanT*m2
end
return out
end
end
local last = keys[#keys]
local out = {}
for column = 2, #last do out[column - 1] = last[column] end
return out
end
local function updateHandDetails(scale)
for _, detail in ipairs(hand.details) do
local p = detail.part
if p and p.Parent then
p.Size = detail.baseSize * scale
p.CFrame = hand.part.CFrame * CFrame.new(detail.offset * scale)
* CFrame.Angles(detail.angles.X, detail.angles.Y, detail.angles.Z)
end
end
end
local function placeHand(pivot)
-- Editor offsets remain camera-local; inspect tricks now animate the wrist and hand too.
local scale = math.clamp(tonumber(feat.handScale) or 0.4, 0.35, 2.25)
local ox = math.clamp(tonumber(feat.handOffsetX) or 0.82, -2.5, 2.5)
local oy = math.clamp(tonumber(feat.handOffsetY) or -0.04, -1.5, 1.5)
local oz = math.clamp(tonumber(feat.handOffsetZ) or 0.43, -1.5, 1.5)
hand.part.Size = HAND_BASE_SIZE * scale
local wristCompensation = 0
-- A slight clockwise roll places the wrist at lower-right and the grip end toward screen center.
-- Default auto-hold pose: forearm enters from the lower-right and slopes down/right,
-- with its inner end at the knife grip. The editor offsets remain additive so users can tune it.
local basePose = pivot
* CFrame.new(0.90 + ox, -0.20 + oy, 0.14 + wristCompensation + oz)
* CFrame.Angles(math.rad(-2), math.rad(7), math.rad(-28))
local inspectPose = CFrame.identity
if insp.active and feat.knifeOut then
local progress = math.clamp(insp.t / insp.dur, 0, 1)
local isButterfly = not string.find(string.lower(tostring(feat.knifeModel or "butterfly")), "karambit", 1, true)
local motion = sampleKnifeInspect(progress, isButterfly)
-- The reference raises the forearm, sweeps it inward during the flip, then returns it
-- to the original lower-right rest pose. The knife uses the same keyframe sample below.
inspectPose = CFrame.new(motion[1], motion[2], motion[3])
* CFrame.Angles(math.rad(motion[4]), math.rad(motion[5]), math.rad(motion[6]))
end
hand.part.CFrame = basePose * inspectPose
updateHandDetails(scale)
end
-- ───── Fog Hand: smoke + glow outline (recreates the cyan foggy look) ─────
local fogAtt = new("Attachment", {Position = Vector3.new(0.5, 0, 0), Parent = hand.part})
local fog = new("ParticleEmitter", {Enabled=false, Texture="rbxassetid://243098098", Rate=16, Lifetime=NumberRange.new(0.5,1), Speed=NumberRange.new(0.3,1), SpreadAngle=Vector2.new(60,60), EmissionDirection=Enum.NormalId.Top,
Color=ColorSequence.new(Color3.new(1,1,1), visualColor("fogHand")), Size=NumberSequence.new({NumberSequenceKeypoint.new(0,0.3),NumberSequenceKeypoint.new(0.4,0.6),NumberSequenceKeypoint.new(1,0)}),
Transparency=NumberSequence.new({NumberSequenceKeypoint.new(0,0.3),NumberSequenceKeypoint.new(1,1)}), LightEmission=0.8, Parent=fogAtt})
local fogGlow = new("Highlight", {Enabled=false, FillTransparency=1, OutlineColor=visualColor("fogHand"), OutlineTransparency=0.05, DepthMode=Enum.HighlightDepthMode.AlwaysOnTop, Adornee=vm, Parent=vm})
local toolStyleGlow = new("Highlight", {Name="OwoToolStyleOutline", Enabled=false, FillTransparency=1, OutlineColor=visualColor("hand"), OutlineTransparency=0.02, DepthMode=Enum.HighlightDepthMode.AlwaysOnTop, Adornee=vm, Parent=vm})
local handEditorGlow = new("Highlight", {Name="OwoHandEditorGlow", Enabled=false, FillTransparency=1, OutlineColor=Color3.fromRGB(255,220,105), OutlineTransparency=0.03, DepthMode=Enum.HighlightDepthMode.AlwaysOnTop, Adornee=hand.model, Parent=vm})
local toolBase = {}
for _, inst in ipairs(vm:GetDescendants()) do
if inst:IsA("BasePart") then toolBase[inst] = {Material=inst.Material, Color=inst.Color, Transparency=inst.Transparency} end
end
-- Normalize model names from old saved configs too (e.g. "Butterfly Knife",
-- "BUTTERFLY", or "Karambit"). Anything that does not explicitly name a
-- karambit defaults to the butterfly, preventing stale config labels showing the wrong model.
local function selectedKnifeModel()
local raw = string.lower(tostring(feat.knifeModel or "butterfly"))
if string.find(raw, "karambit", 1, true) then
return "karambit"
end
return "butterfly"
end
-- Cache the active model. Reparenting hundreds of Parts on every RenderStepped
-- caused flicker/visibility glitches and made the knife appear to jump or vanish.
local activeKnifeModelParent = false
local function syncKnifeModelParents(wantKnife)
local selected = selectedKnifeModel()
local desired = wantKnife and selected or nil
if activeKnifeModelParent == desired then
return selected
end
if bfly.model.Parent ~= nil then bfly.model.Parent = nil end
if kbt.model.Parent ~= nil then kbt.model.Parent = nil end
if desired == "karambit" then
kbt.model.Parent = vm
elseif desired == "butterfly" then
bfly.model.Parent = vm
end
activeKnifeModelParent = desired
return selected
end
local function applyKnifeSkin()
local modelName = selectedKnifeModel()
local skin = modelName == "karambit" and (feat.karambitSkin or "Default") or (feat.butterflyKnifeSkin or "Default")
local palettes = {
Default={blade=STEEL, handle=DARK, metal=Color3.fromRGB(150,150,156), mat=Enum.Material.Metal},
["Candy Cane"]={blade=Color3.fromRGB(246,246,242), handle=Color3.fromRGB(194,28,48), metal=Color3.fromRGB(246,246,242), mat=Enum.Material.SmoothPlastic},
Crimson={blade=Color3.fromRGB(145,18,39), handle=Color3.fromRGB(34,20,28), metal=Color3.fromRGB(231,55,67), mat=Enum.Material.Metal},
Sapphire={blade=Color3.fromRGB(67,166,255), handle=Color3.fromRGB(14,38,83), metal=Color3.fromRGB(135,219,255), mat=Enum.Material.Neon},
Golden={blade=Color3.fromRGB(255,192,55), handle=Color3.fromRGB(97,60,15), metal=Color3.fromRGB(255,225,115), mat=Enum.Material.Metal},
["Neon Circuit"]={blade=Color3.fromRGB(65,255,210), handle=Color3.fromRGB(17,27,34), metal=Color3.fromRGB(65,255,210), mat=Enum.Material.Neon},
Void={blade=Color3.fromRGB(106,58,174), handle=Color3.fromRGB(20,12,31), metal=Color3.fromRGB(207,115,255), mat=Enum.Material.ForceField},
Toxic={blade=Color3.fromRGB(130,220,40), handle=Color3.fromRGB(28,42,22), metal=Color3.fromRGB(210,255,87), mat=Enum.Material.Neon},
}
local pal = palettes[skin] or palettes.Default
-- The Karambit default is steel/silver with a charcoal grip, never the gold palette.
-- Older configs that saved "Golden" for the Karambit are normalized to Default below.
if modelName == "karambit" and skin == "Golden" then
skin = "Default"
feat.karambitSkin = "Default"
end
if skin == "Default" then
if modelName == "karambit" then
pal = {blade=Color3.fromRGB(107, 113, 123), handle=Color3.fromRGB(31, 32, 37), metal=Color3.fromRGB(190, 196, 204), mat=Enum.Material.Metal}
else
pal = {blade=Color3.fromRGB(72, 76, 83), handle=Color3.fromRGB(17, 18, 22), metal=Color3.fromRGB(170, 176, 184), mat=Enum.Material.Metal}
end
end
local custom = feat.visualColors and feat.visualColors.knife
-- A saved shared color must not accidentally turn the Karambit's Default skin gold.
-- Explicitly selected non-default skins still use their own palette, and custom color
-- remains available for other knife skins.
if modelName == "karambit" and skin == "Default" then custom = nil end
-- Butterfly blade has a swept curved clip-point profile and twin split handles.
for i, item in ipairs(bfly.bladeSections) do
local part = item.part
part.Material = pal.mat; part.Color = custom or ((skin == "Candy Cane" and i % 2 == 0) and Color3.fromRGB(196,25,47) or pal.blade)
end
bfly.tip.Material = pal.mat
bfly.tip.Color = (skin == "Candy Cane" and not custom) and Color3.fromRGB(196,25,47) or (custom or pal.blade)
for _, item in ipairs(bfly.spineSegments) do item.part.Material = Enum.Material.Metal; item.part.Color = custom or pal.metal end
for _, item in ipairs(bfly.edgeSegments) do item.part.Material = Enum.Material.Metal; item.part.Color = custom or pal.metal end
for _, item in ipairs(bfly.fullerSegments) do item.part.Material = Enum.Material.Metal; item.part.Color = custom or Color3.fromRGB(108,115,126) end
for _, h in ipairs(bfly.handles) do
for _, handlePart in ipairs(h.segments or {h.part}) do
handlePart.Material = (skin == "Candy Cane" and not custom) and Enum.Material.SmoothPlastic or pal.mat
handlePart.Color = custom or pal.handle
end
h.bolt.Material = Enum.Material.Metal; h.bolt.Color = pal.metal
end
for _, item in ipairs(bfly.endCaps) do
item.part.Material = Enum.Material.SmoothPlastic
item.part.Color = custom or pal.handle
end
for _, item in ipairs(bfly.screws) do
item.part.Material = Enum.Material.Metal
item.part.Color = pal.metal
end
for i, w in ipairs(bfly.wraps) do
w.part.Material = Enum.Material.SmoothPlastic
w.part.Color = (skin == "Candy Cane" and not custom) and (i % 2 == 0 and Color3.fromRGB(250,248,240) or Color3.fromRGB(190,22,43)) or (custom or pal.metal)
end
-- Karambit has a deep crescent blade, raised bevel line, textured grip and open segmented ring.
for i, item in ipairs(kbt.arc) do
item.part.Material = pal.mat
item.part.Color = (skin == "Candy Cane" and not custom) and (i % 2 == 0 and Color3.fromRGB(198,24,45) or Color3.fromRGB(250,248,240)) or (custom or pal.blade)
end
for _, item in ipairs(kbt.bevel) do
item.part.Material = Enum.Material.Metal
item.part.Color = custom or pal.metal
end
for _, item in ipairs(kbt.edge) do
item.part.Material = Enum.Material.Metal
item.part.Color = custom or pal.metal
end
for _, item in ipairs(kbt.handleSegments or {}) do
item.part.Material = Enum.Material.SmoothPlastic
item.part.Color = custom or pal.handle
end
kbt.gripPanel.Material = Enum.Material.SmoothPlastic
kbt.gripPanel.Color = custom or pal.handle
for i, groove in ipairs(kbt.grooves) do
groove.Material = Enum.Material.SmoothPlastic
groove.Color = custom or (skin == "Default" and modelName == "karambit" and Color3.fromRGB(95,100,109) or Color3.fromRGB(26,26,29))
end
for _, seg in ipairs(kbt.ringSegments) do
seg.Material = Enum.Material.Metal
seg.Color = custom or pal.metal
end
for i, band in ipairs(kbt.wraps) do
band.Material = Enum.Material.SmoothPlastic
band.Color = (skin == "Candy Cane" and not custom) and (i % 2 == 0 and Color3.fromRGB(250,248,240) or Color3.fromRGB(198,24,45)) or (custom or pal.metal)
end
-- Keep styles (Ghosted / Neon Edge / Metallic) as a finishing pass over the chosen skin.
local style = feat.visualStyles.knife or "Default"
local chosen = modelName == "karambit" and kbt.model or bfly.model
-- Always clear the previous style first; otherwise Ghosted/Neon transparency can stick
-- when the player switches back to Default or changes knife models.
for _, part in ipairs(chosen:GetDescendants()) do
if part:IsA("BasePart") then
part.Transparency = 0
if style == "Ghosted" then
part.Material = Enum.Material.ForceField; part.Transparency = 0.34
elseif style == "Neon Edge" then
part.Material = Enum.Material.Neon; part.Color = custom or pal.blade; part.Transparency = 0.08
elseif style == "Metallic" then
part.Material = Enum.Material.Metal; part.Transparency = 0
end
end
end
end
local function applyFirstPersonStyle()
local handStyle = feat.visualStyles.hand or "Default"
local knifeStyle = feat.visualStyles.knife or "Default"
toolStyleGlow.OutlineColor = (handStyle == "Neon Edge" and visualColor("hand")) or visualColor("knife")
toolStyleGlow.Enabled = (handStyle == "Neon Edge" and feat.handOut) or (knifeStyle == "Neon Edge" and feat.knifeOut)
for part, baseProps in pairs(toolBase) do
if part and part.Parent then
if part:IsDescendantOf(hand.model) then
if handStyle == "Ghosted" then
part.Material = Enum.Material.ForceField
part.Color = visualColor("hand"):Lerp(Color3.new(1,1,1),0.45)
part.Transparency = math.max(baseProps.Transparency,0.34)
elseif handStyle == "Neon Edge" then
part.Material = Enum.Material.Neon; part.Color = visualColor("hand"); part.Transparency = 0.08
elseif handStyle == "Metallic" then
part.Material = Enum.Material.Metal; part.Color = Color3.fromRGB(155,172,190); part.Transparency = baseProps.Transparency
else
part.Material = baseProps.Material; part.Color = baseProps.Color; part.Transparency = baseProps.Transparency
end
end
end
end
applyKnifeSkin()
end
Fn.applyHandColors = function()
local fogColor = visualColor("fogHand")
fog.Color = ColorSequence.new(Color3.new(1,1,1), fogColor)
fogGlow.OutlineColor = fogColor
applyFirstPersonStyle()
end
-- ───── Echo Hand: fading afterimages ─────
local echoFolder = new("Folder", {Name="OwoHandEcho", Parent=workspace})
local echoAcc = 0
local function spawnEcho()
local style = feat.visualStyles.echoHand or "Soft Echo"
local copies = style == "Stacked Echo" and 2 or 1
local life = style == "Long Echo" and 0.78 or (style == "Wire Echo" and 0.24 or 0.38)
for _, g in ipairs({bfly.model, kbt.model, hand.model}) do
if g.Parent then
for _, part in ipairs(g:GetChildren()) do
if part:IsA("BasePart") and part.Transparency < 1 then
for copy = 1, copies do
local cls = part.ClassName == "WedgePart" and "WedgePart" or "Part"
local mat = style == "Wire Echo" and Enum.Material.Neon or Enum.Material.ForceField
local echoColor = visualColor("echoHand")
local col = style == "Wire Echo" and echoColor or echoColor:Lerp(Color3.new(1,1,1),style=="Long Echo" and 0.58 or 0.3)
local cf = part.CFrame * CFrame.new(copy == 2 and 0.1 or 0, copy == 2 and 0.06 or 0, style == "Stacked Echo" and copy*0.06 or 0)
local e = new(cls, {Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false,
Material=mat, Color=col,
Size=part.Size * (style == "Wire Echo" and 1.025 or (copy == 2 and 0.97 or 1)), CFrame=cf,
Transparency=style == "Long Echo" and 0.2 or (style == "Wire Echo" and 0.5 or 0.35), Parent=echoFolder})
TS:Create(e, TweenInfo.new(life, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {Transparency=1, Size=e.Size*1.06}):Play()
task.delay(life+0.05, function() if e then e:Destroy() end end)
end
end
end
end
end
end
-- The inspect is a full flourish; the hand and knife are animated together from the same grip.
local lastModel = nil
local visible = false
local function show(on)
if on == visible then return end
visible = on
vm.Parent = on and workspace or nil
if not on then fog.Enabled = false; fogGlow.Enabled = false end
end
local function ease(x) return x < 0.5 and 4*x*x*x or 1 - (-2*x+2)^3/2 end
local vmWalkClock = 0
local lastCameraCFrame = nil
local function placeBase(dt)
if not camera then return end
vmWalkClock += dt
local char = player.Character
local hum = char and char:FindFirstChildOfClass("Humanoid")
local hrp = char and char:FindFirstChild("HumanoidRootPart")
local moveAlpha = 0
local lateralAlpha = 0
if hum and hrp and hum.Health > 0 then
local velocity = hrp.AssemblyLinearVelocity
local horizontalSpeed = Vector3.new(velocity.X, 0, velocity.Z).Magnitude
moveAlpha = math.clamp(horizontalSpeed / math.max(hum.WalkSpeed, 1), 0, 1.25)
local localVelocity = camera.CFrame:VectorToObjectSpace(Vector3.new(velocity.X, 0, velocity.Z))
lateralAlpha = math.clamp(localVelocity.X / math.max(hum.WalkSpeed, 1), -1, 1)
end
-- First-person props should follow the camera, but visibly react to locomotion rather
-- than being a perfectly glued overlay. Velocity bob, side sway, and camera-turn lag
-- are all smoothed and remain independent of the inspect animation.
local strideRate = 7.5 + moveAlpha * 5.0
local stride = vmWalkClock * strideRate
local bobX = math.sin(stride) * 0.035 * moveAlpha - lateralAlpha * 0.035
local bobY = (math.abs(math.cos(stride)) * 0.045 - 0.018) * moveAlpha
local bobZ = math.cos(stride * 0.5) * 0.018 * moveAlpha
local turnPitch, turnYaw = 0, 0
if lastCameraCFrame then
local delta = lastCameraCFrame:ToObjectSpace(camera.CFrame)
local dx, dy = delta:ToOrientation()
turnPitch = math.clamp(-dx * 0.70, math.rad(-5), math.rad(5))
turnYaw = math.clamp(-dy * 0.70, math.rad(-6), math.rad(6))
end
lastCameraCFrame = camera.CFrame
local base = camera.CFrame
* CFrame.new(0.18 + bobX, -0.43 + bobY, -1.92 + bobZ)
* CFrame.Angles(math.rad(-5) + turnPitch, math.rad(10) + turnYaw, math.rad(1) - lateralAlpha * math.rad(3))
root.CFrame = root.CFrame:Lerp(base, 1 - math.exp(-dt * 12))
end
local knifeRenderConnection = RS.RenderStepped:Connect(function(dt)
local char = player.Character
local head = char and char:FindFirstChild("Head")
-- Knife cosmetics are FIRST-PERSON ONLY. Never attach the cosmetic model to the
-- world character/right arm in third-person. Support both forced first-person mode
-- and classic camera zoomed all the way into the head.
local camNow = workspace.CurrentCamera or camera
local cameraDistance = (head and camNow and (camNow.CFrame.Position - head.Position).Magnitude) or math.huge
local fp = player.CameraMode == Enum.CameraMode.LockFirstPerson or (head ~= nil and cameraDistance < 1.4)
local wantKnife = feat.knifeOut and char ~= nil and fp
local wantHand = (feat.handOut or feat.handEditMode or feat.knifeOut) and fp
show(wantKnife or wantHand)
local selectedModel = syncKnifeModelParents(wantKnife)
if lastModel ~= selectedModel then
-- Never continue an inspect animation from a different model.
insp.active = false
insp.t = 0
lastModel = selectedModel
end
if not (wantKnife or wantHand) then
hand.model.Parent = nil
handEditorGlow.Enabled = false
return
end
if insp.active and wantKnife then
insp.t = math.min(insp.t + dt, insp.dur)
end
placeBase(dt)
hand.model.Parent = wantHand and vm or nil
handEditorGlow.Enabled = wantHand and feat.handEditMode
fog.Enabled = wantHand and feat.fogHand
fogGlow.Enabled = (wantKnife or wantHand) and feat.fogHand
if wantKnife or wantHand then applyFirstPersonStyle() end
local fogStyle = feat.visualStyles.fogHand or "Smoke Puff"
if fogStyle == "Spiral Mist" then
fog.Rate=26; fog.Lifetime=NumberRange.new(0.9,1.5); fog.Speed=NumberRange.new(0.8,1.6); fog.SpreadAngle=Vector2.new(35,35); fog.Acceleration=Vector3.new(0,1.4,0); fog.RotSpeed=NumberRange.new(-160,160); fog.Size=NumberSequence.new({NumberSequenceKeypoint.new(0,0.15),NumberSequenceKeypoint.new(0.5,0.8),NumberSequenceKeypoint.new(1,0)})
elseif fogStyle == "Spark Fog" then
fog.Rate=34; fog.Lifetime=NumberRange.new(0.3,0.7); fog.Speed=NumberRange.new(1.5,4); fog.SpreadAngle=Vector2.new(150,150); fog.Acceleration=Vector3.new(0,0.2,0); fog.RotSpeed=NumberRange.new(-50,50); fog.Size=NumberSequence.new({NumberSequenceKeypoint.new(0,0.08),NumberSequenceKeypoint.new(0.35,0.2),NumberSequenceKeypoint.new(1,0)})
elseif fogStyle == "Heavy Vapor" then
fog.Rate=48; fog.Lifetime=NumberRange.new(1.2,2.0); fog.Speed=NumberRange.new(0.1,0.6); fog.SpreadAngle=Vector2.new(100,100); fog.Acceleration=Vector3.new(0,0.8,0); fog.RotSpeed=NumberRange.new(-25,25); fog.Size=NumberSequence.new({NumberSequenceKeypoint.new(0,0.5),NumberSequenceKeypoint.new(0.6,1.2),NumberSequenceKeypoint.new(1,0)})
else
fog.Rate=16; fog.Lifetime=NumberRange.new(0.5,1); fog.Speed=NumberRange.new(0.3,1); fog.SpreadAngle=Vector2.new(60,60); fog.Acceleration=Vector3.new(0,0.4,0); fog.RotSpeed=NumberRange.new(-45,45); fog.Size=NumberSequence.new({NumberSequenceKeypoint.new(0,0.3),NumberSequenceKeypoint.new(0.4,0.6),NumberSequenceKeypoint.new(1,0)})
end
fog.Color = ColorSequence.new(Color3.new(1,1,1), fogStyle == "Spark Fog" and Color3.fromRGB(255,245,190) or visualColor("fogHand"))
-- Place the hand, then attach the knife handle's CENTER to the camera-facing side
-- of the hand. The old offset put the model behind the hand and made the karambit
-- look like it floated away. A compensated pivot keeps the grip anchored during tricks.
local handPose = root.CFrame * CFrame.new(0, 0, -0.35)
if wantHand then placeHand(handPose) end
if wantKnife then
-- Knife size is independent of the hand-size slider. The old code reused handScale
-- (default 0.40), shrinking the knife to 40% and making it hard to see.
-- Viewmodel scale is intentionally independent of the hand editor slider, but
-- sized for the new camera depth so the knife does not dwarf the hand or crop out.
local knifeScale = selectedKnifeModel() == "butterfly" and 0.54 or 0.58
applyKnifeScale(knifeScale)
local isButterfly = selectedKnifeModel() == "butterfly"
-- The local model grip is the actual handle center, not the blade root. The forearm's
-- distal end is used as the hand-contact point, and the knife's inner surface is placed
-- flush against the camera-facing hand surface. Knife scale remains independent of
-- hand scale.
local modelDepth = isButterfly and ((0.083 + 0.067 * 0.5) * knifeScale)
or ((0.095 * 0.5) * knifeScale)
local faceSign = 1
local gripAnchor
if wantHand then
-- The single-piece forearm ends at its negative-X tip; put the handle center
-- there, on the camera-facing surface, so it visibly touches the hand.
-- Place the grip at the arm's inner/upper-left end, not near its center.
-- This is what creates the screenshot pose: blade points inward/up-left while the
-- forearm runs diagonally out of frame toward the lower-right.
local handTipX = -hand.part.Size.X * 0.50
local handFace = hand.part.Size.Z * 0.5
gripAnchor = hand.part.CFrame * CFrame.new(handTipX, 0, faceSign * (handFace + modelDepth - 0.001))
else
-- Third-person: resolve the real right hand in priority order. Prefer direct
-- body parts before recursive matches so an accessory/viewmodel part with a
-- similar name can never pull the knife onto the wrong side of the screen.
local gripPart = char:FindFirstChild("RightHand")
local usingR15Hand = gripPart ~= nil and gripPart:IsA("BasePart")
if not (gripPart and gripPart:IsA("BasePart")) then
gripPart = char:FindFirstChild("Right Arm")
usingR15Hand = false
end
if not (gripPart and gripPart:IsA("BasePart")) then
gripPart = char:FindFirstChild("RightLowerArm")
usingR15Hand = false
end
if not (gripPart and gripPart:IsA("BasePart")) then
gripPart = char:FindFirstChild("RightUpperArm")
usingR15Hand = false
end
if not (gripPart and gripPart:IsA("BasePart")) then
-- Some experiences wrap body parts in nested rig Models, so search the
-- remaining legitimate right-arm parts too, not accessories or the camera.
for _, wantedName in ipairs({"RightHand", "Right Arm", "RightLowerArm", "RightUpperArm"}) do
for _, candidate in ipairs(char:GetDescendants()) do
if candidate:IsA("BasePart") and candidate.Name == wantedName then
gripPart = candidate
usingR15Hand = wantedName == "RightHand"
break
end
end
if gripPart and gripPart:IsA("BasePart") then break end
end
end
if gripPart and gripPart:IsA("BasePart") then
-- Use the avatar's own grip attachment when available. It locates the handle
-- at the actual palm/finger grip rather than the center of the forearm.
local gripAttachment = gripPart:FindFirstChild("RightGripAttachment")
local attachmentOffset = gripAttachment and gripAttachment.Position
or Vector3.new(0, usingR15Hand and (-gripPart.Size.Y * 0.16) or (-gripPart.Size.Y * 0.38), 0)
local palmFace = gripPart.Size.Z * 0.5
local localGrip = Vector3.new(
attachmentOffset.X,
attachmentOffset.Y,
attachmentOffset.Z + faceSign * (palmFace + modelDepth - 0.003)
)
local handBasis = gripPart.CFrame - gripPart.CFrame.Position
local gripPosition = (gripPart.CFrame * CFrame.new(localGrip)).Position
gripAnchor = CFrame.new(gripPosition) * handBasis
else
-- Cosmetic viewmodel is first-person-only. If the viewmodel hand is not active,
-- never attach the knife to the world character or invent a floating fallback.
return
end
end
-- Auto-hold pose from the supplied reference: both blades point diagonally toward
-- the upper-left from a grip at the top/inner end of the forearm. Since the hand itself
-- is canted clockwise, the butterfly's model-space axis needs a near-half-turn offset.
local idleRotation = isButterfly and CFrame.Angles(0, 0, math.rad(188)) or CFrame.Angles(0, 0, math.rad(17))
local gripCenterOffset = (isButterfly and 0.375 or -0.30) * knifeScale
local gripCurveCompensation = 0 -- both bowed handles curve outward symmetrically, so their midpoint is the true grip point
-- Both models define their handle center so the calculated gripAnchor is the actual
-- hand contact point, even while the model is being inspected.
local pivot = gripAnchor * idleRotation * CFrame.new(gripCenterOffset, gripCurveCompensation, 0)
local butterflyHandleAngles = {0, 0}
local butterflyBladeAngle = 0
if insp.active then
local progress = math.clamp(insp.t / insp.dur, 0, 1)
local butterflySelected = selectedKnifeModel() == "butterfly"
local motion = sampleKnifeInspect(progress, butterflySelected)
-- The prop has its own traveling path, while the hand has its own motion track.
-- Keep all angle tracks distinct: motion[10..12] are whole-prop pitch/yaw/roll,
-- motion[13] is blade hinge angle, and motion[14] is free-handle angle.
local knifeX, knifeY, knifeZ = motion[7], motion[8], motion[9]
local knifePitch, knifeYaw, knifeRoll = motion[10], motion[11], motion[12]
if butterflySelected then
local heldIndex, freeIndex = 1, 2
butterflyBladeAngle = motion[13]
butterflyHandleAngles[heldIndex] = 0
butterflyHandleAngles[freeIndex] = math.rad(motion[14])
end
pivot = gripAnchor
* CFrame.new(knifeX, knifeY, knifeZ)
* CFrame.Angles(math.rad(knifePitch), math.rad(knifeYaw), math.rad(knifeRoll))
* idleRotation
* CFrame.new(gripCenterOffset, gripCurveCompensation, 0)
if progress >= 1 then
insp.active = false
butterflyHandleAngles = {0, 0}
butterflyBladeAngle = 0
end
end
if selectedKnifeModel() == "butterfly" then
placeButterfly(pivot, knifeScale, butterflyHandleAngles, faceSign, butterflyBladeAngle)
else
placeKarambit(pivot, knifeScale, faceSign)
end
end
if feat.echoHand then
echoAcc += dt
if echoAcc >= 0.1 then echoAcc = 0; spawnEcho() end
else
echoAcc = 0
end
end)
pcall(function() knifeRuntime.__OWO_KNIFE_RENDER = knifeRenderConnection end)
Fn.knifeInspect = function()
if not feat.knifeOut then return end
local model = selectedKnifeModel()
-- Butterfly inspect is a short, grip-anchored blade/free-handle rollover; the karambit has its own separate inspect.
insp.dur = model == "butterfly" and 1.90 or 5.75
insp.active = true; insp.t = 0
if model == "butterfly" then
notify("Butterfly Inspect", "Lift • Outward Sweep • Reverse Catch")
else
notify("Karambit Inspect", "Hooked Sweep • Hold • Late Roll")
end
playUiSound("click")
end
end
-- ══════════════════════════════════════════════════════════════
-- BUTTERFLIES + METEORS
-- ══════════════════════════════════════════════════════════════
do
local bFolder = new("Folder", {Name="OwoButterflies", Parent=workspace})
local butterflies = {}
local lastSpawnB = 0
local function spawnButterfly()
local hrp = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
local base = hrp and hrp.Position or camera.CFrame.Position
local pos = base + Vector3.new(math.random(-30, 30), math.random(2, 14), math.random(-30, 30))
local style = feat.visualStyles.butterflies or "Float"
local model = new("Model", {Name="OwoButterfly_"..style:gsub("%s",""), Parent=bFolder})
local bodySize = style == "Burst" and Vector3.new(0.12,0.12,0.55) or Vector3.new(0.15,0.15,0.4)
local mat = style == "Drift" and Enum.Material.Glass or Enum.Material.Neon
local baseColor = feat.visualColors.butterflies or (style == "Swirl" and Color3.fromRGB(110,220,255) or (style == "Burst" and Color3.fromRGB(255,190,70) or EFFECT_COLOR))
local body = new("Part", {Size=bodySize, Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Material=mat, Color=baseColor, Transparency=0.1, CFrame=CFrame.new(pos), Parent=model})
local wingShape = (style == "Float" or style == "Drift") and Enum.PartType.Ball or Enum.PartType.Block
local wingSize = style == "Burst" and Vector3.new(0.78,0.07,0.32) or (style == "Swirl" and Vector3.new(0.36,0.04,0.85) or Vector3.new(0.72,0.09,0.58))
local wl = new("Part", {Shape=wingShape,Size=wingSize, Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Material=mat, Color=baseColor:Lerp(Color3.new(1,1,1),0.18), Transparency=style=="Drift" and 0.45 or 0.12, CFrame=CFrame.new(pos) * CFrame.new(-0.4,0,0), Parent=model})
local wr = new("Part", {Shape=wingShape,Size=wingSize, Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Material=mat, Color=baseColor:Lerp(Color3.new(1,1,1),0.18), Transparency=style=="Drift" and 0.45 or 0.12, CFrame=CFrame.new(pos) * CFrame.new(0.4,0,0), Parent=model})
butterflies[#butterflies+1] = {model=model, body=body, wingL=wl, wingR=wr, base=pos, ph=math.random() * 6.28, sp=style=="Burst" and (1.0+math.random()) or (0.5 + math.random() * 0.7), style=style}
end
RS.Heartbeat:Connect(function(dt)
local requestedStyle = feat.visualStyles.butterflies or "Float"
for i = #butterflies, 1, -1 do
if butterflies[i].style ~= requestedStyle then
if butterflies[i].model then butterflies[i].model:Destroy() end
table.remove(butterflies, i)
end
end
if feat.butterflies then
lastSpawnB += dt
if #butterflies < feat.butterflyCount and lastSpawnB > 0.3 then lastSpawnB = 0; spawnButterfly() end
elseif #butterflies > 0 then
for _, b in ipairs(butterflies) do b.model:Destroy() end
butterflies = {}
end
local t = tick()
for _, b in ipairs(butterflies) do
local offset = Vector3.new(math.sin(t * b.sp + b.ph) * 3, math.sin(t * b.sp * 1.7 + b.ph) * 1.2, math.cos(t * b.sp * 0.8 + b.ph) * 3)
local pos = b.base + offset
local baseColor = feat.visualColors.butterflies or (b.style == "Swirl" and Color3.fromRGB(110,220,255) or (b.style == "Burst" and Color3.fromRGB(255,190,70) or EFFECT_COLOR))
b.body.Color = baseColor
b.wingL.Color = baseColor:Lerp(Color3.new(1,1,1),0.18)
b.wingR.Color = baseColor:Lerp(Color3.new(1,1,1),0.18)
b.body.CFrame = CFrame.lookAt(pos, pos + Vector3.new(math.cos(t * b.sp + b.ph), 0.3, math.sin(t * b.sp + b.ph)))
local flap = math.sin(t * 8 + b.ph) * 0.6
local fold = b.style == "Swirl" and flap*1.45 or (b.style == "Drift" and flap*0.45 or flap)
b.wingL.CFrame = b.body.CFrame * CFrame.new(-0.15, 0, 0) * CFrame.Angles(0, 0, fold)
b.wingR.CFrame = b.body.CFrame * CFrame.new(0.15, 0, 0) * CFrame.Angles(0, 0, -fold)
end
end)
local meteorAcc = 0
local mrp = RaycastParams.new(); mrp.FilterType = Enum.RaycastFilterType.Exclude
local function explode(pos)
local fl = new("Part",{Shape=Enum.PartType.Ball,Anchored=true,CanCollide=false,CanQuery=false,CanTouch=false,CastShadow=false,Material=Enum.Material.Neon,Color=visualColor("meteor"):Lerp(Color3.new(1,1,1),0.5),Size=Vector3.new(3,3,3),Transparency=0.1,CFrame=CFrame.new(pos),Parent=workspace})
TS:Create(fl, TweenInfo.new(sdur(0.5), Enum.EasingStyle.Quint, Enum.EasingDirection.Out), {Size=Vector3.new(26,26,26), Transparency=1}):Play()
local pe = new("ParticleEmitter",{Texture="rbxassetid://243098098",Rate=0,Lifetime=NumberRange.new(0.6,1.4),Speed=NumberRange.new(14,40),SpreadAngle=Vector2.new(70,70),EmissionDirection=Enum.NormalId.Top,Drag=2,Acceleration=Vector3.new(0,-30,0),Color=ColorSequence.new(Color3.new(1,1,1),visualColor("meteor")),Size=NumberSequence.new({NumberSequenceKeypoint.new(0,1.3),NumberSequenceKeypoint.new(1,0)}),Transparency=NumberSequence.new({NumberSequenceKeypoint.new(0,0),NumberSequenceKeypoint.new(1,1)}),LightEmission=1,Parent=fl})
pe:Emit(70)
local cam = workspace.CurrentCamera
if (cam.CFrame.Position - pos).Magnitude < 90 then Fn.triggerShake(3) end
task.delay(1.6, function() fl:Destroy() end)
end
local function spawnMeteor()
local cam = workspace.CurrentCamera
local EC = EFFECT_COLOR
local meteorStyle = feat.visualStyles.meteor or "Classic Meteor"
local pos = cam.CFrame.Position + cam.CFrame.LookVector * 220 + Vector3.new(math.random(-170, 170), math.random(170, 260), math.random(-170, 170))
local dir = Vector3.new((math.random() - 0.5) * 0.9, -1, (math.random() - 0.5) * 0.9).Unit
local size = 2 + math.random() * 2.2
local meteorShape = meteorStyle == "Rock Shards" and Enum.PartType.Block or Enum.PartType.Ball
local meteorMaterial = meteorStyle == "Rock Shards" and Enum.Material.Slate or (meteorStyle == "Comet Tail" and Enum.Material.ForceField or Enum.Material.Neon)
local m = new("Part",{Shape=meteorShape,Size=meteorStyle=="Plasma Core" and Vector3.new(size*0.7,size*1.3,size*0.7) or Vector3.new(size,size,size),Anchored=true,CanCollide=false,CanQuery=false,CanTouch=false,CastShadow=false,Material=meteorMaterial,Color=meteorStyle=="Rock Shards" and Color3.fromRGB(90,80,75) or EC:Lerp(Color3.new(1,1,1),0.65),CFrame=CFrame.new(pos),Parent=workspace})
new("PointLight",{Color=EC,Range=meteorStyle=="Plasma Core" and 58 or 40,Brightness=meteorStyle=="Plasma Core" and 6 or 4,Parent=m})
local bb = new("BillboardGui",{Size=UDim2.new(size*7,0,size*7,0),LightInfluence=0,AlwaysOnTop=false,Adornee=m,Parent=m})
for k = 1, 5 do
local sc = k / 5
local fr = new("Frame",{AnchorPoint=Vector2.new(0.5,0.5),Position=UDim2.fromScale(0.5,0.5),Size=UDim2.fromScale(sc,sc),BackgroundColor3=EC,BackgroundTransparency=0.9,BorderSizePixel=0,Parent=bb})
new("UICorner",{CornerRadius=UDim.new(0.5,0),Parent=fr})
end
local a0 = new("Attachment",{Parent=m,Position=Vector3.new(0,size*0.5,0)})
local a1 = new("Attachment",{Parent=m,Position=Vector3.new(0,-size*0.5,0)})
new("Trail",{Attachment0=a0,Attachment1=a1,Lifetime=meteorStyle=="Comet Tail" and 2.8 or (meteorStyle=="Rock Shards" and 0.7 or 1.5),LightEmission=1,LightInfluence=0,FaceCamera=true,
Color=ColorSequence.new({ColorSequenceKeypoint.new(0,Color3.new(1,1,1)),ColorSequenceKeypoint.new(0.35,EC),ColorSequenceKeypoint.new(1,EC:Lerp(Color3.new(0,0,0),0.5))}),
Transparency=NumberSequence.new({NumberSequenceKeypoint.new(0,0),NumberSequenceKeypoint.new(1,1)}),
WidthScale=NumberSequence.new({NumberSequenceKeypoint.new(0,1),NumberSequenceKeypoint.new(1,0)}),Parent=m})
new("ParticleEmitter",{Texture="rbxassetid://243098098",Rate=110,Lifetime=NumberRange.new(0.5,1),Speed=NumberRange.new(2,7),SpreadAngle=Vector2.new(180,180),
Color=ColorSequence.new({ColorSequenceKeypoint.new(0,Color3.new(1,1,1)),ColorSequenceKeypoint.new(0.4,EC),ColorSequenceKeypoint.new(1,EC:Lerp(Color3.new(0,0,0),0.6))}),
Size=NumberSequence.new({NumberSequenceKeypoint.new(0,meteorStyle=="Plasma Core" and size*1.3 or size*0.9),NumberSequenceKeypoint.new(1,0)}),Transparency=NumberSequence.new({NumberSequenceKeypoint.new(0,0.1),NumberSequenceKeypoint.new(1,1)}),LightEmission=1,Parent=m})
local t, conn = 0, nil
local speed = 130 + math.random() * 40
conn = RS.Heartbeat:Connect(function(dt)
t += dt
if not m.Parent then conn:Disconnect() return end
local step = dir * speed * dt
mrp.FilterDescendantsInstances = {player.Character, m}
local res = workspace:Raycast(m.Position, step * 1.3, mrp)
if res then
local hp = res.Position
conn:Disconnect(); m:Destroy(); explode(hp)
return
end
m.CFrame = CFrame.new(m.Position + step)
if t > 6 then conn:Disconnect(); m:Destroy() end
end)
end
RS.Heartbeat:Connect(function(dt)
if not feat.meteorShower then return end
meteorAcc += dt
if meteorAcc >= 1 / feat.meteorRate then meteorAcc = 0; spawnMeteor() end
end)
end
-- ══════════════════════════════════════════════════════════════
-- SKYBOXES
-- ══════════════════════════════════════════════════════════════
do
local Sky = {mode = "Off", ents = {}, anim = nil}
Fn.Sky = Sky
local D = 650
local WHITE = Color3.new(1, 1, 1)
local MODES = {"Black Hole", "Aurora", "Galaxy", "Nebula", "Starry Night"}
Sky.MODES = MODES
for _, m in ipairs(MODES) do feat["sky" .. m:gsub(" ", "")] = false end
local function part(props)
local p = new("Part", {Anchored=true, CanCollide=false, CanQuery=false, CanTouch=false, CastShadow=false, Material=Enum.Material.Neon, Size=Vector3.new(1, 1, 1)})
for k, v in pairs(props) do p[k] = v end
p.Parent = Sky.model
return p
end
local function add(p, cf) local e = {p=p, cf=cf}; Sky.ents[#Sky.ents + 1] = e; return e end
local function glow(cf, studs, color, strength)
local a = part({Transparency=1})
local bb = new("BillboardGui", {Size=UDim2.new(studs, 0, studs, 0), LightInfluence=0, Brightness=2, AlwaysOnTop=false, Adornee=a, Parent=a})
for k = 1, 6 do
local s = k / 6
local f = new("Frame", {AnchorPoint=Vector2.new(0.5, 0.5), Position=UDim2.fromScale(0.5, 0.5), Size=UDim2.fromScale(s, s), BackgroundColor3=color, BackgroundTransparency=math.clamp(1 - 0.13 * (strength or 1), 0, 1), BorderSizePixel=0, Parent=bb})
new("UICorner", {CornerRadius=UDim.new(0.5, 0), Parent=f})
end
local e = add(a, cf); e.bb = bb; e.size = studs
return e
end
local function curtain(color, topColor)
local p = part({Transparency=1, Size=Vector3.new(30, 100, 0.2)})
local frames = {}
for _, face in ipairs({Enum.NormalId.Front, Enum.NormalId.Back}) do
local sg = new("SurfaceGui", {Face=face, SizingMode=Enum.SurfaceGuiSizingMode.FixedSize, CanvasSize=Vector2.new(16, 128), LightInfluence=0, Brightness=2.5, Parent=p})
local f = new("Frame", {Size=UDim2.fromScale(1, 1), BackgroundColor3=WHITE, BorderSizePixel=0, Parent=sg})
new("UIGradient", {Rotation=90, Color=ColorSequence.new(topColor, color),
Transparency=NumberSequence.new({NumberSequenceKeypoint.new(0, 1), NumberSequenceKeypoint.new(0.45, 0.7), NumberSequenceKeypoint.new(0.85, 0.12), NumberSequenceKeypoint.new(1, 1)}), Parent=f})
frames[#frames + 1] = f
end
return p, frames
end
local function stars(n, EC)
local list = {}
for _ = 1, n do
local dir
repeat dir = Vector3.new(math.random()*2-1, math.random()*1.1-0.1, math.random()*2-1) until dir.Magnitude > 0.2 and dir.Magnitude <= 1
local sz = 1 + math.random()*2.4
local p = part({Shape=Enum.PartType.Ball, Size=Vector3.new(sz, sz, sz), Color=WHITE:Lerp(EC, math.random()*0.5), Transparency=math.random()*0.4})
local e = add(p, CFrame.new(dir.Unit * (D + 150)))
e.base = p.Transparency
list[#list+1] = e
end
return list
end
local function twinkle(list)
for _ = 1, 14 do
local e = list[math.random(#list)]
e.p.Transparency = math.clamp(e.base + (math.random()-0.5)*0.7, 0, 0.92)
end
end
local function skyDir(az, el) return Vector3.new(math.cos(el) * math.sin(az), math.sin(el), -math.cos(el) * math.cos(az)) end
local BUILD = {}
BUILD["Black Hole"] = function(EC)
local st = stars(220, EC)
local center = Vector3.new(0.35, 0.5, -0.8).Unit * D
local face = CFrame.lookAt(center, Vector3.zero)
glow(CFrame.new(center), 520, EC, 0.9)
glow(CFrame.new(center), 230, WHITE:Lerp(EC, 0.4), 1.3)
add(part({Shape=Enum.PartType.Ball, Size=Vector3.new(96, 96, 96), Color=Color3.new(0, 0, 0)}), CFrame.new(center))
local N = 48
for i = 1, N do
local a = i / N * math.pi * 2
local r = 58
local p = part({Size=Vector3.new(2 * math.pi * r / N * 1.15, 3.2, 1), Color=WHITE:Lerp(EC, 0.35), Transparency=0.15 + 0.5 * (0.5 - 0.5 * math.cos(a))})
add(p, face * CFrame.Angles(0, 0, a) * CFrame.new(0, r, 0))
end
local disk = {}
for ri, r in ipairs({72, 100, 132, 165}) do
local n = 56
for i = 1, n do
local phi = i / n * math.pi * 2
local p = part({Size=Vector3.new(2 * math.pi * r / n * 1.12, 1.4, 30), Color=WHITE:Lerp(EC, 0.15 + ri * 0.2),
Transparency=math.clamp(0.05 + ri * 0.14 + 0.3 * (0.5 + 0.5 * math.sin(phi * 3 + ri)), 0, 0.95)})
disk[#disk + 1] = {e=add(p, CFrame.new()), r=r, phi=phi, w=0.35 * 72 / r}
end
end
local diskCF = face * CFrame.Angles(math.rad(12), 0, 0)
return function(t)
for _, d in ipairs(disk) do d.e.cf = diskCF * CFrame.Angles(0, d.phi + t * d.w, 0) * CFrame.new(0, 0, -d.r) end
twinkle(st)
end
end
BUILD["Aurora"] = function(EC)
local st = stars(200, EC)
local top = EC:Lerp(WHITE, 0.3)
local bands = {}
for b = 1, 2 do
local n = 34
local az0, span = (b == 1) and -1.2 or 0.6, (b == 1) and 2.0 or 1.6
local rad, y = (b == 1) and 520 or 600, (b == 1) and 190 or 260
for i = 1, n do
local p, frames = curtain(EC, top)
bands[#bands + 1] = {p=p, frames=frames, e=add(p, CFrame.new()), az=az0 + span * i / n, rad=rad, y=y, k=i + b * 50, w=rad * span / n * 1.15}
end
end
return function(t)
for _, c in ipairs(bands) do
local k = c.k
local az = c.az + 0.03 * math.sin(t * 0.2 + k * 0.3)
local r = c.rad + 45 * math.sin(k * 0.45 + t * 0.35)
local h = 110 + 70 * (0.5 + 0.5 * math.sin(k * 0.7 + t * 0.6))
local pos = Vector3.new(math.sin(az) * r, c.y + h * 0.5 + 15 * math.sin(k * 0.3 + t * 0.4), -math.cos(az) * r)
c.p.Size = Vector3.new(c.w, h, 0.2)
c.e.cf = CFrame.lookAt(pos, Vector3.new(0, pos.Y, 0))
local tr = 0.15 + 0.45 * (0.5 + 0.5 * math.sin(k * 1.3 + t * 1.1))
for _, f in ipairs(c.frames) do f.BackgroundTransparency = tr end
end
twinkle(st)
end
end
BUILD["Galaxy"] = function(EC)
local st = stars(240, EC)
local center = Vector3.new(-0.45, 0.55, -0.7).Unit * D
local plane = CFrame.lookAt(center, Vector3.zero) * CFrame.Angles(math.rad(-58), 0, 0)
glow(CFrame.new(center), 260, EC, 0.8)
glow(CFrame.new(center), 90, WHITE:Lerp(EC, 0.25), 1.6)
local pts = {}
for i = 1, 180 do
local tt = i / 180
local sz = 5 - tt * 3 + math.random() * 1.5
local p = part({Shape=Enum.PartType.Ball, Size=Vector3.new(sz, sz, sz), Color=WHITE:Lerp(EC, 0.2 + tt * 0.8), Transparency=0.1 + tt * 0.5})
pts[#pts + 1] = {e=add(p, CFrame.new()), ang=(i % 2) * math.pi + tt * math.pi * 3.2 + (math.random() - 0.5) * 0.5, r=12 + tt * 190 + (math.random() - 0.5) * 18, h=(math.random() - 0.5) * 6}
end
for i = 1, 10 do
local tt = i / 10
pts[#pts + 1] = {e=glow(CFrame.new(), 70 + math.random() * 40, EC, 0.45), ang=(i % 2) * math.pi + tt * math.pi * 3.2, r=20 + tt * 180, h=0}
end
return function(t)
local rot = t * 0.04
for _, s in ipairs(pts) do s.e.cf = plane * CFrame.new(math.cos(s.ang + rot) * s.r, s.h, math.sin(s.ang + rot) * s.r) end
twinkle(st)
end
end
BUILD["Nebula"] = function(EC)
local st = stars(260, EC)
local hue, sat, val = EC:ToHSV()
local clouds = {}
for _ = 1, 16 do
local dir = skyDir(math.random() * math.pi * 2, math.rad(12 + math.random() * 62))
local c = Color3.fromHSV((hue + (math.random() - 0.5) * 0.12) % 1, sat, val)
clouds[#clouds + 1] = {e=glow(CFrame.new(dir * D), 180 + math.random() * 220, c, 0.35 + math.random() * 0.35), dir=dir, ph=math.random() * 6}
end
return function(t)
local drift = CFrame.Angles(0, t * 0.01, 0)
for _, c in ipairs(clouds) do
c.e.cf = drift * CFrame.new(c.dir * D + Vector3.new(0, 10 * math.sin(t * 0.3 + c.ph), 0))
local s = c.e.size * (1 - 0.12 * (0.5 + 0.5 * math.sin(t * 0.5 + c.ph)))
c.e.bb.Size = UDim2.new(s, 0, s, 0)
end
twinkle(st)
end
end
BUILD["Starry Night"] = function(EC)
local st = stars(420, EC)
local moon = Vector3.new(0.2, 0.45, -0.85).Unit * D
glow(CFrame.new(moon), 140, WHITE:Lerp(EC, 0.3), 1.2)
add(part({Shape=Enum.PartType.Ball, Size=Vector3.new(34, 34, 34), Color=WHITE:Lerp(EC, 0.15)}), CFrame.new(moon))
local shoot = {}
for i = 1, 3 do
local p = part({Size=Vector3.new(0.8, 0.8, 60), Color=WHITE:Lerp(EC, 0.4), Transparency=1})
shoot[i] = {e=add(p, CFrame.new(0, -5000, 0)), p=p, t0=-10, life=0}
end
local nextShot = 1
return function(t)
twinkle(st)
if t > nextShot then
nextShot = t + 1.5 + math.random() * 3
for _, s in ipairs(shoot) do
if t - s.t0 > s.life then
local az = math.random() * math.pi * 2
s.t0, s.life = t, 0.9 + math.random() * 0.6
s.from = skyDir(az, math.rad(25 + math.random() * 45)) * D
s.vel = Vector3.new(math.cos(az), -0.5, math.sin(az)).Unit * (260 + math.random() * 200)
break
end
end
end
for _, s in ipairs(shoot) do
local a = t - s.t0
if s.from and a <= s.life then
local pos = s.from + s.vel * a
s.e.cf = CFrame.lookAt(pos, pos + s.vel)
s.p.Transparency = math.clamp(math.abs(a / s.life - 0.5) * 2, 0.05, 1)
else
s.p.Transparency = 1
end
end
end
end
local function teardown()
if Sky.conn then Sky.conn:Disconnect(); Sky.conn = nil end
if Sky.model then Sky.model:Destroy(); Sky.model = nil end
if Sky.customInstance then Sky.customInstance:Destroy(); Sky.customInstance = nil end
Sky.ents, Sky.anim = {}, nil
end
local function restoreLighting()
local s = Sky.saved
if not s then return end
Lighting.ClockTime = s.clock; Lighting.OutdoorAmbient = s.oa; Lighting.Ambient = s.amb
for _, sk in ipairs(s.skies) do pcall(function() sk.Parent = Lighting end) end
Sky.saved = nil
end
Fn.setSky = function(mode)
teardown()
Sky.mode = BUILD[mode] and mode or "Off"
for _, m in ipairs(MODES) do
local id = (m:gsub(" ", ""))
feat["sky" .. id] = (m == Sky.mode)
if m ~= Sky.mode and ToggleReg["Sky" .. id] then ToggleReg["Sky" .. id](false) end
end
if Sky.mode == "Off" then restoreLighting() return end
if not Sky.saved then
local skies = {}
for _, c in ipairs(Lighting:GetChildren()) do if c:IsA("Sky") then skies[#skies + 1] = c; c.Parent = nil end end
Sky.saved = {clock=Lighting.ClockTime, oa=Lighting.OutdoorAmbient, amb=Lighting.Ambient, skies=skies}
end
local EC = EFFECT_COLOR
Lighting.ClockTime = 0
Lighting.OutdoorAmbient = Color3.fromRGB(105, 105, 120):Lerp(EC, 0.25)
Lighting.Ambient = Color3.fromRGB(70, 70, 85):Lerp(EC, 0.2)
Sky.model = new("Model", {Name="OwoSkybox", Parent=workspace})
local ok, anim = pcall(BUILD[Sky.mode], EC)
if not ok then warn("[☾] skybox: "..tostring(anim)); teardown(); restoreLighting(); Sky.mode = "Off"; return end
Sky.anim = anim
local parts, cfs = {}, {}
for i, e in ipairs(Sky.ents) do parts[i] = e.p end
local t = 0
Sky.conn = RS.RenderStepped:Connect(function(dt)
t += dt
local ok2, err = pcall(Sky.anim, t, dt)
if not ok2 and not Sky.warned then Sky.warned = true; warn("[☾] skybox: "..tostring(err)) end
if Lighting.ClockTime ~= 0 then Lighting.ClockTime = 0 end
local o = CFrame.new(workspace.CurrentCamera.CFrame.Position)
for i, e in ipairs(Sky.ents) do cfs[i] = o * e.cf end
workspace:BulkMoveTo(parts, cfs, Enum.BulkMoveMode.FireCFrameChanged)
end)
end
Fn.setCustomSkybox = function(rawId)
local id = tostring(rawId or ""):gsub("%s", ""):gsub("rbxassetid://", "")
if id == "" or not id:match("^%d+$") then
notify("Custom Skybox", "Enter a valid Roblox asset ID", false)
return
end
teardown()
if not Sky.saved then
local skies = {}
for _, child in ipairs(Lighting:GetChildren()) do
if child:IsA("Sky") then skies[#skies + 1] = child; child.Parent = nil end
end
Sky.saved = {clock=Lighting.ClockTime, oa=Lighting.OutdoorAmbient, amb=Lighting.Ambient, skies=skies}
end
local sky = new("Sky", {Name="OwoCustomSkybox", Parent=Lighting})
Sky.customInstance = sky
local uri = "rbxassetid://" .. id
sky.SkyboxBk, sky.SkyboxDn, sky.SkyboxFt = uri, uri, uri
sky.SkyboxLf, sky.SkyboxRt, sky.SkyboxUp = uri, uri, uri
Sky.mode = "Custom"
feat.customSkyboxId = id
notify("Custom Skybox", "Applied ID " .. id)
end
Fn.skyRecolor = function() if Sky.mode ~= "Off" then Fn.setSky(Sky.mode) end end
end
-- ══════════════════════════════════════════════════════════════
-- MAIN WINDOW (hover sidebar: icons only -> icons + names)
-- ══════════════════════════════════════════════════════════════
local mkListPage
do
local gui = new("ScreenGui",{Name="OwoClient",ResetOnSpawn=false,IgnoreGuiInset=true,ZIndexBehavior=Enum.ZIndexBehavior.Sibling,DisplayOrder=100,Parent=pg})
UI.gui = gui
local SB_C, SB_E = 70, 196
-- Default opening size matched to the supplied reference screenshot.
local ROOT_W, ROOT_H = 1200, 710
local TOP_H = 90
UI.MIN_W, UI.MIN_H, UI.ROOT_W, UI.MAIN_H = 820, 540, ROOT_W, ROOT_H
UI.sbPinned = false
local win = new("Frame",{Name="Root", Size=UDim2.new(0,ROOT_W,0,ROOT_H), Position=UDim2.new(0.5,0,0.5,0), AnchorPoint=Vector2.new(0.5,0.5), BackgroundTransparency=1, Visible=false, Active=true, Parent=gui})
UI.win = win
local uiScale = new("UIScale", {Scale = 1, Parent = win})
local function fitWindowToViewport()
local cam = workspace.CurrentCamera or camera
if not cam then return end
local viewport = cam.ViewportSize
local fitX = math.max(0.55, (viewport.X - 28) / ROOT_W)
local fitY = math.max(0.55, (viewport.Y - 28) / ROOT_H)
uiScale.Scale = math.min(1, fitX, fitY)
end
fitWindowToViewport()
local function bindViewportCamera(cam)
if not cam then return end
cam:GetPropertyChangedSignal("ViewportSize"):Connect(fitWindowToViewport)
task.defer(fitWindowToViewport)
end
bindViewportCamera(workspace.CurrentCamera)
workspace:GetPropertyChangedSignal("CurrentCamera"):Connect(function()
bindViewportCamera(workspace.CurrentCamera)
end)
-- Use a normal Frame instead of CanvasGroup. CanvasGroup flattens the UI
-- into a texture and can make small text/icons look soft at some resolutions.
local canvas = new("Frame", {Name="Canvas", Size=UDim2.new(1,0,1,0), BackgroundTransparency=1, BorderSizePixel=0, Parent=win})
UI.canvas = canvas
local panel = new("Frame",{Name="Main",Size=UDim2.new(1,0,1,0),BackgroundColor3=T.Bg,BackgroundTransparency=TR.Window,BorderSizePixel=0,ClipsDescendants=true,Parent=canvas})
corner(panel, 16)
local pst = stroke(panel, 1, 0.45, T.Line, true); regRef(pst, "Color", "Line")
regRef(panel, "BackgroundColor3", "Bg"); addSheen(panel)
Glass.G.decorate(panel)
UI.mainPanel = panel
-- Moving shine layer for the main GUI window, independent from overlay shine.
local guiShine = new("Frame", {
Name="OwoGuiShine", AnchorPoint=Vector2.new(0.5,0.5),
Size=UDim2.new(0.28,0,1.8,0), Position=UDim2.new(-0.5,0,0.5,0),
Rotation=18, BackgroundColor3=Color3.new(1,1,1), BackgroundTransparency=0.78,
BorderSizePixel=0, Visible=false, Active=false, ZIndex=500, Parent=panel
})
new("UIGradient", {Rotation=0, Transparency=NumberSequence.new({
NumberSequenceKeypoint.new(0,1), NumberSequenceKeypoint.new(0.35,0.96),
NumberSequenceKeypoint.new(0.5,0.48), NumberSequenceKeypoint.new(0.65,0.96),
NumberSequenceKeypoint.new(1,1)
}), Parent=guiShine})
RS.RenderStepped:Connect(function()
local on = feat.guiShine == true and UI.win ~= nil and UI.win.Visible and guiShine.Parent ~= nil
guiShine.Visible = on
if on then
local phase = (os.clock() % 3.4) / 3.4
guiShine.Position = UDim2.new(-0.42 + phase * 1.84, 0, 0.5, 0)
end
end)
UI.bgImage = new("ImageLabel", {Name="OwoUIBackground", Size=UDim2.new(1,0,1,0), BackgroundTransparency=1, Image="", ImageTransparency=0.3, ScaleType=Enum.ScaleType.Crop, ZIndex=0, Visible=false, Parent=panel})
corner(UI.bgImage, 16)
UI.mommyBackground = new("ImageLabel", {
Name="MommyModeBackground", Size=UDim2.new(1,0,1,0), Position=UDim2.new(0,0,0,0),
BackgroundTransparency=1, Image="rbxassetid://11637032818", ImageTransparency=0.18,
ScaleType=Enum.ScaleType.Crop, ZIndex=0, Visible=feat.mommyMode == true, Parent=panel
})
corner(UI.mommyBackground, 16)
Fn.applyUIBackground = function()
local show = feat.uiBackground and feat.uiBackgroundId ~= ""
UI.bgImage.Visible = show
UI.bgImage.ImageTransparency = feat.uiBackgroundTransparency
if feat.uiBackgroundId ~= "" then UI.bgImage.Image = "rbxthumb://type=Asset&id="..feat.uiBackgroundId.."&w=420&h=420" end
end
-- ───── content side ─────
local holder = new("Frame",{Name="Holder",Size=UDim2.new(1,-SB_C,1,0),Position=UDim2.new(0,SB_C,0,0),BackgroundTransparency=1,Parent=panel})
local topBar = new("Frame",{Name="TopBar",Size=UDim2.new(1,0,0,TOP_H),BackgroundTransparency=1,Parent=holder})
local searchWrap = new("Frame",{Size=UDim2.new(0,210,0,30),Position=UDim2.new(0,18,0,14),BackgroundColor3=T.Card,BackgroundTransparency=0.3,BorderSizePixel=0,Parent=topBar})
corner(searchWrap, 9); regRef(searchWrap, "BackgroundColor3", "Card")
local sws = stroke(searchWrap, 1, 0.6, T.Line, true); regRef(sws, "Color", "Line")
local mag = new("ImageLabel",{BackgroundTransparency=1,Position=UDim2.new(0,8,0.5,-9),Size=UDim2.new(0,18,0,18),Image="rbxassetid://132302594577680",ScaleType=Enum.ScaleType.Fit,ImageColor3=T.Dim,Parent=searchWrap}); regRef(mag,"ImageColor3","Dim")
local searchBox = new("TextBox",{Size=UDim2.new(1,-36,1,0),Position=UDim2.new(0,30,0,0),BackgroundTransparency=1,Font=Enum.Font.GothamMedium,Text="",PlaceholderText="Search...",TextColor3=T.Text,PlaceholderColor3=T.Muted,TextSize=12,ClearTextOnFocus=false,TextXAlignment=Enum.TextXAlignment.Left,Parent=searchWrap})
regRef(searchBox,"TextColor3","Text")
local titleLbl = new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,18,0,48),Size=UDim2.new(1,-150,0,32),Font=Enum.Font.GothamBold,Text="Home",TextColor3=T.Text,TextSize=22,TextXAlignment=Enum.TextXAlignment.Left,Parent=topBar}); regRef(titleLbl,"TextColor3","Text")
local clockLbl = new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(1,-112,0,18),Size=UDim2.new(0,94,0,20),Font=Enum.Font.GothamMedium,Text="00:00",TextColor3=T.Dim,TextSize=12,TextXAlignment=Enum.TextXAlignment.Right,Parent=topBar}); regRef(clockLbl,"TextColor3","Dim")
task.spawn(function() while topBar.Parent do task.wait(1); clockLbl.Text = os.date("%I:%M %p"):gsub("^0","") end end)
drag(win, topBar)
UI.contentArea = new("Frame",{Name="Content",Size=UDim2.new(1,-36,1,-TOP_H-12),Position=UDim2.new(0,18,0,TOP_H),BackgroundTransparency=1,Parent=holder})
-- resize grip
local rh = new("TextButton",{Size=UDim2.new(0,20,0,20),Position=UDim2.new(1,-20,1,-20),BackgroundTransparency=1,Text="",AutoButtonColor=false,ZIndex=60,Parent=win})
local grip = new("Frame",{Size=UDim2.new(1,0,1,0),BackgroundTransparency=1,ZIndex=61,Parent=rh})
for i = 1, 2 do
new("Frame",{Size=UDim2.new(0,10,0,1),Position=UDim2.new(0,6+(i-1)*4,0,14-(i-1)*4),BackgroundColor3=T.Dim,BackgroundTransparency=0.45,BorderSizePixel=0,Rotation=45,ZIndex=62,Parent=grip})
end
local rszA, rszS, rszO = false, nil, nil
rh.InputBegan:Connect(function(i)
if i.UserInputType == Enum.UserInputType.MouseButton1 or i.UserInputType == Enum.UserInputType.Touch then
rszA = true; rszS = i.Position; rszO = win.AbsoluteSize
end
end)
UIS.InputChanged:Connect(function(i)
if rszA and (i.UserInputType == Enum.UserInputType.MouseMovement or i.UserInputType == Enum.UserInputType.Touch) then
win.Size = UDim2.new(0, math.max(UI.MIN_W, rszO.X + (i.Position.X - rszS.X)), 0, math.max(UI.MIN_H, rszO.Y + (i.Position.Y - rszS.Y)))
end
end)
UIS.InputEnded:Connect(function(i)
if rszA and (i.UserInputType == Enum.UserInputType.MouseButton1 or i.UserInputType == Enum.UserInputType.Touch) then rszA = false end
end)
Fn.openMenu = function()
if UI.isOpen then return end
playUiSoundLayered("menuOpen")
UI.isOpen = true
uiScale.Scale = 0.955; win.Visible = true
panel.BackgroundTransparency = 1
TS:Create(panel, TweenInfo.new(sdur(0.24), Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {BackgroundTransparency = TR.Window}):Play()
TS:Create(uiScale, TweenInfo.new(sdur(0.34), Enum.EasingStyle.Quint, Enum.EasingDirection.Out), {Scale = 1}):Play()
end
Fn.closeMenu = function()
if not UI.isOpen then return end
playUiSoundLayered("menuClose")
UI.isOpen = false
TS:Create(panel, TweenInfo.new(sdur(0.16), Enum.EasingStyle.Quad, Enum.EasingDirection.In), {BackgroundTransparency = 1}):Play()
TS:Create(uiScale, TweenInfo.new(sdur(0.18), Enum.EasingStyle.Quad, Enum.EasingDirection.In), {Scale = 0.955}):Play()
task.delay(sdur(0.18), function() if not UI.isOpen then win.Visible = false; panel.BackgroundTransparency = TR.Window end end)
end
Fn.toggleMenu = function() if UI.isOpen then Fn.closeMenu() else Fn.openMenu() end end
-- ───── sidebar (drawer: hover to expand) ─────
local sidebar = new("Frame",{Name="Sidebar",Size=UDim2.new(0,SB_C,1,0),BackgroundColor3=T.Panel,BackgroundTransparency=1,BorderSizePixel=0,ClipsDescendants=true,ZIndex=5,Parent=panel})
corner(sidebar, 16); regRef(sidebar, "BackgroundColor3", "Panel")
UI.sidebar = sidebar
local divider = new("Frame",{Size=UDim2.new(0,1,1,-28),Position=UDim2.new(1,-1,0,14),BackgroundColor3=T.Line,BackgroundTransparency=0.35,BorderSizePixel=0,ZIndex=6,Parent=sidebar}); regRef(divider,"BackgroundColor3","Line")
local fadeTxt, fadeLine = {}, {}
local function ftxt(l) fadeTxt[#fadeTxt+1] = l; l.TextTransparency = 1; return l end
local logo = new("TextButton",{Size=UDim2.new(1,0,0,60),BackgroundTransparency=1,Text="",AutoButtonColor=false,ZIndex=6,Parent=sidebar})
moonwareLogo(logo, 38, UDim2.new(0,12,0.5,-19), T.Text, T.Bg, TR.Window, 7, "SidebarMoonwareMark")
ftxt(new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,SB_C-8,0,13),Size=UDim2.new(1,-SB_C,0,18),Font=Enum.Font.GothamBold,Text="Moonware",TextColor3=T.Text,TextSize=15,TextXAlignment=Enum.TextXAlignment.Left,ZIndex=7,Parent=logo}))
ftxt(new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,SB_C-8,0,31),Size=UDim2.new(1,-SB_C,0,14),Font=Enum.Font.Gotham,Text="Version: V4",TextColor3=T.Muted,TextSize=10,TextXAlignment=Enum.TextXAlignment.Left,ZIndex=7,Parent=logo}))
logo.MouseButton1Click:Connect(function() UI.sbPinned = not UI.sbPinned end)
local tabList = new("ScrollingFrame", {Position=UDim2.new(0,0,0,62), Size=UDim2.new(1,0,1,-62-58), BackgroundTransparency=1, BorderSizePixel=0, ScrollBarThickness=0, CanvasSize=UDim2.new(0,0,0,0), AutomaticCanvasSize=Enum.AutomaticSize.Y, ScrollingDirection=Enum.ScrollingDirection.Y, ZIndex=6, Parent=sidebar})
new("UIListLayout",{Padding=UDim.new(0,3),SortOrder=Enum.SortOrder.LayoutOrder,HorizontalAlignment=Enum.HorizontalAlignment.Center,Parent=tabList})
local Pages, Tabs = {}, {}
local cur = nil
local TITLES = {home="Home", movement="Movement", combat="Combat", visuals="Visuals", overlays="Overlays", music="Music", friends="Friends", themes="Themes", saves="Configs", more="More", misc="Misc"}
local lo = 0
local function section(txt)
lo += 1
local f = new("Frame",{Size=UDim2.new(1,0,0,26),BackgroundTransparency=1,LayoutOrder=lo,ZIndex=6,Parent=tabList})
local l = ftxt(new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,16,0,0),Size=UDim2.new(1,-20,1,0),Font=Enum.Font.GothamBold,Text=txt,TextColor3=T.Muted,TextSize=10,TextXAlignment=Enum.TextXAlignment.Left,ZIndex=7,Parent=f}))
regRef(l, "TextColor3", "Muted")
local line = new("Frame",{Size=UDim2.new(1,-28,0,1),Position=UDim2.new(0,14,0.5,0),BackgroundColor3=T.Line,BackgroundTransparency=0.45,BorderSizePixel=0,ZIndex=7,Parent=f}); regRef(line,"BackgroundColor3","Line")
fadeLine[#fadeLine+1] = line
end
-- Creator Store icons supplied for each sidebar destination.
local TAB_ICON_ASSET_IDS = {
home = "94113191661608",
movement = "13308982029",
combat = "14400935532",
visuals = "84558270211684",
overlays = "83957932853769",
music = "7059338419",
friends = "76209336499935",
themes = "111935208127098",
saves = "122578721103859", -- Configs / settings icon
more = "73911555075911",
misc = "72620556731766", -- Misc icon
}
local TAB_ICON_GLYPHS = {
home="⌂", movement="↗", combat="◎", visuals="◉", overlays="▧",
music="♫", friends="♧", themes="◐", saves="▤", more="⋯", misc="⋯",
}
local function setTabVisual(t, active)
tween(t.btn, 0.15, {BackgroundTransparency = active and 0.55 or 1})
t.icon.ImageColor3 = active and T.Accent or T.Dim
t.fallback.TextColor3 = active and T.Accent or T.Dim
t.label.TextColor3 = active and T.Text or T.Dim
end
local function tab(name, label, _legacyIcon)
lo += 1
local btn = new("TextButton",{Size=UDim2.new(1,-12,0,36),BackgroundColor3=T.Hover,BackgroundTransparency=1,Text="",BorderSizePixel=0,AutoButtonColor=false,LayoutOrder=lo,ZIndex=6,Parent=tabList})
corner(btn, 10); regRef(btn, "BackgroundColor3", "Hover")
local id = TAB_ICON_ASSET_IDS[name]
local ic = new("ImageLabel",{Name="RobloxTabIcon",BackgroundTransparency=1,Position=UDim2.new(0,13,0,7),Size=UDim2.new(0,22,0,22),Image="",ImageColor3=T.Dim,ImageTransparency=0.02,ScaleType=Enum.ScaleType.Fit,ZIndex=7,Visible=false,Parent=btn})
-- The glyph remains visible until an image successfully loads, so a
-- permission/type mismatch can never leave an empty sidebar icon.
local fallback = new("TextLabel",{Name="TabIconFallback",BackgroundTransparency=1,Position=ic.Position,Size=ic.Size,Font=Enum.Font.GothamBold,Text=TAB_ICON_GLYPHS[name] or "•",TextColor3=T.Dim,TextSize=19,Visible=true,ZIndex=8,Parent=btn})
regRef(fallback, "TextColor3", "Dim")
local nm = ftxt(new("TextLabel",{BackgroundColor3=T.Hover,BackgroundTransparency=1,Position=UDim2.new(0,48,0,4),Size=UDim2.new(1,-58,1,-8),Font=Enum.Font.GothamMedium,Text=label,TextColor3=T.Dim,TextSize=13,TextXAlignment=Enum.TextXAlignment.Left,ZIndex=7,Parent=btn}))
-- Keep a fallback visible until the Creator Store image is confirmed loaded.
if id then
applyRobloxAssetIcon(ic, id, fallback)
else
ic.Visible = false
fallback.Visible = true
end
local tabBright = Color3.new(1,1,1)
Hover.add(btn, function(a)
local active = (cur == name)
btn.BackgroundColor3 = T.Hover:Lerp(tabBright, 0.05 * a)
if not active then btn.BackgroundTransparency = 1 - 0.14 * a end
local x = 13 + 3 * (active and 0 or a)
ic.Position = UDim2.new(0, x, 0, 7)
fallback.Position = UDim2.new(0, x, 0, 7)
end, {inSpeed=16, outSpeed=11})
btn.MouseButton1Click:Connect(function() Fn.selTab(name) end)
Tabs[name] = {name=name, btn=btn, icon=ic, fallback=fallback, label=nm}
end
section("FEATURES")
tab("home","Home"); tab("movement","Movement"); tab("visuals","Visuals"); tab("combat","Combat"); tab("overlays","Overlays"); tab("music","Music")
section("OTHERS")
tab("friends","Friends"); tab("themes","Themes"); tab("saves","Configs"); tab("more","More"); tab("misc","Misc")
local prof = new("Frame",{Size=UDim2.new(1,0,0,56),Position=UDim2.new(0,0,1,-56),BackgroundTransparency=1,Active=true,ZIndex=6,Parent=sidebar})
local pav = new("Frame",{Size=UDim2.new(0,30,0,30),Position=UDim2.new(0,10,0.5,-15),BackgroundColor3=T.Off,BorderSizePixel=0,ZIndex=7,Parent=prof}); corner(pav,15)
local pimg = new("ImageLabel",{Name="RobloxAvatarFallback",Size=UDim2.fromScale(1,1),BackgroundTransparency=1,ZIndex=8,Parent=pav,ScaleType=Enum.ScaleType.Crop}); corner(pimg,16)
task.spawn(function()
local ok, thumb = pcall(function() return Players:GetUserThumbnailAsync(player.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size100x100) end)
if ok and thumb and pimg.Parent then pimg.Image = thumb end
end)
local customPfp = new("ImageLabel",{Name="MoonwareCustomProfilePicture",Size=UDim2.fromScale(1,1),BackgroundTransparency=1,Image="",ImageColor3=Color3.new(1,1,1),ScaleType=Enum.ScaleType.Crop,Visible=false,ZIndex=9,Parent=pav}); corner(customPfp,16)
local pavStroke = new("UIStroke",{Color=T.Line,Thickness=1,Transparency=0.25,Parent=pav}); regRef(pavStroke,"Color","Line")
table.insert(profilePfpTargets, {image=customPfp, fallback=pimg})
ftxt(new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,76,0,10),Size=UDim2.new(1,-120,0,16),Font=Enum.Font.GothamBold,Text=player.DisplayName or player.Name,TextColor3=T.Text,TextSize=12,TextXAlignment=Enum.TextXAlignment.Left,TextTruncate=Enum.TextTruncate.AtEnd,ZIndex=7,Parent=prof}))
ftxt(new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,76,0,27),Size=UDim2.new(1,-120,0,14),Font=Enum.Font.Gotham,Text="@"..player.Name,TextColor3=T.Muted,TextSize=10,TextXAlignment=Enum.TextXAlignment.Left,TextTruncate=Enum.TextTruncate.AtEnd,ZIndex=7,Parent=prof}))
-- One shared setter updates both sidebar and status-bar profile pictures.
Fn.setProfilePfp = function(raw)
local id = tostring(raw or ""):match("%d+")
feat.profilePfpId = id or ""
for _, target in ipairs(profilePfpTargets) do
if target.image and target.image.Parent then
if id then
applyRobloxAssetIcon(target.image, id, target.fallback)
else
target.image.Visible = false
if target.fallback then target.fallback.Visible = true end
end
end
end
return id ~= nil
end
if feat.profilePfpId and feat.profilePfpId ~= "" then Fn.setProfilePfp(feat.profilePfpId) end
-- The profile row itself is now the hit target. This avoids the old tiny dots
-- button being covered by the avatar/labels or being clipped by the expanding rail.
-- It is a transparent ScreenGui sibling, aligned to the row every frame below.
local profileMenuButton = new("TextButton",{
Name="ProfilePictureMenuButton",Size=UDim2.new(0,70,0,56),Position=UDim2.new(0,0,0,0),
BackgroundTransparency=1,BorderSizePixel=0,AutoButtonColor=false,
Active=true,Selectable=true,Font=Enum.Font.GothamBold,Text="...",TextColor3=T.Dim,
TextTransparency=1,TextSize=16,TextXAlignment=Enum.TextXAlignment.Right,
TextYAlignment=Enum.TextYAlignment.Center,ZIndex=250,Parent=gui
})
profileMenuButton.Visible = false
local pfpMenu = new("Frame",{
Name="ProfilePictureMenu",Size=UDim2.new(0,202,0,140),Position=UDim2.new(0,0,0,0),
BackgroundColor3=T.Card,BackgroundTransparency=TR.Card,BorderSizePixel=0,
Visible=false,Active=true,ZIndex=260,Parent=gui
})
corner(pfpMenu,12); stroke(pfpMenu,1,0.35,T.Line,true); regRef(pfpMenu,"BackgroundColor3","Card")
new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,10,0,7),Size=UDim2.new(1,-40,0,18),
Font=Enum.Font.GothamBold,Text="PROFILE PICTURE • SIDEBAR BOTTOM LEFT",TextColor3=T.Text,TextSize=10,
TextXAlignment=Enum.TextXAlignment.Left,ZIndex=261,Parent=pfpMenu})
local pfpClose = new("TextButton",{Size=UDim2.new(0,22,0,22),Position=UDim2.new(1,-27,0,4),
BackgroundTransparency=1,BorderSizePixel=0,AutoButtonColor=false,Font=Enum.Font.GothamBold,
Text="x",TextColor3=T.Muted,TextSize=13,ZIndex=261,Parent=pfpMenu})
local pfpInput = new("TextBox",{Size=UDim2.new(1,-16,0,30),Position=UDim2.new(0,8,0,34),
BackgroundColor3=T.Bg,BackgroundTransparency=0.05,BorderSizePixel=0,ClearTextOnFocus=false,
Font=Enum.Font.Gotham,Text=feat.profilePfpId or "",PlaceholderText="Roblox decal URL or ID",
TextColor3=T.Text,PlaceholderColor3=T.Muted,TextSize=10,TextXAlignment=Enum.TextXAlignment.Left,
ZIndex=261,Parent=pfpMenu})
corner(pfpInput,7); stroke(pfpInput,1,0.65,T.Line,true)
local pfpApply = new("TextButton",{Size=UDim2.new(0.5,-12,0,28),Position=UDim2.new(0,8,0,76),
BackgroundColor3=T.Accent,BorderSizePixel=0,AutoButtonColor=false,Font=Enum.Font.GothamBold,
Text="Apply",TextColor3=T.Bg,TextSize=10,ZIndex=261,Parent=pfpMenu})
corner(pfpApply,7)
local pfpReset = new("TextButton",{Size=UDim2.new(0.5,-12,0,28),Position=UDim2.new(0.5,4,0,76),
BackgroundColor3=T.Hover,BorderSizePixel=0,AutoButtonColor=false,Font=Enum.Font.GothamBold,
Text="Reset",TextColor3=T.Text,TextSize=10,ZIndex=261,Parent=pfpMenu})
corner(pfpReset,7); regRef(pfpReset,"BackgroundColor3","Hover"); regRef(pfpReset,"TextColor3","Text")
new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,9,0,110),Size=UDim2.new(1,-18,0,20),
Font=Enum.Font.Gotham,Text="Saved with your Moonware config",TextColor3=T.Muted,TextSize=9,
TextXAlignment=Enum.TextXAlignment.Left,ZIndex=261,Parent=pfpMenu})
local function placeProfileMenu()
local vp = (workspace.CurrentCamera or camera).ViewportSize
local rowPos, rowSize = prof.AbsolutePosition, prof.AbsoluteSize
local menuW, menuH = 202, 140
local x = rowPos.X + rowSize.X + 8
local y = rowPos.Y - menuH + 18
if x + menuW > vp.X - 8 then x = rowPos.X - menuW - 8 end
x = math.clamp(x, 8, math.max(8, vp.X - menuW - 8))
y = math.clamp(y, 8, math.max(8, vp.Y - menuH - 8))
pfpMenu.Position = UDim2.fromOffset(x, y)
end
local function toggleProfileMenu()
if not win.Visible then return end
playUiSoundLayered("click")
pfpInput.Text = feat.profilePfpId or ""
pfpMenu.Visible = not pfpMenu.Visible
if pfpMenu.Visible then placeProfileMenu() end
end
profileMenuButton.Activated:Connect(toggleProfileMenu)
pfpClose.MouseButton1Click:Connect(function() pfpMenu.Visible=false end)
pfpApply.MouseButton1Click:Connect(function()
local id = pfpInput.Text:match("%d+")
if not id then notify("Profile Picture","Paste a valid Roblox decal or image ID",false); return end
if Fn.setProfilePfp(id) then
notify("Profile Picture","Custom PFP applied. Save your config to keep it.")
pfpMenu.Visible = false
end
end)
pfpReset.MouseButton1Click:Connect(function()
pfpInput.Text = ""
Fn.setProfilePfp("")
notify("Profile Picture","Using your Roblox avatar")
pfpMenu.Visible = false
end)
-- hover expand driver (polls the mouse so child buttons can't cause flicker)
do
local expandT, lastA = 0, -1
RS.RenderStepped:Connect(function(dt)
if not win.Visible then
profileMenuButton.Visible = false
pfpMenu.Visible = false
return
end
-- This top-level hitbox follows the entire profile row, so clicking the
-- avatar, username, or dots always opens the same menu.
local rowPos, rowSize = prof.AbsolutePosition, prof.AbsoluteSize
profileMenuButton.Visible = true
profileMenuButton.Position = UDim2.fromOffset(rowPos.X, rowPos.Y)
profileMenuButton.Size = UDim2.fromOffset(rowSize.X, rowSize.Y)
local inside = false
if UI.isOpen then
local m = UIS:GetMouseLocation()
local p, s = panel.AbsolutePosition, panel.AbsoluteSize
local w = sidebar.AbsoluteSize.X
inside = m.X >= p.X and m.X <= p.X + w + 6 and m.Y >= p.Y and m.Y <= p.Y + s.Y
end
local mp = UIS:GetMouseLocation()
local pp, ps = prof.AbsolutePosition, prof.AbsoluteSize
local overProfile = mp.X >= pp.X and mp.X <= pp.X + ps.X and mp.Y >= pp.Y and mp.Y <= pp.Y + ps.Y
local target = (inside or UI.sbPinned or overProfile) and 1 or 0
expandT = slerp(expandT, target, dt, 16)
if math.abs(expandT - target) < 0.003 then expandT = target end
local showProfileDots = overProfile or pfpMenu.Visible
profileMenuButton.TextTransparency = showProfileDots and 0 or 1
profileMenuButton.BackgroundTransparency = 1
if pfpMenu.Visible then placeProfileMenu() end
if math.abs(expandT - target) > 0.02 then lastA = -1 end
if expandT ~= lastA then
lastA = expandT
local a = expandT
sidebar.Size = UDim2.new(0, SB_C + (SB_E - SB_C) * a, 1, 0)
sidebar.BackgroundTransparency = 1 - 0.94 * a
local tt = 1 - math.clamp((a - 0.3) / 0.7, 0, 1)
for _, l in ipairs(fadeTxt) do l.TextTransparency = tt end
for _, f in ipairs(fadeLine) do f.BackgroundTransparency = 0.45 + 0.55 * a end
end
end)
end
-- Global search indexes matching cards from every tab.
local globalSearchResults = new("ScrollingFrame", {
Name="GlobalSearchResults", Size=UDim2.new(1,0,1,0), BackgroundTransparency=1,
BorderSizePixel=0, ScrollBarThickness=3, ScrollBarImageColor3=T.Muted,
CanvasSize=UDim2.new(0,0,0,0), AutomaticCanvasSize=Enum.AutomaticSize.Y,
Visible=false, Parent=UI.contentArea
})
new("UIListLayout", {Padding=UDim.new(0,7), SortOrder=Enum.SortOrder.LayoutOrder, Parent=globalSearchResults})
local function applySearch()
local q = (searchBox.Text:lower():gsub("^%s+", ""):gsub("%s+$", ""))
for _, page in pairs(Pages) do
for _, card in ipairs(page:GetChildren()) do
if card:IsA("GuiObject") then card.Visible = (q == "") end
end
end
for _, child in ipairs(globalSearchResults:GetChildren()) do
if child:IsA("GuiObject") and not child:IsA("UIListLayout") then child:Destroy() end
end
if q == "" then
globalSearchResults.Visible = false
local currentPage = Pages[cur]
if currentPage then currentPage.Visible = true end
return
end
globalSearchResults.Visible = true
for tabName, page in pairs(Pages) do
for _, card in ipairs(page:GetChildren()) do
local label = card:GetAttribute("OwoLbl")
if label and tostring(label):lower():find(q, 1, true) then
local title = tostring(label):gsub("%s+", " ")
local result = new("TextButton", {
Name="SearchResult", Size=UDim2.new(1,-6,0,42),
BackgroundColor3=T.Card, BackgroundTransparency=0.12,
BorderSizePixel=0, AutoButtonColor=false, Text="",
Parent=globalSearchResults
})
corner(result,9); local resultStroke=stroke(result,1,0.65,T.Line,true); regRef(resultStroke,"Color","Line")
new("TextLabel", {BackgroundTransparency=1, Position=UDim2.new(0,12,0,3),
Size=UDim2.new(1,-24,0,17), Font=Enum.Font.GothamSemibold,
Text=title, TextColor3=T.Text, TextSize=12,
TextXAlignment=Enum.TextXAlignment.Left, TextTruncate=Enum.TextTruncate.AtEnd, Parent=result})
new("TextLabel", {BackgroundTransparency=1, Position=UDim2.new(0,12,0,21),
Size=UDim2.new(1,-24,0,14), Font=Enum.Font.GothamMedium,
Text=tostring(TITLES[tabName] or tabName), TextColor3=T.Accent,
TextSize=10, TextXAlignment=Enum.TextXAlignment.Left, Parent=result})
result.MouseButton1Click:Connect(function()
searchBox.Text = ""
Fn.selTab(tabName)
task.defer(function()
local targetPage=Pages[tabName]
if targetPage then
for _, item in ipairs(targetPage:GetChildren()) do
local itemLabel=item:GetAttribute("OwoLbl")
if item:IsA("GuiObject") then
item.Visible = itemLabel and tostring(itemLabel):lower():find(q,1,true) ~= nil or false
end
end
end
end)
end)
end
end
end
for _, page in pairs(Pages) do page.Visible = false end
end
searchBox:GetPropertyChangedSignal("Text"):Connect(applySearch)
Fn.selTab = function(name)
if cur == name then return end
playUiSound("tabSwitch")
cur = name
if searchBox.Text ~= "" then searchBox.Text = "" end
for tn, p in pairs(Pages) do p.Visible = (tn == name) end
for tn, t in pairs(Tabs) do setTabVisual(t, tn == name) end
titleLbl.Text = TITLES[name] or name
local pgf = Pages[name]
if pgf then
pgf.Position = UDim2.new(0, 0, 0, 10)
TS:Create(pgf, TweenInfo.new(sdur(0.22), Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {Position = UDim2.new(0, 0, 0, 0)}):Play()
end
end
mkListPage = function(name)
local p = new("ScrollingFrame",{Size=UDim2.new(1,0,1,0), BackgroundTransparency=1, BorderSizePixel=0, ScrollBarThickness=3, ScrollBarImageColor3=T.Muted, ScrollBarImageTransparency=0.5, CanvasSize=UDim2.new(0,0,0,0), AutomaticCanvasSize=Enum.AutomaticSize.Y, Visible=false, Parent=UI.contentArea})
new("UIListLayout",{Padding=UDim.new(0,8), FillDirection=Enum.FillDirection.Horizontal, Wraps=true, SortOrder=Enum.SortOrder.LayoutOrder, Parent=p})
Pages[name] = p
return p
end
UI.Pages = Pages
end
-- ══════════════════════════════════════════════════════════════
-- WIDGET BUILDERS (toggles / buttons / sliders are 2-column cards)
-- ══════════════════════════════════════════════════════════════
local ROW_H = 54
local function hdr(p, t)
local l = new("TextLabel",{Size=UDim2.new(1,-4,0,24),BackgroundTransparency=1,Font=Enum.Font.GothamBold,Text=t:upper(),TextColor3=T.Dim,TextSize=10,TextXAlignment=Enum.TextXAlignment.Left,Parent=p})
new("UIPadding",{PaddingLeft=UDim.new(0,10),Parent=l})
l:SetAttribute("OwoHdr", true)
regRef(l, "TextColor3", "Dim")
local bar = new("Frame",{Size=UDim2.new(0,2,0,12),Position=UDim2.new(0,0,0.5,-6),BackgroundColor3=T.Accent,BorderSizePixel=0,Parent=l})
corner(bar, 1); gradient(bar, T.Accent, T.Accent2, 90)
return l
end
local Picker
local function applyVisualColor(kind, col)
feat.visualColors[kind] = col
if kind == "self" or kind == "trail" or kind == "wings" or kind == "glow" or kind == "halo" or kind == "crown" or kind == "cape" or kind == "santaHat" or kind == "pickaxe" or kind == "fire" or kind == "sparkle" or kind == "jumpRing" or kind == "landRing" or kind == "charOutline" then
if Fn.rebuildVFX then Fn.rebuildVFX() end
elseif kind == "espChams" then
if Fn.refreshEsp then Fn.refreshEsp() end
for _, data in pairs(Fn.espData or {}) do
if data.highlight then data.highlight.FillColor = col; data.highlight.OutlineColor = col end
end
elseif kind == "espNames" or kind == "espHealth" or kind == "espDistance" then
for _, data in pairs(Fn.espData or {}) do
if kind == "espNames" and data.layoutStroke then data.layoutStroke.Color = col end
if kind == "espNames" and data.nameLbl then data.nameLbl.TextColor3 = col end
if kind == "espDistance" and data.distLbl then data.distLbl.TextColor3 = col end
if kind == "espHealth" and data.healthBar then data.healthBar.BackgroundColor3 = col end
end
if Fn.refreshEsp then Fn.refreshEsp() end
elseif kind == "crosshair" or kind == "crosshairDot" or kind == "crosshairOutline" then
if Fn.rebuildCrosshair then Fn.rebuildCrosshair() end
elseif kind == "aura" then
if Fn.rebuildAuraRing then Fn.rebuildAuraRing() end
elseif kind == "orbs" then
if Fn.rebuildOrbs then Fn.rebuildOrbs() end
elseif kind == "lightning" then
if Fn.rebuildLightning then Fn.rebuildLightning() end
elseif kind == "neonBody" then
if Fn.applyNeonBody then Fn.applyNeonBody() end
elseif kind == "playerTrans" then
if Fn.applyPlayerTransparency then Fn.applyPlayerTransparency() end
elseif kind == "rainbowChar" then
if Fn.applyRainbowChar then Fn.applyRainbowChar() end
elseif kind == "rain" then
if Wx.rain then Wx.rain() end
elseif kind == "thunder" then
if Wx.thunder then Wx.thunder() end
elseif kind == "snow" then
if Wx.snow then Wx.snow() end
elseif kind == "fog" then
if Wx.fog then Wx.fog() end
elseif kind == "fireflies" then
if Wx.fireflies then Wx.fireflies() end
elseif kind == "butterflies" then
-- Existing butterflies pick up this override during their next render update.
elseif kind == "cubes" then
if Wx.cubes then Wx.cubes() end
elseif kind == "ambient" then
if Wx.ambient then Wx.ambient() end
elseif kind == "ripples" or kind == "puddles" or kind == "snowFloor" then
if Wx.all then Wx.all() end
elseif kind == "ghost" or kind == "echoHand" then
-- Their render loops read the saved override for newly spawned afterimages.
elseif kind == "fogHand" or kind == "hand" or kind == "knife" then
if Fn.applyHandColors then Fn.applyHandColors() end
elseif kind == "tint" or kind == "bloom" or kind == "vignette" or kind == "chroma" or kind == "dof" or kind == "retro" or kind == "vhs" or kind == "glitch" then
if Fn.applyScreenFilters then Fn.applyScreenFilters() end
else
if Fn.rebuildVFX then Fn.rebuildVFX() end
end
end
local function openChamsMenu(anchor, kind)
local root = pg:FindFirstChild("OwoClient")
if not root then return end
local old = root:FindFirstChild("OwoVariantMenu")
if old then old:Destroy() end
local options, title
if kind == "self" or kind == "espChams" then
title = "CHAMS STYLE"
options = {"Foggy", "Solid", "Glass", "Outline", "Neon", "Ghost", "Soft"}
elseif kind == "espLayout" then
title = "ESP LAYOUT"
options = {"Compact", "Outlined", "Minimal", "Detailed"}
elseif kind == "trail" then
title = "TRAIL VARIANT"
options = {"Foggy", "Aurora", "Fire", "Stardust", "Hearts", "Neon", "Afterimages", "Divine Rush"}
elseif kind == "wings" then
title = "WING STYLE"
options = {"Crystal", "Angel", "Butterfly", "Moth", "Dragon", "Mechanical", "Void", "Dark Angel", "Neon", "Fairy"}
elseif kind == "crosshair" then
title = "CROSSHAIR SHAPE"
options = {"cross", "dot", "x", "circle"}
elseif kind == "crosshairDot" then
title = "CENTER GLYPH"
options = {"Tiny Dot", "Ring Dot", "Star Center", "Diamond Center"}
elseif kind == "crosshairOutline" then
title = "CROSSHAIR EDGE"
options = {"Thin Edge", "Bold Edge", "Glow Edge", "Double Edge"}
elseif kind == "rain" then title = "RAIN VARIANT"; options = {"Downpour", "Drizzle", "Slanted Storm", "Meteoric"}
elseif kind == "snow" then title = "SNOW VARIANT"; options = {"Flurries", "Blizzard", "Soft Drift", "Sparkling"}
elseif kind == "fog" then title = "FOG VARIANT"; options = {"Low Mist", "Dense Fog", "Rolling Haze", "Dreamy Glow"}
elseif kind == "cubes" or kind == "ambient" then title = "GEOMETRY VARIANT"; options = {"Cubes", "Diamonds", "Wireframe", "Soft Orbs"}
elseif kind == "fireflies" or kind == "butterflies" then title = "PARTICLE VARIANT"; options = {"Float", "Swirl", "Burst", "Drift"}
elseif kind == "ghost" then title = "AFTERIMAGE TRAIL"; options = {"Soft Echo", "Stacked Echo", "Wire Echo", "Long Echo"}
elseif kind == "orbs" then title = "ORBIT GEOMETRY"; options = {"Orbit Spheres", "Orbit Diamonds", "Orbit Runes", "Orbit Shards"}
elseif kind == "glow" then title = "GLOW DESIGN"; options = {"Soft Halo", "Double Rim", "Pulse Glow", "Outline Glow"}
elseif kind == "halo" then title = "HALO DESIGN"; options = {"Orbit Halo", "Double Halo", "Broken Halo", "Solar Crown"}
elseif kind == "crown" then title = "CROWN DESIGN"; options = {"Royal Points", "Triple Crown", "Jagged Crown", "Halo Circlet"}
elseif kind == "aura" then title = "AURA RING DESIGN"; options = {"Arcane Sigil", "Solar Star", "Void Spiral", "Tech Grid"}
elseif kind == "lightning" then title = "LIGHTNING PATTERN"; options = {"Forked Arc", "Spiral Coil", "Ground Strike", "Burst Web"}
elseif kind == "fire" then title = "FIRE AURA SHAPE"; options = {"Flame Pillars", "Ember Swarm", "Fire Spiral", "Inferno Burst"}
elseif kind == "sparkle" then title = "SPARKLE DESIGN"; options = {"Starfall", "Orbiting Dust", "Pulse Stars", "Crystal Shards"}
elseif kind == "footsteps" then title = "FOOTSTEP DESIGN"; options = {"Ember Prints", "Rune Marks", "Shock Puffs", "Spark Trails"}
elseif kind == "jumpRing" or kind == "landRing" then title = "IMPACT SHAPE"; options = {"Double Shockwave", "Star Burst", "Hex Pulse", "Runic Burst"}
elseif kind == "neonBody" then title = "BODY MATERIAL DESIGN"; options = {"Neon Shell", "Forcefield", "Glass Prism", "Metallic Glow"}
elseif kind == "rainbowChar" then title = "RAINBOW ANIMATION"; options = {"Rainbow Wave", "Hue Bands", "Prism Pulse", "Color Drift"}
elseif kind == "playerTrans" then title = "TRANSPARENCY DESIGN"; options = {"Ghost Fade", "Glass Skin", "Phantom", "Outline Silhouette"}
elseif kind == "cape" then title = "CAPE CUT"; options = {"Royal Cape", "Short Mantle", "Wing Cape", "Hologram Cape"}
elseif kind == "santaHat" then title = "HAT DESIGN"; options = {"Classic", "Long Flop", "Frosted", "Candy Trim"}
elseif kind == "pickaxe" then title = "BACK PICKAXE SKIN"; options = {"Candy Cane", "Classic Iron", "Golden", "Crystal", "Inferno", "Void", "Frostbite"}
elseif kind == "charOutline" or kind == "worldOutline" then title = "OUTLINE DESIGN"; options = {"Fine Edge", "Bold Edge", "Soft Edge", "Double Edge"}
elseif kind == "espNames" or kind == "espHealth" or kind == "espDistance" then title = "ESP DISPLAY DESIGN"; options = {"Compact", "Outlined", "Minimal", "Detailed"}
elseif kind == "vignette" then title = "VIGNETTE SHAPE"; options = {"Soft Corners", "Cinema Bars", "Dark Frame", "Focus Tunnel"}
elseif kind == "bloom" then title = "BLOOM PROFILE"; options = {"Soft Bloom", "Lens Glow", "Dream Bloom", "Hard Glow"}
elseif kind == "tint" then title = "TINT PROFILE"; options = {"Soft Wash", "Cinematic", "Dream Glass", "High Contrast"}
elseif kind == "vhs" then title = "VHS DESIGN"; options = {"Tape Lines", "Blue Tape", "Warm Tape", "Dense Scanlines"}
elseif kind == "glitch" then title = "GLITCH PATTERN"; options = {"RGB Tear", "Red Shift", "Blue Shift", "Hard Flash"}
elseif kind == "dof" then title = "DEPTH OF FIELD"; options = {"Portrait Focus", "Dream Bokeh", "Cinematic", "Deep Focus"}
elseif kind == "screenShake" then title = "CAMERA SHAKE"; options = {"Default", "Impact Punch", "Micro Jitter", "Roll Wave"}
elseif kind == "stretch" then title = "ASPECT DESIGN"; options = {"Classic 4:3", "Tactical 5:4", "Subtle Wide", "Ultra Wide"}
elseif kind == "smoothCamera" then title = "CAMERA FEEL"; options = {"Snappy", "Silky", "Cinematic Heavy", "Floaty"}
elseif kind == "sprintFov" then title = "SPRINT FOV"; options = {"Subtle Push", "Fast Zoom", "Wide Sprint", "Tunnel Sprint"}
elseif kind == "cameraRoll" then title = "CAMERA LEAN"; options = {"Subtle Lean", "Arcade Lean", "Heavy Lean", "No Roll"}
elseif kind == "motionBlur" then title = "MOTION BLUR"; options = {"Default", "Directional Streak", "Soft Cinematic", "Heavy Smear"}
elseif kind == "reflective" then title = "WORLD REFLECTION"; options = {"Polished", "Wet Glass", "Chrome", "Soft Satin"}
elseif kind == "realistic" then title = "REALISM PROFILE"; options = {"Natural", "Cinematic", "Soft", "High Detail"}
elseif kind == "fullbright" then title = "FULLBRIGHT PROFILE"; options = {"Studio Bright", "Warm Day", "Cool Night", "Flat White"}
elseif kind == "skybox" then title = "SKYBOX DESIGN"; options = {"Black Hole", "Aurora", "Galaxy", "Nebula", "Starry Night"}
elseif kind == "fpsBoost" then title = "PERFORMANCE PROFILE"; options = {"Balanced", "Maximum FPS", "Low Effects", "Minimal"}
elseif kind == "ripples" then title = "WATER RIPPLE DESIGN"; options = {"Twin Rings", "Ripple Bloom", "Shock Rings", "Wide Waves"}
elseif kind == "puddles" then title = "PUDDLE DESIGN"; options = {"Mirror Pools", "Neon Circles", "Hex Pools", "Soft Pools"}
elseif kind == "snowFloor" then title = "SNOW PATCH DESIGN"; options = {"Powder Patches", "Hex Snow", "Crystal Flakes", "Frost Rings"}
elseif kind == "thunder" then title = "THUNDER WEATHER"; options = {"Double Flash", "Rapid Burst", "Soft Glow", "Violet Storm"}
elseif kind == "meteor" then title = "METEOR DESIGN"; options = {"Classic Meteor", "Comet Tail", "Plasma Core", "Rock Shards"}
elseif kind == "echoHand" then title = "HAND AFTERIMAGE"; options = {"Soft Echo", "Stacked Echo", "Wire Echo", "Long Echo"}
elseif kind == "fogHand" then title = "HAND FOG DESIGN"; options = {"Smoke Puff", "Spiral Mist", "Spark Fog", "Heavy Vapor"}
elseif kind == "knife" then
local isKarambit = string.find(string.lower(tostring(feat.knifeModel or "butterfly")), "karambit", 1, true) ~= nil
local modelName = isKarambit and "KARAMBIT" or "BUTTERFLY KNIFE"
title = modelName .. " SKINS"
local skins = isKarambit and {"Default", "Candy Cane", "Crimson", "Sapphire", "Void", "Toxic"} or {"Default", "Candy Cane", "Crimson", "Sapphire", "Golden", "Neon Circuit", "Void"}
options = {}
for _, skinName in ipairs(skins) do options[#options+1] = "Skin: " .. skinName end
options[#options+1] = "────────────"
options[#options+1] = "Style: Default"
options[#options+1] = "Style: Ghosted"
options[#options+1] = "Style: Neon Edge"
options[#options+1] = "Style: Metallic"
elseif kind == "hand" then title = "FIRST PERSON HAND STYLE"; options = {"Default", "Ghosted", "Neon Edge", "Metallic"}
elseif kind == "teamCheck" then title = "TEAM FILTER"; options = {"Default", "Only Enemies", "All Players", "Neutral Focus"}
elseif kind == "chroma" or kind == "retro" then title = "SCREEN FX PROFILE"; options = {"Subtle", "Cinematic", "Dream", "Intense"}
else
title = (tostring(kind or "visual"):gsub("%u", " %0"):upper()) .. " OPTIONS"
options = {}
end
local mouse = UIS:GetMouseLocation()
local view = camera and camera.ViewportSize or Vector2.new(800,600)
local width, rowH, topH = 202, 28, 30
local colorH = 36
local height = topH + #options * rowH + colorH + 12
local x = math.clamp(mouse.X, 4, math.max(4, view.X-width-4))
local y = math.clamp(mouse.Y, 4, math.max(4, view.Y-height-4))
local menu = new("Frame", {
Name="OwoVariantMenu", Size=UDim2.fromOffset(width,height),
Position=UDim2.fromOffset(x,y), BackgroundColor3=T.Panel,
BorderSizePixel=0, ZIndex=200, Active=true, Parent=root
})
corner(menu, 8); stroke(menu, 1, 0.25, T.Line, true)
new("TextLabel", {
Size=UDim2.new(1,-14,0,topH), Position=UDim2.fromOffset(8,0),
BackgroundTransparency=1, Text=title, TextColor3=T.Accent,
Font=Enum.Font.GothamBold, TextSize=10,
TextXAlignment=Enum.TextXAlignment.Left, ZIndex=201, Parent=menu
})
for i, name in ipairs(options) do
local b = new("TextButton", {
Size=UDim2.new(1,-12,0,rowH-3), Position=UDim2.fromOffset(6,topH+(i-1)*rowH),
BackgroundColor3=T.Card, BorderSizePixel=0, Text=name,
TextColor3=T.Text, Font=Enum.Font.GothamMedium, TextSize=11, TextXAlignment=Enum.TextXAlignment.Left,
AutoButtonColor=true, ZIndex=202, Active=true, Parent=menu
})
corner(b,5)
new("UIPadding", {PaddingLeft=UDim.new(0,9), PaddingRight=UDim.new(0,5), Parent=b})
b.MouseButton1Click:Connect(function()
if kind == "self" then
feat.selfChamsStyle = name
Fn.rebuildVFX()
elseif kind == "espChams" then
feat.espChamsStyle = name
local styles = {
Foggy={fill=0.78,outline=0.12}, Solid={fill=0.05,outline=0},
Glass={fill=0.84,outline=0.08}, Outline={fill=1,outline=0},
Neon={fill=0.28,outline=0}, Ghost={fill=0.48,outline=0.35},
Soft={fill=0.62,outline=0.5},
}
local style = styles[name] or styles.Foggy
for _, data in pairs(Fn.espData or {}) do
if data.highlight then
data.highlight.FillTransparency = style.fill
data.highlight.OutlineTransparency = style.outline
data.highlight.Enabled = feat.espEnabled and feat.espChams
end
end
if Fn.refreshEsp then Fn.refreshEsp() end
elseif kind == "trail" then
feat.trailStyle = name
Fn.rebuildVFX()
elseif kind == "wings" then
feat.wingsStyle = name
Fn.rebuildVFX()
elseif kind == "crosshair" then
feat.crosshairStyle = name
Fn.rebuildCrosshair()
elseif kind == "crosshairDot" or kind == "crosshairOutline" then
feat.visualStyles[kind] = name
Fn.rebuildCrosshair()
elseif kind == "knife" then
if name == "────────────" then menu:Destroy(); return end
if name:sub(1,6) == "Skin: " then
local skinName = name:sub(7)
if string.find(string.lower(tostring(feat.knifeModel or "butterfly")), "karambit", 1, true) then
if skinName == "Golden" then skinName = "Default" end
feat.karambitSkin = skinName
else
feat.butterflyKnifeSkin = skinName
end
elseif name:sub(1,7) == "Style: " then
feat.visualStyles.knife = name:sub(8)
end
if Fn.applyHandColors then Fn.applyHandColors() end
else
feat.visualStyles[kind] = name
if kind == "rain" then Wx.rain()
elseif kind == "snow" then Wx.snow()
elseif kind == "fog" then Wx.fog()
elseif kind == "cubes" then Wx.cubes()
elseif kind == "ambient" then Wx.ambient()
elseif kind == "fireflies" then Wx.fireflies()
elseif kind == "orbs" then Fn.rebuildOrbs()
elseif kind == "aura" then Fn.rebuildAuraRing()
elseif kind == "lightning" then Fn.rebuildLightning()
elseif kind == "glow" or kind == "halo" or kind == "crown" or kind == "cape" or kind == "santaHat" or kind == "pickaxe" or kind == "fire" or kind == "sparkle" or kind == "footsteps" or kind == "jumpRing" or kind == "landRing" then
if kind == "pickaxe" then feat.pickaxeSkin = name end
Fn.rebuildVFX()
elseif kind == "neonBody" then Fn.applyNeonBody()
elseif kind == "rainbowChar" then Fn.applyRainbowChar()
elseif kind == "playerTrans" then Fn.applyPlayerTransparency()
elseif kind == "charOutline" then Fn.rebuildVFX()
elseif kind == "espLayout" or kind == "espNames" or kind == "espHealth" or kind == "espDistance" then Fn.refreshEsp()
elseif kind == "chroma" or kind == "dof" or kind == "retro" or kind == "vhs" or kind == "glitch" then Fn.applyScreenFilters()
elseif kind == "tint" or kind == "bloom" or kind == "vignette" then -- consumed by the screen-effects render loop
elseif kind == "ghost" or kind == "echoHand" or kind == "fogHand" then -- consumed by the corresponding animation loops
elseif kind == "reflective" then Fn.applyReflective()
elseif kind == "fullbright" then Fn.applyFB()
elseif kind == "skybox" then Fn.setSky(name)
elseif kind == "motionBlur" or kind == "screenShake" then -- consumed by camera effects
elseif kind == "stretch" then
local map = { ["Classic 4:3"]=0.75, ["Tactical 5:4"]=0.8, ["Subtle Wide"]=0.88, ["Ultra Wide"]=0.96 }
feat.stretchAmount = map[name] or 0.75
elseif kind == "smoothCamera" then
local map = {Snappy=1.6, Silky=1.0, ["Cinematic Heavy"]=0.52, Floaty=0.28}
feat.smoothCameraStrength = map[name] or 1
elseif kind == "sprintFov" then
local map = { ["Subtle Push"]=5, ["Fast Zoom"]=9, ["Wide Sprint"]=15, ["Tunnel Sprint"]=22 }
feat.sprintFovBoost = map[name] or 8
elseif kind == "cameraRoll" then
local map = { ["Subtle Lean"]=2, ["Arcade Lean"]=5, ["Heavy Lean"]=9, ["No Roll"]=0 }
feat.cameraRollAmount = map[name] or 3
elseif kind == "teamCheck" then
feat.espTeamCheck = name == "Only Enemies" or name == "Default"
elseif kind == "fpsBoost" then
feat.visualStyles[kind] = name
Fn.applyFpsBoost()
elseif kind == "worldOutline" then
-- The outline renderer reads this style on its next update.
end
end
notify("Visual style", name .. " selected")
menu:Destroy()
end)
end
local colorButton = new("TextButton", {
Size=UDim2.new(1,-12,0,29), Position=UDim2.fromOffset(6, topH + #options * rowH + 4),
BackgroundColor3=T.Card, BorderSizePixel=0, Text="◉ CHANGE COLOR",
TextColor3=T.Text, Font=Enum.Font.GothamBold, TextSize=10,
AutoButtonColor=true, ZIndex=202, Active=true, Parent=menu
})
corner(colorButton, 5)
local swatch = new("Frame", {Size=UDim2.fromOffset(12,12), Position=UDim2.new(1,-22,0.5,-6), BackgroundColor3=feat.visualColors[kind] or EFFECT_COLOR, BorderSizePixel=0, ZIndex=203, Parent=colorButton})
corner(swatch, 6); stroke(swatch, 1, 0.25, T.Line, true)
colorButton.MouseButton1Click:Connect(function()
local m = UIS:GetMouseLocation()
local startColor = feat.visualColors[kind] or EFFECT_COLOR
menu:Destroy()
if Picker then
Picker.open(startColor, function(col, final)
if final then applyVisualColor(kind, col) end
end, m.X, m.Y)
end
end)
end
local function mkT(p, label, def, cb, kbName, regName)
local st = def or false
local row = new("TextButton",{Size=UDim2.new(0.5,-5,0,ROW_H),BackgroundColor3=T.Card,BackgroundTransparency=TR.Card,BorderSizePixel=0,AutoButtonColor=false,Text="",Parent=p})
row:SetAttribute("OwoLbl", tostring(label):lower())
corner(row, RM); stroke(row, 1, 0.55, T.Line); regRef(row, "BackgroundColor3", "Card"); regCard(row)
hoverFx(row)
local kW = kbName and 46 or 0
local lbl = new("TextLabel",{Size=UDim2.new(1,-kW-76,1,0),Position=UDim2.new(0,16,0,0),BackgroundTransparency=1,Text=label,TextColor3=T.Text,Font=Enum.Font.GothamMedium,TextSize=12,TextXAlignment=Enum.TextXAlignment.Left,TextTruncate=Enum.TextTruncate.AtEnd,ZIndex=3,Parent=row})
regRef(lbl, "TextColor3", "Text")
local chip
if kbName then
chip = new("TextButton",{Size=UDim2.new(0,42,0,20),Position=UDim2.new(1,-106,0.5,-10),BackgroundColor3=T.Panel,BackgroundTransparency=TR.Card,BorderSizePixel=0,Text="—",TextColor3=T.Dim,Font=Enum.Font.GothamBold,TextSize=10,AutoButtonColor=false,ZIndex=4,Parent=row})
corner(chip, 6); stroke(chip, 1, 0.55, T.Line)
chip.MouseButton1Click:Connect(function() openKeyPrompt(kbName) end)
end
local track = new("Frame",{Size=UDim2.new(0,40,0,22),Position=UDim2.new(1,-54,0.5,-11),BackgroundColor3=st and T.On or T.Off,BackgroundTransparency=st and 0 or 0.25,BorderSizePixel=0,ZIndex=2,Parent=row})
corner(track, 11)
local trackGrad = gradient(track, T.Accent, T.Accent2, 0); trackGrad.Enabled = st
local trackStroke = stroke(track, 1, st and 0.5 or 0.7, st and T.Accent or T.Line, true)
local knob = new("Frame",{Size=UDim2.new(0,16,0,16),Position=st and UDim2.new(1,-18,0.5,-8) or UDim2.new(0,3,0.5,-8),BackgroundColor3=st and Color3.new(1,1,1) or Color3.fromRGB(240,240,244),BorderSizePixel=0,ZIndex=3,Parent=track}); corner(knob, 8)
local function setSt(v)
st = v
TS:Create(track, TweenInfo.new(sdur(0.25), Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {BackgroundColor3 = st and T.On or T.Off, BackgroundTransparency = st and 0 or 0.25}):Play()
TS:Create(knob, TweenInfo.new(sdur(0.35), Enum.EasingStyle.Back, Enum.EasingDirection.Out), {Position = st and UDim2.new(1,-18,0.5,-8) or UDim2.new(0,3,0.5,-8), BackgroundColor3 = st and Color3.new(1,1,1) or Color3.fromRGB(240,240,244)}):Play()
trackGrad.Enabled = st
trackStroke.Color = st and T.Accent or T.Line
trackStroke.Transparency = st and 0.5 or 0.7
if cb then pcall(cb, st) end
end
row.MouseButton1Click:Connect(function()
playUiSoundLayered(st and "toggleOff" or "toggleOn")
setSt(not st)
end)
local variantKind = ({
SelfChams="self", EspChams="espChams", EspEnabled="espLayout", VFXTrail="trail", Crosshair="crosshair",
WxRain="rain", WxRipples="ripples", WxPuddles="puddles", WxSnow="snow", WxSnowFloor="snowFloor", WxFog="fog", WxThunder="thunder", WxStorm="storm", WxMeteor="meteor",
FxCubes="cubes", FxAmbient="ambient", FxFireflies="fireflies", FxButterflies="butterflies", FxGhost="ghost",
FxTint="tint", FxBloom="bloom", FxVignette="vignette", FxChroma="chroma", FxDOF="dof", FxRetro="retro", FxVHS="vhs", FxGlitch="glitch",
ScreenShake="screenShake", MotionBlur="motionBlur", Glossy="reflective", Realistic="realistic", Fullbright="fullbright",
FpsBoost="fpsBoost", Stretch="stretch", SmoothCam="smoothCamera", SprintFov="sprintFov", CamRoll="cameraRoll", EspTeam="teamCheck",
VFXGlow="glow", VFXNeon="neonBody", RainbowChar="rainbowChar", PlayerTrans="playerTrans",
VFXHalo="halo", VFXWings="wings", VFXCrown="crown", VFXSanta="santaHat", VFXCape="cape", VFXPickaxe="pickaxe",
CharOutline="charOutline", WorldOutline="worldOutline", KnifeOut="knife", HandOut="hand", EchoHand="echoHand", FogHand="fogHand",
AuraRing="aura", OrbitOrbs="orbs", VFXFire="fire", VFXSparkle="sparkle", LightningAura="lightning", FireFootsteps="footsteps",
VFXJumpRing="jumpRing", VFXLandRing="landRing", ChDot="crosshairDot", ChOutline="crosshairOutline",
EspNames="espNames", EspHealth="espHealth", EspDistance="espDistance"
})[kbName]
if not variantKind and kbName and kbName:sub(1,3) == "Sky" then variantKind = "skybox"
end
if variantKind then
row.MouseButton2Click:Connect(function()
openChamsMenu(row, variantKind)
end)
end
if regName then
ToggleReg[regName] = setSt
end
if kbName then
Keybinds[kbName] = {key=nil, label=label, isToggle=true, getState=function() return st end, setState=setSt}
ToggleReg[kbName] = setSt
task.spawn(function()
local last
while row.Parent do
local k = Keybinds[kbName].key; local t = k and k.Name or "—"
if t ~= last then chip.Text = t; chip.TextColor3 = k and T.Accent or T.Dim; last = t end
task.wait(0.2)
end
end)
end
end
local function mkB(p, label, cb, kbName)
local btn = new("TextButton",{Size=UDim2.new(0.5,-5,0,ROW_H),BackgroundColor3=T.Card,BackgroundTransparency=TR.Card,BorderSizePixel=0,AutoButtonColor=false,Text="",Parent=p})
btn:SetAttribute("OwoLbl", tostring(label):lower())
corner(btn, RM); stroke(btn, 1, 0.55, T.Line); regRef(btn, "BackgroundColor3", "Card"); regCard(btn)
hoverFx(btn)
local kW = kbName and 46 or 0
local lbl = new("TextLabel",{Size=UDim2.new(1,-kW-40,1,0),Position=UDim2.new(0,16,0,0),BackgroundTransparency=1,Text=label,TextColor3=T.Text,Font=Enum.Font.GothamMedium,TextSize=12,TextXAlignment=Enum.TextXAlignment.Left,TextTruncate=Enum.TextTruncate.AtEnd,ZIndex=3,Parent=btn})
regRef(lbl, "TextColor3", "Text")
local arrow = new("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(0,20,1,0),Position=UDim2.new(1,-28,0,0),Font=Enum.Font.GothamBold,Text="›",TextColor3=T.Muted,TextSize=16,TextXAlignment=Enum.TextXAlignment.Right,ZIndex=3,Parent=btn})
regRef(arrow, "TextColor3", "Muted")
if kbName then
local chip = new("TextButton",{Size=UDim2.new(0,42,0,20),Position=UDim2.new(1,-64,0.5,-10),BackgroundColor3=T.Panel,BackgroundTransparency=TR.Card,BorderSizePixel=0,Text="—",TextColor3=T.Dim,Font=Enum.Font.GothamBold,TextSize=10,AutoButtonColor=false,ZIndex=4,Parent=btn})
corner(chip, 6); stroke(chip, 1, 0.55, T.Line)
chip.MouseButton1Click:Connect(function() openKeyPrompt(kbName) end)
Keybinds[kbName] = {key=nil, label=label, isToggle=false, fire=cb}
end
btn.MouseButton1Click:Connect(function() playUiSoundLayered("click"); if cb then pcall(cb) end end)
return btn
end
local function mkS(p, label, mn, mx, def, cb, saveName, isF)
local v = def
local row = new("Frame",{Size=UDim2.new(0.5,-5,0,ROW_H),BackgroundColor3=T.Card,BackgroundTransparency=TR.Card,BorderSizePixel=0,Parent=p})
row:SetAttribute("OwoLbl", tostring(label):lower())
corner(row, RM); stroke(row, 1, 0.55, T.Line); regRef(row, "BackgroundColor3", "Card"); regCard(row)
local lbl = new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,16,0,7),Size=UDim2.new(1,-96,0,16),Font=Enum.Font.GothamMedium,Text=label,TextColor3=T.Text,TextSize=12,TextXAlignment=Enum.TextXAlignment.Left,TextTruncate=Enum.TextTruncate.AtEnd,ZIndex=3,Parent=row})
regRef(lbl, "TextColor3", "Text")
local vBox = new("Frame",{Position=UDim2.new(1,-66,0,6),Size=UDim2.new(0,52,0,20),BackgroundColor3=T.Accent,BorderSizePixel=0,ZIndex=3,Parent=row})
corner(vBox, 6); gradient(vBox, T.Accent, T.Accent2, 0)
local vLbl = new("TextLabel",{BackgroundTransparency=1,Size=UDim2.new(1,0,1,0),Font=Enum.Font.GothamBold,Text=tostring(v),TextColor3=ON_ACCENT,TextSize=11,ZIndex=4,Parent=vBox})
local track = new("Frame",{Position=UDim2.new(0,16,0,36),Size=UDim2.new(1,-32,0,4),BackgroundColor3=T.Off,BackgroundTransparency=0.2,BorderSizePixel=0,ZIndex=3,Parent=row})
corner(track, 2)
local fill = new("Frame",{Size=UDim2.new((v-mn)/(mx-mn),0,1,0),BackgroundColor3=T.Accent,BorderSizePixel=0,ZIndex=4,Parent=track})
corner(fill, 2); gradient(fill, T.Accent, T.Accent2, 0)
local function setV(nv, force)
nv = math.clamp(nv, mn, mx)
local old = v
if isF then v = math.floor(nv*100+0.5)/100 else v = math.floor(nv+0.5) end
vLbl.Text = tostring(v)
tween(fill, 0.14, {Size = UDim2.new((v-mn)/(mx-mn),0,1,0)}, Enum.EasingStyle.Quad)
if cb and (force or v ~= old) then playUiSound("slider"); pcall(cb, v) end
end
local hit = new("TextButton",{Position=UDim2.new(0,8,0,26),Size=UDim2.new(1,-16,0,28),BackgroundTransparency=1,Text="",AutoButtonColor=false,ZIndex=6,Parent=row})
local d = false
local function isPress(i) return i.UserInputType == Enum.UserInputType.MouseButton1 or i.UserInputType == Enum.UserInputType.Touch end
local function fx(x)
local w = track.AbsoluteSize.X
if w <= 0 then return end
setV(mn + math.clamp((x - track.AbsolutePosition.X)/w, 0, 1) * (mx - mn))
end
hit.InputBegan:Connect(function(i)
if not isPress(i) then return end
d = true
if p:IsA("ScrollingFrame") then p.ScrollingEnabled = false end
fx(i.Position.X)
end)
UIS.InputChanged:Connect(function(i)
if d and (i.UserInputType == Enum.UserInputType.MouseMovement or i.UserInputType == Enum.UserInputType.Touch) then fx(i.Position.X) end
end)
UIS.InputEnded:Connect(function(i)
if d and isPress(i) then d = false; if p:IsA("ScrollingFrame") then p.ScrollingEnabled = true end end
end)
if saveName then SliderReg[saveName] = {get=function() return v end, set=function(x) setV(x, true) end} end
end
-- ══════════════════════════════════════════════════════════════
-- COLOR PICKER (every hex box gets a swatch that opens this)
-- ══════════════════════════════════════════════════════════════
Picker = {}
do
local gui = new("ScreenGui",{Name="OwoPicker",ResetOnSpawn=false,IgnoreGuiInset=true,ZIndexBehavior=Enum.ZIndexBehavior.Sibling,DisplayOrder=200,Parent=pg})
local backdrop = new("TextButton",{Size=UDim2.fromScale(1,1),BackgroundTransparency=1,Text="",AutoButtonColor=false,Visible=false,ZIndex=1,Parent=gui})
local panel = new("Frame",{Size=UDim2.new(0,224,0,240),BackgroundColor3=T.Panel,BackgroundTransparency=0.03,BorderSizePixel=0,Visible=false,Active=true,ZIndex=2,Parent=gui})
corner(panel, 14); regRef(panel, "BackgroundColor3", "Panel")
local ps = stroke(panel, 1, 0.4, T.Line, true); regRef(ps, "Color", "Line")
local ttl = new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,16,0,10),Size=UDim2.new(1,-32,0,18),Font=Enum.Font.GothamBold,Text="Color Picker",TextColor3=T.Text,TextSize=13,TextXAlignment=Enum.TextXAlignment.Left,Parent=panel}); regRef(ttl, "TextColor3", "Text")
local sv = new("Frame",{Position=UDim2.new(0,16,0,36),Size=UDim2.new(0,192,0,122),BackgroundColor3=Color3.new(1,0,0),BorderSizePixel=0,ClipsDescendants=true,Parent=panel}); corner(sv, 8)
local wov = new("Frame",{Size=UDim2.fromScale(1,1),BackgroundColor3=Color3.new(1,1,1),BorderSizePixel=0,Parent=sv})
new("UIGradient",{Transparency=NumberSequence.new({NumberSequenceKeypoint.new(0,0),NumberSequenceKeypoint.new(1,1)}),Parent=wov})
local bov = new("Frame",{Size=UDim2.fromScale(1,1),BackgroundColor3=Color3.new(0,0,0),BorderSizePixel=0,Parent=sv})
new("UIGradient",{Rotation=90,Transparency=NumberSequence.new({NumberSequenceKeypoint.new(0,1),NumberSequenceKeypoint.new(1,0)}),Parent=bov})
local svMark = new("Frame",{AnchorPoint=Vector2.new(0.5,0.5),Size=UDim2.new(0,14,0,14),BackgroundTransparency=1,BorderSizePixel=0,ZIndex=3,Parent=sv}); corner(svMark, 7)
new("UIStroke",{Color=Color3.new(1,1,1),Thickness=2,Parent=svMark})
local hue = new("Frame",{Position=UDim2.new(0,16,0,168),Size=UDim2.new(0,192,0,14),BackgroundColor3=Color3.new(1,1,1),BorderSizePixel=0,Parent=panel}); corner(hue, 7)
do
local ks = {}
for i = 0, 6 do ks[#ks+1] = ColorSequenceKeypoint.new(i / 6, Color3.fromHSV(i / 6 >= 1 and 0 or i / 6, 1, 1)) end
new("UIGradient",{Color=ColorSequence.new(ks),Parent=hue})
end
local hueMark = new("Frame",{AnchorPoint=Vector2.new(0.5,0.5),Position=UDim2.new(0,0,0.5,0),Size=UDim2.new(0,6,1,6),BackgroundColor3=Color3.new(1,1,1),BorderSizePixel=0,ZIndex=3,Parent=hue}); corner(hueMark, 3)
new("UIStroke",{Color=Color3.new(0,0,0),Thickness=1,Transparency=0.5,Parent=hueMark})
local prev = new("Frame",{Position=UDim2.new(0,16,0,194),Size=UDim2.new(0,36,0,30),BackgroundColor3=Color3.new(1,1,1),BorderSizePixel=0,Parent=panel}); corner(prev, 8)
local hexBox = new("TextBox",{Position=UDim2.new(0,60,0,194),Size=UDim2.new(0,96,0,30),BackgroundColor3=T.Bg,BackgroundTransparency=0.3,Font=Enum.Font.GothamBold,Text="#FFFFFF",TextColor3=T.Text,TextSize=12,BorderSizePixel=0,ClearTextOnFocus=false,Parent=panel})
corner(hexBox, 8); regRef(hexBox, "BackgroundColor3", "Bg"); regRef(hexBox, "TextColor3", "Text")
local done = new("TextButton",{Position=UDim2.new(0,164,0,194),Size=UDim2.new(0,44,0,30),BackgroundColor3=Color3.new(1,1,1),Text="OK",Font=Enum.Font.GothamBold,TextColor3=ON_ACCENT,TextSize=12,BorderSizePixel=0,AutoButtonColor=false,Parent=panel})
corner(done, 8); gradient(done, T.Accent, T.Accent2, 0)
local cur, cb, dragging = {h=0, s=1, v=1}, nil, nil
local function color() return Color3.fromHSV(cur.h, cur.s, cur.v) end
local function refresh(fire, final)
local c = color()
sv.BackgroundColor3 = Color3.fromHSV(cur.h, 1, 1)
svMark.Position = UDim2.new(cur.s, 0, 1 - cur.v, 0)
hueMark.Position = UDim2.new(cur.h, 0, 0.5, 0)
prev.BackgroundColor3 = c
hexBox.Text = colorToHex(c)
if fire and cb then pcall(cb, c, final) end
end
local function setFromPos(kind, x, y)
if kind == "sv" then
cur.s = math.clamp((x - sv.AbsolutePosition.X) / math.max(sv.AbsoluteSize.X, 1), 0, 1)
cur.v = 1 - math.clamp((y - sv.AbsolutePosition.Y) / math.max(sv.AbsoluteSize.Y, 1), 0, 1)
else
cur.h = math.clamp((x - hue.AbsolutePosition.X) / math.max(hue.AbsoluteSize.X, 1), 0, 0.999)
end
refresh(true, false)
end
local function isPress(i) return i.UserInputType == Enum.UserInputType.MouseButton1 or i.UserInputType == Enum.UserInputType.Touch end
sv.InputBegan:Connect(function(i) if isPress(i) then dragging = "sv"; setFromPos("sv", i.Position.X, i.Position.Y) end end)
hue.InputBegan:Connect(function(i) if isPress(i) then dragging = "hue"; setFromPos("hue", i.Position.X, i.Position.Y) end end)
UIS.InputChanged:Connect(function(i)
if dragging and (i.UserInputType == Enum.UserInputType.MouseMovement or i.UserInputType == Enum.UserInputType.Touch) then setFromPos(dragging, i.Position.X, i.Position.Y) end
end)
UIS.InputEnded:Connect(function(i)
if dragging and isPress(i) then dragging = nil; refresh(true, true) end
end)
hexBox.FocusLost:Connect(function()
local c = hexToColor(hexBox.Text)
if c then cur.h, cur.s, cur.v = c:ToHSV(); refresh(true, true) else refresh(false) end
end)
function Picker.close()
if not panel.Visible then return end
panel.Visible = false; backdrop.Visible = false
if cb then pcall(cb, color(), true) end
cb = nil
end
backdrop.MouseButton1Click:Connect(Picker.close)
done.MouseButton1Click:Connect(function() playUiSoundLayered("click"); Picker.close() end)
function Picker.open(c, onChange, ax, ay)
if panel.Visible then Picker.close() end
cur.h, cur.s, cur.v = c:ToHSV()
cb = onChange
local vp = workspace.CurrentCamera.ViewportSize
local x = math.clamp((ax or 100) - 236, 8, math.max(8, vp.X - 232))
local y = math.clamp((ay or 100) - 20, 8, math.max(8, vp.Y - 248))
panel.Position = UDim2.new(0, x, 0, y)
backdrop.Visible = true; panel.Visible = true
refresh(false)
end
end
local function attachPicker(box, onChange)
local row = box.Parent
local w = box.Size.X.Offset
local sw = new("TextButton",{Size=UDim2.new(0,24,0,24),Position=UDim2.new(1,-w-12-32,0.5,-12),BackgroundColor3=Color3.new(1,1,1),Text="",AutoButtonColor=false,BorderSizePixel=0,ZIndex=4,Parent=row})
corner(sw, 7); stroke(sw, 1, 0.35, T.Line, true)
local function sync() local c = hexToColor(box.Text); if c then sw.BackgroundColor3 = c end end
box:GetPropertyChangedSignal("Text"):Connect(sync); sync()
sw.MouseButton1Click:Connect(function()
playUiSoundLayered("click")
local c = hexToColor(box.Text) or Color3.new(1, 1, 1)
Picker.open(c, function(col, final) box.Text = colorToHex(col); onChange(col, final) end, sw.AbsolutePosition.X, sw.AbsolutePosition.Y)
end)
return sw
end
local function mkInput(p, label, placeholder, width, colorCb)
local row = new("Frame",{Size=UDim2.new(1,-4,0,50),BackgroundColor3=T.Card,BackgroundTransparency=TR.Card,BorderSizePixel=0,Parent=p})
row:SetAttribute("OwoLbl", tostring(label):lower())
corner(row, RM); stroke(row, 1, 0.55, T.Line); regRef(row, "BackgroundColor3", "Card"); regCard(row)
local w = width or 150
local l = new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,16,0,0),Size=UDim2.new(1,-w-(colorCb and 66 or 30),1,0),Font=Enum.Font.GothamMedium,Text=label,TextColor3=T.Text,TextSize=12,TextXAlignment=Enum.TextXAlignment.Left,ZIndex=3,Parent=row})
regRef(l, "TextColor3", "Text")
local box = new("TextBox",{Size=UDim2.new(0,w,0,30),Position=UDim2.new(1,-w-12,0.5,-15),BackgroundColor3=T.Bg,BackgroundTransparency=0.3,Font=Enum.Font.GothamMedium,Text="",PlaceholderText=placeholder or "",TextColor3=T.Text,PlaceholderColor3=T.Muted,TextSize=12,BorderSizePixel=0,ClearTextOnFocus=false,ZIndex=3,Parent=row})
corner(box, 8); stroke(box, 1, 0.55, T.Line)
regRef(box, "BackgroundColor3", "Bg"); regRef(box, "TextColor3", "Text")
if colorCb then attachPicker(box, colorCb) end
return box
end
local function mkAccentBtn(p, text, cb, h)
local b = new("TextButton",{Size=UDim2.new(1,-4,0,h or 42),BackgroundColor3=Color3.new(1,1,1),Text=text,Font=Enum.Font.GothamBold,TextColor3=ON_ACCENT,TextSize=12,BorderSizePixel=0,AutoButtonColor=false,Parent=p})
b:SetAttribute("OwoLbl", tostring(text):lower())
corner(b, RM); gradient(b, T.Accent, T.Accent2, 0)
b.MouseButton1Click:Connect(function() playUiSoundLayered("click"); pcall(cb) end)
return b
end
-- ══════════════════════════════════════════════════════════════
-- TRANSPARENCY + GLASS CONTROL
-- ══════════════════════════════════════════════════════════════
Fn.applyAllTransparency = function()
if UI.mainPanel then UI.mainPanel.BackgroundTransparency = TR.Window end
for _, f in ipairs(UI.cards) do if f.Parent then f.BackgroundTransparency = TR.Card end end
for _, f in pairs(overlays) do
if not f:GetAttribute("Bare") and not f:GetAttribute("LBare") then f.BackgroundTransparency = TR.Overlay end
end
end
Fn.setOpacity = function(amount)
TR.Window = amount; TR.Sidebar = amount; TR.Content = amount
TR.Title = amount; TR.Card = amount
TR.Overlay = amount; TR.Notify = amount
Fn.applyAllTransparency()
end
Fn.applyGlassTransparency = function()
local t = Glass.winT()
TR.Window = t; TR.Sidebar = t; TR.Content = t; TR.Title = t
TR.Card = math.clamp(t * 0.6 + 0.12, 0.3, 0.7)
TR.Overlay = math.clamp(t * 0.7 + 0.05, 0.3, 0.75)
TR.Notify = math.clamp(t * 0.7, 0.2, 0.7)
Fn.applyAllTransparency()
end
Fn.setGlass = function(on, quiet)
if on == Glass.on then return end
Glass.on = on
for _, g in ipairs(GlassGrads) do if g.Parent then g.Enabled = on end end
for _, e in ipairs(GlassStrokes) do if e.s.Parent then e.g.Enabled = on; e.s.Transparency = on and 0.2 or e.o end end
Glass.refreshAll()
if on then Fn.applyGlassTransparency() else Fn.setOpacity(UI.opacity / 100) end
if ToggleReg.LiquidGlass then pcall(ToggleReg.LiquidGlass, on) end
if Fn.refreshKb then Fn.refreshKb() end
if Fn.updateHud then Fn.updateHud() end
if not quiet then notify("Liquid Glass", on and "ON" or "OFF", on) end
end
Fn.setGlassStyle = function(name, quiet)
local s = Glass.styles[name]; if not s then return end
Glass.applying = true
local map = {clarity="GlassClarity", blur="GlassBlur", shine="GlassShine", tint="GlassTint"}
for k, sn in pairs(map) do
Glass[k] = s[k]
if SliderReg[sn] then pcall(SliderReg[sn].set, s[k]) end
end
Glass.applying = false
Glass.style = name
if Glass.paintStyleBtns then Glass.paintStyleBtns() end
if not Glass.on then Fn.setGlass(true, true) else Fn.applyGlassTransparency() end
Glass.refreshAll()
if not quiet then notify("Liquid Glass", "Style: " .. name) end
end
Fn.setEffectColor = function(c, quiet)
EFFECT_COLOR = c
if UI.colorPreview then UI.colorPreview.BackgroundColor3 = c end
if UI.colorInput then UI.colorInput.Text = colorToHex(c) end
Fn.rebuildVFX(); Wx.color()
if Fn.rebuildAuraRing then Fn.rebuildAuraRing() end
if Fn.rebuildOrbs then Fn.rebuildOrbs() end
if Fn.skyRecolor then Fn.skyRecolor() end
if Fn.rebuildCrosshair then Fn.rebuildCrosshair() end
if not quiet then notify("Color", "Applied to all effects") end
end
Fn.hudPack = function(presetName)
if presetName and PRESETS[presetName] then
for k, v in pairs(PRESETS[presetName]) do T[k] = v end
applyTheme(); Fn.applyAllTransparency(); Fn.refreshKb()
end
UI.hudSync = true
Fn.setEffectColor(T.Accent, true)
for _, n in ipairs({"MusicHud","Coords","SpeedHud","KbOverlay","Potions","FxTint","FxVignette","FxBloom","Crosshair"}) do
if ToggleReg[n] then ToggleReg[n](true) end
end
Fn.updateHud()
notify("HUD Pack", (presetName or "Current theme") .. " HUD enabled")
end
-- Smooth theme transition
Fn.smoothThemeApply = function(preset, duration)
duration = duration or 0.6
local fromColors = {}
for k, v in pairs(preset) do if typeof(T[k]) == "Color3" then fromColors[k] = T[k] end end
local start = os.clock()
task.spawn(function()
while os.clock() - start < duration do
local t = (os.clock() - start) / duration
local et = 1 - (1 - t)^3
for k, target in pairs(preset) do
if fromColors[k] then
T[k] = fromColors[k]:Lerp(target, et)
else
T[k] = target
end
end
applyTheme()
Fn.applyAllTransparency()
RS.RenderStepped:Wait()
end
for k, v in pairs(preset) do T[k] = v end
applyTheme(); Fn.applyAllTransparency()
end)
end
-- ══════════════════════════════════════════════════════════════
-- PAGES
-- ══════════════════════════════════════════════════════════════
local pMove, pCombat, pVis, pOver, pTheme, pSaves, pMisc, pMusic, pMore, pFriends
pMove = mkListPage("movement"); pCombat = mkListPage("combat"); pVis = mkListPage("visuals"); pOver = mkListPage("overlays")
pTheme = mkListPage("themes"); pMusic = mkListPage("music"); pSaves = mkListPage("saves")
pMore = mkListPage("more"); pMisc = mkListPage("misc"); pFriends = mkListPage("friends")
-- COMBAT TARGETING
-- Camera target lock / aim assist and orbit practice controls. Target selection is local-client based.
local CombatState = { target=nil, auraActive=false, auraAngle=0, orbitDirection=1, nextMoveAt=0, savedWalkSpeed=nil, teleported=false, lastProgressAt=0, lastMoveGoal=nil }
local function combatCharacter(plr)
if not plr or plr == player then return nil end
local ch = plr.Character
if not ch then return nil end
local hum = ch:FindFirstChildOfClass("Humanoid")
local head = ch:FindFirstChild("Head")
local root = ch:FindFirstChild("HumanoidRootPart")
if not hum or hum.Health <= 0 or not head or not root then return nil end
return ch, hum, head, root
end
local function combatTargetVisible(plr)
local ch, _, head = combatCharacter(plr)
local cam = workspace.CurrentCamera or camera
if not ch or not head or not cam then return false end
local origin = cam.CFrame.Position
local direction = head.Position - origin
if direction.Magnitude < 0.01 then return true end
local excluded = {}
local myChar = player.Character
if myChar then table.insert(excluded, myChar) end
if cam then table.insert(excluded, cam) end
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Exclude
params.FilterDescendantsInstances = excluded
params.IgnoreWater = true
-- Ignore fully invisible helper parts, but stop when a real world surface
-- blocks the line from the camera to the target's character.
for _ = 1, 8 do
local result = workspace:Raycast(origin, direction, params)
if not result then return true end
local hit = result.Instance
if hit and hit:IsDescendantOf(ch) then return true end
if hit and hit:IsA("BasePart") and hit.Transparency >= 0.95 then
table.insert(excluded, hit)
params.FilterDescendantsInstances = excluded
else
return false
end
end
return false
end
local function combatTargetValid(plr)
local ch, hum, head, root = combatCharacter(plr)
if not ch then return false end
local myChar = player.Character
local myRoot = myChar and myChar:FindFirstChild("HumanoidRootPart")
if not myRoot then return false end
if feat.combatTeamCheck and player.Team ~= nil and plr.Team == player.Team then return false end
if (root.Position - myRoot.Position).Magnitude > (feat.combatMaxDistance or 500) then return false end
if feat.combatWallCheck and not combatTargetVisible(plr) then return false end
return true
end
local function findCombatTarget()
local cam = workspace.CurrentCamera or camera
if not cam then return nil end
local vp = cam.ViewportSize
local center = Vector2.new(vp.X * 0.5, vp.Y * 0.5)
local best, bestScore = nil, math.huge
for _, plr in ipairs(Players:GetPlayers()) do
if combatTargetValid(plr) then
local _, _, head, root = combatCharacter(plr)
if head and root then
local pos, onScreen = cam:WorldToViewportPoint(head.Position)
local screenDistance = (Vector2.new(pos.X, pos.Y) - center).Magnitude
if onScreen and screenDistance <= (feat.combatAimFov or 260) and screenDistance < bestScore then
best, bestScore = plr, screenDistance
end
end
end
end
return best
end
local function getCombatTarget()
if CombatState.target and combatTargetValid(CombatState.target) then return CombatState.target end
CombatState.target = findCombatTarget()
return CombatState.target
end
local function aimCameraAtTarget(plr, dt, snap)
local cam = workspace.CurrentCamera or camera
local _, _, head = combatCharacter(plr)
if not cam or not head then return end
local goal = CFrame.lookAt(cam.CFrame.Position, head.Position)
if snap then cam.CFrame = goal else cam.CFrame = cam.CFrame:Lerp(goal, math.clamp((dt or 1/60) * 14, 0, 1)) end
end
RS.RenderStepped:Connect(function(dt)
if not (feat.combatTargetLock or feat.combatAimbot or feat.combatSilentAura) then
CombatState.target = nil
return
end
local target = getCombatTarget()
if target then
-- Aimbot is a direct camera aim; Target Lock and Silent Aura use a smoothed camera turn.
aimCameraAtTarget(target, dt, feat.combatAimbot)
end
end)
RS.PreSimulation:Connect(function(dt)
local ch = player.Character
local hum = ch and ch:FindFirstChildOfClass("Humanoid")
local root = ch and ch:FindFirstChild("HumanoidRootPart")
if not feat.combatSilentAura then
if CombatState.auraActive then
if hum then
hum.WalkSpeed = CombatState.savedWalkSpeed or feat.walkSpeed or 16
if CombatState.savedAutoRotate ~= nil then
hum.AutoRotate = CombatState.savedAutoRotate
else
hum.AutoRotate = true
end
hum.Jump = false
end
if root then
-- Let physics resume naturally when the aura is disabled.
root.AssemblyAngularVelocity = Vector3.zero
end
CombatState.auraActive = false
CombatState.teleported = false
CombatState.savedWalkSpeed = nil
CombatState.savedAutoRotate = nil
CombatState.nextMoveAt = 0
CombatState.lastProgressAt = 0
CombatState.lastMoveGoal = nil
CombatState.lastTargetPosition = nil
CombatState.orbitDirection = 1
end
return
end
if not hum or hum.Health <= 0 or not root then return end
-- Keep the current live target while it exists. Wall check and range are used
-- to acquire a new target, not to randomly drop an already-locked orbit.
local target = CombatState.target
local _, targetHum, targetHead, targetRoot = combatCharacter(target)
local targetUsable = targetRoot and targetHum and targetHum.Health > 0
and (not feat.combatTeamCheck or player.Team == nil or target.Team ~= player.Team)
if not targetUsable then
CombatState.target = nil
target = findCombatTarget()
if not target then
-- Fallback reacquisition: choose the nearest eligible visible target,
-- even if their head is outside the screen-center FOV.
local bestDist = math.huge
local myPosition = root.Position
for _, candidate in ipairs(Players:GetPlayers()) do
if candidate ~= player and (not feat.combatTeamCheck or player.Team == nil or candidate.Team ~= player.Team) then
local _, cHum, _, cRoot = combatCharacter(candidate)
if cHum and cRoot then
local dist = (cRoot.Position - myPosition).Magnitude
if dist <= (feat.combatMaxDistance or 500)
and dist < bestDist
and (not feat.combatWallCheck or combatTargetVisible(candidate)) then
bestDist = dist
target = candidate
end
end
end
end
end
CombatState.target = target
_, targetHum, targetHead, targetRoot = combatCharacter(target)
end
local now = os.clock()
local anchor
if targetRoot and targetHum and targetHum.Health > 0 then
anchor = targetRoot.Position
CombatState.lastTargetPosition = anchor
else
-- If the target respawns/dies for a moment, keep the flight path moving
-- around the last known anchor until another target can be acquired.
anchor = CombatState.lastTargetPosition
end
if not anchor then return end
local radius = math.max(2, feat.combatAuraRadius or 2.5)
local flightSpeed = math.clamp(feat.combatAuraWalkSpeed or 300, 8, 300)
local flyHeight = math.clamp(feat.combatAuraFlyHeight or 1, 1, 20)
if not CombatState.auraActive then
CombatState.savedWalkSpeed = hum.WalkSpeed
CombatState.savedAutoRotate = hum.AutoRotate
local offset = root.Position - anchor
local flatOffset = Vector3.new(offset.X, 0, offset.Z)
if flatOffset.Magnitude < 0.1 then flatOffset = Vector3.new(1, 0, 0) end
CombatState.auraAngle = math.atan2(flatOffset.Z, flatOffset.X)
CombatState.auraActive = true
CombatState.teleported = false
CombatState.lastProgressAt = now
CombatState.orbitDirection = CombatState.orbitDirection or 1
hum:ChangeState(Enum.HumanoidStateType.Freefall)
end
-- True continuous flight orbit: update the character transform every physics
-- step, rather than relying on MoveTo or player input (both can stall).
hum.WalkSpeed = flightSpeed
hum.AutoRotate = false
hum.Jump = false
-- Convert the requested studs/second directly to orbital angular velocity.
-- The previous 6.5 rad/s cap limited a 2.5-stud orbit to about 16 studs/s.
local angularSpeed = flightSpeed / radius
local direction = CombatState.orbitDirection or 1
CombatState.auraAngle = (CombatState.auraAngle + dt * angularSpeed * direction) % (math.pi * 2)
local a = CombatState.auraAngle
local radial = Vector3.new(math.cos(a), 0, math.sin(a))
-- Apply the configured flight speed directly to the tangent velocity.
local tangent = Vector3.new(-math.sin(a), 0, math.cos(a)) * (flightSpeed * direction)
local bob = math.sin(a * 1.7) * math.min(1.5, flyHeight * 0.3)
local nextPos = anchor + radial * radius + Vector3.new(0, flyHeight + bob, 0)
local lookAt = Vector3.new(anchor.X, nextPos.Y, anchor.Z)
root.CFrame = CFrame.lookAt(nextPos, lookAt)
-- Keep a tangential velocity for a smooth replicated flight path; the next
-- PreSimulation tick corrects position again so the orbit does not stop.
local verticalVelocity = math.cos(a * 1.7) * 1.7 * math.min(1.5, flyHeight * 0.3) * angularSpeed * direction
root.AssemblyLinearVelocity = tangent + Vector3.new(0, verticalVelocity, 0)
root.AssemblyAngularVelocity = Vector3.zero
end)
-- HOME
do
local pHome = new("Frame", {Name="HomePage", Size=UDim2.new(1,0,1,0), BackgroundTransparency=1, Visible=false, Parent=UI.contentArea})
UI.Pages["home"] = pHome
-- Optional Home binary hover effect. It is OFF by default so the Home
-- background stays clean until enabled from Themes.
local homeHoverEnabled = false
local binaryLayer = new("Frame", {
Name="HomeBinaryBackground", Size=UDim2.fromScale(1,1), Position=UDim2.fromScale(0,0),
BackgroundTransparency=1, BorderSizePixel=0, ClipsDescendants=true,
Active=false, Selectable=false, Visible=false, ZIndex=1, Parent=pHome
})
local binaryRows = {}
local binaryTextSize = 10
local binaryRowHeight = 13
local binaryCols = 260
local binaryRowCount = 120
local binaryRadius = 118
local binaryFeather = 52
local binaryCellEasing = 0.065
local binaryActiveCells = {}
local guiService = game:GetService("GuiService")
local textService = game:GetService("TextService")
local glyphMeasure = textService:GetTextSize("1", binaryTextSize, Enum.Font.Code, Vector2.new(1000,100))
local binaryGlyphWidth = math.max(1, glyphMeasure.X)
local function makeBinaryRow(rowIndex)
local chars = table.create(binaryCols)
for colIndex = 1, binaryCols do chars[colIndex] = "1" end
local row = new("TextLabel", {
Name="BinaryTextLine", BackgroundTransparency=1,
Position=UDim2.new(0,0,0,(rowIndex-1)*binaryRowHeight),
Size=UDim2.new(1,0,0,binaryRowHeight),
Font=Enum.Font.Code, Text=table.concat(chars), TextColor3=Color3.fromRGB(91,105,128),
TextSize=binaryTextSize, TextXAlignment=Enum.TextXAlignment.Left,
TextYAlignment=Enum.TextYAlignment.Center, TextWrapped=false,
RichText=true, ZIndex=1, Active=false, Selectable=false, Parent=binaryLayer
})
binaryRows[rowIndex] = {label=row, chars=chars}
end
for rowIndex = 1, binaryRowCount do makeBinaryRow(rowIndex) end
local function renderBinaryRow(rowIndex)
local rowData = binaryRows[rowIndex]
if not rowData then return end
local parts = table.create(binaryCols)
for colIndex = 1, binaryCols do
local key = (rowIndex-1)*binaryCols + colIndex
local cell = binaryActiveCells[key]
local amount = cell and cell.amount or 0
if amount > 0.012 then
-- Blend the zero from the dim base text into a vivid blue-white glow.
local red = math.floor(91 + (239-91)*amount)
local green = math.floor(105 + (247-105)*amount)
local blue = math.floor(128 + (255-128)*amount)
local hex = string.format("#%02X%02X%02X", red, green, blue)
local outline = string.format("#%02X%02X%02X",
math.floor(105 + 135*amount), math.floor(135 + 120*amount), 255)
local thickness = string.format("%.2f", 0.7 + amount*2.3)
local transparency = string.format("%.2f", 0.92 - amount*0.86)
parts[colIndex] = '0'
else
parts[colIndex] = rowData.chars[colIndex]
end
end
rowData.label.Text = table.concat(parts)
end
local function clearBinaryReveal()
table.clear(binaryActiveCells)
for rowIndex, rowData in pairs(binaryRows) do
rowData.label.Text = table.concat(rowData.chars)
end
end
local binaryLastMouse = nil
Fn.setHomeHover = function(enabled)
homeHoverEnabled = enabled == true
binaryLayer.Visible = homeHoverEnabled
if not homeHoverEnabled then
clearBinaryReveal()
binaryLastMouse = nil
end
feat.homeHoverReveal = homeHoverEnabled
end
RS.RenderStepped:Connect(function(dt)
if not homeHoverEnabled then return end
if not pHome.Visible then
if next(binaryActiveCells) ~= nil then clearBinaryReveal() end
binaryLastMouse = nil
return
end
-- GetMouseLocation is screen-space and includes the top bar inset.
-- Convert it to the IgnoreGuiInset ScreenGui's coordinate space before
-- comparing it with the binary layer's AbsolutePosition.
local mouse = UIS:GetMouseLocation() - guiService:GetGuiInset()
local origin = binaryLayer.AbsolutePosition
local size = binaryLayer.AbsoluteSize
local inside = size.X > 0 and size.Y > 0
and mouse.X >= origin.X and mouse.Y >= origin.Y
and mouse.X <= origin.X + size.X and mouse.Y <= origin.Y + size.Y
local targetCells = {}
if inside then
local localX = mouse.X - origin.X
local localY = mouse.Y - origin.Y
local radius = binaryRadius
local firstRow = math.max(1, math.floor((localY-radius-binaryRowHeight)/binaryRowHeight)+1)
local lastRow = math.min(binaryRowCount, math.ceil((localY+radius)/binaryRowHeight)+1)
local firstCol = math.max(1, math.floor((localX-radius)/binaryGlyphWidth)+1)
local lastCol = math.min(binaryCols, math.ceil((localX+radius)/binaryGlyphWidth)+1)
for rowIndex = firstRow, lastRow do
local centerY = (rowIndex-1)*binaryRowHeight + binaryRowHeight/2
local dy = centerY - localY
for colIndex = firstCol, lastCol do
local centerX = (colIndex-0.5)*binaryGlyphWidth
local dx = centerX - localX
local distance = math.sqrt(dx*dx + dy*dy)
if distance < radius then
local edge = math.clamp((radius-distance)/binaryFeather, 0, 1)
local target = edge*edge*(3-2*edge)
if target > 0.008 then
local key = (rowIndex-1)*binaryCols + colIndex
targetCells[key] = target
end
end
end
end
binaryLastMouse = mouse
else
binaryLastMouse = nil
end
-- Ease every affected cell toward its new state. This animates both
-- entering the circle and leaving it, including when the cursor moves.
local blend = 1 - math.exp(-math.max(dt, 0)/binaryCellEasing)
local changedRows = {}
for key, cell in pairs(binaryActiveCells) do
local target = targetCells[key] or 0
local previous = cell.amount
local current = previous + (target-previous)*blend
cell.amount = current
local rowIndex = math.floor((key-1)/binaryCols)+1
if math.abs(current-previous) > 0.0025 then
changedRows[rowIndex] = true
end
if target == 0 and current < 0.012 then
binaryActiveCells[key] = nil
changedRows[rowIndex] = true
end
end
-- New cells fade in from the original 1 instead of snapping to 0.
for key, target in pairs(targetCells) do
if not binaryActiveCells[key] then
local amount = target*blend
binaryActiveCells[key] = {amount=amount}
local rowIndex = math.floor((key-1)/binaryCols)+1
changedRows[rowIndex] = true
end
end
for rowIndex in pairs(changedRows) do
renderBinaryRow(rowIndex)
end
end)
-- Wide Moonware welcome panel.
local hero = new("Frame", {
Name="HomeHero", Size=UDim2.new(1,-4,0,190), Position=UDim2.new(0,0,0,0),
BackgroundColor3=T.Card, BackgroundTransparency=TR.Card, BorderSizePixel=0, ClipsDescendants=true, Parent=pHome
})
corner(hero,18); stroke(hero,1,0.45,T.Line); regRef(hero,"BackgroundColor3","Card"); regCard(hero)
local heroStripe = new("Frame", {Size=UDim2.new(0,5,1,0), BackgroundColor3=T.Accent, BorderSizePixel=0, Parent=hero})
corner(heroStripe,4); gradient(heroStripe,T.Accent,T.Accent2,90)
local heroKicker = new("TextLabel", {
BackgroundTransparency=1, Position=UDim2.new(0,26,0,22), Size=UDim2.new(1,-190,0,18),
Font=Enum.Font.GothamBold, Text="MOONWARE / CONTROL CENTER", TextColor3=T.Accent,
TextSize=11, TextXAlignment=Enum.TextXAlignment.Left, Parent=hero
})
local heroTitle = new("TextLabel", {
BackgroundTransparency=1, Position=UDim2.new(0,24,0,48), Size=UDim2.new(1,-190,0,46),
Font=Enum.Font.GothamBlack, Text="Welcome back", TextColor3=T.Text,
TextSize=32, TextXAlignment=Enum.TextXAlignment.Left, Parent=hero
})
local heroName = new("TextLabel", {
BackgroundTransparency=1, Position=UDim2.new(0,26,0,96), Size=UDim2.new(1,-190,0,22),
Font=Enum.Font.GothamMedium, Text=(player.DisplayName or player.Name).." • @"..player.Name,
TextColor3=T.Dim, TextSize=13, TextXAlignment=Enum.TextXAlignment.Left, Parent=hero
})
local heroDesc = new("TextLabel", {
BackgroundTransparency=1, Position=UDim2.new(0,26,0,126), Size=UDim2.new(1,-190,0,20),
Font=Enum.Font.Gotham, Text="Your session, your style. Everything in one place.",
TextColor3=T.Muted, TextSize=12, TextXAlignment=Enum.TextXAlignment.Left, Parent=hero
})
for _, label in ipairs({heroTitle,heroName,heroDesc}) do
regRef(label,"TextColor3", label==heroTitle and "Text" or (label==heroName and "Dim" or "Muted"))
end
local livePill = new("Frame", {
Size=UDim2.new(0,130,0,26), Position=UDim2.new(0,26,1,-42),
BackgroundColor3=T.Hover, BackgroundTransparency=0, BorderSizePixel=0, Parent=hero
})
corner(livePill,13); stroke(livePill,1,0.65,T.Line)
local liveDot = new("Frame", {Size=UDim2.new(0,7,0,7),Position=UDim2.new(0,11,0.5,-3.5),BackgroundColor3=Color3.fromRGB(105,220,155),BorderSizePixel=0,Parent=livePill})
corner(liveDot,4)
new("TextLabel", {
BackgroundTransparency=1, Position=UDim2.new(0,25,0,0), Size=UDim2.new(1,-30,1,0),
Font=Enum.Font.GothamBold, Text="SESSION ACTIVE", TextColor3=T.Text,
TextSize=9, TextXAlignment=Enum.TextXAlignment.Left, Parent=livePill
})
local logoHalo = new("Frame", {
Size=UDim2.new(0,132,0,132), Position=UDim2.new(1,-158,0.5,-66),
BackgroundColor3=T.Hover, BackgroundTransparency=0.1, BorderSizePixel=0, Parent=hero
})
corner(logoHalo,66); stroke(logoHalo,1,0.45,T.Line)
moonwareLogo(logoHalo, 78, UDim2.new(0.5,-39,0.5,-39), T.Text, T.Hover, 0.1, 4, "HomeMoonwareMark")
-- Two simple status cards: Player and Session Time.
local statsRow = new("Frame", {
Name="HomeStats", Size=UDim2.new(1,-4,0,112), Position=UDim2.new(0,0,0,208),
BackgroundTransparency=1, Parent=pHome
})
new("UIListLayout", {FillDirection=Enum.FillDirection.Horizontal, Padding=UDim.new(0,10), SortOrder=Enum.SortOrder.LayoutOrder, Parent=statsRow})
local function makeStat(label, value, detail, assetId, fallbackGlyph, order)
local card = new("Frame", {
Size=UDim2.new(0.5,-5,1,0), BackgroundColor3=T.Card, BackgroundTransparency=TR.Card,
BorderSizePixel=0, LayoutOrder=order, Parent=statsRow
})
corner(card,14); stroke(card,1,0.55,T.Line); regRef(card,"BackgroundColor3","Card"); regCard(card)
local ico = new("ImageLabel", {
Name="HomeStatIcon", BackgroundTransparency=1,
Position=UDim2.new(0,15,0,12), Size=UDim2.new(0,27,0,27),
ImageColor3=T.Accent, ScaleType=Enum.ScaleType.Fit, Visible=false, Parent=card
})
local fallback = new("TextLabel", {
BackgroundTransparency=1, Position=ico.Position, Size=ico.Size,
Font=Enum.Font.GothamBold, Text=fallbackGlyph, TextColor3=T.Accent,
TextSize=19, Parent=card
})
applyRobloxAssetIcon(ico, assetId, fallback)
local title = new("TextLabel", {
BackgroundTransparency=1, Position=UDim2.new(0,52,0,14), Size=UDim2.new(1,-64,0,16),
Font=Enum.Font.GothamBold, Text=label, TextColor3=T.Muted, TextSize=9,
TextXAlignment=Enum.TextXAlignment.Left, Parent=card
})
local valueLabel = new("TextLabel", {
BackgroundTransparency=1, Position=UDim2.new(0,16,0,45), Size=UDim2.new(1,-30,0,25),
Font=Enum.Font.GothamBold, Text=value, TextColor3=T.Text, TextSize=18,
TextXAlignment=Enum.TextXAlignment.Left, TextTruncate=Enum.TextTruncate.AtEnd, Parent=card
})
local detailLabel = new("TextLabel", {
BackgroundTransparency=1, Position=UDim2.new(0,16,0,76), Size=UDim2.new(1,-30,0,17),
Font=Enum.Font.Gotham, Text=detail, TextColor3=T.Dim, TextSize=10,
TextXAlignment=Enum.TextXAlignment.Left, TextTruncate=Enum.TextTruncate.AtEnd, Parent=card
})
regRef(ico,"ImageColor3","Accent"); regRef(fallback,"TextColor3","Accent")
regRef(title,"TextColor3","Muted"); regRef(valueLabel,"TextColor3","Text"); regRef(detailLabel,"TextColor3","Dim")
return valueLabel
end
makeStat("PLAYER", player.DisplayName or player.Name, "@"..player.Name, "7992557371", "♙", 1)
local sessionValue = makeStat("SESSION TIME", "00:00:00", "This script session", "111410683560709", "◷", 2)
local sessionStarted = os.clock()
task.spawn(function()
while sessionValue.Parent do
local elapsed = math.max(0,math.floor(os.clock()-sessionStarted))
local hours = math.floor(elapsed/3600)
local minutes = math.floor(elapsed/60)%60
local seconds = elapsed%60
sessionValue.Text = string.format("%02d:%02d:%02d",hours,minutes,seconds)
task.wait(1)
end
end)
local quickTitle = new("TextLabel", {
BackgroundTransparency=1, Position=UDim2.new(0,2,0,344), Size=UDim2.new(1,-4,0,20),
Font=Enum.Font.GothamBold, Text="QUICK ACCESS", TextColor3=T.Text, TextSize=12,
TextXAlignment=Enum.TextXAlignment.Left, Parent=pHome
})
local quickSub = new("TextLabel", {
BackgroundTransparency=1, Position=UDim2.new(0,2,0,365), Size=UDim2.new(1,-4,0,16),
Font=Enum.Font.GothamMedium, Text="Jump straight into your favourite controls.", TextColor3=Color3.fromRGB(220,226,240),
TextSize=12, TextXAlignment=Enum.TextXAlignment.Left, Parent=pHome
})
regRef(quickTitle,"TextColor3","Text"); quickTitle.TextColor3=Color3.fromRGB(255,255,255)
local quickRow = new("Frame", {
Name="HomeQuickAccess", Size=UDim2.new(1,-4,0,102), Position=UDim2.new(0,0,0,390),
BackgroundTransparency=1, Parent=pHome
})
new("UIListLayout", {FillDirection=Enum.FillDirection.Horizontal, Padding=UDim.new(0,10), SortOrder=Enum.SortOrder.LayoutOrder, Parent=quickRow})
local function mkTile(label, assetId, fallbackGlyph, kbName, order)
local tile = new("TextButton", {
Size=UDim2.new(1/4,-8,1,0), BackgroundColor3=T.Card, BackgroundTransparency=TR.Card,
Text="", BorderSizePixel=0, AutoButtonColor=false, LayoutOrder=order, Parent=quickRow
})
corner(tile,13); stroke(tile,1,0.55,T.Line); regRef(tile,"BackgroundColor3","Card"); regCard(tile)
local ico = new("ImageLabel", {
Name="HomeActionIcon", BackgroundTransparency=1,
Position=UDim2.new(0,14,0,11), Size=UDim2.new(0,32,0,32),
ImageColor3=T.Accent, ScaleType=Enum.ScaleType.Fit, Visible=false, Parent=tile
})
local fallback = new("TextLabel", {
BackgroundTransparency=1, Position=ico.Position, Size=ico.Size,
Font=Enum.Font.GothamBold, Text=fallbackGlyph, TextColor3=T.Accent,
TextSize=22, Parent=tile
})
if assetId then applyRobloxAssetIcon(ico, assetId, fallback) end
regRef(ico,"ImageColor3","Accent"); regRef(fallback,"TextColor3","Accent")
local lbl = new("TextLabel", {
BackgroundTransparency=1, Position=UDim2.new(0,14,0,54), Size=UDim2.new(1,-78,0,18),
Font=Enum.Font.GothamBold, Text=label, TextColor3=T.Text, TextSize=12,
TextXAlignment=Enum.TextXAlignment.Left, Parent=tile
})
regRef(lbl,"TextColor3","Text")
-- A dedicated bind chip lets users assign a key without opening the Movement tab.
local bindChip = new("TextButton", {
Size=UDim2.new(0,54,0,20), Position=UDim2.new(1,-66,0,52),
BackgroundColor3=T.Panel, BackgroundTransparency=TR.Card, BorderSizePixel=0,
Text="BIND", TextColor3=T.Dim, Font=Enum.Font.GothamBold, TextSize=9,
AutoButtonColor=false, Parent=tile
})
corner(bindChip,6); stroke(bindChip,1,0.55,T.Line)
bindChip.MouseButton1Click:Connect(function()
if Keybinds[kbName] then
playUiSoundLayered("click")
openKeyPrompt(kbName)
end
end)
task.spawn(function()
local lastText
while bindChip.Parent do
local kb = Keybinds[kbName]
local text = (kb and kb.key and kb.key.Name) or "BIND"
if text ~= lastText then
bindChip.Text = text
bindChip.TextColor3 = (kb and kb.key) and T.Accent or T.Dim
lastText = text
end
task.wait(0.2)
end
end)
hoverFx(tile)
tile.MouseButton1Click:Connect(function()
playUiSoundLayered("click")
local kb = Keybinds[kbName]
if kb then
if kb.isToggle then kb.setState(not kb.getState())
elseif kb.fire then pcall(kb.fire) end
end
end)
end
mkTile("Fly", "119133565006804", "↗", "Fly", 1)
mkTile("NoClip", "111363292630417", "◈", "NoClip", 2)
mkTile("Infinite Jump", "99183002748390", "↟", "InfJump", 3)
-- No Free Cam icon URL was supplied; keep its camera-style symbol as fallback.
mkTile("Free Cam", nil, "◎", "FreeCam", 4)
local footerBack = new("Frame", {
Name="HomeFooterBackground", AnchorPoint=Vector2.new(0,1),
Position=UDim2.new(0,0,1,-5), Size=UDim2.new(0,300,0,30),
BackgroundColor3=Color3.fromRGB(12,15,23), BackgroundTransparency=0.02, BorderSizePixel=0,
ZIndex=5, Parent=pHome
})
corner(footerBack,9)
stroke(footerBack,1,0.55,T.Line)
regRef(footerBack,"BackgroundColor3","Card")
local homeFooter = new("TextLabel", {
Name="HomeFooterCredit", BackgroundTransparency=1,
Position=UDim2.new(0,11,0,0), Size=UDim2.new(1,-22,1,0),
Font=Enum.Font.GothamBold, Text="Moonware • Made by n_e_r_v_y with love",
TextColor3=Color3.fromRGB(255,255,255), TextSize=12, TextTransparency=0,
TextXAlignment=Enum.TextXAlignment.Left, TextYAlignment=Enum.TextYAlignment.Center,
ZIndex=6, Parent=footerBack
})
homeFooter.TextColor3=Color3.fromRGB(255,255,255)
end
-- MOVEMENT
do
hdr(pMove, "Movement")
mkT(pMove, "Fly", false, function(s) if s then Fn.startFly() else Fn.stopFly() end end, "Fly")
mkS(pMove, "Fly Speed", 10, 300, 55, function(v) feat.flySpeed = v end, "FlySpeed")
mkS(pMove, "Fly Accel", 2, 30, 12, function(v) feat.flyAccel = v end, "FlyAccel")
mkS(pMove, "Fly Damping", 2, 30, 10, function(v) feat.flyDamping = v end, "FlyDamp")
mkS(pMove, "Vertical Boost", 1, 3, 1.3, function(v) feat.flyVerticalBoost = v end, "FlyVert", true)
mkT(pMove, "Infinite Jump", false, function(s) feat.infJump = s end, "InfJump")
mkT(pMove, "NoClip", false, function(s) feat.noclip = s end, "NoClip")
hdr(pMove, "Character")
mkS(pMove, "WalkSpeed", 8, 300, 16, function(v)
feat.walkSpeed = v
local h = player.Character and player.Character:FindFirstChildOfClass("Humanoid")
if h and not feat.freeCam then h.WalkSpeed = v end
end, "WalkSpeed")
mkS(pMove, "JumpPower", 20, 300, 50, function(v)
feat.jumpPower = v
local h = player.Character and player.Character:FindFirstChildOfClass("Humanoid")
if h and not feat.freeCam then h.UseJumpPower = true; h.JumpPower = v end
end, "JumpPower")
hdr(pMove, "Camera")
mkT(pMove, "Free Cam", false, function(s)
if s then
local ok = Fn.startFreeCam()
if ok == false then task.defer(function() if ToggleReg["FreeCam"] then ToggleReg["FreeCam"](false) end end) end
else Fn.stopFreeCam() end
end, "FreeCam")
mkS(pMove, "Free Cam Speed", 10, 300, 60, function(v) feat.freeCamSpeed = v end, "FreeCamSpeed")
end
-- COMBAT
-- Includes camera lock, aim assist, and configurable orbit behavior. ESP/chams use existing renderers.
do
hdr(pCombat, "Targeting")
mkT(pCombat, "Target Lock", false, function(on)
feat.combatTargetLock = on
if on then CombatState.target = findCombatTarget() elseif not feat.combatAimbot and not feat.combatSilentAura then CombatState.target = nil end
end, "CombatTargetLock")
mkT(pCombat, "Aimbot (Camera Aim)", false, function(on)
feat.combatAimbot = on
if on then CombatState.target = findCombatTarget() elseif not feat.combatTargetLock and not feat.combatSilentAura then CombatState.target = nil end
end, "CombatAimbot")
mkT(pCombat, "Silent Aura (Orbit Target)", false, function(on)
feat.combatSilentAura = on
if on then CombatState.target = findCombatTarget(); CombatState.auraActive = false
elseif not feat.combatTargetLock and not feat.combatAimbot then CombatState.target = nil end
end, "CombatSilentAura")
mkT(pCombat, "Target Team Check", true, function(on) feat.combatTeamCheck = on; CombatState.target = nil end, "CombatTeamCheck")
mkT(pCombat, "Wall Check", true, function(on)
feat.combatWallCheck = on
CombatState.target = nil
notify("Combat", on and "Wall Check enabled: only visible targets can be selected" or "Wall Check disabled")
end, "CombatWallCheck")
mkS(pCombat, "Aim FOV (pixels)", 50, 800, 260, function(v) feat.combatAimFov = v; CombatState.target = nil end, "CombatAimFov")
mkS(pCombat, "Max Target Distance", 50, 1500, 500, function(v) feat.combatMaxDistance = v; CombatState.target = nil end, "CombatMaxDist")
hdr(pCombat, "Silent Aura Movement")
mkS(pCombat, "Orbit Flight Speed", 8, 300, 300, function(v) feat.combatAuraWalkSpeed = v end, "CombatAuraSpeed")
mkS(pCombat, "Orbit Radius", 2, 12, 2.5, function(v) feat.combatAuraRadius = v end, "CombatAuraRadius", true)
mkS(pCombat, "Orbit Fly Height", 1, 20, 1, function(v) feat.combatAuraFlyHeight = v end, "CombatAuraFlyHeight", true)
mkB(pCombat, "Clear Locked Target", function() CombatState.target = nil; notify("Combat", "Target cleared") end)
hdr(pCombat, "ESP / Chams")
mkT(pCombat, "Player ESP", feat.espEnabled, function(on)
feat.espEnabled = on
if Fn.setEspEnabled then Fn.setEspEnabled(on) end
if ToggleReg.EspEnabled then ToggleReg.EspEnabled(on) end
end, "CombatESP")
mkT(pCombat, "Player Chams", feat.espChams, function(on)
feat.espChams = on
if Fn.refreshEsp then Fn.refreshEsp() end
if ToggleReg.EspChams then ToggleReg.EspChams(on) end
end, "CombatChams")
mkS(pCombat, "ESP Max Distance", 50, 1500, 500, function(v) feat.espMaxDist = v; if Fn.refreshEsp then Fn.refreshEsp() end end, "CombatEspDistance")
mkB(pCombat, "Open Visual ESP Settings", function() if Fn.selTab then Fn.selTab("visuals") end end)
end
-- VISUALS
do
hdr(pVis, "Effect Color")
local colorRow = new("Frame",{Size=UDim2.new(1,-4,0,50),BackgroundColor3=T.Card,BackgroundTransparency=TR.Card,BorderSizePixel=0,Parent=pVis})
colorRow:SetAttribute("OwoLbl", "color effect color")
corner(colorRow, RM); stroke(colorRow, 1, 0.55, T.Line); regRef(colorRow, "BackgroundColor3", "Card"); regCard(colorRow)
local clrLbl = new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,18,0,0),Size=UDim2.new(1,-180,1,0),Font=Enum.Font.GothamMedium,Text="Color",TextColor3=T.Text,TextSize=12,TextXAlignment=Enum.TextXAlignment.Left,ZIndex=3,Parent=colorRow})
regRef(clrLbl, "TextColor3", "Text")
UI.colorPreview = new("Frame",{Size=UDim2.new(0,32,0,26),Position=UDim2.new(1,-152,0.5,-13),BackgroundColor3=EFFECT_COLOR,BorderSizePixel=0,ZIndex=3,Parent=colorRow})
corner(UI.colorPreview, 7); stroke(UI.colorPreview, 1, 0.35, T.Line)
UI.colorInput = new("TextBox",{Size=UDim2.new(0,110,0,30),Position=UDim2.new(1,-114,0.5,-15),BackgroundColor3=T.Bg,BackgroundTransparency=0.3,Font=Enum.Font.GothamBold,Text=colorToHex(EFFECT_COLOR),PlaceholderText="#RRGGBB",TextColor3=T.Text,PlaceholderColor3=T.Muted,TextSize=12,BorderSizePixel=0,ClearTextOnFocus=false,ZIndex=3,Parent=colorRow})
corner(UI.colorInput, 8); stroke(UI.colorInput, 1, 0.55, T.Line)
regRef(UI.colorInput, "BackgroundColor3", "Bg"); regRef(UI.colorInput, "TextColor3", "Text")
local cpBtn = new("TextButton",{Size=UDim2.fromScale(1,1),BackgroundTransparency=1,Text="",ZIndex=5,Parent=UI.colorPreview})
cpBtn.MouseButton1Click:Connect(function()
playUiSoundLayered("click")
Picker.open(EFFECT_COLOR, function(c, final)
UI.colorInput.Text = colorToHex(c); UI.colorPreview.BackgroundColor3 = c
if final then Fn.setEffectColor(c) end
end, UI.colorPreview.AbsolutePosition.X, UI.colorPreview.AbsolutePosition.Y)
end)
UI.colorInput.FocusLost:Connect(function()
local c = hexToColor(UI.colorInput.Text)
if c then Fn.setEffectColor(c) else UI.colorInput.Text = colorToHex(EFFECT_COLOR); notify("Color", "Invalid hex code", false) end
end)
hdr(pVis, "Time of Day")
mkB(pVis, "Day (12:00)", Fn.setDay, "DayBtn")
mkB(pVis, "Night (00:00)", Fn.setNight, "NightBtn")
mkB(pVis, "Sunset (17:30)", Fn.setSunset, "SunsetBtn")
mkB(pVis, "Restore Original", Fn.restoreLight, "RestoreTime")
local customSkyInput = mkInput(pVis, "Custom Skybox ID", "Roblox sky asset ID", 200)
customSkyInput.Text = feat.customSkyboxId or ""
customSkyInput.FocusLost:Connect(function(enter)
if enter or customSkyInput.Text ~= "" then
local raw = tostring(customSkyInput.Text or ""):gsub("%s", ""):gsub("rbxassetid://", "")
if raw:match("^%d+$") then
Fn.setCustomSkybox(raw)
else
notify("Custom Skybox", "Enter a numeric asset ID", false)
end
end
end)
mkB(pVis, "Apply Custom Skybox", function() Fn.setCustomSkybox(customSkyInput.Text) end)
hdr(pVis, "Skybox")
for _, m in ipairs(Fn.Sky.MODES) do
mkT(pVis, m, false, function(s) if s then Fn.setSky(m) elseif Fn.Sky.mode == m then Fn.setSky("Off") end end, "Sky" .. (m:gsub(" ", "")))
end
hdr(pVis, "Weather")
mkT(pVis, "Rain", false, function(s)
feat.rain = s
Wx.rain()
end, "WxRain")
mkT(pVis, "Rain Ripples", false, function(s) feat.rainRipples = s end, "WxRipples")
mkS(pVis, "Ripple Amount", 4, 80, 28, function(v) feat.rippleRate = v end, "RippleRate")
mkS(pVis, "Ripple Radius", 15, 90, 45, function(v) feat.rippleRadius = v end, "RippleRadius")
mkS(pVis, "Ripple Size", 0.5, 4, 1.6, function(v) feat.rippleSize = v end, "RippleSize", true)
mkT(pVis, "Rain Puddles", false, function(s) feat.rainPuddles = s end, "WxPuddles")
mkS(pVis, "Puddle Amount", 4, 60, 22, function(v) feat.puddleCount = v end, "PuddleCount")
mkS(pVis, "Puddle Size", 1, 8, 3.5, function(v) feat.puddleSize = v end, "PuddleSize", true)
mkT(pVis, "Snow", false, function(s)
feat.snow = s
Wx.snow()
end, "WxSnow")
mkT(pVis, "Snow On The Floor", false, function(s) feat.snowFloor = s end, "WxSnowFloor")
mkS(pVis, "Snow Floor Radius", 20, 100, 50, function(v) feat.snowRadius = v end, "SnowRadius")
mkS(pVis, "Snow Depth", 0.05, 0.6, 0.18, function(v) feat.snowDepth = v end, "SnowDepth", true)
mkT(pVis, "Fog", false, function(s) feat.fog = s; Wx.fog() end, "WxFog")
mkS(pVis, "Fog Density", 0, 1, 0.35, function(v) feat.fogDensity = v; Wx.fogDensity(v) end, "FogDensity", true)
mkT(pVis, "Thunder", false, function(s)
feat.thunder = s
if Wx.thunder then Wx.thunder() end
end, "WxThunder")
mkT(pVis, "Storm (Rain + Thunder)", false, function(s)
feat.rain = s
feat.thunder = s
Wx.rain()
if Wx.thunder then Wx.thunder() end
if ToggleReg.WxRain then ToggleReg.WxRain(s) end
if ToggleReg.WxThunder then ToggleReg.WxThunder(s) end
end, "WxStorm")
mkT(pVis, "Meteor Shower", false, function(s) feat.meteorShower = s end, "WxMeteor")
mkS(pVis, "Meteor Rate", 1, 20, 3, function(v) feat.meteorRate = v end, "MeteorRate", true)
hdr(pVis, "Floating Effects")
mkT(pVis, "Floating Cubes", false, function(s) feat.cubes = s; Wx.cubes() end, "FxCubes")
mkS(pVis, "Cube Count", 2, 16, 6, function(v) feat.cubeCount = v; if feat.cubes then Wx.cubes() end end, "CubeCount")
mkS(pVis, "Cube Radius", 2, 12, 4.5, function(v) feat.cubeRadius = v end, "CubeRadius", true)
mkS(pVis, "Cube Speed", 0, 5, 1.2, function(v) feat.cubeSpeed = v end, "CubeSpeed", true)
mkT(pVis, "Ambient Cubes", false, function(s) feat.ambient = s; Wx.ambient() end, "FxAmbient")
mkT(pVis, "Fireflies", false, function(s) feat.fireflies = s; Wx.fireflies() end, "FxFireflies")
mkT(pVis, "Butterflies", false, function(s) feat.butterflies = s end, "FxButterflies")
mkS(pVis, "Butterfly Count", 2, 30, 10, function(v) feat.butterflyCount = v end, "ButterflyCount")
mkT(pVis, "Afterimages", false, function(s) feat.ghost = s end, "FxGhost")
mkS(pVis, "Ghost Interval", 0.04, 0.4, 0.12, function(v) feat.ghostInterval = v end, "GhostInterval", true)
hdr(pVis, "Screen")
hdr(pVis, "Overlay Polish")
mkT(pVis, "Overlay Shine", false, function(s) feat.overlayShine = s end, "OverlayShine")
mkT(pVis, "Screen Tint", false, function(s) feat.tint = s end, "FxTint")
mkS(pVis, "Tint Strength", 0, 100, 60, function(v) feat.tintStrength = v end, "TintStrength")
mkT(pVis, "Bloom", false, function(s) feat.bloom = s end, "FxBloom")
mkT(pVis, "Vignette", false, function(s) feat.vignette = s end, "FxVignette")
mkT(pVis, "Chromatic Aberration", false, function(s) feat.chromaticAberration = s; Fn.applyScreenFilters() end, "FxChroma")
mkS(pVis, "Chroma Strength", 0, 2, 0.6, function(v) feat.chromaticStrength = v; Fn.applyScreenFilters() end, "ChromaStrength", true)
mkT(pVis, "Depth of Field", false, function(s) feat.depthOfField = s; Fn.applyScreenFilters() end, "FxDOF")
mkT(pVis, "Retro Filter", false, function(s) feat.retroFilter = s; Fn.applyScreenFilters() end, "FxRetro")
mkS(pVis, "Retro Strength", 0, 1, 0.7, function(v) feat.retroStrength = v; Fn.applyScreenFilters() end, "RetroStrength", true)
mkT(pVis, "VHS Scanlines", false, function(s) feat.vhsFilter = s; Fn.applyScreenFilters() end, "FxVHS")
mkT(pVis, "Glitch Filter", false, function(s) feat.glitchFilter = s; Fn.applyScreenFilters() end, "FxGlitch")
-- Standard visual controls continue below.
mkT(pVis, "Fullbright", false, function(s) feat.fullbright = s; Fn.applyFB() end, "Fullbright")
mkS(pVis, "Camera FOV", 20, 120, 70, function(v) camera.FieldOfView = v end, "FOV", true)
hdr(pVis, "Screen Ratio")
mkT(pVis, "Stretched Res (4:3)", false, function(s) feat.stretch = s end, "Stretch")
mkS(pVis, "Stretch Amount", 0.4, 1, 0.75, function(v) feat.stretchAmount = v end, "StretchAmount", true)
mkB(pVis, "Preset: 4:3", function() if SliderReg.StretchAmount then SliderReg.StretchAmount.set(0.75) end; if ToggleReg.Stretch then ToggleReg.Stretch(true) end end)
mkB(pVis, "Preset: 5:4", function() if SliderReg.StretchAmount then SliderReg.StretchAmount.set(0.71) end; if ToggleReg.Stretch then ToggleReg.Stretch(true) end end)
mkB(pVis, "Preset: 16:10", function() if SliderReg.StretchAmount then SliderReg.StretchAmount.set(0.9) end; if ToggleReg.Stretch then ToggleReg.Stretch(true) end end)
mkB(pVis, "Preset: Extra Wide", function() if SliderReg.StretchAmount then SliderReg.StretchAmount.set(0.6) end; if ToggleReg.Stretch then ToggleReg.Stretch(true) end end)
hdr(pVis, "Camera FX")
mkT(pVis, "Smooth Camera", false, function(s) feat.smoothCamera = s end, "SmoothCam")
mkS(pVis, "Camera Smoothness", 0.1, 2, 0.5, function(v) feat.smoothCameraStrength = v end, "SmoothCamStr", true)
mkT(pVis, "Sprint FOV Boost", false, function(s) feat.sprintFov = s end, "SprintFov")
mkS(pVis, "Sprint FOV Amount", 0, 40, 15, function(v) feat.sprintFovBoost = v end, "SprintFovAmt")
mkT(pVis, "Camera Roll on Strafe", false, function(s) feat.cameraRoll = s end, "CamRoll")
mkS(pVis, "Roll Amount", 0, 20, 6, function(v) feat.cameraRollAmount = v end, "RollAmt")
mkT(pVis, "Screen Shake", false, function(s) feat.screenShake = s end, "ScreenShake")
mkS(pVis, "Shake Amount", 0, 3, 0.5, function(v) feat.shakeAmount = v end, "ShakeAmt", true)
hdr(pVis, "Shaders")
mkT(pVis, "Motion Blur", false, function(s) feat.motionBlur = s end, "MotionBlur")
mkS(pVis, "Motion Blur Strength", 0, 3, 1.0, function(v) feat.motionBlurStrength = v end, "MotionBlurStrength", true)
mkT(pVis, "Glossy (Reflective World)", false, function(s) feat.reflective = s; Fn.applyReflective() end, "Glossy")
mkS(pVis, "Gloss Strength", 0, 1, 0.5, function(v) Fn.setReflectiveStrength(v) end, "Reflectivity", true)
mkT(pVis, "Realistic Shader", false, function(s) feat.realistic = s end, "Realistic")
mkS(pVis, "Realism Strength", 0, 2, 1.0, function(v) Fn.setRealisticStrength(v) end, "RealismStrength", true)
hdr(pVis, "Performance")
mkT(pVis, "FPS Boost (strip textures)", false, function(s) feat.fpsBoost = s; Fn.applyFpsBoost() end, "FpsBoost")
hdr(pVis, "Body")
mkT(pVis, "Glow", false, function(s) feat.glow = s; Fn.rebuildVFX() end, "VFXGlow")
mkT(pVis, "Neon Body", false, function(s) feat.neon = s; Fn.applyNeonBody() end, "VFXNeon")
mkT(pVis, "Rainbow Character", false, function(s) feat.rainbowChar = s; Fn.applyRainbowChar() end, "RainbowChar")
mkS(pVis, "Rainbow Speed", 0.1, 3, 0.5, function(v) feat.rainbowSpeed = v end, "RainbowSpeed", true)
mkT(pVis, "Player Transparency", false, function(s) feat.playerTransparency = s; Fn.applyPlayerTransparency() end, "PlayerTrans")
mkS(pVis, "Transparency Level", 0, 100, 0, function(v) feat.playerTransparencyLevel = v; if feat.playerTransparency then Fn.applyPlayerTransparency() end end, "PlayerAlpha")
hdr(pVis, "Accessories")
mkT(pVis, "Halo", false, function(s) feat.halo = s; Fn.rebuildVFX() end, "VFXHalo")
mkT(pVis, "Wings", false, function(s) feat.wings = s; Fn.rebuildVFX() end, "VFXWings")
mkT(pVis, "Crown", false, function(s) feat.crown = s; Fn.rebuildVFX() end, "VFXCrown")
mkT(pVis, "Santa Hat", false, function(s) feat.santaHat = s; Fn.rebuildVFX() end, "VFXSanta")
mkS(pVis, "Hat Transparency", 0, 0.9, 0.35, function(v) feat.santaTransparency = v; if feat.santaHat then Fn.rebuildVFX() end end, "SantaTransparency", true)
hdr(pVis, "Capes")
mkT(pVis, "Moonware Cape", false, function(s) feat.cape = s; Fn.rebuildVFX(); if s then notify("Cape", "Moonware Cape equipped") end end, "VFXCape")
mkS(pVis, "Cape Length", 2.5, 6.5, 4.2, function(v) feat.capeLength = v; if feat.cape then Fn.rebuildVFX() end end, "CapeLength", true)
mkT(pVis, "Back Pickaxe (Cosmetic)", false, function(s) feat.pickaxe = s; Fn.rebuildVFX(); if s then notify("Pickaxe", "Back pickaxe equipped — right-click to change skin") end end, "VFXPickaxe")
hdr(pVis, "Outlines & Chams")
mkT(pVis, "My Chams (Self Only)", false, function(s) feat.selfChams = s; Fn.rebuildVFX() end, "SelfChams")
mkS(pVis, "My Chams Fill", 0, 1, 0.55, function(v) feat.selfChamsFill = v; if feat.selfChams then Fn.rebuildVFX() end end, "SelfChamsFill", true)
mkT(pVis, "Character Outline", false, function(s) feat.charOutline = s; Fn.rebuildVFX() end, "CharOutline")
mkT(pVis, "World Outlines (every corner)", false, function(s) feat.worldOutline = s end, "WorldOutline")
hdr(pVis, "Knife Inspect (First Person)")
mkT(pVis, "Show Knife", false, function(s) feat.knifeOut = s end, "KnifeOut")
mkB(pVis, "Model: Butterfly Knife", function() feat.knifeModel = "butterfly"; notify("Knife", "Butterfly Knife equipped") end)
mkB(pVis, "Model: Karambit", function() feat.knifeModel = "karambit"; notify("Knife", "Karambit equipped") end)
mkB(pVis, "Inspect", Fn.knifeInspect, "KnifeInspect")
mkT(pVis, "First Person Hand", true, function(s) feat.handOut = s end, "HandOut")
mkT(pVis, "Hand Editor Mode", false, function(s)
feat.handEditMode = s
if s then
notify("Hand Editor", "Adjust Move X/Y/Z and Hand Size below. The yellow outline marks the editable hand.")
end
end, "HandEditorMode")
mkS(pVis, "Hand Move X", -2.5, 2.5, feat.handOffsetX or 0.82, function(v) feat.handOffsetX = v end, "HandMoveX", true)
mkS(pVis, "Hand Move Y", -1.5, 1.5, feat.handOffsetY or -0.04, function(v) feat.handOffsetY = v end, "HandMoveY", true)
mkS(pVis, "Hand Move Z", -1.5, 1.5, feat.handOffsetZ or 0.43, function(v) feat.handOffsetZ = v end, "HandMoveZ", true)
mkS(pVis, "Hand Size", 0.35, 2.25, feat.handScale or 0.4, function(v) feat.handScale = v end, "HandScale", true)
mkB(pVis, "Reset Hand Layout", function()
feat.handOffsetX, feat.handOffsetY, feat.handOffsetZ, feat.handScale = 0.82, -0.04, 0.43, 0.4
if SliderReg.HandMoveX then SliderReg.HandMoveX.set(0.82) end
if SliderReg.HandMoveY then SliderReg.HandMoveY.set(-0.04) end
if SliderReg.HandMoveZ then SliderReg.HandMoveZ.set(0.43) end
if SliderReg.HandScale then SliderReg.HandScale.set(0.4) end
notify("Hand Editor", "Default hand layout restored")
end)
mkT(pVis, "Echo Hand (Afterimages)", false, function(s) feat.echoHand = s end, "EchoHand")
mkT(pVis, "Fog Hand (Glow + Smoke)", false, function(s) feat.fogHand = s end, "FogHand")
mkS(pVis, "Outline Radius", 20, 200, 70, function(v) feat.outlineRadius = v end, "OutlineRadius")
mkS(pVis, "Outline Thickness", 0.02, 0.15, 0.05, function(v) feat.outlineThick = v end, "OutlineThick", true)
local olBox = mkInput(pVis, "Outline Color", "#000000", nil, function(c, final) feat.outlineColorHex = colorToHex(c); if final then Fn.rebuildVFX() end end)
olBox.Text = "#000000"
olBox.FocusLost:Connect(function()
local c = hexToColor(olBox.Text)
if c then feat.outlineColorHex = colorToHex(c); Fn.rebuildVFX() end
end)
hdr(pVis, "Auras")
mkT(pVis, "Aura Ring", false, function(s) feat.auraRing = s; Fn.rebuildAuraRing() end, "AuraRing")
mkS(pVis, "Ring Size", 1, 10, 3.2, function(v) feat.auraRingSize = v; if feat.auraRing then Fn.rebuildAuraRing() end end, "AuraRingSize", true)
mkT(pVis, "Orbiting Orbs", false, function(s) feat.orbitOrbs = s; Fn.rebuildOrbs() end, "OrbitOrbs")
mkS(pVis, "Orb Count", 2, 24, 6, function(v) feat.orbitOrbCount = v; if feat.orbitOrbs then Fn.rebuildOrbs() end end, "OrbCount")
mkS(pVis, "Orb Radius", 1, 10, 2.6, function(v) feat.orbitOrbRadius = v end, "OrbRadius", true)
mkS(pVis, "Orb Speed", 0.1, 6, 1.6, function(v) feat.orbitOrbSpeed = v end, "OrbSpeed", true)
mkS(pVis, "Orb Size", 0.1, 1.5, 0.4, function(v) feat.orbitOrbSize = v; if feat.orbitOrbs then Fn.rebuildOrbs() end end, "OrbSize", true)
mkT(pVis, "Fire Aura", false, function(s) feat.fire = s; Fn.rebuildVFX() end, "VFXFire")
mkT(pVis, "Sparkle Aura", false, function(s) feat.sparkle = s; Fn.rebuildVFX() end, "VFXSparkle")
mkT(pVis, "Lightning Aura", false, function(s) feat.lightningAura = s; Fn.rebuildLightning() end, "LightningAura")
mkS(pVis, "Lightning Rate", 1, 30, 8, function(v) feat.lightningRate = v end, "LightningRate", true)
hdr(pVis, "Trails")
mkT(pVis, "Trail", false, function(s) feat.trail = s; Fn.rebuildVFX() end, "VFXTrail")
mkT(pVis, "Fire Footsteps", false, function(s) feat.fireFootsteps = s; Fn.rebuildFireFootsteps() end, "FireFootsteps")
hdr(pVis, "Movement FX")
mkT(pVis, "Jump Rings", false, function(s) feat.jumpRing = s; Fn.rebuildVFX() end, "VFXJumpRing")
mkT(pVis, "Landing Rings", false, function(s) feat.landRing = s; Fn.rebuildVFX() end, "VFXLandRing")
hdr(pVis, "ESP / Chams")
mkT(pVis, "Player ESP", false, function(s) feat.espEnabled = s; Fn.setEspEnabled(s) end, "EspEnabled")
mkT(pVis, "ESP Names", true, function(s) feat.espNames = s; Fn.refreshEsp() end, "EspNames")
mkT(pVis, "ESP Health", true, function(s) feat.espHealth = s; Fn.refreshEsp() end, "EspHealth")
mkT(pVis, "ESP Distance", true, function(s) feat.espDistance = s; Fn.refreshEsp() end, "EspDistance")
mkT(pVis, "Chams (Highlight)", false, function(s) feat.espChams = s; Fn.refreshEsp() end, "EspChams")
mkT(pVis, "Team Check", false, function(s) feat.espTeamCheck = s end, "EspTeam")
mkS(pVis, "ESP Max Distance", 50, 2000, 500, function(v) feat.espMaxDist = v end, "EspMaxDist")
hdr(pVis, "Crosshair")
mkT(pVis, "Show Crosshair", false, function(s) feat.crosshair = s; Fn.rebuildCrosshair() end, "Crosshair")
mkB(pVis, "Style: Cross", function() feat.crosshairStyle = "cross"; Fn.rebuildCrosshair() end)
mkB(pVis, "Style: Dot", function() feat.crosshairStyle = "dot"; Fn.rebuildCrosshair() end)
mkB(pVis, "Style: X", function() feat.crosshairStyle = "x"; Fn.rebuildCrosshair() end)
mkB(pVis, "Style: Circle", function() feat.crosshairStyle = "circle"; Fn.rebuildCrosshair() end)
mkS(pVis, "Size", 2, 30, 8, function(v) feat.crosshairSize = v; Fn.rebuildCrosshair() end, "ChSize")
mkS(pVis, "Thickness", 1, 6, 2, function(v) feat.crosshairThickness = v; Fn.rebuildCrosshair() end, "ChThick")
mkS(pVis, "Gap", 0, 20, 4, function(v) feat.crosshairGap = v; Fn.rebuildCrosshair() end, "ChGap")
mkT(pVis, "Center Dot", true, function(s) feat.crosshairDot = s; Fn.rebuildCrosshair() end, "ChDot")
mkT(pVis, "Outline", true, function(s) feat.crosshairOutline = s; Fn.rebuildCrosshair() end, "ChOutline")
local chColorBox = mkInput(pVis, "Crosshair Color", "#FFFFFF", nil, function(c) feat.crosshairColorHex = colorToHex(c); Fn.rebuildCrosshair() end)
chColorBox.Text = "#FFFFFF"
chColorBox.FocusLost:Connect(function()
local c = hexToColor(chColorBox.Text)
if c then feat.crosshairColorHex = colorToHex(c); Fn.rebuildCrosshair() end
end)
end
-- OVERLAYS TAB
do
hdr(pOver, "HUD Pack")
mkB(pOver, "Enable Full HUD (current theme)", function() Fn.hudPack() end)
hdr(pOver, "Overlays")
mkT(pOver, "Potions (Active Effects)", false, function(s) overlays.potions.Visible = s; if s and Fn.potionsRebuild then Fn.potionsRebuild() end end, "Potions")
mkT(pOver, "Music HUD", false, function(s) overlays.musicHud.Visible = s; if s then Fn.updateHud() end end, "MusicHud")
mkT(pOver, "Lyrics Bar", false, function(s) overlays.lyrics.Visible = s; Lyrics.barKey = nil end, "LyricsBar")
mkT(pOver, "Coordinates", false, function(s) overlays.coords.Visible = s end, "Coords")
mkT(pOver, "Speed", false, function(s) overlays.speed.Visible = s end, "SpeedHud")
mkT(pOver, "Keybind Overlay", false, function(s) overlays.keybinds.Visible = s; if s then Fn.refreshKb() end end, "KbOverlay")
mkT(pOver, "Keystrokes", false, function(s) overlays.keystrokes.Visible = s end, "Keystrokes")
mkT(pOver, "Mousestrokes", false, function(s) overlays.mousestrokes.Visible = s end, "Mousestrokes")
mkT(pOver, "Status Bar", false, function(s) overlays.statusBar.Visible = s; if not s then pcall(function() Fn.setSbMode("normal", false) end) end end, "StatusBar")
mkT(pOver, "FPS Counter", false, function(s) overlays.fps.Visible = s end, "FpsBox")
mkT(pOver, "Ping", false, function(s) overlays.ping.Visible = s end, "PingBox")
hdr(pOver, "Edit Widgets")
local editHint = new("TextLabel",{Size=UDim2.new(1,-4,0,58),BackgroundColor3=T.Card,BackgroundTransparency=TR.Card,Font=Enum.Font.Gotham,
Text=" Open chat (press / or click the chat bar) to enter edit mode. Drag the separate-looking logo and status strip together as one widget. Click widgets to cycle layouts. Drag the corner to resize Keystrokes and Mousestrokes.",
TextColor3=T.Dim,TextSize=11,TextXAlignment=Enum.TextXAlignment.Left,TextYAlignment=Enum.TextYAlignment.Center,TextWrapped=true,BorderSizePixel=0,Parent=pOver})
editHint:SetAttribute("OwoLbl", "edit widgets chat")
corner(editHint, RM); stroke(editHint, 1, 0.55, T.Line); regRef(editHint, "BackgroundColor3", "Card"); regRef(editHint, "TextColor3", "Dim"); regCard(editHint)
hdr(pOver, "Status Bar Lyrics")
mkT(pOver, "Show Lyrics in Status Bar", true, function(s) feat.lyricsInStatusBar = s; Lyrics.sbKey = nil end, "StatusBarLyrics")
mkT(pOver, "Smooth Transition", true, function(s) feat.smoothLyricsTransition = s end, "SmoothLyrics")
mkS(pOver, "Transition Duration", 0.1, 2, 0.6, function(v) feat.lyricsTransitionDuration = v end, "LyricsTransition", true)
hdr(pOver, "Position")
mkB(pOver, "Reset All Positions", function()
for n, f in pairs(overlays) do if UI.defaultPos[n] then f.Position = UI.defaultPos[n] end end
notify("Overlays", "All positions reset")
end)
hdr(pOver, "Reset Individual Overlays")
local OVERLAY_LABELS = {
statusBar = "Status Bar", fps = "FPS Counter", coords = "Coordinates",
ping = "Ping", keybinds = "Keybind Overlay",
musicHud = "Music HUD", speed = "Speed", lyrics = "Lyrics Bar",
keystrokes = "Keystrokes", mousestrokes = "Mousestrokes", potions = "Potions",
}
for key, label in pairs(OVERLAY_LABELS) do
local btn = new("TextButton", {
Size = UDim2.new(0.5, -5, 0, 40), BackgroundColor3 = T.Card,
BackgroundTransparency = TR.Card, BorderSizePixel = 0,
AutoButtonColor = false, Text = "", Parent = pOver,
})
btn:SetAttribute("OwoLbl", ("reset " .. label):lower())
corner(btn, RM); stroke(btn, 1, 0.55, T.Line)
regRef(btn, "BackgroundColor3", "Card"); regCard(btn)
local lbl = new("TextLabel", {
BackgroundTransparency = 1, Size = UDim2.new(1, -32, 1, 0),
Position = UDim2.new(0, 14, 0, 0), Font = Enum.Font.GothamMedium,
Text = "Reset " .. label, TextColor3 = T.Text, TextSize = 12,
TextXAlignment = Enum.TextXAlignment.Left, ZIndex = 3, Parent = btn,
})
regRef(lbl, "TextColor3", "Text")
local icon = new("TextLabel", {
BackgroundTransparency = 1, Size = UDim2.new(0, 20, 1, 0),
Position = UDim2.new(1, -24, 0, 0), Font = Enum.Font.GothamBold,
Text = "↺", TextColor3 = T.Muted, TextSize = 14,
TextXAlignment = Enum.TextXAlignment.Right, ZIndex = 3, Parent = btn,
})
regRef(icon, "TextColor3", "Muted")
hoverFx(btn)
btn.MouseButton1Click:Connect(function()
playUiSoundLayered("click")
local f = overlays[key]
local d = UI.defaultPos[key]
if f and d then
tween(f, 0.2, { Position = d })
if Fn.resetLayout then Fn.resetLayout(key) end
notify("Overlay", label .. " reset")
else
notify("Overlay", label .. " not available", false)
end
end)
end
end
-- THEMES
do
hdr(pTheme, "Home Effects")
mkT(pTheme, "GUI Shine", false, function(s) feat.guiShine = s end, "GuiShine")
mkT(pTheme, "Home Cursor Hover Effect", false, function(enabled)
if Fn.setHomeHover then Fn.setHomeHover(enabled) end
end, nil, "HomeHoverReveal")
hdr(pTheme, "Smoothness")
mkS(pTheme, "UI Smoothness", 0.3, 3, 1.0, function(v) Smooth.level = v end, "UISmoothness", true)
mkS(pTheme, "Color Transition Speed", 0.5, 3, 4.0, function(v) Smooth.colorSpeed = v end, "ColorSpeed", true)
mkS(pTheme, "Effect Transition Speed", 1, 15, 7.0, function(v) Smooth.effectSpeed = v end, "EffectSpeed", true)
hdr(pTheme, "Liquid Glass")
-- live preview: colourful backdrop with a real glass pill on top
local pv = new("Frame",{Size=UDim2.new(1,-4,0,120),BackgroundColor3=Color3.fromRGB(10,12,22),BorderSizePixel=0,ClipsDescendants=true,Parent=pTheme})
pv:SetAttribute("OwoLbl", "liquid glass preview")
corner(pv, RM); stroke(pv, 1, 0.55, T.Line, true)
local function orb(x, y, s, c)
local o = new("Frame",{Size=UDim2.new(0,s,0,s),Position=UDim2.new(x,-s/2,y,-s/2),BackgroundColor3=c,BorderSizePixel=0,Parent=pv})
corner(o, s/2); return o
end
orb(0.16, 0.30, 74, Color3.fromRGB(255,110,150)); orb(0.50, 0.78, 96, Color3.fromRGB(90,160,255))
orb(0.84, 0.28, 66, Color3.fromRGB(120,255,190)); orb(0.68, 0.50, 40, Color3.fromRGB(255,200,90))
local gp = new("Frame",{Size=UDim2.new(0.62,0,0,64),Position=UDim2.new(0.19,0,0.5,-32),BackgroundColor3=T.Bg,BackgroundTransparency=Glass.winT(),BorderSizePixel=0,Parent=pv})
corner(gp, 18)
Glass.G.decorate(gp, {always=true})
local gpT = new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,0,0,12),Size=UDim2.new(1,0,0,22),Font=Enum.Font.GothamBold,Text="Liquid Glass",TextColor3=Color3.new(1,1,1),TextSize=16,ZIndex=5,Parent=gp})
local gpS = new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,0,0,34),Size=UDim2.new(1,0,0,16),Font=Enum.Font.Gotham,Text="move your cursor over me",TextColor3=Color3.fromRGB(200,205,220),TextSize=10,ZIndex=5,Parent=gp})
Glass.refreshAll()
-- style presets
local styleRow = new("Frame",{Size=UDim2.new(1,-4,0,38),BackgroundTransparency=1,Parent=pTheme})
styleRow:SetAttribute("OwoLbl", "glass style frosted clear tinted crystal midnight")
new("UIListLayout",{FillDirection=Enum.FillDirection.Horizontal,Padding=UDim.new(0,6),SortOrder=Enum.SortOrder.LayoutOrder,Parent=styleRow})
Glass.styleBtns = {}
for i, name in ipairs(Glass.styleOrder) do
local b = new("TextButton",{Size=UDim2.new(1/#Glass.styleOrder,-5,1,0),LayoutOrder=i,BackgroundColor3=T.Card,BackgroundTransparency=TR.Card,Text=name,Font=Enum.Font.GothamBold,TextColor3=T.Dim,TextSize=11,BorderSizePixel=0,AutoButtonColor=false,Parent=styleRow})
corner(b, RM); stroke(b, 1, 0.55, T.Line, true); regRef(b, "BackgroundColor3", "Card"); regCard(b)
b.MouseButton1Click:Connect(function() playUiSoundLayered("click"); Fn.setGlassStyle(name) end)
Glass.styleBtns[name] = b
end
Glass.paintStyleBtns = function()
for n, b in pairs(Glass.styleBtns) do
local sel = (n == Glass.style)
b.TextColor3 = sel and T.Accent or T.Dim
local s = b:FindFirstChildOfClass("UIStroke")
if s then s.Color = sel and T.Accent or T.Line; s.Transparency = sel and 0.2 or 0.55 end
end
end
Glass.paintStyleBtns()
hdr(pTheme, "Sound Theme")
mkT(pTheme, "Mommy Mode", false, function(enabled)
feat.mommyMode = enabled
UISounds.mommyMode = enabled
if UI.mommyBackground then UI.mommyBackground.Visible = enabled end
if enabled then
UISounds.normalPitch = feat.uiSoundPitch or UISounds.normalPitch or 1.4
feat.uiSoundPitch = 1.0
UISounds.pitch = 1.0
playUiSound("menuOpen")
notify("Mommy Mode", "Custom UI sounds enabled")
else
feat.uiSoundPitch = UISounds.normalPitch or 1.4
UISounds.pitch = feat.uiSoundPitch
playUiSound("click")
notify("Mommy Mode", "Custom UI sounds disabled")
end
end, "MommyMode")
mkT(pTheme, "Liquid Glass", false, function(s) Fn.setGlass(s) end, "LiquidGlass")
mkT(pTheme, "Blur World Behind Menu", true, function(s) Glass.worldBlur = s end, "GlassWorldBlur")
mkT(pTheme, "Light Follows Cursor", true, function(s) Glass.anim = s end, "GlassAnim")
local function gset(field, post)
return function(v)
Glass[field] = v
if not Glass.applying then Glass.style = "Custom"; if Glass.paintStyleBtns then Glass.paintStyleBtns() end end
if post then post() end
Glass.refreshAll()
end
end
mkS(pTheme, "Glass Clarity", 30, 100, 62, gset("clarity", function() if Glass.on then Fn.applyGlassTransparency() end end), "GlassClarity")
mkS(pTheme, "Frost Blur", 0, 30, 10, gset("blur"), "GlassBlur")
mkS(pTheme, "Shine", 0, 1, 0.55, gset("shine"), "GlassShine", true)
mkS(pTheme, "Edge Light", 1, 4, 2.4, gset("refraction"), "GlassRefraction", true)
mkS(pTheme, "Tint", 0, 1, 0, gset("tint"), "GlassTint", true)
hdr(pTheme, "UI Transparency")
mkS(pTheme, "Window Opacity", 0, 90, 0, function(v) UI.opacity = v; if not Glass.on then Fn.setOpacity(v / 100) end end, "UITransparency")
hdr(pTheme, "Custom Background")
mkT(pTheme, "Use Decal Background", false, function(s) feat.uiBackground = s; Fn.applyUIBackground() end, "UIBackground")
local bgIdBox = mkInput(pTheme, "Decal / Image ID", "e.g. 1234567890", 200)
bgIdBox.FocusLost:Connect(function()
local raw = tostring(bgIdBox.Text or ""):gsub("%s",""):gsub("rbxassetid://",""):gsub("[^%d]","")
if raw == "" then return end
feat.uiBackgroundId = raw
Fn.applyUIBackground()
notify("Background", "Loaded ID "..raw)
end)
mkS(pTheme, "Background Transparency", 0, 1, 0.3, function(v) feat.uiBackgroundTransparency = v; Fn.applyUIBackground() end, "UIBackgroundTrans", true)
hdr(pTheme, "Full HUD")
for _, name in ipairs(PRESET_ORDER) do mkB(pTheme, name .. " HUD", function() Fn.hudPack(name) end) end
hdr(pTheme, "Presets (Smooth Transition)")
for _, name in ipairs(PRESET_ORDER) do
mkB(pTheme, name, function()
Fn.smoothThemeApply(PRESETS[name], 0.8)
task.delay(0.85, function()
if UI.hudSync then Fn.setEffectColor(PRESETS[name].Accent, true) end
Fn.refreshKb(); Fn.updateHud()
if Glass.paintStyleBtns then Glass.paintStyleBtns() end
notify("Theme", name .. " applied")
end)
end)
end
end
-- MUSIC
do
-- Spotify launches in the user's Spotify app/browser. Roblox cannot stream
-- Spotify audio into SoundService, so this keeps the integration external.
hdr(pMusic, "Spotify")
local spotifyLinkBox = mkInput(pMusic, "Spotify link", "Track / playlist URL", 220)
spotifyLinkBox.Text = "https://open.spotify.com/"
local spotifyHint = new("TextLabel", {
Size=UDim2.new(1,-10,0,30), BackgroundTransparency=1,
Font=Enum.Font.Gotham, Text="Spotify plays in its own app or browser while Roblox stays open.",
TextColor3=T.Muted, TextSize=10, TextWrapped=true,
TextXAlignment=Enum.TextXAlignment.Left, Parent=pMusic
})
regRef(spotifyHint, "TextColor3", "Muted")
local function getSpotifyUrl()
local raw = tostring(spotifyLinkBox.Text or ""):gsub("^%s+", ""):gsub("%s+$", "")
if raw == "" then raw = "https://open.spotify.com/" end
if raw == "https://open.spotify.com" then raw = raw .. "/" end
local kind, id = raw:match("^spotify:([%a]+):([%w]+)$")
local allowedKinds = {track=true, album=true, playlist=true, artist=true, show=true, episode=true}
if kind and id and allowedKinds[kind] then
raw = "https://open.spotify.com/" .. kind .. "/" .. id
end
if not raw:match("^https://open%.spotify%.com/") and not raw:match("^https://spotify%.link/") then
notify("Spotify", "Enter a Spotify track, album or playlist link", false)
return nil
end
return raw
end
local function copySpotifyUrl(url)
if typeof(setclipboard) == "function" then
local ok = pcall(setclipboard, url)
if ok then
notify("Spotify", "Link copied. Paste it into Spotify or your browser")
return true
end
end
notify("Spotify", "Could not open automatically. Use: " .. url, false)
return false
end
local function openSpotifyLink()
local url = getSpotifyUrl()
if not url then return end
local opener = nil
if typeof(openurl) == "function" then
opener = openurl
elseif typeof(open_url) == "function" then
opener = open_url
elseif typeof(openURL) == "function" then
opener = openURL
elseif typeof(syn) == "table" and typeof(syn.open_url) == "function" then
opener = function(value) return syn.open_url(value) end
end
if opener then
local ok, result = pcall(opener, url)
if ok and result ~= false then
notify("Spotify", "Opening Spotify")
return
end
end
copySpotifyUrl(url)
end
mkAccentBtn(pMusic, "Open Spotify", openSpotifyLink)
mkB(pMusic, "Copy Spotify Link", function()
local url = getSpotifyUrl()
if url then copySpotifyUrl(url) end
end)
hdr(pMusic, "Now Playing")
local nowCard = new("Frame",{Size=UDim2.new(1,-4,0,72),BackgroundColor3=T.Card,BackgroundTransparency=TR.Card,BorderSizePixel=0,Parent=pMusic})
nowCard:SetAttribute("OwoLbl", "now playing")
corner(nowCard, RM); stroke(nowCard, 1, 0.55, T.Line); regRef(nowCard, "BackgroundColor3", "Card"); regCard(nowCard)
UI.nowLbl = new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,16,0,12),Size=UDim2.new(1,-32,0,20),Font=Enum.Font.GothamBold,Text="Nothing playing",TextColor3=T.Text,TextSize=13,TextXAlignment=Enum.TextXAlignment.Left,TextTruncate=Enum.TextTruncate.AtEnd,Parent=nowCard})
regRef(UI.nowLbl, "TextColor3", "Text")
local nowSub = new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,16,0,34),Size=UDim2.new(1,-32,0,16),Font=Enum.Font.Gotham,Text="Save songs below, then control them here or from the Music HUD",TextColor3=T.Muted,TextSize=10,TextXAlignment=Enum.TextXAlignment.Left,Parent=nowCard})
regRef(nowSub, "TextColor3", "Muted")
local ctrlRow = new("Frame",{Size=UDim2.new(1,-4,0,42),BackgroundTransparency=1,Parent=pMusic})
ctrlRow:SetAttribute("OwoLbl", "prev play pause stop next loop")
new("UIListLayout",{FillDirection=Enum.FillDirection.Horizontal,Padding=UDim.new(0,6),SortOrder=Enum.SortOrder.LayoutOrder,Parent=ctrlRow})
local function mkMusicBtn(text, order, cb)
local b = new("TextButton",{Size=UDim2.new(0.2,-5,1,0),BackgroundColor3=T.Card,BackgroundTransparency=TR.Card,Text=text,Font=Enum.Font.GothamBold,TextColor3=T.Text,TextSize=11,BorderSizePixel=0,AutoButtonColor=false,LayoutOrder=order,Parent=ctrlRow})
corner(b, RM); stroke(b, 1, 0.55, T.Line); regRef(b, "BackgroundColor3", "Card"); regRef(b, "TextColor3", "Text"); regCard(b)
hoverFx(b)
b.MouseButton1Click:Connect(function() playUiSoundLayered("click"); cb(b) end)
return b
end
mkMusicBtn("Prev", 1, function() Music.prev() end)
mkMusicBtn("Play/Pause", 2, function() Music.toggle() end)
mkMusicBtn("Stop", 3, function() Music.stop() end)
mkMusicBtn("Next", 4, function() Music.next() end)
UI.loopBtn = mkMusicBtn("Loop: ON", 5, function(self)
Music.looped = not Music.looped; Music.sound.Looped = Music.looped
self.Text = Music.looped and "Loop: ON" or "Loop: OFF"
end)
hdr(pMusic, "Volume")
mkS(pMusic, "Music Volume", 0, 100, 50, function(v) Music.volume = v / 100; Music.sound.Volume = Music.volume end, "MusicVolume")
hdr(pMusic, "Save a Song")
local nameBox = mkInput(pMusic, "Name", "My song")
local idBox = mkInput(pMusic, "Audio ID", "e.g. 1837879082")
local artBox = mkInput(pMusic, "Artist (for lyrics)", "Enter artist name")
mkAccentBtn(pMusic, "Save to Library", function() Lib.add(idBox.Text, nameBox.Text, artBox.Text) end)
mkAccentBtn(pMusic, "Save Currently Playing", function()
if not Music.id then notify("Library", "Nothing is playing", false) return end
Lib.add(Music.id, nameBox.Text ~= "" and nameBox.Text or Music.name, artBox.Text ~= "" and artBox.Text or Music.artist)
end)
mkAccentBtn(pMusic, "Play this ID", function() Music.play(idBox.Text, nameBox.Text, artBox.Text) end)
hdr(pMusic, "My Songs")
local libList = new("Frame",{Size=UDim2.new(1,-4,0,0),BackgroundTransparency=1,AutomaticSize=Enum.AutomaticSize.Y,Parent=pMusic})
new("UIListLayout",{SortOrder=Enum.SortOrder.LayoutOrder,Padding=UDim.new(0,6),Parent=libList})
Lib.refresh = function()
for _, c in ipairs(libList:GetChildren()) do if c:IsA("Frame") or c:IsA("TextLabel") then c:Destroy() end end
if #Lib.list == 0 then
local e = new("TextLabel",{Size=UDim2.new(1,0,0,42),BackgroundColor3=T.Card,BackgroundTransparency=TR.Card,Font=Enum.Font.Gotham,Text="No saved songs yet",TextColor3=T.Muted,TextSize=11,BorderSizePixel=0,Parent=libList})
corner(e, RM); stroke(e, 1, 0.55, T.Line); regRef(e, "BackgroundColor3", "Card"); regCard(e)
return
end
for i, entry in ipairs(Lib.list) do
local row = new("Frame",{Size=UDim2.new(1,0,0,52),BackgroundColor3=T.Card,BackgroundTransparency=TR.Card,BorderSizePixel=0,LayoutOrder=i,Parent=libList})
corner(row, RM); stroke(row, 1, 0.55, T.Line); regRef(row, "BackgroundColor3", "Card"); regCard(row)
new("TextBox",{BackgroundTransparency=1,Position=UDim2.new(0,12,0,5),Size=UDim2.new(1,-140,0,22),Font=Enum.Font.GothamBold,Text=entry.name,TextColor3=T.Text,TextSize=12,TextXAlignment=Enum.TextXAlignment.Left,ClearTextOnFocus=false,TextTruncate=Enum.TextTruncate.AtEnd,Parent=row})
new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,12,0,28),Size=UDim2.new(1,-140,0,16),Font=Enum.Font.Gotham,Text="ID: "..entry.id,TextColor3=T.Muted,TextSize=10,TextXAlignment=Enum.TextXAlignment.Left,TextTruncate=Enum.TextTruncate.AtEnd,Parent=row})
local play = new("TextButton",{Size=UDim2.new(0,64,0,28),Position=UDim2.new(1,-118,0.5,-14),BackgroundColor3=Color3.new(1,1,1),Text="Play",Font=Enum.Font.GothamBold,TextColor3=ON_ACCENT,TextSize=11,BorderSizePixel=0,AutoButtonColor=false,ZIndex=4,Parent=row})
corner(play, 7); gradient(play, T.Accent, T.Accent2, 0)
play.MouseButton1Click:Connect(function() playUiSoundLayered("click"); Music.play(entry.id, entry.name, entry.artist) end)
local del = new("TextButton",{Size=UDim2.new(0,36,0,28),Position=UDim2.new(1,-46,0.5,-14),BackgroundColor3=T.Card,Text="X",Font=Enum.Font.GothamBold,TextColor3=T.Bad,TextSize=12,BorderSizePixel=0,AutoButtonColor=false,ZIndex=4,Parent=row})
corner(del, 7); stroke(del, 1, 0.55, T.Line)
del.MouseButton1Click:Connect(function() playUiSoundLayered("click"); Lib.remove(i) end)
end
end
Lib.refresh()
hdr(pMusic, "3D Lyrics")
mkT(pMusic, "3D Lyrics (in the air)", false, function(s) feat.lyrics3d = s; Lyrics.A.idx = nil end, "Lyrics3D")
mkS(pMusic, "3D Lyrics Size", 0.8, 3, 1.6, function(v) Lyrics.airScale = v end, "Lyrics3DSize", true)
mkT(pMusic, "Auto-find lyrics when playing", true, function(s) Lyrics.auto = s end, "LyricsAuto")
mkS(pMusic, "Lyrics Offset (sec)", -8, 5, 0, function(v) Lyrics.offset = v end, "LyricsOffset", true)
local lyBox = mkInput(pMusic, "Artist - Song", "Enter actual title + artist", 190)
mkAccentBtn(pMusic, "Find Lyrics", function()
local q = lyBox.Text
if q == "" then
if Music.id and Music.name:match("^Audio%s+%d+$") then
notify("Lyrics", "Enter the song title and artist first. A Roblox audio ID alone has no reliable lyric metadata.", false)
return
end
q = (Music.artist ~= "" and (Music.artist.." ") or "") .. (Music.id and Music.name or "")
end
Lyrics.fetch(q)
end)
hdr(pMusic, "Manual Lyrics")
local lyricsHelp = new("TextLabel",{Size=UDim2.new(1,-8,0,30),BackgroundTransparency=1,
Font=Enum.Font.Gotham,Text="Paste LRC timestamps like [01:23.45] or plain text. Plain text is spread across the song.",
TextColor3=T.Muted,TextSize=10,TextWrapped=true,TextXAlignment=Enum.TextXAlignment.Left,
Parent=pMusic})
regRef(lyricsHelp,"TextColor3","Muted")
local pasteRow = new("Frame",{Size=UDim2.new(1,-4,0,132),BackgroundColor3=T.Card,BackgroundTransparency=TR.Card,BorderSizePixel=0,Parent=pMusic})
pasteRow:SetAttribute("OwoLbl", "paste lyrics")
corner(pasteRow, RM); stroke(pasteRow, 1, 0.55, T.Line); regRef(pasteRow, "BackgroundColor3", "Card"); regCard(pasteRow)
local pasteBox = new("TextBox",{Size=UDim2.new(1,-20,1,-16),Position=UDim2.new(0,10,0,8),BackgroundTransparency=1,Font=Enum.Font.Gotham,Text="",PlaceholderText="Paste your own / permitted lyrics. LRC: [01:23.45] line. Plain text is spread across the track.",TextColor3=T.Text,PlaceholderColor3=T.Muted,TextSize=11,MultiLine=true,TextWrapped=true,TextXAlignment=Enum.TextXAlignment.Left,TextYAlignment=Enum.TextYAlignment.Top,ClearTextOnFocus=false,Parent=pasteRow})
regRef(pasteBox, "TextColor3", "Text")
mkAccentBtn(pMusic, "Load Pasted Lyrics", function() Lyrics.loadText(pasteBox.Text) end)
mkB(pMusic, "Clear Lyrics", function() Lyrics.clear(); notify("Lyrics", "Cleared", false) end)
hdr(pMusic, "Search Roblox Library")
local searchRow = new("Frame",{Size=UDim2.new(1,-4,0,50),BackgroundColor3=T.Card,BackgroundTransparency=TR.Card,BorderSizePixel=0,Parent=pMusic})
searchRow:SetAttribute("OwoLbl", "search roblox library song")
corner(searchRow, RM); stroke(searchRow, 1, 0.55, T.Line); regRef(searchRow, "BackgroundColor3", "Card"); regCard(searchRow)
local searchInput = new("TextBox",{Size=UDim2.new(1,-140,0,30),Position=UDim2.new(0,12,0.5,-15),BackgroundColor3=T.Bg,BackgroundTransparency=0.3,Font=Enum.Font.GothamMedium,Text="",PlaceholderText="song name or artist",TextColor3=T.Text,PlaceholderColor3=T.Muted,TextSize=12,BorderSizePixel=0,ClearTextOnFocus=false,Parent=searchRow})
corner(searchInput, 8); stroke(searchInput, 1, 0.55, T.Line)
regRef(searchInput, "BackgroundColor3", "Bg"); regRef(searchInput, "TextColor3", "Text")
local searchBtn = new("TextButton",{Size=UDim2.new(0,100,0,30),Position=UDim2.new(1,-112,0.5,-15),BackgroundColor3=Color3.new(1,1,1),Text="Search",Font=Enum.Font.GothamBold,TextColor3=ON_ACCENT,TextSize=12,BorderSizePixel=0,AutoButtonColor=false,Parent=searchRow})
corner(searchBtn, 8); gradient(searchBtn, T.Accent, T.Accent2, 0)
local resultsList = new("Frame",{Size=UDim2.new(1,-4,0,0),BackgroundTransparency=1,AutomaticSize=Enum.AutomaticSize.Y,Parent=pMusic})
new("UIListLayout",{SortOrder=Enum.SortOrder.LayoutOrder,Padding=UDim.new(0,6),Parent=resultsList})
local function note(text, h)
local e = new("TextLabel",{Size=UDim2.new(1,0,0,h or 40),BackgroundColor3=T.Card,BackgroundTransparency=TR.Card,Font=Enum.Font.Gotham,Text=text,TextColor3=T.Muted,TextSize=11,TextWrapped=true,BorderSizePixel=0,Parent=resultsList})
corner(e, RM); stroke(e, 1, 0.55, T.Line); regRef(e, "BackgroundColor3", "Card"); regCard(e)
return e
end
local function doSearch()
local query = searchInput.Text:gsub("^%s+", ""):gsub("%s+$", "")
if query == "" then notify("Music", "Type something to search", false) return end
for _, c in ipairs(resultsList:GetChildren()) do if c:IsA("Frame") or c:IsA("TextLabel") then c:Destroy() end end
local loading = note("Searching...", 36)
task.spawn(function()
local items
local ok, pages = pcall(function()
local params = Instance.new("AudioSearchParams")
params.SearchKeyword = query
return AssetService:SearchAudio(params)
end)
if ok and pages then
local ok2, page = pcall(function() return pages:GetCurrentPage() end)
if ok2 and type(page) == "table" then
items = {}
for _, it in ipairs(page) do items[#items+1] = { id = it.Id, name = it.Title or it.Name, artist = it.Artist } end
end
end
if not items then
local ok3, old = pcall(function() return AssetService:SearchAudioAsync(query, Enum.AssetType.Audio, 1, 20) end)
if ok3 and type(old) == "table" then
items = {}
for _, it in ipairs(old) do items[#items+1] = { id = it.Id, name = it.Name or it.Title, artist = it.Artist } end
end
end
loading:Destroy()
if not items or #items == 0 then note("No results (search may be blocked in-game) — paste an audio ID instead.", 44) return end
for i, item in ipairs(items) do
local row = new("Frame",{Size=UDim2.new(1,0,0,48),BackgroundColor3=T.Card,BackgroundTransparency=TR.Card,BorderSizePixel=0,LayoutOrder=i,Parent=resultsList})
corner(row, RM); stroke(row, 1, 0.55, T.Line); regRef(row, "BackgroundColor3", "Card"); regCard(row)
local tl = new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,12,0,6),Size=UDim2.new(1,-170,0,18),Font=Enum.Font.GothamBold,Text=tostring(item.name or "Unknown"),TextColor3=T.Text,TextSize=12,TextXAlignment=Enum.TextXAlignment.Left,TextTruncate=Enum.TextTruncate.AtEnd,Parent=row})
regRef(tl, "TextColor3", "Text")
local sl = new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,12,0,24),Size=UDim2.new(1,-170,0,14),Font=Enum.Font.Gotham,Text="ID: "..tostring(item.id).." • "..tostring(item.artist or "Unknown"),TextColor3=T.Muted,TextSize=10,TextXAlignment=Enum.TextXAlignment.Left,TextTruncate=Enum.TextTruncate.AtEnd,Parent=row})
regRef(sl, "TextColor3", "Muted")
local playB = new("TextButton",{Size=UDim2.new(0,54,0,28),Position=UDim2.new(1,-120,0.5,-14),BackgroundColor3=Color3.new(1,1,1),Text="Play",Font=Enum.Font.GothamBold,TextColor3=ON_ACCENT,TextSize=11,BorderSizePixel=0,AutoButtonColor=false,Parent=row})
corner(playB, 7); gradient(playB, T.Accent, T.Accent2, 0)
playB.MouseButton1Click:Connect(function() Music.play(item.id, item.name, item.artist) end)
local saveB = new("TextButton",{Size=UDim2.new(0,54,0,28),Position=UDim2.new(1,-62,0.5,-14),BackgroundColor3=T.Card,Text="Save",Font=Enum.Font.GothamBold,TextColor3=T.Text,TextSize=11,BorderSizePixel=0,AutoButtonColor=false,Parent=row})
corner(saveB, 7); stroke(saveB, 1, 0.55, T.Line)
saveB.MouseButton1Click:Connect(function() Lib.add(item.id, item.name, item.artist) end)
end
end)
end
searchBtn.MouseButton1Click:Connect(doSearch)
searchInput.FocusLost:Connect(function(enter) if enter then doSearch() end end)
end
-- FRIENDS
do
hdr(pFriends, "Friends")
local topRow = new("Frame", {Size = UDim2.new(1, -4, 0, 42), BackgroundTransparency = 1, Parent = pFriends})
topRow:SetAttribute("OwoLbl", "refresh friends")
new("UIListLayout", {FillDirection = Enum.FillDirection.Horizontal, Padding = UDim.new(0, 6), SortOrder = Enum.SortOrder.LayoutOrder, Parent = topRow})
local refreshBtn = new("TextButton", {Size = UDim2.new(0.5, -3, 1, 0), BackgroundColor3 = Color3.new(1,1,1), Text = "Refresh", Font = Enum.Font.GothamBold, TextColor3 = ON_ACCENT, TextSize = 12, BorderSizePixel = 0, AutoButtonColor = false, LayoutOrder = 1, Parent = topRow})
corner(refreshBtn, RM); gradient(refreshBtn, T.Accent, T.Accent2, 0)
refreshBtn.MouseButton1Click:Connect(function() playUiSoundLayered("click"); Friends.refresh(function() notify("Friends", #Friends.list .. " friends loaded") end) end)
local searchBox = mkInput(pFriends, "Search", "name", 180)
local currentSearch = ""
searchBox:GetPropertyChangedSignal("Text"):Connect(function()
currentSearch = searchBox.Text:lower()
if Friends.refreshList then Friends.refreshList() end
end)
hdr(pFriends, "Your Friends")
local listFrame = new("Frame", {Size = UDim2.new(1, -4, 0, 0), BackgroundTransparency = 1, AutomaticSize = Enum.AutomaticSize.Y, Parent = pFriends})
new("UIListLayout", {SortOrder = Enum.SortOrder.LayoutOrder, Padding = UDim.new(0, 6), Parent = listFrame})
Friends.refreshList = function()
for _, c in ipairs(listFrame:GetChildren()) do if c:IsA("Frame") or c:IsA("TextLabel") then c:Destroy() end end
local list = Friends.list
if currentSearch ~= "" then
local filtered = {}
for _, f in ipairs(list) do
if (f.username:lower():find(currentSearch, 1, true) or (f.displayName or ""):lower():find(currentSearch, 1, true)) then filtered[#filtered + 1] = f end
end
list = filtered
end
if #list == 0 then
local e = new("TextLabel", {Size = UDim2.new(1, 0, 0, 42), BackgroundColor3 = T.Card, BackgroundTransparency = TR.Card, Font = Enum.Font.Gotham, Text = "No friends to show.", TextColor3 = T.Muted, TextSize = 11, BorderSizePixel = 0, Parent = listFrame})
corner(e, RM); stroke(e, 1, 0.55, T.Line); regRef(e, "BackgroundColor3", "Card"); regCard(e)
return
end
for i, entry in ipairs(list) do
local row = new("Frame", {Size = UDim2.new(1, 0, 0, 52), BackgroundColor3 = T.Card, BackgroundTransparency = TR.Card, BorderSizePixel = 0, LayoutOrder = i, Parent = listFrame})
corner(row, RM); stroke(row, 1, 0.55, T.Line); regRef(row, "BackgroundColor3", "Card"); regCard(row)
local av = new("Frame", {Size = UDim2.new(0, 34, 0, 34), Position = UDim2.new(0, 10, 0.5, -17), BackgroundColor3 = T.Off, BorderSizePixel = 0, Parent = row}); corner(av, 17)
local avi = new("ImageLabel", {Size = UDim2.new(1, 0, 1, 0), BackgroundTransparency = 1, Parent = av}); corner(avi, 17)
task.spawn(function()
local ok, thumb = pcall(function() return Players:GetUserThumbnailAsync(entry.userId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size100x100) end)
if ok and thumb then avi.Image = thumb end
end)
new("TextLabel", {BackgroundTransparency = 1, Position = UDim2.new(0, 52, 0, 8), Size = UDim2.new(1, -150, 0, 18), Font = Enum.Font.GothamBold, Text = entry.displayName or entry.username, TextColor3 = T.Text, TextSize = 12, TextXAlignment = Enum.TextXAlignment.Left, TextTruncate = Enum.TextTruncate.AtEnd, Parent = row})
new("TextLabel", {BackgroundTransparency = 1, Position = UDim2.new(0, 52, 0, 26), Size = UDim2.new(1, -150, 0, 16), Font = Enum.Font.Gotham, Text = "@" .. entry.username, TextColor3 = entry.isOnline and T.Accent or T.Muted, TextSize = 10, TextXAlignment = Enum.TextXAlignment.Left, Parent = row})
local favBtn = new("TextButton", {Size = UDim2.new(0, 26, 0, 26), Position = UDim2.new(1, -70, 0.5, -13), BackgroundTransparency = 1, Text = entry.isFavourite and "★" or "☆", Font = Enum.Font.GothamBold, TextColor3 = entry.isFavourite and Color3.fromRGB(255, 200, 60) or T.Muted, TextSize = 18, AutoButtonColor = false, Parent = row})
favBtn.MouseButton1Click:Connect(function() playUiSoundLayered("click"); Friends.toggleFavourite(entry.userId) end)
local msgBtn = new("TextButton", {Size = UDim2.new(0, 44, 0, 26), Position = UDim2.new(1, -42, 0.5, -13), BackgroundColor3 = Color3.new(1,1,1), Text = "Chat", Font = Enum.Font.GothamBold, TextColor3 = ON_ACCENT, TextSize = 10, BorderSizePixel = 0, AutoButtonColor = false, Parent = row})
corner(msgBtn, 7); gradient(msgBtn, T.Accent, T.Accent2, 0)
msgBtn.MouseButton1Click:Connect(function() playUiSoundLayered("click"); Friends.openChat(entry.userId) end)
end
end
task.spawn(function() task.wait(0.5); Friends.refresh() end)
end
-- SAVES
do
local Saves, SaveOrder = {}, {}
local SAVE_FILE = "owo_saves.json"
local OVKB = {statusBar="StatusBar", fps="FpsBox", coords="Coords", ping="PingBox", keybinds="KbOverlay", musicHud="MusicHud", speed="SpeedHud", lyrics="LyricsBar", keystrokes="Keystrokes", mousestrokes="Mousestrokes", potions="Potions"}
local FEATMAP = {
HomeHoverReveal="homeHoverReveal",
Fly="fly", InfJump="infJump", NoClip="noclip", FreeCam="freeCam", Fullbright="fullbright",
VFXGlow="glow", VFXNeon="neon", VFXTrail="trail", VFXFire="fire", VFXSparkle="sparkle",
VFXHalo="halo", VFXWings="wings", VFXCrown="crown",
SkyBlackHole="skyBlackHole", SkyAurora="skyAurora", SkyGalaxy="skyGalaxy", SkyNebula="skyNebula",
SkyStarryNight="skyStarryNight", VFXJumpRing="jumpRing", VFXLandRing="landRing",
WxRain="rain", WxSnow="snow", WxFog="fog", WxThunder="thunder", FxFireflies="fireflies",
WxMeteor="meteorShower", FxCubes="cubes", FxAmbient="ambient", FxTint="tint",
FxBloom="bloom", FxVignette="vignette", Lyrics3D="lyrics3d", PlayerTrans="playerTransparency",
RainbowChar="rainbowChar", AuraRing="auraRing", OrbitOrbs="orbitOrbs",
LightningAura="lightningAura", FireFootsteps="fireFootsteps", FxButterflies="butterflies",
FxGhost="ghost", FxChroma="chromaticAberration", FxDOF="depthOfField", FxRetro="retroFilter",
FxVHS="vhsFilter", FxGlitch="glitchFilter", SprintFov="sprintFov", CamRoll="cameraRoll",
ScreenShake="screenShake", MotionBlur="motionBlur", Glossy="reflective", Realistic="realistic",
FpsBoost="fpsBoost", UIBackground="uiBackground", SmoothCam="smoothCamera",
EspEnabled="espEnabled", EspNames="espNames", EspHealth="espHealth",
EspDistance="espDistance", EspChams="espChams", EspTeam="espTeamCheck",
Crosshair="crosshair", ChDot="crosshairDot", ChOutline="crosshairOutline",
UISounds="uiSounds", StatusBarLyrics="lyricsInStatusBar", SmoothLyrics="smoothLyricsTransition",
EditAnywhere="editAnywhere", WxRipples="rainRipples", WxPuddles="rainPuddles", WxSnowFloor="snowFloor", KnifeOut="knifeOut", HandOut="handOut", EchoHand="echoHand", FogHand="fogHand", Stretch="stretch",
VFXSanta="santaHat", VFXCape="cape", SelfChams="selfChams", CharOutline="charOutline", WorldOutline="worldOutline",
}
local function col(t) if type(t) == "table" and #t == 3 then return Color3.new(t[1], t[2], t[3]) end return nil end
local function snap()
local d = {theme={}, transparency={}, features={}, keybinds={}, sliders={}, overlays={}, meta={}, music={}, glass={}, friends={}, smooth={}}
for k, v in pairs(T) do if typeof(v) == "Color3" then d.theme[k] = {v.R, v.G, v.B} end end
for k, v in pairs(TR) do d.transparency[k] = v end
for k, v in pairs(feat) do if type(v) == "boolean" or type(v) == "number" or type(v) == "string" then d.features[k] = v end end
d.features.effectColor = {EFFECT_COLOR.R, EFFECT_COLOR.G, EFFECT_COLOR.B}
for n, kb in pairs(Keybinds) do d.keybinds[n] = kb.key and kb.key.Name or nil end
for n, s in pairs(SliderReg) do local ok, v = pcall(s.get); if ok then d.sliders[n] = v end end
for name, frame in pairs(overlays) do d.overlays[name] = {xS=frame.Position.X.Scale, xO=frame.Position.X.Offset, yS=frame.Position.Y.Scale, yO=frame.Position.Y.Offset, vis=frame.Visible} end
local win = UI.win
d.meta.winPos = {xS=win.Position.X.Scale, xO=win.Position.X.Offset, yS=win.Position.Y.Scale, yO=win.Position.Y.Offset}
d.meta.winSize = {w=win.Size.X.Offset, h=win.Size.Y.Offset}
d.music = {volume=Music.volume, looped=Music.looped}
d.glass = {on=Glass.on, style=Glass.style, clarity=Glass.clarity, blur=Glass.blur, shine=Glass.shine, tint=Glass.tint, refraction=Glass.refraction, worldBlur=Glass.worldBlur, anim=Glass.anim, opacity=UI.opacity}
d.smooth = {level=Smooth.level, colorSpeed=Smooth.colorSpeed, effectSpeed=Smooth.effectSpeed}
local favList = {}
for id, v in pairs(Friends.favourites) do if v then favList[#favList+1] = id end end
d.friends = {chats = Friends.chats, favourites = favList}
return d
end
local function load(d)
if type(d) ~= "table" then return false end
Fn.setGlass(false, true)
if d.theme then for k, v in pairs(d.theme) do local c = col(v); if c then T[k] = c end end; applyTheme() end
if d.transparency then for k, v in pairs(d.transparency) do if TR[k] ~= nil then TR[k] = v end end; Fn.applyAllTransparency() end
if d.keybinds then for n, kn in pairs(d.keybinds) do if Keybinds[n] then if kn then local kc = Enum.KeyCode[kn]; if kc then Keybinds[n].key = kc end else Keybinds[n].key = nil end end end end
if d.features then
for k, v in pairs(d.features) do
if k == "effectColor" then local c = col(v); if c then Fn.setEffectColor(c, true) end
elseif feat[k] ~= nil then feat[k] = v end
end
if Fn.setProfilePfp then Fn.setProfilePfp(feat.profilePfpId or "") end
for kbName, featKey in pairs(FEATMAP) do if ToggleReg[kbName] and feat[featKey] ~= nil then pcall(function() ToggleReg[kbName](feat[featKey]) end) end end
Fn.rebuildVFX(); Wx.all()
if Fn.applyScreenFilters then Fn.applyScreenFilters() end
if Fn.rebuildCrosshair then Fn.rebuildCrosshair() end
if Fn.setEspEnabled then Fn.setEspEnabled(feat.espEnabled) end
if Fn.applyUIBackground then Fn.applyUIBackground() end
if Fn.potionsRebuild then Fn.potionsRebuild() end
if Fn.applyAllLayouts then Fn.applyAllLayouts() end
end
if d.sliders then for n, v in pairs(d.sliders) do local s = SliderReg[n]; if s then pcall(function() s.set(v) end) end end end
if d.overlays then
local legacyLogo = d.overlays.statusLogo
for name, pos in pairs(d.overlays) do
if name ~= "statusLogo" then
local f = overlays[name]
if f then
f.Position = UDim2.new(pos.xS, pos.xO, pos.yS, pos.yO)
local m = OVKB[name]
if m and ToggleReg[m] then pcall(ToggleReg[m], pos.vis) else f.Visible = pos.vis end
end
end
end
do
-- Old builds saved the logo and strip as two separate overlays.
-- Migrate either visible legacy piece into the one combined widget.
local oldBar = d.overlays.statusBar
local wasLogoVisible = legacyLogo and legacyLogo.vis == true
local wasBarVisible = oldBar and oldBar.vis == true
overlays.statusBar.Visible = (wasBarVisible or wasLogoVisible) and true or false
end
Fn.refreshKb()
end
if d.meta then
local win = UI.win
if d.meta.winPos then win.Position = UDim2.new(d.meta.winPos.xS, d.meta.winPos.xO, d.meta.winPos.yS, d.meta.winPos.yO) end
if d.meta.winSize then win.Size = UDim2.new(0, math.max(UI.MIN_W, d.meta.winSize.w or UI.ROOT_W), 0, math.max(UI.MIN_H, d.meta.winSize.h or UI.MAIN_H)) end
end
if d.music then
if d.music.volume then Music.volume = d.music.volume; Music.sound.Volume = Music.volume end
if d.music.looped ~= nil then Music.looped = d.music.looped; Music.sound.Looped = Music.looped; if UI.loopBtn then UI.loopBtn.Text = Music.looped and "Loop: ON" or "Loop: OFF" end end
end
if d.glass then
if d.glass.opacity then UI.opacity = d.glass.opacity end
for _, k in ipairs({"clarity","blur","shine","tint","refraction"}) do if type(d.glass[k]) == "number" then Glass[k] = d.glass[k] end end
if d.glass.style then Glass.style = d.glass.style; if Glass.paintStyleBtns then Glass.paintStyleBtns() end end
if d.glass.worldBlur ~= nil and ToggleReg.GlassWorldBlur then pcall(ToggleReg.GlassWorldBlur, d.glass.worldBlur == true) end
if d.glass.anim ~= nil and ToggleReg.GlassAnim then pcall(ToggleReg.GlassAnim, d.glass.anim == true) end
Glass.refreshAll()
if d.glass.on then Fn.setGlass(true, true) end
end
if d.smooth then
if d.smooth.level then Smooth.level = d.smooth.level end
if d.smooth.colorSpeed then Smooth.colorSpeed = d.smooth.colorSpeed end
if d.smooth.effectSpeed then Smooth.effectSpeed = d.smooth.effectSpeed end
end
if d.friends then
if d.friends.chats then Friends.chats = d.friends.chats end
if d.friends.favourites then for _, id in ipairs(d.friends.favourites) do Friends.favourites[id] = true end end
Friends.save(); if Friends.refresh then Friends.refresh() end
end
Fn.updateHud()
return true
end
local function save()
if not FILE_OK then return end
local ok, e = pcall(function() return HttpService:JSONEncode({s=Saves, o=SaveOrder}) end)
if ok then pcall(writefile, SAVE_FILE, e) end
end
if FILE_OK then
local function tryLoad(p)
local ok, ex = pcall(isfile, p); if not (ok and ex) then return nil end
local ok2, raw = pcall(readfile, p); if not ok2 then return nil end
local ok3, d = pcall(function() return HttpService:JSONDecode(raw) end)
if ok3 and type(d) == "table" then return d end
return nil
end
local d = tryLoad(SAVE_FILE) or tryLoad("shyclient_v3_saves.json") or tryLoad("shyclient_saves.json")
if d then Saves = d.s or {}; SaveOrder = d.o or {} end
end
local refreshList
hdr(pSaves, "Save Current Setup")
local ni = mkInput(pSaves, "Save Name", "Config 1")
local function doSave(name)
if name == "" then notify("Save", "Enter a name", false) return end
if not Saves[name] then table.insert(SaveOrder, name) end
Saves[name] = snap(); save(); ni.Text = ""
if refreshList then refreshList() end
notify("Save", "Saved: " .. name)
end
local br = new("Frame",{Size=UDim2.new(1,-4,0,46),BackgroundTransparency=1,Parent=pSaves})
br:SetAttribute("OwoLbl", "save quick save")
new("UIListLayout",{FillDirection=Enum.FillDirection.Horizontal,Padding=UDim.new(0,8),Parent=br})
local sb = new("TextButton",{Size=UDim2.new(0.5,-4,1,0),BackgroundColor3=Color3.new(1,1,1),Text="Save",Font=Enum.Font.GothamBold,TextColor3=ON_ACCENT,TextSize=12,BorderSizePixel=0,AutoButtonColor=false,Parent=br})
corner(sb, RM); gradient(sb, T.Accent, T.Accent2, 0)
sb.MouseButton1Click:Connect(function() playUiSoundLayered("click"); doSave((ni.Text:gsub("^%s+",""):gsub("%s+$",""))) end)
local qs = new("TextButton",{Size=UDim2.new(0.5,-4,1,0),BackgroundColor3=T.Card,BackgroundTransparency=TR.Card,Text="Quick Save",Font=Enum.Font.GothamBold,TextColor3=T.Text,TextSize=12,BorderSizePixel=0,AutoButtonColor=false,Parent=br})
corner(qs, RM); stroke(qs, 1, 0.55, T.Line); regRef(qs, "BackgroundColor3", "Card"); regRef(qs, "TextColor3", "Text"); regCard(qs)
qs.MouseButton1Click:Connect(function() playUiSoundLayered("click"); doSave("Slot " .. (#SaveOrder + 1)) end)
hdr(pSaves, "Saved Slots")
local sl = new("Frame",{Size=UDim2.new(1,-4,0,0),BackgroundTransparency=1,AutomaticSize=Enum.AutomaticSize.Y,Parent=pSaves})
new("UIListLayout",{SortOrder=Enum.SortOrder.LayoutOrder,Padding=UDim.new(0,6),Parent=sl})
refreshList = function()
for _, c in ipairs(sl:GetChildren()) do if c:IsA("Frame") or c:IsA("TextLabel") then c:Destroy() end end
if #SaveOrder == 0 then
local e = new("TextLabel",{Size=UDim2.new(1,0,0,42),BackgroundColor3=T.Card,BackgroundTransparency=TR.Card,Font=Enum.Font.Gotham,Text="No saves yet",TextColor3=T.Muted,TextSize=11,BorderSizePixel=0,Parent=sl})
corner(e, RM); stroke(e, 1, 0.55, T.Line); regRef(e, "BackgroundColor3", "Card"); regCard(e)
return
end
for i, name in ipairs(SaveOrder) do
if Saves[name] then
local row = new("Frame",{Size=UDim2.new(1,0,0,48),BackgroundColor3=T.Card,BackgroundTransparency=TR.Card,BorderSizePixel=0,LayoutOrder=i,Parent=sl})
corner(row, RM); stroke(row, 1, 0.55, T.Line); regRef(row, "BackgroundColor3", "Card"); regCard(row)
new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,16,0,0),Size=UDim2.new(1,-230,1,0),Font=Enum.Font.GothamMedium,Text=name,TextColor3=T.Text,TextSize=12,TextXAlignment=Enum.TextXAlignment.Left,TextTruncate=Enum.TextTruncate.AtEnd,ZIndex=3,Parent=row})
local function mb(t, x, bg, fg, isAccent, cb)
local b = new("TextButton",{Size=UDim2.new(0,64,0,28),Position=UDim2.new(1,x,0.5,-14),BackgroundColor3=bg,Text=t,Font=Enum.Font.GothamBold,TextColor3=fg,TextSize=11,BorderSizePixel=0,AutoButtonColor=false,ZIndex=4,Parent=row})
corner(b, 7)
if isAccent then gradient(b, T.Accent, T.Accent2, 0) else stroke(b, 1, 0.55, T.Line) end
b.MouseButton1Click:Connect(function() playUiSoundLayered("click"); cb() end)
end
mb("Load", -212, Color3.new(1,1,1), ON_ACCENT, true, function() if load(Saves[name]) then notify("Save", "Loaded: " .. name) end end)
mb("Delete", -72, T.Card, T.Bad, false, function()
Saves[name] = nil
for k, n in ipairs(SaveOrder) do if n == name then table.remove(SaveOrder, k); break end end
save(); if refreshList then refreshList() end
notify("Save", "Deleted: " .. name, false)
end)
end
end
end
refreshList()
end
-- MORE
do
hdr(pMore, "Utility")
mkB(pMore, "Reset Character", function() local c = player.Character; if c then c:BreakJoints() end; notify("Character", "Reset") end)
mkB(pMore, "Rejoin Server", function() game:GetService("TeleportService"):Teleport(game.PlaceId, player) end)
mkB(pMore, "Copy Position", function()
local hrp = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
if hrp then
local p = hrp.Position
local s = string.format("Vector3.new(%.1f, %.1f, %.1f)", p.X, p.Y, p.Z)
if setclipboard then setclipboard(s) end
notify("Position", s)
end
end)
local flinging = false
local function findPlayerByName(query)
query = tostring(query or ""):gsub("^%s+", ""):gsub("%s+$", ""):lower()
if query == "" then return nil end
local partial = nil
for _, p in ipairs(Players:GetPlayers()) do
if p ~= player then
local n, d = p.Name:lower(), p.DisplayName:lower()
if n == query or d == query then return p end
if not partial and (n:sub(1, #query) == query or d:sub(1, #query) == query) then partial = p end
end
end
if partial then return partial end
for _, p in ipairs(Players:GetPlayers()) do
if p ~= player and (p.Name:lower():find(query, 1, true) or p.DisplayName:lower():find(query, 1, true)) then return p end
end
return nil
end
local function flingPlayer(target)
if flinging then notify("Fling", "Already flinging", false) return end
local char = player.Character
local hrp = char and char:FindFirstChild("HumanoidRootPart")
local hum = char and char:FindFirstChildOfClass("Humanoid")
if not hrp or not hum then notify("Fling", "Character not ready", false) return end
local tchar = target.Character
local thrp = tchar and tchar:FindFirstChild("HumanoidRootPart")
if not thrp then notify("Fling", target.Name .. " has no character", false) return end
flinging = true
notify("Fling", "Flinging " .. target.Name)
local origCF = hrp.CFrame
local saved = {}
for _, p in ipairs(char:GetDescendants()) do
if p:IsA("BasePart") then
saved[p] = p.CustomPhysicalProperties
p.CustomPhysicalProperties = PhysicalProperties.new(100, 0.3, 0.5)
end
end
local startTime = tick()
local function finished()
local th = target.Character and target.Character:FindFirstChild("HumanoidRootPart")
local el = tick() - startTime
return el > 4 or not th or not target.Parent
or (el > 0.4 and th.AssemblyLinearVelocity.Magnitude > 300)
or not (player.Character and player.Character:FindFirstChild("HumanoidRootPart"))
end
local conn
conn = RS.Heartbeat:Connect(function()
if finished() then return end
local th = target.Character.HumanoidRootPart
local mh = player.Character.HumanoidRootPart
mh.CFrame = th.CFrame + th.AssemblyLinearVelocity * 0.1
mh.AssemblyAngularVelocity = Vector3.new(0, 1e5, 0)
mh.AssemblyLinearVelocity = Vector3.zero
end)
task.spawn(function()
while not finished() do task.wait(0.03) end
conn:Disconnect()
local h2 = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
if h2 then
for _ = 1, 10 do
h2.AssemblyAngularVelocity = Vector3.zero
h2.AssemblyLinearVelocity = Vector3.zero
h2.CFrame = origCF
task.wait()
end
for p, props in pairs(saved) do
if p and p.Parent then p.CustomPhysicalProperties = props end
end
end
flinging = false
notify("Fling", "Done: " .. target.Name)
end)
end
hdr(pMore, "Fling Player")
local flingInput = mkInput(pMore, "Player Name", "username")
local function doFling()
local target = findPlayerByName(flingInput.Text)
if not target then notify("Fling", "Player not found", false) return end
flingPlayer(target)
end
mkAccentBtn(pMore, "Fling", doFling, 44)
flingInput.FocusLost:Connect(function(enter) if enter then doFling() end end)
local hint = new("TextLabel",{Size=UDim2.new(1,-4,0,44),BackgroundColor3=T.Card,BackgroundTransparency=TR.Card,Font=Enum.Font.Gotham,
Text=" Type a name or display name (partial works). You return to your spot afterwards.",
TextColor3=T.Dim,TextSize=11,TextXAlignment=Enum.TextXAlignment.Left,TextYAlignment=Enum.TextYAlignment.Center,TextWrapped=true,BorderSizePixel=0,Parent=pMore})
hint:SetAttribute("OwoLbl", "fling hint")
corner(hint, RM); stroke(hint, 1, 0.55, T.Line); regRef(hint, "BackgroundColor3", "Card"); regRef(hint, "TextColor3", "Dim"); regCard(hint)
end
-- MISC
do
hdr(pMisc, "Widgets")
mkT(pMisc, "Edit Widgets Without Chat", false, function(s) feat.editAnywhere = s end, "EditAnywhere")
hdr(pMisc, "UI Sounds")
mkT(pMisc, "UI Sounds", true, function(s)
feat.uiSounds = s
UISounds.enabled = s
if s then task.delay(0.1, function() playUiSound("toggleOn") end) end
end, "UISounds")
mkS(pMisc, "Sound Volume", 0, 100, 90, function(v) feat.uiSoundVolume = v; UISounds.volume = v / 100 end, "UISoundVolume")
mkS(pMisc, "Sound Pitch", 0.5, 2.0, 1.4, function(v) UISounds.normalPitch = v; feat.uiSoundPitch = v; if not UISounds.mommyMode then UISounds.pitch = v end end, "UISoundPitch", true)
local soundIdBox = mkInput(pMisc, "Custom Sound ID (empty = built-in chimes)", "17582213219")
soundIdBox.Text = feat.uiSoundId or "17582213219"
soundIdBox.FocusLost:Connect(function()
local id = soundIdBox.Text:gsub("%s", "")
Fn.setUiSoundId(id)
task.delay(0.1, function() playUiSoundLayered("click") end)
notify("UI Sounds", id ~= "" and ("ID set: " .. id) or "Using built-in sounds")
end)
mkB(pMisc, "Preview Sounds", function()
playUiSoundLayered("toggleOn")
task.delay(0.35, function() playUiSoundLayered("click") end)
task.delay(0.7, function() playUiSoundLayered("notify") end)
end)
hdr(pMisc, "About")
local aboutCard = new("Frame",{Size=UDim2.new(1,-4,0,72),BackgroundColor3=T.Card,BackgroundTransparency=TR.Card,BorderSizePixel=0,Parent=pMisc})
aboutCard:SetAttribute("OwoLbl", "about made by n_e_r_v_y with love")
corner(aboutCard, RM); stroke(aboutCard, 1, 0.55, T.Line); regRef(aboutCard, "BackgroundColor3", "Card"); regCard(aboutCard)
local aboutStripe = new("Frame",{Size=UDim2.new(1,0,0,2),BackgroundColor3=Color3.new(1,1,1),BorderSizePixel=0,Parent=aboutCard})
corner(aboutStripe, RM); gradient(aboutStripe, T.Accent, T.Accent2, 0)
moonwareLogo(aboutCard, 26, UDim2.new(0.5,-13,0,7), T.Text, T.Card, TR.Card, 2, "AboutMoonwareMark")
local t2 = new("TextLabel",{BackgroundTransparency=1,Position=UDim2.new(0,0,0,36),Size=UDim2.new(1,0,0,18),Font=Enum.Font.GothamMedium,Text="Made by n_e_r_v_y with love",TextColor3=T.Accent,TextSize=12,Parent=aboutCard})
regRef(t2, "TextColor3", "Accent")
end
-- ══════════════════════════════════════════════════════════════
-- START
-- ══════════════════════════════════════════════════════════════
UISounds.volume = (feat.uiSoundVolume or 90) / 100
UISounds.normalPitch = feat.uiSoundPitch or 1.4
UISounds.mommyMode = feat.mommyMode == true
UISounds.pitch = UISounds.mommyMode and 1.0 or UISounds.normalPitch
Fn.setOpacity(0)
UI.opacity = 0
Fn.selTab("home")
Fn.refreshKb()
Fn.updateHud()
Fn.applyScreenFilters()
Fn.rebuildCrosshair()
if Fn.applyUIBackground then Fn.applyUIBackground() end
UISounds.enabled = feat.uiSounds
UISounds.volume = (feat.uiSoundVolume or 90) / 100
UISounds.normalPitch = feat.uiSoundPitch or UISounds.normalPitch or 1.4
UISounds.pitch = UISounds.mommyMode and 1.0 or UISounds.normalPitch
if feat.uiSoundId then Fn.setUiSoundId(feat.uiSoundId) end
UIS.InputBegan:Connect(function(i, gp)
if gp then return end
if i.KeyCode == Enum.KeyCode.RightShift then Fn.toggleMenu() end
end)
notify("Moonware", "Loaded. Right Shift.")
print("[Moonware] Loaded.")