001    package net.minecraft.src;
002    
003    import cpw.mods.fml.common.Side;
004    import cpw.mods.fml.common.asm.SideOnly;
005    
006    public class EntityCreeper extends EntityMob
007    {
008        /**
009         * Time when this creeper was last in an active state (Messed up code here, probably causes creeper animation to go
010         * weird)
011         */
012        private int lastActiveTime;
013    
014        /**
015         * The amount of time since the creeper was close enough to the player to ignite
016         */
017        private int timeSinceIgnited;
018        private int field_82225_f = 30;
019        private int field_82226_g = 3;
020    
021        public EntityCreeper(World par1World)
022        {
023            super(par1World);
024            this.texture = "/mob/creeper.png";
025            this.tasks.addTask(1, new EntityAISwimming(this));
026            this.tasks.addTask(2, new EntityAICreeperSwell(this));
027            this.tasks.addTask(3, new EntityAIAvoidEntity(this, EntityOcelot.class, 6.0F, 0.25F, 0.3F));
028            this.tasks.addTask(4, new EntityAIAttackOnCollide(this, 0.25F, false));
029            this.tasks.addTask(5, new EntityAIWander(this, 0.2F));
030            this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
031            this.tasks.addTask(6, new EntityAILookIdle(this));
032            this.targetTasks.addTask(1, new EntityAINearestAttackableTarget(this, EntityPlayer.class, 16.0F, 0, true));
033            this.targetTasks.addTask(2, new EntityAIHurtByTarget(this, false));
034        }
035    
036        /**
037         * Returns true if the newer Entity AI code should be run
038         */
039        public boolean isAIEnabled()
040        {
041            return true;
042        }
043    
044        public int func_82143_as()
045        {
046            return this.getAttackTarget() == null ? 3 : 3 + (this.health - 1);
047        }
048    
049        /**
050         * Called when the mob is falling. Calculates and applies fall damage.
051         */
052        protected void fall(float par1)
053        {
054            super.fall(par1);
055            this.timeSinceIgnited = (int)((float)this.timeSinceIgnited + par1 * 1.5F);
056    
057            if (this.timeSinceIgnited > this.field_82225_f - 5)
058            {
059                this.timeSinceIgnited = this.field_82225_f - 5;
060            }
061        }
062    
063        public int getMaxHealth()
064        {
065            return 20;
066        }
067    
068        protected void entityInit()
069        {
070            super.entityInit();
071            this.dataWatcher.addObject(16, Byte.valueOf((byte) - 1));
072            this.dataWatcher.addObject(17, Byte.valueOf((byte)0));
073        }
074    
075        /**
076         * (abstract) Protected helper method to write subclass entity data to NBT.
077         */
078        public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
079        {
080            super.writeEntityToNBT(par1NBTTagCompound);
081    
082            if (this.dataWatcher.getWatchableObjectByte(17) == 1)
083            {
084                par1NBTTagCompound.setBoolean("powered", true);
085            }
086    
087            par1NBTTagCompound.setShort("Fuse", (short)this.field_82225_f);
088            par1NBTTagCompound.setByte("ExplosionRadius", (byte)this.field_82226_g);
089        }
090    
091        /**
092         * (abstract) Protected helper method to read subclass entity data from NBT.
093         */
094        public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
095        {
096            super.readEntityFromNBT(par1NBTTagCompound);
097            this.dataWatcher.updateObject(17, Byte.valueOf((byte)(par1NBTTagCompound.getBoolean("powered") ? 1 : 0)));
098    
099            if (par1NBTTagCompound.hasKey("Fuse"))
100            {
101                this.field_82225_f = par1NBTTagCompound.getShort("Fuse");
102            }
103    
104            if (par1NBTTagCompound.hasKey("ExplosionRadius"))
105            {
106                this.field_82226_g = par1NBTTagCompound.getByte("ExplosionRadius");
107            }
108        }
109    
110        /**
111         * Called to update the entity's position/logic.
112         */
113        public void onUpdate()
114        {
115            if (this.isEntityAlive())
116            {
117                this.lastActiveTime = this.timeSinceIgnited;
118                int var1 = this.getCreeperState();
119    
120                if (var1 > 0 && this.timeSinceIgnited == 0)
121                {
122                    this.worldObj.playSoundAtEntity(this, "random.fuse", 1.0F, 0.5F);
123                }
124    
125                this.timeSinceIgnited += var1;
126    
127                if (this.timeSinceIgnited < 0)
128                {
129                    this.timeSinceIgnited = 0;
130                }
131    
132                if (this.timeSinceIgnited >= this.field_82225_f)
133                {
134                    this.timeSinceIgnited = this.field_82225_f;
135    
136                    if (!this.worldObj.isRemote)
137                    {
138                        boolean var2 = this.worldObj.func_82736_K().func_82766_b("mobGriefing");
139    
140                        if (this.getPowered())
141                        {
142                            this.worldObj.createExplosion(this, this.posX, this.posY, this.posZ, (float)(this.field_82226_g * 2), var2);
143                        }
144                        else
145                        {
146                            this.worldObj.createExplosion(this, this.posX, this.posY, this.posZ, (float)this.field_82226_g, var2);
147                        }
148    
149                        this.setDead();
150                    }
151                }
152            }
153    
154            super.onUpdate();
155        }
156    
157        /**
158         * Returns the sound this mob makes when it is hurt.
159         */
160        protected String getHurtSound()
161        {
162            return "mob.creeper.say";
163        }
164    
165        /**
166         * Returns the sound this mob makes on death.
167         */
168        protected String getDeathSound()
169        {
170            return "mob.creeper.death";
171        }
172    
173        /**
174         * Called when the mob's health reaches 0.
175         */
176        public void onDeath(DamageSource par1DamageSource)
177        {
178            super.onDeath(par1DamageSource);
179    
180            if (par1DamageSource.getEntity() instanceof EntitySkeleton)
181            {
182                this.dropItem(Item.record13.shiftedIndex + this.rand.nextInt(10), 1);
183            }
184        }
185    
186        public boolean attackEntityAsMob(Entity par1Entity)
187        {
188            return true;
189        }
190    
191        /**
192         * Returns true if the creeper is powered by a lightning bolt.
193         */
194        public boolean getPowered()
195        {
196            return this.dataWatcher.getWatchableObjectByte(17) == 1;
197        }
198    
199        @SideOnly(Side.CLIENT)
200    
201        /**
202         * Connects the the creeper flashes to the creeper's color multiplier
203         */
204        public float setCreeperFlashTime(float par1)
205        {
206            return ((float)this.lastActiveTime + (float)(this.timeSinceIgnited - this.lastActiveTime) * par1) / (float)(this.field_82225_f - 2);
207        }
208    
209        /**
210         * Returns the item ID for the item the mob drops on death.
211         */
212        protected int getDropItemId()
213        {
214            return Item.gunpowder.shiftedIndex;
215        }
216    
217        /**
218         * Returns the current state of creeper, -1 is idle, 1 is 'in fuse'
219         */
220        public int getCreeperState()
221        {
222            return this.dataWatcher.getWatchableObjectByte(16);
223        }
224    
225        /**
226         * Sets the state of creeper, -1 to idle and 1 to be 'in fuse'
227         */
228        public void setCreeperState(int par1)
229        {
230            this.dataWatcher.updateObject(16, Byte.valueOf((byte)par1));
231        }
232    
233        /**
234         * Called when a lightning bolt hits the entity.
235         */
236        public void onStruckByLightning(EntityLightningBolt par1EntityLightningBolt)
237        {
238            super.onStruckByLightning(par1EntityLightningBolt);
239            this.dataWatcher.updateObject(17, Byte.valueOf((byte)1));
240        }
241    }