From abc4bb024aca6e83147352ee39e207b14b8909d6 Mon Sep 17 00:00:00 2001 From: Blade <28675825+MrXBlade@users.noreply.github.com> Date: Sun, 17 Nov 2024 01:16:20 +0100 Subject: [PATCH] Improved moa AI, no longer spinning --- .../entity/passive/MoaEntityRenderer.java | 2 +- .../entities/ParadiseLostEntityTypes.java | 4 +- .../entities/passive/moa/MoaEntity.java | 45 ++++---- .../passive/moa/MoaWanderAroundGoal.java | 105 ++++++++++++++++++ 4 files changed, 131 insertions(+), 25 deletions(-) create mode 100644 src/main/java/net/id/paradiselost/entities/passive/moa/MoaWanderAroundGoal.java diff --git a/src/main/java/net/id/paradiselost/client/rendering/entity/passive/MoaEntityRenderer.java b/src/main/java/net/id/paradiselost/client/rendering/entity/passive/MoaEntityRenderer.java index f6a88e465..020fbc208 100644 --- a/src/main/java/net/id/paradiselost/client/rendering/entity/passive/MoaEntityRenderer.java +++ b/src/main/java/net/id/paradiselost/client/rendering/entity/passive/MoaEntityRenderer.java @@ -21,7 +21,7 @@ public MoaEntityRenderer(EntityRendererFactory.Context renderManager) { @Override protected void scale(MoaEntity moa, MatrixStack matrixStack, float partialTicks) { - float moaScale = moa.isBaby() ? Math.min(0.43F + (moa.age * 0.00001f), 0.65f) : 1.0F; + float moaScale = moa.isBaby() ? Math.min(0.43F + (moa.age * 0.00001f), 0.72f) : 1.0F; matrixStack.scale(moaScale, moaScale, moaScale); } diff --git a/src/main/java/net/id/paradiselost/entities/ParadiseLostEntityTypes.java b/src/main/java/net/id/paradiselost/entities/ParadiseLostEntityTypes.java index 9addeee5e..11401d782 100644 --- a/src/main/java/net/id/paradiselost/entities/ParadiseLostEntityTypes.java +++ b/src/main/java/net/id/paradiselost/entities/ParadiseLostEntityTypes.java @@ -39,10 +39,10 @@ public class ParadiseLostEntityTypes { attributes(EnvoyEntity::createEnvoyAttributes), spawnRestrictions(EnvoyEntity::canMobSpawn)); // passive - public static final EntityType MOA = add("moa", of(MoaEntity::new, CREATURE, changing(1.0F, 2.0F), 5), + public static final EntityType MOA = add("moa", of(MoaEntity::new, CREATURE, changing(0.8F, 1.9F), 5), attributes(MoaEntity::createMoaAttributes), spawnRestrictions(ParadiseLostAnimalEntity::isValidNaturalParadiseLostSpawn)); - public static final EntityType POPOM = add("popom", of(PopomEntity::new, CREATURE, changing(1.0F, 2.0F), 5), + public static final EntityType POPOM = add("popom", of(PopomEntity::new, CREATURE, changing(0.6F, 1.0F), 5), attributes(PopomEntity::createPopomAttributes), spawnRestrictions(PopomEntity::canMobSpawn)); // projectile diff --git a/src/main/java/net/id/paradiselost/entities/passive/moa/MoaEntity.java b/src/main/java/net/id/paradiselost/entities/passive/moa/MoaEntity.java index bb75f3559..b48507373 100644 --- a/src/main/java/net/id/paradiselost/entities/passive/moa/MoaEntity.java +++ b/src/main/java/net/id/paradiselost/entities/passive/moa/MoaEntity.java @@ -88,32 +88,35 @@ public MoaEntity(EntityType entityType, World world) { public static DefaultAttributeContainer.Builder createMoaAttributes() { return createMobAttributes() .add(EntityAttributes.GENERIC_MAX_HEALTH, 35.0D) - .add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 3.0D) - .add(EntityAttributes.GENERIC_STEP_HEIGHT, 1.0); + .add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 1.0D) + .add(EntityAttributes.GENERIC_STEP_HEIGHT, 1.0) + //.add(EntityAttributes.GENERIC_GRAVITY, 0.95f) + .add(EntityAttributes.GENERIC_JUMP_STRENGTH, 0.22f) + .add(EntityAttributes.GENERIC_FLYING_SPEED, 0.5f); } @Override protected void initGoals() { - this.goalSelector.add(0, new MoaEscapeDangerGoal(this, 0.8)); + this.goalSelector.add(0, new MoaEscapeDangerGoal(this, 0.9f)); this.goalSelector.add(1, new EatFromBowlGoal(0.4, 24, 16)); - this.goalSelector.add(2, new AnimalMateGoal(this, 0.25F)); - this.goalSelector.add(8, new LookAroundGoal(this)); //LookGoal + this.goalSelector.add(1, new AnimalMateGoal(this, 0.25F)); + this.goalSelector.add(2, new TemptGoal(this, 0.7D, Ingredient.fromTag(ParadiseLostItemTags.MOA_TEMPTABLES), false)); - this.goalSelector.add(7, new LookAtEntityGoal(this, ParrotEntity.class, 18F, 0.035f)); - this.goalSelector.add(8, new StopAndLookAtEntityGoal(this, ParrotEntity.class, 25, 0.025f)); - this.goalSelector.add(7, new StopAndLookAtEntityGoal(this, LivingEntity.class, 10, 0.005f)); - if (!isBaby()) { - this.goalSelector.add(2, new TemptGoal(this, 0.7D, Ingredient.fromTag(ParadiseLostItemTags.MOA_TEMPTABLES), false)); - } else { - this.goalSelector.add(2, new TemptGoal(this, 1D, Ingredient.fromTag(ParadiseLostItemTags.MOA_TEMPTABLES), false)); - this.goalSelector.add(8, new LookAtEntityGoal(this, PlayerEntity.class, 5F, 0.01f)); - } - this.goalSelector.add(9, new WanderAroundFarGoal(this, 0.32F, 1f)); //WanderGoal + this.goalSelector.add(7, new LookAtEntityGoal(this, ParrotEntity.class, 18F, 5f)); + this.goalSelector.add(7, new StopAndLookAtEntityGoal(this, ParrotEntity.class, 25, 8f)); + + this.goalSelector.add(8, new LookAtEntityGoal(this, LivingEntity.class, 10F, 40f)); + this.goalSelector.add(8, new StopAndLookAtEntityGoal(this, LivingEntity.class, 4, 70f)); + + //this.goalSelector.add(9, new WanderAroundFarGoal(this, 0.32F, 0.01f)); //WanderGoal + this.goalSelector.add(9, new MoaWanderAroundGoal(this, 0.320D, 210)); + //this.goalSelector.add(10, new MoaWanderAroundGoal(this, 0.400D, 290)); + this.goalSelector.add(11, new LookAroundGoal(this)); //LookGoal this.goalSelector.add(1, new SwimGoal(this)); - this.goalSelector.add(12, new FollowParentGoal(this, 0.11D)); + this.goalSelector.add(12, new FollowParentGoal(this, 0.33D)); super.initGoals(); } @@ -207,6 +210,7 @@ protected void dropInventory() { } } + float wingFlapSpeed = 2.5f; float idleFlapSpeed = 12; float randFlapSpeed, randFlapTimer = 200f, prevWingRoll, prevWingYaw; @@ -312,7 +316,6 @@ public float getWingYaw() { public float getLegPitch() { float baseLegPitch = isGliding() ? -1.5708F : 0.0174533F; - float lDif = -baseLegPitch - curLegPitch; if (Math.abs(lDif) > 0.005F) { curLegPitch += lDif / 6; @@ -322,15 +325,13 @@ public float getLegPitch() { public float getRandomFloat(float from, float to){ float finalNumber = 1; - from *= 100; to *= 100; - finalNumber = from + this.random.nextInt((int)to); return finalNumber / 100; } -//Moa Sound stuff + //Moa Sound stuff int moaSoundCallCooldown = 200; private float soundChance = 0; private float songChance = 0; @@ -433,9 +434,9 @@ public void tick() { genes.setHunger(hunger - 0.5F); } - if (hunger < 20F && getWorld().getTime() % 10 == 0) { + if ((hunger < 15F && getWorld().getTime() % 10 == 0 && isSaddled())) { produceParticlesServer(ParticleTypes.ANGRY_VILLAGER, random.nextInt(3), 1, 0); - if (hunger < 10F && hasPassengers()) { + if (hunger < 8F && hasPassengers()) { removeAllPassengers(); playSound(ParadiseLostSoundEvents.ENTITY_MOA_DEATH, 0.15f, 1.5F + random.nextFloat() * 0.5F); } diff --git a/src/main/java/net/id/paradiselost/entities/passive/moa/MoaWanderAroundGoal.java b/src/main/java/net/id/paradiselost/entities/passive/moa/MoaWanderAroundGoal.java new file mode 100644 index 000000000..43596de46 --- /dev/null +++ b/src/main/java/net/id/paradiselost/entities/passive/moa/MoaWanderAroundGoal.java @@ -0,0 +1,105 @@ +package net.id.paradiselost.entities.passive.moa; + +import java.util.EnumSet; +import net.minecraft.entity.ai.NoPenaltyTargeting; +import net.minecraft.entity.ai.goal.Goal; +import net.minecraft.entity.mob.PathAwareEntity; +import net.minecraft.util.math.Vec3d; +import org.jetbrains.annotations.Nullable; + +public class MoaWanderAroundGoal extends Goal { + public static final int DEFAULT_CHANCE = 120; + protected final PathAwareEntity mob; + protected double targetX; + protected double targetY; + protected double targetZ; + protected final double speed; + protected int chance; + protected boolean ignoringChance; + private final boolean canDespawn; + + public MoaWanderAroundGoal(PathAwareEntity mob, double speed) { + this(mob, speed, 120); + } + + public MoaWanderAroundGoal(PathAwareEntity mob, double speed, int chance) { + this(mob, speed, chance, true); + } + + public MoaWanderAroundGoal(PathAwareEntity entity, double speed, int chance, boolean canDespawn) { + this.mob = entity; + this.speed = speed; + this.chance = chance; + this.canDespawn = canDespawn; + this.setControls(EnumSet.of(Goal.Control.MOVE)); + } + + @Override + public boolean canStart() { + if (this.mob.hasControllingPassenger()) { + return false; + } else { + if (!this.ignoringChance) { + if (this.canDespawn && this.mob.getDespawnCounter() >= 100) { + return false; + } + + if (this.mob.getRandom().nextInt(toGoalTicks(this.chance)) != 0) { + return false; + } + } + + Vec3d bestTarget = null; + double highestY = Double.NEGATIVE_INFINITY; + + //Take 3 samples, get the one with the highest Y value + for (int i = 0; i < 4; i++) { + Vec3d sampleTarget = this.getWanderTarget(); + if (sampleTarget != null && sampleTarget.y > highestY) { + highestY = sampleTarget.y; + bestTarget = sampleTarget; + } + } + + if (bestTarget == null) { + return false; + } else { + //Set new target to high Y one + this.targetX = bestTarget.x; + this.targetY = bestTarget.y; + this.targetZ = bestTarget.z; + this.ignoringChance = false; + return true; + } + } + } + + @Nullable + protected Vec3d getWanderTarget() { + return NoPenaltyTargeting.find(this.mob, 9, 8); + } + + @Override + public boolean shouldContinue() { + return !this.mob.getNavigation().isIdle() && !this.mob.hasControllingPassenger(); + } + + @Override + public void start() { + this.mob.getNavigation().startMovingTo(this.targetX, this.targetY, this.targetZ, this.speed); + } + + @Override + public void stop() { + this.mob.getNavigation().stop(); + super.stop(); + } + + public void ignoreChanceOnce() { + this.ignoringChance = true; + } + + public void setChance(int chance) { + this.chance = chance; + } +}