mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-12 21:17:32 +00:00
Prevent Movement Abilities through Barriers
This commit is contained in:
1 parent
948b708223
commit
0f5a191bcf
3 files changed
+114
-2
No files matched your search
@@ -2609,6 +2609,96 @@ public abstract class Ability implements IAbility, IAbilityAction {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a caster's movement in a given direction is blocked by a solid enemy barrier.
|
||||
* Tests a short segment from the caster's current position along the movement direction
|
||||
* against all active dome and panel barriers.
|
||||
*
|
||||
* @return true if a solid enemy barrier blocks the movement
|
||||
*/
|
||||
protected static boolean isMovementBlockedByBarrier(EntityLivingBase caster, double dirX, double dirZ, double speed) {
|
||||
if (caster.worldObj == null) return false;
|
||||
|
||||
double nextX = caster.posX + dirX * speed;
|
||||
double nextZ = caster.posZ + dirZ * speed;
|
||||
double eyeY = caster.posY + caster.getEyeHeight() * 0.5;
|
||||
|
||||
java.util.List<EntityEnergyBarrier> barriers = EntityEnergyBarrier.getActiveBarriers(caster.worldObj);
|
||||
for (EntityEnergyBarrier barrier : barriers) {
|
||||
if (barrier.isDead || barrier.isCharging()) continue;
|
||||
if (!barrier.getBarrierData().solid) continue;
|
||||
|
||||
// Skip barriers owned by or allied to the caster
|
||||
if (barrier.getOwnerEntityId() == caster.getEntityId()) continue;
|
||||
Entity barrierOwner = barrier.getOwnerEntity();
|
||||
if (barrierOwner instanceof EntityLivingBase) {
|
||||
if (AbilityTargetHelper.isAlly(caster, (EntityLivingBase) barrierOwner)) continue;
|
||||
}
|
||||
|
||||
if (barrier instanceof EntityEnergyDome) {
|
||||
EntityEnergyDome dome = (EntityEnergyDome) barrier;
|
||||
float radius = dome.getDomeRadius();
|
||||
|
||||
// Check if the movement segment crosses the dome boundary from outside
|
||||
double ocX = caster.posX - dome.posX;
|
||||
double ocY = eyeY - dome.posY;
|
||||
double ocZ = caster.posZ - dome.posZ;
|
||||
double originDistSq = ocX * ocX + ocY * ocY + ocZ * ocZ;
|
||||
if (originDistSq < (double) radius * radius) continue; // Inside dome, skip
|
||||
|
||||
double rdX = nextX - caster.posX;
|
||||
double rdZ = nextZ - caster.posZ;
|
||||
double a = rdX * rdX + rdZ * rdZ;
|
||||
double b = 2.0 * (ocX * rdX + ocZ * rdZ);
|
||||
double c = ocX * ocX + ocZ * ocZ - (double) radius * radius;
|
||||
double discriminant = b * b - 4.0 * a * c;
|
||||
if (discriminant < 0 || a < 1e-10) continue;
|
||||
double sqrtD = Math.sqrt(discriminant);
|
||||
double t1 = (-b - sqrtD) / (2.0 * a);
|
||||
if (t1 >= 0.0 && t1 <= 1.0) return true;
|
||||
} else if (barrier instanceof EntityEnergyPanel) {
|
||||
EntityEnergyPanel panel = (EntityEnergyPanel) barrier;
|
||||
float halfW = panel.getPanelData().getPanelWidth() * 0.5f;
|
||||
float halfH = panel.getPanelData().getPanelHeight() * 0.5f;
|
||||
float yawRad = (float) Math.toRadians(panel.getPanelYaw());
|
||||
double normalX = -Math.sin(yawRad);
|
||||
double normalZ = Math.cos(yawRad);
|
||||
double cos = Math.cos(yawRad);
|
||||
double sin = Math.sin(yawRad);
|
||||
|
||||
double relX = caster.posX - panel.posX;
|
||||
double relZ = caster.posZ - panel.posZ;
|
||||
double prevDist = relX * normalX + relZ * normalZ;
|
||||
|
||||
double relNX = nextX - panel.posX;
|
||||
double relNZ = nextZ - panel.posZ;
|
||||
double currDist = relNX * normalX + relNZ * normalZ;
|
||||
|
||||
// Check if segment crosses the panel plane
|
||||
if (prevDist * currDist > 0) continue;
|
||||
|
||||
double rayDirX = nextX - caster.posX;
|
||||
double rayDirZ = nextZ - caster.posZ;
|
||||
double denom = rayDirX * normalX + rayDirZ * normalZ;
|
||||
if (Math.abs(denom) < 1e-10) continue;
|
||||
|
||||
double t = -prevDist / denom;
|
||||
if (t < 0.0 || t > 1.0) continue;
|
||||
|
||||
double hitX = caster.posX + rayDirX * t;
|
||||
double hitZ = caster.posZ + rayDirZ * t;
|
||||
|
||||
double localRight = (hitX - panel.posX) * cos + (hitZ - panel.posZ) * sin;
|
||||
if (Math.abs(localRight) > halfW) continue;
|
||||
double localY = eyeY - panel.posY;
|
||||
if (Math.abs(localY) > halfH) continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// LINE-OF-SIGHT UTILITIES
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
@@ -202,13 +202,14 @@ public abstract class AbilityMovement extends Ability {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if movement direction is blocked by walls.
|
||||
* Check if movement direction is blocked by walls or solid barriers.
|
||||
*
|
||||
* @return true if blocked
|
||||
*/
|
||||
protected boolean checkBlocked(EntityLivingBase caster, float speed) {
|
||||
if (isPreview() || movementDirection == null) return false;
|
||||
return isMovementBlocked(caster, movementDirection.xCoord, movementDirection.zCoord, speed);
|
||||
return isMovementBlocked(caster, movementDirection.xCoord, movementDirection.zCoord, speed)
|
||||
|| isMovementBlockedByBarrier(caster, movementDirection.xCoord, movementDirection.zCoord, speed);
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
@@ -427,6 +427,27 @@ public class AbilitySlam extends Ability implements IAbilitySlam {
|
||||
((EntityNPCInterface) caster).getNavigator().clearPathEntity();
|
||||
}
|
||||
|
||||
// Check if slam trajectory is blocked by a solid barrier
|
||||
if (!isPreview() && !caster.worldObj.isRemote) {
|
||||
double moveX = caster.motionX;
|
||||
double moveZ = caster.motionZ;
|
||||
double hSpeed = Math.sqrt(moveX * moveX + moveZ * moveZ);
|
||||
if (hSpeed > 0.01) {
|
||||
double normX = moveX / hSpeed;
|
||||
double normZ = moveZ / hSpeed;
|
||||
if (isMovementBlockedByBarrier(caster, normX, normZ, hSpeed)) {
|
||||
caster.motionX = 0;
|
||||
caster.motionZ = 0;
|
||||
if (caster instanceof EntityPlayerMP) {
|
||||
((EntityPlayerMP) caster).playerNetServerHandler.sendPacket(
|
||||
new S12PacketEntityVelocity(caster));
|
||||
} else {
|
||||
caster.velocityChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Track if entity has risen above launch position.
|
||||
// This prevents premature landing detection for players, where
|
||||
// server-side caster.onGround remains true from stale C03 packets
|
||||
|
||||
Reference in new issue
Block a user