Minecraft 1.12.2 Mod开发笔记——实践1:给武器带上爆炸的附魔

总目录:Minecraft 1.12.2 开发笔记

实践1:爆炸弓/引爆剑/手榴弹

显然,Minecraft中的TNT并不能满足我们随意轰炸的欲望

  • 附魔种类判断
  • 攻击/被攻击事件
  • 实现爆炸

我们来实现之前的引爆附魔效果,效果图如下

有关攻击的事件

  • AttackEntityEvent 玩家攻击实体时触发,显然先于下面的 LivingAttackEvent 触发
  • LivingAttackEvent 存活的实体被攻击时触发
  • LivingSetAttackTargetEvent 生物设置其攻击目标时触发,这里的生物应该指的就是可主动攻击的生物,不包括玩家。比如僵尸看到村民开始追击。

有关弓箭的事件

  • ArrowNockEvent 开始拉弓时触发
  • ArrowLooseEvent 松开弓时触发,无论是否射出箭
  • ProjectileImpactEvent.Arrow 弓箭落地时触发,实际是关于射出的弓箭实体的事件

可以看到,如果是引爆的近程武器,我们可以使用 AttackEntityEvent 或 LivingAttackEvent 来实现;如果是弓这个远程武器,我们可以用 LivingAttackEvent 或 ProjectileImpactEvent.Arrow 来实现。注意箭/火焰弹等远程武器不会触发 AttackEntityEvent。

爆炸

Minecraft 中的爆炸使用 World 对象的

createExplosion(Entity entityIn, x, y, z, strength, boolean isSmoking) 实现。

  • entityIn 爆炸源,可以为 null,不参与爆炸伤害判定
  • x,y,z double,坐标
  • strength float,爆炸威力/范围,普通苦力怕为3.0,TNT为4.0或者更大一点,末影水晶为6.0,所以说。。
  • isSmoking 是否破坏地形和造成伤害

此外,World 对象还有一个

newExplosion(Entity entityIn, x, y, z, strength, boolean isFlaming, boolean isSmoking)

方法,比上面的多了一个 isFlaming 参数,即爆炸是否产生火。而上面的那个方法即为 isFlaming=false 的情况。

如何判断附魔

EnchantmentHelper.getEnchantmentLevel(Enchantment enchID, ItemStack stack)
  • enchID 需要检测的附魔对象
  • stack 需要检测的物品,可以从player对象上拿到
  • return 返回附魔等级,若无返回0

通过 AttackEntityEvent 事件实现引爆在近战武器上的效果

@SubscribeEvent
public static void onPlayerAttack(AttackEntityEvent event) {
    Entity e = event.getTarget();
    EntityPlayer player = event.getEntityPlayer();
    if (!player.world.isRemote) {
        if (EnchantmentHelper.getEnchantmentLevel(ElementLoader.ignite, player.getHeldItemMainhand()) == 1) {
            player.world.createExplosion(player, e.posX, e.posY, e.posZ, 3.0f, true);
        }
    }
}
  • player.world.isRemote 用于判断是哪个 Side,通常我们只需要一个 Side 去处理即可,比如服务器端。暂时还没有弄明白,但很多事件都是这么写的
  • player.getHeldItemMainhand() 用于获取玩家主手的物品,也可以探索player的其他方法
  • 这里我们设置玩家自身是爆炸源,要不然你想让玩家炸死么

通过 ProjectileImpactEvent.Arrow 事件实现爆炸弓

@SubscribeEvent
public static void onArrowAttack(ProjectileImpactEvent.Arrow event) {
    EntityArrow e = event.getArrow();
    if (!e.world.isRemote) {
        if (e.shootingEntity instanceof EntityPlayer) {
            EntityPlayer player = (EntityPlayer) e.shootingEntity;
            if (EnchantmentHelper.getEnchantmentLevel(ElementLoader.ignite, player.getHeldItemMainhand()) != 0) {
                e.world.createExplosion(null, e.posX, e.posY, e.posZ, 10.0f, true);
            }
        }
    }
}
  • 基本大同小异,注意不同的对象有不同的方法和属性

通过 LivingAttackEvent 事件

一些伤害类型可以直接使用 event.getSource() 获取伤害类型并与 DamageSource 中的常量进行比较,有些没有常量的伤害类型可以使用 event.getSource().getDamageType() 来获取伤害类型名称进行比较,名称可从 DamageSource 类中查看。其中远程武器比如弓箭等被定义为间接伤害,可以用 getTrueSource() 来获取射箭者实体。

投掷物手榴弹

未完待续......

posted @ 2020-03-05 18:09  0.0~~  阅读(2366)  评论(1编辑  收藏  举报