Smoother + Most-Cost Effective Flight Pathing

This commit is contained in:
Kam committed 2026-02-23 04:38:02 -05:00
1 parent 960b223155
commit a79ba3a0e4
3 files changed
+114 -14

No files matched your search

@@ -173,7 +173,8 @@ public class FlyPathFinder extends PathFinder {
for (int j = 0; j < i; ++j) {
NPCPathPoint pathpoint5 = this.pathOptions[j];
float f1 = pathpoint4.totalPathDistance + this.getTraversalCost(pathpoint4, pathpoint5);
float f1 = pathpoint4.totalPathDistance + this.getTraversalCost(pathpoint4, pathpoint5)
+ this.getDirectionalPenalty(pathpoint4, pathpoint5, p_75861_3_);
if (!pathpoint5.isAssigned() || f1 < pathpoint5.totalPathDistance) {
pathpoint5.previous = pathpoint4;
@@ -211,6 +212,24 @@ public class FlyPathFinder extends PathFinder {
return DIAGONAL_3D_COST;
}
private float getDirectionalPenalty(NPCPathPoint from, NPCPathPoint to, NPCPathPoint goal) {
int stepX = to.xCoord - from.xCoord;
int stepY = to.yCoord - from.yCoord;
int stepZ = to.zCoord - from.zCoord;
int goalX = goal.xCoord - from.xCoord;
int goalY = goal.yCoord - from.yCoord;
int goalZ = goal.zCoord - from.zCoord;
int stepLen = Math.abs(stepX) + Math.abs(stepY) + Math.abs(stepZ);
int goalLen = Math.abs(goalX) + Math.abs(goalY) + Math.abs(goalZ);
if (stepLen == 0 || goalLen == 0) {
return 0.0F;
}
float alignment = (float) (stepX * goalX + stepY * goalY + stepZ * goalZ) / (float) (stepLen * goalLen);
return (1.0F - alignment) * 0.04F;
}
private float estimateCostToTarget(NPCPathPoint from, NPCPathPoint to) {
float dx = Math.abs(to.xCoord - from.xCoord);
float dy = Math.abs(to.yCoord - from.yCoord);
@@ -21,6 +21,10 @@ import noppes.npcs.entity.EntityNPCInterface;
import javax.annotation.Nullable;
public class PathNavigateFlying extends PathNavigate {
private static final long MIN_REPATH_INTERVAL_TICKS = 8L;
private static final long MAX_REPATH_INTERVAL_TICKS = 30L;
private static final int PATH_REUSE_TARGET_DELTA_SQ = 2;
private static final int FINAL_NODE_REUSE_DELTA_SQ = 3;
private EntityNPCInterface theEntity;
private World worldObj;
@@ -83,16 +87,21 @@ public class PathNavigateFlying extends PathNavigate {
}
public void updatePath() {
if (this.worldObj.getTotalWorldTime() - this.lastTimeUpdated > 20L) {
if (this.targetPos != null) {
this.currentPath = null;
this.currentPath = this.getPathToXYZ(this.targetPos.getX(), this.targetPos.getY(), this.targetPos.getZ());
this.lastTimeUpdated = this.worldObj.getTotalWorldTime();
this.tryUpdatePath = false;
}
} else {
this.tryUpdatePath = true;
if (this.targetPos == null) {
this.tryUpdatePath = false;
return;
}
long now = this.worldObj.getTotalWorldTime();
if (now - this.lastTimeUpdated < this.getAdaptiveRepathInterval()) {
this.tryUpdatePath = true;
return;
}
this.currentPath = null;
this.currentPath = this.getPathToXYZ(this.targetPos.getX(), this.targetPos.getY(), this.targetPos.getZ());
this.lastTimeUpdated = now;
this.tryUpdatePath = false;
}
public void setAvoidsWater(boolean p_75491_1_) {
@@ -156,7 +165,8 @@ public class PathNavigateFlying extends PathNavigate {
BlockPos pos = new BlockPos(x, y, z);
if (!this.canNavigate()) {
return null;
} else if (this.currentPath != null && !this.currentPath.isFinished() && pos.equals(this.targetPos)) {
} else if (this.canReuseCurrentPath(pos)) {
this.targetPos = pos;
return this.currentPath;
} else {
this.targetPos = pos;
@@ -180,7 +190,8 @@ public class PathNavigateFlying extends PathNavigate {
return null;
} else {
BlockPos blockpos = new BlockPos(entity);
if (this.currentPath != null && !this.currentPath.isFinished() && blockpos.equals(this.targetPos)) {
if (this.canReuseCurrentPath(blockpos)) {
this.targetPos = blockpos;
return this.currentPath;
} else {
this.targetPos = blockpos;
@@ -215,6 +226,8 @@ public class PathNavigateFlying extends PathNavigate {
this.removeSunnyPath();
}
this.smoothCurrentPath();
if (this.currentPath.getCurrentPathLength() == 0) {
return false;
} else {
@@ -242,6 +255,72 @@ public class PathNavigateFlying extends PathNavigate {
return !this.isInLiquid() || (this.canSwim && this.isInLiquid());
}
private long getAdaptiveRepathInterval() {
if (this.targetPos == null) {
return MAX_REPATH_INTERVAL_TICKS;
}
double distance = this.theEntity.getDistance(this.targetPos.getX() + 0.5D, this.targetPos.getY(), this.targetPos.getZ() + 0.5D);
return (long) MathHelper.clamp_double(distance * 0.6D, MIN_REPATH_INTERVAL_TICKS, MAX_REPATH_INTERVAL_TICKS);
}
private boolean canReuseCurrentPath(BlockPos newTarget) {
if (this.currentPath == null || this.currentPath.isFinished() || this.targetPos == null) {
return false;
}
if (this.getBlockDistanceSq(this.targetPos, newTarget) <= PATH_REUSE_TARGET_DELTA_SQ) {
return true;
}
NPCPathPoint finalPoint = this.currentPath.getFinalPathPoint();
return finalPoint != null && this.getPointDistanceSq(finalPoint, newTarget) <= FINAL_NODE_REUSE_DELTA_SQ;
}
private int getBlockDistanceSq(BlockPos a, BlockPos b) {
int dx = a.getX() - b.getX();
int dy = a.getY() - b.getY();
int dz = a.getZ() - b.getZ();
return dx * dx + dy * dy + dz * dz;
}
private int getPointDistanceSq(NPCPathPoint point, BlockPos blockPos) {
int dx = point.xCoord - blockPos.getX();
int dy = point.yCoord - blockPos.getY();
int dz = point.zCoord - blockPos.getZ();
return dx * dx + dy * dy + dz * dz;
}
private void smoothCurrentPath() {
if (this.currentPath == null) {
return;
}
int pathLength = this.currentPath.getCurrentPathLength();
if (pathLength < 3) {
return;
}
int width = MathHelper.ceiling_double_int(this.theEntity.width);
int height = MathHelper.ceiling_double_int(this.theEntity.height + 1.0F);
NPCPathPoint[] points = this.currentPath.points;
int writeIndex = 1;
int anchorIndex = 0;
for (int readIndex = 2; readIndex < pathLength; readIndex++) {
Vec3 anchor = this.currentPath.getVectorFromIndex(this.theEntity, anchorIndex);
Vec3 probe = this.currentPath.getVectorFromIndex(this.theEntity, readIndex);
if (!this.isDirectPathBetweenPoints(anchor, probe, width, height)) {
points[writeIndex++] = points[readIndex - 1];
anchorIndex = readIndex - 1;
}
}
points[writeIndex++] = points[pathLength - 1];
this.currentPath.setCurrentPathLength(writeIndex);
if (this.currentPath.getCurrentPathIndex() >= writeIndex) {
this.currentPath.setCurrentPathIndex(Math.max(0, writeIndex - 1));
}
}
public void onUpdateNavigation() {
++this.totalTicks;
@@ -91,11 +91,13 @@ public abstract class EntityNPCFlying extends EntityNPCInterface {
this.prevLimbSwingAmount = this.limbSwingAmount;
double distanceX = this.posX - this.prevPosX;
double distanceZ = this.posZ - this.prevPosZ;
float distance = MathHelper.sqrt_double(distanceX * distanceX + distanceZ * distanceZ) * 4.0F;
float distance = MathHelper.sqrt_double(distanceX * distanceX + distanceZ * distanceZ);
float swingScale = this.getNavigator().noPath() ? 0.35F : 0.9F;
distance *= swingScale;
if (distance > 1.0F) {
distance = 1.0F;
}
this.limbSwingAmount += (distance - this.limbSwingAmount) * 0.4F;
this.limbSwingAmount += (distance - this.limbSwingAmount) * 0.18F;
this.limbSwing += this.limbSwingAmount;
}