Skip to content

Attribute Definitions ​

Attribute files live under attributes/*.yml, one attribute per file. An attribute file states which fields exist and what each one does, which value kinds are available, and how attribute ids and value ranges are designed. The definition you write decides how a value is identified, clamped, displayed, parsed, and used by combat or other modules

Important fields ​

FieldTypeRequiredDefaultDescription
idstringYes—Unique attribute id used by other modules
display_namestringNosame as idDisplay name and lore matching key
value_kindenumNoFLATValue style, such as FLAT, PERCENT, CHANCE, REGEN, RESOURCE, or DERIVED
target_typeenumNoGENERICTarget system, such as GENERIC, DAMAGE, RESOURCE, or VANILLA
target_idstringNo""Damage type id, resource id, or vanilla attribute id depending on target_type
mmoitems_statstringNo""MMOItems stat id mapping, used to bridge attribute reads when MMOItems is installed
default_valuedoubleNo0Default base value
min_value / max_valuedoubleNounlimitedOptional clamps applied to the aggregated final value
allow_negativebooleanNotrueWhether negative values are allowed. When false, a negative final value becomes 0
priorityintegerNo0Lore parsing priority. Higher values match earlier
lore_format_idstringNo""Linked lore format definition
lore_pattern / lore_patternsstring / list<string>No[]Regex patterns used for lore parsing
attribute_powerdoubleNo1.0Weight used when calculating total power
tagslist<string>No[]Optional attribute tags (e.g. DEBUFF). Used by the MythicMobs emaki_attribute_add_tag / emaki_attribute_clear_tag mechanics to add or clear temporary attributes in bulk. Case-insensitive
temporary_stack_modeenumNoREPLACEStack behavior when the same attribute is re-applied inside the same effect group: REPLACE (default) overwrites, STACK adds value and remaining duration. The same attribute across different groups always coexists (ADD values are summed) regardless of this setting. A skill-provided stack_mode overrides this
parent_attributebooleanNofalseWhether this definition is a parent attribute used by the attribute-points system. Parent attributes may also enter item snapshots from lore or EA attribute PDC and expand child_bonuses
child_bonusesmap<string,double>No{}Map of child attribute contributions per allocated parent point. Child targets must exist and must not be parent attributes
descriptionstring / listNo""Description text (string or list) usable in GUIs or help output

Upgrade notes: value limits now apply to the final value

Previously min_value / max_value / allow_negative only applied while parsing a single item lore line; the aggregated final value was not limited at all. Attributes such as crit chance could therefore be stacked to 150% across several pieces of equipment and really resolved as 150%

They now apply to the final value after every source has been aggregated. All 47 bundled attribute definitions declare these three fields, so every attribute is affected. The nine attributes capped at 100 are the most noticeable: physical_crit_rate, projectile_crit_rate, spell_crit_rate, block_rate, block_reduction, dodge_chance, and the three *_crit_evasion attributes

  • If you relied on out-of-range values taking effect, they are now pushed back into the declared range. Raise that attribute's max_value instead of relying on out-of-range stacking
  • The order is scaling curves → derived attributes → value limits, so derived inputs are not truncated early, while derived results are still bound by their own range
  • A single equipment contribution is not limited; only the entity's final value is. A +80 item and a -50 temporary debuff both still take part, so a debuff never stops working because an intermediate value went out of range
  • For ranged values (the 1-5 form) only the lower bound is limited and the range width is preserved. If the lower bound is raised, the whole range shifts up rather than being truncated

Parent attributes and attribute points ​

Parent attributes power the attribute-points system. When a player allocates available points into an attribute marked with parent_attribute: true, the allocated point count contributes to the parent attribute itself, and each child_bonuses entry adds extra child-attribute value per point. Player data is stored under data/parent_attributes/<UUID>.yml with available_points, reset_points, and allocations

yaml
id: strength
display_name: '<red>Strength'
value_kind: FLAT
parent_attribute: true
child_bonuses:
  physical_attack: 1.0
  projectile_attack: 0.5

Parent attributes appear in traces and final snapshots and can be read like normal numeric attributes from item lore or the ea_attribute.ea_attributes PDC. An item parent value keeps its own ID and also contributes to each child attribute ID through child_bonuses. The same parent attribute from lore and PDC is added first, then expanded. The runtime has no fixed parent or child IDs and creates no fallback parent attribute when definitions are absent; every relationship comes from the currently loaded attribute YAML. EmakiItem variables remain text placeholders only and do not automatically become EA attributes. If child_bonuses points to a missing attribute or another parent attribute, /ea lint reports the configuration issue

Value kinds ​

ValueDescription
FLATFixed additive value
PERCENTPercentage value. Lore parsing handles % suffixes
CHANCEChance-like percentage value
REGENRegeneration rate
RESOURCEResource capacity contribution
DERIVEDDerived attribute calculated from other values

Target types ​

ValueDescription
GENERICGeneral-purpose attribute
DAMAGEParticipates in a damage_types/*.yml damage pipeline
RESOURCEAffects resource maximums or recovery
VANILLASyncs to a vanilla Minecraft/Bukkit attribute. target_id uses the bare vanilla name without a generic. prefix, such as max_health, attack_speed, or scale

Example: physical attack ​

yaml
id: physical_attack
display_name: '<red>Physical Attack'
value_kind: FLAT
target_type: DAMAGE
target_id: physical
default_value: 0
min_value: 0
max_value: 999999
allow_negative: false
priority: 100
lore_format_id: default_flat
attribute_power: 1.0
description:
  - 'Increases physical damage.'

Example: crit chance ​

yaml
id: physical_crit_rate
display_name: '<yellow>Physical Crit Chance'
value_kind: CHANCE
target_type: DAMAGE
target_id: physical
default_value: 0
min_value: 0
max_value: 100
allow_negative: false
priority: 90
lore_format_id: default_percent
attribute_power: 1.0
description:
  - 'Increases the physical critical hit chance.'
  - 'The range is 0-100, where 15 means 15%.'

Example: health (resource capacity) ​

yaml
id: health
display_name: '<green>Health'
value_kind: RESOURCE
target_type: RESOURCE
target_id: health
default_value: 0
min_value: 0
max_value: 1000000
allow_negative: false
priority: 100
lore_format_id: default_resource
attribute_power: 1.0

To sync with Bukkit's vanilla maximum health instead, use target_type: VANILLA with the bare target_id: max_health (this is exactly what the bundled max_health_vanilla.yml does)

Example: movement speed ​

yaml
id: movement_speed
display_name: '<aqua>Movement Speed'
value_kind: FLAT
target_type: GENERIC
target_id: movement_speed
default_value: 0.0
min_value: -1000
max_value: 1000
allow_negative: true
priority: 51
lore_format_id: default_flat
attribute_power: 1.0

Example: mana regeneration ​

yaml
id: mana_regen
display_name: '<blue>Mana Regeneration'
value_kind: REGEN
target_type: RESOURCE
target_id: mana
default_value: 0
min_value: 0
max_value: 100
allow_negative: false
priority: 60
lore_format_id: default_regen
attribute_power: 0.8
description:
  - 'Mana restored per second.'

Ranged random values ​

Attribute supports ranged contributions. A range keeps the minimum, maximum, and the actual value rolled this time in the snapshot contribution, which is exactly what you want for random attack or random percentage gear affixes

Example:

yaml
ea_attributes:
  physical_attack: "10-20"
  physical_crit_rate: "5%-12%"

Guidelines:

  • Numeric ranges are suitable for attack, defense, and resource-capacity attributes
  • Percentage ranges are suitable for PERCENT and CHANCE attributes. Keep one consistent scale across the system; do not mix 0.15 and 15 for the same meaning
  • Debug output should inspect the min, max, and actual resolved value when a contribution comes from a range
  • New equipment systems should still prefer PDC payloads over lore-only parsing

Lore parsing ​

In lore_pattern and lore_patterns you can use these variables:

VariableExpands to
%Key% / %key%Escaped display_name
%Value% / %value%Numeric capture group ([+-]?\d+(?:\.\d+)?)(?:\s*[-~~]\s*([+-]?\d+(?:\.\d+)?))?. It contains two groups: the first is the value itself, the second is an optional range upper bound. Accepted range separators are -, ~, and the full-width ~. When only the first group matches, the lower and upper bounds are identical

Lore parsing exists to stay compatible with old or external items; do not make it the primary data source for a new equipment system. Text parsing breaks on colors, language, and formatting, players or other plugins can rewrite lore, PDC is faster and more stable than text parsing, and similar lines can be matched by mistake. For new systems, let EmakiItem, Forge, Strengthen, or Gem write explicit PDC payloads instead

Built-in lore format priority ​

Format IDPriority
default_percent100
default_regen80
default_resource60
default_flat50

Higher priority formats are matched first when several formats could match the same lore line

Value range design ​

Percentage attributes ​

Remember: this module resolves every percentage and chance value on a 0-100 scale, where 15 means 15%. The bundled attributes and config all follow that scale: physical_crit_rate declares max_value: 100.0, config.yml sets physical_crit_damage: 150.0 and block_rate / block_reduction: 100.0 under default_profile.attributes, and damage_types/physical.yml expressions are written as (%multiplier% / 100). Chance inputs are clamped to [0, 100] during resolution

yaml
# Recommended: keep one 0-100 scale
min_value: 0
max_value: 100  # 100% cap

# Not recommended: mixing in a 0-1 scale
min_value: 0
max_value: 1  # resolution treats this as 1%, not 100%

Attack and defense ​

Declare a sane cap to prevent value inflation:

yaml
# Attack
max_value: 999999

# Defense (usually should not exceed the attack cap)
max_value: 999999

# Penetration (usually should not exceed the defense cap)
max_value: 999999