§ How to · with Picoo
How to make a Roblox sword fighting game (with AI)
By Sametcan Tasgiran, Founder & Developer·Published ·Updated
Every Roblox sword fighting game starts with the sword: a Tool that sits in the hand, a swing that plays an animation, and damage the server decides. Ask Picoo for a sword fighting game and it applies its sword_tool recipe: a Sword in StarterPack, so every player spawns with one, with every hit checked on the server.
5 files · 139 lines · one recipe call. Set damage, reach and cooldown, or ask for a glowing element blade, in the prompt; combos, blocking and parry are a follow-up prompt.
Sword Tool in StarterPack
A Tool named Sword with a Handle, so every player spawns with one in their Backpack. The Handle does not collide and is massless, and RequiresHandle and GripPos are set, so the sword sits in the hand when equipped.
Server-side hit check
The client sends only the swing. The server checks that the player is holding the Sword, enforces a 0.5-second cooldown with its own clock, and picks the target itself: the closest living Humanoid whose HumanoidRootPart is within 8 studs.
Damage for players and NPCs
The target takes 25 damage through Humanoid:TakeDamage. Any Humanoid counts, so the same sword works in PvP and against NPCs. A player can hit the same player at most once every 0.4 seconds.
Roblox slash animation
The server adds a toolanim value that makes the default Animate script play Roblox's own slash on R6 and R15 rigs, visible to every player. If the game has removed Animate, the LocalScript plays the matching slash itself.
Hit sound and sparks
Each hit plays swordslash.wav and bursts 30 spark particles at the target, both cleaned up with Debris.
Element blades
Ask for a fire, ice, void, lightning, shadow or holy sword and the blade turns Neon in that color. The LocalScript adds a PointLight, a stream of element particles and a trail that shows during each swing, drawn on the holder's client.
Files Picoo ships for this prompt
5 files · 139 lines · one recipe call
StarterPack/Sword
The Tool. RequiresHandle is on, CanBeDropped is off, and GripPos seats the hilt in the hand.
instance
StarterPack/Sword/Handle
The blade: a 0.3 × 0.3 × 5.5 stud Metal Part with CanCollide off and Massless on, so it welds to the hand when equipped.
instance
StarterPack/Sword/SwordLocal.lua
LocalScript: on click, fires the swing to the server and plays the slash itself if the character has no Animate script.
37 lines
ServerScriptService/SwordServer.lua
Server Script: checks the swing, finds the closest Humanoid in reach, applies the damage, and plays the hit sound and sparks.
102 lines
ReplicatedStorage/Remotes/SwordSwing
RemoteEvent the client fires on each swing. It carries no target and no damage.
instance
Sample output: ServerScriptService/SwordServer.lua
--!strict
-- Generated by Picoo recipe: sword_tool
-- Server-authoritative damage: validates player holds Tool, target in range, debounce
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Debris = game:GetService("Debris")
local DAMAGE = 25
local ATTACK_RANGE = 8
local COOLDOWN = 0.5
local HIT_DEBOUNCE = 0.4
local Remotes = ReplicatedStorage:WaitForChild("Remotes")
local SwordSwing: RemoteEvent = Remotes:WaitForChild("SwordSwing") :: RemoteEvent
local lastSwing: { [number]: number } = {}
local lastHit: { [string]: number } = {}
local function findHumanoidInRange(player: Player): Humanoid?
local character = player.Character
local rootPart = character and character:FindFirstChild("HumanoidRootPart") :: BasePart?
if not rootPart then return nil end
local closestHumanoid: Humanoid? = nil
local closestDist = ATTACK_RANGE
for _, other in ipairs(workspace:GetDescendants()) do
if other:IsA("Humanoid") and other.Parent ~= character and other.Health > 0 then
local otherRoot = other.Parent:FindFirstChild("HumanoidRootPart") :: BasePart?
if otherRoot then
local d = (otherRoot.Position - rootPart.Position).Magnitude
if d <= closestDist then closestDist = d; closestHumanoid = other end
end
end
end
return closestHumanoid
end
SwordSwing.OnServerEvent:Connect(function(player: Player)
local character = player.Character
if not character then return end
local tool = character:FindFirstChildOfClass("Tool")
if not tool or tool.Name ~= "Sword" then return end
local now = tick()
if lastSwing[player.UserId] and (now - lastSwing[player.UserId]) < COOLDOWN then return end
lastSwing[player.UserId] = now
-- (excerpt) the Roblox slash animation is triggered here, then:
local target = findHumanoidInRange(player)
if not target then return end
local targetPlayer = Players:GetPlayerFromCharacter(target.Parent)
if targetPlayer then
local pairKey = player.UserId .. ":" .. targetPlayer.UserId
if lastHit[pairKey] and (now - lastHit[pairKey]) < HIT_DEBOUNCE then return end
lastHit[pairKey] = now
end
target:TakeDamage(DAMAGE)
-- (excerpt ends) then the hit sound and a 30-spark burst at the targetBuilding a Roblox sword fighting game
Sword fighting games live or die on the sword, and the sword is where hand-written code usually breaks. A Tool whose Handle collides will not weld to the hand, and a swing that trusts the client lets an exploiter hit anyone from anywhere. Picoo builds the sword from a fixed recipe, sword_tool, so both are handled the same way every time.
The Tool goes in StarterPack, so every player spawns with it. Its Handle is a 0.3 × 0.3 × 5.5 stud Metal blade with CanCollide off, Anchored off and Massless on, and the Tool has RequiresHandle on and a GripPos that seats the hilt in the hand. These are set as properties when the sword is created, before anyone equips it.
When a player clicks, the LocalScript checks its own 0.5-second cooldown and fires SwordSwing with no arguments. Everything that matters happens on the server: it confirms the player is holding the Sword, applies the same cooldown with its own clock, and searches the workspace for the closest living Humanoid whose HumanoidRootPart is within 8 studs. That Humanoid takes 25 damage, a slash sound plays, and 30 sparks burst from the target. A player can hit the same player at most once every 0.4 seconds.
The swing animation is Roblox's own Slash. The server adds a toolanim value to the Tool, which the default Animate script plays on R6 and R15 rigs; if your game has replaced Animate, the LocalScript plays the matching slash itself. Name an element (fire, ice, void, lightning, shadow or holy) and the blade turns Neon in that color, and the LocalScript adds a light, element particles and a swing trail on the holder's client.
That is the weapon. A sword fighting game adds rules around it, and each of those is a follow-up prompt: an arena, rounds with a winner, a kill leaderboard, or a combat layer with combos, blocking and parry.
See more on the Luau generator, the AI Luau script writer, the 3D model generator and the game builder, read how Picoo compares with ChatGPT, or browse the full blog.
Frequently asked
What does Picoo build when I ask for a sword fighting game?+
Its sword_tool recipe: a Sword Tool in StarterPack with its Handle and a LocalScript, a server Script, and a SwordSwing RemoteEvent. Every player spawns with the sword, so players can fight as soon as the game starts. An arena, rounds, a kill counter or a leaderboard are follow-up prompts.
Can an exploiter fake a hit or the damage?+
The client never sends a target or a damage number; SwordSwing carries only the swing. The server checks that the player holds the Sword and that 0.5 seconds have passed since their last swing, then picks the closest living Humanoid within 8 studs of the player's HumanoidRootPart and applies the damage set on the server.
Can I change damage, reach and speed, or add more swords?+
Yes. Describe the sword and Picoo passes the values to the recipe: name, damage (default 25), attack_range (8 studs), cooldown (0.5 seconds), handle color, element and swing style. 'A fire katana that does 40 damage' covers name, element and damage. A sword with a different name gets its own Tool, scripts and RemoteEvent, so several swords can sit in StarterPack side by side.
How do I add combos, blocking and parry?+
Ask for them in a follow-up prompt. This recipe gives you the sword and a single swing; a combo chain, a heavy attack, blocking, a parry window and stamina are a combat layer built on top of it.
What about animations?+
The swing uses Roblox's own Slash animation. The server adds a toolanim value to the Tool, which the default Animate script plays on R6 and R15 rigs for every player to see; if your game has removed Animate, the LocalScript plays the matching slash itself. Ask for a procedural swing and the recipe instead arcs the blade through Tool.Grip and swings the right arm in code, with no animation asset.
Related Picoo prompts
Roblox combat system
3 scripts · 1,181 lines · one recipe call. Press Play and fight with M1, E, F, Q, R and Shift.
Roblox boss fight
1 file · 199 lines · one recipe call. Five color themes and a scale setting for titan-sized bosses.
How to prevent exploits in Roblox
Example output: 4 files · 160 lines of guards. The model writes this code for your game, so the files and line counts vary.