damage/ 负责把角色、武器、声骸套装的计算点注册进 DamageManager,并在运行时自动加载。
第一次接入时,不需要先读完整手册。先记住下面三件事:
roles/{id}.tsweapons/{id}.tsgroup/{id}.ts完整字段、公式、完整示例见 REFERENCE.md。
| 位置 | 用途 |
|---|---|
index.ts | 模块入口,自动加载 roles / weapons / group |
types.ts | BuffDef、SkillDef、CalcType 定义 |
DynamicStateProviders.ts | atChain、atBreach 等辅助函数 |
roles/{id}.ts | 角色伤害配置 |
weapons/{id}.ts | 武器效果配置 |
group/{id}.ts | 声骸套装配置 |
param 取自 role/{id}.json 的 skills[].damages[].attributeIdgroup 和 match.events 用游戏全称,比如 '共鸣技能'tag 和 match.range 用简称或技能名,比如 '技能'、'焚身以火'damage_type = null 的条目通常不是伤害,不要拿来做 param如果只记一条,记第 2 条和第 3 条:events/group 用全称,range/tag 用简称。
角色数据在 resource/data/role/{id}.json,文件名就是角色 ID。
param 对应 damages[].attributeId。示例:
{
"skills": [
{
"type": "共鸣技能",
"name": "暴力美学",
"damages": [
{ "name": "技能伤害", "attributeId": 1107013, "damage_type": 4 },
{ "name": "冷却时间", "attributeId": 1107015, "damage_type": null }
]
}
]
}
这里应当取 1107013,不要取 1107015。
group 直接照抄 skills[].typetag 只在需要被 range 精确匹配时填写loaded 只在“这个伤害依附于别的触发场景”时填写最常见的 loaded 场景:
共鸣回路 伤害其实发生在 共鸣技能 之后共鸣解放 的某段伤害需要吃 共鸣技能 触发增益import { CharacterCalculator } from '../CharacterCalculator.js'
import { registerRole } from '../RegistryRole.js'
import { StatType } from '../../calc/Stats.js'
import { BuffDef, SkillDef, BuffTarget } from '../types.js'
import { atChain, atBreach } from '../DynamicStateProviders.js'
export class XxxCalculator extends CharacterCalculator {
public readonly id = 角色ID
public readonly buffs: BuffDef[] = [
// 所有增益写在这里
]
public readonly skills: SkillDef[] = [
// 所有展示计算点写在这里
]
}
registerRole(XxxCalculator)
param 是否真的来自 attributeIdgroup 是否用了游戏全称range 是否用了简称或技能名loaded武器数据在 resource/data/weapon/{id}.json。
重点读这两个字段:
skill.descriptionskill.params描述里的 {N} 对应 params[N]。示例:
{
"skill": {
"description": "全属性伤害加成提升{0}。施放变奏技能时...共鸣技能伤害加成提升{1},持续{2}秒。",
"params": [
["12%", "15%", "18%", "21%", "24%"],
["24%", "30%", "36%", "42%", "48%"],
["12", "12", "12", "12", "12"]
]
}
}
通常只写战斗内触发增益:
getParam(data, N, rank) 读取import { registerWeapon, getParam } from '../RegistryWeapon.js'
import { StatType } from '../../calc/Stats.js'
registerWeapon(武器ID, (data, rank) => [
{
name: `${data.name}:效果名`,
type: StatType.xxx,
value: getParam(data, N, rank),
match: { events: '触发条件全称' },
},
])
套装文件写在 group/{id}.ts。只要根据件数返回对应 BuffDef[] 即可:
import { registerEchoSet } from '../RegistryEchoSet.js'
import { StatType } from '../../calc/Stats.js'
import { BuffTarget } from '../types.js'
registerEchoSet('8', (count) => {
if (count < 5) return []
return [{ name: '套装:轻云出月(5)', type: StatType.atk, value: 0.225, target: BuffTarget.Next }]
})
这部分是补真实角色时最容易踩坑的地方,绯雪这类角色基本都会碰到。
先选“实战里真正拿来结算的主输出点”,再决定写哪些 SkillDef。
以绯雪为例,更合理的核心点是:
霜罚·白玉切预求我身·见心预求我身·归刃(3层)重击·枯霜·预求身居合不要把“有倍率”但不属于主输出循环的段硬塞进核心面板。
补角色时,不要只看 skills。还要一起看:
最容易漏掉的不是“攻击提升 10%”这种明牌,而是:
final_dmgdmg_deepenTeam / Next 类增益很多条目看起来像常驻,实际不是。
绯雪这组里典型的几类:
雪落无声之愿 的暴击提升,要先满足 霜渐效应 和 落雪 这层前提灼霜 的忽视防御,只对满足条件的解放类伤害生效如果条件写宽,面板会虚高;如果条件写窄,核心点会被低估。
有些技能的 group 和它真正吃增益的事件不是一回事,这时必须补 loaded。
判断方法:
共鸣回路 / 常态攻击 下,但实际是某个 共鸣技能 或 共鸣解放 链路里打出来的吗loaded不补的话,武器、链路、套装上的条件增益会吃不到。
有些技能不是单一倍率,而是:
这类技能先定口径,再写代码,例如:
预求我身·归刃 按 3 层【锻雪·归刃】计算不要把“每层额外倍率”直接当成一个夸大的 skill_ratio 乱乘;先确认它和基础倍率是什么关系。
当前这套结构不擅长表达这类状态:
像 雪落无声之愿 的 落雪 就属于这类。
这种情况的处理原则:
| 错误写法 | 为什么错 |
|---|---|
range: ['普通攻击'] | range 不认全称,只认简称 |
events: '普攻' | events 不认简称,只认全称 |
param 取了 level | 真正需要的是 attributeId |
| 武器常驻属性又注册一遍 | 会双算 |
依附触发的伤害没写 loaded | 对应条件增益吃不到 |
下面这些情况,直接去看 REFERENCE.md:
StatType 用哪个Healing、Shield、HarmonicDamageloaded、target、forceCrittypes.ts../calc/Stats.tsDynamicStateProviders.tsREFERENCE.md