# ChaosMix

The ChaosMix Plugin is a comprehensive server-side chaos machine system that replaces hardcoded mix logic with data-driven XML configuration. It consists of three configuration files that work together to define all chaos mix recipes, success rate calculations, and item filtering rules.

## File Locations

* `GameServer/Data/Plugins/ChaosMix/ChaosMix_Options.xml` - Item filtering and charm option presets
* `GameServer/Data/Plugins/ChaosMix/ChaosMix_Formulas.xml` - Reusable success rate calculation formulas
* `GameServer/Data/Plugins/ChaosMix/ChaosMix_Recipes.xml` - Complete mix recipes (122 recipes)

## System Architecture

The plugin loads configurations in this order:

1. **Formulas** - Parsed first since recipes reference them
2. **Options** - Mix/charm/chaos charm presets loaded
3. **Recipes** - Complete mix definitions loaded and organized by MixType

### Mix Types

Each NPC has a dedicated MixType that categorizes its available recipes:

| MixType           | Value | NPC            | Description                      |
| ----------------- | ----- | -------------- | -------------------------------- |
| GOBLIN\_NORMAL    | 0     | Chaos Goblin   | Standard upgrades                |
| GOBLIN\_CHAOSITEM | 1     | Chaos Goblin   | Chaos items (Helm, Weapon, etc.) |
| GOBLIN\_ADD380    | 2     | Chaos Goblin   | +380 Ancient items               |
| CASTLE\_SENIOR    | 3     | Castle Senior  | Castle siege items               |
| TRAINER           | 4     | Trainer        | Pet/mount training               |
| OSBOURNE          | 5     | Osbourne       | Wings                            |
| JERRIDON          | 6     | Jerridon       | Blood Castle items               |
| ELPIS             | 7     | Elpis          | Dinorant/Fenrir                  |
| CHAOS\_CARD       | 8     | Chaos Card     | Card gambling                    |
| CHERRYBLOSSOM     | 9     | Cherry Blossom | Special items                    |
| EXTRACT\_SEED     | 10    | Seed Master    | Seed extraction                  |
| SEED\_SPHERE      | 11    | Seed Sphere    | Seed spheres                     |
| ATTACH\_SOCKET    | 12    | Socket Master  | Socket attachment                |
| DETACH\_SOCKET    | 13    | Socket Master  | Socket removal                   |

## Configuration File 1: ChaosMix\_Options.xml

Defines reusable option presets for item filtering and charm behavior.

### MixOption Presets

Controls what items can be added to the chaos box for a particular recipe.

| Attribute           | Type   | Default | Description                                                                                |
| ------------------- | ------ | ------- | ------------------------------------------------------------------------------------------ |
| `Id`                | int    | -       | Unique preset ID (referenced by recipes)                                                   |
| `Char`              | char   | -       | Legacy character code (A-I) - optional, not used by plugin                                 |
| `Name`              | string | -       | Human-readable preset name                                                                 |
| `ExcludeChaosItems` | bool   | false   | When true, blocks Chaos Machine-specific items (Chaos Helm, Weapon, etc.) from being added |
| `Exclude380`        | bool   | false   | When true, blocks +380 Ancient items from being added                                      |
| `ExcludeFenrir`     | bool   | false   | When true, blocks Fenrir items from being added                                            |
| `UpgradableOnly`    | bool   | false   | When true, only allows items that can be upgraded (weapons/armor with +level)              |

{% hint style="danger" %}
**MixOption NOT ENFORCED**: While MixOption presets are loaded from XML, they are NOT currently enforced during recipe validation. The `ExcludeChaosItems`, `Exclude380`, `ExcludeFenrir`, and `UpgradableOnly` flags are stored but never checked when items are added to the chaos box. Item filtering must be done through Source requirements instead.
{% endhint %}

{% hint style="warning" %}
**Unused Attributes**: The XML config files may contain `RefiningStoneOnly`, `NoArmor`, and `NoWeapons` attributes, but these are NOT loaded or enforced by the plugin. They are ignored and have no effect.
{% endhint %}

