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