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 }