package mhfc.net.common.entity.projectile; import java.util.List; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import mhfc.net.common.helper.DamageHelper; import mhfc.net.common.util.Utilities; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.IProjectile; import net.minecraft.entity.monster.EntityEnderman; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.projectile.EntityArrow; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.play.server.S2BPacketChangeGameState; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.DamageSource; import net.minecraft.util.MathHelper; import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.Vec3; import net.minecraft.world.World; public class EntityWyverniaArrow extends EntityArrow implements IProjectile{ protected int arrowHeadingX = -1; protected int arrowHeadingY = -1; protected int arrowHeadingZ = -1; protected Block block; protected Utilities util; public int arrowData; public boolean isitInGround; protected double defaultRenderDistanceWeight = 14.0D; protected int ticksisInGround; protected int ticksInAir; protected double damage = 12.0D; //Raise to third damage of the vanilla arrow. /** The amount of knockback an arrow applies when it hits a mob. */ private int knockbackStrength; public EntityWyverniaArrow(World world) { super(world); renderDistanceWeight = defaultRenderDistanceWeight; setSize(util.mhfc_vanilla_size_x, util.mhfc_vanilla_size_y); } public EntityWyverniaArrow(World world, double posX, double posY, double posZ) { super(world); renderDistanceWeight = defaultRenderDistanceWeight; setSize(util.mhfc_vanilla_size_x, util.mhfc_vanilla_size_y); setPosition(posX, posY, posZ); yOffset = 0.0F; } // i dont know exactly whats par1 and par2 atm. @Heltrato public EntityWyverniaArrow(World world, EntityLivingBase theShooter, EntityLivingBase target, float unknownA, float unknownB){ super(world); renderDistanceWeight = defaultRenderDistanceWeight; shootingEntity = theShooter; if(theShooter instanceof EntityPlayer){ canBePickedUp = 1; } posY = theShooter.posY + (double)theShooter.getEyeHeight() - 0.10000000149011612D; double d0 = target.posX - theShooter.posX; double d1 = target.boundingBox.minY + (double)(target.height / 3.0F) - posY; double d2 = target.posZ - theShooter.posZ; double d3 = (double)MathHelper.sqrt_double(d0 * d0 + d2 * d2); if (d3 >= 1.0E-7D) { float f2 = (float)(Math.atan2(d2, d0) * 180.0D / Math.PI) - 90.0F; float f3 = (float)(-(Math.atan2(d1, d3) * 180.0D / Math.PI)); double d4 = d0 / d3; double d5 = d2 / d3; setLocationAndAngles(theShooter.posX + d4, posY, theShooter.posZ + d5, f2, f3); yOffset = 0.0F; float f4 = (float)d3 * 0.2F; setThrowableHeading(d0, d1 + (double)f4, d2, unknownA, unknownB); } } public EntityWyverniaArrow(World world, EntityLivingBase theShooter, float unknownA) { super(world); renderDistanceWeight = defaultRenderDistanceWeight; shootingEntity = theShooter; if (theShooter instanceof EntityPlayer) { canBePickedUp = 1; } setSize(0.5F, 0.5F); setLocationAndAngles(theShooter.posX, theShooter.posY + (double)theShooter.getEyeHeight(), theShooter.posZ, theShooter.rotationYaw, theShooter.rotationPitch); posX -= (double)(MathHelper.cos(rotationYaw / 180.0F * (float)Math.PI) * 0.16F); posY -= 0.10000000149011612D; posZ -= (double)(MathHelper.sin(rotationYaw / 180.0F * (float)Math.PI) * 0.16F); setPosition(posX, posY, posZ); yOffset = 0.0F; motionX = (double)(-MathHelper.sin(rotationYaw / 180.0F * (float)Math.PI) * MathHelper.cos(rotationPitch / 180.0F * (float)Math.PI)); motionZ = (double)(MathHelper.cos(rotationYaw / 180.0F * (float)Math.PI) * MathHelper.cos(rotationPitch / 180.0F * (float)Math.PI)); motionY = (double)(-MathHelper.sin(rotationPitch / 180.0F * (float)Math.PI)); setThrowableHeading(motionX, motionY, motionZ, unknownA * 1.5F, 1.0F); } public void setKnockbackStrength(int p_70240_1_) { knockbackStrength = p_70240_1_; } public void setThrowableHeading(double par1, double par2, double par3, float par4, float par5) { float x2 = MathHelper.sqrt_double(par1 * par1 + par2 * par2 + par3 * par3); par1 /= (double)x2; par2 /= (double)x2; par3 /= (double)x2; par1 += rand.nextGaussian() * (double)(rand.nextBoolean() ? -1 : 1) * 0.007499999832361937D * (double)par5; par2 += rand.nextGaussian() * (double)(rand.nextBoolean() ? -1 : 1) * 0.007499999832361937D * (double)par5; par3 += rand.nextGaussian() * (double)(rand.nextBoolean() ? -1 : 1) * 0.007499999832361937D * (double)par5; par1 *= (double)par4; par2 *= (double)par4; par3 *= (double)par4; motionX = par1; motionY = par2; motionZ = par3; float x3 = MathHelper.sqrt_double(par1 * par1 + par3 * par3); prevRotationYaw = rotationYaw = (float)(Math.atan2(par1, par3) * 180.0D / Math.PI); prevRotationPitch = rotationPitch = (float)(Math.atan2(par2, (double)x3) * 180.0D / Math.PI); ticksisInGround = 0; } public double getDamage() { return damage; } @SideOnly(Side.CLIENT) public void setPositionAndRotation2(double par1, double par2, double par3, float float1, float float2, int par4) { setPosition(par1, par2, par3); setRotation(float1, float2); } public void setDamage(double damaX) { this.damage = damaX; } // diz is displacment. @SideOnly(Side.CLIENT) public void setVelocity(double dizX, double disY, double disZ) { motionX = dizX; motionY = disY; motionZ = disZ; if (prevRotationPitch == 0.0F && prevRotationYaw == 0.0F) { float y1 = MathHelper.sqrt_double(dizX * dizX + disZ * disZ); prevRotationYaw = rotationYaw = (float)(Math.atan2(dizX, disZ) * 180.0D / Math.PI); prevRotationPitch = rotationPitch = (float)(Math.atan2(disY, (double)y1) * 180.0D / Math.PI); prevRotationPitch = rotationPitch; prevRotationYaw = rotationYaw; setLocationAndAngles(posX, posY, posZ, rotationYaw, rotationPitch); ticksisInGround = 0; } } public void onUpdate() { super.onEntityUpdate(); if (prevRotationPitch == 0.0F && prevRotationYaw == 0.0F) { float f = MathHelper.sqrt_double(motionX * motionX + motionZ * motionZ); prevRotationYaw = rotationYaw = (float)(Math.atan2(motionX, motionZ) * 180.0D / Math.PI); prevRotationPitch = rotationPitch = (float)(Math.atan2(motionY, (double)f) * 180.0D / Math.PI); } Block blockz = worldObj.getBlock(arrowHeadingX, arrowHeadingY, arrowHeadingZ); if (blockz.getMaterial() != Material.air) { blockz.setBlockBoundsBasedOnState(worldObj, arrowHeadingX, arrowHeadingY, arrowHeadingZ); AxisAlignedBB axisalignedbb = blockz.getCollisionBoundingBoxFromPool(worldObj, arrowHeadingX, arrowHeadingY, arrowHeadingZ); if (axisalignedbb != null && axisalignedbb.isVecInside(Vec3.createVectorHelper(posX, posY, posZ))) { isitInGround = true; } } if (arrowShake > 0) { --arrowShake; } if (isitInGround) { int j = worldObj.getBlockMetadata(arrowHeadingX, arrowHeadingY, arrowHeadingZ); if (block == blockz && j == arrowData) { ++ticksisInGround; if (ticksisInGround == 1200) { setDead(); } } else { isitInGround = false; motionX *= (double)(rand.nextFloat() * 0.2F); motionY *= (double)(rand.nextFloat() * 0.2F); motionZ *= (double)(rand.nextFloat() * 0.2F); ticksisInGround = 0; ticksInAir = 0; } } else { ++ticksInAir; Vec3 vec31 = Vec3.createVectorHelper(posX, posY, posZ); Vec3 vec3 = Vec3.createVectorHelper(posX + motionX, posY + motionY, posZ + motionZ); MovingObjectPosition movingobjectposition = worldObj.func_147447_a(vec31, vec3, false, true, false); vec31 = Vec3.createVectorHelper(posX, posY, posZ); vec3 = Vec3.createVectorHelper(posX + motionX, posY + motionY, posZ + motionZ); if (movingobjectposition != null) { vec3 = Vec3.createVectorHelper(movingobjectposition.hitVec.xCoord, movingobjectposition.hitVec.yCoord, movingobjectposition.hitVec.zCoord); } Entity entity = null; @SuppressWarnings("rawtypes") List list = worldObj.getEntitiesWithinAABBExcludingEntity(this, boundingBox.addCoord(motionX, motionY, motionZ).expand(1.0D, 1.0D, 1.0D)); double d0 = 0.0D; int i; float f1; for (i = 0; i < list.size(); ++i) { Entity entity1 = (Entity)list.get(i); if (entity1.canBeCollidedWith() && (entity1 != shootingEntity || ticksInAir >= 5)) { f1 = 0.3F; AxisAlignedBB axisalignedbb1 = entity1.boundingBox.expand((double)f1, (double)f1, (double)f1); MovingObjectPosition movingobjectposition1 = axisalignedbb1.calculateIntercept(vec31, vec3); if (movingobjectposition1 != null) { double d1 = vec31.distanceTo(movingobjectposition1.hitVec); if (d1 < d0 || d0 == 0.0D) { entity = entity1; d0 = d1; } } } } if (entity != null) { movingobjectposition = new MovingObjectPosition(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; } } float f2; float f4; if (movingobjectposition != null) { if (movingobjectposition.entityHit != null) { f2 = MathHelper.sqrt_double(motionX * motionX + motionY * motionY + motionZ * motionZ); int k = MathHelper.ceiling_double_int((double)f2 * damage); if (getIsCritical()) { k += rand.nextInt(k / 2 + 2); } DamageSource damagesource = null; if (shootingEntity == null) { damagesource = DamageHelper.causeWyverniaArrow(this, this); } else { damagesource = DamageHelper.causeWyverniaArrow(this, shootingEntity); } if (isBurning() && !(movingobjectposition.entityHit instanceof EntityEnderman)) { movingobjectposition.entityHit.setFire(5); } if (movingobjectposition.entityHit.attackEntityFrom(damagesource, (float)k)) { if (movingobjectposition.entityHit instanceof EntityLivingBase) { EntityLivingBase entitylivingbase = (EntityLivingBase)movingobjectposition.entityHit; if (!worldObj.isRemote) { entitylivingbase.setArrowCountInEntity(entitylivingbase.getArrowCountInEntity() + 1); } if (knockbackStrength > 0) { f4 = MathHelper.sqrt_double(motionX * motionX + motionZ * motionZ); if (f4 > 0.0F) { movingobjectposition.entityHit.addVelocity(motionX * (double)knockbackStrength * 0.6000000238418579D / (double)f4, 0.1D, motionZ * (double)knockbackStrength * 0.6000000238418579D / (double)f4); } } if (shootingEntity != null && shootingEntity instanceof EntityLivingBase) { EnchantmentHelper.func_151384_a(entitylivingbase, shootingEntity); EnchantmentHelper.func_151385_b((EntityLivingBase)shootingEntity, entitylivingbase); } if (shootingEntity != null && movingobjectposition.entityHit != shootingEntity && movingobjectposition.entityHit instanceof EntityPlayer && shootingEntity instanceof EntityPlayerMP) { ((EntityPlayerMP)shootingEntity).playerNetServerHandler.sendPacket(new S2BPacketChangeGameState(6, 0.0F)); } } playSound("random.bowhit", 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 { arrowHeadingX = movingobjectposition.blockX; arrowHeadingY = movingobjectposition.blockY; arrowHeadingZ = movingobjectposition.blockZ; block = worldObj.getBlock(arrowHeadingX, arrowHeadingY, arrowHeadingZ); arrowData = worldObj.getBlockMetadata(arrowHeadingX, arrowHeadingY, arrowHeadingZ); motionX = (double)((float)(movingobjectposition.hitVec.xCoord - posX)); motionY = (double)((float)(movingobjectposition.hitVec.yCoord - posY)); motionZ = (double)((float)(movingobjectposition.hitVec.zCoord - posZ)); f2 = MathHelper.sqrt_double(motionX * motionX + motionY * motionY + motionZ * motionZ); posX -= motionX / (double)f2 * 0.05000000074505806D; posY -= motionY / (double)f2 * 0.05000000074505806D; posZ -= motionZ / (double)f2 * 0.05000000074505806D; playSound("random.bowhit", 1.0F, 1.2F / (rand.nextFloat() * 0.2F + 0.9F)); isitInGround = true; arrowShake = 7; setIsCritical(false); if (block.getMaterial() != Material.air) { block.onEntityCollidedWithBlock(worldObj, arrowHeadingX, arrowHeadingY, arrowHeadingZ, this); } } } if (getIsCritical()) { for (i = 0; i < 4; ++i) { worldObj.spawnParticle("crit", posX + motionX * (double)i / 4.0D, posY + motionY * (double)i / 4.0D, posZ + motionZ * (double)i / 4.0D, -motionX, -motionY + 0.2D, -motionZ); } } posX += motionX; posY += motionY; posZ += motionZ; f2 = MathHelper.sqrt_double(motionX * motionX + motionZ * motionZ); rotationYaw = (float)(Math.atan2(motionX, motionZ) * 180.0D / Math.PI); for (rotationPitch = (float)(Math.atan2(motionY, (double)f2) * 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 f3 = 0.99F; f1 = 0.05F; if (isInWater()) { for (int l = 0; l < 4; ++l) { f4 = 0.25F; worldObj.spawnParticle("bubble", posX - motionX * (double)f4, posY - motionY * (double)f4, posZ - motionZ * (double)f4, motionX, motionY, motionZ); } f3 = 0.8F; } if (isWet()) { extinguish(); } motionX *= (double)f3; motionY *= (double)f3; motionZ *= (double)f3; motionY -= (double)f1; setPosition(posX, posY, posZ); func_145775_I(); } } @Override protected void entityInit() { dataWatcher.addObject(16, Byte.valueOf((byte) 0)); dataWatcher.addObject(17, ""); } @Override public void writeEntityToNBT(NBTTagCompound writeNBT) { writeNBT.setShort("XTile", (short)arrowHeadingX); writeNBT.setShort("YTile", (short)arrowHeadingY); writeNBT.setShort("ZTile", (short)arrowHeadingZ); writeNBT.setShort("Life", (short)ticksisInGround); writeNBT.setByte("InTile", (byte)Block.getIdFromBlock(block)); writeNBT.setByte("InData", (byte)arrowData); writeNBT.setByte("Shake", (byte)arrowShake); writeNBT.setByte("InGround", (byte)(isitInGround ? 1 : 0)); writeNBT.setByte("Pickup", (byte)canBePickedUp); writeNBT.setDouble("Damage", damage); } @Override public void readEntityFromNBT(NBTTagCompound p_70037_1_) { arrowHeadingX = p_70037_1_.getShort("XTile"); arrowHeadingY = p_70037_1_.getShort("YTile"); arrowHeadingZ = p_70037_1_.getShort("ZTile"); ticksisInGround = p_70037_1_.getShort("Life"); block = Block.getBlockById(p_70037_1_.getByte("InTile") & 255); arrowData = p_70037_1_.getByte("InData") & 255; arrowShake = p_70037_1_.getByte("Shake") & 255; isitInGround = p_70037_1_.getByte("InGround") == 1; if (p_70037_1_.hasKey("Damage", 99)) { damage = p_70037_1_.getDouble("Damage"); } if (p_70037_1_.hasKey("Pickup", 99)) { canBePickedUp = p_70037_1_.getByte("Pickup"); } else if (p_70037_1_.hasKey("Player", 99)) { canBePickedUp = p_70037_1_.getBoolean("Player") ? 1 : 0; } } public boolean getIsCritical() { byte b0 = dataWatcher.getWatchableObjectByte(16); return (b0 & 1) != 0; } public void setIsCritical(boolean istrue) { byte b0 = dataWatcher.getWatchableObjectByte(16); if (istrue) { dataWatcher.updateObject(16, Byte.valueOf((byte)(b0 | 1))); } else { dataWatcher.updateObject(16, Byte.valueOf((byte)(b0 & -2))); } } }