天赋运行时
天赋注册、抽取、修习公式、保存状态、同步与管理员工具。
玩家为每项天赋保存先天等级、隐藏潜力、熟练度与修习点,另有独立的显现组件。游戏效果读取修习后的有效等级;可见性只影响呈现,不限制加成或修习奖励。
它做什么
实现位于 internal.talent,消费辅助类位于 util.talents。没有 TalentAPI 门面,也没有天赋 JSON 加载器。这些内部类供仓库开发使用,不是稳定的外部 API。天赋 提供面向玩家的加成与目录。
isekaiexpansion:talent 与 isekaiexpansion:talent_reveal 是自动同步的玩家组件,重生均使用 ALWAYS_COPY。IsekaiTalents.init() 注册定义与服务端加入钩子。加入时调用 patchData(0.0F),不会自动读取玩家的幸运属性。
运行时模型
注册表、初始抽取与同类组
E/D/C/B/A/S 对应 0/1/2/3/4/5,数字转换会限制到该范围。当前共 36 项天赋:18 种近战武器、4 种远程武器、双持、星界能量容量、6 种常见元素与 6 种扩展法术学派。
| 定义分组 | E / D / C / B / A / S 权重 | 幸运强度 |
|---|---|---|
| 星界能量容量 | 15 / 20 / 30 / 25 / 8 / 2 | 0.35 |
| 双持 | 34 / 26 / 22 / 12 / 5 / 1 | 0.25 |
| 常见元素 | 10 / 20 / 30 / 25 / 10 / 5 | 0.45 |
| 扩展法术学派 | 30 / 25 / 25 / 12 / 5 / 3 | 0.20 |
| 近战/远程武器 | 17 / 23 / 30 / 17 / 10 / 3 | 0.30 |
| 新定义构建器默认值 | 60 / 25 / 10 / 4 / 1 / 0 | 0.30 |
这些是规则应用前的权重,不是最终独立概率。等级索引 r 的调整权重为 max(0, round(base × (1 + luck × strength × r / 5)));基础权重为零时仍为零。调整后总权重非正则重试原始非负权重,仍为空时返回 E。
随机种子对 UUID 两部分、服务端世界种子和新取出的 player.getRandom().nextLong() 做 XOR,因此仅凭 UUID 与世界种子不能重现重掷结果。先抽取全部等级,再依次执行定义规则和全局规则。规则重复到无变化或达到 16 轮;达到上限会接受当前结果,不保证已收敛。外层允许 24 次尝试并提供全部 E 的后备,但现有规则上下文没有公开的判无效操作,当前规则也不设置其 invalid 标志。
| 初始规则 | 结果 |
|---|---|
| 任一映射的元素/扩展学派为 S | 基础星界能量至少为 B。 |
| 任一映射的元素/扩展学派为 A | 基础星界能量至少为 C。 |
| 光/治疗或暗/奥术配对中有 S | 另一项至少为 A。 |
| 光/治疗或暗/奥术配对中有 A | 另一项至少为 B。 |
| 近战同类组中有 A / S | 全组至少为 C / B。 |
| 弓/弩组中有 A / S | 两项至少为 B / A。 |
| 枪/魔导枪组中有 A / S | 两项至少为 A / A。 |
近战分组为剑刃(sword、rapier、katana、dagger、greatsword)、长柄(spear、halberd、glaive、lance、scythe)、冲击(axe、mace、hammer、gauntlet)、投掷(chakram、boomerang)和魔法器具(wand、staff)。法术配对与武器同类组还共享一次潜力抽取,再分别产生组内偏差。元素对容量的前置关系不构成同类组。每项天赋保留最先注册的亲和组。修习与管理员改等级不会重新执行初始联动规则。
潜力与熟练度公式
潜力 p 限制为 0–99,基础抽取在该整数区间均匀分布。幸运生成 lean = clamp(luck × 0.25, −1, 1);非负值将抽取结果推向 99,负值推向 0,随后舍入并限制范围。同类组成员在共同抽取值上独立增加 −12–12 的整数偏差,再限制范围;独立天赋各自抽取。
| 潜力 | 最多修习阶数 | 尚未考虑 S 空间时的熟练度上限 |
|---|---|---|
| 0–21 | 0 | 0 |
| 22–65 | 1 | 4 |
| 66–99 | 2 | 9 |
设 L 为熟练度、i 为先天等级索引,t 为潜力允许阶数与 L 已达到阶数的较小者(4 前为 0,4 起为 1,9 起为 2)。有效等级为 clamp(i + t, 0, 5),实际获得阶数也不能超过 5 − i。个人熟练度上限依据 min(allowed tiers, 5 − i) 分别为 0、4 或 9。
每步代价公式如下:
gift = clamp(p, 0, 99) / 99
grind = 1.35 - (1.35 - 0.65) * gift
toll = 1 + (1.5 ^ effectiveRankIndex - 1) * grind
base = 90 * (max(0, L) + 1) ^ 1.55
stepCost = max(10, round(round(base * toll) / 10) * 10)
expCap 在 L ≥ 9 时返回 0,但不会因较低的个人上限而自行返回 0;判断能否修习应使用 canStillGrow()。cumulativeExp 累加到公共等级上限以内的每步代价。TalentProficiencyLeveler 将个人上限交给 IsekaiCore 的 LevelingHandler 处理溢出进度;适配器在没有成长空间时清空修习点。处理器缓存索引为先天等级 × 100 + 潜力,最多 600 项。
修习、消费与可见性
TalentProficiencyService.award 只接受 ServerPlayerEntity、非 null 天赋 ID、正数点数、非创造/旁观模式、已有进度条目且仍可成长的情况。奖励原值入账,不乘潜力系数,也不检查显现。熟练度等级变化立即同步,并在相关时刷新派生能量;仅计数变化则走节流同步。
| 钩子 | 奖励与归属 |
|---|---|
| 近战天赋伤害修正 | 对伤害标记的近战武器类型奖励 8;当前双手武器符合双持条件时,双持再奖励 8。直接伤害来源必须是玩家。 |
| 远程天赋伤害修正 | 对标记的远程武器类型奖励 11;通过弹射物所有者/远程攻击者解析归属。 |
进度 > 0.30 的法术 RELEASE | 对映射学派奖励 10,对基础星界能量奖励 4。 |
单独的法术 CHANNEL | 此钩子不奖励修习。 |
伤害奖励发生在修正函数求值阶段,不检查正伤害、不等待最终生命损失,也不按每次挥动去重。双持不要求两只手分别成功命中。法术在符合条件的释放后奖励,不要求正数能量扣费,也包括引导法术的释放路径;学派无映射时可能只有储备奖励,没有学派奖励。
近战、远程与法术加成读取有效等级。攻速刷新在服务端生物 tick 执行,将双手近战增量与一次双持增量相加,使用 EntityAttributeModifier.Operation.ADDITION。当前 UI 的百分比格式不改变该运算。DualWieldTalentUtil.offHandMultiplier 存在,但当前仓库没有调用者,因此其额外副手倍率没有接入现有伤害流程。
映射学派的绑定和施法受天赋检查约束,创造模式跳过。施法时间缩放仅用于原始时长为正的非引导玩家法术。能量消耗将法术基础消耗与天赋、其他消耗修正相乘后舍入。容量修正以 attribute base × (rank multiplier − 1) 替换 UUID 435f53d1-e0fd-4307-bc5d-df7fc035c78b 的修正项,并在加入/修补、设置等级与熟练度变化时刷新。
显现钩子独立:有目标的近战攻击动作显现武器天赋及符合条件的双持天赋;射击进度 ≥ 1 显现远程天赋。水晶隐藏组有辅助方法与管理员命令,但没有物品使用调用点。法术修习不显现天赋。开启全部显现会清空显式解锁列表;单独关闭全部显现不会额外清除显式条目。lockAll 只关闭标志,reset 命令还会调用 clearUnlocked。
约定
注册与修改
| 入口 | 约定 |
|---|---|
TalentDefinition.builder(id) | 内部构建器;权重下限为 0,幸运强度限制为 0–2。构建时复制权重与规则列表。 |
TalentRegistry.register(def) | 同 ID 替换,不拒绝重复,也没有线程同步。 |
registerRule(id, rule) | 在保持插入顺序的存储中替换同 ID 全局规则。 |
registerAffinityGroup(group, members) | 每项天赋最先加入的组生效。 |
TalentRules.minIf/maxIf | 条件等级下限/上限;自定义规则同步执行,没有异常隔离。 |
TalentsComponent.get(id) | 有效等级,缺失时返回 E。 |
innate(id) | 先天等级,缺失时返回 E。 |
progress(id) | 返回可变实时进度;缺失时创建 E/潜力 0,拒绝 null ID。 |
set(id, rank) | 修改先天等级并同步,保留潜力、熟练度与修习点,不验证注册表成员身份。 |
forceReroll(luck) | 重新抽取并替换全部天赋进度,不重置显现状态。 |
TalentRevealer.unlock/unlockAll | 增加可见性,不检查注册表、不改变等级;批量操作合并同步。 |
TalentRevealComponent.patchData() | 移除过时的显式解锁 ID;加入钩子没有调用该方法。 |
在公共初始化阶段一致注册,早于玩家加入或客户端目录捕获。玩家进度应在服务端线程修改。内部 setter 不检查侧别,也不维护全部跨字段约束;直接修改熟练度/潜力后应调用适当的组件刷新。不要将这些内部类当作受支持的附属模组门面。
保存字段与修补
| 字段 | 类型 | 默认值 | 作用 |
|---|---|---|---|
hasGen | 布尔值 | false | 是否完成初次抽取;false 时修补会重新抽取并替换已有条目。 |
talents | Compound | 空 | 天赋标识符字符串到进度 compound 的映射。 |
talents.<id>.rank | 整数 | 0 | 先天等级,限制为 0–5。 |
talents.<id>.potential | 整数 | 0 | 隐藏潜力,限制为 0–99。 |
talents.<id>.level | 整数 | 0 | 熟练度,限制为 0–9,不限制到个人上限。 |
talents.<id>.exp | 整数 | 0 | 修习点下限为零;读取时不按每步代价封顶。 |
revealAll | 布尔值 | false | 独立显现组件标志;为 true 时读取忽略显式列表。 |
unlocked | 字符串列表 | 空 | 合法 ID 成为显式解锁,重复合并、无效项跳过。只在非全部显现且列表非空时写出。 |
这里没有载荷版本或旧整数等级转换。非 compound 条目按 compound 读取时使用 getter 默认值,不保留其旧数字等级。合法但未注册的 ID 会保留到原始读取结束,再由天赋修补移除;非法标识符键直接跳过。
初次生成会抽取全部条目、同步并应用容量。后续加入会移除过时天赋 ID;若缺少条目,则进行一次完整新抽取,但只填入缺项,保留原有记录。因此新增天赋的抽取联动可能依赖那些被丢弃的、现有天赋的重掷值;修补不会依据当前规则重新协调整个存档角色。
同步与呈现
修习计数最多每 40 ticks(2 秒)世界时间同步一次。检查发生在下一次奖励到来时,没有定时补发;节流窗口内的最后一次奖励可能直到其他同步或重连才可见。等级变化立即同步。
isekaiexpansion:player_talent_growth 按 identifier/VarInt/VarInt 携带天赋 ID、熟练度和有效等级,仅在实际获得天赋阶数时提示,不对每个熟练度等级提示。isekaiexpansion:player_talent_unlocked 只携带显现 ID。两个数据包都不替代组件状态。
客户端界面打开时捕获固定的 TalentSnapshot。隐藏条目遮蔽名称、加成和熟练度,但同步组件仍含进度与潜力,因此不显示数字是 UI 约定,不代表客户端拿不到数据。已显现统计使用与游戏效果相同的加成辅助方法。卡片修习条使用个人可达空间,档案的已得阶数分母则使用潜力最多阶数;先天 A 且潜力深厚时,可能只有一阶可练,但潜力分母仍为两阶。
天赋名称键为 talent.<namespace>.<path>,描述追加 .desc;纹理位于 assets/<namespace>/textures/talent/<path>.png。描述翻译缺失时使用界面后备文本,隐藏卡片使用 isekaiexpansion:textures/talent/locked.png。界面不暂停游戏,左键选择、右键打开模态档案;Escape 先关闭档案,再关闭界面。
扩展方式
在公共初始化时新增定义,提供双语条目与图标,并显式接入游戏效果或修习钩子。仅注册不会创建新的伤害类别、学派映射或训练来源。下面是内部使用示例,导入来自 internal.talent、Minecraft Identifier 与 ServerPlayerEntity:
public static void registerExampleTalent() {
TalentRegistry.INSTANCE.register(
TalentDefinition.builder(new Identifier("example", "craft"))
.weights(60, 25, 10, 4, 1, 0)
.luckStrength(0.30F)
.build());
}
public static void awardExamplePractice(ServerPlayerEntity player) {
TalentProficiencyService.award(
player, new Identifier("example", "craft"), 8);
}
玩家必须在注册后完成进度修补,奖励才可能成功。仅在目标服务端动作发生时发放;若动作还应显现天赋,需要另外调用显现辅助方法,奖励不等于显现。
验证
以下命令均要求权限等级 2。<target> 接受玩家选择器,显式天赋参数必须指向已注册定义。
/ise talent 下的命令 | 效果 |
|---|---|
reroll <target> [luck] | 幸运默认 0,命令只接受非负浮点数。重置全部等级/潜力/修习,保留显现。 |
set <target> <talent> <rank> | 等级 0–5,仅改变先天等级。 |
proficiency level <target> <talent> <level> | 等级 0–9;清空修习点,但不限制到个人上限。 |
proficiency potential <target> <talent> <potential> | 潜力 0–99;保留等级与修习点,刷新派生效果。 |
proficiency grant <target> <talent> <amount> | 正整数,遵守正常奖励检查;创造/旁观/已封顶目标可能没有获得修习,但仍计入反馈人数。 |
proficiency inspect <target> <talent> | 报告先天/有效等级、熟练度、修习点/代价、原始潜力、潜力阶数与当前负担倍率。 |
reveal unlock <target> <talent> | 显现一项。 |
reveal crystal <target> | 显现 13 项容量/学派条目。 |
reveal all <target> | 开启全部显现并清空显式解锁。 |
reveal reset <target> | 关闭全部显现并清空显式解锁。 |
测试潜力边界 21/22、65/66,熟练度 4/9 的升阶,先天 A/S 的空间,大额修习奖励,以及超过个人上限的保存值。验证隐藏天赋仍能修习、显现不改等级、重掷保留显现。对照双手平加攻速与界面百分比。检查映射/无映射学派、引导与释放、零消耗法术、新定义加入时修补、重生,以及节流窗口内最后一次奖励后不再触发奖励的情况。
等级/潜力 setter 是管理员工具,不是普通游戏过程,可能保留超过上限的等级或旧修习总量。应检查结果,不要假设全部字段已共同归一化。