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