Firework + Achievement VFX
ReleasedA free Roblox VFX pack built around two small replicated systems: fireworks and achievement bursts. Each effect keeps its own config, remote, client script, server replicator, and effect module, so it is easy to grab only the part you need.
Firework
The firework side is the more animated system. Each volley launches small rocket VFX from the player's position, moves them through a cubic Bezier path, adds a bit of late-flight wobble, and bursts at the target point.
1local function GetRocketPosition(rocketData, alpha: number)
2 local opposite = 1 - alpha
3 local position = rocketData.start * (opposite ^ 3)
4 + rocketData.controlOne * (3 * opposite ^ 2 * alpha)
5 + rocketData.controlTwo * (3 * opposite * alpha ^ 2)
6 + rocketData.target * (alpha ^ 3)
7
8 local wobbleAlpha = math.clamp((alpha - 0.48) / (1 - 0.48), 0, 1)
9 wobbleAlpha = wobbleAlpha * wobbleAlpha * (3 - 2 * wobbleAlpha)
10
11 local wobble = math.sin(alpha * math.pi * 2)
12 * (1 - alpha)
13 * rocketData.wobble
14 * wobbleAlpha
15
16 return position + rocketData.wobbleDirection * wobble
17end1UserInputService.InputBegan:Connect(function(input: InputObject, gpe: boolean)
2 if gpe then
3 return
4 end
5
6 if input.KeyCode == Enum.KeyCode.F and not firing then
7 firing = true
8
9 task.spawn(function()
10 while firing do
11 FireworkEvent:FireServer()
12 task.wait(0.3)
13 end
14 end)
15 end
16end)
17
18UserInputService.InputEnded:Connect(function(input: InputObject)
19 if input.KeyCode == Enum.KeyCode.F then
20 firing = false
21 end
22end)Achievement
The achievement side follows the same client/server shape, but the VFX is attached to the emitting player. The server broadcasts the player object, then each client resolves that character and emits the local particle clone on the root part.
1local function EmitOnCharacter(character: Model?, config: {})
2 local rootPart = character and character:FindFirstChild("HumanoidRootPart")
3 if not rootPart or not rootPart:IsA("BasePart") then
4 return
5 end
6
7 local template = GetVFX(config.AssetName or EFFECT_ASSET)
8 if not template then
9 warn("[AchievementSystem] Missing ReplicatedStorage.Assets.VFX." .. tostring(config.AssetName or EFFECT_ASSET))
10 return
11 end
12
13 local effect = template:Clone()
14 effect.Name = "AchievementEffect"
15 PrepareEffect(effect)
16 SetEnabled(effect, false)
17
18 if effect:IsA("Attachment") then
19 effect.Position = config.Offset
20 effect.Parent = rootPart
21 else
22 effect.Parent = rootPart
23 MoveEffect(effect, rootPart.CFrame * CFrame.new(config.Offset))
24 WeldEffect(effect, rootPart)
25 end
26
27 EmitParticles(effect, config)
28 Debris:AddItem(effect, config.Lifetime)
29end1AchievementEvent.OnServerEvent:Connect(function(player: Player)
2 local character = player.Character
3 local rootPart = character and character:FindFirstChild("HumanoidRootPart")
4 if not rootPart or not rootPart:IsA("BasePart") then
5 return
6 end
7
8 AchievementEvent:FireAllClients(player)
9end)1AchievementEvent.OnClientEvent:Connect(function(player: Player, config: {}?)
2 if not player then
3 return
4 end
5
6 AchievementEffect.PlayFromCharacter(player.Character, config)
7end)
8
9UserInputService.InputBegan:Connect(function(input: InputObject, gpe: boolean)
10 if gpe then
11 return
12 end
13
14 if input.KeyCode == Enum.KeyCode.E and not firing then
15 firing = true
16
17 task.spawn(function()
18 while firing do
19 AchievementEvent:FireServer()
20 task.wait(AchievementConfig.Cooldown)
21 end
22 end)
23 end
24end)Free to use
This system is open-source and free to grab, edit, and use in your own Roblox projects. Credits are not required, but they are always appreciated.