Extensions
Combat extension (Melee → Combat System)

Combat extension (Melee System → Combat System)

A worked example of a combat / moveset extension: a package that adds a moveset to the Combat System base. Here it's Melee System (punches and kicks). Read the Extensions overview first for the shared contract. This family is the best example of optional dependencies and the primary token method for animations.

What it extends

The Combat System auto-discovers moveset data from SharedSource/Datas/Combat/ and loads attack logic from CombatController/CombatService components. A combat extension drops in its moveset data + attack handlers and (optionally) ships animations the user uploads.

Step 1 — Declare required and optional systems

Melee requires the Combat System and DamageHandler, and optionally enhances itself with the NPC System (for fighting NPCs). This is the reference example for mixing always_on: true and always_on: false:

[
  {
    "display_name": "Combat System",
    "unique_id": "144835c0-4f96-43ea-8707-8429b4f99b22",
    "always_on": true,
    "isInitiallyChecked": true
  },
  {
    "display_name": "DamageHandler",
    "unique_id": "ca59f635-993a-4741-8c81-c9f7370fbf48",
    "always_on": true,
    "isInitiallyChecked": true
  },
  {
    "display_name": "NPC System",
    "unique_id": "07473040-45dc-4afa-bb24-462e187d10ee",
    "always_on": false,
    "isInitiallyChecked": false
  }
]
  • Required systems (always_on: true) install first and can't be unchecked.
  • The optional NPC System (always_on: false, isInitiallyChecked: false) is offered as an unchecked choice — the extension works without it, but gains NPC battles if included.

The zip

Melee_System/
├─ Instructions.md
├─ metadata.json                        # name, description, version, created_by
├─ relevant_systems.json                # 2 required + 1 optional
├─ unpack_on_roblox_studio_meta.json    # manifest for the Studio export below
├─ Unpack_On_Source/
│  ├─ ReplicatedStorage/ClientSource/Client/CombatController/Components/Others/NormalAttack.lua
│  ├─ ReplicatedStorage/SharedSource/Datas/Combat/AttackMoveset.lua    # moveset data (drop-in)
│  ├─ ReplicatedStorage/SharedSource/Datas/Combat/PunchSettings.lua    # equipped move config
│  └─ ServerScriptService/ServerSource/Server/CombatService/Components/Others/NormalAttack.lua
├─ Unpack_On_Roblox_Studio/
│  └─ ReplicatedStorage/Assets/Effects/Punches/PunchEffect.rbxm        # hit VFX
└─ To_Upload_By_User/
   └─ Animations/  Left_Jab.rbxm  Right_Jab.rbxm  Left_Front_kick.rbxm  Right_Front_kick.rbxm
                   + superbullet_metadata.json

Step 2 — Drop-in files and the Studio manifest

  • AttackMoveset.lua holds the moveset data (and the animation ID placeholders — see Step 4).
  • PunchSettings.lua selects which move is equipped; users can tweak it after install:
-- Unpack_On_Source/ReplicatedStorage/SharedSource/Datas/Combat/PunchSettings.lua
EquippedPunch = "Jab",
EquippedKick  = "FrontKick",
  • Client and server NormalAttack.lua components carry the attack logic.
  • The hit VFX ships in Unpack_On_Roblox_Studio/, described by a root-level unpack_on_roblox_studio_meta.json manifest:
{
  "version": 1,
  "exports": [
    {
      "name": "PunchEffect.rbxm",
      "targetService": "ReplicatedStorage",
      "relativePath": "Assets/Effects/Punches",
      "exportType": "instance",
      "basePath": "ReplicatedStorage/Assets/Effects/Punches/PunchEffect"
    }
  ]
}

Step 4 — Animation upload (primary method)

Melee ships four animations. Unlike Fireball's fallback approach, Melee uses the primary token method for animations — each rbxassetid://… placeholder in AttackMoveset.lua is replaced in-place after upload. Multiple entries can target the same source file:

[
  {
    "file_path": "To_Upload_By_User/Animations/Left_Jab.rbxm",
    "display_name": "Left Jab",
    "source_path": "ReplicatedStorage/SharedSource/Datas/Combat/AttackMoveset.lua",
    "token": "rbxassetid://117328173810607"
  },
  {
    "file_path": "To_Upload_By_User/Animations/Right_Jab.rbxm",
    "display_name": "Right Jab",
    "source_path": "ReplicatedStorage/SharedSource/Datas/Combat/AttackMoveset.lua",
    "token": "rbxassetid://121349669167393"
  }
]

Here the token is the full rbxassetid://… string (not a bare number) because that's exactly what appears in AttackMoveset.lua. See Animations for both methods.

Extensions can advertise further extensions

Melee's own docs point users to Melee Extensions (Hook, Straight, Uppercut, Elbow, Side Kick, Roundhouse, Knee) via a bundled doc (Combat/Documentations/ADD_MORE_MELEE_ANIMATIONS_EXTENSION.md). An extension can layer on top of another extension — the dependency chain in relevant_systems.json handles it the same way.

Checklist

  • relevant_systems.json marks required systems always_on: true and enhancers always_on: false.
  • Moveset data + attack components are drop-in files under the Combat extension points.
  • unpack_on_roblox_studio_meta.json describes each Studio export in Unpack_On_Roblox_Studio/.
  • Animation token values in the upload metadata match the rbxassetid://… placeholders in AttackMoveset.lua.
  • metadata.json has name, description, and a bumped version_number.