### CharmOption Presets

Controls how Bless charms affect success rate.

| Attribute       | Type   | Default | Description                                            |
| --------------- | ------ | ------- | ------------------------------------------------------ |
| `Id`            | int    | -       | Unique preset ID                                       |
| `Char`          | char   | -       | Legacy character code - optional, not used by plugin   |
| `Name`          | string | -       | Human-readable preset name                             |
| `MaxCharms`     | int    | 10      | Maximum number of charms allowed (0 = no charms)       |
| `BonusPerCharm` | int    | 1       | Success rate bonus per charm (typically +1% per charm) |

{% hint style="danger" %}
**NOT IMPLEMENTED**: The CharmOption presets are loaded from XML but are NOT currently used in success rate calculation. The plugin does not count Jewel of Bless items or apply the BonusPerCharm rate increase. This feature is defined but not implemented in the current code.
{% endhint %}

### ChaosCharmOption Presets

Controls whether Chaos charms (special items that guarantee success) are allowed.

| Attribute        | Type   | Default | Description                                                     |
| ---------------- | ------ | ------- | --------------------------------------------------------------- |
| `Id`             | int    | -       | Unique preset ID                                                |
| `Char`           | char   | -       | Legacy character code - optional, not used by plugin            |
| `Name`           | string | -       | Human-readable preset name                                      |
| `MaxChaosCharms` | int    | 1       | Maximum chaos charms allowed (0 = not allowed, 1 = one allowed) |

{% hint style="danger" %}
**NOT IMPLEMENTED**: The ChaosCharmOption presets are loaded from XML but are NOT currently used in mix execution. The plugin does not detect or apply chaos charm guaranteed success logic. This feature is defined but not implemented in the current code.
{% endhint %}

### Preset Examples

{% tabs %}
{% tab title="Default (All Allowed)" %}

```xml
<MixOption Id="1" Char="A" Name="DEFAULT"
  ExcludeChaosItems="0" Exclude380="0" ExcludeFenrir="0"
  UpgradableOnly="0" RefiningStoneOnly="0" NoArmor="0" NoWeapons="0" />
```

Allows all item types - most permissive option.
{% endtab %}

{% tab title="Upgradable Only" %}

```xml
<MixOption Id="2" Char="E" Name="UPGRADABLE_ONLY"
  UpgradableOnly="1" />
```

Only allows weapons/armor that can have +levels. Used for item upgrade recipes.
{% endtab %}

{% tab title="Block Chaos Items" %}

```xml
<MixOption Id="5" Char="B" Name="NO_CHAOS_ITEMS"
  ExcludeChaosItems="1" Exclude380="0" ExcludeFenrir="0" />
```

Blocks Chaos Machine items from being used as ingredients.
{% endtab %}
{% endtabs %}

## Configuration File 2: ChaosMix\_Formulas.xml

Defines reusable mathematical formulas for calculating success rates using token-based expressions.

### Formula Structure

| Attribute | Type   | Default | Description                                                       |
| --------- | ------ | ------- | ----------------------------------------------------------------- |
| `Id`      | int    | -       | Unique formula ID (referenced by recipes via FormulaId)           |
| `Name`    | string | -       | Human-readable formula description                                |
| `MaxRate` | int    | 100     | Maximum success rate cap (0-100) regardless of calculation result |

### Formula Tokens

Formulas are defined as sequences of tokens that are evaluated using recursive descent parsing (respects operator precedence and parentheses).

#### Operators

| Token Op | Symbol | Description                                         |
| -------- | ------ | --------------------------------------------------- |
| `NUMBER` | -      | Literal number value (specify with Value attribute) |
| `ADD`    | +      | Addition                                            |
| `SUB`    | -      | Subtraction                                         |
| `MUL`    | \*     | Multiplication                                      |
| `DIV`    | /      | Division (safe - returns 0 if divisor is 0)         |
| `LP`     | (      | Left parenthesis                                    |
| `RP`     | )      | Right parenthesis                                   |
| `INT`    | INT()  | Convert to integer (truncate)                       |

