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    }