001package net.minecraft.entity.ai;
002
003import net.minecraft.entity.EntityLiving;
004import net.minecraft.entity.IRangedAttackMob;
005
006public 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}