    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    }