/*******************************************************************************
* AbyssalCraft
* Copyright (c) 2012 - 2017 Shinoow.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v3
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl-3.0.txt
*
* Contributors:
* Shinoow - implementation
******************************************************************************/
package com.shinoow.abyssalcraft.common.entity;
import java.util.List;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.IEntityLivingData;
import net.minecraft.entity.monster.EntityEnderman;
import net.minecraft.entity.monster.EntityZombie;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.init.Items;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.ItemStack;
import net.minecraft.network.play.server.SPacketChangeGameState;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.World;
import com.shinoow.abyssalcraft.api.AbyssalCraftAPI;
import com.shinoow.abyssalcraft.api.entity.EntityUtil;
public class EntityCoraliumArrow extends EntityArrow {
private int xTile = -1;
private int yTile = -1;
private int zTile = -1;
private Block inTile;
private int inData;
private boolean inGround;
private int ticksInGround;
private int ticksInAir;
private double damage = 2.0D;
/** The amount of knockback an arrow applies when it hits a mob. */
private int knockbackStrength;
public EntityCoraliumArrow(World par1World,
EntityLivingBase par2EntityLivingBase) {
super(par1World, par2EntityLivingBase);
}
public EntityCoraliumArrow(World par1World, double par2, double par4,
double par6) {
super(par1World, par2, par4, par6);
}
public EntityCoraliumArrow(World par1World) {
super(par1World);
}
@Override
public void onUpdate()
{
super.onUpdate();
if (prevRotationPitch == 0.0F && prevRotationYaw == 0.0F)
{
float f = MathHelper.sqrt(motionX * motionX + motionZ * motionZ);
prevRotationYaw = rotationYaw = (float)(MathHelper.atan2(motionX, motionZ) * 180.0D / Math.PI);
prevRotationPitch = rotationPitch = (float)(MathHelper.atan2(motionY, f) * 180.0D / Math.PI);
}
BlockPos blockpos = new BlockPos(xTile, yTile, zTile);
IBlockState iblockstate = world.getBlockState(blockpos);
Block block = iblockstate.getBlock();
if (block.getMaterial(iblockstate) != Material.AIR)
{
// block.setBlockBoundsBasedOnState(worldObj, blockpos);
AxisAlignedBB axisalignedbb = block.getBoundingBox(iblockstate, world, blockpos);
if (axisalignedbb != null && axisalignedbb.isVecInside(new Vec3d(posX, posY, posZ)))
inGround = true;
}
if (arrowShake > 0)
--arrowShake;
if (inGround)
{
int j = block.getMetaFromState(iblockstate);
if (block == inTile && j == inData)
{
++ticksInGround;
if (ticksInGround >= 1200)
setDead();
}
else
{
inGround = false;
motionX *= rand.nextFloat() * 0.2F;
motionY *= rand.nextFloat() * 0.2F;
motionZ *= rand.nextFloat() * 0.2F;
ticksInGround = 0;
ticksInAir = 0;
}
}
else
{
++ticksInAir;
Vec3d vec31 = new Vec3d(posX, posY, posZ);
Vec3d vec3 = new Vec3d(posX + motionX, posY + motionY, posZ + motionZ);
RayTraceResult movingobjectposition = world.rayTraceBlocks(vec31, vec3, false, true, false);
vec31 = new Vec3d(posX, posY, posZ);
vec3 = new Vec3d(posX + motionX, posY + motionY, posZ + motionZ);
if (movingobjectposition != null)
vec3 = new Vec3d(movingobjectposition.hitVec.xCoord, movingobjectposition.hitVec.yCoord, movingobjectposition.hitVec.zCoord);
Entity entity = null;
List<Entity> list = world.getEntitiesWithinAABBExcludingEntity(this, getEntityBoundingBox().addCoord(motionX, motionY, motionZ).expand(1.0D, 1.0D, 1.0D));
double d0 = 0.0D;
for (int i = 0; i < list.size(); ++i)
{
Entity entity1 = list.get(i);
if (entity1.canBeCollidedWith() && (entity1 != shootingEntity || ticksInAir >= 5))
{
float f1 = 0.3F;
AxisAlignedBB axisalignedbb1 = entity1.getEntityBoundingBox().expand(f1, f1, f1);
RayTraceResult movingobjectposition1 = axisalignedbb1.calculateIntercept(vec31, vec3);
if (movingobjectposition1 != null)
{
double d1 = vec31.squareDistanceTo(movingobjectposition1.hitVec);
if (d1 < d0 || d0 == 0.0D)
{
entity = entity1;
d0 = d1;
}
}
}
}
if (entity != null)
movingobjectposition = new RayTraceResult(entity);
if (movingobjectposition != null && movingobjectposition.entityHit != null && movingobjectposition.entityHit instanceof EntityPlayer)
{
EntityPlayer entityplayer = (EntityPlayer)movingobjectposition.entityHit;
if (entityplayer.capabilities.disableDamage || shootingEntity instanceof EntityPlayer && !((EntityPlayer)shootingEntity).canAttackPlayer(entityplayer))
movingobjectposition = null;
}
if (movingobjectposition != null)
if (movingobjectposition.entityHit != null)
{
float f2 = MathHelper.sqrt(motionX * motionX + motionY * motionY + motionZ * motionZ);
int l = MathHelper.ceil(f2 * damage);
if (getIsCritical())
l += rand.nextInt(l / 2 + 2);
DamageSource damagesource;
if (shootingEntity == null)
damagesource = DamageSource.causeArrowDamage(this, this);
else
damagesource = DamageSource.causeArrowDamage(this, shootingEntity);
if (isBurning() && !(movingobjectposition.entityHit instanceof EntityEnderman))
movingobjectposition.entityHit.setFire(5);
if (movingobjectposition.entityHit.attackEntityFrom(damagesource, l))
{
if (movingobjectposition.entityHit instanceof EntityLivingBase)
{
EntityLivingBase entitylivingbase = (EntityLivingBase)movingobjectposition.entityHit;
if(EntityUtil.isEntityCoralium(entitylivingbase)){}
else entitylivingbase.addPotionEffect(new PotionEffect(AbyssalCraftAPI.coralium_plague, 100));
if (!world.isRemote)
entitylivingbase.setArrowCountInEntity(entitylivingbase.getArrowCountInEntity() + 1);
if(entitylivingbase.isDead && entitylivingbase instanceof EntityZombie){
EntityDepthsGhoul ghoul = new EntityDepthsGhoul(entitylivingbase.world);
if(entitylivingbase.world.getDifficulty() == EnumDifficulty.HARD && entitylivingbase.world.rand.nextBoolean()
|| entitylivingbase.world.rand.nextInt(8) == 0) {
ghoul.copyLocationAndAnglesFrom(entitylivingbase);
ghoul.onInitialSpawn(world.getDifficultyForLocation(movingobjectposition.getBlockPos()), (IEntityLivingData)null);
if(entitylivingbase.isChild())
ghoul.setChild(true);
ghoul.setGhoulType(0);
entitylivingbase.world.removeEntity(entitylivingbase);
entitylivingbase.world.spawnEntity(ghoul);
}
}
if (!world.isRemote)
entitylivingbase.setArrowCountInEntity(entitylivingbase.getArrowCountInEntity() + 1);
if (knockbackStrength > 0)
{
float f7 = MathHelper.sqrt(motionX * motionX + motionZ * motionZ);
if (f7 > 0.0F)
movingobjectposition.entityHit.addVelocity(motionX * knockbackStrength * 0.6000000238418579D / f7, 0.1D, motionZ * knockbackStrength * 0.6000000238418579D / f7);
}
if (shootingEntity instanceof EntityLivingBase)
{
EnchantmentHelper.applyThornEnchantments(entitylivingbase, shootingEntity);
EnchantmentHelper.applyArthropodEnchantments((EntityLivingBase)shootingEntity, entitylivingbase);
}
if (shootingEntity != null && movingobjectposition.entityHit != shootingEntity && movingobjectposition.entityHit instanceof EntityPlayer && shootingEntity instanceof EntityPlayerMP)
((EntityPlayerMP)shootingEntity).connection.sendPacket(new SPacketChangeGameState(6, 0.0F));
}
playSound(SoundEvents.ENTITY_ARROW_HIT_PLAYER, 1.0F, 1.2F / (rand.nextFloat() * 0.2F + 0.9F));
if (!(movingobjectposition.entityHit instanceof EntityEnderman))
setDead();
}
else
{
motionX *= -0.10000000149011612D;
motionY *= -0.10000000149011612D;
motionZ *= -0.10000000149011612D;
rotationYaw += 180.0F;
prevRotationYaw += 180.0F;
ticksInAir = 0;
}
}
else
{
BlockPos blockpos1 = movingobjectposition.getBlockPos();
xTile = blockpos1.getX();
yTile = blockpos1.getY();
zTile = blockpos1.getZ();
IBlockState iblockstate1 = world.getBlockState(blockpos1);
inTile = iblockstate1.getBlock();
inData = inTile.getMetaFromState(iblockstate1);
motionX = (float)(movingobjectposition.hitVec.xCoord - posX);
motionY = (float)(movingobjectposition.hitVec.yCoord - posY);
motionZ = (float)(movingobjectposition.hitVec.zCoord - posZ);
float f5 = MathHelper.sqrt(motionX * motionX + motionY * motionY + motionZ * motionZ);
posX -= motionX / f5 * 0.05000000074505806D;
posY -= motionY / f5 * 0.05000000074505806D;
posZ -= motionZ / f5 * 0.05000000074505806D;
playSound(SoundEvents.ENTITY_ARROW_HIT, 1.0F, 1.2F / (rand.nextFloat() * 0.2F + 0.9F));
inGround = true;
arrowShake = 7;
setIsCritical(false);
if (inTile.getMaterial(iblockstate1) != Material.AIR)
inTile.onEntityCollidedWithBlock(world, blockpos1, iblockstate1, this);
}
if (getIsCritical())
for (int k = 0; k < 4; ++k)
world.spawnParticle(EnumParticleTypes.CRIT, posX + motionX * k / 4.0D, posY + motionY * k / 4.0D, posZ + motionZ * k / 4.0D, -motionX, -motionY + 0.2D, -motionZ, new int[0]);
posX += motionX;
posY += motionY;
posZ += motionZ;
float f3 = MathHelper.sqrt(motionX * motionX + motionZ * motionZ);
rotationYaw = (float)(MathHelper.atan2(motionX, motionZ) * 180.0D / Math.PI);
for (rotationPitch = (float)(MathHelper.atan2(motionY, f3) * 180.0D / Math.PI); rotationPitch - prevRotationPitch < -180.0F; prevRotationPitch -= 360.0F)
;
while (rotationPitch - prevRotationPitch >= 180.0F)
prevRotationPitch += 360.0F;
while (rotationYaw - prevRotationYaw < -180.0F)
prevRotationYaw -= 360.0F;
while (rotationYaw - prevRotationYaw >= 180.0F)
prevRotationYaw += 360.0F;
rotationPitch = prevRotationPitch + (rotationPitch - prevRotationPitch) * 0.2F;
rotationYaw = prevRotationYaw + (rotationYaw - prevRotationYaw) * 0.2F;
float f4 = 0.99F;
float f6 = 0.05F;
if (isInWater())
{
for (int i1 = 0; i1 < 4; ++i1)
{
float f8 = 0.25F;
world.spawnParticle(EnumParticleTypes.WATER_BUBBLE, posX - motionX * f8, posY - motionY * f8, posZ - motionZ * f8, motionX, motionY, motionZ, new int[0]);
}
f4 = 0.6F;
}
if (isWet())
extinguish();
motionX *= f4;
motionY *= f4;
motionZ *= f4;
motionY -= f6;
setPosition(posX, posY, posZ);
doBlockCollisions();
}
}
@Override
protected ItemStack getArrowStack() {
return new ItemStack(Items.ARROW);
}
}