package micdoodle8.mods.galacticraft.planets.venus.entities; import com.google.common.collect.Lists; import micdoodle8.mods.galacticraft.api.GalacticraftRegistry; import micdoodle8.mods.galacticraft.api.entity.IEntityBreathable; import micdoodle8.mods.galacticraft.core.entities.EntityBossBase; import micdoodle8.mods.galacticraft.core.entities.IBoss; import micdoodle8.mods.galacticraft.core.util.ConfigManagerCore; import micdoodle8.mods.galacticraft.planets.venus.VenusItems; import net.minecraft.block.Block; import net.minecraft.entity.*; import net.minecraft.entity.ai.*; import net.minecraft.entity.boss.IBossDisplayData; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Items; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.nbt.NBTTagLong; import net.minecraft.pathfinding.PathNavigate; import net.minecraft.pathfinding.PathNavigateGround; import net.minecraft.potion.Potion; import net.minecraft.potion.PotionEffect; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.BlockPos; import net.minecraft.util.DamageSource; import net.minecraft.util.MathHelper; import net.minecraft.world.World; import java.util.List; import java.util.Random; import java.util.UUID; public class EntitySpiderQueen extends EntityBossBase implements IEntityBreathable, IBoss, IBossDisplayData, IRangedAttackMob { public boolean shouldEvade; private List<EntityJuicer> juicersSpawned = Lists.newArrayList(); private List<UUID> spawnedPreload; private int rangedAttackTime; private int minRangedAttackTime; private int maxRangedAttackTime; public EntitySpiderQueen(World worldIn) { super(worldIn); this.setSize(1.4F, 0.9F); this.tasks.addTask(4, new EntityAIAttackOnCollide(this, EntityPlayer.class, 1.0, true)); this.tasks.addTask(5, new EntityAIWander(this, 0.8D)); this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F)); this.tasks.addTask(6, new EntityAILookIdle(this)); this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false)); this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, true)); this.maxRangedAttackTime = 60; this.minRangedAttackTime = 20; this.ignoreFrustumCheck = true; } @Override public boolean canBePushed() { return false; } @Override public double getMountedYOffset() { return (double)(this.height * 0.5F); } @Override protected PathNavigate getNewNavigator(World worldIn) { return new PathNavigateGround(this, worldIn); } @Override protected void entityInit() { super.entityInit(); this.dataWatcher.addObject(16, (byte)-1); } public byte getBurrowedCount() { return this.dataWatcher.getWatchableObjectByte(16); } public void setBurrowedCount(byte count) { this.dataWatcher.updateObject(16, count); } @Override public void onUpdate() { super.onUpdate(); if (!this.worldObj.isRemote) { if (!this.shouldEvade && this.deathTicks <= 0) { EntityLivingBase attackTarget = this.getAttackTarget(); if (attackTarget != null) { double dX = attackTarget.posX - this.posX; double dY = attackTarget.getEntityBoundingBox().minY + (double)(attackTarget.height / 3.0F) - this.posY; double dZ = attackTarget.posZ - this.posZ; float distance = 5.0F; double d0 = this.getDistanceSq(attackTarget.posX, attackTarget.getEntityBoundingBox().minY, attackTarget.posZ); this.getLookHelper().setLookPositionWithEntity(attackTarget, 30.0F, 30.0F); if (--this.rangedAttackTime == 0) { if (dX * dX + dY * dY + dZ * dZ > distance * distance) { float f = MathHelper.sqrt_double(d0) / distance; this.attackEntityWithRangedAttack(attackTarget, 0.0F); this.rangedAttackTime = MathHelper.floor_float(f * (float) (this.maxRangedAttackTime - this.minRangedAttackTime) + (float) this.minRangedAttackTime); } } else if (this.rangedAttackTime < 0) { float f2 = MathHelper.sqrt_double(d0) / distance; this.rangedAttackTime = MathHelper.floor_float(f2 * (float)(this.maxRangedAttackTime - this.minRangedAttackTime) + (float)this.minRangedAttackTime); } } } } if (this.spawnedPreload != null) { for (UUID id : this.spawnedPreload) { Entity entity = null; for (Entity e : this.worldObj.getLoadedEntityList()) { if (e.getUniqueID().equals(id)) { entity = e; break; } } if (entity instanceof EntityJuicer) { this.juicersSpawned.add((EntityJuicer) entity); } } if (this.juicersSpawned.size() == this.spawnedPreload.size()) { this.spawnedPreload.clear(); this.spawnedPreload = null; } } if (!this.worldObj.isRemote && this.shouldEvade) { if (this.spawner != null) { AxisAlignedBB roomBounds = this.spawner.getRangeBounds(); double tarX = (roomBounds.minX + roomBounds.maxX) / 2.0; double tarZ = (roomBounds.minZ + roomBounds.maxZ) / 2.0; double dX = tarX - this.posX; double dY = roomBounds.maxY - this.posY; double dZ = tarZ - this.posZ; double movespeed = 1.0 * this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).getAttributeValue(); this.motionX = Math.min(Math.max(dX / 2.0F, -movespeed), movespeed); this.motionZ = Math.min(Math.max(dZ / 2.0F, -movespeed), movespeed); this.navigator.tryMoveToXYZ(tarX, this.posY, tarZ, movespeed); if (Math.abs(dX) < 0.1 && Math.abs(dZ) < 0.1) { this.motionY = Math.min(dY, 0.2); if (Math.abs(dY) - this.height < 1.1 && Math.abs(this.posY - this.lastTickPosY) < 0.05) { if (this.getBurrowedCount() >= 0) { if (this.ticksExisted % 20 == 0) { if (this.juicersSpawned.size() < 6) { EntityJuicer juicer = new EntityJuicer(this.worldObj); double angle = Math.random() * 2 * Math.PI; double dist = 3.0F; juicer.setPosition(this.posX + dist * Math.sin(angle), this.posY + 0.2F, this.posZ + dist * Math.cos(angle)); juicer.setHanging(true); this.worldObj.spawnEntityInWorld(juicer); this.juicersSpawned.add(juicer); } } if (this.getBurrowedCount() < 20) { this.setBurrowedCount((byte) (this.getBurrowedCount() + 1)); } } else { this.setBurrowedCount((byte) 0); } } } } if (!this.juicersSpawned.isEmpty()) { boolean allDead = true; for (EntityJuicer juicer : this.juicersSpawned) { if (!juicer.isDead) { allDead = false; } } if (allDead) { this.juicersSpawned.clear(); this.shouldEvade = false; this.setBurrowedCount((byte) -1); } } } } @Override public ItemStack getGuaranteedLoot(Random rand) { List<ItemStack> stackList = GalacticraftRegistry.getDungeonLoot(3); return stackList.get(rand.nextInt(stackList.size())).copy(); } @Override public void knockBack(Entity entityIn, float par2, double par3, double par4) { } @Override protected void applyEntityAttributes() { super.applyEntityAttributes(); this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(150.0F * ConfigManagerCore.dungeonBossHealthMod); this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setBaseValue(0.250000001192092896D); } @Override protected float getSoundPitch() { return (this.rand.nextFloat() - this.rand.nextFloat()) * 0.1F + 0.4F; } @Override protected float getSoundVolume() { return 5.0F; } @Override protected String getLivingSound() { return "mob.spider.say"; } @Override protected String getHurtSound() { return "mob.spider.say"; } @Override protected String getDeathSound() { return "mob.spider.death"; } @Override protected void playStepSound(BlockPos pos, Block blockIn) { this.playSound("mob.spider.step", 0.5F, 0.5F); } @Override protected Item getDropItem() { return Items.string; } @Override protected void dropFewItems(boolean par1, int par2) { super.dropFewItems(par1, par2); if (par1 && (this.rand.nextInt(3) == 0 || this.rand.nextInt(1 + par2) > 0)) { this.dropItem(Items.spider_eye, 1); } } @Override public void setInWeb() { } @Override public EnumCreatureAttribute getCreatureAttribute() { return EnumCreatureAttribute.ARTHROPOD; } @Override public boolean isPotionApplicable(PotionEffect potioneffectIn) { return potioneffectIn.getPotionID() != Potion.poison.id && super.isPotionApplicable(potioneffectIn); } @Override public float getEyeHeight() { return 0.65F; } @Override public boolean canBreath() { return true; } @Override public boolean isEntityInvulnerable(DamageSource source) { if (this.getBurrowedCount() >= 0) { return true; } return super.isEntityInvulnerable(source); } @Override protected void damageEntity(DamageSource damageSrc, float damageAmount) { float healthLast = this.getHealth(); super.damageEntity(damageSrc, damageAmount); float health = this.getHealth(); float thirdHealth = this.getMaxHealth() / 3.0F; if (health < thirdHealth && healthLast >= thirdHealth) { shouldEvade = true; } else if (health < 2 * thirdHealth && healthLast >= 2 * thirdHealth) { shouldEvade = true; } } @Override public void attackEntityWithRangedAttack(EntityLivingBase target, float damage) { EntityWebShot entityarrow = new EntityWebShot(this.worldObj, this, target, 0.8F, (float)(14 - this.worldObj.getDifficulty().getDifficultyId() * 4)); this.playSound("random.bow", 1.0F, 1.0F / (this.getRNG().nextFloat() * 0.4F + 0.8F)); this.worldObj.spawnEntityInWorld(entityarrow); } @Override public void writeEntityToNBT(NBTTagCompound tagCompound) { super.writeEntityToNBT(tagCompound); tagCompound.setBoolean("should_evade", this.shouldEvade); NBTTagList list = new NBTTagList(); for (EntityJuicer juicer : this.juicersSpawned) { list.appendTag(new NBTTagLong(juicer.getPersistentID().getMostSignificantBits())); list.appendTag(new NBTTagLong(juicer.getPersistentID().getLeastSignificantBits())); } tagCompound.setTag("spawned_children", list); } @Override public void readEntityFromNBT(NBTTagCompound tagCompound) { super.readEntityFromNBT(tagCompound); this.shouldEvade = tagCompound.getBoolean("should_evade"); if (tagCompound.hasKey("spawned_children")) { this.spawnedPreload = Lists.newArrayList(); NBTTagList list = tagCompound.getTagList("spawned_children", 4); for (int i = 0; i < list.tagCount(); i += 2) { NBTTagLong tagMost = (NBTTagLong) list.get(i); NBTTagLong tagLeast = (NBTTagLong) list.get(i + 1); this.spawnedPreload.add(new UUID(tagMost.getLong(), tagLeast.getLong())); } } } @Override public int getChestTier() { return 3; } @Override public void dropKey() { this.entityDropItem(new ItemStack(VenusItems.key, 1, 0), 0.5F); } }