smithery/neversight

vfx-effects

Implements visual effects including particle systems, camera effects, lighting, mesh effects, and UI animations. Use when creating combat VFX, environmental effects, feedback systems, or any visual polish.

Installation

$ npx skills add smithery/neversight --skill vfx-effects

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery/neversight · top by installs.

npx skills add smithery/neversight

Browse all from smithery/neversight

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Skill metadata

Parsed from SKILL.md frontmatter.

Allowed toolsRead, Write, Edit, Glob, Grep

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 16,702 B
  • docs SUMMARY.md 224 B

History

  1. First recorded snapshot · 0 installs

SKILL.md

Roblox Visual Effects (VFX)

When implementing VFX, use these patterns for impactful and performant effects.

Particle Effects

Anime Hit VFX

local function createHitEffect(position, direction, intensity)
    intensity = intensity or 1

    -- Impact flash
    local flash = Instance.new("Part")
    flash.Shape = Enum.PartType.Ball
    flash.Size = Vector3.new(0.1, 0.1, 0.1)
    flash.Position = position
    flash.Anchored = true
    flash.CanCollide = false
    flash.Material = Enum.Material.Neon
    flash.Color = Color3.new(1, 1, 1)
    flash.Parent = workspace.Effects

    -- Scale up and fade
    local tweenInfo = TweenInfo.new(0.15, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
    TweenService:Create(flash, tweenInfo, {
        Size = Vector3.new(3, 3, 3) * intensity,
        Transparency = 1
    }):Play()

    -- Radial lines (speedlines)
    local numLines = 8
    for i = 1, numLines do
        local angle = (i / numLines) * math.pi * 2
        local lineDir = Vector3.new(math.cos(angle), 0, math.sin(angle))

        local line = Instance.new("Part")
        line.Size = Vector3.new(0.1, 0.1, 2)
        line.CFrame = CFrame.lookAt(position, position + lineDir) * CFrame.new(0, 0, -1)
        line.Anchored = true
        line.CanCollide = false
        line.Material = Enum.Material.Neon
        line.Color = Color3.new(1, 0.9, 0.8)
        line.Parent = workspace.Effects

        TweenService:Create(line, TweenInfo.new(0.2), {
            Size = Vector3.new(0.05, 0.05, 5) * intensity,
            CFrame = line.CFrame * CFrame.new(0, 0, -3),
            Transparency = 1
        }):Play()

        Debris:AddItem(line, 0.3)
    end

    -- Screen shake
    shakeCamera(0.3, intensity * 5)

    Debris:AddItem(flash, 0.2)
end

Slash Trail

local function createSlashTrail(weapon, duration)
    local attachment0 = weapon:FindFirstChild("TrailAttachment0")
    local attachment1 = weapon:FindFirstChild("TrailAttachment1")

    if not attachment0 or not attachment1 then
        -- Create attachments at blade ends
        attachment0 = Instance.new("Attachment")
        attachment0.Name = "TrailAttachment0"
        attachment0.Position = Vector3.new(0, 0, 2)  -- Tip
        attachment0.Parent = weapon

        attachment1 = Instance.new("Attachment")
        attachment1.Name = "TrailAttachment1"
        attachment1.Position = Vector3.new(0, 0, 0)  -- Base
        attachment1.Parent = weapon
    end

    local trail = Instance.new("Trail")
    trail.Attachment0 = attachment0
    trail.Attachment1 = attachment1
    trail.Lifetime = 0.3
    trail.MinLength = 0
    trail.FaceCamera = true
    trail.Color = ColorSequence.new({
        ColorSequenceKeypoint.new(0, Color3.new(1, 1, 1)),
        ColorSequenceKeypoint.new(1, Color3.new(0.8, 0.8, 1))
    })
    trail.Transparency = NumberSequence.new({
        NumberSequenceKeypoint.new(0, 0),
        NumberSequenceKeypoint.new(0.5, 0.3),
        NumberSequenceKeypoint.new(1, 1)
    })
    trail.WidthScale = NumberSequence.new({
        NumberSequenceKeypoint.new(0, 1),
        NumberSequenceKeypoint.new(1, 0.2)
    })
    trail.Parent = weapon

    -- Disable after duration
    task.delay(duration, function()
        trail.Enabled = false
        Debris:AddItem(trail, trail.Lifetime)
    end)

    return trail
end

Aura Effect

local function createAura(character, color, intensity)
    local hrp = character:FindFirstChild("HumanoidRootPart")
    if not hrp then return end

    local attachment = Instance.new("Attachment")
    attachment.Parent = hrp

    local particles = Instance.new("ParticleEmitter")
    particles.Color = ColorSequence.new(color)
    particles.Size = NumberSequence.new({
        NumberSequenceKeypoint.new(0, 0.5),
        NumberSequenceKeypoint.new(0.5, 1),
        NumberSequenceKeypoint.new(1, 0)
    })
    particles.Transparency = NumberSequence.new({
        NumberSequenceKeypoint.new(0, 0.5),
        NumberSequenceKeypoint.new(1, 1)
    })
    particles.Lifetime = NumberRange.new(0.5, 1)
    particles.Rate = 50 * intensity
    particles.Speed = NumberRange.new(2, 4)
    particles.SpreadAngle = Vector2.new(180, 180)
    particles.Acceleration = Vector3.new(0, 5, 0)
    particles.EmissionDirection = Enum.NormalId.Top
    particles.Parent = attachment

    -- Point light for glow
    local light = Instance.new("PointLight")
    light.Color = color
    light.Brightness = intensity
    light.Range = 10
    light.Parent = hrp

    return {
        stop = function()
            particles.Enabled = false
            TweenService:Create(light, TweenInfo.new(0.5), {Brightness = 0}):Play()
            Debris:AddItem(attachment, 1)
            Debris:AddItem(light, 0.5)
        end
    }
end

Camera Effects

Screen Shake

local ShakeModule = {}
local currentShake = Vector3.new()

function ShakeModule.shake(duration, magnitude, frequency)
    frequency = frequency or 20

    local startTime = os.clock()
    local conn
    conn = RunService.RenderStepped:Connect(function()
        local elapsed = os.clock() - startTime
        if elapsed > duration then
            currentShake = Vector3.new()
            conn:Disconnect()
            return
        end

        -- Decay over time
        local decay = 1 - (elapsed / duration)
        local shake = magnitude * decay

        -- Random offset
        currentShake = Vector3.new(
            (math.random() - 0.5) * 2 * shake,
            (math.random() - 0.5) * 2 * shake,
            0
        )
    end)
end

function ShakeModule.getOffset()
    return currentShake
end

-- Apply in camera update
RunService.RenderStepped:Connect(function()
    local offset = ShakeModule.getOffset()
    camera.CFrame = camera.CFrame * CFrame.new(offset)
end)

Hit Stop (Frame Freeze)

local function hitStop(duration)
    duration = duration or 0.05

    -- Store original time scale
    local originalSpeed = 1

    -- Slow down animations
    for _, player in ipairs(Players:GetPlayers()) do
        local character = player.Character
        if character then
            local humanoid = character:FindFirstChildOfClass("Humanoid")
            if humanoid then
                local animator = humanoid:FindFirstChildOfClass("Animator")
                if animator then
                    for _, track in ipairs(animator:GetPlayingAnimationTracks()) do
                        track:AdjustSpeed(0.01)
                    end
                end
            end
        end
    end

    task.wait(duration)

    -- Restore
    for _, player in ipairs(Players:GetPlayers()) do
        local character = player.Character
        if character then
            local humanoid = character:FindFirstChildOfClass("Humanoid")
            if humanoid then
                local animator = humanoid:FindFirstChildOfClass("Animator")
                if animator then
                    for _, track in ipairs(animator:GetPlayingAnimationTracks()) do
                        track:AdjustSpeed(1)
                    end
                end
            end
        end
    end
end

Zoom Punch Effect

local function zoomPunch(intensity, duration)
    intensity = intensity or 5
    duration = duration or 0.1

    local camera = workspace.CurrentCamera
    local originalFOV = camera.FieldOfView

    -- Quick zoom in
    TweenService:Create(camera, TweenInfo.new(duration * 0.3, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {
        FieldOfView = originalFOV - intensity
    }):Play()

    task.wait(duration * 0.3)

    -- Slower return
    TweenService:Create(camera, TweenInfo.new(duration * 0.7, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {
        FieldOfView = originalFOV
    }):Play()
end

Lighting Effects

Dynamic Muzzle Flash

local function muzzleFlash(attachment)
    -- Light
    local light = Instance.new("PointLight")
    light.Color = Color3.new(1, 0.9, 0.5)
    light.Brightness = 5
    light.Range = 15
    light.Parent = attachment

    -- Flash particle
    local flash = Instance.new("ParticleEmitter")
    flash.Texture = "rbxassetid://123456789"  -- Muzzle flash texture
    flash.Size = NumberSequence.new(1.5)
    flash.Lifetime = NumberRange.new(0.05)
    flash.Rate = 0
    flash.Speed = NumberRange.new(0)
    flash.Parent = attachment

    flash:Emit(1)

    -- Fade light
    TweenService:Create(light, TweenInfo.new(0.1), {Brightness = 0}):Play()

    Debris:AddItem(light, 0.15)
    Debris:AddItem(flash, 0.1)
end

Lightning Flash

local function lightningFlash()
    local lighting = game:GetService("Lighting")
    local originalAmbient = lighting.Ambient

    -- Flash white
    lighting.Ambient = Color3.new(1, 1, 1)

    task.wait(0.05)
    lighting.Ambient = originalAmbient
    task.wait(0.1)
    lighting.Ambient = Color3.new(0.8, 0.8, 0.8)
    task.wait(0.05)
    lighting.Ambient = originalAmbient
end

Mesh & Material Effects

Dissolve Effect

local function dissolve(part, duration)
    -- Create a dissolve texture
    local surfaceGui = Instance.new("SurfaceGui")
    surfaceGui.Face = Enum.NormalId.Front
    surfaceGui.LightInfluence = 0

    local frame = Instance.new("Frame")
    frame.Size = UDim2.new(1, 0, 1, 0)
    frame.BackgroundTransparency = 1
    frame.Parent = surfaceGui

    local gradient = Instance.new("UIGradient")
    gradient.Rotation = 90
    gradient.Parent = frame

    surfaceGui.Parent = part

    -- Animate gradient offset
    local startTime = os.clock()
    local conn
    conn = RunService.RenderStepped:Connect(function()
        local elapsed = os.clock() - startTime
        local t = elapsed / duration

        if t >= 1 then
            part:Destroy()
            conn:Disconnect()
            return
        end

        gradient.Offset = Vector2.new(0, t * 2 - 1)
        part.Transparency = t
    end)
end

Outline Effect

local function addOutline(character, color, thickness)
    thickness = thickness or 0.05

    for _, part in ipairs(character:GetDescendants()) do
        if part:IsA("BasePart") and part.Name ~= "HumanoidRootPart" then
            local outline = part:Clone()
            outline.Name = "Outline"
            outline.Size = part.Size + Vector3.new(thickness, thickness, thickness)
            outline.Material = Enum.Material.SmoothPlastic
            outline.Color = color
            outline.CanCollide = false
            outline.Massless = true
            outline.Transparency = 0

            local weld = Instance.new("WeldConstraint")
            weld.Part0 = part
            weld.Part1 = outline
            weld.Parent = outline

            outline.Parent = part
        end
    end
end

UI Visual Effects

Damage Numbers

local function showDamageNumber(position, damage, isCrit)
    local billboardGui = Instance.new("BillboardGui")
    billboardGui.Size = UDim2.new(0, 100, 0, 50)
    billboardGui.StudsOffset = Vector3.new(0, 2, 0)
    billboardGui.Adornee = nil
    billboardGui.AlwaysOnTop = true

    local label = Instance.new("TextLabel")
    label.Size = UDim2.new(1, 0, 1, 0)
    label.BackgroundTransparency = 1
    label.Text = tostring(math.floor(damage))
    label.TextColor3 = isCrit and Color3.new(1, 0.8, 0) or Color3.new(1, 1, 1)
    label.TextStrokeTransparency = 0
    label.TextStrokeColor3 = Color3.new(0, 0, 0)
    label.TextScaled = true
    label.Font = Enum.Font.GothamBold
    label.Parent = billboardGui

    -- Position in world
    local part = Instance.new("Part")
    part.Anchored = true
    part.CanCollide = false
    part.Transparency = 1
    part.Size = Vector3.new(0.1, 0.1, 0.1)
    part.Position = position
    part.Parent = workspace.Effects

    billboardGui.Adornee = part
    billboardGui.Parent = part

    -- Animate: rise and fade
    local startY = position.Y
    local startTime = os.clock()

    local conn
    conn = RunService.RenderStepped:Connect(function()
        local elapsed = os.clock() - startTime
        local t = elapsed / 1

        if t >= 1 then
            part:Destroy()
            conn:Disconnect()
            return
        end

        -- Rise with easing
        local easeT = 1 - (1 - t) ^ 2
        part.Position = Vector3.new(position.X, startY + easeT * 3, position.Z)

        -- Fade out
        label.TextTransparency = t
        label.TextStrokeTransparency = t

        -- Scale pop for crits
        if isCrit and t < 0.2 then
            local scale = 1 + math.sin(t * 5 * math.pi) * 0.3
            label.TextSize = 24 * scale
        end
    end)
end

Cooldown Sweep

local function createCooldownUI(button, cooldownDuration)
    local overlay = Instance.new("Frame")
    overlay.Name = "CooldownOverlay"
    overlay.Size = UDim2.new(1, 0, 1, 0)
    overlay.BackgroundColor3 = Color3.new(0, 0, 0)
    overlay.BackgroundTransparency = 0.5
    overlay.Parent = button

    local gradient = Instance.new("UIGradient")
    gradient.Rotation = -90
    gradient.Transparency = NumberSequence.new({
        NumberSequenceKeypoint.new(0, 0),
        NumberSequenceKeypoint.new(0.5, 0),
        NumberSequenceKeypoint.new(0.501, 1),
        NumberSequenceKeypoint.new(1, 1)
    })
    gradient.Parent = overlay

    -- Animate
    local startTime = os.clock()
    local conn
    conn = RunService.RenderStepped:Connect(function()
        local elapsed = os.clock() - startTime
        local t = elapsed / cooldownDuration

        if t >= 1 then
            overlay:Destroy()
            conn:Disconnect()
            return
        end

        -- Rotate gradient to create sweep effect
        gradient.Rotation = -90 + (t * 360)
    end)
end

Advanced VFX

Beam Weapon

local function createBeam(startAttachment, endPosition, duration)
    local endPart = Instance.new("Part")
    endPart.Anchored = true
    endPart.CanCollide = false
    endPart.Transparency = 1
    endPart.Size = Vector3.new(0.1, 0.1, 0.1)
    endPart.Position = endPosition
    endPart.Parent = workspace.Effects

    local endAttachment = Instance.new("Attachment")
    endAttachment.Parent = endPart

    local beam = Instance.new("Beam")
    beam.Attachment0 = startAttachment
    beam.Attachment1 = endAttachment
    beam.Width0 = 0.5
    beam.Width1 = 0.3
    beam.FaceCamera = true
    beam.Color = ColorSequence.new(Color3.new(1, 0, 0))
    beam.Transparency = NumberSequence.new(0)
    beam.LightEmission = 1
    beam.LightInfluence = 0
    beam.TextureSpeed = 5
    beam.Parent = startAttachment

    -- Fade out
    task.delay(duration * 0.7, function()
        TweenService:Create(beam, TweenInfo.new(duration * 0.3), {
            Transparency = NumberSequence.new(1)
        }):Play()
    end)

    Debris:AddItem(endPart, duration)
    Debris:AddItem(beam, duration)

    return beam
end

Lightning Chain

local function createLightningChain(startPos, endPos, segments)
    segments = segments or 8

    local parts = {}
    local direction = endPos - startPos
    local segmentLength = direction.Magnitude / segments

    for i = 1, segments do
        local t1 = (i - 1) / segments
        local t2 = i / segments

        local p1 = startPos + direction * t1
        local p2 = startPos + direction * t2

        -- Add random offset (except for endpoints)
        if i > 1 then
            local jitter = segmentLength * 0.5
            p1 = p1 + Vector3.new(
                (math.random() - 0.5) * jitter,
                (math.random() - 0.5) * jitter,
                (math.random() - 0.5) * jitter
            )
        end

        local segment = Instance.new("Part")
        segment.Anchored = true
        segment.CanCollide = false
        segment.Material = Enum.Material.Neon
        segment.Color = Color3.new(0.7, 0.8, 1)

        local dist = (p2 - p1).Magnitude
        segment.Size = Vector3.new(0.1, 0.1, dist)
        segment.CFrame = CFrame.lookAt((p1 + p2) / 2, p2)
        segment.Parent = workspace.Effects

        table.insert(parts, segment)
    end

    -- Quick flash and fade
    task.delay(0.05, function()
        for _, part in ipairs(parts) do
            TweenService:Create(part, TweenInfo.new(0.1), {Transparency = 1}):Play()
        end
    end)

    task.delay(0.15, function()
        for _, part in ipairs(parts) do
            part:Destroy()
        end
    end)
end