Hello, in my mod I have a gun, which shoots bullets which are entities, I want to be able to make an entity wield the gun and shoot it much like a skeleton uses a bow. I have this as my entity (ruthlessly copied from EntitySkeleton);
package uk.co.toomuchminecraft.sabermod;
import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.asm.SideOnly;
import java.util.Calendar;
import net.minecraft.src.AchievementList;
import net.minecraft.src.Block;
import net.minecraft.src.DamageSource;
import net.minecraft.src.Enchantment;
import net.minecraft.src.EnchantmentHelper;
import net.minecraft.src.Entity;
import net.minecraft.src.EntityAIArrowAttack;
import net.minecraft.src.EntityAIAttackOnCollide;
import net.minecraft.src.EntityAIHurtByTarget;
import net.minecraft.src.EntityAILookIdle;
import net.minecraft.src.EntityAINearestAttackableTarget;
import net.minecraft.src.EntityAISwimming;
import net.minecraft.src.EntityAIWander;
import net.minecraft.src.EntityAIWatchClosest;
import net.minecraft.src.EntityArrow;
import net.minecraft.src.EntityLiving;
import net.minecraft.src.EntityMob;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.EnumCreatureAttribute;
import net.minecraft.src.IRangedAttackMob;
import net.minecraft.src.Item;
import net.minecraft.src.ItemStack;
import net.minecraft.src.MathHelper;
import net.minecraft.src.NBTTagCompound;
import net.minecraft.src.World;
public class EntityStormTrooper extends EntityMob implements IRangedAttackMob
{
private EntityAIArrowAttack field_85037_d = new EntityAIArrowAttack(this, 0.25F, 60, 10.0F);
private EntityAIAttackOnCollide field_85038_e = new EntityAIAttackOnCollide(this, EntityPlayer.class, 0.31F, false);
public EntityStormTrooper(World par1World)
{
super(par1World);
this.texture = "/SaberMod/mobs/stormtrooper.png";
this.moveSpeed = 0.25F;
this.tasks.addTask(1, new EntityAISwimming(this));
this.tasks.addTask(5, new EntityAIWander(this, this.moveSpeed));
this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
this.tasks.addTask(6, new EntityAILookIdle(this));
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false));
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, 16.0F, 0, true));
if (par1World != null && !par1World.isRemote)
{
this.func_85036_m();
}
}
protected void entityInit()
{
super.entityInit();
this.dataWatcher.addObject(13, new Byte((byte)0));
}
/**
* Returns true if the newer Entity AI code should be run
*/
public boolean isAIEnabled()
{
return true;
}
public int getMaxHealth()
{
return 20;
}
/**
* Returns the sound this mob makes while it's alive.
*/
protected String getLivingSound()
{
return "sabermod.stormtrooper.stormtrooper";
}
/**
* Returns the sound this mob makes when it is hurt.
*/
protected String getHurtSound()
{
return "";
}
/**
* Returns the sound this mob makes on death.
*/
protected String getDeathSound()
{
return "";
}
/**
* Plays step sound at given x, y, z for the entity
*/
protected void playStepSound(int par1, int par2, int par3, int par4)
{
this.func_85030_a("mob.zombie.step", 0.15F, 1.0F);
}
/**
* Returns the amount of damage a mob should deal.
*/
public int getAttackStrength(Entity par1Entity)
{
return super.getAttackStrength(par1Entity);
}
/**
* Get this Entity's EnumCreatureAttribute
*/
public EnumCreatureAttribute getCreatureAttribute()
{
return EnumCreatureAttribute.UNDEFINED;
}
/**
* Returns the item ID for the item the mob drops on death.
*/
protected int getDropItemId()
{
return Item.ingotIron.shiftedIndex;
}
protected void dropRareDrop(int par1)
{
switch (this.rand.nextInt(3))
{
case 0:
this.dropItem(new ItemStack(SaberMod.blasterBattery, 1, 15).itemID, 1);
break;
case 1:
this.dropItem(new ItemStack(SaberMod.blasterBattery, 1, 0).itemID, 1);
break;
case 2:
this.dropItem(Item.beefRaw.shiftedIndex, 3);
}
}
@Override
protected void func_82164_bB()
{
super.func_82164_bB();
this.setCurrentItemOrArmor(0, new ItemStack(SaberMod.blaster));
}
/**
* Initialize this creature.
*/
public void initCreature()
{
if (this.rand.nextFloat() >= field_82181_as[this.worldObj.difficultySetting])
{
;
}
this.canPickUpLoot = false;
if (this.getCurrentItemOrArmor(4) == null)
{
Calendar var1 = this.worldObj.getCurrentDate();
if (var1.get(2) + 1 == 10 && var1.get(5) == 31 && this.rand.nextFloat() < 0.25F)
{
this.setCurrentItemOrArmor(4, new ItemStack(this.rand.nextFloat() < 0.1F ? Block.pumpkinLantern : Block.pumpkin));
this.equipmentDropChances[4] = 0.0F;
}
}
}
public void func_85036_m()
{
this.tasks.func_85156_a(this.field_85038_e);
this.tasks.func_85156_a(this.field_85037_d);
ItemStack var1 = this.getHeldItem();
if (var1 != null && var1.itemID == SaberMod.blaster.shiftedIndex)
{
this.tasks.addTask(4, this.field_85037_d);
}
else
{
this.tasks.addTask(4, this.field_85038_e);
}
}
/**
* Attack the specified entity using a ranged attack.
*/
public void attackEntityWithRangedAttack(EntityLiving par1EntityLiving)
{
EntityBlast var2 = new EntityBlast(this.worldObj, this);
int var3 = EnchantmentHelper.getEnchantmentLevel(Enchantment.power.effectId, this.getHeldItem());
int var4 = EnchantmentHelper.getEnchantmentLevel(Enchantment.punch.effectId, this.getHeldItem());
if (var3 > 0)
{
var2.setDamage(var2.getDamage() + (double)var3 * 0.5D + 0.5D);
}
if (var4 > 0)
{
var2.setKnockbackStrength(var4);
}
if (EnchantmentHelper.getEnchantmentLevel(Enchantment.flame.effectId, this.getHeldItem()) > 0)
{
var2.setFire(100);
}
this.func_85030_a("", 1.0F, 1.0F / (this.getRNG().nextFloat() * 0.4F + 0.8F));
this.worldObj.spawnEntityInWorld(var2);
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
{
super.readEntityFromNBT(par1NBTTagCompound);
this.func_85036_m();
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
{
super.writeEntityToNBT(par1NBTTagCompound);
}
/**
* Sets the held item, or an armor slot. Slot 0 is held item. Slot 1-4 is armor. Params: Item, slot
*/
public void setCurrentItemOrArmor(int par1, ItemStack par2ItemStack)
{
super.setCurrentItemOrArmor(par1, par2ItemStack);
if (!this.worldObj.isRemote && par1 == 0)
{
this.func_85036_m();
}
}
}
Which is meant to shoot the blaster, which class looks like this;
package uk.co.toomuchminecraft.sabermod;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.util.ArrayList;
import java.util.List;
import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.asm.SideOnly;
import cpw.mods.fml.common.network.PacketDispatcher;
import net.minecraft.src.CreativeTabs;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.Item;
import net.minecraft.src.ItemStack;
import net.minecraft.src.Packet250CustomPayload;
import net.minecraft.src.World;
public class SaberBlaster extends Item
{
public SaberBlaster(int par1)
{
super(par1);
this.iconIndex = 72;
this.bFull3D = true;
setCreativeTab(CreativeTabs.tabCombat);
this.maxStackSize = 1;
this.setMaxDamage(500);
}
@Override
public String getTextureFile()
{
return "/SaberMod/items.png";
}
/**
* Returns a slot index in main inventory containing a specific itemID
*/
private ItemStack getInventoryFirstItemStack(EntityPlayer par2EntityPlayer)
{
for (int var1 = 0; var1 < par2EntityPlayer.inventory.mainInventory.length; ++var1)
{
if (par2EntityPlayer.inventory.mainInventory[var1] != null && par2EntityPlayer.inventory.mainInventory[var1].itemID == SaberMod.blasterBattery.shiftedIndex)
{
if(par2EntityPlayer.inventory.getStackInSlot(var1).getItemDamage() > 0)
{
return par2EntityPlayer.inventory.getStackInSlot(var1);
}
}
}
return null;
}
private void getSoundToPlay(EntityPlayer par2EntityPlayer)
{
ItemStack stack = null;
for (int var1 = 0; var1 < par2EntityPlayer.inventory.mainInventory.length; ++var1)
{
if (par2EntityPlayer.inventory.mainInventory[var1] != null && par2EntityPlayer.inventory.mainInventory[var1].itemID == SaberMod.blasterBattery.shiftedIndex)
{
stack = par2EntityPlayer.inventory.getStackInSlot(var1);
}
}
if(stack != null)
{
if(stack.getItemDamage() > 0)
{
sendSoundPacket(4);
}
else
{
sendSoundPacket(3);
}
}
}
/**
* Called whenever this item is equipped and the right mouse button is pressed. Args: itemStack, world, entityPlayer
*/
public ItemStack onItemRightClick(ItemStack par1ItemStack, World par2World, EntityPlayer par3EntityPlayer)
{
if(getInventoryFirstItemStack(par3EntityPlayer) != null)
{
EntityBlast blast = new EntityBlast(par2World, par3EntityPlayer);
if (!par2World.isRemote)
{
par2World.spawnEntityInWorld(blast);
}
getSoundToPlay(par3EntityPlayer);
getInventoryFirstItemStack(par3EntityPlayer).setItemDamage(getInventoryFirstItemStack(par3EntityPlayer).getItemDamage() - 1);
}
return par1ItemStack;
}
@SideOnly(Side.CLIENT)
private void sendSoundPacket(int sound)
{
ByteArrayOutputStream bos = new ByteArrayOutputStream(4);
DataOutputStream outputStream = new DataOutputStream(bos);
try
{
outputStream.writeInt(sound);
}
catch (Exception ex)
{
ex.printStackTrace();
}
Packet250CustomPayload packet = new Packet250CustomPayload();
packet.channel = "SaberSound";
packet.data = bos.toByteArray();
packet.length = bos.size();
PacketDispatcher.sendPacketToServer(packet);
}
}
The Model;
package uk.co.toomuchminecraft.sabermod.client;
import uk.co.toomuchminecraft.sabermod.EntityStormTrooper;
import net.minecraft.src.Entity;
import net.minecraft.src.EntityLiving;
import net.minecraft.src.ModelRenderer;
import net.minecraft.src.ModelZombie;
import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.asm.SideOnly;
@SideOnly(Side.CLIENT)
public class ModelStormTrooper extends ModelZombie
{
public ModelStormTrooper()
{
this(0.0F);
}
public ModelStormTrooper(float par1)
{
super(par1, 0.0F, 64, 32);
}
/**
* Used for easily adding entity-dependent animations. The second and third float params here are the same second
* and third as in the setRotationAngles method.
*/
public void setLivingAnimations(EntityLiving par1EntityLiving, float par2, float par3, float par4)
{
this.aimedBow = true;
super.setLivingAnimations(par1EntityLiving, par2, par3, par4);
}
/**
* Sets the model's various rotation angles. For bipeds, par1 and par2 are used for animating the movement of arms
* and legs, where par1 represents the time(so that arms and legs swing back and forth) and par2 represents how
* "far" arms and legs can swing at most.
*/
public void setRotationAngles(float par1, float par2, float par3, float par4, float par5, float par6, Entity par7Entity)
{
super.setRotationAngles(par1, par2, par3, par4, par5, par6, par7Entity);
}
}
and the render are as so;
package uk.co.toomuchminecraft.sabermod.client;
import org.lwjgl.opengl.GL11;
import uk.co.toomuchminecraft.sabermod.EntityStormTrooper;
import net.minecraft.client.Minecraft;
import net.minecraft.src.Entity;
import net.minecraft.src.EntityLiving;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.FontRenderer;
import net.minecraft.src.ModelBase;
import net.minecraft.src.RenderLiving;
import net.minecraft.src.Tessellator;
public class RenderStormTrooper extends RenderLiving
{
public RenderStormTrooper(ModelBase modelbase, float f)
{
super(modelbase, f);
}
public void func_177_a(EntityStormTrooper entityRandom, double d, double d1, double d2,
float f, float f1)
{
super.doRenderLiving(entityRandom, d, d1, d2, f, f1);
}
public void doRenderLiving(EntityLiving entityliving, double d, double d1, double d2,
float f, float f1)
{
func_177_a((EntityStormTrooper)entityliving, d, d1, d2, f, f1);
}
public void doRender(Entity entity, double d, double d1, double d2,
float f, float f1)
{
func_177_a((EntityStormTrooper)entity, d, d1, d2, f, f1);
}
}
How can I make the blaster appear in the entities hand and for it to shoot the bullet;
package uk.co.toomuchminecraft.sabermod;
import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.asm.SideOnly;
import java.util.List;
import java.util.Random;
import net.minecraft.src.AxisAlignedBB;
import net.minecraft.src.Block;
import net.minecraft.src.DamageSource;
import net.minecraft.src.Entity;
import net.minecraft.src.EntityLiving;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.IProjectile;
import net.minecraft.src.ItemStack;
import net.minecraft.src.MathHelper;
import net.minecraft.src.MovingObjectPosition;
import net.minecraft.src.NBTTagCompound;
import net.minecraft.src.Vec3;
import net.minecraft.src.World;
public class EntityBlast extends Entity implements IProjectile
{
private int xTile = -1;
private int yTile = -1;
private int zTile = -1;
private int inTile = 0;
private int inData = 0;
private boolean inGround = false;
/** Seems to be some sort of timer for animating an arrow. */
public int arrowShake = 0;
/** The owner of this arrow. */
public Entity shootingEntity;
private int ticksInGround;
private int ticksInAir = 0;
private double damage = 2.0D;
/** The amount of knockback an arrow applies when it hits a mob. */
private int knockbackStrength;
public EntityBlast(World par1World)
{
super(par1World);
this.setSize(0.5F, 0.5F);
}
public EntityBlast(World par1World, double par2, double par4, double par6)
{
super(par1World);
this.setSize(0.5F, 0.5F);
this.setPosition(par2, par4, par6);
this.yOffset = 0.0F;
}
public EntityBlast(World par1World, EntityLiving par2EntityLiving, EntityLiving par3EntityLiving, float par4, float par5)
{
super(par1World);
this.shootingEntity = par2EntityLiving;
this.posY = par2EntityLiving.posY + (double)par2EntityLiving.getEyeHeight() - 0.10000000149011612D;
double var6 = par3EntityLiving.posX - par2EntityLiving.posX;
double var8 = par3EntityLiving.posY + (double)par3EntityLiving.getEyeHeight() - 0.699999988079071D - this.posY;
double var10 = par3EntityLiving.posZ - par2EntityLiving.posZ;
double var12 = (double)MathHelper.sqrt_double(var6 * var6 + var10 * var10);
if (var12 >= 1.0E-7D)
{
float var14 = (float)(Math.atan2(var10, var6) * 180.0D / Math.PI) - 90.0F;
float var15 = (float)(-(Math.atan2(var8, var12) * 180.0D / Math.PI));
double var16 = var6 / var12;
double var18 = var10 / var12;
this.setLocationAndAngles(par2EntityLiving.posX + var16, this.posY, par2EntityLiving.posZ + var18, var14, var15);
this.yOffset = 0.0F;
float var20 = (float)var12 * 0.2F;
this.setThrowableHeading(var6, var8 + (double)var20, var10, par4, par5);
}
}
public EntityBlast(World par1World, EntityLiving par2EntityLiving)
{
super(par1World);
Random rand = new Random();
this.shootingEntity = par2EntityLiving;
this.setSize(0.5F, 0.5F);
this.setLocationAndAngles(par2EntityLiving.posX, par2EntityLiving.posY + (double)par2EntityLiving.getEyeHeight(), par2EntityLiving.posZ, par2EntityLiving.rotationYaw, par2EntityLiving.rotationPitch);
this.posX -= (double)(MathHelper.cos(this.rotationYaw / 180.0F * (float)Math.PI) * 0.16F);
this.posY -= 0.10000000149011612D;
this.posZ -= (double)(MathHelper.sin(this.rotationYaw / 180.0F * (float)Math.PI) * 0.16F);
this.setPosition(this.posX, this.posY, this.posZ);
this.yOffset = 0.0F;
this.motionX = (double)(-MathHelper.sin(this.rotationYaw / ((rand.nextFloat() * 10) + 175.0F) * (float)Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float)Math.PI));
this.motionZ = (double)(MathHelper.cos(this.rotationYaw / ((rand.nextFloat() * 10) + 175.0F) * (float)Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float)Math.PI));
this.motionY = (double)(-MathHelper.sin(this.rotationPitch / ((rand.nextFloat() * 10) + 175.0F) * (float)Math.PI));
this.setThrowableHeading(this.motionX, this.motionY, this.motionZ, 20F * 1.5F, 1.0F);
}
protected void entityInit()
{
this.dataWatcher.addObject(16, Byte.valueOf((byte)0));
}
/**
* Similar to setArrowHeading, it's point the throwable entity to a x, y, z direction.
*/
public void setThrowableHeading(double par1, double par3, double par5, float par7, float par8)
{
float var9 = MathHelper.sqrt_double(par1 * par1 + par3 * par3 + par5 * par5);
par1 /= (double)var9;
par3 /= (double)var9;
par5 /= (double)var9;
par1 += this.rand.nextGaussian() * 0.007499999832361937D * (double)par8;
par3 += this.rand.nextGaussian() * 0.007499999832361937D * (double)par8;
par5 += this.rand.nextGaussian() * 0.007499999832361937D * (double)par8;
par1 *= (double)par7;
par3 *= (double)par7;
par5 *= (double)par7;
this.motionX = par1;
this.motionY = par3;
this.motionZ = par5;
float var10 = MathHelper.sqrt_double(par1 * par1 + par5 * par5);
this.prevRotationYaw = this.rotationYaw = (float)(Math.atan2(par1, par5) * 180.0D / Math.PI);
this.prevRotationPitch = this.rotationPitch = (float)(Math.atan2(par3, (double)var10) * 180.0D / Math.PI);
this.ticksInGround = 0;
}
@SideOnly(Side.CLIENT)
/**
* Sets the position and rotation. Only difference from the other one is no bounding on the rotation. Args: posX,
* posY, posZ, yaw, pitch
*/
public void setPositionAndRotation2(double par1, double par3, double par5, float par7, float par8, int par9)
{
this.setPosition(par1, par3, par5);
this.setRotation(par7, par8);
}
@SideOnly(Side.CLIENT)
/**
* Sets the velocity to the args. Args: x, y, z
*/
public void setVelocity(double par1, double par3, double par5)
{
this.motionX = par1;
this.motionY = par3;
this.motionZ = par5;
if (this.prevRotationPitch == 0.0F && this.prevRotationYaw == 0.0F)
{
float var7 = MathHelper.sqrt_double(par1 * par1 + par5 * par5);
this.prevRotationYaw = this.rotationYaw = (float)(Math.atan2(par1, par5) * 180.0D / Math.PI);
this.prevRotationPitch = this.rotationPitch = (float)(Math.atan2(par3, (double)var7) * 180.0D / Math.PI);
this.prevRotationPitch = this.rotationPitch;
this.prevRotationYaw = this.rotationYaw;
this.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, this.rotationPitch);
this.ticksInGround = 0;
}
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
super.onUpdate();
if(this.inGround)
{
this.setDead();
}
if (this.prevRotationPitch == 0.0F && this.prevRotationYaw == 0.0F)
{
float var1 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
this.prevRotationYaw = this.rotationYaw = (float)(Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI);
this.prevRotationPitch = this.rotationPitch = (float)(Math.atan2(this.motionY, (double)var1) * 180.0D / Math.PI);
}
int var16 = this.worldObj.getBlockId(this.xTile, this.yTile, this.zTile);
if (var16 > 0)
{
Block.blocksList[var16].setBlockBoundsBasedOnState(this.worldObj, this.xTile, this.yTile, this.zTile);
AxisAlignedBB var2 = Block.blocksList[var16].getCollisionBoundingBoxFromPool(this.worldObj, this.xTile, this.yTile, this.zTile);
if (var2 != null && var2.isVecInside(this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ)))
{
this.inGround = true;
}
}
if (this.arrowShake > 0)
{
--this.arrowShake;
}
if (this.inGround)
{
int var18 = this.worldObj.getBlockId(this.xTile, this.yTile, this.zTile);
int var19 = this.worldObj.getBlockMetadata(this.xTile, this.yTile, this.zTile);
if (var18 == this.inTile && var19 == this.inData)
{
++this.ticksInGround;
if (this.ticksInGround == 1200)
{
this.setDead();
}
}
else
{
this.inGround = false;
this.motionX *= (double)(this.rand.nextFloat() * 0.2F);
this.motionY *= (double)(this.rand.nextFloat() * 0.2F);
this.motionZ *= (double)(this.rand.nextFloat() * 0.2F);
this.ticksInGround = 0;
this.ticksInAir = 0;
}
}
else
{
++this.ticksInAir;
Vec3 var17 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ);
Vec3 var3 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);
MovingObjectPosition var4 = this.worldObj.rayTraceBlocks_do_do(var17, var3, false, true);
var17 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ);
var3 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);
if (var4 != null)
{
var3 = this.worldObj.getWorldVec3Pool().getVecFromPool(var4.hitVec.xCoord, var4.hitVec.yCoord, var4.hitVec.zCoord);
}
Entity var5 = null;
List var6 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox.addCoord(this.motionX, this.motionY, this.motionZ).expand(1.0D, 1.0D, 1.0D));
double var7 = 0.0D;
int var9;
float var11;
for (var9 = 0; var9 < var6.size(); ++var9)
{
Entity var10 = (Entity)var6.get(var9);
if (var10.canBeCollidedWith() && (var10 != this.shootingEntity || this.ticksInAir >= 5))
{
var11 = 0.3F;
AxisAlignedBB var12 = var10.boundingBox.expand((double)var11, (double)var11, (double)var11);
MovingObjectPosition var13 = var12.calculateIntercept(var17, var3);
if (var13 != null)
{
double var14 = var17.distanceTo(var13.hitVec);
if (var14 < var7 || var7 == 0.0D)
{
var5 = var10;
var7 = var14;
}
}
}
}
if (var5 != null)
{
var4 = new MovingObjectPosition(var5);
}
float var20;
if (var4 != null)
{
if (var4.entityHit != null)
{
var20 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionY * this.motionY + this.motionZ * this.motionZ);
int var23 = MathHelper.ceiling_double_int((double)var20 * this.damage);
if (this.getIsCritical())
{
var23 += this.rand.nextInt(var23 / 2 + 2);
}
DamageSource var21 = DamageSource.generic;
if (this.isBurning())
{
var4.entityHit.setFire(5);
}
if (var4.entityHit.attackEntityFrom(var21, var23))
{
if (var4.entityHit instanceof EntityLiving)
{
if (!this.worldObj.isRemote)
{
EntityLiving var24 = (EntityLiving)var4.entityHit;
var24.func_85034_r(var24.func_85035_bI() + 1);
}
if (this.knockbackStrength > 0)
{
float var25 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
if (var25 > 0.0F)
{
var4.entityHit.addVelocity(this.motionX * (double)this.knockbackStrength * 0.6000000238418579D / (double)var25, 0.1D, this.motionZ * (double)this.knockbackStrength * 0.6000000238418579D / (double)var25);
}
}
}
this.func_85030_a("", 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
this.setDead();
}
else
{
this.motionX *= -0.10000000149011612D;
this.motionY *= -0.10000000149011612D;
this.motionZ *= -0.10000000149011612D;
this.rotationYaw += 180.0F;
this.prevRotationYaw += 180.0F;
this.ticksInAir = 0;
}
}
else
{
this.xTile = var4.blockX;
this.yTile = var4.blockY;
this.zTile = var4.blockZ;
this.inTile = this.worldObj.getBlockId(this.xTile, this.yTile, this.zTile);
this.inData = this.worldObj.getBlockMetadata(this.xTile, this.yTile, this.zTile);
this.motionX = (double)((float)(var4.hitVec.xCoord - this.posX));
this.motionY = (double)((float)(var4.hitVec.yCoord - this.posY));
this.motionZ = (double)((float)(var4.hitVec.zCoord - this.posZ));
var20 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionY * this.motionY + this.motionZ * this.motionZ);
this.posX -= this.motionX / (double)var20 * 0.05000000074505806D;
this.posY -= this.motionY / (double)var20 * 0.05000000074505806D;
this.posZ -= this.motionZ / (double)var20 * 0.05000000074505806D;
this.func_85030_a("", 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
this.inGround = true;
this.arrowShake = 7;
this.setIsCritical(false);
if (this.inTile != 0)
{
Block.blocksList[this.inTile].onEntityCollidedWithBlock(this.worldObj, this.xTile, this.yTile, this.zTile, this);
}
}
}
if (this.getIsCritical())
{
for (var9 = 0; var9 < 4; ++var9)
{
this.worldObj.spawnParticle("crit", this.posX + this.motionX * (double)var9 / 4.0D, this.posY + this.motionY * (double)var9 / 4.0D, this.posZ + this.motionZ * (double)var9 / 4.0D, -this.motionX, -this.motionY + 0.2D, -this.motionZ);
}
}
this.posX += this.motionX;
this.posY += this.motionY;
this.posZ += this.motionZ;
var20 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
this.rotationYaw = (float)(Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI);
for (this.rotationPitch = (float)(Math.atan2(this.motionY, (double)var20) * 180.0D / Math.PI); this.rotationPitch - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F)
{
;
}
while (this.rotationPitch - this.prevRotationPitch >= 180.0F)
{
this.prevRotationPitch += 360.0F;
}
while (this.rotationYaw - this.prevRotationYaw < -180.0F)
{
this.prevRotationYaw -= 360.0F;
}
while (this.rotationYaw - this.prevRotationYaw >= 180.0F)
{
this.prevRotationYaw += 360.0F;
}
this.rotationPitch = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * 0.2F;
this.rotationYaw = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F;
float var22 = 0.99F;
var11 = 0.05F;
if (this.isInWater())
{
for (int var26 = 0; var26 < 4; ++var26)
{
float var27 = 0.25F;
this.worldObj.spawnParticle("bubble", this.posX - this.motionX * (double)var27, this.posY - this.motionY * (double)var27, this.posZ - this.motionZ * (double)var27, this.motionX, this.motionY, this.motionZ);
}
var22 = 0.8F;
}
this.motionX *= (double)var22;
this.motionY *= (double)var22;
this.motionZ *= (double)var22;
this.motionY -= (double)var11;
this.setPosition(this.posX, this.posY, this.posZ);
this.doBlockCollisions();
}
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
{
par1NBTTagCompound.setShort("xTile", (short)this.xTile);
par1NBTTagCompound.setShort("yTile", (short)this.yTile);
par1NBTTagCompound.setShort("zTile", (short)this.zTile);
par1NBTTagCompound.setByte("inTile", (byte)this.inTile);
par1NBTTagCompound.setByte("inData", (byte)this.inData);
par1NBTTagCompound.setByte("shake", (byte)this.arrowShake);
par1NBTTagCompound.setByte("inGround", (byte)(this.inGround ? 1 : 0));
par1NBTTagCompound.setDouble("damage", this.damage);
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
{
this.xTile = par1NBTTagCompound.getShort("xTile");
this.yTile = par1NBTTagCompound.getShort("yTile");
this.zTile = par1NBTTagCompound.getShort("zTile");
this.inTile = par1NBTTagCompound.getByte("inTile") & 255;
this.inData = par1NBTTagCompound.getByte("inData") & 255;
this.arrowShake = par1NBTTagCompound.getByte("shake") & 255;
this.inGround = par1NBTTagCompound.getByte("inGround") == 1;
if (par1NBTTagCompound.hasKey("damage"))
{
this.damage = par1NBTTagCompound.getDouble("damage");
}
}
/**
* returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to
* prevent them from trampling crops
*/
protected boolean canTriggerWalking()
{
return false;
}
@SideOnly(Side.CLIENT)
public float getShadowSize()
{
return 0.0F;
}
public void setDamage(double par1)
{
this.damage = par1;
}
public double getDamage()
{
return this.damage;
}
/**
* Sets the amount of knockback the arrow applies when it hits a mob.
*/
public void setKnockbackStrength(int par1)
{
this.knockbackStrength = par1;
}
/**
* If returns false, the item will not inflict any damage against entities.
*/
public boolean canAttackWithItem()
{
return false;
}
/**
* Whether the arrow has a stream of critical hit particles flying behind it.
*/
public void setIsCritical(boolean par1)
{
byte var2 = this.dataWatcher.getWatchableObjectByte(16);
if (par1)
{
this.dataWatcher.updateObject(16, Byte.valueOf((byte)(var2 | 1)));
}
else
{
this.dataWatcher.updateObject(16, Byte.valueOf((byte)(var2 & -2)));
}
}
/**
* Whether the arrow has a stream of critical hit particles flying behind it.
*/
public boolean getIsCritical()
{
byte var1 = this.dataWatcher.getWatchableObjectByte(16);
return (var1 & 1) != 0;
}
}