> For the complete documentation index, see [llms.txt](https://axiomemu.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://axiomemu.gitbook.io/docs/data/plugins/chaosmix/recipes.md).

# ChaosMix Recipes

Every chaos machine recipe - inputs, success formula, options, rewards

The recipe catalog. Every chaos machine combination lives here: which NPC hosts it, which items are accepted as sources, how success rate is computed, how much zen it costs, and what item drops on success.

## File Location

```
Data/Plugins/Items/ChaosMix/ChaosMix_Recipes.xml
```

Loaded once at GameServer startup. Hot reloadable via the ChaosMix plugin admin command.

## Schema

```xml
<ChaosMixConfig Version="1">
    <Recipes>
        <Recipe MixType="..." MixIndex="..." MixID="...">
            <Display ... Category="..." Result="..." ResultRandom="..." />
            <Requirements Level="..." />
            <ZenCost Type="..." Value="..." />
            <SuccessRate FormulaId="..." MaxRate="..." />
            <Options MixOptionId="..." CharmOptionId="..." ChaosCharmOptionId="..." />
            <Sources>
                <Source Index="..." TypeMin="..." TypeMax="..." LevelMin="..." LevelMax="..."
                        OptionMin="..." OptionMax="..." DurMin="..." DurMax="..."
                        CountMin="..." CountMax="..." SpecialFlags="..."
                        NameText="..." Group="..." />
            </Sources>
            <Rewards>
                <Reward ItemBagId="..." Weight="..." />
            </Rewards>
        </Recipe>
    </Recipes>
</ChaosMixConfig>
```

## Recipe Identity

| Attribute  | Type | Effect                                                                                                                                                                                                                                                                                                |
| ---------- | ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `MixType`  | int  | Which NPC/context hosts this recipe. See [MixType reference](/docs/data/plugins/chaosmix.md#mixtype-reference)                                                                                                                                                                                        |
| `MixIndex` | int  | 0-based slot within the `MixType` group                                                                                                                                                                                                                                                               |
| `MixID`    | int  | Mix code. Drives client-side routing (combine animation, UI prompts). For built-in mixes it also selects which reward routine produces the item on success. It does not pick the recipe, but the client must send the same value or the mix is refused. See [MixID Ranges](#recommended-mixid-ranges) |

{% hint style="warning" %}
`MixType` + `MixIndex` is what the plugin uses to look up a recipe. It is the dispatch key. `MixID` does not pick the recipe, but it is checked: if the `MixID` the client sends does not match the recipe's `MixID`, the mix is refused (the client shows "wrong combination"). Every `MixID` routes through the plugin - there are no reserved values that skip it.
{% endhint %}

## MixID Ranges

Every mix routes through the plugin first. If a recipe matches the submitted `MixType` + `MixIndex`, the plugin handles it. If no recipe matches, the server refuses the mix - there is no legacy fall-through.

The wire field for `MixID` is a single byte, so keep `MixID <= 255`. A recipe with `MixID` above 255 is refused when a player tries it (the client shows "wrong combination"), unless the recipe has its own reward bag (`<Reward ItemBagId>` greater than `0`). The refusal is logged as `recipe-MixID=... > 255 without an ItemBag reward - REFUSED`. Even with a reward bag, the client only sends the low byte (for example `300` arrives as `44`), and that byte must still match.

### Recommended MixID Ranges

* **`1..57`** - Built-in mix codes (Chaos Item, Devil Square, +Item Level, Dinorant, Fruit, Wings, Fenrir, 380 item, Harmony, Socket, Lucky Item Create `51` / Refine `52`, etc.). These are all shipped as plugin recipes. Reuse a value here only when your recipe is the built-in mix (so the matching reward routine runs on success). `51` and `52` are ordinary recipes now, safe like the rest.
* **`58..99`** - Gaps between built-in codes. Works today, but a future season update may claim these. Not recommended for new recipes.
* **`100..255`** - Recommended for new custom recipes that ship their own `<Rewards>` block. No collision with built-in codes.

{% hint style="info" %}
Custom recipes that deliver their own reward via a `<Rewards>` block (`ItemBagId > 0`) do not use `MixID` to pick the reward, but the client must still send the same `MixID`. Use `100..255` so it never collides with a built-in code. Custom recipes that instead rely on a built-in reward routine must reuse that mix's `MixID`.
{% endhint %}

### Debugging a Mix That Does Nothing

If clicking "Combine" plays the animation but nothing else happens:

1. Confirm the client and XML agree on `MixType` / `MixIndex`. That pair is the dispatch key; a mismatch means no recipe is found and the server refuses the mix.
2. Confirm the client and XML agree on `MixID`. A different `MixID` is refused and logged as `[MixIDMismatch]`.
3. Confirm the plugin loaded (check the GameServer startup log for the recipe count).
4. Check the ChaosMix log for the day (`GameServer/ChaosMix/YYYY-MM-DD.txt`). A refused mix records the account, character, and the `MixType` / `MixID` / `MixIndex` that had no matching recipe, plus a dump of the box contents.

## Display

Visual layout in the NPC dialog. Text ids resolve to client display strings, not to [Message.xml](/docs/data/message.md) notices.

Ids below `10000` come from the client's own `Text.bmd`. Ids at or above `10000` come from [GameStrings.xml](/docs/data/gamestrings.md), which is synced to the client at login - use that range to add new text without patching and reshipping the client.

| Attribute          | Effect                                                                                                                                                                                                                                           |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `NameText1/2/3`    | Title text IDs                                                                                                                                                                                                                                   |
| `DescText1-3`      | Description text IDs                                                                                                                                                                                                                             |
| `AdviceText1-3`    | Advice/hint text IDs                                                                                                                                                                                                                             |
| `Width` / `Height` | Grid cells the recipe occupies in the NPC's recipe list                                                                                                                                                                                          |
| `Category`         | Recipe Book group. Default `0` = "Other". The group name is GameStrings id `11300 + Category` (shipped: `1` Item Upgrade, `2` Wings & Capes, `3` Pets & Fenrir, `4` Potions & Stones, `5` Events & Chests, `6` Chaos Weapons, `7` Inscription)   |
| `Result`           | Item the Recipe Book shows as the output. `"Section,Index"` or `"Section,Index,Level"` (for example `"13,15"`), or `"main"` / `"main,Level"` = the main material (source 0) comes back upgraded. Empty = no result shown. No level = "any level" |
| `ResultRandom`     | `1` = the output is one of several items (for example a random wing); the shown icon is only an example. Default `0`                                                                                                                             |

`Category`, `Result` and `ResultRandom` are display only. They feed the Chaos Goblin Recipe Book window and never change what the mix accepts or gives.

## Requirements

```xml
<Requirements Level="..." />
```

| Attribute | Effect                                      |
| --------- | ------------------------------------------- |
| `Level`   | Minimum character level required to attempt |

## Cost

```xml
<ZenCost Type="A" Value="..." />
```

| Attribute | Effect                                                                                                                                                                         |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `Type`    | Cost scaling mode. `A` = flat `Value`, `B` = `Value` \* computed success rate, `C` = flat `Value`, `D` = flat `Value` (harmony cost slot; currently returns `Value` unchanged) |
| `Value`   | Zen cost input to the mode above                                                                                                                                               |

Numeric Types `1`..`4` are accepted as aliases for `A`..`D`.

## Success Rate

```xml
<SuccessRate FormulaId="..." MaxRate="100" />
```

| Attribute   | Effect                                                                                                                                                                                                                                                                                                            |
| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `FormulaId` | Formula to evaluate. Defined in [ChaosMix\_Formulas.xml](/docs/data/plugins/chaosmix/formulas.md)                                                                                                                                                                                                                 |
| `MaxRate`   | Hard ceiling on the computed success rate. If omitted, defaults to `100`, in which case the recipe inherits the referenced formula's own `MaxRate`. If set to anything other than `100`, the recipe's value wins and the formula's `MaxRate` is ignored. The final computed rate is also clamped to `100` overall |

## Options

```xml
<Options MixOptionId="..." CharmOptionId="..." ChaosCharmOptionId="..." LuckBonus="0" />
```

| Attribute            | Effect                                                                                                                                                                                                                                                                               |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `MixOptionId`        | Which source-item filter applies                                                                                                                                                                                                                                                     |
| `CharmOptionId`      | Charm policy                                                                                                                                                                                                                                                                         |
| `ChaosCharmOptionId` | Chaos charm policy                                                                                                                                                                                                                                                                   |
| `LuckBonus`          | `1` = if the Source 0 item has Luck, add `LuckChaosMixRate` (ItemOption.xml) plus `AddLuckSuccessRate2_AL*` (GameServerInfo - Common.dat) to the rate. Default `0`. Vanilla grants this only on the +10 to +15 item upgrade mixes; the shipped recipes set it there and nowhere else |

The first three refer to entries in [ChaosMix\_Options.xml](/docs/data/plugins/chaosmix/options.md).

## Sources

One or more required inputs. Each `<Source>` describes a valid range of items the chaos box must contain. Source order in the XML defines the source index; the first `<Source>` element is source 0, the second is source 1, and so on. There is no explicit `Index` attribute on `<Source>` - an `Index` attribute in the XML is ignored by the loader.

| Attribute                 | Effect                                                                                                                                                                                                                                                                  |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `TypeMin` / `TypeMax`     | Item index range, given as `section * 512 + type` (for example section 12, type 3 = 6147). Use the same value for both to require one specific item. Section and type numbers come from [Item.xml](/docs/data/item/item.md)                                             |
| `LevelMin` / `LevelMax`   | Item +level range                                                                                                                                                                                                                                                       |
| `OptionMin` / `OptionMax` | Item +option (additional damage/defense option) range                                                                                                                                                                                                                   |
| `DurMin` / `DurMax`       | Durability range for equipment; for stackable items this is checked against the stack count instead                                                                                                                                                                     |
| `CountMin` / `CountMax`   | Minimum/maximum number of matching items (or total stack count for stackables) that must be present. `CountMax` is only enforced when set to a value below `255`                                                                                                        |
| `SpecialFlags`            | Bitmask of required attributes on matching items. `0x01` = Excellent option present, `0x02` = +380 item, `0x04` = Set (Ancient) item, `0x08` = Jewel-of-Harmony-refined item, `0x10` = Socket item. Luck is handled via the formula's `LUCKOPT` token, not this bitmask |
| `NameText`                | Display override for this source in the combine window's "Items for combination" list. Text id resolved the same way as `<Display>` ids. `0` or absent = the client names the source after its `TypeMin` item                                                           |
| `Group`                   | Recipe Book display only. Sources with the same `Group` (`1`-`255`) are shown as one "One of:" ingredient that needs just one item (for example the catalysts of an inscribe recipe). Default `0` = no group. Matching ignores it                                       |

A recipe may have up to **16** `<Source>` rows. A recipe with more than 16 is not loaded at all (the GameServer log shows `has N <Source> rows (max 16) - skipped`).

### Naming a grouped source

By default the client labels a source with the real name of its `TypeMin` item. That is correct for a source that requires one specific item, and misleading for one that accepts a range: a source spanning every Manticore piece across every class shows "Manticore Helm \[BM]" (and changes as the player inserts items), so it reads as if only the Helm is accepted.

`NameText` replaces the base label:

```xml
<Source TypeMin="..." TypeMax="..." CountMin="1" CountMax="6" NameText="10500" />
<!-- GameStrings.xml: <String Id="10500" Text="Manticore Armor Part" /> -->
```

Only the base noun is replaced. Level, option, durability and count decoration still compose onto it, so the example above renders as `Manticore Armor Part 1~6 pcs`.

`NameText` also supersedes the client's built-in group labels (the fixed list that turns certain hardcoded type spans into "Any Armor", "1st Wings" and similar). A source with `NameText` set never falls through to those.

{% hint style="info" %}
This is the fix for tiered crafts built as one recipe per piece per class. Give every recipe in the tier the same `NameText` on its sources and the whole tier reads as a single clean "Any \<part>" instead of 72 recipes each naming a different concrete item.
{% endhint %}

The engine walks each slot in the chaos box and matches it against the first `<Source>` whose ranges and flags all apply; each slot is assigned to at most one source. Validation succeeds only if every `<Source>` has at least `CountMin` matching items (and no more than `CountMax` when `CountMax < 255`). If validation fails, the client sees "wrong combination".

## Rewards

```xml
<Rewards>
    <Reward ItemBagId="..." Weight="..." />
</Rewards>
```

| Attribute   | Effect                                                                                                                                                                                                                                      |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ItemBagId` | Event item bag to draw the reward from. `> 0` = the plugin creates the reward from that bag and owns delivery end-to-end. `0` = the reward is produced by the built-in reward routine for this `MixID` (used by the shipped built-in mixes) |
| `Weight`    | Weight for picking this reward when multiple `<Reward>` entries exist                                                                                                                                                                       |

Event item bags live in [EventItemBag/](/docs/data/eventitembag.md). A recipe with `ItemBagId=0` still gets a reward; the built-in reward routine for that mix produces the item on success. New custom recipes should set `ItemBagId > 0` so the reward is fully data-driven.

## Example Recipe

{% code title="ChaosMix\_Recipes.xml fragment" %}

```xml
<Recipe MixType="0" MixIndex="1" MixID="3">
    <Display NameText1="604" NameText2="0" NameText3="0"
             DescText1="606" DescText2="607" DescText3="608"
             AdviceText1="0" AdviceText2="0" AdviceText3="0"
             Width="5" Height="4" />
    <Requirements Level="10" />
    <ZenCost Type="A" Value="2000000" />
    <SuccessRate FormulaId="2" />
    <Options MixOptionId="2" CharmOptionId="1" ChaosCharmOptionId="2" />
    <Sources>
        <Source TypeMin="0" TypeMax="7167"
                LevelMin="9" LevelMax="9"
                OptionMin="0" OptionMax="255"
                DurMin="0" DurMax="255"
                CountMin="1" CountMax="1"
                SpecialFlags="1" />
        <Source TypeMin="6159" TypeMax="6159"
                LevelMin="0" LevelMax="255"
                OptionMin="0" OptionMax="255"
                DurMin="0" DurMax="255"
                CountMin="1" CountMax="1"
                SpecialFlags="0" />
    </Sources>
    <Rewards>
        <Reward ItemBagId="0" Weight="100" />
    </Rewards>
</Recipe>
```

{% endcode %}

Goblin slot 1 (`MixType=0 MixIndex=1`): combine a +9 item with a Jewel of Chaos (item 6159) for 2M zen. Success formula 2 (`50 + LUCKOPT`). The first source must be an Excellent item (`SpecialFlags=0x01`). `ItemBagId=0`, so the built-in reward routine for this mix produces the result on success.

## Important Behavior

* **Mismatched inputs are rejected, not consumed.** If the chaos box contains an item that no `<Source>` in the matched recipe accepts, the whole mix is refused before anything is charged or destroyed. The client shows "wrong combination". This covers the +380 case: putting a non-+380 item into a recipe that requires +380 (for example a +380 item plus a normal item of the same type) is rejected on the server, and the client filters those items out of the interface, so the player cannot combine them and lose the jewels. Nothing is consumed on a rejected mix.
* **The chaos box is the only source of mix inputs.** Recipes match against whatever the player placed in the chaos box, regardless of which inventory area those items came from. Items held in the extended inventory can be placed into the chaos box and used in a mix like any other inventory item.
* **Dispatch is by `MixType` + `MixIndex`.** `MixID` does not select the recipe. Two recipes may share a `MixID` (for example the two Lucky Item Refine variants) as long as their `MixIndex` differs.
* **`MixID` must still match.** The client sends a `MixID` with every mix. If it is not the found recipe's `MixID`, the mix is refused and nothing is consumed. This stops one recipe's rate and cost being used to run a different mix.

## Cross-File Dependencies

| Attribute                                            | Related in                                                        |
| ---------------------------------------------------- | ----------------------------------------------------------------- |
| `FormulaId`                                          | [ChaosMix\_Formulas.xml](/docs/data/plugins/chaosmix/formulas.md) |
| `MixOptionId`, `CharmOptionId`, `ChaosCharmOptionId` | [ChaosMix\_Options.xml](/docs/data/plugins/chaosmix/options.md)   |
| `TypeMin/Max`                                        | [Item.xml](/docs/data/item/item.md)                               |
| `ItemBagId`                                          | [EventItemBag](/docs/data/eventitembag.md)                        |

## Common Issues

* **Click "Combine": animation plays, no items consumed, no reward, no error** - The submitted `MixType` / `MixIndex` has no matching recipe, so the server refused the mix. The animation is client-side. Check the ChaosMix log for the day to see the `MixType` / `MixID` / `MixIndex` that was refused, then confirm the client and XML agree. Also possible: the plugin failed to load (check GameServer startup log), or a custom reward `ItemBagId` points at a non-existent bag
* **Recipe not found for valid-looking inputs** - `Source` ranges too narrow; verify item indices in Item.xml
* **Client shows "wrong combination" despite correct items** - `Sources` block has fewer entries than the client expects, or an input item matches no `<Source>` range and is rejected
* **Recipe succeeds with wrong reward** - `ItemBagId="0"` uses the built-in reward routine for that mix. To customize the reward, point `ItemBagId` at an entry in [EventItemBag](/docs/data/eventitembag.md) instead
* **`[MixIDMismatch] ... REFUSED` in the ChaosMix log** - client and XML disagree on `MixID`. The mix is refused. Set the recipe's `MixID` to the value the client sends (shown as `client-MixID` in the log line)
* **`> 255 without an ItemBag reward - REFUSED` in the ChaosMix log** - `MixID` above 255 does not fit the single-byte wire field. Keep `MixID <= 255`, or give the recipe its own reward bag (`ItemBagId > 0`)
* **Recipe missing after load** - more than 16 `<Source>` rows. Split it into smaller recipes
* **Editing a recipe did nothing** - reload via admin command or restart. The plugin caches parsed data
