001 package net.minecraft.src; 002 003 public class EntityAIArrowAttack extends EntityAIBase 004 { 005 World worldObj; 006 007 /** The entity the AI instance has been applied to */ 008 EntityLiving entityHost; 009 EntityLiving attackTarget; 010 011 /** 012 * A decrementing tick that spawns a ranged attack once this value reaches 0. It is then set back to the 013 * maxRangedAttackTime. 014 */ 015 int rangedAttackTime = 0; 016 float entityMoveSpeed; 017 int field_75318_f = 0; 018 019 /** 020 * The ID of this ranged attack AI. This chooses which entity is to be used as a ranged attack. 021 */ 022 int rangedAttackID; 023 024 /** 025 * The maximum time the AI has to wait before peforming another ranged attack. 026 */ 027 int maxRangedAttackTime; 028 029 public EntityAIArrowAttack(EntityLiving par1EntityLiving, float par2, int par3, int par4) 030 { 031 this.entityHost = par1EntityLiving; 032 this.worldObj = par1EntityLiving.worldObj; 033 this.entityMoveSpeed = par2; 034 this.rangedAttackID = par3; 035 this.maxRangedAttackTime = par4; 036 this.setMutexBits(3); 037 } 038 039 /** 040 * Returns whether the EntityAIBase should begin execution. 041 */ 042 public boolean shouldExecute() 043 { 044 EntityLiving var1 = this.entityHost.getAttackTarget(); 045 046 if (var1 == null) 047 { 048 return false; 049 } 050 else 051 { 052 this.attackTarget = var1; 053 return true; 054 } 055 } 056 057 /** 058 * Returns whether an in-progress EntityAIBase should continue executing 059 */ 060 public boolean continueExecuting() 061 { 062 return this.shouldExecute() || !this.entityHost.getNavigator().noPath(); 063 } 064 065 /** 066 * Resets the task 067 */ 068 public void resetTask() 069 { 070 this.attackTarget = null; 071 } 072 073 /** 074 * Updates the task 075 */ 076 public void updateTask() 077 { 078 double var1 = 100.0D; 079 double var3 = this.entityHost.getDistanceSq(this.attackTarget.posX, this.attackTarget.boundingBox.minY, this.attackTarget.posZ); 080 boolean var5 = this.entityHost.getEntitySenses().canSee(this.attackTarget); 081 082 if (var5) 083 { 084 ++this.field_75318_f; 085 } 086 else 087 { 088 this.field_75318_f = 0; 089 } 090 091 if (var3 <= var1 && this.field_75318_f >= 20) 092 { 093 this.entityHost.getNavigator().clearPathEntity(); 094 } 095 else 096 { 097 this.entityHost.getNavigator().tryMoveToEntityLiving(this.attackTarget, this.entityMoveSpeed); 098 } 099 100 this.entityHost.getLookHelper().setLookPositionWithEntity(this.attackTarget, 30.0F, 30.0F); 101 this.rangedAttackTime = Math.max(this.rangedAttackTime - 1, 0); 102 103 if (this.rangedAttackTime <= 0) 104 { 105 if (var3 <= var1 && var5) 106 { 107 this.doRangedAttack(); 108 this.rangedAttackTime = this.maxRangedAttackTime; 109 } 110 } 111 } 112 113 /** 114 * Performs a ranged attack according to the AI's rangedAttackID. 115 */ 116 private void doRangedAttack() 117 { 118 if (this.rangedAttackID == 1) 119 { 120 EntityArrow var1 = new EntityArrow(this.worldObj, this.entityHost, this.attackTarget, 1.6F, 12.0F); 121 this.worldObj.playSoundAtEntity(this.entityHost, "random.bow", 1.0F, 1.0F / (this.entityHost.getRNG().nextFloat() * 0.4F + 0.8F)); 122 this.worldObj.spawnEntityInWorld(var1); 123 } 124 else if (this.rangedAttackID == 2) 125 { 126 EntitySnowball var9 = new EntitySnowball(this.worldObj, this.entityHost); 127 double var2 = this.attackTarget.posX - this.entityHost.posX; 128 double var4 = this.attackTarget.posY + (double)this.attackTarget.getEyeHeight() - 1.100000023841858D - var9.posY; 129 double var6 = this.attackTarget.posZ - this.entityHost.posZ; 130 float var8 = MathHelper.sqrt_double(var2 * var2 + var6 * var6) * 0.2F; 131 var9.setThrowableHeading(var2, var4 + (double)var8, var6, 1.6F, 12.0F); 132 this.worldObj.playSoundAtEntity(this.entityHost, "random.bow", 1.0F, 1.0F / (this.entityHost.getRNG().nextFloat() * 0.4F + 0.8F)); 133 this.worldObj.spawnEntityInWorld(var9); 134 } 135 } 136 }