Skip to content

表达式求值错误定位

版本要求: HNAttribute 2.4.0+

概述

从 2.4.0 版本开始,当表达式求值失败时,会输出详细的错误信息,帮助你快速定位问题所在的配置文件和位置。

错误信息格式

[WARN] 表达式求值失败 [节点ID] mode=表达式模式, script=表达式内容, error=错误原因

示例错误信息

[WARN] 表达式求值失败 [combat.stages[4].combo.formula] mode=EXPRESSION, script=damage * (1 + combo_bonus / 200), error=Unknown variable: combo_bonus

错误信息解读

节点 ID

  • 格式:combat.stages[索引].阶段ID.字段名
  • 例如:combat.stages[4].combo.formula 表示第 4 个战斗阶段的 combo 效果的 formula 字段
  • 可以根据索引和阶段 ID 快速定位到具体的配置文件

表达式模式

  • EXPRESSION: 简单表达式模式(支持数学运算、函数调用)
  • GROOVY: Groovy 脚本模式(支持完整的 Groovy 语法)

表达式内容

  • 显示实际的表达式字符串
  • 可以直接看到是哪个表达式出了问题

错误原因

  • 显示具体的错误信息
  • 常见错误:
    • Unknown variable: xxx - 变量未定义
    • Syntax error - 语法错误
    • Division by zero - 除零错误
    • Type mismatch - 类型不匹配

常见问题排查

问题 1:变量未定义

错误信息:

[WARN] 表达式求值失败 [combat.stages[4].damage_bonus.formula] mode=EXPRESSION, script=damage * (1 + damage_amplify / 250), error=Unknown variable: damage_amplify

原因: 表达式中使用了 damage_amplify 变量,但该属性未在 attributes/combat.yml 中定义。

解决方案:attributes/combat.yml 中添加该属性定义:

yaml
damage_amplify:
  display: "&c增伤率"
  names:
    - "增伤率"
    - "伤害增幅"
  read-pattern: default
  default: 0.0
  min: 0.0
  max: 300.0

问题 2:语法错误

错误信息:

[WARN] 表达式求值失败 [combat.stages[2].hit.formula] mode=EXPRESSION, script=accuracy - victim_dodge), error=Syntax error: unexpected token ')'

原因: 表达式中括号不匹配,多了一个右括号。

解决方案: 修正表达式:

yaml
formula: "accuracy - victim_dodge"

问题 3:除零错误

错误信息:

[WARN] 表达式求值失败 [combat.stages[5].reduction.formula] mode=EXPRESSION, script=damage / defense, error=Division by zero

原因:defense 为 0 时会触发除零错误。

解决方案: 使用 max() 函数避免除零:

yaml
formula: "damage / max(1, defense)"

问题 4:类型不匹配

错误信息:

[WARN] 表达式求值失败 [combat.stages[3].condition] mode=EXPRESSION, script=attacker.player, error=Type mismatch: expected number, got boolean

原因: 条件表达式应该返回数值(> 0 为真),但返回了布尔值。

解决方案: 使用三元运算符或 IF 函数:

yaml
condition: "attacker_player > 0 ? 1 : 0"
# 或
condition: "IF(attacker_player > 0, 1, 0)"

定位配置文件

根据节点 ID 定位配置文件:

战斗管线 stage

  • 节点 ID:通常是 pipeline.validate.<stageId>pipeline.stage.<stageId>
  • 配置文件:pipelines/<stageId>.yml

示例:

  • 错误:pipeline.validate.damage
  • 可能的文件:pipelines/damage.yml

属性定义

  • 节点 ID:attributes.<属性ID>.字段名
  • 配置文件:attributes/<分类>.yml

示例:

  • 错误:attributes.damage_amplify.formula
  • 可能的文件:attributes/combat.yml

Buff 定义

  • 节点 ID:buffs.<buff_key>.字段名
  • 配置文件:buffs/<分类>.yml

示例:

  • 错误:buffs.speed_boost.condition
  • 可能的文件:buffs/default.yml

周期效果定义

  • 节点 ID:periodic.<effect_key>.字段名
  • 配置文件:periodic/<分类>.yml

示例:

  • 错误:periodic.bleed.tick_condition
  • 可能的文件:periodic/dot-demo.yml

调试技巧

1. 使用简单表达式测试

先用简单的常量测试,确认配置格式正确:

yaml
formula: "100"  # 先用常量测试

2. 逐步添加变量

一次添加一个变量,确认每个变量都可用:

yaml
formula: "damage"  # 先测试 damage
formula: "damage * 2"  # 再测试运算
formula: "damage * (1 + damage_amplify / 100)"  # 最后添加复杂逻辑

3. 检查变量名

确保变量名与属性 ID 完全一致(区分大小写、下划线):

  • damage_amplify
  • damageAmplify
  • damage-amplify

4. 使用 max/min 函数防御性编程

避免除零、负数等异常情况:

yaml
formula: "damage / max(1, defense)"  # 防止除零
formula: "max(0, damage - reduction)"  # 防止负数

5. 查看完整日志

在服务器启动时查看完整的配置加载日志,可能会有更多提示信息。

相关文档

HN 系列插件文档