工具等级系统 Tool Leveling

Iguana Tinker Tweaks 的核心机制:Tinkers’ Construct 的工具在使用过程中累积经验并升级,每次升级有几率获得一个随机修饰符。本条目只讲升级骨架与经验曲线;随机奖励见 随机奖励修饰符。

  • 模块:脉冲 ToolLeveling(Reference.PULSE_LEVELING)
  • 主类:iguanaman.iguanatweakstconstruct.leveling.IguanaToolLeveling
  • 逻辑:leveling/LevelingLogic.java
  • 总开关:配置项 toolLeveling(默认 true)

NBT 标签

全部写在工具的 InfiTool 复合标签内,常量定义于 LevelingLogic:

常量 标签键 类型 含义
TAG_EXP ToolEXP long 当前工具等级累计经验
TAG_LEVEL ToolLevel int 当前工具等级(1 起)
TAG_BOOST_EXP HeadEXP long 挖掘等级提升进度(键名沿用旧的 HeadEXP 以保兼容)
TAG_IS_BOOSTED HarvestLevelModified boolean 是否已完成挖掘等级提升
— HarvestLevel int 工具的挖掘等级
— CheatyXP int 被判定为异常注入的经验(橡皮鸡计数)
— Original string 被橡皮鸡替换前的工具注册名
— Modifiers int 剩余修饰符槽数

工具首次被写入等级数据时 addLevelingData 会设 ToolLevel=1、ToolEXP=0、HeadEXP=0、HarvestLevelModified=false,并把 HarvestLevel 从材料等级减 1 写入(hlvl - 1),这就是「所有镐的挖掘等级都低 1 级、必须先提升」的机制来源。

经验来源

挖方块(最主要来源)

