> For the complete documentation index, see [llms.txt](https://enchantedmobs.superiormc.cn/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://enchantedmobs.superiormc.cn/for-enchantmentreform/configs/custom-attributes.md).

# Custom Attributes

Every `.yml` file in `plugins/EnchantmentReform/attributes` defines one persistent per-player integer attribute. Its base value and persistent modifiers are stored in the player's PDC. The final value after modifiers is passed to the configured power as `{level}`.

```yaml
name: '{lang:custom-attribute-hunger_slowdown-name}'
description: '{lang:custom-attribute-hunger_slowdown-description}'

minimum-value: 0
maximum-value: 1000
default-value: 0

skip-power-at-default-value: true
skip-power-at-zero: true

variables:
  prevention_chance: '%:{level} / 10'

powers:
  on-food-level-change:
    conditions:
      food-decreased:
        type: food_change
        compare: '<'
        value: 0
    modifiers:
      slow-hunger-loss:
        type: food
        operation: ADD
        value: 1
        random: '{level} / 1000'
```

## Fields

| Field                         | Default         | Description                                                                                                                                                             |
| ----------------------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`                        | file ID         | Display name; supports `{lang:...}`.                                                                                                                                    |
| `description`                 | none            | Optional description; supports `{lang:...}`, `{level}`, and entries from `variables`. In descriptions, `{level}` is the viewing player's current final attribute value. |
| `minimum-value`               | `0`             | Lowest value that can be stored.                                                                                                                                        |
| `maximum-value`               | integer maximum | Highest value that can be stored.                                                                                                                                       |
| `default-value`               | `0`             | Base value returned when the player has no stored PDC value.                                                                                                            |
| `skip-power-at-default-value` | `false`         | Does not add this source to power execution when its final value equals `default-value`.                                                                                |
| `skip-power-at-zero`          | `false`         | Does not add this source to power execution when its final value is zero.                                                                                               |
| `variables`                   | none            | Shared value/formula variables available to both the description and powers, using the same syntax as enchantment variables.                                            |
| `powers`                      | required        | Uses the same trigger, condition, modifier, and ability format as enchantments and custom items.                                                                        |

Base and final values outside the configured range are clamped. Modifier calculations are rounded to the nearest integer after all operations. The two skip options are independent, even when the default value is zero.

Descriptions are rendered at the player's current final value, so they update after the base value or a modifier changes. Prefix a description formula with `%:` to calculate and append a percent sign; for example, `'%:{level} / 10'` renders as `50%` at value `500`.

## Modifiers

Each modifier has a namespaced ID, a decimal amount, and one operation. Modifiers are calculated in this order:

1. `ADD_VALUE`: add the amount directly.
2. `ADD_MULTIPLIED_BASE`: add the base value multiplied by the amount.
3. `ADD_MULTIPLIED_TOTAL`: multiply the accumulated value by `1 + amount`; multiple modifiers multiply successively.

For a base value of `100`, modifiers `ADD_VALUE 20`, `ADD_MULTIPLIED_BASE 0.5`, and `ADD_MULTIPLIED_TOTAL 0.1` result in `(100 + 20 + 100 × 0.5) × 1.1 = 187`.

Command-created modifiers persist in player PDC. Temporary modifiers created by `refresh_attribute` remain runtime-only and are removed when they expire, their enchantment/custom-item source stops being active, or the ability unloads.

The bundled `hunger_slowdown` attribute uses `0..1000`. At value `500`, each normal food-level loss has approximately a 50% chance to be prevented; at `1000`, normal one-point losses are prevented. It is extracted automatically when the attributes directory is empty.

The bundled `liquid_surface_breathing_distance` attribute uses `0..64`. When the player's eyes are in water or lava and the surface of that same liquid is no farther directly above than the attribute value, air loss is prevented. The effect is driven entirely by the attribute YAML's `on-air-change` power, the `air_change` and `liquid_surface_distance` conditions, and the `air` modifier; there is no listener tied to this attribute ID. The file is extracted whenever missing without overwriting an existing file.

Code can use `AttributeManager.attributeManager` to access `getBaseValue`, final `getValue`, `setValue`, `addValue`, `resetValue`, `getModifiers`, `addModifier`, `setModifier`, and `removeModifier`.

Administrators can change an online player's value with:

```
/enchantmentreform setattribute <player> <attribute> <value>
/enchantmentreform addattribute <player> <attribute> <delta>
/enchantmentreform addattributemodifier <player> <attribute> <modifier-id> <amount> <operation>
/enchantmentreform setattributemodifier <player> <attribute> <modifier-id> <amount> <operation>
```

`setattribute` and `addattribute` change the base value. `addattributemodifier` refuses an existing modifier ID, matching vanilla modifier-add behavior. `setattributemodifier` creates or replaces that ID.

Players can use `/enchantmentreform attributegui` to view every custom attribute, including their own base value, final value, range, and active modifiers.

With PlaceholderAPI installed, `%enchantmentreform_attribute_<id>%` displays the player's current value. For example, `%enchantmentreform_attribute_hunger_slowdown%` displays `hunger_slowdown`.

The `set_attribute` and `refresh_attribute` abilities accept custom attribute IDs as well as Bukkit attributes. A custom attribute may be written as `hunger_slowdown`, `custom_attribute:hunger_slowdown`, or `enchantmentreform:hunger_slowdown`; its target must be a player. `set_attribute` changes its base value, while `refresh_attribute` applies a temporary modifier and accepts both the new operation names above and the legacy Bukkit names.
