Skip to content

品质系统 ​

品质等级怎么配置, 锻造结果落在哪个品质由什么决定, 保底怎么算, 以及品质怎么改变成品的名称和 Lore

品质系统决定锻造结果落在哪个品质等级, 同时影响材料效果的数值倍率和物品的展示

全局品质配置 ​

品质在 config.yml 的 quality 节点里做全局配置. 发货默认值:

yaml
quality:
  tiers:
    - name: "平庸"
      weight: 60
      multiplier: 1.0
    - name: "精良"
      weight: 30
      multiplier: 1.05
    - name: "有缺"
      weight: 10
      multiplier: 0.95
    - name: "优质"
      weight: 5
      multiplier: 1.1
    - name: "无暇"
      weight: 2
      multiplier: 1.15
    - name: "完美"
      weight: 1
      multiplier: 1.2
  default_tier: "平庸"
  guarantee:
    enabled: true
    threshold: 60
    minimum: "无暇"
  item_meta:
    enabled: true
    tiers:
      无暇:
        name_actions:
          - action: "prepend_prefix"
            value: "<color:#4B64C8>[无暇] </color>"
        lore_actions:
        action:
          - 'broadcast_message text="<color:#4B64C8>%player_name%锻造出了一个无暇品质的%var.forge_show_item%</color>"'
      完美:
        name_actions:
          - action: "prepend_prefix"
            value: "<color:#FFD700>[完美] </color>"
        lore_actions:
        action:
          - 'broadcast_message text="<color:#FFD700>%player_name%锻造出了一个完美品质的%var.forge_show_item%</color>"'
      # 平庸 / 精良 / 有缺 / 优质 只有 name_actions, 无 action 广播

config.yml 的 item_meta.tiers 共 6 个档位; 上例省略了其余 4 档, 它们与"无暇"结构相同, 但只有 name_actions

quality 字段 ​

字段类型必填默认值取值范围说明
quality.tierslist<object>否单一品质 普通 (权重 100, 倍率 1.0)每项为记录或 "品质名-权重-倍率" 字符串品质池. 留空或全部条目都不合法时, 退到内置默认池, 同时把保底和 item_meta 一起关掉
quality.tiers[].namestring是 (该记录存在时)—非空字符串品质的唯一标识, 同时也是显示名. 留空时这一项被忽略
quality.tiers[].weightinteger是 (该记录存在时)—> 0抽取权重, 越大越容易被抽到. <= 0 时这一项被忽略
quality.tiers[].multipliernumber否1.0任意数值材料效果数值要乘的倍数 (配置值 × 材料数量 × 品质倍率)
quality.default_tierstring否普通品质池中存在的品质名没抽到有效品质名时用的备用品质. 写进去的名字不存在时, 改用品质池的第一项
quality.guaranteeobject否见下—保底配置, 见保底机制
quality.item_metaobject否见下—品质物品元数据, 见 item_meta 品质写入
yaml
quality:
  tiers:
    - name: "普通"
      weight: 70
      multiplier: 1.0
    - name: "精良"
      weight: 25
      multiplier: 1.05
    - name: "史诗"
      weight: 5
      multiplier: 1.15
  default_tier: "普通"

tiers 格式 ​

quality.tiers 的每一项既可以写成上面的记录形式, 也可以写成 "品质名-权重-倍率" 字符串 (用 - 切成三段); 两种写法都解析失败时, 这一项被忽略

NOTE

tiers 全部解析失败时, 会退回内置默认品质池 (只有一种品质 普通, 权重 100, 倍率 1.0), 同时保底和 item_meta 都会关掉

保底机制 ​

下表"默认值"是指配置里没写这个键时代码采用的回退值, 和随包 config.yml 里的发布值不一样. 随包发布值是 enabled: true, threshold: 60, minimum: "无暇", 也就是随包配置本身就把保底打开了

字段类型必填默认值取值范围说明
quality.guarantee.enabledboolean否falsetrue / false是否打开全局保底. 随包发布值是 true
quality.guarantee.thresholdinteger否10>= 1 (< 1 提升为 1)连续多少次没达到最低品质就触发保底. 随包发布值是 60
quality.guarantee.minimumstring否普通品质池中存在的品质名保底触发时给的最低品质等级. 这个名字不存在时退回 default_tier. 随包发布值是 无暇

保底判定规则:

  • 每次锻造后, 比较这次抽中的品质在品质池里的位次和保底最低品质的位次
  • 位次更低时, 保底计数 +1; 否则把保底计数重置为 0
  • 计数达到 threshold - 1 后, 下一次锻造直接给出保底品质, 并把计数重置
yaml
quality:
  guarantee:
    enabled: true
    threshold: 30
    minimum: "精良"

