默认类属性(DEFAULT)
什么是 DEFAULT 类型?
DEFAULT 是最简单的属性类型——它不做任何事情。它唯一的作用就是提供一个数值,让其他属性来读取。
你可以把 DEFAULT 属性理解为「配置项」或「数据字段」。比如:
物理护甲是 DEFAULT 属性,它本身没有任何效果物理攻击(ATTACK_AND_DEFENSE 类型)在处理伤害时读取物理护甲的值来计算减免
什么时候用 DEFAULT?
简单来说:如果一个属性不需要主动触发效果,只是作为数值供其他属性读取,那就用 DEFAULT。
常见例子:
- 护甲值、穿透值、暴击率、暴击伤害——这些数值的意义由「物理攻击」这个主属性决定
- 战斗力——纯数值,由插件面板自动读取
- 你的自定义辅助数值
纯 DEFAULT 属性
先看最简单的例子——一个只提供战斗力、无任何逻辑的属性:
Groovy
package scripts.attributes
import cn.org.bukkit.craneattribute.core.attribute.AttributeTypes
import groovy.transform.CompileStatic
import scripts.libs.GroovyAttribute
@CompileStatic
class MyPowerAttribute extends GroovyAttribute {
MyPowerAttribute() {
// 类型=DEFAULT, ID, 名称, 优先级, 战斗力系数, 最大值
super(AttributeTypes.DEFAULT, "my_power", "我的战斗力", 1, 1.0D, -1.0D)
}
}你没有看错,这个属性只需要构造函数,不需要重写任何方法。它就静静地存在于属性面板中,提供战斗力数值。
属性注册后:
- 在物品 Lore 上写
我的战斗力: 100即可生效 - 实体会获得
100 * 1.0 = 100点战斗力 - 可以通过
%ca_我的战斗力%变量查询
注册 DEFAULT 子属性
更常见的用法是:在主属性(如 ATTACK_AND_DEFENSE)的构造函数中注册 DEFAULT 子属性。
为什么要注册子属性?
假设你正在写「物理攻击」属性,你需要:
物理攻击本身(ATTACK_AND_DEFENSE 类型)——负责计算伤害物理护甲(DEFAULT 类型)——防御方的减免数值物理穿透(DEFAULT 类型)——攻击方的穿透数值
后两者不需要主动触发任何效果,它们只是「物理攻击」计算过程中的参数。所以它们应该是 DEFAULT 类型。
完整示例
Groovy
package scripts.attributes
import cn.org.bukkit.craneattribute.core.attribute.AttributeTypes
import cn.org.bukkit.craneattribute.core.attribute.handler.AttackAndDefenseHandler
import groovy.transform.CompileStatic
import scripts.libs.GroovyAttribute
import scripts.libs.Utils
import org.bukkit.entity.LivingEntity
@CompileStatic
class MyPhysicalAttack extends GroovyAttribute {
MyPhysicalAttack() {
// 主属性是 ATTACK_AND_DEFENSE 类型
super(AttributeTypes.ATTACK_AND_DEFENSE, "my_attack", "我的物理攻击", 1, 1.0D, -1.0D)
// 注册子属性(DEFAULT 类型)
Utils.registerDefaultAttribute("my_armor", "我的物理护甲", 0.0D, -1.0D)
Utils.registerDefaultAttribute("my_penetration", "我的物理穿透", 0.0D, -1.0D)
}
@Override
boolean onAttackAndDefense(LivingEntity attacker, LivingEntity entity, AttackAndDefenseHandler handler) {
// 获取攻击力
double attack = handler.getRandomValue(attacker, "我的物理攻击")
// 获取穿透和护甲
double penetration = handler.getRandomValue(attacker, "我的物理穿透")
double armor = handler.getRandomValue(entity, "我的物理护甲")
// 计算:攻击 - (护甲 - 穿透),护甲可以被穿透抵消
double effectiveArmor = Math.max(0, armor - penetration)
double damage = attack - effectiveArmor
if (damage > 0) {
handler.addDamage(attacker, damage)
handler.addMessage(attacker, "§f造成 ${String.format("%.2f", damage)} 点伤害")
// 护甲被穿透则防御方看到穿透提示
if (penetration > 0 && armor > 0) {
handler.addMessage(entity, "§7被穿透 ${String.format("%.2f", penetration)} 点护甲")
}
return true
}
return false
}
}关键点:
- 主属性(
我的物理攻击)是ATTACK_AND_DEFENSE类型 —— 它负责触发 - 子属性(
我的物理护甲、我的物理穿透)是DEFAULT类型 —— 它们只提供数值 - 在
onAttackAndDefense中通过handler.getRandomValue()读取子属性的值 Utils.registerDefaultAttribute(id, name, power, max)注册子属性
JavaScript 版本
JavaScript
var type = "ATTACK_AND_DEFENSE"
var id = "my_attack"
var name = "我的物理攻击"
var priority = 1
var power = 1.0
var max = -1.0
// 在 init 函数中注册子属性
function init(attr) {
AttributeAPI.registerDefaultAttribute("my_armor", "我的物理护甲", 0.0, -1.0)
AttributeAPI.registerDefaultAttribute("my_penetration", "我的物理穿透", 0.0, -1.0)
}
function onAttackAndDefense(attr, attacker, entity, handler) {
var attack = handler.getRandomValue(attacker, "我的物理攻击")
var penetration = handler.getRandomValue(attacker, "我的物理穿透")
var armor = handler.getRandomValue(entity, "我的物理护甲")
var effectiveArmor = Math.max(0, armor - penetration)
var damage = attack - effectiveArmor
if (damage > 0) {
handler.addDamage(attacker, damage)
attacker.sendMessage("造成 " + damage.toFixed(2) + " 点伤害")
return true
}
return false
}注册 vs 不注册
你可能会问:「我直接在代码里用 handler.getRandomValue(entity, "某个名字") 读取,不注册行不行?」
不行。 必须注册后,插件才知道这个属性存在,物品上的 Lore 才能被正确解析。不注册的话,即使物品上写了 某个名字: 100,插件也不会识别它。
注册的本质是告诉插件:「有一个属性叫这个名字,请你在解析物品时注意它。」
常见错误
忘记注册子属性
Groovy
// 错误!物理护甲没注册,物品上的 "物理护甲: 50" 不会被识别
@CompileStatic
class BadAttack extends GroovyAttribute {
BadAttack() {
super(AttributeTypes.ATTACK_AND_DEFENSE, "bad", "错误示范", 1, 1.0D, -1.0D)
// 缺少: Utils.registerDefaultAttribute("armor", "物理护甲", 0.0D, -1.0D)
}
boolean onAttackAndDefense(LivingEntity attacker, LivingEntity entity, AttackAndDefenseHandler handler) {
// 读取到的永远是 0,因为插件不知道 "物理护甲" 这个属性
double armor = handler.getRandomValue(entity, "物理护甲")
return true
}
}给 DEFAULT 属性写处理方法
Groovy
// 错误!DEFAULT 类型不会调用 onAttackAndDefense,写了也白写
@CompileStatic
class BadDefault extends GroovyAttribute {
BadDefault() {
super(AttributeTypes.DEFAULT, "bad_default", "错误默认", 1, 0.0D, -1.0D)
}
@Override
boolean onAttackAndDefense(...) {
// 这段代码永远不会被执行!
return true
}
}