001    package net.minecraft.src;
002    
003    public abstract class EntityAITarget extends EntityAIBase
004    {
005        /** The entity that this task belongs to */
006        protected EntityLiving taskOwner;
007        protected float targetDistance;
008    
009        /**
010         * If true, EntityAI targets must be able to be seen (cannot be blocked by walls) to be suitable targets.
011         */
012        protected boolean shouldCheckSight;
013        private boolean field_75303_a;
014        private int field_75301_b;
015        private int field_75302_c;
016        private int field_75298_g;
017    
018        public EntityAITarget(EntityLiving par1EntityLiving, float par2, boolean par3)
019        {
020            this(par1EntityLiving, par2, par3, false);
021        }
022    
023        public EntityAITarget(EntityLiving par1EntityLiving, float par2, boolean par3, boolean par4)
024        {
025            this.field_75301_b = 0;
026            this.field_75302_c = 0;
027            this.field_75298_g = 0;
028            this.taskOwner = par1EntityLiving;
029            this.targetDistance = par2;
030            this.shouldCheckSight = par3;
031            this.field_75303_a = par4;
032        }
033    
034        /**
035         * Returns whether an in-progress EntityAIBase should continue executing
036         */
037        public boolean continueExecuting()
038        {
039            EntityLiving var1 = this.taskOwner.getAttackTarget();
040    
041            if (var1 == null)
042            {
043                return false;
044            }
045            else if (!var1.isEntityAlive())
046            {
047                return false;
048            }
049            else if (this.taskOwner.getDistanceSqToEntity(var1) > (double)(this.targetDistance * this.targetDistance))
050            {
051                return false;
052            }
053            else
054            {
055                if (this.shouldCheckSight)
056                {
057                    if (this.taskOwner.getEntitySenses().canSee(var1))
058                    {
059                        this.field_75298_g = 0;
060                    }
061                    else if (++this.field_75298_g > 60)
062                    {
063                        return false;
064                    }
065                }
066    
067                return true;
068            }
069        }
070    
071        /**
072         * Execute a one shot task or start executing a continuous task
073         */
074        public void startExecuting()
075        {
076            this.field_75301_b = 0;
077            this.field_75302_c = 0;
078            this.field_75298_g = 0;
079        }
080    
081        /**
082         * Resets the task
083         */
084        public void resetTask()
085        {
086            this.taskOwner.setAttackTarget((EntityLiving)null);
087        }
088    
089        /**
090         * A method used to see if an entity is a suitable target through a number of checks.
091         */
092        protected boolean isSuitableTarget(EntityLiving par1EntityLiving, boolean par2)
093        {
094            if (par1EntityLiving == null)
095            {
096                return false;
097            }
098            else if (par1EntityLiving == this.taskOwner)
099            {
100                return false;
101            }
102            else if (!par1EntityLiving.isEntityAlive())
103            {
104                return false;
105            }
106            else if (!this.taskOwner.isExplosiveMob(par1EntityLiving.getClass()))
107            {
108                return false;
109            }
110            else
111            {
112                if (this.taskOwner instanceof EntityTameable && ((EntityTameable)this.taskOwner).isTamed())
113                {
114                    if (par1EntityLiving instanceof EntityTameable && ((EntityTameable)par1EntityLiving).isTamed())
115                    {
116                        return false;
117                    }
118    
119                    if (par1EntityLiving == ((EntityTameable)this.taskOwner).getOwner())
120                    {
121                        return false;
122                    }
123                }
124                else if (par1EntityLiving instanceof EntityPlayer && !par2 && ((EntityPlayer)par1EntityLiving).capabilities.disableDamage)
125                {
126                    return false;
127                }
128    
129                if (!this.taskOwner.isWithinHomeDistance(MathHelper.floor_double(par1EntityLiving.posX), MathHelper.floor_double(par1EntityLiving.posY), MathHelper.floor_double(par1EntityLiving.posZ)))
130                {
131                    return false;
132                }
133                else if (this.shouldCheckSight && !this.taskOwner.getEntitySenses().canSee(par1EntityLiving))
134                {
135                    return false;
136                }
137                else
138                {
139                    if (this.field_75303_a)
140                    {
141                        if (--this.field_75302_c <= 0)
142                        {
143                            this.field_75301_b = 0;
144                        }
145    
146                        if (this.field_75301_b == 0)
147                        {
148                            this.field_75301_b = this.func_75295_a(par1EntityLiving) ? 1 : 2;
149                        }
150    
151                        if (this.field_75301_b == 2)
152                        {
153                            return false;
154                        }
155                    }
156    
157                    return true;
158                }
159            }
160        }
161    
162        private boolean func_75295_a(EntityLiving par1EntityLiving)
163        {
164            this.field_75302_c = 10 + this.taskOwner.getRNG().nextInt(5);
165            PathEntity var2 = this.taskOwner.getNavigator().getPathToEntityLiving(par1EntityLiving);
166    
167            if (var2 == null)
168            {
169                return false;
170            }
171            else
172            {
173                PathPoint var3 = var2.getFinalPathPoint();
174    
175                if (var3 == null)
176                {
177                    return false;
178                }
179                else
180                {
181                    int var4 = var3.xCoord - MathHelper.floor_double(par1EntityLiving.posX);
182                    int var5 = var3.zCoord - MathHelper.floor_double(par1EntityLiving.posZ);
183                    return (double)(var4 * var4 + var5 * var5) <= 2.25D;
184                }
185            }
186        }
187    }