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 }