001 package net.minecraft.src; 002 003 public class EntityAIArrowAttack extends EntityAIBase 004 { 005 /** The entity the AI instance has been applied to */ 006 private final EntityLiving entityHost; 007 008 /** 009 * The entity (as a RangedAttackMob) the AI instance has been applied to. 010 */ 011 private final IRangedAttackMob rangedAttackEntityHost; 012 private EntityLiving attackTarget; 013 014 /** 015 * A decrementing tick that spawns a ranged attack once this value reaches 0. It is then set back to the 016 * maxRangedAttackTime. 017 */ 018 private int rangedAttackTime = 0; 019 private float entityMoveSpeed; 020 private int field_75318_f = 0; 021 022 /** 023 * The maximum time the AI has to wait before peforming another ranged attack. 024 */ 025 private int maxRangedAttackTime; 026 private float field_82642_h; 027 028 public EntityAIArrowAttack(IRangedAttackMob par1IRangedAttackMob, float par2, int par3, float par4) 029 { 030 if (!(par1IRangedAttackMob instanceof EntityLiving)) 031 { 032 throw new IllegalArgumentException("ArrowAttackGoal requires Mob implements RangedAttackMob"); 033 } 034 else 035 { 036 this.rangedAttackEntityHost = par1IRangedAttackMob; 037 this.entityHost = (EntityLiving)par1IRangedAttackMob; 038 this.entityMoveSpeed = par2; 039 this.maxRangedAttackTime = par3; 040 this.field_82642_h = par4 * par4; 041 this.rangedAttackTime = par3 / 2; 042 this.setMutexBits(3); 043 } 044 } 045 046 /** 047 * Returns whether the EntityAIBase should begin execution. 048 */ 049 public boolean shouldExecute() 050 { 051 EntityLiving var1 = this.entityHost.getAttackTarget(); 052 053 if (var1 == null) 054 { 055 return false; 056 } 057 else 058 { 059 this.attackTarget = var1; 060 return true; 061 } 062 } 063 064 /** 065 * Returns whether an in-progress EntityAIBase should continue executing 066 */ 067 public boolean continueExecuting() 068 { 069 return this.shouldExecute() || !this.entityHost.getNavigator().noPath(); 070 } 071 072 /** 073 * Resets the task 074 */ 075 public void resetTask() 076 { 077 this.attackTarget = null; 078 this.field_75318_f = 0; 079 this.rangedAttackTime = this.maxRangedAttackTime / 2; 080 } 081 082 /** 083 * Updates the task 084 */ 085 public void updateTask() 086 { 087 double var1 = this.entityHost.getDistanceSq(this.attackTarget.posX, this.attackTarget.boundingBox.minY, this.attackTarget.posZ); 088 boolean var3 = this.entityHost.getEntitySenses().canSee(this.attackTarget); 089 090 if (var3) 091 { 092 ++this.field_75318_f; 093 } 094 else 095 { 096 this.field_75318_f = 0; 097 } 098 099 if (var1 <= (double)this.field_82642_h && this.field_75318_f >= 20) 100 { 101 this.entityHost.getNavigator().clearPathEntity(); 102 } 103 else 104 { 105 this.entityHost.getNavigator().tryMoveToEntityLiving(this.attackTarget, this.entityMoveSpeed); 106 } 107 108 this.entityHost.getLookHelper().setLookPositionWithEntity(this.attackTarget, 30.0F, 30.0F); 109 this.rangedAttackTime = Math.max(this.rangedAttackTime - 1, 0); 110 111 if (this.rangedAttackTime <= 0) 112 { 113 if (var1 <= (double)this.field_82642_h && var3) 114 { 115 this.rangedAttackEntityHost.attackEntityWithRangedAttack(this.attackTarget); 116 this.rangedAttackTime = this.maxRangedAttackTime; 117 } 118 } 119 } 120 }