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 }