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 }