diff --git a/changelog.md b/changelog.md index 375bddab1b..3d74cc2a6e 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,7 @@ * Merged [Inworld integration](https://github.com/Luke100000/minecraft-comes-alive/wiki/GPT3-based-conversations) branch (thanks CSCMe!) * Fixed incompatibility with Cobblemon (thanks Apion!) +* Fixed AI issues with Grim Reapers, causing him to go much higher than intended * Fixed issues when using Arabic numerals * Fixed crashes when using TTS * Fixed Inn spamming adventurers diff --git a/common/src/main/java/net/mca/entity/GrimReaperEntity.java b/common/src/main/java/net/mca/entity/GrimReaperEntity.java index a2cc1ec399..fabdfcf73d 100644 --- a/common/src/main/java/net/mca/entity/GrimReaperEntity.java +++ b/common/src/main/java/net/mca/entity/GrimReaperEntity.java @@ -28,7 +28,7 @@ import net.minecraft.entity.mob.HostileEntity; import net.minecraft.entity.mob.PathAwareEntity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.projectile.ArrowEntity; +import net.minecraft.entity.projectile.ProjectileEntity; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.sound.SoundCategory; @@ -44,7 +44,7 @@ public class GrimReaperEntity extends PathAwareEntity implements CTrackedEntity< public static final CDataManager DATA = new CDataManager.Builder<>(GrimReaperEntity.class).addAll(ATTACK_STAGE).build(); - private final ServerBossBar bossInfo = (ServerBossBar)new ServerBossBar(getDisplayName(), BossBar.Color.PURPLE, BossBar.Style.PROGRESS).setDarkenSky(true); + private final ServerBossBar bossInfo = (ServerBossBar) new ServerBossBar(getDisplayName(), BossBar.Color.PURPLE, BossBar.Style.PROGRESS).setDarkenSky(true); public GrimReaperEntity(EntityType type, World world) { super(type, world); @@ -89,11 +89,10 @@ public EntityGroup getGroup() { protected void initGoals() { this.targetSelector.add(1, new GrimReaperTargetGoal(this)); + this.goalSelector.add(0, new LookAtEntityGoal(this, PlayerEntity.class, 24, 1.0f)); this.goalSelector.add(1, new GrimReaperRestGoal(this)); this.goalSelector.add(2, new GrimReaperMeleeGoal(this)); this.goalSelector.add(3, new GrimReaperIdleGoal(this, 1)); - this.goalSelector.add(4, new LookAtEntityGoal(this, PlayerEntity.class, 8)); - this.goalSelector.add(5, new LookAroundGoal(this)); } @Override @@ -166,16 +165,21 @@ public boolean damage(DamageSource source, float damage) { return false; } - Entity attacker = source.getSource(); + Entity entity = source.getSource(); + Entity attacker = source.getAttacker(); - // Ignore damage when blocking, and teleport behind the attacker when attacked - if (!getWorld().isClient && this.getAttackState() == ReaperAttackState.BLOCK && attacker != null) { + // Ignore damage when blocking, and randomly teleport around + if (this.getAttackState() == ReaperAttackState.BLOCK && attacker != null) { + playSound(SoundsMCA.REAPER_BLOCK.get(), 1.0F, 1.0F); + return false; + } - double deltaX = this.getX() - attacker.getX(); - double deltaZ = this.getZ() - attacker.getZ(); + // Teleport next to the player who fired an arrow + if (entity instanceof ProjectileEntity && getAttackState() != ReaperAttackState.REST && attacker != null && random.nextBoolean()) { + double newX = attacker.getX() + (random.nextFloat() >= 0.50F ? 4 : -4); + double newZ = attacker.getZ() + (random.nextFloat() >= 0.50F ? 4 : -4); - playSound(SoundsMCA.REAPER_BLOCK.get(), 1.0F, 1.0F); - requestTeleport(attacker.getX() - (deltaX * 2), attacker.getY() + 2, this.getZ() - (deltaZ * 2)); + requestTeleport(newX, attacker.getY(), newZ); return false; } @@ -183,29 +187,15 @@ public boolean damage(DamageSource source, float damage) { if (!getWorld().isClient && random.nextFloat() >= 0.30F && attacker != null) { double deltaX = this.getX() - attacker.getX(); double deltaZ = this.getZ() - attacker.getZ(); + double distance = Math.sqrt(deltaX * deltaX + deltaZ * deltaZ); + double length = Math.max(5.0, distance) / distance * 0.95; - requestTeleport(attacker.getX() - (deltaX * 2), attacker.getY() + 2, this.getZ() - (deltaZ * 2)); - } - - // Teleport behind the player who fired an arrow and ignore its damage. - if (attacker instanceof ArrowEntity arrow) { - if (getAttackState() != ReaperAttackState.REST) { - Entity owner = arrow.getOwner(); - - if (owner != null) { - double newX = owner.getX() + (random.nextFloat() >= 0.50F ? 2 : -2); - double newZ = owner.getZ() + (random.nextFloat() >= 0.50F ? 2 : -2); - - requestTeleport(newX, owner.getY(), newZ); - } - arrow.discard(); - } - return false; + requestTeleport(attacker.getX() - deltaX * length, attacker.getY() + 1.5, attacker.getZ() - deltaZ * length); } // 25% damage when healing if (this.getAttackState() == ReaperAttackState.REST) { - damage *= 0.25; + damage *= 0.25f; } return super.damage(source, damage); @@ -243,12 +233,6 @@ public void tick() { return; } - // look at the player. Always. - PlayerEntity player = getWorld().getClosestPlayer(this, 10.D); - if (player != null) { - getLookControl().lookAt(player.getX(), player.getEyeY(), player.getZ()); - } - LivingEntity entityToAttack = this.getTarget(); // See if our entity to attack has died at any point. diff --git a/common/src/main/java/net/mca/entity/ai/goal/GrimReaperIdleGoal.java b/common/src/main/java/net/mca/entity/ai/goal/GrimReaperIdleGoal.java index 8a6eaafae4..a5d6775b9e 100644 --- a/common/src/main/java/net/mca/entity/ai/goal/GrimReaperIdleGoal.java +++ b/common/src/main/java/net/mca/entity/ai/goal/GrimReaperIdleGoal.java @@ -53,7 +53,7 @@ protected Vec3d getPosition() { return reaper.getTarget().getPos(); } - return NoWaterTargeting.find(reaper, 8, 6, -2, Vec3d.ofBottomCenter(reaper.getBlockPos()), 1); + return NoWaterTargeting.find(reaper, 8, 6, -1, Vec3d.ofBottomCenter(reaper.getBlockPos()), 1); } @Override diff --git a/common/src/main/java/net/mca/entity/ai/goal/GrimReaperMeleeGoal.java b/common/src/main/java/net/mca/entity/ai/goal/GrimReaperMeleeGoal.java index 09fed6df74..1b221cf4d7 100644 --- a/common/src/main/java/net/mca/entity/ai/goal/GrimReaperMeleeGoal.java +++ b/common/src/main/java/net/mca/entity/ai/goal/GrimReaperMeleeGoal.java @@ -13,7 +13,7 @@ import net.minecraft.util.math.Vec3d; public class GrimReaperMeleeGoal extends Goal { - private final static int COOLDOWN = 150; + private static final int COOLDOWN = 150; private final GrimReaperEntity reaper; private int blockDuration; @@ -46,7 +46,7 @@ public boolean canStop() { @Override public void start() { - blockDuration = 60; + blockDuration = 50; attackDuration = 100; retreatDuration = 20; diff --git a/common/src/main/java/net/mca/entity/ai/goal/GrimReaperRestGoal.java b/common/src/main/java/net/mca/entity/ai/goal/GrimReaperRestGoal.java index d7d270884f..b07b673e14 100644 --- a/common/src/main/java/net/mca/entity/ai/goal/GrimReaperRestGoal.java +++ b/common/src/main/java/net/mca/entity/ai/goal/GrimReaperRestGoal.java @@ -15,12 +15,12 @@ import net.minecraft.util.math.Vec3d; public class GrimReaperRestGoal extends Goal { - private final static int COOLDOWN = 1000; + private static final int COOLDOWN = 1000; private final GrimReaperEntity reaper; private int lastHeal = -COOLDOWN; private int healingCount = 0; private static final int MAX_HEALING_COUNT = 5; - private static final int MAX_HEALING_TIME = 500; + private static final int MAX_HEALING_TIME = 400; private int healingTime; public GrimReaperRestGoal(GrimReaperEntity reaper) {