血魔法仪式:匠魂之咒
基本信息
| 属性 | 值 |
|---|---|
| 注册入口 | BMCompat.bloody(),postInit 且 Loader.isModLoaded("AWWayofTime") && Config.BM(SuperTic.java:54) |
| 仪式 ID | "SuperTiC_Modifier"(BMCompat.java:12) |
| 仪式实现类 | com.Zoko061602.SuperTic.compat.RitualTinkerer extends RitualEffect |
| 显示名 | Spell of the diligent Tinkerer / 匠魂之咒(BMCompat.java:16 + lang ritual.SuperTiC_Modifier.name) |
| LP 消耗 | Config.BM_LP,默认 100000,范围 1 ~ 80000000(Config.java:80-86) |
| 刷新消耗 | getCostPerRefresh() 返回 0(RitualTinkerer.java:27-30) |
注册代码
Rituals.registerRitual("SuperTiC_Modifier", 1, Config.BM_LP, new RitualTinkerer(), "Spell of the diligent Tinkerer");
(BMCompat.java:11-16)整体包在 try { ... } catch (Exception e) { e.printStackTrace(); } 里
(BMCompat.java:10、17-19)——注册失败只打堆栈,游戏继续。
效果:升级槽 +1(与附魔配方同目标)
成功时对 NBT 的操作与附魔配方完全一致(RitualTinkerer.java:127-131,
对照 InfusionModifierRecipe.java:31-37):
nbt.setBoolean("STicBM", true);
int mod = nbt.getCompoundTag("InfiTool").getInteger("Modifiers") + 1;
nbt.getCompoundTag("InfiTool").setInteger("Modifiers", mod);
标记是 STicBM(不是 STicTC),因此同一件工具可以先附魔再仪式,或反之——
两条路径的"只能一次"标记彼此独立,各用各的。lang 文本
“every tool can only gain one extra slot this way”(zh_CN.lang 的 STiC 行)
描述的是附魔路径,血魔法路径 lang 里没有对应说明。
执行流程
performEffect 用 ritualStone.getVar1() 做两阶段状态机
(RitualTinkerer.java:33-142)。
阶段 1:var1 == 0 — 等待工具投入
在仪式石正上方 y+1 ~ y+2 的 1×1×1 空间内搜 EntityItem
(AxisAlignedBB.getBoundingBox(x, y + 1.0D, z, x + 1, y + 2, z + 1),
RitualTinkerer.java:41-43)。对每个掉落物:
| 情况 | 行为 | 源码 |
|---|---|---|
是 ToolCore 且 NBT 无 STicBM |
setVar1(1);在 y+1 处放一道闪电;setCooldown(399);item.setDead()(吞掉原物品);break |
RitualTinkerer.java:49-56 |
是 ToolCore 但 NBT 已有 STicBM |
向 ±6 格立方内((x±6, y±6, z±6))所有 EntityPlayer 广播 “This tool seems to resist the energy”;setActive(false) 并 return |
RitualTinkerer.java:57-65 |
非 ToolCore(任何掉落物) |
有 1/10 概率放一次 SpellHelper.sendIndexedParticleToAllAround(color 1,20 帧) |
RitualTinkerer.java:69-81 |
⚠️
stack.getTagCompound()在ToolCore分支里直接赋给nbt后立刻调nbt.getBoolean("STicBM")(RitualTinkerer.java:50-51)。若工具没有 NBT (getTagCompound()返回null),这里会 NPE。而阶段 2 同样依赖nbt非 null。 见 已知源码问题。
阶段 2:var1 != 0 — 倒计时与天劫
每次 performEffect 把 cooldown 减 1(RitualTinkerer.java:85)。期间:
1/30概率触发一次落雷,位置从 8 个固定偏移中随机选 1 (world.rand.nextInt(8),RitualTinkerer.java:87-121):(x+4,y,z)、(x-4,y,z)、(x+0,y,z+4)、(x-0,y,z-4)、(x+2,y+2,z+2)、(x+2,y+2,z-2)、(x-2,y+2,z+2)、(x-2,y+2,z-2)cooldown <= 0时结算:写 NBT → 在(x+0.5, y+1, z+0.5)生成新EntityItem→setVar1(0)→setActive(false)(RitualTinkerer.java:125-139)
从激活到出结果共 400 次 performEffect:激活时 setCooldown(399)(RitualTinkerer.java:54),
之后每次调用减 1,减到 <= 0 需 399 次,即激活后第 400 次调用结算。
源码没有把这 399 写成常量,也没说明该值与 Blood Magic 主体的 tick 频率关系。
⚠️ 结算处
if (spawnedItem != null)的判空在spawnedItem.setTagCompound(nbt)之后 (RitualTinkerer.java:127、129),顺序无实际意义——若stack为 null 早在RitualTinkerer.java:127就炸了。
仪式组件布局
getRitualComponentList 返回 26 个 RitualComponent(RitualTinkerer.java:144-182),
构造参数为 (itemMeta, x, y, z),其中 x / z 用 ±1 表示方位、y 为层高:
| 组 | 组件数 | 布局 | 行号 |
|---|---|---|---|
| 内圈四角 | 4 | (1,-1,1,2)、(1,-1,-1,3)、(-1,-1,1,3)、(-1,-1,-1,2) |
RitualTinkerer.java:146-149 |
| 外圈四角(低) | 4 | (±2,0,±2,0) |
RitualTinkerer.java:151-154 |
| 外圈四角(高) | 4 | (±2,1,±2,{2或3}) |
RitualTinkerer.java:156-159 |
| 北向尖刺 | 3 | (3,-1,0,1)、(4,-1,0,5)、(4,±1,-1,4) |
RitualTinkerer.java:161-163 |
| 南向尖刺 | 3 | (-3,-1,0,1)、(-4,-1,0,5)、(-4,±1,-1,4) |
RitualTinkerer.java:165-167 |
| 东向尖刺 | 4 | (0,-1,3,1)、(0,-1,4,5)、(±1,-1,4,4) |
RitualTinkerer.java:169-172 |
| 西向尖刺 | 4 | (0,-1,-3,1)、(0,-1,-4,5)、(±1,-1,-4,4) |
RitualTinkerer.java:174-177 |
四向尖刺各 3~4 个,东/西比北/南多一个,四组不对称。itemMeta 列(第一个参数)
在所有 26 个组件里只有 1、2、3、4 四个值,且与方向无关——
即整个布局不使用 Blood Magic 原版的 0(空气)位置区分,完全靠 x/z 偏移表达形状。
源码里没有任何注释或常量名说明 2 / 3 / 4 对应什么材料。
已知源码问题
- NPE:
ToolCore无 NBT 时崩(RitualTinkerer.java:50-51)。stack.getTagCompound()返回 null 时直接nbt.getBoolean("STicBM")。匠魂工具正常都带InfiToolNBT, 但被其它方式损坏 NBT 的工具会命中。对照组:PotionEventHandler.java:39-41对同一情况做了tags == null的显式判空,两个文件风格不一致。 performEffect的粒子分支对非工具物品也生效:world.rand.nextInt(10) == 0的 特效在if (stack instanceof ToolCore)块之外(RitualTinkerer.java:69), 所以往仪式石里丢任何东西(骨头、泥土)都会有 1/10 概率放特效。源码无注释说明是否有意。- 英文提示语硬编码:“This tool seems to resist the energy”
(
RitualTinkerer.java:63)用ChatComponentText直接构造,不走ChatComponentTranslation, 因此没有 zh_CN 翻译。而仪式名本身有 lang(ritual.SuperTiC_Modifier.name)。 中文玩家会看到英文提示。 - 阶段 2 不再检查工具是否还在:阶段 1 已
item.setDead(),阶段 2 只用缓存的stack字段(RitualTinkerer.java:127)。若中途该RitualEffect实例被复用 (Blood Magic 的仪式对象生命周期由其本体管理),stack/nbt字段 (RitualTinkerer.java:23-25)会残留上一次的工具 NBT。 - LP 与冷却硬编码的 399 无来源说明:
RitualTinkerer.java:54的399是魔法数, 与Config.BM_LP的可配置风格不一致。