#### Variable Tokens

These tokens reference values calculated from chaos box contents:

| Token Op       | Description                  | Calculation                                                    |
| -------------- | ---------------------------- | -------------------------------------------------------------- |
| `MAXRATE`      | Returns the MaxRate value    | Direct value from formula's MaxRate attribute                  |
| `ITEM`         | Total buy value of all items | Sum of m\_BuyMoney for all items                               |
| `WING`         | Buy value of wing items      | Sum of m\_BuyMoney for items in section 12                     |
| `EXCELLENT`    | Buy value of excellent items | Sum of m\_BuyMoney for items with excellent flags              |
| `EQUIP`        | Buy value of equipment       | Sum of m\_BuyMoney for items in sections 0-11 (weapons/armor)  |
| `SET`          | Buy value of set items       | Sum of m\_BuyMoney for set items                               |
| `LEVEL1`       | Level of first item          | m\_Level of first item in chaos box (0 if empty)               |
| `NONJEWELITEM` | Buy value excluding jewels   | Sum of m\_BuyMoney excluding Bless/Soul/Life/Creation/Guardian |
| `LUCKOPT`      | Luck option bonus            | Returns 25 if any item has luck, 0 otherwise                   |

### Common Formulas

{% tabs %}
{% tab title="Fixed Rate" %}

```xml
<!-- Formula 1: Always return MaxRate (90%) -->
<Formula Id="1" MaxRate="90">
  <Token Op="MAXRATE" />
</Formula>
```

Simple fixed rate - just returns the MaxRate value. Used when success rate doesn't depend on items.
{% endtab %}

{% tab title="Base + Luck" %}

```xml
<!-- Formula 2: 50% base + 25% if luck (max 75%) -->
<Formula Id="2" MaxRate="75">
  <Token Op="NUMBER" Value="50" />
  <Token Op="ADD" />
  <Token Op="LUCKOPT" />
</Formula>
```

Common pattern: base rate improved by luck option. LUCKOPT adds 25% if any item has luck.
{% endtab %}

{% tab title="Item Value Based" %}

```xml
<!-- Formula 9: Rate based on total item value -->
<Formula Id="9" MaxRate="100">
  <Token Op="ITEM" />
  <Token Op="DIV" />
  <Token Op="NUMBER" Value="20000" />
</Formula>
```

Higher value items = higher success rate. Total value divided by 20,000 = rate percentage.
{% endtab %}

{% tab title="Complex Wing Formula" %}

```xml
<!-- Formula 10: Wing and excellent value combined -->
<Formula Id="10" MaxRate="90">
  <Token Op="INT" />
  <Token Op="LP" />
  <Token Op="WING" />
  <Token Op="DIV" />
  <Token Op="NUMBER" Value="4000000" />
  <Token Op="RP" />
  <Token Op="ADD" />
  <Token Op="INT" />
  <Token Op="LP" />
  <Token Op="EXCELLENT" />
  <Token Op="DIV" />
  <Token Op="NUMBER" Value="40000" />
  <Token Op="RP" />
</Formula>
```

Evaluates to: INT(WING/4000000) + INT(EXCELLENT/40000). Used for wing upgrade recipes.
{% endtab %}
{% endtabs %}

## Configuration File 3: ChaosMix\_Recipes.xml

Defines complete mix recipes with all requirements, costs, and rewards. Contains 122 recipes organized by MixType.

### Recipe Structure

#### Basic Identifiers

| Attribute  | Type | Description                                                              |
| ---------- | ---- | ------------------------------------------------------------------------ |
| `MixType`  | int  | Mix type (0-13) - determines which NPC offers this recipe                |
| `MixIndex` | int  | Index within the MixType array - client uses this to identify the recipe |
| `MixID`    | int  | Legacy mix ID - used for backwards compatibility                         |

