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