§ How to · with Forge AI

How to make a Roblox sword fighting game (with AI)

By Sametcan Tasgiran, Founder & Developer·Published ·Updated

A Roblox sword fighting game needs five wired pieces: hit detection, combo strings, blocking, parry windows, and ragdoll on kill. Forge AI generates all five in 58 seconds — including a stamina meter and slow-motion parry feedback.

7 files · 220 lines · 58 seconds · 1 credit. Server-authoritative damage, no client trust.

Hit detection

OverlapParams sphere cast from the sword tip on swing. Server validates range, angle, and target line of sight before applying damage.

3-hit combo string

Light-light-heavy chain. Each hit increments a combo counter; heavy on the third strike does 2x damage and applies a knockback impulse.

Blocking + parry

Hold-to-block reduces incoming damage by 75%. Releasing block within a 0.2s window of an incoming hit triggers a parry — full negate + opponent stunned.

Stamina meter

Attacks and blocks consume stamina. Empty stamina disables both. Regenerates at 25/sec when not in combat. BillboardGui above the player shows current value.

Ragdoll on kill

On death, Humanoid:BreakJoints() plus a Motor6D→Socket swap creates a real ragdoll with physics. Sword drops as a separate Part the killer can pick up.

Damage numbers

Pooled BillboardGui per Humanoid spawns float-and-fade text on each hit. Color tier: white normal, yellow heavy, red parry-punish.

Files Forge AI ships for this prompt

7 files · 220 lines · 58 seconds · 1 credit

ServerScriptService/SwordCombat.lua

Damage calc, combo counter, parry window logic

92 lines

ServerScriptService/RagdollService.lua

Motor6D → Socket swap on death

38 lines

ReplicatedStorage/Remotes/SwingRemote

Client → server swing notification

instance

ReplicatedStorage/Remotes/BlockRemote

Block hold/release state

instance

StarterPlayer/StarterPlayerScripts/SwordClient.lua

Input handling, animation triggers

44 lines

StarterGui/StaminaHUD.lua

Stamina bar + combo counter

22 lines

StarterGui/DamageNumber.lua

Pooled float-and-fade text

24 lines

Sample output: ServerScriptService/SwordCombat.lua

--!strict
-- ServerScriptService/SwordCombat.lua  (Forge AI · excerpt)
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local SwingRemote = ReplicatedStorage:WaitForChild("Remotes"):WaitForChild("SwingRemote")

local DAMAGE_LIGHT, DAMAGE_HEAVY = 12, 28
local PARRY_WINDOW = 0.2
local COMBO_RESET_SEC = 1.5

local state: { [Player]: { combo: number, lastSwing: number, blocking: boolean, blockStart: number } } = {}

local function getOrInit(p: Player)
    if not state[p] then state[p] = { combo = 0, lastSwing = 0, blocking = false, blockStart = 0 } end
    return state[p]
end

SwingRemote.OnServerEvent:Connect(function(attacker: Player, targetChar: Model)
    local s = getOrInit(attacker)
    local target = targetChar and targetChar:FindFirstChildOfClass("Humanoid")
    if not target then return end
    local distance = (attacker.Character.HumanoidRootPart.Position - targetChar.HumanoidRootPart.Position).Magnitude
    if distance > 7 then return end  -- range check

    if os.clock() - s.lastSwing > COMBO_RESET_SEC then s.combo = 0 end
    s.combo += 1
    s.lastSwing = os.clock()

    local isHeavy = (s.combo % 3) == 0
    local dmg = isHeavy and DAMAGE_HEAVY or DAMAGE_LIGHT

    -- Check defender state for block/parry
    local defender = Players:GetPlayerFromCharacter(targetChar)
    local ds = defender and state[defender]
    if ds and ds.blocking then
        if os.clock() - ds.blockStart < PARRY_WINDOW then
            return  -- perfect parry: full negate (stun handled client-side)
        end
        dmg = math.floor(dmg * 0.25)  -- block reduction
    end

    target:TakeDamage(dmg)
end)

Building a Roblox sword fighting game

Sword fighting games are the most popular Roblox combat genre — and the easiest place to ship damage exploits. The two failure modes that kill sword games on launch: client-trusted damage (exploiter writes 9999) and missing range checks (exploiter swings from 50 studs away). Forge AI closes both at the server layer.

The Forge AI sword fighting prompt produces a 7-file system in 58 seconds. Every damage decision happens server-side. The client fires SwingRemote with the target UserId; the server validates distance (max 7 studs), angle (front cone), and line of sight before reading the equipped tool's damage attribute. There is no path for the client to write a damage value.

The combo string is the gameplay depth. Light-light-heavy chains feel responsive because the third hit applies extra knockback and slow-motion feedback. The combo counter increments only on confirmed damage, so missing breaks the chain. Combo state is server-stored — clients see UI updates via RemoteEvent.

Blocking and parry are the skill gate. Hold-to-block reduces damage 75% but drains stamina. The parry window — release block within 0.2 seconds of an incoming hit — negates all damage and stuns the attacker. This rewards reactive play without making blocks trivially OP. Forge sets the parry window as a top-of-file constant so you can tune for your audience (PvP-heavy games go to 0.15s; casual to 0.3s).

The ragdoll on kill is the polish that signals "this game is serious." On death, the server breaks the Humanoid joints and swaps each Motor6D for a BallSocketConstraint, creating a real physics ragdoll. The sword drops as a separate Part the killer can pick up. Together with damage numbers and stamina UI, the system reads as a finished combat game in under a minute of prompting.

See more on the Luau generator, the game builder, or browse the full blog.

Frequently asked

Can I add multiple sword types (katana, claymore, dagger)?+

Yes. Each weapon Tool has Attributes for DAMAGE, RANGE, SPEED, COMBO_PATTERN. The same SwordCombat module reads the equipped tool's attributes — no script duplication. Forge can extend with a follow-up prompt.

Does parry work in PvE against NPCs?+

Yes. NPCs are Humanoids the same as players. The parry timing window is checked against any incoming damage attempt — server-side validation, works regardless of attacker type.

How does the combo reset work?+

Combo counter resets to 0 if 1.5 seconds pass without a successful hit (configurable). Missing entirely also resets — the counter only advances on confirmed damage.

Can I add a critical hit chance?+

Yes. After the damage calc, roll math.random() against a CRIT_CHANCE constant. Crit applies a multiplier (default 1.75x) and uses a different damage number color. Forge can add this in a follow-up.

What about animations?+

SwordClient.lua loads animations from the tool's ReplicatedStorage folder by name (Swing1, Swing2, HeavySwing, Block, Parry). Forge generates the Tool with placeholder animations — replace with your own asset IDs.

Related Forge AI prompts