mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-13 01:57:34 +00:00
Better Fix to Lock Movement and Rotation Locking during Abilities. Fix Interupting on Projectile Abilities
This commit is contained in:
1 parent
86055202a9
commit
326626ad8e
26 files changed
+266
-51
No files matched your search
@@ -67,6 +67,7 @@ public abstract class Ability implements IAbility {
|
||||
|
||||
// Feedback
|
||||
protected LockMovementType lockMovement = LockMovementType.WINDUP;
|
||||
protected LockType lockType = LockType.BOTH;
|
||||
protected int windUpColor = 0x80FF4400; // Telegraph color during wind up
|
||||
protected int activeColor = 0xC0FF0000; // Telegraph warning/active color
|
||||
|
||||
@@ -390,15 +391,27 @@ public abstract class Ability implements IAbility {
|
||||
defs.add(FieldDef.intField("ability.cooldownTicks", this::getCooldownTicks, this::setCooldownTicks)
|
||||
.tab("General").range(0, 10000));
|
||||
defs.add(FieldDef.section("ability.section.movement").tab("General"));
|
||||
defs.add(FieldDef.stringEnumField("ability.lockMovement", LockMovementType.getDisplayKeys(),
|
||||
() -> this.getLockMovement().getDisplayKey(),
|
||||
v -> {
|
||||
String[] keys = LockMovementType.getDisplayKeys();
|
||||
for (int i = 0; i < keys.length; i++) {
|
||||
if (keys[i].equals(v)) { this.setLockMovement(LockMovementType.fromOrdinal(i)); break; }
|
||||
}
|
||||
})
|
||||
.tab("General").hover("ability.hover.lockMove"));
|
||||
defs.add(FieldDef.row(
|
||||
FieldDef.stringEnumField("ability.lockPosition", LockMovementType.getDisplayKeys(),
|
||||
() -> this.getLockMovement().getDisplayKey(),
|
||||
v -> {
|
||||
String[] keys = LockMovementType.getDisplayKeys();
|
||||
for (int i = 0; i < keys.length; i++) {
|
||||
if (keys[i].equals(v)) { this.setLockMovement(LockMovementType.fromOrdinal(i)); break; }
|
||||
}
|
||||
})
|
||||
.hover("ability.hover.lockPosition"),
|
||||
FieldDef.stringEnumField("ability.lockType", LockType.getDisplayKeys(),
|
||||
() -> this.getLockType().getDisplayKey(),
|
||||
v -> {
|
||||
String[] keys = LockType.getDisplayKeys();
|
||||
for (int i = 0; i < keys.length; i++) {
|
||||
if (keys[i].equals(v)) { this.setLockType(LockType.fromOrdinal(i)); break; }
|
||||
}
|
||||
})
|
||||
.hover("ability.hover.lockType")
|
||||
.visibleWhen(() -> this.lockMovement != LockMovementType.NO)
|
||||
).tab("General"));
|
||||
defs.add(FieldDef.row(
|
||||
FieldDef.boolField("ability.interruptible", this::isInterruptible, this::setInterruptible)
|
||||
.hover("ability.hover.interruptible"),
|
||||
@@ -940,6 +953,7 @@ public abstract class Ability implements IAbility {
|
||||
nbt.setInteger("recovery", dazedTicks);
|
||||
nbt.setBoolean("interruptible", interruptible);
|
||||
nbt.setInteger("lockMovement", lockMovement.ordinal());
|
||||
nbt.setInteger("lockType", lockType.ordinal());
|
||||
nbt.setInteger("windUpColor", windUpColor);
|
||||
nbt.setInteger("activeColor", activeColor);
|
||||
nbt.setString("windUpSound", windUpSound);
|
||||
@@ -990,6 +1004,7 @@ public abstract class Ability implements IAbility {
|
||||
dazedTicks = nbt.getInteger("recovery");
|
||||
interruptible = nbt.getBoolean("interruptible");
|
||||
lockMovement = LockMovementType.fromOrdinal(nbt.getInteger("lockMovement"));
|
||||
lockType = nbt.hasKey("lockType") ? LockType.fromOrdinal(nbt.getInteger("lockType")) : LockType.BOTH;
|
||||
windUpColor = nbt.getInteger("windUpColor");
|
||||
activeColor = nbt.getInteger("activeColor");
|
||||
windUpSound = nbt.getString("windUpSound");
|
||||
@@ -1154,6 +1169,14 @@ public abstract class Ability implements IAbility {
|
||||
this.lockMovement = lockMovement;
|
||||
}
|
||||
|
||||
public LockType getLockType() {
|
||||
return lockType;
|
||||
}
|
||||
|
||||
public void setLockType(LockType lockType) {
|
||||
this.lockType = lockType;
|
||||
}
|
||||
|
||||
/**
|
||||
* API method: Get lock movement type as integer.
|
||||
* @return 0=NO, 1=WINDUP, 2=ACTIVE, 3=WINDUP_AND_ACTIVE
|
||||
@@ -1173,19 +1196,53 @@ public abstract class Ability implements IAbility {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if movement should be locked during WINDUP phase.
|
||||
* API method: Get lock type as integer.
|
||||
* @return 0=MOVEMENT, 1=ROTATION, 2=BOTH
|
||||
*/
|
||||
@Override
|
||||
public boolean isMovementLockedDuringWindup() {
|
||||
return lockMovement.locksWindup();
|
||||
public int getLockTypeOrdinal() {
|
||||
return lockType.ordinal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if movement should be locked during ACTIVE phase.
|
||||
* API method: Set lock type from integer.
|
||||
* @param type 0=MOVEMENT, 1=ROTATION, 2=BOTH
|
||||
*/
|
||||
@Override
|
||||
public void setLockTypeOrdinal(int type) {
|
||||
this.lockType = LockType.fromOrdinal(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if movement (pathfinding/motion) should be locked during WINDUP phase.
|
||||
*/
|
||||
@Override
|
||||
public boolean isMovementLockedDuringWindup() {
|
||||
return lockMovement.locksWindup() && lockType.locksMovement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if movement (pathfinding/motion) should be locked during ACTIVE phase.
|
||||
*/
|
||||
@Override
|
||||
public boolean isMovementLockedDuringActive() {
|
||||
return lockMovement.locksActive();
|
||||
return lockMovement.locksActive() && lockType.locksMovement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if rotation (yaw/pitch) should be locked during WINDUP phase.
|
||||
*/
|
||||
@Override
|
||||
public boolean isRotationLockedDuringWindup() {
|
||||
return lockMovement.locksWindup() && lockType.locksRotation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if rotation (yaw/pitch) should be locked during ACTIVE phase.
|
||||
*/
|
||||
@Override
|
||||
public boolean isRotationLockedDuringActive() {
|
||||
return lockMovement.locksActive() && lockType.locksRotation();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1194,9 +1251,23 @@ public abstract class Ability implements IAbility {
|
||||
public boolean isMovementLockedForCurrentPhase() {
|
||||
switch (phase) {
|
||||
case WINDUP:
|
||||
return lockMovement.locksWindup();
|
||||
return isMovementLockedDuringWindup();
|
||||
case ACTIVE:
|
||||
return lockMovement.locksActive();
|
||||
return isMovementLockedDuringActive();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if rotation should be locked during the current phase.
|
||||
*/
|
||||
public boolean isRotationLockedForCurrentPhase() {
|
||||
switch (phase) {
|
||||
case WINDUP:
|
||||
return isRotationLockedDuringWindup();
|
||||
case ACTIVE:
|
||||
return isRotationLockedDuringActive();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package kamkeel.npcs.controllers.data.ability;
|
||||
|
||||
/**
|
||||
* Defines what an ability locks when Lock Position is enabled.
|
||||
*/
|
||||
public enum LockType {
|
||||
MOVEMENT,
|
||||
ROTATION,
|
||||
BOTH;
|
||||
|
||||
public boolean locksMovement() {
|
||||
return this == MOVEMENT || this == BOTH;
|
||||
}
|
||||
|
||||
public boolean locksRotation() {
|
||||
return this == ROTATION || this == BOTH;
|
||||
}
|
||||
|
||||
public String getDisplayKey() {
|
||||
switch (this) {
|
||||
case MOVEMENT:
|
||||
return "ability.lockType.movement";
|
||||
case ROTATION:
|
||||
return "ability.lockType.rotation";
|
||||
case BOTH:
|
||||
return "ability.lockType.both";
|
||||
default:
|
||||
return "ability.lockType.both";
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] getDisplayKeys() {
|
||||
return new String[]{
|
||||
"ability.lockType.movement",
|
||||
"ability.lockType.rotation",
|
||||
"ability.lockType.both"
|
||||
};
|
||||
}
|
||||
|
||||
public static LockType fromOrdinal(int ordinal) {
|
||||
LockType[] values = values();
|
||||
if (ordinal >= 0 && ordinal < values.length) {
|
||||
return values[ordinal];
|
||||
}
|
||||
return BOTH;
|
||||
}
|
||||
}
|
||||
@@ -126,6 +126,11 @@ public class AbilityBeam extends Ability implements IAbilityEnergyBeam {
|
||||
public void onComplete(EntityLivingBase caster, EntityLivingBase target) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInterrupt(EntityLivingBase caster, net.minecraft.util.DamageSource source, float damage) {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
// Despawn beam entity if still alive
|
||||
|
||||
@@ -167,6 +167,11 @@ public class AbilityBeamDual extends Ability {
|
||||
public void onComplete(EntityLivingBase caster, EntityLivingBase target) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInterrupt(EntityLivingBase caster, net.minecraft.util.DamageSource source, float damage) {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
// Despawn beam entity if still alive
|
||||
|
||||
@@ -127,6 +127,11 @@ public class AbilityDisc extends Ability implements IAbilityDisc {
|
||||
public void onComplete(EntityLivingBase caster, EntityLivingBase target) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInterrupt(EntityLivingBase caster, net.minecraft.util.DamageSource source, float damage) {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
// Despawn disc entity if still alive
|
||||
|
||||
@@ -176,6 +176,11 @@ public class AbilityDiscDual extends Ability {
|
||||
public void onComplete(EntityLivingBase caster, EntityLivingBase target) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInterrupt(EntityLivingBase caster, net.minecraft.util.DamageSource source, float damage) {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
// Despawn disc entity if still alive
|
||||
|
||||
@@ -136,6 +136,7 @@ public class AbilityLaserShot extends Ability implements IAbilityLaserShot {
|
||||
|
||||
@Override
|
||||
public void onInterrupt(EntityLivingBase caster, DamageSource source, float damage) {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -122,6 +122,11 @@ public class AbilityOrb extends Ability implements IAbilityOrb {
|
||||
// Nothing to clean up - entity manages itself
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInterrupt(EntityLivingBase caster, net.minecraft.util.DamageSource source, float damage) {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
// Despawn orb entity if still alive
|
||||
|
||||
@@ -211,6 +211,11 @@ public class AbilityOrbBarrage extends Ability {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInterrupt(EntityLivingBase caster, DamageSource source, float damage) {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
currentOrb = 0;
|
||||
|
||||
@@ -161,7 +161,11 @@ public class AbilityOrbDual extends Ability {
|
||||
|
||||
@Override
|
||||
public void onComplete(EntityLivingBase caster, EntityLivingBase target) {
|
||||
// Nothing to clean up - entity manages itself
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInterrupt(EntityLivingBase caster, net.minecraft.util.DamageSource source, float damage) {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -217,9 +217,6 @@ public class AbilitySlam extends Ability implements IAbilitySlam {
|
||||
double dragPowN = Math.pow(drag, flightTicks);
|
||||
double vHorizontal = horizontalDist * (1.0 - drag) / (1.0 - dragPowN);
|
||||
|
||||
// Speed scales horizontal velocity to cover ground faster
|
||||
vHorizontal *= speedFactor;
|
||||
|
||||
// Adjust vertical velocity for height difference between start and target
|
||||
if (dy > 0) {
|
||||
vy += dy / flightTicks * 1.5; // Going up - need more velocity
|
||||
@@ -438,7 +435,7 @@ public class AbilitySlam extends Ability implements IAbilitySlam {
|
||||
int flightTicks = (int) Math.max(10, Math.min(horizontalDist * 1.5 / speedFactor, 40));
|
||||
double drag = 0.91;
|
||||
double dragPowN = Math.pow(drag, flightTicks);
|
||||
double vHorizontal = horizontalDist * (1.0 - drag) / (1.0 - dragPowN) * speedFactor;
|
||||
double vHorizontal = horizontalDist * (1.0 - drag) / (1.0 - dragPowN);
|
||||
|
||||
double dirX = dx / horizontalDist;
|
||||
double dirZ = dz / horizontalDist;
|
||||
|
||||
@@ -100,6 +100,11 @@ public class AbilitySweeper extends Ability implements IAbilitySweeper {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInterrupt(EntityLivingBase caster, net.minecraft.util.DamageSource source, float damage) {
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
// Clean up entity if still alive
|
||||
|
||||
@@ -205,10 +205,19 @@ public class EntityAbilityLaser extends EntityAbilityProjectile {
|
||||
startY = posY;
|
||||
startZ = posZ;
|
||||
|
||||
// Calculate velocity toward target
|
||||
// Always derive direction from the owner's current yaw/pitch.
|
||||
// This ensures the laser fires in the direction the NPC is visually facing,
|
||||
// which matches the telegraph line direction regardless of Lock Movement mode.
|
||||
Entity owner = getOwnerEntity();
|
||||
|
||||
if (target != null) {
|
||||
if (owner != null) {
|
||||
float yaw = (float) Math.toRadians(owner.rotationYaw);
|
||||
float pitch = (float) Math.toRadians(owner.rotationPitch);
|
||||
this.dirX = -Math.sin(yaw) * Math.cos(pitch);
|
||||
this.dirY = -Math.sin(pitch);
|
||||
this.dirZ = Math.cos(yaw) * Math.cos(pitch);
|
||||
} else if (target != null) {
|
||||
// Fallback: aim at target if owner is somehow unavailable
|
||||
double dx = target.posX - startX;
|
||||
double dy = (target.posY + target.getEyeHeight() - 0.4) - startY;
|
||||
double dz = target.posZ - startZ;
|
||||
@@ -218,13 +227,6 @@ public class EntityAbilityLaser extends EntityAbilityProjectile {
|
||||
this.dirY = dy / len;
|
||||
this.dirZ = dz / len;
|
||||
}
|
||||
} else if (owner != null) {
|
||||
// Fire in NPC's facing direction
|
||||
float yaw = (float) Math.toRadians(owner.rotationYaw);
|
||||
float pitch = (float) Math.toRadians(owner.rotationPitch);
|
||||
this.dirX = -Math.sin(yaw) * Math.cos(pitch);
|
||||
this.dirY = -Math.sin(pitch);
|
||||
this.dirZ = Math.cos(yaw) * Math.cos(pitch);;
|
||||
}
|
||||
|
||||
setPosition(endX, endY, endZ);
|
||||
|
||||
@@ -18,6 +18,7 @@ import noppes.npcs.entity.EntityNPCInterface;
|
||||
import noppes.npcs.scripted.NpcAPI;
|
||||
import noppes.npcs.scripted.event.AbilityEvent;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
@@ -147,10 +148,15 @@ public class DataAbilities {
|
||||
// Remove telegraph - it has served its purpose
|
||||
removeTelegraph(currentAbility);
|
||||
|
||||
// Lock rotation if movement is locked during ACTIVE phase
|
||||
// Capture current rotation values to force them every tick
|
||||
if (currentAbility.isMovementLockedDuringActive()) {
|
||||
captureLockedRotation();
|
||||
// Handle rotation lock transition from WINDUP to ACTIVE
|
||||
if (currentAbility.isRotationLockedDuringActive()) {
|
||||
// ACTIVE or WINDUP_AND_ACTIVE: capture (or keep) rotation lock
|
||||
if (!rotationLocked) {
|
||||
captureLockedRotation();
|
||||
}
|
||||
} else if (rotationLocked) {
|
||||
// WINDUP only: release the lock now that windup is over
|
||||
releaseLockedRotation();
|
||||
}
|
||||
|
||||
// Play active sound and animation
|
||||
@@ -390,6 +396,9 @@ public class DataAbilities {
|
||||
executeImmediate(ability, target);
|
||||
} else {
|
||||
// Normal windup flow
|
||||
if (ability.isRotationLockedDuringWindup()) {
|
||||
captureLockedRotation();
|
||||
}
|
||||
spawnTelegraph(ability, target);
|
||||
playAbilitySound(ability.getWindUpSound());
|
||||
playAbilityAnimation(ability.getWindUpAnimation());
|
||||
@@ -403,8 +412,8 @@ public class DataAbilities {
|
||||
* Called when windUpTicks is 0.
|
||||
*/
|
||||
private void executeImmediate(Ability ability, EntityLivingBase target) {
|
||||
// Lock rotation if movement is locked during ACTIVE phase
|
||||
if (ability.isMovementLockedDuringActive()) {
|
||||
// Lock rotation if rotation is locked during ACTIVE phase
|
||||
if (ability.isRotationLockedDuringActive()) {
|
||||
captureLockedRotation();
|
||||
}
|
||||
|
||||
@@ -934,9 +943,12 @@ public class DataAbilities {
|
||||
// ROTATION LOCKING
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
/** Bit flag for rotation lock in the existing data watcher slot 15 bitfield */
|
||||
private static final int ROTATION_LOCKED_FLAG = 16;
|
||||
|
||||
/**
|
||||
* Capture current rotation values to lock NPC's look direction.
|
||||
* Called when entering ACTIVE phase with movement locked during active.
|
||||
* Called when entering a locked phase (WINDUP or ACTIVE depending on LockMovementType).
|
||||
*/
|
||||
private void captureLockedRotation() {
|
||||
lockedYaw = npc.rotationYaw;
|
||||
@@ -944,22 +956,53 @@ public class DataAbilities {
|
||||
lockedRenderYawOffset = npc.renderYawOffset;
|
||||
lockedPitch = npc.rotationPitch;
|
||||
rotationLocked = true;
|
||||
npc.setBoolFlag(true, ROTATION_LOCKED_FLAG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Release the rotation lock.
|
||||
* Called when leaving ACTIVE phase or ability completes.
|
||||
* Called when leaving the locked phase or ability completes.
|
||||
*/
|
||||
private void releaseLockedRotation() {
|
||||
rotationLocked = false;
|
||||
npc.setBoolFlag(false, ROTATION_LOCKED_FLAG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply locked rotation values to the NPC.
|
||||
* Called AFTER super.onLivingUpdate() in EntityNPCInterface to override
|
||||
* any rotation changes made by the look helper or AI tasks.
|
||||
* any rotation changes made by the look helper, AI tasks, or body smoothing.
|
||||
* Runs on both client and server.
|
||||
*/
|
||||
public void applyLockedRotation() {
|
||||
if (npc.worldObj.isRemote) {
|
||||
// Client-side: check bit 16 in the existing flags data watcher (slot 15)
|
||||
boolean flagActive = npc.getBoolFlag(ROTATION_LOCKED_FLAG);
|
||||
if (!flagActive) {
|
||||
rotationLocked = false;
|
||||
return;
|
||||
}
|
||||
// First tick the flag is active: capture current rotation values
|
||||
if (!rotationLocked) {
|
||||
lockedYaw = npc.rotationYaw;
|
||||
lockedYawHead = npc.rotationYawHead;
|
||||
lockedRenderYawOffset = npc.renderYawOffset;
|
||||
lockedPitch = npc.rotationPitch;
|
||||
rotationLocked = true;
|
||||
}
|
||||
// Force all rotation values back to locked state
|
||||
npc.rotationYaw = lockedYaw;
|
||||
npc.rotationYawHead = lockedYawHead;
|
||||
npc.renderYawOffset = lockedRenderYawOffset;
|
||||
npc.rotationPitch = lockedPitch;
|
||||
npc.prevRotationYaw = lockedYaw;
|
||||
npc.prevRotationYawHead = lockedYawHead;
|
||||
npc.prevRenderYawOffset = lockedRenderYawOffset;
|
||||
npc.prevRotationPitch = lockedPitch;
|
||||
return;
|
||||
}
|
||||
|
||||
// Server-side: use stored locked values
|
||||
if (!rotationLocked) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -93,7 +93,9 @@ public class EntityAIAmbushTarget extends EntityAIBase {
|
||||
* Updates the task
|
||||
*/
|
||||
public void updateTask() {
|
||||
this.theEntity.getLookHelper().setLookPositionWithEntity(targetEntity, 30.0F, 30.0F);
|
||||
if (!this.theEntity.abilities.isRotationLocked()) {
|
||||
this.theEntity.getLookHelper().setLookPositionWithEntity(targetEntity, 30.0F, 30.0F);
|
||||
}
|
||||
}
|
||||
|
||||
private Vec3 findHidingSpot() {
|
||||
|
||||
@@ -118,7 +118,9 @@ public class EntityAIAttackTarget extends EntityAIBase {
|
||||
* Updates the task
|
||||
*/
|
||||
public void updateTask() {
|
||||
this.npc.getLookHelper().setLookPositionWithEntity(this.entityTarget, 30.0F, 30.0F);
|
||||
if (!this.npc.abilities.isRotationLocked()) {
|
||||
this.npc.getLookHelper().setLookPositionWithEntity(this.entityTarget, 30.0F, 30.0F);
|
||||
}
|
||||
|
||||
// Skip pathfinding updates if ability is controlling movement
|
||||
if (!navOverride && !this.npc.abilities.isAbilityControllingMovement() && --this.field_75445_i <= 0) {
|
||||
|
||||
@@ -63,7 +63,7 @@ public class EntityAIDodgeShoot extends EntityAIBase {
|
||||
* Updates the task
|
||||
*/
|
||||
public void updateTask() {
|
||||
if (this.entity.getAttackTarget() != null)
|
||||
if (this.entity.getAttackTarget() != null && !this.entity.abilities.isRotationLocked())
|
||||
this.entity.getLookHelper().setLookPositionWithEntity(this.entity.getAttackTarget(), 30.0F, 30.0F);
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,9 @@ public class EntityAIFollow extends EntityAIBase {
|
||||
if (updateTick < 10)
|
||||
return;
|
||||
updateTick = 0;
|
||||
this.npc.getLookHelper().setLookPositionWithEntity(owner, 10.0F, (float) this.npc.getVerticalFaceSpeed());
|
||||
if (!this.npc.abilities.isRotationLocked()) {
|
||||
this.npc.getLookHelper().setLookPositionWithEntity(owner, 10.0F, (float) this.npc.getVerticalFaceSpeed());
|
||||
}
|
||||
|
||||
double speed = 1 + distance / 150;
|
||||
if (speed > 3)
|
||||
|
||||
@@ -26,7 +26,7 @@ public class EntityAILook extends EntityAIBase {
|
||||
*/
|
||||
@Override
|
||||
public boolean shouldExecute() {
|
||||
return !npc.isAttacking() && npc.getNavigator().noPath() && !npc.isPlayerSleeping() && npc.isEntityAlive();
|
||||
return !npc.abilities.isRotationLocked() && !npc.isAttacking() && npc.getNavigator().noPath() && !npc.isPlayerSleeping() && npc.isEntityAlive();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -91,7 +91,9 @@ public class EntityAIOrbitTarget extends EntityAIBase {
|
||||
* Updates the task
|
||||
*/
|
||||
public void updateTask() {
|
||||
this.theEntity.getLookHelper().setLookPositionWithEntity(targetEntity, 30.0F, 30.0F);
|
||||
if (!this.theEntity.abilities.isRotationLocked()) {
|
||||
this.theEntity.getLookHelper().setLookPositionWithEntity(targetEntity, 30.0F, 30.0F);
|
||||
}
|
||||
if (this.theEntity.getNavigator().noPath() && this.tick >= 0) {
|
||||
if (this.theEntity.onGround && !this.theEntity.isInWater()) {
|
||||
double d0 = this.targetDistance * (double) (MathHelper.cos(angle / 180.0F * (float) Math.PI));
|
||||
|
||||
@@ -100,7 +100,9 @@ public class EntityAIRangedAttack extends EntityAIBase {
|
||||
* Updates the task
|
||||
*/
|
||||
public void updateTask() {
|
||||
this.entityHost.getLookHelper().setLookPositionWithEntity(this.attackTarget, 30.0F, 30.0F);
|
||||
if (!this.entityHost.abilities.isRotationLocked()) {
|
||||
this.entityHost.getLookHelper().setLookPositionWithEntity(this.attackTarget, 30.0F, 30.0F);
|
||||
}
|
||||
double var1 = this.entityHost.getDistanceSq(this.attackTarget.posX, this.attackTarget.boundingBox.minY, this.attackTarget.posZ);
|
||||
float field_82642_h = this.entityHost.stats.rangedRange * this.entityHost.stats.rangedRange;
|
||||
|
||||
|
||||
@@ -68,7 +68,9 @@ public class EntityAIStalkTarget extends EntityAIBase {
|
||||
* Updates the task
|
||||
*/
|
||||
public void updateTask() {
|
||||
this.theEntity.getLookHelper().setLookPositionWithEntity(targetEntity, 30.0F, 30.0F);
|
||||
if (!this.theEntity.abilities.isRotationLocked()) {
|
||||
this.theEntity.getLookHelper().setLookPositionWithEntity(targetEntity, 30.0F, 30.0F);
|
||||
}
|
||||
|
||||
if (this.theEntity.getNavigator().noPath() || this.overRide) {
|
||||
if (this.isLookingAway()) {
|
||||
|
||||
@@ -31,7 +31,7 @@ public class EntityAIWatchClosest extends EntityAIBase {
|
||||
*/
|
||||
@Override
|
||||
public boolean shouldExecute() {
|
||||
if (this.theWatcher.getRNG().nextFloat() >= this.field_75331_e || theWatcher.isInteracting()) {
|
||||
if (this.theWatcher.abilities.isRotationLocked() || this.theWatcher.getRNG().nextFloat() >= this.field_75331_e || theWatcher.isInteracting()) {
|
||||
return false;
|
||||
} else {
|
||||
if (this.theWatcher.getAttackTarget() != null) {
|
||||
|
||||
@@ -8,6 +8,7 @@ import net.minecraft.pathfinding.PathPoint;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.util.Vec3;
|
||||
import noppes.npcs.constants.AiMutex;
|
||||
import noppes.npcs.entity.EntityNPCInterface;
|
||||
|
||||
public class EntityAIZigZagTarget extends EntityAIBase {
|
||||
private EntityCreature theEntity;
|
||||
@@ -82,6 +83,8 @@ public class EntityAIZigZagTarget extends EntityAIBase {
|
||||
* Updates the task
|
||||
*/
|
||||
public void updateTask() {
|
||||
this.theEntity.getLookHelper().setLookPositionWithEntity(targetEntity, 30.0F, 30.0F);
|
||||
if (!(this.theEntity instanceof EntityNPCInterface) || !((EntityNPCInterface) this.theEntity).abilities.isRotationLocked()) {
|
||||
this.theEntity.getLookHelper().setLookPositionWithEntity(targetEntity, 30.0F, 30.0F);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1693,7 +1693,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti
|
||||
}
|
||||
|
||||
/**
|
||||
* 1: walking, 2:interacting, 4:attacking, 8:killed
|
||||
* 1: walking, 2:interacting, 4:attacking, 8:killed, 16:rotationLocked
|
||||
*/
|
||||
public boolean getBoolFlag(int id) {
|
||||
return (dataWatcher.getWatchableObjectInt(15) & id) != 0;
|
||||
|
||||
Reference in new issue
Block a user