#### Display Node

Controls how the recipe appears in the client UI.

| Attribute         | Type | Description                                             |
| ----------------- | ---- | ------------------------------------------------------- |
| `NameText1/2/3`   | int  | GlobalText indices for recipe name (multi-line support) |
| `DescText1/2/3`   | int  | GlobalText indices for description                      |
| `AdviceText1/2/3` | int  | GlobalText indices for advice/tips                      |
| `Width`           | int  | Preview item width in grid (1-8)                        |
| `Height`          | int  | Preview item height in grid (1-8)                       |

#### Requirements Node

| Attribute | Type | Description                                          |
| --------- | ---- | ---------------------------------------------------- |
| `Level`   | int  | Minimum character level required to perform this mix |

#### ZenCost Node

| Attribute | Type | Description                                                                                                           |
| --------- | ---- | --------------------------------------------------------------------------------------------------------------------- |
| `Type`    | char | Zen calculation method: 'A'=flat cost, 'B'=rate\*value, 'C'=flat, 'D'=flat (intended for harmony but not implemented) |
| `Value`   | uint | Base zen cost or multiplier depending on Type                                                                         |

Zen calculation types:

* **Type A/C/D**: Flat cost - charges exactly the Value amount
* **Type B**: Rate-based - charges (successRate \* Value) zen

{% hint style="info" %}
Type D was intended for special Jewel of Harmony cost calculations but currently behaves identically to Type A/C (flat cost).
{% endhint %}

#### SuccessRate Node

| Attribute   | Type | Description                                                              |
| ----------- | ---- | ------------------------------------------------------------------------ |
| `FormulaId` | int  | Reference to a formula in ChaosMix\_Formulas.xml (0 = use inline tokens) |
| `MaxRate`   | int  | Optional override for formula's MaxRate                                  |

If FormulaId is 0, you can define inline `<Token>` nodes here instead of referencing a formula.

#### Options Node

| Attribute            | Type | Description                             |
| -------------------- | ---- | --------------------------------------- |
| `MixOptionId`        | int  | Reference to MixOption preset ID        |
| `CharmOptionId`      | int  | Reference to CharmOption preset ID      |
| `ChaosCharmOptionId` | int  | Reference to ChaosCharmOption preset ID |

#### Sources Node

Contains multiple `<Source>` elements defining required items.

| Attribute      | Type | Description                                            |
| -------------- | ---- | ------------------------------------------------------ |
| `Index`        | int  | Source slot index (0-7)                                |
| `TypeMin`      | int  | Minimum item type code (item index)                    |
| `TypeMax`      | int  | Maximum item type code (allows range matching)         |
| `LevelMin`     | int  | Minimum item level (0-255)                             |
| `LevelMax`     | int  | Maximum item level                                     |
| `OptionMin`    | int  | Minimum +option level (0-255)                          |
| `OptionMax`    | int  | Maximum +option level                                  |
| `DurMin`       | int  | Minimum durability or stack count (0-255)              |
| `DurMax`       | int  | Maximum durability or stack count                      |
| `CountMin`     | int  | Minimum item count required (supports stackable items) |
| `CountMax`     | int  | Maximum item count allowed (255 = unlimited)           |
| `SpecialFlags` | uint | Bitflags for special requirements (see below)          |

#### Special Flags

Bitflags that can be combined using OR:

| Flag                | Hex  | Description                             |
| ------------------- | ---- | --------------------------------------- |
| `CMIX_SF_EXCELLENT` | 0x01 | Item must have excellent options        |
| `CMIX_SF_ADD380`    | 0x02 | Item must be +380 Ancient               |
| `CMIX_SF_SETITEM`   | 0x04 | Item must be a set item                 |
| `CMIX_SF_HARMONY`   | 0x08 | Item must have Jewel of Harmony applied |
| `CMIX_SF_SOCKET`    | 0x10 | Item must have sockets                  |

