package mods.tinker.tconstruct.entity; import mods.tinker.tconstruct.TConstruct; import mods.tinker.tconstruct.common.TContent; import mods.tinker.tconstruct.library.TConstructRegistry; import mods.tinker.tconstruct.library.crafting.ToolBuilder; import mods.tinker.tconstruct.library.tools.ToolCore; import net.minecraft.block.material.Material; import net.minecraft.entity.EntityList; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.boss.IBossDisplayData; import net.minecraft.entity.monster.EntityCreeper; import net.minecraft.entity.monster.EntitySkeleton; import net.minecraft.entity.monster.IMob; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.potion.Potion; import net.minecraft.util.DamageSource; import net.minecraft.util.MathHelper; import net.minecraft.util.StatCollector; import net.minecraft.world.EnumSkyBlock; import net.minecraft.world.World; import net.minecraftforge.common.ForgeHooks; public class BlueSlime extends EntityLiving implements IMob, IBossDisplayData { private static final float[] field_100000_e = new float[] { 1.0F, 0.75F, 0.5F, 0.25F, 0.0F, 0.25F, 0.5F, 0.75F }; public float sizeOffset; public float sizeFactor; public float sizeHeight; /** the time between each jump of the slime */ protected int slimeJumpDelay = 0; public BlueSlime(World world) { super(world); this.texture = "/mods/tinker/textures/mob/slimeedible.png"; int offset = this.rand.nextInt(299); if (offset < 149) offset = 1; else if (offset < 298) offset = 2; else offset = 3; int size = 1 << offset; this.yOffset = 0.0F; this.slimeJumpDelay = this.rand.nextInt(120) + 40; this.setSlimeSize(size); this.jumpMovementFactor = 0.004F * size + 0.01F; } protected void damageEntity (DamageSource damageSource, int damage) { //Minecraft.getMinecraft().getLogAgent().logInfo("Damage: "+damage); if (damageSource.damageType.equals("arrow")) damage = damage / 2; super.damageEntity(damageSource, damage); } public String getEntityName () { String s = EntityList.getEntityString(this); if (s == null) { s = "generic"; } if (getSlimeSize() >= 8) s = "TConstruct.KingSlime"; return StatCollector.translateToLocal("entity." + s + ".name"); } @Override public void initCreature () { if (getSlimeSize() == 2 && rand.nextInt(8) == 0) { EntitySkeleton entityskeleton = new EntitySkeleton(this.worldObj); entityskeleton.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, 0.0F); entityskeleton.initCreature(); this.worldObj.spawnEntityInWorld(entityskeleton); entityskeleton.mountEntity(this); } if (getSlimeSize() == 4 && rand.nextInt(12) == 0) { EntityCreeper creeper = new EntityCreeper(this.worldObj); creeper.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, 0.0F); creeper.initCreature(); this.worldObj.spawnEntityInWorld(creeper); creeper.mountEntity(this); } if (getSlimeSize() == 8) { for (int i = 0; i < 5; i++) { BlueSlime slime = new BlueSlime(this.worldObj); slime.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, 0.0F); slime.initCreature(); this.worldObj.spawnEntityInWorld(slime); } BlueSlime slime = new BlueSlime(this.worldObj); slime.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, 0.0F); slime.setSlimeSize(2); this.worldObj.spawnEntityInWorld(slime); EntitySkeleton skelton = new EntitySkeleton(this.worldObj); skelton.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, 0.0F); skelton.initCreature(); this.worldObj.spawnEntityInWorld(skelton); skelton.mountEntity(slime); } } @Override public double getMountedYOffset () { return this.height * 0.3; } protected void jump () { this.motionY = 0.05 * getSlimeSize() + 0.37; if (this.isPotionActive(Potion.jump)) { this.motionY += (double) ((float) (this.getActivePotionEffect(Potion.jump).getAmplifier() + 1) * 0.1F); } if (this.isSprinting()) { float f = this.rotationYaw * 0.017453292F; this.motionX -= (double) (MathHelper.sin(f) * 0.2F); this.motionZ += (double) (MathHelper.cos(f) * 0.2F); } if (this.getBrightness(1.0F) > 0.9F && rand.nextInt(5) == 0 && this.worldObj.canBlockSeeTheSky(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ))) { int size = this.getSlimeSize() - 1; if (size < 7) { if (size <= 0) this.kill(); else this.setSlimeSize(size); } } this.isAirBorne = true; ForgeHooks.onLivingJump(this); } protected void fall (float par1) { } protected String getSlimeParticle () { return "blueslime"; } @Override public boolean getCanSpawnHere () { return isValidLightLevel() && this.worldObj.checkNoEntityCollision(this.boundingBox) && this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox).isEmpty() && !this.worldObj.isAnyLiquid(this.boundingBox); } protected boolean isValidLightLevel () { int x = MathHelper.floor_double(this.posX); int y = MathHelper.floor_double(this.boundingBox.minY); int z = MathHelper.floor_double(this.posZ); if (y < 60 && rand.nextInt(5) != 0) { return false; } if (this.worldObj.getSavedLightValue(EnumSkyBlock.Sky, x, y, z) > this.rand.nextInt(32)) { return false; } else { int light = this.worldObj.getBlockLightValue(x, y, z); if (this.worldObj.isThundering()) { int i1 = this.worldObj.skylightSubtracted; this.worldObj.skylightSubtracted = 10; light = this.worldObj.getBlockLightValue(x, y, z); this.worldObj.skylightSubtracted = i1; } return light <= this.rand.nextInt(8); } } protected void entityInit () { super.entityInit(); this.dataWatcher.addObject(16, new Byte((byte) 1)); this.dataWatcher.addObject(17, new Integer(100)); } public void setSlimeSize (int size) { this.dataWatcher.updateObject(16, new Byte((byte) size)); this.setSize(0.6F * size, 0.6F * size); this.setPosition(this.posX, this.posY, this.posZ); this.setEntityHealth(this.getMaxHealth()); this.experienceValue = size + 2; if (size >= 8) this.experienceValue = 500; } public int getMaxHealth () { int i = this.getSlimeSize(); if (i == 1) return 4; if (i == 8) return 100; return (int) Math.min(i * i + 8, 49); } /** * Returns the size of the slime. */ public int getSlimeSize () { return this.dataWatcher.getWatchableObjectByte(16); } /** * (abstract) Protected helper method to write subclass entity data to NBT. */ public void writeEntityToNBT (NBTTagCompound par1NBTTagCompound) { super.writeEntityToNBT(par1NBTTagCompound); par1NBTTagCompound.setInteger("Size", this.getSlimeSize() - 1); } /** * (abstract) Protected helper method to read subclass entity data from NBT. */ public void readEntityFromNBT (NBTTagCompound par1NBTTagCompound) { super.readEntityFromNBT(par1NBTTagCompound); this.setSlimeSize(par1NBTTagCompound.getInteger("Size") + 1); this.dataWatcher.updateObject(17, Integer.valueOf(this.health)); } /** * Returns the name of the sound played when the slime jumps. */ protected String getJumpSound () { return "mob.slime." + (this.getSlimeSize() > 1 ? "big" : "small"); } /** * Called to update the entity's position/logic. */ public void onUpdate () { if (!this.worldObj.isRemote && this.worldObj.difficultySetting == 0 && this.getSlimeSize() > 0) { this.isDead = true; } if (!this.worldObj.isRemote) { this.dataWatcher.updateObject(17, Integer.valueOf(this.health)); } this.sizeFactor += (this.sizeOffset - this.sizeFactor) * 0.5F; this.sizeHeight = this.sizeFactor; boolean flag = this.onGround; super.onUpdate(); int i; if (this.onGround && !flag) { i = this.getSlimeSize(); for (int j = 0; j < i * 8; ++j) { float f = this.rand.nextFloat() * (float) Math.PI * 2.0F; float offset = this.rand.nextFloat() * 0.5F + 0.5F; float xPos = MathHelper.sin(f) * (float) i * 0.5F * offset; float zPos = MathHelper.cos(f) * (float) i * 0.5F * offset; TConstruct.proxy.spawnParticle(this.getSlimeParticle(), this.posX + (double) xPos, this.boundingBox.minY, this.posZ + (double) zPos, 0.0D, 0.0D, 0.0D); } if (this.makesSoundOnLand()) { this.playSound(this.getJumpSound(), this.getSoundVolume(), ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F) / 0.8F); } this.sizeOffset = -0.5F; } else if (!this.onGround && flag) { this.sizeOffset = 1.0F; } this.func_70808_l(); if (this.worldObj.isRemote) { i = this.getSlimeSize(); this.setSize(0.6F * (float) i, 0.6F * (float) i); } } protected void updateEntityActionState () { //Minecraft.getMinecraft().getLogAgent().logInfo("Collided with "+entity.getEntityName()); this.despawnEntity(); EntityPlayer entityplayer = this.worldObj.getClosestVulnerablePlayerToEntity(this, 16.0D); if (entityplayer != null) { this.faceEntity(entityplayer, 10.0F, 20.0F); } else if (this.onGround && this.slimeJumpDelay == 1) { this.rotationYaw = this.rotationYaw + rand.nextFloat() * 180 - 90; if (rotationYaw > 360) rotationYaw -= 360; if (rotationYaw < 0) rotationYaw += 360; } if (this.onGround && this.slimeJumpDelay-- <= 0) { this.slimeJumpDelay = this.getJumpDelay(); if (entityplayer != null) { this.slimeJumpDelay /= 12; } this.isJumping = true; if (this.makesSoundOnJump()) { this.playSound(this.getJumpSound(), this.getSoundVolume(), ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F) * 0.8F); } this.moveStrafing = 1.0F - this.rand.nextFloat() * 2.0F; this.moveForward = (float) (1 * this.getSlimeSize()); } else { this.isJumping = false; if (this.onGround) { this.moveStrafing = this.moveForward = 0.0F; } } } public boolean handleWaterMovement() { return false; } protected void func_70808_l () { this.sizeOffset *= 0.6F; } /** * Gets the amount of time the slime needs to wait between jumps. */ protected int getJumpDelay () { return this.rand.nextInt(120) + 40; } protected BlueSlime createInstance () { return new BlueSlime(this.worldObj); } /** * Will get destroyed next tick. */ public void setDead () { int size = this.getSlimeSize(); if (!this.worldObj.isRemote && size > 1 && this.getHealth() <= 0 && size < 8) { float f = (-0.5F) * (float) size / 4.0F; float f1 = (-0.5F) * (float) size / 4.0F; BlueSlime entityslime = this.createInstance(); entityslime.setSlimeSize(size / 2); entityslime.setLocationAndAngles(this.posX + (double) f, this.posY + 0.5D, this.posZ + (double) f1, this.rand.nextFloat() * 360.0F, 0.0F); this.worldObj.spawnEntityInWorld(entityslime); } super.setDead(); } protected void dropFewItems (boolean par1, int par2) { int size = this.getSlimeSize(); int j = this.getDropItemId(); if (j > 0 && (rand.nextInt(2) == 0) || size >= 8) { int k = rand.nextInt(3) + rand.nextInt(this.getSlimeSize()); if (par2 > 0) { k += this.rand.nextInt(par2 + 1); } for (int l = 0; l < k; ++l) { this.dropItem(j, 1); } } if (size == 8) { ToolCore tool = getValidTool(); Item accessory = tool.getAccessoryItem(); ItemStack accessoryStack = accessory != null ? new ItemStack(tool.getAccessoryItem(), 1, 17) : null; ItemStack toolStack = ToolBuilder.instance.buildTool(new ItemStack(tool.getHeadItem(), 1, 17), new ItemStack(tool.getHandleItem(), 1, 17), accessoryStack, "King Slime " + tool.getToolName()); NBTTagCompound tags = toolStack.getTagCompound().getCompoundTag("InfiTool"); tags.setInteger("Attack", 3 + tool.getDamageVsEntity(null)); tags.setInteger("TotalDurability", 1500); tags.setInteger("BaseDurability", 1500); tags.setInteger("MiningSpeed", 800); this.entityDropItem(toolStack, 0f); if (rand.nextInt(5) == 0) { ItemStack dropStack = new ItemStack(TContent.heartCanister, 1, 1); this.entityDropItem(dropStack, 0f); } } } ToolCore getValidTool() { ToolCore tool = TConstructRegistry.tools.get(rand.nextInt(TConstructRegistry.tools.size())); if (tool.getAccessoryItem() != null) tool = getValidTool(); return tool; } /** * Called by a player entity when they collide with an entity */ public void onCollideWithPlayer (EntityPlayer par1EntityPlayer) { if (this.canDamagePlayer()) { int i = this.getSlimeSize(); if (this.canEntityBeSeen(par1EntityPlayer) && this.getDistanceSqToEntity(par1EntityPlayer) < 0.6D * (double) i * 0.6D * (double) i && par1EntityPlayer.attackEntityFrom(DamageSource.causeMobDamage(this), this.getAttackStrength())) { this.playSound("mob.attack", 1.0F, (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F); } } } /** * Indicates weather the slime is able to damage the player (based upon the slime's size) */ protected boolean canDamagePlayer () { return this.getSlimeSize() > 1; } /** * Gets the amount of damage dealt to the player when "attacked" by the slime. */ protected int getAttackStrength () { return this.getSlimeSize(); } /** * Returns the sound this mob makes when it is hurt. */ protected String getHurtSound () { return "mob.slime." + (this.getSlimeSize() > 1 ? "big" : "small"); } /** * Returns the sound this mob makes on death. */ protected String getDeathSound () { return "mob.slime." + (this.getSlimeSize() > 1 ? "big" : "small"); } /** * Returns the item ID for the item the mob drops on death. */ protected int getDropItemId () { return TContent.strangeFood.itemID; } /** * Returns the volume for the sounds this mob makes. */ protected float getSoundVolume () { return Math.min(0.05F * (float) this.getSlimeSize(), 0.3f); } /** * The speed it takes to move the entityliving's rotationPitch through the faceEntity method. This is only currently * use in wolves. */ public int getVerticalFaceSpeed () { return 0; } /** * Returns true if the slime makes a sound when it jumps (based upon the slime's size) */ protected boolean makesSoundOnJump () { return this.getSlimeSize() > 0; } /** * Returns true if the slime makes a sound when it lands after a jump (based upon the slime's size) */ protected boolean makesSoundOnLand () { return this.getSlimeSize() > 2; } @Override public int getBossHealth () { return this.dataWatcher.getWatchableObjectInt(17); } }