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}