001 package net.minecraft.src; 002 003 public class EntitySlime extends EntityLiving implements IMob 004 { 005 public float field_70813_a; 006 public float field_70811_b; 007 public float field_70812_c; 008 009 /** the time between each jump of the slime */ 010 private int slimeJumpDelay = 0; 011 012 public EntitySlime(World par1World) 013 { 014 super(par1World); 015 this.texture = "/mob/slime.png"; 016 int var2 = 1 << this.rand.nextInt(3); 017 this.yOffset = 0.0F; 018 this.slimeJumpDelay = this.rand.nextInt(20) + 10; 019 this.setSlimeSize(var2); 020 } 021 022 protected void entityInit() 023 { 024 super.entityInit(); 025 this.dataWatcher.addObject(16, new Byte((byte)1)); 026 } 027 028 protected void setSlimeSize(int par1) 029 { 030 this.dataWatcher.updateObject(16, new Byte((byte)par1)); 031 this.setSize(0.6F * (float)par1, 0.6F * (float)par1); 032 this.setPosition(this.posX, this.posY, this.posZ); 033 this.setEntityHealth(this.getMaxHealth()); 034 this.experienceValue = par1; 035 } 036 037 public int getMaxHealth() 038 { 039 int var1 = this.getSlimeSize(); 040 return var1 * var1; 041 } 042 043 /** 044 * Returns the size of the slime. 045 */ 046 public int getSlimeSize() 047 { 048 return this.dataWatcher.getWatchableObjectByte(16); 049 } 050 051 /** 052 * (abstract) Protected helper method to write subclass entity data to NBT. 053 */ 054 public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) 055 { 056 super.writeEntityToNBT(par1NBTTagCompound); 057 par1NBTTagCompound.setInteger("Size", this.getSlimeSize() - 1); 058 } 059 060 /** 061 * (abstract) Protected helper method to read subclass entity data from NBT. 062 */ 063 public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) 064 { 065 super.readEntityFromNBT(par1NBTTagCompound); 066 this.setSlimeSize(par1NBTTagCompound.getInteger("Size") + 1); 067 } 068 069 /** 070 * Returns the name of a particle effect that may be randomly created by EntitySlime.onUpdate() 071 */ 072 protected String getSlimeParticle() 073 { 074 return "slime"; 075 } 076 077 /** 078 * Returns the name of the sound played when the slime jumps. 079 */ 080 protected String getJumpSound() 081 { 082 return "mob.slime." + (this.getSlimeSize() > 1 ? "big" : "small"); 083 } 084 085 /** 086 * Called to update the entity's position/logic. 087 */ 088 public void onUpdate() 089 { 090 if (!this.worldObj.isRemote && this.worldObj.difficultySetting == 0 && this.getSlimeSize() > 0) 091 { 092 this.isDead = true; 093 } 094 095 this.field_70811_b += (this.field_70813_a - this.field_70811_b) * 0.5F; 096 this.field_70812_c = this.field_70811_b; 097 boolean var1 = this.onGround; 098 super.onUpdate(); 099 int var2; 100 101 if (this.onGround && !var1) 102 { 103 var2 = this.getSlimeSize(); 104 105 for (int var3 = 0; var3 < var2 * 8; ++var3) 106 { 107 float var4 = this.rand.nextFloat() * (float)Math.PI * 2.0F; 108 float var5 = this.rand.nextFloat() * 0.5F + 0.5F; 109 float var6 = MathHelper.sin(var4) * (float)var2 * 0.5F * var5; 110 float var7 = MathHelper.cos(var4) * (float)var2 * 0.5F * var5; 111 this.worldObj.spawnParticle(this.getSlimeParticle(), this.posX + (double)var6, this.boundingBox.minY, this.posZ + (double)var7, 0.0D, 0.0D, 0.0D); 112 } 113 114 if (this.makesSoundOnLand()) 115 { 116 this.func_85030_a(this.getJumpSound(), this.getSoundVolume(), ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F) / 0.8F); 117 } 118 119 this.field_70813_a = -0.5F; 120 } 121 else if (!this.onGround && var1) 122 { 123 this.field_70813_a = 1.0F; 124 } 125 126 this.func_70808_l(); 127 128 if (this.worldObj.isRemote) 129 { 130 var2 = this.getSlimeSize(); 131 this.setSize(0.6F * (float)var2, 0.6F * (float)var2); 132 } 133 } 134 135 protected void updateEntityActionState() 136 { 137 this.despawnEntity(); 138 EntityPlayer var1 = this.worldObj.getClosestVulnerablePlayerToEntity(this, 16.0D); 139 140 if (var1 != null) 141 { 142 this.faceEntity(var1, 10.0F, 20.0F); 143 } 144 145 if (this.onGround && this.slimeJumpDelay-- <= 0) 146 { 147 this.slimeJumpDelay = this.getJumpDelay(); 148 149 if (var1 != null) 150 { 151 this.slimeJumpDelay /= 3; 152 } 153 154 this.isJumping = true; 155 156 if (this.makesSoundOnJump()) 157 { 158 this.func_85030_a(this.getJumpSound(), this.getSoundVolume(), ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F) * 0.8F); 159 } 160 161 this.moveStrafing = 1.0F - this.rand.nextFloat() * 2.0F; 162 this.moveForward = (float)(1 * this.getSlimeSize()); 163 } 164 else 165 { 166 this.isJumping = false; 167 168 if (this.onGround) 169 { 170 this.moveStrafing = this.moveForward = 0.0F; 171 } 172 } 173 } 174 175 protected void func_70808_l() 176 { 177 this.field_70813_a *= 0.6F; 178 } 179 180 /** 181 * Gets the amount of time the slime needs to wait between jumps. 182 */ 183 protected int getJumpDelay() 184 { 185 return this.rand.nextInt(20) + 10; 186 } 187 188 protected EntitySlime createInstance() 189 { 190 return new EntitySlime(this.worldObj); 191 } 192 193 /** 194 * Will get destroyed next tick. 195 */ 196 public void setDead() 197 { 198 int var1 = this.getSlimeSize(); 199 200 if (!this.worldObj.isRemote && var1 > 1 && this.getHealth() <= 0) 201 { 202 int var2 = 2 + this.rand.nextInt(3); 203 204 for (int var3 = 0; var3 < var2; ++var3) 205 { 206 float var4 = ((float)(var3 % 2) - 0.5F) * (float)var1 / 4.0F; 207 float var5 = ((float)(var3 / 2) - 0.5F) * (float)var1 / 4.0F; 208 EntitySlime var6 = this.createInstance(); 209 var6.setSlimeSize(var1 / 2); 210 var6.setLocationAndAngles(this.posX + (double)var4, this.posY + 0.5D, this.posZ + (double)var5, this.rand.nextFloat() * 360.0F, 0.0F); 211 this.worldObj.spawnEntityInWorld(var6); 212 } 213 } 214 215 super.setDead(); 216 } 217 218 /** 219 * Called by a player entity when they collide with an entity 220 */ 221 public void onCollideWithPlayer(EntityPlayer par1EntityPlayer) 222 { 223 if (this.canDamagePlayer()) 224 { 225 int var2 = this.getSlimeSize(); 226 227 if (this.canEntityBeSeen(par1EntityPlayer) && this.getDistanceSqToEntity(par1EntityPlayer) < 0.6D * (double)var2 * 0.6D * (double)var2 && par1EntityPlayer.attackEntityFrom(DamageSource.causeMobDamage(this), this.getAttackStrength())) 228 { 229 this.func_85030_a("mob.attack", 1.0F, (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F); 230 } 231 } 232 } 233 234 /** 235 * Indicates weather the slime is able to damage the player (based upon the slime's size) 236 */ 237 protected boolean canDamagePlayer() 238 { 239 return this.getSlimeSize() > 1; 240 } 241 242 /** 243 * Gets the amount of damage dealt to the player when "attacked" by the slime. 244 */ 245 protected int getAttackStrength() 246 { 247 return this.getSlimeSize(); 248 } 249 250 /** 251 * Returns the sound this mob makes when it is hurt. 252 */ 253 protected String getHurtSound() 254 { 255 return "mob.slime." + (this.getSlimeSize() > 1 ? "big" : "small"); 256 } 257 258 /** 259 * Returns the sound this mob makes on death. 260 */ 261 protected String getDeathSound() 262 { 263 return "mob.slime." + (this.getSlimeSize() > 1 ? "big" : "small"); 264 } 265 266 /** 267 * Returns the item ID for the item the mob drops on death. 268 */ 269 protected int getDropItemId() 270 { 271 return this.getSlimeSize() == 1 ? Item.slimeBall.shiftedIndex : 0; 272 } 273 274 /** 275 * Checks if the entity's current position is a valid location to spawn this entity. 276 */ 277 public boolean getCanSpawnHere() 278 { 279 Chunk var1 = this.worldObj.getChunkFromBlockCoords(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posZ)); 280 281 if (this.worldObj.getWorldInfo().getTerrainType().handleSlimeSpawnReduction(rand, worldObj)) 282 { 283 return false; 284 } 285 else 286 { 287 if (this.getSlimeSize() == 1 || this.worldObj.difficultySetting > 0) 288 { 289 if (this.worldObj.getBiomeGenForCoords(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posZ)) == BiomeGenBase.swampland && this.posY > 50.0D && this.posY < 70.0D && this.worldObj.getBlockLightValue(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ)) <= this.rand.nextInt(8)) 290 { 291 return super.getCanSpawnHere(); 292 } 293 294 if (this.rand.nextInt(10) == 0 && var1.getRandomWithSeed(987234911L).nextInt(10) == 0 && this.posY < 40.0D) 295 { 296 return super.getCanSpawnHere(); 297 } 298 } 299 300 return false; 301 } 302 } 303 304 /** 305 * Returns the volume for the sounds this mob makes. 306 */ 307 protected float getSoundVolume() 308 { 309 return 0.4F * (float)this.getSlimeSize(); 310 } 311 312 /** 313 * The speed it takes to move the entityliving's rotationPitch through the faceEntity method. This is only currently 314 * use in wolves. 315 */ 316 public int getVerticalFaceSpeed() 317 { 318 return 0; 319 } 320 321 /** 322 * Returns true if the slime makes a sound when it jumps (based upon the slime's size) 323 */ 324 protected boolean makesSoundOnJump() 325 { 326 return this.getSlimeSize() > 0; 327 } 328 329 /** 330 * Returns true if the slime makes a sound when it lands after a jump (based upon the slime's size) 331 */ 332 protected boolean makesSoundOnLand() 333 { 334 return this.getSlimeSize() > 2; 335 } 336 }