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.func_85030_a("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                int var2 = Item.record13.shiftedIndex + this.rand.nextInt(Item.field_85180_cf.shiftedIndex - Item.record13.shiftedIndex + 1);
185                this.dropItem(var2, 1);
186            }
187        }
188    
189        public boolean attackEntityAsMob(Entity par1Entity)
190        {
191            return true;
192        }
193    
194        /**
195         * Returns true if the creeper is powered by a lightning bolt.
196         */
197        public boolean getPowered()
198        {
199            return this.dataWatcher.getWatchableObjectByte(17) == 1;
200        }
201    
202        @SideOnly(Side.CLIENT)
203    
204        /**
205         * Connects the the creeper flashes to the creeper's color multiplier
206         */
207        public float setCreeperFlashTime(float par1)
208        {
209            return ((float)this.lastActiveTime + (float)(this.timeSinceIgnited - this.lastActiveTime) * par1) / (float)(this.field_82225_f - 2);
210        }
211    
212        /**
213         * Returns the item ID for the item the mob drops on death.
214         */
215        protected int getDropItemId()
216        {
217            return Item.gunpowder.shiftedIndex;
218        }
219    
220        /**
221         * Returns the current state of creeper, -1 is idle, 1 is 'in fuse'
222         */
223        public int getCreeperState()
224        {
225            return this.dataWatcher.getWatchableObjectByte(16);
226        }
227    
228        /**
229         * Sets the state of creeper, -1 to idle and 1 to be 'in fuse'
230         */
231        public void setCreeperState(int par1)
232        {
233            this.dataWatcher.updateObject(16, Byte.valueOf((byte)par1));
234        }
235    
236        /**
237         * Called when a lightning bolt hits the entity.
238         */
239        public void onStruckByLightning(EntityLightningBolt par1EntityLightningBolt)
240        {
241            super.onStruckByLightning(par1EntityLightningBolt);
242            this.dataWatcher.updateObject(17, Byte.valueOf((byte)1));
243        }
244    }