diff --git a/src/main/java/com/zivilon/cinder_loe/entity/boss/CryptBoss.java b/src/main/java/com/zivilon/cinder_loe/entity/boss/CryptBoss.java new file mode 100644 index 0000000..93c6fcd --- /dev/null +++ b/src/main/java/com/zivilon/cinder_loe/entity/boss/CryptBoss.java @@ -0,0 +1,202 @@ +package com.zivilon.cinder_loe.entity.boss; + +import com.zivilon.cinder_loe.CinderLoE; +import com.zivilon.cinder_loe.projectiles.MorgulBlast; +import lotr.common.enchant.LOTREnchantment; +import lotr.common.enchant.LOTREnchantmentHelper; +import lotr.common.entity.ai.*; +import lotr.common.entity.npc.LOTREntityNPC; +import lotr.common.fac.LOTRFaction; +import lotr.common.quest.LOTRMiniQuest; +import lotr.common.world.structure.LOTRChestContents; +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.entity.*; +import net.minecraft.entity.ai.*; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.DamageSource; +import net.minecraft.util.MathHelper; +import net.minecraft.world.World; + +public class CryptBoss extends LOTREntityNPC { + + private EntityAIBase meleeAttackAI = new LOTREntityAIAttackOnCollide(this, 2.0, false); + private EntityAIBase rangedAttackAI = new LOTREntityAIRangedAttack(this, 1.5, 30, 50, 24.0f); + + //Copying Wraith temporarily + public CryptBoss(World world) { + super(world); + setSize(0.8F, 2.5F); + this.tasks.taskEntries.clear(); + this.tasks.addTask(0, (EntityAIBase)new EntityAISwimming((EntityLiving)this)); + this.tasks.addTask(0, (EntityAIBase)new LOTREntityAIBossJumpAttack(this, 1.5, 0.02f)); + this.tasks.addTask(2, (EntityAIBase)new EntityAIWander((EntityCreature)this, 1.0)); + this.tasks.addTask(3, (EntityAIBase)new EntityAIWatchClosest2((EntityLiving)this, EntityPlayer.class, 12.0f, 0.02f)); + this.tasks.addTask(3, (EntityAIBase)new EntityAIWatchClosest2((EntityLiving)this, LOTREntityNPC.class, 8.0f, 0.02f)); + this.tasks.addTask(4, (EntityAIBase)new EntityAIWatchClosest((EntityLiving)this, EntityLiving.class, 10.0f, 0.02f)); + this.tasks.addTask(5, (EntityAIBase)new EntityAILookIdle((EntityLiving)this)); + addTargetTasks(true); + } + + @Override + public void sendSpeechBank(EntityPlayer entityplayer, String speechBank) { + this.sendSpeechBank(entityplayer, speechBank, (LOTRMiniQuest)null); + } + + protected void entityInit() { + super.entityInit(); + this.dataWatcher.addObject(17, Integer.valueOf(0)); + } + + @Override + protected void applyEntityAttributes() { + super.applyEntityAttributes(); + this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(300.0); + this.getEntityAttribute(SharedMonsterAttributes.followRange).setBaseValue(32.0); + this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setBaseValue(0.0); + this.getEntityAttribute(npcAttackDamage).setBaseValue(16.0); + } + + public int getDeathFadeTime() { + return this.dataWatcher.getWatchableObjectInt(17); + } + + public void setDeathFadeTime(int i) { + this.dataWatcher.updateObject(17, Integer.valueOf(i)); + } + + public LOTRFaction getFaction() { + return LOTRFaction.UTUMNO; + } + + public void writeEntityToNBT(NBTTagCompound nbt) { + super.writeEntityToNBT(nbt); + nbt.setInteger("DeathFadeTime", getDeathFadeTime()); + } + + public void readEntityFromNBT(NBTTagCompound nbt) { + super.readEntityFromNBT(nbt); + setDeathFadeTime(nbt.getInteger("DeathFadeTime")); + } + + @Override + public void moveEntityWithHeading(float strafe, float forward) { + // First, call the super method to preserve normal movement behavior + super.moveEntityWithHeading(strafe, forward); + + // Check for water at the entity's feet + int x = MathHelper.floor_double(this.posX); + int y = MathHelper.floor_double(this.posY); + int z = MathHelper.floor_double(this.posZ); + + boolean isWater = this.worldObj.getBlock(x, y, z).getMaterial() == Material.water || + this.worldObj.getBlock(x, y - 1, z).getMaterial() == Material.water; // Check below the entity too + + if (isWater) { + this.onGround = true; // Treat water as solid ground + this.motionY = 0.0; // Stop falling/sinking + this.setPosition(this.posX, y + 1, this.posZ); // Adjust position to stay on top of the water + } + } + + + public void setInWeb() {} + + public void onLivingUpdate() { + super.onLivingUpdate(); + if (rand.nextBoolean()) + ((Entity)this).worldObj.spawnParticle("morgulPortal", ((Entity)this).posX + (rand.nextDouble() - 0.5D) * ((Entity)this).width, ((Entity)this).posY + rand.nextDouble() * ((Entity)this).height, ((Entity)this).posZ + (rand.nextDouble() - 0.5D) * ((Entity)this).width, 0.0D, 0.0D, 0.0D); + if (!((Entity)this).worldObj.isRemote) { + if (getDeathFadeTime() > 0) + setDeathFadeTime(getDeathFadeTime() - 1); + if (getDeathFadeTime() == 1) + setDead(); + } + } + + @Override + public void onAttackModeChange(LOTREntityNPC.AttackMode mode, boolean mounted) { + if (mode == LOTREntityNPC.AttackMode.IDLE) { + this.tasks.removeTask(this.meleeAttackAI); + this.tasks.removeTask(this.rangedAttackAI); + this.tasks.addTask(1, this.meleeAttackAI); + } + if (mode == LOTREntityNPC.AttackMode.MELEE) { + this.tasks.removeTask(this.meleeAttackAI); + this.tasks.removeTask(this.rangedAttackAI); + this.tasks.addTask(1, this.meleeAttackAI); + } + if (mode == LOTREntityNPC.AttackMode.RANGED) { + this.tasks.removeTask(this.meleeAttackAI); + this.tasks.removeTask(this.rangedAttackAI); + this.tasks.addTask(1, this.rangedAttackAI); + } + } + + @Override + public void attackEntityWithRangedAttack(EntityLivingBase target, float f) { + MorgulBlast projectile = new MorgulBlast(this.worldObj, (EntityLivingBase)this, target); + projectile.leavesDamage = 6.0f; + this.worldObj.spawnEntityInWorld((Entity)projectile); + this.playSound("lotr:wraith.marchWraith_shoot", this.getSoundVolume(), this.getSoundPitch()); + this.swingItem(); + } + + public boolean attackEntityFrom(DamageSource damagesource, float f) { + boolean vulnerable = false; + Entity entity = damagesource.getEntity(); + if (entity instanceof EntityLivingBase && entity == damagesource.getSourceOfDamage()) { + ItemStack itemstack = ((EntityLivingBase)entity).getHeldItem(); + if (itemstack != null && LOTREnchantmentHelper.hasEnchant(itemstack, LOTREnchantment.baneWraith)) + vulnerable = true; + } + if (vulnerable && getDeathFadeTime() == 0) { + boolean flag = super.attackEntityFrom(damagesource, f); + return flag; + } + return false; + } + + public void onDeath(DamageSource damagesource) { + super.onDeath(damagesource); + if (!((Entity)this).worldObj.isRemote) + setDeathFadeTime(30); + } + + protected void dropFewItems(boolean flag, int i) { + super.dropFewItems(flag, i); + int flesh = 1 + rand.nextInt(3) + rand.nextInt(i + 1); + for (int l = 0; l < flesh; l++) + dropItem(Items.rotten_flesh, 1); + dropChestContents(LOTRChestContents.MARSH_REMAINS, 1, 3 + i); + } + + public EnumCreatureAttribute getCreatureAttribute() { + return EnumCreatureAttribute.UNDEAD; + } + + protected String getHurtSound() { + return "lotr:wight.hurt"; + } + + protected String getDeathSound() { + return "lotr:wight.death"; + } + + public boolean handleWaterMovement() { + return false; + } + + protected void func_145780_a(int i, int j, int k, Block block) {} + + @Override + public String getSpeechBank(EntityPlayer entityplayer) { + if (this.isFriendlyAndAligned(entityplayer)) { + return "corruptSpeak/all/neutral"; + } + return "corruptSpeak/all/hostile"; + } +} diff --git a/src/main/java/com/zivilon/cinder_loe/projectiles/MorgulBlast.java b/src/main/java/com/zivilon/cinder_loe/projectiles/MorgulBlast.java index cb9e9bf..ea2b655 100644 --- a/src/main/java/com/zivilon/cinder_loe/projectiles/MorgulBlast.java +++ b/src/main/java/com/zivilon/cinder_loe/projectiles/MorgulBlast.java @@ -30,6 +30,27 @@ public class MorgulBlast extends LOTREntityMallornLeafBomb { this.setPosition(this.posX, this.posY, this.posZ); } + public MorgulBlast(World world, EntityLivingBase thrower, EntityLivingBase target) { + super(world, thrower); + this.setSize(2.0f, 2.0f); + this.setPosition(this.posX, this.posY, this.posZ); + this.throwerUUID = thrower.getUniqueID(); + this.posY = thrower.posY + (double)thrower.getEyeHeight() - 0.1; + double dx = target.posX - thrower.posX; + double dy = target.boundingBox.minY + (double)(target.height / 3.0f) - this.posY; + double dz = target.posZ - thrower.posZ; + double dxz = MathHelper.sqrt_double((double)(dx * dx + dz * dz)); + if (dxz >= 1.0E-7) { + float f2 = (float)(Math.atan2(dz, dx) * 180.0 / Math.PI) - 90.0f; + float f3 = (float)(-(Math.atan2(dy, dxz) * 180.0 / Math.PI)); + double d4 = dx / dxz; + double d5 = dz / dxz; + this.setLocationAndAngles(thrower.posX + d4, this.posY, thrower.posZ + d5, f2, f3); + this.yOffset = 0.0f; + this.setThrowableHeading(dx, dy, dz, this.func_70182_d(), 1.0f); + } + } + private void explode(Entity target) { if (!this.worldObj.isRemote) { double range = 2.0;