    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    }