實踐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()
來獲取射箭者實體。
投擲物手榴彈
未完待續......