From 55cd8cc5b3cf556b82d58b6a66a2ef4fb804c7be Mon Sep 17 00:00:00 2001 From: Kam Date: Fri, 6 Feb 2026 03:34:45 -0500 Subject: [PATCH] Fix Rotation Locking --- src/main/java/noppes/npcs/DataAbilities.java | 25 ++++++++++++++++++- .../npcs/entity/EntityNPCInterface.java | 7 ++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/main/java/noppes/npcs/DataAbilities.java b/src/main/java/noppes/npcs/DataAbilities.java index 36dc6f34a..19dc59ecd 100644 --- a/src/main/java/noppes/npcs/DataAbilities.java +++ b/src/main/java/noppes/npcs/DataAbilities.java @@ -117,10 +117,33 @@ public class DataAbilities { * Should be called every tick from onLivingUpdate(). */ public void tick() { - if (!enabled || npc.worldObj.isRemote || npc.isKilled()) { + if (npc.worldObj.isRemote) { return; } + // Force-stop any running ability when NPC is killed or abilities are disabled + if (!enabled || npc.isKilled()) { + if (currentAbility != null) { + removeTelegraph(currentAbility); + stopAbilityAnimation(); + releaseLockedRotation(); + releaseLockedPosition(); + currentAbility = null; + lastTarget = null; + } else { + // No ability but locks could be orphaned + if (rotationLocked) releaseLockedRotation(); + if (positionLocked) releaseLockedPosition(); + } + return; + } + + // Safety: release orphaned locks if no ability is actively executing + if (currentAbility == null || !currentAbility.isExecuting()) { + if (rotationLocked) releaseLockedRotation(); + if (positionLocked) releaseLockedPosition(); + } + // Tick current ability if executing if (currentAbility != null && currentAbility.isExecuting()) { tickCurrentAbility(); diff --git a/src/main/java/noppes/npcs/entity/EntityNPCInterface.java b/src/main/java/noppes/npcs/entity/EntityNPCInterface.java index 6b344f9b9..00de6d405 100644 --- a/src/main/java/noppes/npcs/entity/EntityNPCInterface.java +++ b/src/main/java/noppes/npcs/entity/EntityNPCInterface.java @@ -308,6 +308,13 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti @Override public void onUpdate() { super.onUpdate(); + + // Re-apply locks after super.onUpdate() to override body rotation smoothing + // in EntityLivingBase.onUpdate() (func_110146_f) which runs AFTER onLivingUpdate() + // and overwrites renderYawOffset, causing a visible twitch each frame. + abilities.applyLockedRotation(); + abilities.applyLockedPosition(); + if (!isRemote()) { if (this.ticksExisted % 10 == 0) { EventHooks.onNPCUpdate(this);