Skip to content

意外受伤类属性(ACCIDENTAL_DAMAGED)

概述

ACCIDENTAL_DAMAGED 在实体受到非直接攻击伤害时触发。这包括:

  • 摔落伤害
  • 溺水伤害
  • 火焰/岩浆伤害
  • 窒息伤害
  • 药水伤害(部分情况)
  • 仙人掌、甜浆果丛等环境伤害

与 ATTACK_AND_DEFENSE 的区别:

  • ATTACK_AND_DEFENSE:实体 A 攻击实体 B
  • ACCIDENTAL_DAMAGED:没有具体的攻击者(或者攻击者不重要),伤害来自环境

需要重写的方法

Groovy
@Override
void onEnable()

/**
 * @param it      抽象的「攻击者」——一个随机生成的 UUID(非真实实体)
 * @param entity  受伤者
 * @param handler 处理器
 * @return 属性是否触发
 */
@Override
boolean onAccidentalDamage(
    UUID it,
    LivingEntity entity,
    AccidentalDamageHandler handler
)
JavaScript
function onEnable(attr)

function onAccidentalDamage(attr, it, entity, handler)

关于 it 参数:it 是一个随机生成的 UUID,不代表任何真实存在的实体。它的作用是给伤害分配一个「来源标识」,让你可以在伤害分源机制中使用。对于大部分场景,你不需要直接使用它——操作伤害时用 handler.addDamage(entity, ...) 即可。

处理器能力

接口能力
DamageTrackeraddDamage, getDamage, setDamage, multiplyDamage
AttributeTrackergetRandomValue, getAttrData, trigger
MetadataTrackersetMeta, getMeta, hasMeta
BlockTracker获取造成伤害的方块信息
CancellablesetCancelled(true)

注意:DamageTracker!和 ATTACK_AND_DEFENSE 一样,可以操作伤害。但没有 MessageTracker,消息需要自己发。

示例:摔落减伤

Groovy
package scripts.attributes

import cn.org.bukkit.craneattribute.core.attribute.AttributeTypes
import cn.org.bukkit.craneattribute.core.attribute.handler.AccidentalDamageHandler
import groovy.transform.CompileStatic
import scripts.libs.GroovyAttribute
import org.bukkit.entity.LivingEntity

@CompileStatic
class FallReduction extends GroovyAttribute {

    FallReduction() {
        super(AttributeTypes.ACCIDENTAL_DAMAGED, "fall_reduction", "摔落减伤", 1, 0.0D, -1.0D)

        Utils.registerDefaultAttribute("fall_resist", "摔落抗性", 0.0D, -1.0D)
    }

    @Override
    boolean onAccidentalDamage(UUID it, LivingEntity entity, AccidentalDamageHandler handler) {
        // 获取摔落抗性面板值
        double reduction = handler.getRandomValue(entity, "摔落抗性")

        if (reduction > 0) {
            // 获取当前累计伤害
            double currentDamage = handler.getDamage(entity)

            // 计算减免后的伤害(不低于0)
            double newDamage = Math.max(0, currentDamage - reduction)

            // 设置减免后的伤害
            handler.setDamage(entity, newDamage)

            entity.sendMessage("§a摔落减伤!减免了 ${String.format("%.2f", reduction)} 点伤害,最终受到 ${String.format("%.2f", newDamage)} 点伤害")
            return true
        }
        return false
    }
}

示例:火焰免疫

完全取消火焰伤害:

Groovy
@CompileStatic
class FireImmunity extends GroovyAttribute {

    FireImmunity() {
        super(AttributeTypes.ACCIDENTAL_DAMAGED, "fire_immunity", "火焰免疫", 1, 0.0D, -1.0D)
    }

    @Override
    boolean onAccidentalDamage(UUID it, LivingEntity entity, AccidentalDamageHandler handler) {
        // 判断伤害原因(需要在 attribute.yml 中配置 trigger damage cause)
        // 或者通过 DamageCause 判断(需要 BlockTracker 接口提供的方法)
        double immunity = handler.getRandomValue(entity, "火焰免疫")

        if (immunity >= 100) {
            // 完全免疫:取消本次伤害
            handler.setCancelled(true)
            entity.setFireTicks(0) // 灭火
            entity.sendMessage("§6火焰免疫触发!")
            return true
        } else if (immunity > 0) {
            // 部分减免
            double damage = handler.getDamage(entity)
            handler.setDamage(entity, damage * (1 - immunity / 100))
            return true
        }
        return false
    }
}

注意: ACCIDENTAL_DAMAGED 有一个触发器配置 trigger damage cause(在 attribute.yml 中),可以用来限制只有特定伤害原因才触发。例如,你不想让「火焰免疫」属性在玩家摔落时也触发检测。

配置伤害原因白名单

attribute.yml 中:

YAML
trigger setting:
  ACCIDENTAL_DAMAGED:
    trigger damage cause:
      - FALL
      - FIRE
      - LAVA

如果配置了白名单,只有列表中的伤害原因才会触发 ACCIDENTAL_DAMAGED 类型的属性。

JavaScript 示例

JavaScript
var type = "ACCIDENTAL_DAMAGED"
var id = "fall_reduction"
var name = "摔落减伤"
var priority = 1
var power = 0.0
var max = -1.0

function init(attr) {
    AttributeAPI.registerDefaultAttribute("fall_resist", "摔落抗性", 0.0, -1.0)
}

function onAccidentalDamage(attr, it, entity, handler) {
    var reduction = handler.getRandomValue(entity, "摔落抗性")
    if (reduction > 0) {
        var currentDmg = handler.getDamage(entity)
        var newDmg = Math.max(0, currentDmg - reduction)
        handler.setDamage(entity, newDmg)
        entity.sendMessage("摔落减伤触发!减免 " + reduction.toFixed(2) + " 点")
        return true
    }
    return false
}

注意事项

  1. it 是随机 UUID,不代表真实实体——不要尝试用 Bukkit.getEntity(it) 获取实体
  2. 伤害减免设置后,最终伤害由所有 ACCIDENTAL_DAMAGED 属性的处理结果叠加决定
  3. 使用 handler.setCancelled(true) 可以完全取消伤害
  4. 如果要区分伤害类型(摔落/火焰/溺水等),需要在 attribute.yml 中配置 trigger damage cause
  5. 不需要对 it(UUID)操作伤害——直接对 entity 操作即可