Description
Customize your army with incredible visual effects! Visual customization script for Roblox Medieval RTS that lets you apply special effects to your units using a stylish, easy-to-use GUI. Choose from built-in effects such as Blue Fire, Gold Sparkles, Shadow Smoke, Emerald Glow, and Royal Highlight, or explore additional effects detected in the game's ReplicatedStorage. Perfect for players who want to customize their King, Knights, and entire army with unique appearances. Features ✨ Built-in Visual Effects 🔥 Blue Fire — Surround your units with magical blue flames. ✨ Gold Sparkles — Give your army golden particle effects. 💨 Shadow Smoke — Add a mysterious purple smoke effect. 💡 Emerald Glow — Illuminate your units with a vibrant green light. 👑 Royal Highlight — Give your King or army a prestigious golden outline. 🎨 Effect Library Displays available effects in an organized scrolling list. Select and apply effects instantly. Supports ParticleEmitters, Fire, Smoke, Sparkles, Highlights, and multiple light effects. ⚔️ Unit Customization ALL UNITS: Apply your selected effect to your entire army. SELECTED: Customize only units selected in-game. KING: Apply a special effect exclusively to your King. Automatically applies your chosen effect to newly spawned units when using ALL UNITS or KING. 📱 Modern GUI Clean dark-themed interface with green accents. Draggable and collapsible window. Scrollable effect library. Simple Apply and Clear buttons. Compatible with mobile and PC interfaces. How to Use Join Roblox Medieval RTS. Execute the script. Open the Effects Studio GUI. Choose ALL UNITS, SELECTED, or KING. Select your favorite effect from the library. Press APPLY EFFECT . Use CLEAR EFFECTS whenever you want to remove your applied effects.
Script source Luau
-- [[ BloxScripts Risk Notice ]]
-- This script has not been verified by BloxScripts.fun. Deal with caution.
--
-- Stay safe:
-- • Never log in on unofficial Roblox sites or lookalike domains.
-- • Real Roblox links use roblox.com (check the .com ending).
-- • Treat fake Roblox login / "claim reward" pages as phishing.
-- [[ End BloxScripts Risk Notice ]]
-- Medieval RTS | Client Effects Studio V1
-- Visual effects customizer for Medieval RTS.
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local LocalPlayer = Players.LocalPlayer
local PlayerGui = LocalPlayer:WaitForChild("PlayerGui")
local myFolder = workspace:WaitForChild("Game"):WaitForChild("PlayerFolder"):WaitForChild(LocalPlayer.Name)
local Units = myFolder:WaitForChild("Units")
local Buildings = myFolder:FindFirstChild("Buildings")
local GUI_NAME = "MedievalClientEffectsStudio"
local EFFECT_TAG = "__ClientEffectStudio"
local oldGui = PlayerGui:FindFirstChild(GUI_NAME)
if oldGui then oldGui:Destroy() end
local BG = Color3.fromRGB(19, 25, 34)
local PANEL = Color3.fromRGB(29, 39, 51)
local ACCENT = Color3.fromRGB(88, 225, 176)
local WHITE = Color3.fromRGB(236, 245, 248)
local MUTED = Color3.fromRGB(154, 171, 188)
local function new(className, parent, props)
local instance = Instance.new(className)
for k, v in pairs(props or {}) do instance[k] = v end
instance.Parent = parent
return instance
end
local function corner(parent, radius)
return new("UICorner", parent, { CornerRadius = UDim.new(0, radius or 9) })
end
local gui = new("ScreenGui", PlayerGui, {
Name = GUI_NAME, ResetOnSpawn = false, ZIndexBehavior = Enum.ZIndexBehavior.Sibling
})
local frame = new("Frame", gui, {
Size = UDim2.fromOffset(284, 310), Position = UDim2.new(0, 14, 0.28, 0),
BackgroundColor3 = BG, BorderSizePixel = 0, Active = true, Draggable = true,
ClipsDescendants = true
})
corner(frame, 12)
new("UIStroke", frame, {Color = Color3.fromRGB(62, 82, 96), Thickness = 1})
new("TextLabel", frame, {
Text = "✦ EFFECTS STUDIO", Size = UDim2.fromOffset(212, 39),
Position = UDim2.fromOffset(13, 2), BackgroundTransparency = 1,
TextColor3 = ACCENT, TextSize = 15, Font = Enum.Font.GothamBold,
TextXAlignment = Enum.TextXAlignment.Left
})
local collapse = new("TextButton", frame, {
Text = "−", Size = UDim2.fromOffset(33, 29), Position = UDim2.fromOffset(244, 7),
BackgroundColor3 = PANEL, TextColor3 = WHITE, Font = Enum.Font.GothamBold,
TextSize = 21, BorderSizePixel = 0
})
corner(collapse, 7)
new("Frame", frame, {
Position = UDim2.fromOffset(12, 42), Size = UDim2.fromOffset(260, 1),
BorderSizePixel = 0, BackgroundColor3 = Color3.fromRGB(58, 77, 90)
})
local function button(text, x, y, width, height, color)
local b = new("TextButton", frame, {
Text = text, Size = UDim2.fromOffset(width, height),
Position = UDim2.fromOffset(x, y), BackgroundColor3 = color or PANEL,
BorderSizePixel = 0, TextColor3 = WHITE, Font = Enum.Font.GothamSemibold,
TextSize = 12, TextWrapped = true
})
corner(b, 7)
return b
end
local targetTitle = new("TextLabel", frame, {
Text = "APPLY TO", Size = UDim2.fromOffset(240, 17),
Position = UDim2.fromOffset(13, 49), BackgroundTransparency = 1,
TextColor3 = MUTED, Font = Enum.Font.GothamBold, TextSize = 10,
TextXAlignment = Enum.TextXAlignment.Left
})
local targetButtons = {
All = button("ALL UNITS", 12, 69, 83, 30),
Selected = button("SELECTED", 101, 69, 83, 30),
King = button("KING", 190, 69, 82, 30),
}
local chosenTarget = "All"
local function updateTargets()
for mode, b in pairs(targetButtons) do
b.BackgroundColor3 = mode == chosenTarget and Color3.fromRGB(33, 125, 98) or PANEL
end
end
for mode, b in pairs(targetButtons) do
b.MouseButton1Click:Connect(function()
chosenTarget = mode
updateTargets()
end)
end
updateTargets()
new("TextLabel", frame, {
Text = "EFFECT LIBRARY", Size = UDim2.fromOffset(240, 17),
Position = UDim2.fromOffset(13, 107), BackgroundTransparency = 1,
TextColor3 = MUTED, Font = Enum.Font.GothamBold, TextSize = 10,
TextXAlignment = Enum.TextXAlignment.Left
})
local list = new("ScrollingFrame", frame, {
Size = UDim2.fromOffset(260, 99), Position = UDim2.fromOffset(12, 127),
BackgroundColor3 = PANEL, BorderSizePixel = 0,
ScrollBarThickness = 3, ScrollBarImageColor3 = ACCENT,
CanvasSize = UDim2.fromOffset(0, 0), AutomaticCanvasSize = Enum.AutomaticSize.Y
})
corner(list, 8)
new("UIListLayout", list, {
SortOrder = Enum.SortOrder.LayoutOrder, Padding = UDim.new(0, 2)
})
local status = new("TextLabel", frame, {
Text = "Choose an effect, then APPLY.",
Size = UDim2.fromOffset(260, 33), Position = UDim2.fromOffset(12, 231),
BackgroundTransparency = 1, TextColor3 = MUTED,
Font = Enum.Font.Gotham, TextSize = 11, TextWrapped = true,
TextXAlignment = Enum.TextXAlignment.Left
})
local applyButton = button("APPLY EFFECT", 12, 270, 125, 30, Color3.fromRGB(30, 139, 100))
local clearButton = button("CLEAR EFFECTS", 146, 270, 126, 30, Color3.fromRGB(131, 52, 66))
local hidden = false
collapse.MouseButton1Click:Connect(function()
hidden = not hidden
frame.Size = hidden and UDim2.fromOffset(284, 43) or UDim2.fromOffset(284, 310)
collapse.Text = hidden and "+" or "−"
end)
local effectTypes = {
ParticleEmitter = true, Fire = true, Smoke = true,
Sparkles = true, PointLight = true, SpotLight = true,
SurfaceLight = true, Highlight = true
}
local entries = {
{ name = "✨ Gold Sparkles", kind = "preset", id = "gold" },
{ name = "🔥 Blue Fire", kind = "preset", id = "bluefire" },
{ name = "💨 Shadow Smoke", kind = "preset", id = "smoke" },
{ name = "💡 Emerald Glow", kind = "preset", id = "glow" },
{ name = "👑 Royal Highlight", kind = "preset", id = "royal" },
}
local found = 0
for _, d in ReplicatedStorage:GetDescendants() do
if effectTypes[d.ClassName] and found < 150 then
found += 1
table.insert(entries, {
name = "◆ " .. d.Name .. " (" .. d.ClassName .. ")",
kind = "asset", template = d
})
end
end
table.sort(entries, function(a, b)
if a.kind ~= b.kind then return a.kind == "preset" end
return a.name:lower() < b.name:lower()
end)
local selectedEntry = entries[1]
local entryButtons = {}
local function updateEntries()
for entry, b in pairs(entryButtons) do
b.BackgroundColor3 = entry == selectedEntry and Color3.fromRGB(37, 107, 86) or PANEL
b.TextColor3 = entry == selectedEntry and WHITE or MUTED
end
end
for i, entry in entries do
local b = new("TextButton", list, {
Text = " " .. entry.name,
Size = UDim2.new(1, -7, 0, 28), BorderSizePixel = 0,
BackgroundColor3 = PANEL, TextColor3 = MUTED,
Font = Enum.Font.Gotham, TextSize = 11,
TextXAlignment = Enum.TextXAlignment.Left,
LayoutOrder = i
})
b.MouseButton1Click:Connect(function()
selectedEntry = entry
updateEntries()
status.Text = "Selected: " .. entry.name
end)
entryButtons[entry] = b
end
updateEntries()
local function isUnit(model)
return model:IsA("Model") and model.Parent == Units
end
local function getTargets()
local results = {}
for _, model in Units:GetChildren() do
if isUnit(model) then
if chosenTarget == "All"
or (chosenTarget == "King" and model.Name == "King")
or (chosenTarget == "Selected" and model:FindFirstChild("SelectionPart", true)) then
table.insert(results, model)
end
end
end
return results
end
local function getAnchor(model)
local p = model:FindFirstChild("Hitbox", true)
if p and p:IsA("BasePart") then return p end
if model.PrimaryPart then return model.PrimaryPart end
return model:FindFirstChildWhichIsA("BasePart", true)
end
local function clearModel(model)
for _, obj in model:GetDescendants() do
if obj:GetAttribute(EFFECT_TAG) == true then
obj:Destroy()
end
end
end
local function buildPreset(id)
local obj
if id == "gold" then
obj = Instance.new("Sparkles")
obj.SparkleColor = Color3.fromRGB(255, 190, 50)
elseif id == "bluefire" then
obj = Instance.new("Fire")
obj.Color = Color3.fromRGB(50, 150, 255)
obj.SecondaryColor = Color3.fromRGB(55, 255, 248)
obj.Heat = 4
obj.Size = 5
elseif id == "smoke" then
obj = Instance.new("Smoke")
obj.Color = Color3.fromRGB(75, 58, 130)
obj.Opacity = 0.4
obj.RiseVelocity = 3
obj.Size = 4
elseif id == "glow" then
obj = Instance.new("PointLight")
obj.Color = Color3.fromRGB(67, 255, 172)
obj.Brightness = 1.8
obj.Range = 14
elseif id == "royal" then
obj = Instance.new("Highlight")
obj.FillColor = Color3.fromRGB(255, 196, 69)
obj.OutlineColor = Color3.fromRGB(255, 241, 193)
obj.FillTransparency = 0.72
obj.OutlineTransparency = 0
end
return obj
end
local function applyModel(model, entry)
local anchor = getAnchor(model)
if not anchor then return false end
clearModel(model)
local obj
if entry.kind == "preset" then
obj = buildPreset(entry.id)
elseif entry.template and entry.template.Parent then
local ok, cloned = pcall(function() return entry.template:Clone() end)
if ok then obj = cloned end
end
if not obj then return false end
obj:SetAttribute(EFFECT_TAG, true)
obj.Parent = obj:IsA("Highlight") and model or anchor
return true
end
-- Apply to existing targets, and optionally to units added later for All/King.
local liveEntry = nil
local liveMode = nil
applyButton.MouseButton1Click:Connect(function()
local count = 0
for _, model in getTargets() do
if applyModel(model, selectedEntry) then count += 1 end
end
liveEntry = selectedEntry
liveMode = chosenTarget
if count == 0 then
status.Text = "No matching units detected (check selection)."
else
status.Text = "Applied effect to " .. count .. " unit(s)."
end
end)
clearButton.MouseButton1Click:Connect(function()
liveEntry = nil
liveMode = nil
local count = 0
for _, model in Units:GetChildren() do
if model:IsA("Model") then
clearModel(model)
count += 1
end
end
status.Text = "Cleared effects from " .. count .. " unit(s)."
end)
local spawnConnection
spawnConnection = Units.ChildAdded:Connect(function(model)
if not liveEntry or not gui.Parent then return end
if not model:IsA("Model") then return end
if liveMode ~= "All" and not (liveMode == "King" and model.Name == "King") then return end
task.spawn(function()
local attempts = 0
while model.Parent == Units and attempts < 20 and gui.Parent do
if getAnchor(model) then
applyModel(model, liveEntry)
return
end
attempts += 1
task.wait(0.25)
end
end)
end)
gui.Destroying:Connect(function()
if spawnConnection then spawnConnection:Disconnect() end
end)
status.Text = string.format("%d replicated effect assets + 5 presets", found)
print("[EFFECTS STUDIO] Loaded", found, "effect assets")
Review the source before using it. Executions count successful copies, capped at 10 per user and network per script in 24 hours.


Your community, in one place