Skip to content

Commit

Permalink
Lich improvements
Browse files Browse the repository at this point in the history
-Various fixes
-Lich enters third phase when all minions are dead
-Added ranged attack to third phase
-Added an extra shield
-Restored life drain attack (WIP)
  • Loading branch information
IcarussOne committed Oct 5, 2024
1 parent 6f2cf2e commit ed1bc4e
Show file tree
Hide file tree
Showing 4 changed files with 739 additions and 567 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ public void setRotationAngles(float limbSwing, float limbSwingAmount, float ageI
bipedRightArm.rotateAngleX += MathHelper.sin(ageInTicks * 0.167F) * 0.15F;
bipedLeftArm.rotateAngleX -= MathHelper.sin(ageInTicks * 0.167F) * 0.15F;

if (entity instanceof EntityTFLich && ((EntityTFLich) entity).isChargeDagger()){
bipedRightArm.rotateAngleZ = -0.3F;
bipedLeftArm.rotateAngleX = 0.0F;
}

bipedHead.rotationPointY = -4.0F;
bipedHeadwear.rotationPointY = -4.0F;
bipedRightLeg.rotationPointY = 9.5F;
Expand Down
66 changes: 66 additions & 0 deletions src/main/java/twilightforest/entity/ai/EntityAITFLichPopMobs.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package twilightforest.entity.ai;

import java.util.List;

import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.entity.monster.EntityMob;
import net.minecraft.init.SoundEvents;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.WorldServer;
import twilightforest.entity.boss.EntityTFLich;
import twilightforest.item.TFItems;
import twilightforest.item.scepter.ItemTFScepterLifeDrain;

public class EntityAITFLichPopMobs extends EntityAIBase {

private final EntityTFLich lich;

public EntityAITFLichPopMobs(EntityTFLich lich) {
this.lich = lich;
this.setMutexBits(3);
}

@Override
public boolean shouldExecute() {
return !this.lich.isShadowClone() &&
this.lich.getHealth() < this.lich.getMaxHealth() &&
this.lich.getPopCooldown() == 0 &&
!this.lich.world.getEntitiesWithinAABB(EntityLiving.class,
this.lich.getEntityBoundingBox().grow(32.0D, 16.0D, 32.0D),
e -> EntityTFLich.POPPABLE.contains(e.getClass()) && this.lich.getEntitySenses().canSee(e)).isEmpty();
}

@Override
public void startExecuting() {
lich.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(TFItems.lifedrain_scepter));
}

@Override
public void updateTask() {
super.updateTask();

// TODO: Add life drain scepter particles
for (EntityLiving mob : lich.world.getEntitiesWithinAABB(EntityLiving.class, this.lich.getEntityBoundingBox().grow(32.0D, 16.0D, 32.0D), e -> EntityTFLich.POPPABLE.contains(e.getClass()))) {
if (this.lich.getEntitySenses().canSee(mob)) {
mob.setDead();
mob.spawnExplosionParticle();

// Play sounds
this.lich.playSound(SoundEvents.ENTITY_ZOMBIE_INFECT, 3.0F, 0.4F + this.lich.getRNG().nextFloat() * 0.2F);
mob.playSound(SoundEvents.ENTITY_ZOMBIE_VILLAGER_CURE, 0.7F, 2.0F + this.lich.getRNG().nextFloat() * 0.2F);

// Heal 5% of max health
this.lich.heal(this.lich.getMaxHealth() * 5.0F / 100.0F);

this.lich.swingArm(EnumHand.MAIN_HAND);
this.lich.setPopCooldown(40);
break;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package twilightforest.entity.ai;

import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.init.Items;
import net.minecraft.init.SoundEvents;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.MathHelper;
import twilightforest.entity.boss.EntityTFLich;
import twilightforest.entity.boss.EntityTFThrownWep;

public class EntityAITFLichShootDagger extends EntityAIBase {
private EntityTFLich lich;
private int attackTick;
private EntityLivingBase attackTarget;

public EntityAITFLichShootDagger(EntityTFLich entityTFLich) {
this.lich = entityTFLich;
this.setMutexBits(3);
}


@Override
public boolean shouldExecute() {
this.attackTarget = this.lich.getAttackTarget();

if (this.attackTarget == null) {
return false;
} else {
return this.lich.getPhase() == 3 && this.lich.getRNG().nextInt(40) == 0 && this.lich.canEntityBeSeen(this.attackTarget);
}
}

@Override
public boolean shouldContinueExecuting() {
return this.attackTick >= 0;
}

@Override
public void startExecuting() {
this.lich.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, ItemStack.EMPTY);
attackTick = 5 + this.lich.getRNG().nextInt(5);
this.lich.setChargeDagger(true);
this.lich.playSound(SoundEvents.ITEM_ARMOR_EQUIP_GOLD, 2.0F, 1.1F);

double d0 = this.attackTarget.posX - this.lich.posX;
double d1 = this.attackTarget.posZ - this.lich.posZ;
float f = MathHelper.sqrt(d0 * d0 + d1 * d1);

if (this.lich.onGround) {
if ((double) f >= 1.0E-4D) {
this.lich.motionX -= d0 / (double) f * 0.8D * 0.7D + this.lich.motionX * 0.3D;
this.lich.motionZ -= d1 / (double) f * 0.8D * 0.7D + this.lich.motionZ * 0.3D;
}

this.lich.motionY = 0.3F;
}
}

@Override
public void updateTask() {
this.lich.getLookHelper().setLookPositionWithEntity(attackTarget, 30.0F, 30.0F);

if (this.attackTick-- == 0) {
this.lich.setChargeDagger(false);
this.lich.playSound(SoundEvents.ENTITY_SNOWBALL_THROW, 2.0F, 1.0F + this.lich.getRNG().nextFloat() * 0.1F);
this.shootDagger(this.attackTarget);
}
}

private void shootDagger(Entity targetedEntity) {
float bodyFacingAngle = ((this.lich.renderYawOffset * 3.141593F) / 180F);
double sx = this.lich.posX + (MathHelper.cos(bodyFacingAngle) * 1);
double sy = this.lich.posY + (this.lich.height * 0.82);
double sz = this.lich.posZ + (MathHelper.sin(bodyFacingAngle) * 1);

double tx = targetedEntity.posX - sx;
double ty = (targetedEntity.getEntityBoundingBox().minY + (double) (targetedEntity.height / 2.0F)) - (this.lich.posY + this.lich.height / 2.0F);
double tz = targetedEntity.posZ - sz;

this.lich.playSound(SoundEvents.ENTITY_ITEM_BREAK, 2.0F, 2.0F + this.lich.getRNG().nextFloat() * 0.1F);
EntityTFThrownWep projectile = new EntityTFThrownWep(this.lich.world, this.lich).setItem(new ItemStack(Items.GOLDEN_SWORD));

float speed = 1.5F;

projectile.shoot(tx, ty, tz, speed, 1.0F);

projectile.setLocationAndAngles(sx, sy, sz, this.lich.rotationYaw, this.lich.rotationPitch);

this.lich.world.spawnEntity(projectile);
}
}
Loading

0 comments on commit ed1bc4e

Please sign in to comment.