leveling/LevelingActiveToolMod.beforeBlockBreak(继承 Tinkers’ 的 ActiveToolMod)——源码注释直言 // This class is responsible for actually getting XP when mining!:

  1. 实体必须是 EntityPlayer;若是 FakePlayer 且 allowFakePlayerLeveling == false 则跳过(注释 // nope, you don't use an autonomous activator!);
  2. 工具必须是 HarvestTool;
  3. 方块材质不得在黑名单中:leaves, vine, circuits, glass, piston, snow;
  4. 必须同时满足 canHarvestBlock && isEffective && calculateStrength >= 1.0f(源码注释 // only give xp if the use makes sense)。

给的经验:xp = 1,若方块有 ore* 前缀的 OreDict 条目(代码里用 OreDictionary.getOreName(id).startsWith("ore") 逐个查)则 xp++。

同时累积 随机奖励权重:

  • 方块掉落数 > 1 → LAPIS 权重 +1
  • 否则 → REDSTONE 权重 +1
  • 周围 6 个方向任一为岩浆 → AUTOSMELT 权重 +10(源码注释 // it only took 7 lines to make this pun)

造成伤害

leveling/handlers/LevelingEventHandler.onHurt(LivingHurtEvent):

  1. 伤害类型必须是 "player" 或 "arrow";
  2. 攻击者必须是 EntityPlayer(FakePlayer 受 allowFakePlayerLeveling 约束);
  3. 装了 Backhand 时主手无工具则回落到副手;伤害源是 ShurikenEntity 时改为在副手位/相邻格找手里剑;
  4. xp = min(round(伤害量), round(怪物当前生命));
  5. 非武器工具只得一半(Math.max(1, round(xp / 2f)));
  6. 攻击「低等动物」再减半;
  7. 目标已死亡则只给 1/4(Math.max(1, round(xp / 4f)));
  8. 投射物武器的经验同时给弹药。

锄地

onUseHoe(UseHoeEvent):仅当手持 ToolCore 且方块是草/泥土、上面是空气时给 1L 经验。

凿子

onCrafting(PlayerEvent.ItemCraftedEvent):只认合成矩阵里有 Chisel 的情况,给凿子 1 点经验。源码注释解释为什么不检查具体配方:// we don't check for chisel recipes specifically, since there is no other recipe that requires a chisel。

制造工具

onCraftTool(ToolCraftEvent.NormalTool)不给经验,而是初始化等级数据:

LevelingLogic.addLevelingTags(toolTag, event.tool);
toolTag.setInteger("Modifiers", Math.max(toolTag.getInteger("Modifiers")
        - (3 - Config.toolLevelingExtraModifiers), 0));

即新工具默认扣 3 个修饰符槽,toolLevelingExtraModifiers 每设为 1 就少扣 1 个(保证首次升级有槽可用)。

创造模式不累积经验:addXP 首行即 if (player.capabilities.isCreativeMode) return;

经验如何分配到两条曲线

LevelingLogic.addXP 把同一点经验同时加到两条曲线:

Long toolXp  = hasXp(tags)     ? getXp(tags) + xp     : -1L;
Long boostXp = hasBoostXp(tags) ? getBoostXp(tags) + xp : -1L;
updateXP(tool, player, toolXp, boostXp);

-1L 表示「不改动」。因此挖矿得到的经验会同时推进工具等级(见上)与挖掘等级(见 Mining Level Boost)。

经验需求公式

LevelingLogic.getRequiredXp(tool, tags, miningBoost),基准 base = 100f,再按工具类型分派:

弓(bow trait)

base = 200
base *= FlightSpeed * 0.7
base *= xpRequiredWeaponsPercentage / 100

武器(weapon trait 且不是 Hammer)

base = 140
base *= getDamageModifier()
base *= max(1, Attack) * 1.2
if (Scythe)      base *= 1.5
base *= xpRequiredWeaponsPercentage / 100

其他(工具 / 镐 / 锤等)

if (HarvestLevel < 1) base -= 20
if (HarvestLevel < 2) base -= 15
base += (主头材料基础速度 + (实际速度 - 基础速度) / 5) / 2.4
// 有第二个头/手柄/额外部件时,divider 相应 +1 并累加对应速度
if (Hammer)     base *= 5.1
if (Excavator)  base *= 6.2
if (LumberAxe)  base *= 1.38
if (Shovel)     base *= 1.2
if (Hatchet)    base *= 0.66
base *= xpRequiredToolsPercentage / 100

等级指数增长

非挖掘提升路径追加:

if (ToolLevel >= 1) base *= pow(xpPerLevelMultiplier, ToolLevel - 1)
if (HarvestLevel == 0) base /= xpPerLevelMultiplier * xpPerLevelMultiplier
base *= getXPMultiplier(tool, tags)   // 材料 xpAmount,几何平均

getXPMultiplier 只统计头部部件(HEAD)——除非 onlyHeadsChangeXPRequirement 为 false,此时手柄/配件也计入;Hammer 的 extra 视为头,Excavator/Cleaver/LumberAxe/Mattock 的 accessory 视为头。多材料工具用几何平均(注释强调 NOT the arethmatic mean!)。

防作弊:橡皮鸡

LevelingLogic.updateXP 每次加经验都会累加 CheatyXP。当 CheatyXP * 2 >= 所需经验 时判定为异常注入:

  1. 聊天栏显示 message.levelup.chicken(暗红色);
  2. 播放 iguanatweakstconstruct:chicken 音效(音量 0.9,音调 1.0);
  3. 把 Original 记为原工具注册名,工具物品本身被替换为橡皮鸡(IguanaToolLeveling.rubberChicken);
  4. ToolEXP 清 0、CheatyXP 清 0。

恢复方式见 /imadirtycheater 指令。

升级时发生什么

LevelingLogic 达到经验阈值后:ToolLevel +1、ToolEXP 归零、Modifiers +1(获得一个修饰符槽)。若当前等级命中 randomBonusesAtlevels(默认 {2,3,4,5,6})则额外触发一次 随机奖励;若 toolLevelingExtraModifiers > 0 且等级命中 toolModifiersAtLevels(默认 {2,4,6})则白送额外槽位。

上限由 maxToolLevel 控制(默认 6,isMaxLevel 判定 getLevel(tags) >= Config.maxToolLevel)。

提示与显示

  • leveling/LevelingTooltips.java 生成工具提示中的经验条与百分比
  • leveling/handlers/LevelingToolTipHandler 挂到物品提示事件
  • LevelingEventHandler.onRenderGameOverlay 在 F3 调试界面左侧追加经验行(受 showDebugXP 控制);普通界面下 level <= 5 时显示工具经验,超过则改显示挖掘提升经验