001 package net.minecraft.entity.monster; 002 003 import cpw.mods.fml.relauncher.Side; 004 import cpw.mods.fml.relauncher.SideOnly; 005 import net.minecraft.entity.Entity; 006 import net.minecraft.entity.ai.EntityAIAttackOnCollide; 007 import net.minecraft.entity.ai.EntityAIAvoidEntity; 008 import net.minecraft.entity.ai.EntityAICreeperSwell; 009 import net.minecraft.entity.ai.EntityAIHurtByTarget; 010 import net.minecraft.entity.ai.EntityAILookIdle; 011 import net.minecraft.entity.ai.EntityAINearestAttackableTarget; 012 import net.minecraft.entity.ai.EntityAISwimming; 013 import net.minecraft.entity.ai.EntityAIWander; 014 import net.minecraft.entity.ai.EntityAIWatchClosest; 015 import net.minecraft.entity.effect.EntityLightningBolt; 016 import net.minecraft.entity.passive.EntityOcelot; 017 import net.minecraft.entity.player.EntityPlayer; 018 import net.minecraft.item.Item; 019 import net.minecraft.nbt.NBTTagCompound; 020 import net.minecraft.util.DamageSource; 021 import net.minecraft.world.World; 022 023 public class EntityCreeper extends EntityMob 024 { 025 /** 026 * Time when this creeper was last in an active state (Messed up code here, probably causes creeper animation to go 027 * weird) 028 */ 029 private int lastActiveTime; 030 031 /** 032 * The amount of time since the creeper was close enough to the player to ignite 033 */ 034 private int timeSinceIgnited; 035 private int fuseTime = 30; 036 037 /** Explosion radius for this creeper. */ 038 private int explosionRadius = 3; 039 040 public EntityCreeper(World par1World) 041 { 042 super(par1World); 043 this.texture = "/mob/creeper.png"; 044 this.tasks.addTask(1, new EntityAISwimming(this)); 045 this.tasks.addTask(2, new EntityAICreeperSwell(this)); 046 this.tasks.addTask(3, new EntityAIAvoidEntity(this, EntityOcelot.class, 6.0F, 0.25F, 0.3F)); 047 this.tasks.addTask(4, new EntityAIAttackOnCollide(this, 0.25F, false)); 048 this.tasks.addTask(5, new EntityAIWander(this, 0.2F)); 049 this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F)); 050 this.tasks.addTask(6, new EntityAILookIdle(this)); 051 this.targetTasks.addTask(1, new EntityAINearestAttackableTarget(this, EntityPlayer.class, 16.0F, 0, true)); 052 this.targetTasks.addTask(2, new EntityAIHurtByTarget(this, false)); 053 } 054 055 /** 056 * Returns true if the newer Entity AI code should be run 057 */ 058 public boolean isAIEnabled() 059 { 060 return true; 061 } 062 063 public int func_82143_as() 064 { 065 return this.getAttackTarget() == null ? 3 : 3 + (this.health - 1); 066 } 067 068 /** 069 * Called when the mob is falling. Calculates and applies fall damage. 070 */ 071 protected void fall(float par1) 072 { 073 super.fall(par1); 074 this.timeSinceIgnited = (int)((float)this.timeSinceIgnited + par1 * 1.5F); 075 076 if (this.timeSinceIgnited > this.fuseTime - 5) 077 { 078 this.timeSinceIgnited = this.fuseTime - 5; 079 } 080 } 081 082 public int getMaxHealth() 083 { 084 return 20; 085 } 086 087 protected void entityInit() 088 { 089 super.entityInit(); 090 this.dataWatcher.addObject(16, Byte.valueOf((byte) - 1)); 091 this.dataWatcher.addObject(17, Byte.valueOf((byte)0)); 092 } 093 094 /** 095 * (abstract) Protected helper method to write subclass entity data to NBT. 096 */ 097 public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) 098 { 099 super.writeEntityToNBT(par1NBTTagCompound); 100 101 if (this.dataWatcher.getWatchableObjectByte(17) == 1) 102 { 103 par1NBTTagCompound.setBoolean("powered", true); 104 } 105 106 par1NBTTagCompound.setShort("Fuse", (short)this.fuseTime); 107 par1NBTTagCompound.setByte("ExplosionRadius", (byte)this.explosionRadius); 108 } 109 110 /** 111 * (abstract) Protected helper method to read subclass entity data from NBT. 112 */ 113 public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) 114 { 115 super.readEntityFromNBT(par1NBTTagCompound); 116 this.dataWatcher.updateObject(17, Byte.valueOf((byte)(par1NBTTagCompound.getBoolean("powered") ? 1 : 0))); 117 118 if (par1NBTTagCompound.hasKey("Fuse")) 119 { 120 this.fuseTime = par1NBTTagCompound.getShort("Fuse"); 121 } 122 123 if (par1NBTTagCompound.hasKey("ExplosionRadius")) 124 { 125 this.explosionRadius = par1NBTTagCompound.getByte("ExplosionRadius"); 126 } 127 } 128 129 /** 130 * Called to update the entity's position/logic. 131 */ 132 public void onUpdate() 133 { 134 if (this.isEntityAlive()) 135 { 136 this.lastActiveTime = this.timeSinceIgnited; 137 int var1 = this.getCreeperState(); 138 139 if (var1 > 0 && this.timeSinceIgnited == 0) 140 { 141 this.playSound("random.fuse", 1.0F, 0.5F); 142 } 143 144 this.timeSinceIgnited += var1; 145 146 if (this.timeSinceIgnited < 0) 147 { 148 this.timeSinceIgnited = 0; 149 } 150 151 if (this.timeSinceIgnited >= this.fuseTime) 152 { 153 this.timeSinceIgnited = this.fuseTime; 154 155 if (!this.worldObj.isRemote) 156 { 157 boolean var2 = this.worldObj.getGameRules().getGameRuleBooleanValue("mobGriefing"); 158 159 if (this.getPowered()) 160 { 161 this.worldObj.createExplosion(this, this.posX, this.posY, this.posZ, (float)(this.explosionRadius * 2), var2); 162 } 163 else 164 { 165 this.worldObj.createExplosion(this, this.posX, this.posY, this.posZ, (float)this.explosionRadius, var2); 166 } 167 168 this.setDead(); 169 } 170 } 171 } 172 173 super.onUpdate(); 174 } 175 176 /** 177 * Returns the sound this mob makes when it is hurt. 178 */ 179 protected String getHurtSound() 180 { 181 return "mob.creeper.say"; 182 } 183 184 /** 185 * Returns the sound this mob makes on death. 186 */ 187 protected String getDeathSound() 188 { 189 return "mob.creeper.death"; 190 } 191 192 /** 193 * Called when the mob's health reaches 0. 194 */ 195 public void onDeath(DamageSource par1DamageSource) 196 { 197 super.onDeath(par1DamageSource); 198 199 if (par1DamageSource.getEntity() instanceof EntitySkeleton) 200 { 201 int var2 = Item.record13.itemID + this.rand.nextInt(Item.recordWait.itemID - Item.record13.itemID + 1); 202 this.dropItem(var2, 1); 203 } 204 } 205 206 public boolean attackEntityAsMob(Entity par1Entity) 207 { 208 return true; 209 } 210 211 /** 212 * Returns true if the creeper is powered by a lightning bolt. 213 */ 214 public boolean getPowered() 215 { 216 return this.dataWatcher.getWatchableObjectByte(17) == 1; 217 } 218 219 @SideOnly(Side.CLIENT) 220 221 /** 222 * Params: (Float)Render tick. Returns the intensity of the creeper's flash when it is ignited. 223 */ 224 public float getCreeperFlashIntensity(float par1) 225 { 226 return ((float)this.lastActiveTime + (float)(this.timeSinceIgnited - this.lastActiveTime) * par1) / (float)(this.fuseTime - 2); 227 } 228 229 /** 230 * Returns the item ID for the item the mob drops on death. 231 */ 232 protected int getDropItemId() 233 { 234 return Item.gunpowder.itemID; 235 } 236 237 /** 238 * Returns the current state of creeper, -1 is idle, 1 is 'in fuse' 239 */ 240 public int getCreeperState() 241 { 242 return this.dataWatcher.getWatchableObjectByte(16); 243 } 244 245 /** 246 * Sets the state of creeper, -1 to idle and 1 to be 'in fuse' 247 */ 248 public void setCreeperState(int par1) 249 { 250 this.dataWatcher.updateObject(16, Byte.valueOf((byte)par1)); 251 } 252 253 /** 254 * Called when a lightning bolt hits the entity. 255 */ 256 public void onStruckByLightning(EntityLightningBolt par1EntityLightningBolt) 257 { 258 super.onStruckByLightning(par1EntityLightningBolt); 259 this.dataWatcher.updateObject(17, Byte.valueOf((byte)1)); 260 } 261 }