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 }