#### Rewards Node

| Attribute   | Type | Description                                                             |
| ----------- | ---- | ----------------------------------------------------------------------- |
| `ItemBagId` | int  | Reference to EventItemBagManager item bag (0 = legacy hardcoded reward) |
| `Weight`    | int  | Weight for weighted random selection (if multiple rewards)              |

## Important Behavior

{% hint style="info" %}
**Formula Evaluation Order**: Formulas are NOT RPN (Reverse Polish Notation). They use recursive descent parsing that respects standard mathematical operator precedence (multiplication/division before addition/subtraction) and parentheses. This means you write expressions naturally: `50 + LUCKOPT`, not `50 LUCKOPT +`. The INT() operator truncates to integer, useful for preventing fractional rate increases.
{% endhint %}

{% hint style="info" %}
**Source Validation Best-Match**: When validating chaos box contents, each item is matched against source requirements in order. Once an item matches a source, it won't be matched against other sources. If you have overlapping source ranges, order matters.
{% endhint %}

{% hint style="info" %}
**Stackable Item Counting**: For stackable items (jewels, potions), the DurMin/DurMax attributes check against stack count (not durability), and multiple stacks can satisfy a single source's CountMin requirement.
{% endhint %}

{% hint style="warning" %}
**Reward System Fallback**: If `ItemBagId="0"`, the plugin calculates zen cost and success rate but lets legacy ChaosBox.cpp code handle the reward generation. This is used for recipes that have complex reward logic hardcoded in the original system.
{% endhint %}

{% hint style="info" %}
**Tax Application**: All zen costs are subject to Castle Siege chaos machine tax. The final cost is: `zenCost + (zenCost * taxRate / 100)`.
{% endhint %}

## Recipe Examples

{% tabs %}
{% tab title="Simple Upgrade" %}

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

**Explanation**:

* Requires level 10 character
* Costs 2,000,000 zen flat
* Base 50% success rate + 25% if item has luck
* Requires exactly one +9 item, one Jewel of Chaos, one Jewel of Bless, one Jewel of Soul
* Reward handled by legacy code
  {% endtab %}

{% tab title="Excellent Item Requirement" %}

```xml
<Recipe MixType="0" MixIndex="0" MixID="6">
  <Display NameText1="613" NameText2="0" NameText3="0"
    DescText1="610" DescText2="611" DescText3="0"
    Width="1" Height="1" />
  <Requirements Level="10" />
  <ZenCost Type="A" Value="3000000" />
  <SuccessRate FormulaId="1" /> <!-- MAXRATE 90% -->
  <Options MixOptionId="1" CharmOptionId="1" ChaosCharmOptionId="1" />
  <Sources>
    <Source Index="0"
      TypeMin="7190" TypeMax="7190"
      CountMin="1" CountMax="1"
      SpecialFlags="0" />
    <Source Index="1"
      TypeMin="6159" TypeMax="6159"
      CountMin="1" CountMax="1"
      SpecialFlags="0" />
  </Sources>
  <Rewards>
    <Reward ItemBagId="0" Weight="100" />
  </Rewards>
</Recipe>
```

**Explanation**:

* Fixed 90% success rate (no luck bonus)
* Requires specific items by type (7190 and 6159)
* CharmOptionId and ChaosCharmOptionId are set but currently have no effect (not implemented)
  {% endtab %}

{% tab title="Range Match with Special Flags" %}

```xml
<Recipe MixType="0" MixIndex="6" MixID="4">
  <Requirements Level="10" />
  <ZenCost Type="A" Value="4000000" />
  <SuccessRate FormulaId="2" />
  <Options MixOptionId="2" CharmOptionId="1" ChaosCharmOptionId="2" />
  <Sources>
    <Source Index="0"
      TypeMin="0" TypeMax="7167"
      LevelMin="10" LevelMax="10"
      OptionMin="0" OptionMax="255"
      CountMin="1" CountMax="1"
      SpecialFlags="1" />  <!-- 0x01 = EXCELLENT -->
  </Sources>
  <Rewards>
    <Reward ItemBagId="0" Weight="100" />
  </Rewards>
</Recipe>
```

