/** Copyright (C) <2015> <coolAlias> This file is part of coolAlias' Zelda Sword Skills Minecraft Mod; as such, you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package zeldaswordskills.entity.projectile; import net.minecraft.block.material.Material; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.BlockPos; import net.minecraft.util.DamageSource; import net.minecraft.util.EntityDamageSourceIndirect; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.MovingObjectPosition; import net.minecraft.world.World; import zeldaswordskills.api.entity.BombType; import zeldaswordskills.api.entity.CustomExplosion; import zeldaswordskills.api.entity.IEntityBomb; import zeldaswordskills.item.ItemBomb; import zeldaswordskills.ref.Config; public class EntityArrowBomb extends EntityArrowCustom implements IEntityBomb { /** Watchable object index for bomb's type */ private static final int BOMBTYPE_DATAWATCHER_INDEX = 25; /** Uses ItemBomb's radius if this value is zero */ private float radius = 0.0F; /** Whether this bomb is capable of destroying blocks */ private boolean canGrief = true; public EntityArrowBomb(World world) { super(world); } public EntityArrowBomb(World world, double x, double y, double z) { super(world, x, y, z); } public EntityArrowBomb(World world, EntityLivingBase shooter, float velocity) { super(world, shooter, velocity); } public EntityArrowBomb(World world, EntityLivingBase shooter, EntityLivingBase target, float velocity, float wobble) { super(world, shooter, target, velocity, wobble); } @Override public void entityInit() { super.entityInit(); dataWatcher.addObject(BOMBTYPE_DATAWATCHER_INDEX, BombType.BOMB_STANDARD.ordinal()); } @Override protected DamageSource getDamageSource(Entity entity) { return new EntityDamageSourceIndirect("bomb arrow", this, shootingEntity).setProjectile().setExplosion(); } /** * Sets this bomb's radius */ public EntityArrowBomb setRadius(float radius) { this.radius = radius; return this; } // TODO @Override public boolean canGriefAdventureMode() { return Config.canGriefAdventure(); } /** * Sets this bomb to not destroy blocks, but still cause damage */ public EntityArrowBomb setNoGrief() { canGrief = false; return this; } @Override public BombType getType() { return BombType.values()[dataWatcher.getWatchableObjectInt(BOMBTYPE_DATAWATCHER_INDEX)]; } /** * Sets this bomb's {@link BombType} */ public EntityArrowBomb setType(BombType type) { dataWatcher.updateObject(BOMBTYPE_DATAWATCHER_INDEX, type.ordinal()); return this; } @Override public float getMotionFactor() { return 1.0F; } @Override public float getDestructionFactor() { return 1.0F; } @Override public boolean hasPostExplosionEffect() { return false; } @Override protected float getVelocityFactor() { return 1.0F; } @Override protected float getGravityVelocity() { return 0.065F; } @Override protected EnumParticleTypes getParticle() { return EnumParticleTypes.SMOKE_NORMAL; } @Override protected boolean shouldSpawnParticles() { return true; } @Override public void onUpdate() { super.onUpdate(); if (worldObj.provider.getDimensionId() == -1 && ticksInAir > 0 && !worldObj.isRemote && (getType() == BombType.BOMB_STANDARD || getType() == BombType.BOMB_FLOWER)) { CustomExplosion.createExplosion(this, worldObj, posX, posY, posZ, (radius == 0.0F ? ItemBomb.getRadius(getType()) : radius), (float) getDamage(), canGrief); setDead(); } } @Override protected void onImpact(MovingObjectPosition mop) { Material material = worldObj.getBlockState(new BlockPos(this)).getBlock().getMaterial(); // func_147470_e is isBoundingBoxBurning boolean inFire = isBurning() || (material == Material.lava || material == Material.fire) || worldObj.isFlammableWithin(getEntityBoundingBox()); if (!isDud(inFire)) { if (!worldObj.isRemote) { CustomExplosion.createExplosion(this, worldObj, posX, posY, posZ, (radius == 0.0F ? ItemBomb.getRadius(getType()) : radius), (float) getDamage(), canGrief); setDead(); } } else { super.onImpact(mop); } } /** * Returns true if the bomb is a dud: in the water or a water bomb in the nether * @param inFire whether this bomb is in fire, lava, or currently burning */ private boolean isDud(boolean inFire) { switch(getType()) { case BOMB_WATER: return inFire || worldObj.provider.getDimensionId() == -1; default: return (worldObj.getBlockState(new BlockPos(this)).getBlock().getMaterial() == Material.water); } } @Override public void writeEntityToNBT(NBTTagCompound compound) { super.writeEntityToNBT(compound); compound.setInteger("arrowType", getType().ordinal()); compound.setFloat("bombRadius", radius); compound.setBoolean("canGrief", canGrief); } @Override public void readEntityFromNBT(NBTTagCompound compound) { super.readEntityFromNBT(compound); setType(BombType.values()[compound.getInteger("arrowType") % BombType.values().length]); radius = compound.getFloat("bombRadius"); canGrief = compound.getBoolean("canGrief"); } }