Damage System
EmakiAttribute's damage system is based on damage type definitions and a stage-based calculation pipeline, supporting three damage categories (physical, projectile, spell) as well as custom damage types.
Damage Type Definition
Damage type files are located in the damage_types/ directory. Each YAML file defines one damage type.
YAML Format
id: physical
display_name: "物理伤害"
aliases:
- "melee"
- "physical_damage"
allowed_events:
- entity_attack
- entity_sweep_attack
hard_lock: false
stages:
- id: base_attack
kind: FLAT_PERCENT
source: ATTACKER
mode: ADD
flat_attributes:
- physical_attack
percent_attributes:
- physical_damage_bonus
- id: crit
kind: FLAT_PERCENT
source: ATTACKER
mode: ADD
chance_attributes:
- physical_crit_rate
flat_attributes:
- physical_crit_damage
multiplier_attributes: []
min_chance: 0.0
max_chance: 100.0
- id: target_defense
kind: FLAT_PERCENT
source: TARGET
mode: SUBTRACT
flat_attributes:
- physical_defense
percent_attributes: []
recovery:
source: ATTACKER
resistance_source: TARGET
flat_attributes:
- lifesteal
percent_attributes:
- percentage_lifesteal
resistance_attributes:
- lifesteal_resistance
min_result: 0.0Field Descriptions
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
id | String | Yes | — | Unique damage type identifier |
display_name | String | No | Same as id | Display name |
aliases | List | No | [] | Alias list for matching |
allowed_events | List | No | [] | Bukkit DamageCauses that can trigger this damage type |
hard_lock | boolean | No | false | Whether to hard-lock to specified events |
stages | List | Yes | [] | Damage calculation stage list, executed in order |
recovery | Object | No | null | Recovery/lifesteal definition |
description | String | No | "" | Description |
attacker_message | String | No | null | Attacker damage message (MiniMessage format) |
target_message | String | No | null | Target damage message (MiniMessage format) |
Built-in Damage Types
| ID | Display Name | Primary Events | Description |
|---|---|---|---|
physical | Physical Damage | entity_attack, entity_sweep_attack | Melee physical damage |
projectile | Projectile Damage | projectile | Bow, crossbow, and other projectile damage |
spell | Spell Damage | — | Skill-triggered spell damage, typically triggered by MythicMobs mechanics |
Stage Definition
Each damage type contains an ordered list of stages. The damage value is calculated sequentially through each stage.
Stage Fields
| Field | Type | Default | Description |
|---|---|---|---|
id | String | "stage" | Stage identifier |
kind | Enum | FLAT_PERCENT | Stage type |
source | Enum | ATTACKER | Attribute source (ATTACKER/TARGET/CONTEXT) |
mode | Enum | ADD | Operation mode (ADD/SUBTRACT) |
flat_attributes | List | [] | Flat value attribute list |
percent_attributes | List | [] | Percentage attribute list |
chance_attributes | List | [] | Chance attribute list (for crits, etc.) |
multiplier_attributes | List | [] | Multiplier attribute list |
expression | String | "" | Custom expression (CUSTOM type only) |
min_result | Double | null | Stage result lower bound |
max_result | Double | null | Stage result upper bound |
min_chance | Double | null | Chance lower bound |
max_chance | Double | null | Chance upper bound |
min_multiplier | Double | null | Multiplier lower bound |
max_multiplier | Double | null | Multiplier upper bound |
FLAT_PERCENT Type
Standard flat value + percentage calculation mode.
When mode: ADD:
stage_result = flat + input × (percent / 100)
final_value = input + stage_resultWhen mode: SUBTRACT:
stage_result = flat + input × (percent / 100)
final_value = input - stage_resultWhere flat is the sum of flat_attributes, percent is the sum of percent_attributes, and input is the output from the previous stage.
CUSTOM Type
Uses a custom expression for calculation. The following variables are available in the expression:
| Variable | Description |
|---|---|
{input} | Current input value (output from previous stage) |
{flat} | Sum of flat_attributes |
{percent} | Sum of percent_attributes |
{chance} | Sum of chance_attributes |
{multiplier} | Sum of multiplier_attributes |
{crit} | Whether critical hit (1 or 0) |
{roll} | Crit random number (0–100) |
# Custom stage example
- id: custom_stage
kind: CUSTOM
source: ATTACKER
expression: "{input} * (1 + {percent} / 100) + {flat} * {crit}"Special Stage IDs
| Stage ID | Description |
|---|---|
crit / critical | Critical hit stage. The system automatically performs crit determination (based on chance_attributes), and the result affects subsequent calculations |
defense / target_defense | Defense stage. Typically source: TARGET, mode: SUBTRACT, reads defense attributes from the target |
Critical Hit Stage
When the stage ID is crit or critical, the system performs a random determination based on chance_attributes (e.g., crit rate). On a successful crit, flat_attributes (e.g., crit damage) and multiplier_attributes take effect. The target's physical_crit_evasion and similar attributes reduce the crit probability.
Recovery/Lifesteal Definition
recovery:
source: ATTACKER # Lifesteal attribute source
resistance_source: TARGET # Lifesteal resistance attribute source
flat_attributes: # Flat lifesteal attributes
- lifesteal
percent_attributes: # Percentage lifesteal attributes
- percentage_lifesteal
resistance_attributes: # Lifesteal resistance attributes
- lifesteal_resistance
expression: "" # Optional custom expression
min_result: 0.0 # Recovery lower bound
max_result: null # Recovery upper boundLifesteal calculation formula:
base_recovery = flat + finalDamage × (percent / 100)
resistance_factor = 1 - clamp(resistance / 100, 0, 1)
actual_recovery = base_recovery × resistance_factorComplete Damage Calculation Pipeline
┌─────────────────────────────────────────────┐
│ 1. Event Trigger (EntityDamageByEntityEvent)│
│ Cancel vanilla damage event │
└──────────────────┬──────────────────────────┘
▼
┌─────────────────────────────────────────────┐
│ 2. Projectile Snapshot Mechanism │
│ On launch: write attacker attribute │
│ snapshot to Projectile │
│ On hit: read snapshot as attacker attrs │
└──────────────────┬──────────────────────────┘
▼
┌─────────────────────────────────────────────┐
│ 3. Determine Damage Type │
│ allowed_damage_causes → damage_type │
│ Fallback to default_damage_type │
└──────────────────┬──────────────────────────┘
▼
┌─────────────────────────────────────────────┐
│ 4. Dodge Determination │
│ Target dodge_chance → random roll │
│ Dodge success → skip remaining calc │
└──────────────────┬──────────────────────────┘
▼
┌─────────────────────────────────────────────┐
│ 5. Stage-based Calculation │
│ Execute stages list in order │
│ Each stage output feeds into next input │
│ ┌─ base_attack (ADD) │
│ ├─ crit (crit roll + crit damage) │
│ └─ target_defense (SUBTRACT) │
└──────────────────┬──────────────────────────┘
▼
┌─────────────────────────────────────────────┐
│ 6. Fire EmakiAttributeDamageEvent │
│ Other plugins can listen and modify │
│ finalDamage │
│ Can cancel damage │
└──────────────────┬──────────────────────────┘
▼
┌─────────────────────────────────────────────┐
│ 7. Apply Damage │
│ a. Synthetic hit dispatch (knockback │
│ + sound) │
│ b. Directly deduct target health │
│ c. Aggro update │
│ d. Attack cooldown │
│ e. Recovery/lifesteal calculation │
│ f. Damage message dispatch │
│ g. Health sync to Bukkit │
└─────────────────────────────────────────────┘Projectile Snapshot
Projectiles (arrows, etc.) snapshot the attacker's attribute state at launch time. On hit, the snapshot from launch time is used rather than current attributes, ensuring attribute changes do not affect already-launched projectiles.
DamageContext Variables
DamageContext is the core context object for damage calculation, used throughout the entire calculation pipeline.
| Field | Type | Description |
|---|---|---|
attacker | LivingEntity | Attacker entity |
target | LivingEntity | Target entity |
projectile | Projectile | Projectile (may be null) |
cause | DamageCause | Bukkit damage cause |
damageTypeId | String | Damage type ID |
sourceDamage | double | Original damage value (from the event) |
baseDamage | double | Base damage value (initial value entering stage calculation) |
attackerSnapshot | AttributeSnapshot | Attacker attribute snapshot |
targetSnapshot | AttributeSnapshot | Target attribute snapshot |
variables | DamageContextVariables | Extended variable table |
DamageContextVariables
The extended variable table supports the following built-in keys:
| Key | Description |
|---|---|
cause / damage_cause | Damage cause |
allow_critical | Whether critical hits are allowed |
allow_target_dodge | Whether target dodge is allowed |
calculate_target_defense | Whether to calculate target defense |
trigger_mythic_on_damaged | Whether to trigger MythicMobs onDamaged |
mythic_skill | MythicMobs skill name |
mythic_power | MythicMobs skill power |
damage_type | Damage type override |
DamageResult
After damage calculation completes, a DamageResult is generated containing damageTypeId, finalDamage, critical (whether it was a crit), roll (crit random number), stageValues (output values for each stage), and a full DamageContext reference.