NOTE

保底计数器按"玩家 + 配方"分别记录, 存在 data/<玩家UUID>.yml 里. quality_modify 的 force 模式会跳过全部保底逻辑, 既不触发保底也不更新计数. 配方自己的保底 (attempts) 和全局保底只会生效其中一个, 见配方级别品质覆盖

item_meta 品质写入 ​

quality.item_meta.enabled 为 true 时, 锻造成功后会按品质等级对结果物品多做几步操作:

字段类型必填默认值取值范围说明
quality.item_meta.enabledboolean否falsetrue / false是否把品质对应的名称, Lore 和动作写到锻造结果上. 随包发布值是 true
quality.item_meta.tiers.<品质名>object否空键为品质名, 大小写不敏感按品质登记的元数据. 品质名不在注册表里时, 这一条不生效
quality.item_meta.tiers.<品质名>.name_actionsobject | list否不登记CoreLib 名称动作对结果物品名称执行的动作. 值为 null (只写键, 不给值) 时不登记这个品质的名称动作
quality.item_meta.tiers.<品质名>.lore_actionsobject | list否不登记CoreLib Lore 动作对结果物品 Lore 执行的动作. 随包 config.yml 在这里只写键, 不给值 (也就是 null), 含义是"不登记这个品质的 Lore 动作"; 这和显式写空列表 [] (登记一条空动作链) 不一样
quality.item_meta.tiers.<品质名>.actionlist<string>否空列表CoreLib 动作行按品质执行的动作列表 (比如全服广播)

下面是一个可复制的例子: 给"精良"加名称前缀, 并让"完美"触发全服广播

yaml
quality:
  item_meta:
    enabled: true
    tiers:
      精良:
        name_actions:
          - action: "prepend_prefix"
            value: "<color:#1F871F>[精良] </color>"
      完美:
        name_actions:
          - action: "prepend_prefix"
            value: "<color:#FFD700>[完美] </color>"
        action:
          - 'broadcast_message text="<color:#FFD700>%player_name% 锻造出了完美品质的 %var.forge_show_item%</color>"'

品质元数据的动作与配方 result.success 的动作, 材料效果动作会合并到一起, 统一应用到结果物品上

确定性算法 ​

品质计算用的是确定性算法: 品质由一段指纹算出来, 指纹里包含"玩家 UUID + 配方 ID + 当前保底计数 + 目标与各槽位物品签名", 再加上预览种子, 不是每次现掷随机数. 内部对这段 roll key 取 SHA-256, 用哈希前 12 位十六进制字符换算成一个 0~1 的比例, 再拿这个比例去品质池上做加权选择

已经准备好的锻造结果会缓存下来, 最多 128 项, 每项存活 30 秒, 因此:

  • 你在界面里看到的品质结果和实际锻造结果一致
  • 30 秒内重复提交相同输入不会改变结果
  • 你换了材料, 或等缓存过期之后, 结果会变化

配方级别品质覆盖 ​

每个配方都能在自己的 quality 节点里覆盖全局配置. 注意配方里的字段名和全局配置不一样:

yaml
quality:
  enabled: true
  custom_pool:
    - "普通-50-1.0"
    - "精良-35-1.08"
    - "史诗-15-1.25"
  guarantee:
    enabled: true
    attempts: 5
    minimum: "精良"
字段类型必填默认值取值范围说明
enabledboolean否falsetrue / false是否打开配方自己的品质配置. 为 false 时 custom_pool 和配方自己的保底都不生效
custom_poollist<string>否空"品质名-权重-倍率" 字符串这个配方专用的品质池. 为空或全部条目不合法时, 用全局的 quality.tiers
guarantee.enabledboolean否falsetrue / false是否打开配方自己的保底
guarantee.attemptsinteger否10>= 1 (< 1 提升为 1)配方自己的保底阈值. 对应全局配置里的 threshold
guarantee.minimumstring否普通品质池中存在的品质名配方保底给的最低品质. 这个名字不存在时取配方池的第一项, 还是没有就退回全局保底的最低品质

NOTE

配方自己的保底没打开, 而全局保底打开了时, 就退回全局的 threshold 与 minimum. 只有配方的 quality.enabled 和 quality.guarantee.enabled 同时为 true 时, attempts / minimum 才会被采用

与材料效果的交互 ​

  • variables 效果值 = 配置值 × 材料数量 × 品质倍率
  • ea_attribute 效果值 = 配置值 × 材料数量 × 品质倍率
  • quality_modify 的 force 模式会跳过保底判定和计数更新
  • quality_modify 的 minimum 模式只在抽中品质低于指定品质时, 把结果提升到该品质

材料效果的详细写法见材料系统