Matrix Attunement(节点基体调制)

基本信息

属性 值
类名 shukaro.nodalmechanics.recipe.RecipeAttune
接口 thaumcraft.api.crafting.IArcaneRecipe
注册时机 NodalRecipes.initRecipes()(FMLInitializationEvent),ThaumcraftApi.getCraftingRecipes().add(...)
工作方块 奥术工作台(Arcane Workbench,3×3 网格)
前置研究 NODECATALYZATION(ThaumcraftApiHelper.isResearchComplete 校验,未完成永不匹配)
核心物品 节点基体(1 个,且只能有 1 个)
填充材料 泰老 essentia 源质瓶 itemEssence:1(1~8 个)
换算倍率 ESSENTIA_MULTIPLIER = 4

功能

把 essentia 源质瓶里的要素灌进节点基体,得到要素更多的基体。这是「节点基体」 从"空"变成"有种子"的第一步,也是本 mod 全流程里唯一可以反复执行的配方—— 基体的 tooltip 专门有一行「可多次调制」(en_US: You can attune it multiple times!)。

matches(IInventory, World, EntityPlayer) 的判定顺序:

  1. 研究校验:玩家未完成 NODECATALYZATION → 直接 false。
  2. 找基体:三重循环扫描 3×3 共 9 格,命中第一个基体后继续扫; 只要再遇到第二个基体就立刻 false(一张基体配方只能放一个)。
  3. 基体缺失 → false。
  4. 扫材料:再次遍历 9 格
    • 空栈(null 或 getItem() == null)→ 跳过;
    • 与基体匹配 → 跳过(中心那张基体本身);
    • 匹配 itemEssence:1 源质瓶 → 必须带非空 Aspects NBT,否则整张配方失败(false), 然后把瓶内每种要素按 瓶内数量 / 4(整数除法)累加进结果列表;
    • 任何其他物品 → false。
  5. 结果:累加值 > 0 时成功,产物 = 基体的副本,把累加出的要素合并到基体原有 Aspects 上(aspectList.add(initialAspectList))后写回 NBT。

因为要素是相加而不是覆盖,基体可以从空开始一步步累积,也可以拿一张已调制的基体 继续往上加——这正是"递归过程"的含义。

要素换算规则

aspectList.add(aspect, phialAspectList.getAmount(aspect) / 4):

瓶内某要素数量 灌入基体的要素数量
8 2
7 1
5 1
4 1
1 ~ 3 0(整数除法截断)
0 0(但若整瓶 Aspects 为空 → 配方直接失败)

要点:源质瓶里哪怕只有 1~3 点某要素,该要素也会被整除成 0 而白扔; 但只要该瓶 Aspects 列表非空,配方本身仍然成立(只是没加到东西)。

vis 消耗

getAspects() 返回固定值,与瓶数、瓶内要素量完全无关:

要素 vis
AER 2
IGNIS 2
AQUA 2
TERRA 2
ORDO 2
PERDITIO 2
合计 12

即无论灌 1 瓶还是 8 瓶,奥术工作台都只扣 12 vis(getAspects(IInventory) 直接 返回 getAspects(),没有按输入量缩放的逻辑)。作为对比,基体上的要素总量是累加的, 两者不成正比。

数值

数值 值
配方占用格数 9(getRecipeSize(),即整个 3×3)
可用基体数量 恰好 1
可用源质瓶数量 0 ~ 8(至少 1 个非空瓶)
essentia → 要素 整数除 4
vis 消耗 固定 12(六本原各 2)
产物 基体副本,NBT 要素 = 原要素 + 本次累加

研究页面图示(仅展示,未注册)

NodalRecipes 另外构造了两张静态 ShapedArcaneRecipe 给研究页面显示用:

配方 布局 材料 产物
variedAttuneRecipe ABC / X / DEF 6 个源质瓶,每瓶 8 点不同的本原要素;X = 节点基体 六种本原要素各 2 的已调制基体
sameAttuneRecipe AAA / ABA / AAA 8 个源质瓶,每瓶 8 点 IGNIS;B = 节点基体 IGNIS 16 的已调制基体

两张的 vis 消耗都是 attuneAspectList(六本原各 2 = 12),与动态配方一致。

⚠️ 这两张静态配方没有被加入配方列表:initRecipes() 只注册了 matrixRecipe、 RecipeAttune、RecipeNode 三个。所以它们只出现在研究页面上供玩家对照, 真正的执行永远走 RecipeAttune——上面两张布局表是"设计意图"的展示, 实际能否匹配以 matches() 的规则为准(例如源质瓶瓶内要素组合与布局图不一致时, 动态配方照样成功)。

限制

  • 必须先完成 NODECATALYZATION 研究。
  • 一张配方里出现两个基体即失败。
  • 源质瓶必须带非空 Aspects;空瓶(无 NBT 或要素为空)会让整张配方失败。
  • 源质瓶 NBT 不参与匹配判定(OreDictionary.itemMatches(phial, slotStack, true) 中 源质瓶用的是默认比较),所以任意要素组合的源质瓶都可用——元素种类不受这张配方约束。
  • 要素换算为整数除法,1~3 点要素会被丢弃(见上表)。
  • vis 固定 12,与实际投入量脱钩(平衡性上的刻意设计,本 mod 未给出理由)。
  • output 字段是 RecipeAttune 的实例成员,由 matches() 写入、getCraftingResult() 复制返回;该对象在配方列表中全局共享一个实例(见研究页面的静态配方限制说明)。

相关条目