工具材料触发药水效果
基本信息
| 属性 | 值 |
|---|---|
| 核心类 | com.Zoko061602.SuperTic.PotionEventHandler(package-private,getInstance() 单例,PotionEventHandler.java:17-21) |
| 触发事件 | AttackEntityEvent(SuperEventHandler.java:12-15,无优先级指定即 NORMAL) |
| 生效条件 | 目标为 EntityLivingBase 且攻击者为 EntityPlayerMP(PotionEventHandler.java:24) |
| 注册时机 | preInit,MinecraftForge.EVENT_BUS.register(new SuperEventHandler())(SuperTic.java:47) |
判定的四个前置检查
按源码顺序(PotionEventHandler.java:24-78):
| 顺序 | 检查 | 失败后果 | 源码 |
|---|---|---|---|
| 1 | event.target instanceof EntityLivingBase && event.entityPlayer instanceof EntityPlayerMP |
直接返回 | PotionEventHandler.java:24 |
| 2 | player.getCurrentEquippedItem() == null |
直接返回 | PotionEventHandler.java:27-29 |
| 3 | 目标是 EntityPlayer 且 player.canAttackPlayer(tar) |
直接返回(PVP 保护 / 队友判定时不给buff) | PotionEventHandler.java:31-33 |
| 4 | 手持物 getItem() instanceof ToolCore 且 getTagCompound() != null |
直接返回 | PotionEventHandler.java:35-41 |
注意第 3 条的语义:
canAttackPlayer返回false才不发效果。也就是说 可以攻击时才发效果,是正向判断而非"禁止 PVP 时生效"。
读取的四个部件位置
从 InfiTool NBT 复合标签读(PotionEventHandler.java:43-55):
| NBT 键 | 读取条件 |
|---|---|
Head |
无条件 |
Handle |
无条件 |
Accessory |
tool.getPartAmount() >= 3 |
Extra |
tool.getPartAmount() >= 4 |
未读取的位置保持 -1(PotionEventHandler.java:46-47)。之后每个位置都查
Config.id_eff.containsKey(位置),命中后按符号分派(PotionEventHandler.java:57-76):
if (Config.id_eff.get(head) > 0) addEffect(target, head);
else if (Config.id_eff.get(head) < 0) addEffect(player, head);
正数 → 施加给被攻击的目标;负数 → 施加给攻击者自己。 这与 effects.cfg 里
“Effect id (if negative gets applied to player)” 的注释一致(Config.java:35)。
实际施加
private void addEffect(EntityLivingBase e, int id) {
int r = new Random().nextInt(Config.id_prob.get(id));
if (r == 0) e.addPotionEffect(
new PotionEffect(Math.abs(Config.id_eff.get(id)), Config.id_dur.get(id), Config.id_amp.get(id)));
}
(PotionEventHandler.java:82-86)
| 项目 | 来源 | effects.cfg 默认值 |
|---|---|---|
| 触发概率 | Config.id_prob(nextInt(prob) == 0,即 1/prob 命中) |
1(100% 触发) |
| 药水 ID | Math.abs(Config.id_eff) |
0(无效果) |
| 时长 | Config.id_dur(tick) |
200 tick |
| 等级 | Config.id_amp(即 amplifier,getLatin 里的罗马数字) |
1(即效果 I) |
⚠️ 每次调用都 new Random()(PotionEventHandler.java:83),不使用实体/世界已有的 RNG。
在高频攻击下这会持续构造新 Random 对象,且结果是时间种子驱动——不保证同一攻击的
可复现性。
物品部件提示(Tooltip)
TooltipEventHandler(TooltipEventHandler.java,@SideOnly(Side.CLIENT))被
SuperEventHandler.Tooltip(@SideOnly(Side.CLIENT),SuperEventHandler.java:17-22)
在 ItemTooltipEvent 时调用,一次做三件事(TooltipEventHandler.java:43-47):
1. 材料部件提示 addPartTooltips
对 instanceof IToolPart 的物品(材料本身 / 未组装的工具部件),用
item.getMaterialID(e.itemStack) 查 Config.id_eff;为 0 则不显示
(TooltipEventHandler.java:50-52)。显示为 药水名 + 罗马数字,并用聊天色区分方向
(TooltipEventHandler.java:53-56):
| 效果 ID 符号 | 颜色 | 含义 |
|---|---|---|
| 负 | EnumChatFormatting.AQUA |
给自己 |
| 正 | EnumChatFormatting.DARK_AQUA |
给目标 |
2. 组装工具提示 addPotionTooltips
对 instanceof ToolCore 的成品工具,按 Head → Handle → Binding(Accessory) → Extra
顺序输出(TooltipEventHandler.java:110、124、138、152),规则:
- 每行只显示一种药水;若多个部件是同一种药水,取其中最高等级并只显示一行
(
TooltipEventHandler.java:102-115等处逐段比较c < xxx.getAmplifier()) - 后面的部件若药水与前面已显示的重复,则跳过
Binding行要求getPartAmount() >= 3,Extra行要求getPartAmount() == 4(TooltipEventHandler.java:132、148)- 整段包在
try { ... } catch (Exception ex) { ex.printStackTrace(); }里 (TooltipEventHandler.java:163-165)
3. TGregworks 材料提示 addGregTooltips
对 IToolPart 且 GameRegistry.findUniqueIdentifierFor(item).modId.equals("TGregworks")
的材料,显示 mat.stonebound(TooltipEventHandler.java:170-182):
mat.stonebound |
显示 |
|---|---|
> 0 |
Stonebound: x + 正值 |
< 0 |
Jagged: x + 取负后的绝对值 |
== 0 |
不显示 |
罗马数字映射
getLatin(TooltipEventHandler.java:27-41):0/1 → " I"、2 → " II" …、
10 → " X"、其他 → " X+"。所以 Amplifier = 1 显示为「I」,
Amplifier = 0 也显示为「I」(两者不可区分)。
配置来源
Config.id_eff / id_dur / id_amp / id_prob 四个 HashMap<Integer,Integer> 在
postInit 由 Config.idConfig(effects.cfg) 填充(SuperTic.java:52)。
详见 配置项。