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 fuseTime = 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.fuseTime - 5) 060 { 061 this.timeSinceIgnited = this.fuseTime - 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.fuseTime); 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.fuseTime = 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.fuseTime) 135 { 136 this.timeSinceIgnited = this.fuseTime; 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 * Params: (Float)Render tick. Returns the intensity of the creeper's flash when it is ignited. 206 */ 207 public float getCreeperFlashIntensity(float par1) 208 { 209 return ((float)this.lastActiveTime + (float)(this.timeSinceIgnited - this.lastActiveTime) * par1) / (float)(this.fuseTime - 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 }