Skip to content

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

yaml
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.0

Field Descriptions

FieldTypeRequiredDefaultDescription
idStringYesUnique damage type identifier
display_nameStringNoSame as idDisplay name
aliasesListNo[]Alias list for matching
allowed_eventsListNo[]Bukkit DamageCauses that can trigger this damage type
hard_lockbooleanNofalseWhether to hard-lock to specified events
stagesListYes[]Damage calculation stage list, executed in order
recoveryObjectNonullRecovery/lifesteal definition
descriptionStringNo""Description
attacker_messageStringNonullAttacker damage message (MiniMessage format)
target_messageStringNonullTarget damage message (MiniMessage format)

Built-in Damage Types

IDDisplay NamePrimary EventsDescription
physicalPhysical Damageentity_attack, entity_sweep_attackMelee physical damage
projectileProjectile DamageprojectileBow, crossbow, and other projectile damage
spellSpell DamageSkill-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

FieldTypeDefaultDescription
idString"stage"Stage identifier
kindEnumFLAT_PERCENTStage type
sourceEnumATTACKERAttribute source (ATTACKER/TARGET/CONTEXT)
modeEnumADDOperation mode (ADD/SUBTRACT)
flat_attributesList[]Flat value attribute list
percent_attributesList[]Percentage attribute list
chance_attributesList[]Chance attribute list (for crits, etc.)
multiplier_attributesList[]Multiplier attribute list
expressionString""Custom expression (CUSTOM type only)
min_resultDoublenullStage result lower bound
max_resultDoublenullStage result upper bound
min_chanceDoublenullChance lower bound
max_chanceDoublenullChance upper bound
min_multiplierDoublenullMultiplier lower bound
max_multiplierDoublenullMultiplier upper bound

FLAT_PERCENT Type

Standard flat value + percentage calculation mode.

When mode: ADD:

stage_result = flat + input × (percent / 100)
final_value = input + stage_result

When mode: SUBTRACT:

stage_result = flat + input × (percent / 100)
final_value = input - stage_result

Where 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:

VariableDescription
{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)
yaml
# Custom stage example
- id: custom_stage
  kind: CUSTOM
  source: ATTACKER
  expression: "{input} * (1 + {percent} / 100) + {flat} * {crit}"

Special Stage IDs

Stage IDDescription
crit / criticalCritical hit stage. The system automatically performs crit determination (based on chance_attributes), and the result affects subsequent calculations
defense / target_defenseDefense 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

yaml
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 bound

Lifesteal calculation formula:

base_recovery = flat + finalDamage × (percent / 100)
resistance_factor = 1 - clamp(resistance / 100, 0, 1)
actual_recovery = base_recovery × resistance_factor

Complete 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.

FieldTypeDescription
attackerLivingEntityAttacker entity
targetLivingEntityTarget entity
projectileProjectileProjectile (may be null)
causeDamageCauseBukkit damage cause
damageTypeIdStringDamage type ID
sourceDamagedoubleOriginal damage value (from the event)
baseDamagedoubleBase damage value (initial value entering stage calculation)
attackerSnapshotAttributeSnapshotAttacker attribute snapshot
targetSnapshotAttributeSnapshotTarget attribute snapshot
variablesDamageContextVariablesExtended variable table

DamageContextVariables

The extended variable table supports the following built-in keys:

KeyDescription
cause / damage_causeDamage cause
allow_criticalWhether critical hits are allowed
allow_target_dodgeWhether target dodge is allowed
calculate_target_defenseWhether to calculate target defense
trigger_mythic_on_damagedWhether to trigger MythicMobs onDamaged
mythic_skillMythicMobs skill name
mythic_powerMythicMobs skill power
damage_typeDamage 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.

Released under the GPL-3.0 License