等离子球

基本信息

属性 值
实现类 com.gtnewhorizons.gravisuiteneo.common.EntityPlasmaBallMKII
父类 gravisuite.EntityPlasmaBall(父模组 GraviSuite)
实体 ID 由父模组的 registerEntity 分配,见下方「实体注册」
基础伤害 PLASMA_DAMAGE 100.0F(EntityPlasmaBallMKII.java:34)
产出者 等离子炮

⚠️ 本条目只覆盖本 mod 覆写与新增的部分。追踪、碰撞、渲染的主体逻辑在父类 gravisuite.EntityPlasmaBall 中,父模组不在本 wiki 收录范围。

实体注册

本仓库没有任何 EntityRegistry.registerModEntity / registerGlobalEntityID 调用。注册是通过 Mixin 借用父模组的注册流程完成的:

@ModifyConstant(constant = @Constant(classValue = EntityPlasmaBall.class),
                method = "preInit", remap = false)                    // MixinGraviSuite_General.java:102
private Class<?> gravisuiteneo$getEntityPlasmaBallClass(Class<?> original) {
    return EntityPlasmaBallMKII.class;
}

父模组 GraviSuite.preInit 调用 registerEntity(EntityPlasmaBall.class, ...) 时,这个 @ModifyConstant 把常量替换成本类,于是实体 ID 由父模组的 registerEntity 分配,注册名也是父模组那一套(该方法的 slice 见 MixinGraviSuite_General.java:88-97)。

运行时生成方式有两种,都是直接 new + spawnEntityInWorld:

调用点 场景
items/ItemPlasmaLauncher.java:94、:98 等离子炮 开火
mixins/MixinItemRelocator.java:53 父模组传送器产生的等离子球(构造器带 TeleportPoint)

因此本实体沿用父模组的实体 ID 与刷怪/追踪配置,不占用本 mod 自己的 ID 段。

三个构造路径

构造器 用途 关键设置
(World, EntityPlasmaBall, float) 爆炸阶段(:39-50) entityType = 3;maxRange = 512.0;speedPerTick = 1.0;motion 三轴清零;位置复制自原球;finalTicksForDestruction = ticksExisted + 10
(World, EntityLivingBase, float, byte) 发射阶段(:55-64) dataWatcher[29] = charge;maxRange = 512.0;speedPerTick = 1.33;entityType == 2 时再 changeEntitySpeed(3.0F)
(World, EntityLivingBase, TeleportPoint, byte) 传送点变体(:83-85) 直接透传给父类
(World) 反射/反序列化用(:87-89) 直接透传给父类

changeEntitySpeed(3.0F)(:66-81)把 motion 向量归一化后再乘 3.0,并把父类的 speedPerTick 也乘 3.0 —— 即炮弹的初速是基础值的 3 × 1.33。

⚠️ changeEntitySpeed 未做 magnitude == 0 判零(:68-70),在 motion 为零向量时会除零得到 NaN。

生命周期

onUpdate(:99-105)在服务端额外加一条销毁条件:

if (!worldObj.isRemote && finalTicksForDestruction > -1
        && ticksExisted >= finalTicksForDestruction) setDead();

finalTicksForDestruction 初值 -1(:37),只有「爆炸阶段」构造器会设为 ticksExisted + 10(:42)——即爆炸视觉球存活 10 tick 后自毁。发射阶段的球不受此限制,由父类按 maxRange = 512 控制。

伤害与范围

onImpact(:129-)仅在 actionType == 2(炮弹)时进入伤害逻辑(:135);爆炸球(actionType == 3)直接 return(:130-132)。

命中半径

getImpactRadius(charge) = 6.0 * charge          // :123-126
tImpactRadius = clamp_double(getImpactRadius(charge), 1.0, 15.0)   // :139
  • 公式基准:效率 100% 时半径 6(源码注释:“Nominal radius for 100% plasma is 6; That’s a 12x12x12 cube”,:124)
  • 实际钳制到 [1.0, 15.0](:139)。源码 :137 的注释写「Cap the radius at 10, that’s 30x30x30」,但代码写的是 15.0 而非 10.0 —— 注释与实现不一致
  • 伤害系数 charge 来自炮的 Math.min(100.0F, efficiency / 100),故半径最大为 6 × 100 = 600,被钳到 15

范围选取

getEntitiesWithinAABB(EntityLivingBase.class, ...)(:144-152 命中实体 / :154-162 命中方块)取以命中点为中心、半边长 tImpactRadius 的立方 AABB —— 因此是立方体而非球体:半径 15 实际覆盖 30×30×30(与 :137 注释一致)。

伤害结算

tFinalDamage = this.charge * PLASMA_DAMAGE;   // :165,即 charge × 100.0
charge 单体伤害 AABB 半径
1(效率 100%) 100 6
2 200 12
10(效率 1000%,但炮侧封顶 100) 1000 15(钳制)
100(炮侧上限) 10000 15(钳制)

伤害源为 DamageSources.causePlayerPlazmaDamage(ownerEntity)(:178),属主取自 getOwnerEntity()(:142)。

地形破坏

tTerrainDamage = this.charge >= 2(:140)。为真时 worldObj.createExplosion(null, blockX, blockY, blockZ, this.charge, true)(:168)——强度就是 charge,且点燃方块(最后一个参数 true)。

⚠️ 即 charge < 2(即等离子效率 < 200%)时不破坏地形,charge >= 2 时按 charge 强度炸方块。

成就触发

onImpact 里两个分支直接触发成就(需 ownerEntity 非 null):

条件 成就 源码
累计伤害 tDamageDealt > 9000 OVER9000(gravisuite.itsover9000) :181-183
致死实体数 tEntitiesHitDeadly > 100 ULTRAKILL(gravisuite.ultrakill) :184-186

两者都是 成就树 上以 PLASMAGUN 为前置的 special 成就。注意判定用严格大于(>),恰好 9000 或恰好 100 不触发。

NBT

键 类型 源码
charge float writeToNBT :110,readFromNBT :116

另有 dataWatcher 索引 29 存 charge(entityInit :92-96,getCharge :120),setObjectWatched(29) 开启同步。

声音

命中时在服务端播放 gravisuiteneo:plasmaImpact,音量 1.25F,音高 1.0F(:190-196)。开火声音 plasmaFired 挂在炮上,见 等离子炮。

渲染

渲染由 mixins/MixinRenderPlasmaBall 注入父类渲染器,仅客户端加载(GraviSuiteNeoMixins.java:51)。