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 }