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