From d0894550633f5565dbc0cf14f78a7ae6bd57c2a7 Mon Sep 17 00:00:00 2001 From: Bernhard Bonigl Date: Sat, 29 Nov 2014 23:02:23 +0100 Subject: [PATCH] Separate BlueSlime and King Slime into separate entities + baseclass --- .../tconstruct/armor/TinkerArmorEvents.java | 6 - .../tconstruct/blocks/slime/SlimeFluid.java | 12 +- .../tconstruct/tools/items/TitleIcon.java | 13 +- .../java/tconstruct/world/TinkerWorld.java | 1 + .../world/TinkerWorldProxyClient.java | 4 +- .../tconstruct/world/entity/BlueSlime.java | 587 +----------------- .../world/entity/KingBlueSlime.java | 115 ++++ .../tconstruct/world/entity/MetalSlime.java | 2 +- .../tconstruct/world/entity/SlimeBase.java | 429 +++++++++++++ .../tconstruct/world/model/SlimeRender.java | 22 +- 10 files changed, 582 insertions(+), 609 deletions(-) create mode 100644 src/main/java/tconstruct/world/entity/KingBlueSlime.java create mode 100644 src/main/java/tconstruct/world/entity/SlimeBase.java diff --git a/src/main/java/tconstruct/armor/TinkerArmorEvents.java b/src/main/java/tconstruct/armor/TinkerArmorEvents.java index 0ba03176044..13e904d7b89 100644 --- a/src/main/java/tconstruct/armor/TinkerArmorEvents.java +++ b/src/main/java/tconstruct/armor/TinkerArmorEvents.java @@ -35,12 +35,6 @@ public void onLivingDrop (LivingDropsEvent event) if (event.entityLiving instanceof IBossDisplayData) { - if (event.entityLiving instanceof BlueSlime) - { - BlueSlime slime = (BlueSlime) event.entityLiving; - if (slime.getSlimeSize() < 8) - return; - } String entityName = event.entityLiving.getClass().getSimpleName().toLowerCase(); if (entityName.contains("entitynpc") || entityName.contains("entitycustomnpc")) return; diff --git a/src/main/java/tconstruct/blocks/slime/SlimeFluid.java b/src/main/java/tconstruct/blocks/slime/SlimeFluid.java index cbe68d32c8e..fc8994d3412 100644 --- a/src/main/java/tconstruct/blocks/slime/SlimeFluid.java +++ b/src/main/java/tconstruct/blocks/slime/SlimeFluid.java @@ -10,6 +10,8 @@ import net.minecraftforge.fluids.*; import tconstruct.world.TinkerWorld; import tconstruct.world.entity.BlueSlime; +import tconstruct.world.entity.KingBlueSlime; +import tconstruct.world.entity.SlimeBase; public class SlimeFluid extends BlockFluidClassic { @@ -46,9 +48,13 @@ public void updateTick (World world, int x, int y, int z, Random rand) super.updateTick(world, x, y, z, rand); if (rand.nextInt(100) == 0 && world.getBlockMetadata(x, y, z) == 0 && world.checkNoEntityCollision(AxisAlignedBB.getBoundingBox(x - 1, y - 1, z - 1, x + 2, y + 2, z + 2))) { - BlueSlime entityslime = new BlueSlime(world); - entityslime.setPosition((double) x + 0.5D, (double) y + 1.5D, (double) z + 0.5D); - world.spawnEntityInWorld(entityslime); + SlimeBase slime; + if(rand.nextInt(300) == 0) + slime = new KingBlueSlime(world); + else + slime = new BlueSlime(world); + slime.setPosition((double) x + 0.5D, (double) y + 1.5D, (double) z + 0.5D); + world.spawnEntityInWorld(slime); } } diff --git a/src/main/java/tconstruct/tools/items/TitleIcon.java b/src/main/java/tconstruct/tools/items/TitleIcon.java index 238eb8a031c..d1392b9be4e 100644 --- a/src/main/java/tconstruct/tools/items/TitleIcon.java +++ b/src/main/java/tconstruct/tools/items/TitleIcon.java @@ -15,7 +15,9 @@ import tconstruct.client.TProxyClient; import tconstruct.library.tools.ToolCore; import tconstruct.world.entity.BlueSlime; +import tconstruct.world.entity.KingBlueSlime; +// spawn egg. public class TitleIcon extends Item { int[] primaryColor = { 0x66BBE8, 0x66BBE8 }; @@ -29,6 +31,7 @@ public TitleIcon() { super(); this.setCreativeTab(CreativeTabs.tabMisc); + this.setHasSubtypes(true); } @Override @@ -135,7 +138,7 @@ public boolean onItemUse (ItemStack stack, EntityPlayer player, World world, int spawnEntity(posX, posY, posZ, new BlueSlime(world), world, player); break; case 1: - spawnBossSlime(posX, posY, posZ, new BlueSlime(world), world, player); + spawnBossSlime(posX, posY, posZ, new KingBlueSlime(world), world, player); break; } if (!player.capabilities.isCreativeMode) @@ -168,8 +171,8 @@ public static EntityLiving activateSpawnEgg (ItemStack stack, World world, doubl spawnEntity(posX, posY, posZ, entity, world); break; case 1: - entity = new BlueSlime(world); - spawnBossSlime(posX, posY, posZ, new BlueSlime(world), world); + entity = new KingBlueSlime(world); + spawnBossSlime(posX, posY, posZ, new KingBlueSlime(world), world); break; } return entity; @@ -197,7 +200,7 @@ public static void spawnEntity (double x, double y, double z, Entity entity, Wor } } - public static void spawnBossSlime (double x, double y, double z, BlueSlime entity, World world, EntityPlayer player) + public static void spawnBossSlime (double x, double y, double z, KingBlueSlime entity, World world, EntityPlayer player) { if (!world.isRemote) { @@ -208,7 +211,7 @@ public static void spawnBossSlime (double x, double y, double z, BlueSlime entit } } - public static void spawnBossSlime (double x, double y, double z, BlueSlime entity, World world) + public static void spawnBossSlime (double x, double y, double z, KingBlueSlime entity, World world) { if (!world.isRemote) { diff --git a/src/main/java/tconstruct/world/TinkerWorld.java b/src/main/java/tconstruct/world/TinkerWorld.java index bd14afcbcd5..24945fe8681 100644 --- a/src/main/java/tconstruct/world/TinkerWorld.java +++ b/src/main/java/tconstruct/world/TinkerWorld.java @@ -269,6 +269,7 @@ public void createEntities () // TConstruct.instance, 32, 5, true); EntityRegistry.registerModEntity(BlueSlime.class, "EdibleSlime", 12, TConstruct.instance, 64, 5, true); + EntityRegistry.registerModEntity(KingBlueSlime.class, "KingSlime", 14, TConstruct.instance, 64, 5, true); // EntityRegistry.registerModEntity(MetalSlime.class, "MetalSlime", 13, // TConstruct.instance, 64, 5, true); diff --git a/src/main/java/tconstruct/world/TinkerWorldProxyClient.java b/src/main/java/tconstruct/world/TinkerWorldProxyClient.java index 310e6aabcdd..111ea8928bd 100644 --- a/src/main/java/tconstruct/world/TinkerWorldProxyClient.java +++ b/src/main/java/tconstruct/world/TinkerWorldProxyClient.java @@ -35,7 +35,9 @@ void registerRenderer () RenderingRegistry.registerBlockHandler(new SlimePadRender()); // Entities - RenderingRegistry.registerEntityRenderingHandler(BlueSlime.class, new SlimeRender(new ModelSlime(16), new ModelSlime(0), 0.25F)); + SlimeRender slimeRender = new SlimeRender(new ModelSlime(16), new ModelSlime(0), 0.25F); + RenderingRegistry.registerEntityRenderingHandler(BlueSlime.class, slimeRender); + RenderingRegistry.registerEntityRenderingHandler(KingBlueSlime.class, slimeRender); RenderingRegistry.registerEntityRenderingHandler(CartEntity.class, new CartRender()); VillagerRegistry.instance().registerVillagerSkin(78943, new ResourceLocation("tinker", "textures/mob/villagertools.png")); diff --git a/src/main/java/tconstruct/world/entity/BlueSlime.java b/src/main/java/tconstruct/world/entity/BlueSlime.java index f3d8246dd04..31d60881334 100644 --- a/src/main/java/tconstruct/world/entity/BlueSlime.java +++ b/src/main/java/tconstruct/world/entity/BlueSlime.java @@ -1,554 +1,13 @@ package tconstruct.world.entity; -import net.minecraft.entity.*; -import net.minecraft.entity.ai.EntitySenses; -import net.minecraft.entity.boss.IBossDisplayData; -import net.minecraft.entity.monster.*; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.*; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.potion.Potion; -import net.minecraft.util.*; +import net.minecraft.item.Item; import net.minecraft.world.*; -import net.minecraftforge.common.ForgeHooks; -import tconstruct.armor.TinkerArmor; -import tconstruct.library.TConstructRegistry; -import tconstruct.library.crafting.ToolBuilder; -import tconstruct.library.tools.ToolCore; import tconstruct.world.TinkerWorld; -public class BlueSlime extends EntityLiving implements IMob, IBossDisplayData +public class BlueSlime extends SlimeBase { - 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) - { + public BlueSlime(World world) { super(world); - initializeSlime(); - } - - protected void initializeSlime () - { - 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) - { - if (damageSource.damageType.equals("arrow")) - damage = damage / 2; - super.damageEntity(damageSource, damage); - } - - @Override - public String getCommandSenderName() { - if (getSlimeSize() >= 8) - return StatCollector.translateToLocal("entity.TConstruct.KingSlime.name"); - - return super.getCommandSenderName(); - } - - @Override - public IEntityLivingData onSpawnWithEgg (IEntityLivingData par1EntityLivingData) - { - Object par1EntityLivingData1 = super.onSpawnWithEgg(par1EntityLivingData); - - 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.onSpawnWithEgg(par1EntityLivingData); - 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.onSpawnWithEgg(par1EntityLivingData); - 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.onSpawnWithEgg(par1EntityLivingData); - 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.onSpawnWithEgg(par1EntityLivingData); - this.worldObj.spawnEntityInWorld(skelton); - skelton.mountEntity(slime); - } - - return (IEntityLivingData) par1EntityLivingData1; - } - - @Override - public double getMountedYOffset () - { - return this.height * 0.3; - } - - @Override - public 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); - } - - @Override - 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 (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); - } - /*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); - }*/ - } - - @Override - protected void entityInit () - { - super.entityInit(); - this.dataWatcher.addObject(16, new Byte((byte) 1)); - } - - public void setSlimeSize (int size) - { - this.dataWatcher.updateObject(16, new Byte((byte) size)); - this.setSize(0.6F * (float) size, 0.6F * (float) size); - this.setPosition(this.posX, this.posY, this.posZ); - this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(this.getMaxHealthForSize()); - this.setHealth(this.getMaxHealthForSize()); - - this.experienceValue = size + 2 ^ (size); - if (size >= 8) - this.experienceValue = 500; - } - - // Invoked by constructor to set max health dependant on current size - private float getMaxHealthForSize () - { - int i = this.getSlimeSize(); - if (i == 1) - return 4; - if (i == 8) - return 100; - return (float) 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. - */ - @Override - 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. - */ - @Override - 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. - */ - @Override - public void onUpdate () - { - if (!this.worldObj.isRemote && this.worldObj.difficultySetting == EnumDifficulty.PEACEFUL && this.getSlimeSize() > 0) - { - this.isDead = true; - } - - 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; - TinkerWorld.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.alterSquishAmount(); - - if (this.worldObj.isRemote) - { - i = this.getSlimeSize(); - this.setSize(0.6F * (float) i, 0.6F * (float) i); - } - } - - @Override - protected void updateEntityActionState () - { - // Minecraft.getMinecraft().getLogAgent().logInfo("Collided with "+entity.getEntityName()); - if (this.getSlimeSize() < 8) - 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; - } - } - } - - @Override - public boolean handleWaterMovement () - { - return false; - } - - protected void alterSquishAmount () - { - 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. - */ - @Override - 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(); - } - - @Override - protected void dropFewItems (boolean par1, int par2) - { - int size = this.getSlimeSize(); - Item j = this.getDropItem(); - - if (j != null && (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.entityDropItem(new ItemStack(j), 1); - } - } - - if (size == 8) - { - ToolCore tool = getValidTool(); - - final ItemStack headStack = new ItemStack(tool.getHeadItem(), 1, 17); - final ItemStack handleStack = new ItemStack(tool.getHandleItem(), 1, 17); - final ItemStack accessoryStack = tool.getAccessoryItem() != null ? new ItemStack(tool.getAccessoryItem(), 1, 17) : null; - final ItemStack extraStack = tool.getExtraItem() != null ? new ItemStack(tool.getExtraItem(), 1, 17) : null; - - String loc = "tool." + tool.getToolName().toLowerCase() + ".kingslime"; // special localization the same way as materials - String name; - if(StatCollector.canTranslate(loc)) - name = StatCollector.translateToLocal(loc); - else - name = StatCollector.translateToLocal("tool.kingslimeprefix") + " " + tool.getLocalizedToolName(); - - ItemStack toolStack = ToolBuilder.instance.buildTool(headStack, handleStack, accessoryStack, extraStack, name); - - if (toolStack != null) - { - NBTTagCompound tags = toolStack.getTagCompound().getCompoundTag("InfiTool"); - tags.setInteger("Attack", 5 + tool.getDamageVsEntity(null)); - tags.setInteger("TotalDurability", 2500); - tags.setInteger("BaseDurability", 2500); - tags.setInteger("MiningSpeed", 1400); - - this.entityDropItem(toolStack, 0f); - if (rand.nextInt(5) == 0) - { - ItemStack dropStack = new ItemStack(TinkerArmor.heartCanister, 1, 1); - this.entityDropItem(dropStack, 0f); - } - } - } - } - - ToolCore getValidTool () - { - ToolCore tool = TConstructRegistry.tools.get(rand.nextInt(TConstructRegistry.tools.size())); - /*if (tool.getExtraItem() != null) - tool = getValidTool();*/ - return tool; - } - - /** - * Called by a player entity when they collide with an entity - */ - @Override - 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. - */ - @Override - protected String getHurtSound () - { - return "mob.slime." + (this.getSlimeSize() > 1 ? "big" : "small"); - } - - /** - * Returns the sound this mob makes on death. - */ - @Override - protected String getDeathSound () - { - return "mob.slime." + (this.getSlimeSize() > 1 ? "big" : "small"); } /** @@ -560,45 +19,13 @@ protected Item getDropItem () return TinkerWorld.strangeFood; } - /** - * Returns the volume for the sounds this mob makes. - */ @Override - protected float getSoundVolume () - { - return Math.min(0.05F * (float) this.getSlimeSize(), 0.3f); + protected String getSlimeParticle() { + return "blueslime"; } - /** - * The speed it takes to move the entityliving's rotationPitch through the - * faceEntity method. This is only currently use in wolves. - */ @Override - public int getVerticalFaceSpeed () - { - return 0; + protected SlimeBase createInstance(World world) { + return new BlueSlime(world); } - - /** - * 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); } - */ } diff --git a/src/main/java/tconstruct/world/entity/KingBlueSlime.java b/src/main/java/tconstruct/world/entity/KingBlueSlime.java new file mode 100644 index 00000000000..61f4b35dc17 --- /dev/null +++ b/src/main/java/tconstruct/world/entity/KingBlueSlime.java @@ -0,0 +1,115 @@ +package tconstruct.world.entity; + +import net.minecraft.entity.boss.IBossDisplayData; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.StatCollector; +import net.minecraft.world.World; +import tconstruct.armor.TinkerArmor; +import tconstruct.library.TConstructRegistry; +import tconstruct.library.crafting.ToolBuilder; +import tconstruct.library.tools.ToolCore; + +public class KingBlueSlime extends SlimeBase implements IBossDisplayData { + public KingBlueSlime(World world) { + super(world); + + this.experienceValue = 500; + + // persistance required. this is used by named entities to not despawn, for example. + func_110163_bv(); + } + + @Override + protected String getSlimeParticle() { + return "blueslime"; + } + + @Override + protected SlimeBase createInstance(World world) { + return new KingBlueSlime(world); + } + + @Override + protected void initializeSlime() { + this.yOffset = 0.0F; + this.slimeJumpDelay = this.rand.nextInt(120) + 40; + this.setSlimeSize(8); + } + + @Override + protected float getMaxHealthForSize() { + return 100; + } + + @Override + protected boolean canDespawn() { + return false; + } + + @Override + public void setDead() { + if (!this.worldObj.isRemote && this.getHealth() <= 0) + { + // doesn't break into the next smaller one. let's spawn many tiny slimes instead! :D + int c = 15 + this.rand.nextInt(6); + for(; c > 0; c--) { + BlueSlime entityslime = new BlueSlime(this.worldObj); + entityslime.setSlimeSize(1); + double r = rand.nextDouble() * Math.PI; + double x = Math.cos(r); + double z = Math.sin(r); + entityslime.setLocationAndAngles(this.posX - 1d + x, this.posY + 0.5D, this.posZ - 1d + z, this.rand.nextFloat() * 360.0F, 0.0F); + entityslime.setVelocity(x, -0.5d - rand.nextDouble(), z); + this.worldObj.spawnEntityInWorld(entityslime); + } + } + + this.isDead = true; + } + + @Override + protected void dropFewItems(boolean par1, int par2) { + super.dropFewItems(par1, par2); + + ToolCore tool = getValidTool(); + + final ItemStack headStack = new ItemStack(tool.getHeadItem(), 1, 17); + final ItemStack handleStack = new ItemStack(tool.getHandleItem(), 1, 17); + final ItemStack accessoryStack = tool.getAccessoryItem() != null ? new ItemStack(tool.getAccessoryItem(), 1, 17) : null; + final ItemStack extraStack = tool.getExtraItem() != null ? new ItemStack(tool.getExtraItem(), 1, 17) : null; + + String loc = "tool." + tool.getToolName().toLowerCase() + ".kingslime"; // special localization the same way as materials + String name; + if(StatCollector.canTranslate(loc)) + name = StatCollector.translateToLocal(loc); + else + name = StatCollector.translateToLocal("tool.kingslimeprefix") + " " + tool.getLocalizedToolName(); + + ItemStack toolStack = ToolBuilder.instance.buildTool(headStack, handleStack, accessoryStack, extraStack, name); + + if (toolStack != null) + { + NBTTagCompound tags = toolStack.getTagCompound().getCompoundTag("InfiTool"); + tags.setInteger("Attack", 5 + tool.getDamageVsEntity(null)); + tags.setInteger("TotalDurability", 2500); + tags.setInteger("BaseDurability", 2500); + tags.setInteger("MiningSpeed", 1400); + + this.entityDropItem(toolStack, 0f); + if (rand.nextInt(5) == 0) + { + ItemStack dropStack = new ItemStack(TinkerArmor.heartCanister, 1, 1); + this.entityDropItem(dropStack, 0f); + } + } + } + + ToolCore getValidTool () + { + ToolCore tool = TConstructRegistry.tools.get(rand.nextInt(TConstructRegistry.tools.size())); + /*if (tool.getExtraItem() != null) + tool = getValidTool();*/ + return tool; + } +} diff --git a/src/main/java/tconstruct/world/entity/MetalSlime.java b/src/main/java/tconstruct/world/entity/MetalSlime.java index bd7ca9f3958..4b28c1a1fe4 100644 --- a/src/main/java/tconstruct/world/entity/MetalSlime.java +++ b/src/main/java/tconstruct/world/entity/MetalSlime.java @@ -22,7 +22,7 @@ public boolean attackEntityFrom (DamageSource damageSource, int damage) } // Invoked by constructor to set max health dependant on current size - private float getMaxHealthForSize () + protected float getMaxHealthForSize () { int i = this.getSlimeSize(); if (i == 1) diff --git a/src/main/java/tconstruct/world/entity/SlimeBase.java b/src/main/java/tconstruct/world/entity/SlimeBase.java new file mode 100644 index 00000000000..f59f8ce15ec --- /dev/null +++ b/src/main/java/tconstruct/world/entity/SlimeBase.java @@ -0,0 +1,429 @@ +package tconstruct.world.entity; + +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.boss.IBossDisplayData; +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.world.EnumDifficulty; +import net.minecraft.world.EnumSkyBlock; +import net.minecraft.world.World; +import net.minecraftforge.common.ForgeHooks; +import tconstruct.world.TinkerWorld; + +public abstract class SlimeBase extends EntityLiving implements IMob { + public float sizeOffset; + public float sizeFactor; + public float sizeHeight; + + /** the time between each jump of the slime, used for counting */ + protected int slimeJumpDelay = 0; + + + public SlimeBase(World world) + { + super(world); + initializeSlime(); + } + + + /** Returns the name of the particle used by the slime */ + protected abstract String getSlimeParticle(); + + /** Returns the name of the sound played when the slime jumps. */ + protected String getJumpSound () + { + return "mob.slime." + (this.getSlimeSize() > 1 ? "big" : "small"); + } + + /** 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; + } + + public int getSlimeSize () + { + return this.dataWatcher.getWatchableObjectByte(16); + } + + public void setSlimeSize (int size) + { + this.dataWatcher.updateObject(16, (byte) size); + this.setSize(0.6F * (float) size, 0.6F * (float) size); + this.setPosition(this.posX, this.posY, this.posZ); + this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(this.getMaxHealthForSize()); + this.setHealth(this.getMaxHealthForSize()); + + this.jumpMovementFactor = 0.004F * size + 0.01F; + + this.experienceValue = size + 2 ^ (size); + } + + /** returns the health for the slime depending on its size */ + protected float getMaxHealthForSize () + { + int i = this.getSlimeSize(); + if (i == 1) + return 4; + + return (float) Math.min(i * i + 8, 49); + } + + /** Gets the amount of time the slime needs to wait between jumps. */ + protected int getJumpDelay () + { + return this.rand.nextInt(120) + 40; + } + + /** + * 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(); + } + + /** + * Return an instance of the implementing entity here. Used for the slime splitting on death. + */ + protected abstract SlimeBase createInstance(World world); + + + + + + protected void initializeSlime() + { + 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); + } + + @Override + protected void entityInit () + { + super.entityInit(); + this.dataWatcher.addObject(16, (byte) 1); + } + + @Override + public 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 instanceof IBossDisplayData) && 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 <= 0) + this.kill(); + else + this.setSlimeSize(size); + } + + this.isAirBorne = true; + ForgeHooks.onLivingJump(this); + } + + /** + * Called to update the entity's position/logic. + */ + @Override + public void onUpdate () + { + if (!this.worldObj.isRemote && this.worldObj.difficultySetting == EnumDifficulty.PEACEFUL && this.getSlimeSize() > 0) + { + this.isDead = true; + } + + 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; + TinkerWorld.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.alterSquishAmount(); + + if (this.worldObj.isRemote) + { + i = this.getSlimeSize(); + this.setSize(0.6F * (float) i, 0.6F * (float) i); + } + } + + protected void alterSquishAmount () + { + this.sizeOffset *= 0.6F; + } + + @Override + protected void updateEntityActionState () + { + 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) this.getSlimeSize(); + } + else + { + this.isJumping = false; + + if (this.onGround) + { + this.moveStrafing = this.moveForward = 0.0F; + } + } + } + + @Override + 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); + } + } + } + + @Override + 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; + SlimeBase entityslime = this.createInstance(this.worldObj); + 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(); + } + + // Drops items depending on slime size + @Override + protected void dropFewItems (boolean par1, int par2) + { + int size = this.getSlimeSize(); + Item j = this.getDropItem(); + + if (j != null && (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.entityDropItem(new ItemStack(j), 1); + } + } + } + + @Override + protected void fall (float distance) + { + // we call the event for proper behaviour with other stuff + ForgeHooks.onLivingFall(this, distance); + // but don't calc damage or anything + } + + @Override + public boolean getCanSpawnHere () + { + // needs free space + if(!this.worldObj.checkNoEntityCollision(this.boundingBox) || !this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox).isEmpty() || this.worldObj.isAnyLiquid(this.boundingBox)) + return false; + + int x = MathHelper.floor_double(this.posX); + int y = MathHelper.floor_double(this.boundingBox.minY); + int z = MathHelper.floor_double(this.posZ); + + 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); + } + } + + // slime jockeys! + @Override + public double getMountedYOffset() + { + return this.height * 0.3; + } + + /** + * Returns the sound this mob makes when it is hurt. + */ + @Override + protected String getHurtSound () + { + return getJumpSound(); + } + + /** + * Returns the sound this mob makes on death. + */ + @Override + protected String getDeathSound () + { + return getJumpSound(); + } + + /** + * Returns the volume for the sounds this mob makes. + */ + @Override + protected float getSoundVolume () + { + return Math.min(0.05F * (float) this.getSlimeSize(), 0.3f); + } + + @Override + public int getVerticalFaceSpeed () + { + return 0; + } + + /** + * (abstract) Protected helper method to write subclass entity data to NBT. + */ + @Override + 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. + */ + @Override + public void readEntityFromNBT (NBTTagCompound par1NBTTagCompound) + { + super.readEntityFromNBT(par1NBTTagCompound); + this.setSlimeSize(par1NBTTagCompound.getInteger("Size") + 1); + } +} diff --git a/src/main/java/tconstruct/world/model/SlimeRender.java b/src/main/java/tconstruct/world/model/SlimeRender.java index ab97696cd87..03ef46751c6 100644 --- a/src/main/java/tconstruct/world/model/SlimeRender.java +++ b/src/main/java/tconstruct/world/model/SlimeRender.java @@ -7,7 +7,8 @@ import net.minecraft.entity.boss.BossStatus; import net.minecraft.util.ResourceLocation; import org.lwjgl.opengl.GL11; -import tconstruct.world.entity.BlueSlime; +import tconstruct.world.entity.KingBlueSlime; +import tconstruct.world.entity.SlimeBase; @SideOnly(Side.CLIENT) public class SlimeRender extends RenderLiving @@ -25,21 +26,16 @@ public SlimeRender(ModelBase par1ModelBase, ModelBase par2ModelBase, float par3) public void doRender (EntityLiving par1EntityLiving, double par2, double par4, double par6, float par8, float par9) { super.doRender(par1EntityLiving, par2, par4, par6, par8, par9); - renderBossHealth((BlueSlime) par1EntityLiving); - } - - public void renderBossHealth (BlueSlime slime) - { - if (slime.getSlimeSize() >= 8) - BossStatus.setBossStatus(slime, true); + if(par1EntityLiving instanceof KingBlueSlime) + BossStatus.setBossStatus((KingBlueSlime) par1EntityLiving, true); } /** * Determines whether Slime Render should pass or not. */ - protected int shouldSlimeRenderPass (BlueSlime blueSlime, int par2, float par3) + protected int shouldSlimeRenderPass (SlimeBase slime, int par2, float par3) { - if (blueSlime.isInvisible()) + if (slime.isInvisible()) { return 0; } @@ -66,7 +62,7 @@ else if (par2 == 0) /** * sets the scale for the slime based on getSlimeSize in EdibleSlime */ - protected void scaleSlime (BlueSlime par1EdibleSlime, float par2) + protected void scaleSlime (SlimeBase par1EdibleSlime, float par2) { float f1 = (float) par1EdibleSlime.getSlimeSize(); float f2 = (par1EdibleSlime.sizeHeight + (par1EdibleSlime.sizeFactor - par1EdibleSlime.sizeHeight) * par2) / (f1 * 0.5F + 1.0F); @@ -81,7 +77,7 @@ protected void scaleSlime (BlueSlime par1EdibleSlime, float par2) @Override protected void preRenderCallback (EntityLivingBase par1EntityLiving, float par2) { - this.scaleSlime((BlueSlime) par1EntityLiving, par2); + this.scaleSlime((SlimeBase) par1EntityLiving, par2); } /** @@ -90,7 +86,7 @@ protected void preRenderCallback (EntityLivingBase par1EntityLiving, float par2) @Override protected int shouldRenderPass (EntityLivingBase par1EntityLiving, int par2, float par3) { - return this.shouldSlimeRenderPass((BlueSlime) par1EntityLiving, par2, par3); + return this.shouldSlimeRenderPass((SlimeBase) par1EntityLiving, par2, par3); } @Override