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 (par1EntityLiving.boundingBox.maxY > this.taskOwner.boundingBox.minY && par1EntityLiving.boundingBox.minY < this.taskOwner.boundingBox.maxY)
107            {
108                if (!this.taskOwner.isExplosiveMob(par1EntityLiving.getClass()))
109                {
110                    return false;
111                }
112                else
113                {
114                    if (this.taskOwner instanceof EntityTameable && ((EntityTameable)this.taskOwner).isTamed())
115                    {
116                        if (par1EntityLiving instanceof EntityTameable && ((EntityTameable)par1EntityLiving).isTamed())
117                        {
118                            return false;
119                        }
120    
121                        if (par1EntityLiving == ((EntityTameable)this.taskOwner).getOwner())
122                        {
123                            return false;
124                        }
125                    }
126                    else if (par1EntityLiving instanceof EntityPlayer && !par2 && ((EntityPlayer)par1EntityLiving).capabilities.disableDamage)
127                    {
128                        return false;
129                    }
130    
131                    if (!this.taskOwner.isWithinHomeDistance(MathHelper.floor_double(par1EntityLiving.posX), MathHelper.floor_double(par1EntityLiving.posY), MathHelper.floor_double(par1EntityLiving.posZ)))
132                    {
133                        return false;
134                    }
135                    else if (this.shouldCheckSight && !this.taskOwner.getEntitySenses().canSee(par1EntityLiving))
136                    {
137                        return false;
138                    }
139                    else
140                    {
141                        if (this.field_75303_a)
142                        {
143                            if (--this.field_75302_c <= 0)
144                            {
145                                this.field_75301_b = 0;
146                            }
147    
148                            if (this.field_75301_b == 0)
149                            {
150                                this.field_75301_b = this.func_75295_a(par1EntityLiving) ? 1 : 2;
151                            }
152    
153                            if (this.field_75301_b == 2)
154                            {
155                                return false;
156                            }
157                        }
158    
159                        return true;
160                    }
161                }
162            }
163            else
164            {
165                return false;
166            }
167        }
168    
169        private boolean func_75295_a(EntityLiving par1EntityLiving)
170        {
171            this.field_75302_c = 10 + this.taskOwner.getRNG().nextInt(5);
172            PathEntity var2 = this.taskOwner.getNavigator().getPathToEntityLiving(par1EntityLiving);
173    
174            if (var2 == null)
175            {
176                return false;
177            }
178            else
179            {
180                PathPoint var3 = var2.getFinalPathPoint();
181    
182                if (var3 == null)
183                {
184                    return false;
185                }
186                else
187                {
188                    int var4 = var3.xCoord - MathHelper.floor_double(par1EntityLiving.posX);
189                    int var5 = var3.zCoord - MathHelper.floor_double(par1EntityLiving.posZ);
190                    return (double)(var4 * var4 + var5 * var5) <= 2.25D;
191                }
192            }
193        }
194    }