**Explanation**:

* Source accepts any item type from 0 to 7167
* Must be exactly level +10
* Must have excellent options (SpecialFlags="1")
  {% endtab %}
  {% endtabs %}

## Common Configuration Tasks

### Adding a New Recipe

1. Decide which MixType (NPC) should offer the recipe
2. Assign a unique MixIndex within that MixType
3. Define source requirements (required items with ranges)
4. Choose or create a FormulaId for success rate
5. Set MixOptionId, CharmOptionId, ChaosCharmOptionId
6. Define zen cost and type
7. Add Display text references
8. Test in-game and verify item validation

### Creating a Custom Formula

1. Open `ChaosMix_Formulas.xml`
2. Add a new `<Formula>` with unique Id
3. Define MaxRate (hard cap on success)
4. Add Token elements in RPN order
5. Use LUCKOPT, ITEM, WING, etc. variables as needed
6. Reference the formula in recipes with `FormulaId="X"`

### Adjusting Success Rates

**Global Changes**: Edit the base number in formulas (e.g., change "50" to "60" in formula 2) **Individual Recipe**: Override MaxRate in the recipe's SuccessRate node **Luck Impact**: LUCKOPT always adds 25% when luck is present

{% hint style="warning" %}
**Charm Bonuses Not Implemented**: The CharmOption and ChaosCharmOption features are currently non-functional. To provide rate increases from charms, you must build it into your formulas manually.
{% endhint %}

### Item Type Codes

Item type codes follow the formula: `(Section * 512) + ItemIndex`

Common sections:

* 0-5: Weapons
* 6-11: Armor
* 12: Wings
* 13: Pets/Helpers
* 14: Jewels/Potions
* 15: Scrolls

Example: Jewel of Chaos = section 14, index 22 = `(14 * 512) + 22 = 7190`

## Common Issues

{% hint style="danger" %}
**Known Limitations**: The plugin has several features that are defined in XML but NOT implemented in code:

* **MixOption filtering** (ExcludeChaosItems, Exclude380, etc.) - loaded but never enforced
* **CharmOption bonuses** (BonusPerCharm) - loaded but never applied to success rate
* **ChaosCharmOption** (guaranteed success) - loaded but never checked
* **ZenType 'D'** (harmony special) - loaded but behaves identically to Type 'A' flat cost

To work around these limitations, use Source requirements for filtering and build charm bonuses into your formulas manually.
{% endhint %}

{% hint style="warning" %}
**Recipe Not Loading**: Check server log for XML parsing errors. Most common cause is invalid FormulaId reference or malformed XML.
{% endhint %}

{% hint style="warning" %}
**Wrong Items Accepted**: Source validation is order-dependent. If you have overlapping TypeMin/TypeMax ranges, the first matching source will claim the item. Use SpecialFlags to make sources more specific.
{% endhint %}

{% hint style="warning" %}
**Success Rate Too High/Low**: Remember that LUCKOPT adds 25% (not 1%), and MaxRate always caps the final result. If formula calculates 150% but MaxRate is 90, the result is 90%.
{% endhint %}

{% hint style="danger" %}
**ItemBagId=0 Requires Legacy Code**: If you set ItemBagId to 0, you MUST have corresponding hardcoded reward logic in ChaosBox.cpp. Otherwise, the mix will succeed but give no reward. Use ItemBag system for new recipes.
{% endhint %}

{% hint style="info" %}
**Client Must Match**: The client must have matching recipe data. Recipes are synced to client via GameDataSync. If the client doesn't have the recipe, it won't show in the chaos machine UI even if the server has it configured.
{% endhint %}

## Reload Command

The plugin supports runtime reloading:

```
/reload chaosmix
```

This re-reads all three XML files without restarting the server. Useful for testing configuration changes.
