diff --git a/src/main/java/noppes/npcs/entity/EntityNPCInterface.java b/src/main/java/noppes/npcs/entity/EntityNPCInterface.java index ff269b964..58aadb253 100644 --- a/src/main/java/noppes/npcs/entity/EntityNPCInterface.java +++ b/src/main/java/noppes/npcs/entity/EntityNPCInterface.java @@ -2129,15 +2129,38 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti this.moveStrafing = strafe; this.moveForward = forward; - if (isMountFlightModeActive()) { - performMountedFlightMovement(strafe, forward, moveSpeed); - return; - } + boolean flightMode = isMountFlightModeActive(); + double prevMotionX = this.motionX; + double prevMotionY = this.motionY; + double prevMotionZ = this.motionZ; + float previousJumpFactor = this.jumpMovementFactor; + float appliedJumpFactor = getMountedAirStrafeFactor(moveSpeed, flightMode); + + this.jumpMovementFactor = appliedJumpFactor; if (!worldObj.isRemote) { this.setAIMoveSpeed(moveSpeed); } + super.moveEntityWithHeading(strafe, forward); + + if (flightMode) { + this.motionY = prevMotionY; + this.isAirBorne = true; + } + + this.jumpMovementFactor = previousJumpFactor; + + if (!worldObj.isRemote) { + double newMotionX = this.motionX; + double newMotionY = this.motionY; + double newMotionZ = this.motionZ; + if (Math.abs(newMotionX - prevMotionX) > 1.0E-5D || Math.abs(newMotionY - prevMotionY) > 1.0E-5D || Math.abs(newMotionZ - prevMotionZ) > 1.0E-5D) { + this.velocityChanged = true; + } + } + + syncMountedRiderVelocity(); updateMountedLimbSwing(); } @@ -2145,39 +2168,38 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti return NPCMountUtil.isMountInFlightMode(mountState); } - private void performMountedFlightMovement(float strafe, float forward, float moveSpeed) { + private float getMountedAirStrafeFactor(float moveSpeed, boolean flightMode) { + if (moveSpeed <= 0.0F) { + return 0.0F; + } + if (!flightMode) { + return moveSpeed * 0.1F; + } + final float AIR_FRICTION = 0.91F; + final float BASE = 0.16277136F; + return moveSpeed * (BASE / (AIR_FRICTION * AIR_FRICTION * AIR_FRICTION)); + } + + private void syncMountedRiderVelocity() { + if (!(this.riddenByEntity instanceof EntityLivingBase)) { + return; + } + EntityLivingBase rider = (EntityLivingBase) this.riddenByEntity; + double riderPrevMotionX = rider.motionX; + double riderPrevMotionY = rider.motionY; + double riderPrevMotionZ = rider.motionZ; + + rider.motionX = this.motionX; + rider.motionY = this.motionY; + rider.motionZ = this.motionZ; + rider.fallDistance = 0.0F; + rider.isAirBorne = !this.onGround; + if (!worldObj.isRemote) { - this.setAIMoveSpeed(moveSpeed); - } - - float inputMagnitude = MathHelper.sqrt_float(strafe * strafe + forward * forward); - if (inputMagnitude < 1.0E-3F) { - this.motionX *= 0.6D; - this.motionZ *= 0.6D; - if (Math.abs(this.motionX) < 0.003D) { - this.motionX = 0.0D; + if (Math.abs(rider.motionX - riderPrevMotionX) > 1.0E-5D || Math.abs(rider.motionY - riderPrevMotionY) > 1.0E-5D || Math.abs(rider.motionZ - riderPrevMotionZ) > 1.0E-5D) { + rider.velocityChanged = true; } - if (Math.abs(this.motionZ) < 0.003D) { - this.motionZ = 0.0D; - } - } else { - float normStrafe = strafe / inputMagnitude; - float normForward = forward / inputMagnitude; - float yawRad = this.rotationYaw * (float) Math.PI / 180.0F; - double sinYaw = Math.sin(yawRad); - double cosYaw = Math.cos(yawRad); - double targetMotionX = (normStrafe * cosYaw - normForward * sinYaw) * moveSpeed; - double targetMotionZ = (normForward * cosYaw + normStrafe * sinYaw) * moveSpeed; - this.motionX = targetMotionX; - this.motionZ = targetMotionZ; } - - this.moveEntity(this.motionX, this.motionY, this.motionZ); - this.velocityChanged = true; - if (!this.onGround) { - this.isAirBorne = true; - } - updateMountedLimbSwing(); } private void updateMountedLimbSwing() { diff --git a/src/main/java/noppes/npcs/util/NPCMountUtil.java b/src/main/java/noppes/npcs/util/NPCMountUtil.java index 1caa4ba14..708bf3b76 100644 --- a/src/main/java/noppes/npcs/util/NPCMountUtil.java +++ b/src/main/java/noppes/npcs/util/NPCMountUtil.java @@ -54,7 +54,7 @@ public final class NPCMountUtil { controlledForward *= 0.25F; } - float moveSpeed = Math.max(0.0F, npc.getSpeed()); + float moveSpeed = getMountMoveSpeed(npc); boolean riderSprinting = rider.isSprinting() && mount.isSprintAllowed(); if (riderSprinting) { moveSpeed *= 1.2F; @@ -71,7 +71,6 @@ public final class NPCMountUtil { npc.setSprinting(riderSprinting); npc.stepHeight = 1.0F; - npc.jumpMovementFactor = moveSpeed * 0.1F; npc.getNavigator().clearPathEntity(); npc.setAttackTarget(null); @@ -86,6 +85,10 @@ public final class NPCMountUtil { return true; } + private static float getMountMoveSpeed(EntityNPCInterface npc) { + return Math.max(0.0F, npc.getSpeed()); + } + private static void applyMountedVerticalMotion(EntityNPCInterface npc, MountState state, RoleMount mount, EntityLivingBase rider, float moveSpeed, float forward) { if (mount == null) { return; @@ -103,46 +106,65 @@ public final class NPCMountUtil { boolean descendPressed = rider instanceof EntityPlayer && isSpecialKeyDown((EntityPlayer) rider); if (flightMode) { - npc.motionY = 0.0D; + double previousMotionY = npc.motionY; + double newMotionY = 0.0D; if (jumpPressed) { - npc.motionY += ascendSpeed; + newMotionY += ascendSpeed; } else if (descendPressed) { - npc.motionY -= descendSpeed; + newMotionY -= descendSpeed; } - npc.motionY = MathHelper.clamp_double(npc.motionY, -descendSpeed, ascendSpeed); - + newMotionY = MathHelper.clamp_double(newMotionY, -descendSpeed, ascendSpeed); + npc.motionY = newMotionY; npc.setNpcFlyingState(true); npc.setNpcJumpingState(jumpPressed); npc.isAirBorne = true; - npc.velocityChanged = true; npc.fallDistance = 0.0F; + if (!npc.worldObj.isRemote && Math.abs(previousMotionY - newMotionY) > 1.0E-4D) { + npc.velocityChanged = true; + } + if (!npc.worldObj.isRemote && rider instanceof EntityPlayer) { EntityPlayer player = (EntityPlayer) rider; if (!player.capabilities.isFlying) { + double playerPrevMotion = player.motionY; player.motionY = npc.motionY; - player.velocityChanged = true; + if (Math.abs(playerPrevMotion - player.motionY) > 1.0E-4D) { + player.velocityChanged = true; + } } } return; } if (jumpPressed && npc.onGround) { + double previousMotionY = npc.motionY; npc.motionY = jumpFactor; npc.setNpcJumpingState(true); npc.isAirBorne = true; - npc.velocityChanged = true; npc.fallDistance = 0.0F; if (!npc.worldObj.isRemote) { + if (Math.abs(previousMotionY - npc.motionY) > 1.0E-4D) { + npc.velocityChanged = true; + } net.minecraftforge.common.ForgeHooks.onLivingJump(npc); } return; } if (!npc.onGround) { - npc.motionY = Math.max(npc.motionY, -descendSpeed); + double previousMotionY = npc.motionY; + double limitedMotionY = Math.max(npc.motionY, -descendSpeed); + if (Math.abs(previousMotionY - limitedMotionY) > 1.0E-4D) { + npc.motionY = limitedMotionY; + if (!npc.worldObj.isRemote) { + npc.velocityChanged = true; + } + } else { + npc.motionY = limitedMotionY; + } npc.setNpcFlyingState(!npc.isInWater()); } else { npc.setNpcFlyingState(false); @@ -152,13 +174,16 @@ public final class NPCMountUtil { } if (npc.onGround) { + double previousMotionY = npc.motionY; if (rider.isJumping) { npc.motionY = jumpFactor; npc.setNpcJumpingState(true); npc.isAirBorne = true; - npc.velocityChanged = true; npc.fallDistance = 0.0F; if (!npc.worldObj.isRemote) { + if (Math.abs(previousMotionY - npc.motionY) > 1.0E-4D) { + npc.velocityChanged = true; + } net.minecraftforge.common.ForgeHooks.onLivingJump(npc); } } else { @@ -214,10 +239,12 @@ public final class NPCMountUtil { } public static void haltMountedMotion(EntityNPCInterface npc, MountState state) { + double prevMotionX = npc.motionX; + double prevMotionY = npc.motionY; + double prevMotionZ = npc.motionZ; npc.motionX = 0.0D; npc.motionY = 0.0D; npc.motionZ = 0.0D; - npc.velocityChanged = true; npc.isAirBorne = false; npc.setSprinting(false); npc.moveForward = 0.0F; @@ -227,6 +254,9 @@ public final class NPCMountUtil { npc.limbSwing = 0.0F; npc.getNavigator().clearPathEntity(); npc.fallDistance = 0.0F; + if (!npc.worldObj.isRemote && (Math.abs(prevMotionX) > 1.0E-4D || Math.abs(prevMotionY) > 1.0E-4D || Math.abs(prevMotionZ) > 1.0E-4D)) { + npc.velocityChanged = true; + } resetMountedFlightState(npc, state); } @@ -254,12 +284,15 @@ public final class NPCMountUtil { } double desired = -descendSpeed; + double previousMotionY = npc.motionY; npc.motionY = desired; npc.isAirBorne = true; - npc.velocityChanged = true; npc.fallDistance = 0.0F; npc.setNpcFlyingState(true); npc.setNpcJumpingState(false); + if (!npc.worldObj.isRemote && Math.abs(previousMotionY - desired) > 1.0E-4D) { + npc.velocityChanged = true; + } } public static void stabilizeDismountedRider(Entity rider) {