From ba76e746a2f772ee3d4be97af8995f2a0328c3b9 Mon Sep 17 00:00:00 2001 From: Konstantin Shandurenko Date: Sun, 17 Oct 2021 22:07:59 +0300 Subject: [PATCH] Entity#lookAt and updating view in melee/ranged/combined attack goals when within attackable range (#494) --- .../net/minestom/server/entity/Entity.java | 24 +++++++++++++++++++ .../entity/ai/goal/CombinedAttackGoal.java | 1 + .../entity/ai/goal/FollowTargetGoal.java | 3 +-- .../entity/ai/goal/MeleeAttackGoal.java | 1 + .../entity/ai/goal/RangedAttackGoal.java | 1 + 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/minestom/server/entity/Entity.java b/src/main/java/net/minestom/server/entity/Entity.java index 222001be6..006883b79 100644 --- a/src/main/java/net/minestom/server/entity/Entity.java +++ b/src/main/java/net/minestom/server/entity/Entity.java @@ -40,6 +40,7 @@ import net.minestom.server.utils.block.BlockIterator; import net.minestom.server.utils.chunk.ChunkUtils; import net.minestom.server.utils.entity.EntityUtils; import net.minestom.server.utils.player.PlayerUtils; +import net.minestom.server.utils.position.PositionUtils; import net.minestom.server.utils.time.Cooldown; import net.minestom.server.utils.time.TimeUnit; import net.minestom.server.utils.validate.Check; @@ -280,6 +281,29 @@ public class Entity implements Viewable, Tickable, TagHandler, PermissionHandler sendPacketToViewersAndSelf(new EntityRotationPacket(getEntityId(), yaw, pitch, onGround)); } + /** + * Changes the view of the entity so that it looks in a direction to the given position. + * + * @param position the position to look at. + */ + public void lookAt(@NotNull Pos position) { + Vec delta = position.sub(getPosition()).asVec().normalize(); + setView( + PositionUtils.getLookYaw(delta.x(), delta.z()), + PositionUtils.getLookPitch(delta.x(), delta.y(), delta.z()) + ); + } + + /** + * Changes the view of the entity so that it looks in a direction to the given entity. + * + * @param entity the entity to look at. + */ + public void lookAt(@NotNull Entity entity) { + Check.argCondition(entity.instance != instance, "Entity can look at another entity that is within it's own instance"); + lookAt(entity.position); + } + /** * When set to true, the entity will automatically get new viewers when they come too close. * This can be use to have complete control over which player can see it, without having to deal with diff --git a/src/main/java/net/minestom/server/entity/ai/goal/CombinedAttackGoal.java b/src/main/java/net/minestom/server/entity/ai/goal/CombinedAttackGoal.java index 5cfa0f406..5dff8b4ef 100644 --- a/src/main/java/net/minestom/server/entity/ai/goal/CombinedAttackGoal.java +++ b/src/main/java/net/minestom/server/entity/ai/goal/CombinedAttackGoal.java @@ -198,6 +198,7 @@ public class CombinedAttackGoal extends GoalSelector { if (pathPosition != null) { navigator.setPathTo(null); } + this.entityCreature.lookAt(target); return; } // Otherwise going to the target. diff --git a/src/main/java/net/minestom/server/entity/ai/goal/FollowTargetGoal.java b/src/main/java/net/minestom/server/entity/ai/goal/FollowTargetGoal.java index 74b192b94..183b56c6e 100644 --- a/src/main/java/net/minestom/server/entity/ai/goal/FollowTargetGoal.java +++ b/src/main/java/net/minestom/server/entity/ai/goal/FollowTargetGoal.java @@ -60,8 +60,7 @@ public class FollowTargetGoal extends GoalSelector { navigator.setPathTo(null); return; } - if (navigator.getPathPosition() == null || - (!navigator.getPathPosition().samePoint(lastTargetPos))) { + if (navigator.getPathPosition() == null || !navigator.getPathPosition().samePoint(lastTargetPos)) { navigator.setPathTo(lastTargetPos); } else { forceEnd = true; diff --git a/src/main/java/net/minestom/server/entity/ai/goal/MeleeAttackGoal.java b/src/main/java/net/minestom/server/entity/ai/goal/MeleeAttackGoal.java index 0527d4c6e..d96ae1c9b 100644 --- a/src/main/java/net/minestom/server/entity/ai/goal/MeleeAttackGoal.java +++ b/src/main/java/net/minestom/server/entity/ai/goal/MeleeAttackGoal.java @@ -81,6 +81,7 @@ public class MeleeAttackGoal extends GoalSelector { // Attack the target entity if (entityCreature.getDistance(target) <= range) { + entityCreature.lookAt(target); if (!Cooldown.hasCooldown(time, lastHit, delay)) { entityCreature.attack(target, true); this.lastHit = time; diff --git a/src/main/java/net/minestom/server/entity/ai/goal/RangedAttackGoal.java b/src/main/java/net/minestom/server/entity/ai/goal/RangedAttackGoal.java index 17efa45e9..d9b5a02f5 100644 --- a/src/main/java/net/minestom/server/entity/ai/goal/RangedAttackGoal.java +++ b/src/main/java/net/minestom/server/entity/ai/goal/RangedAttackGoal.java @@ -124,6 +124,7 @@ public class RangedAttackGoal extends GoalSelector { if (pathPosition != null) { navigator.setPathTo(null); } + this.entityCreature.lookAt(target); return; } final var targetPosition = target.getPosition();