Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
Kam committed 2026-03-01 04:44:51 -05:00
commit e7fcc3a71a
4 files changed
+201 -108

No files matched your search

@@ -171,6 +171,32 @@ public abstract class EntityEnergyBarrier extends EntityEnergyAbility {
double prevPosX, double prevPosY, double prevPosZ,
int ownerEntityId);
/**
* Compute the outward surface normal at a given hit point on this barrier.
* Used by external systems (e.g., mixin-based projectile reflection) that cannot
* access barrier-subtype internals.
*
* @param hitX, hitY, hitZ Position near the barrier surface
* @param velX, velY, velZ Incoming velocity (used as fallback direction)
* @return double[3] normalized surface normal pointing outward from the barrier
*/
public abstract double[] getSurfaceNormal(double hitX, double hitY, double hitZ,
double velX, double velY, double velZ);
/**
* Compute a position just outside the barrier surface, along the outward normal
* from the given position. Used to snap paused/reflected projectiles outside
* the collision zone.
*
* @param px, py, pz Current projectile position
* @param velX, velY, velZ Current velocity (used as fallback for direction)
* @param bias Distance outside the surface to snap to
* @return double[3] position outside the barrier surface
*/
public abstract double[] getOutsideSurfacePoint(double px, double py, double pz,
double velX, double velY, double velZ,
float bias);
// ==================== GENERIC PROJECTILE HIT ====================
/**
@@ -209,6 +235,71 @@ public abstract class EntityEnergyBarrier extends EntityEnergyAbility {
return true;
}
/**
* Apply damage from a generic (non-CNPC+) projectile and return full hit context.
* Same logic as onProjectileHitResolved() but for raw Entity + typeId.
*
* @param projectileEntity The entity that hit the barrier (for event context)
* @param damage Base damage to apply
* @param typeId Type identifier for damage multiplier lookup (e.g., "dbc.ki_attack")
* @return Full ProjectileHitOutcome with result, reflect data, remaining damage
*/
public ProjectileHitOutcome onGenericProjectileHitResolved(Entity projectileEntity, float damage, String typeId) {
float multiplier = barrierData.getMultiplier(typeId);
float finalDamage = damage * multiplier;
if (!worldObj.isRemote) {
float eventDamage = EventHooks.onEnergyBarrierHit(this, ownerEntityId, null, finalDamage);
if (eventDamage < 0) {
return new ProjectileHitOutcome(
ProjectileHitResult.PASS,
currentHealth, currentHealth,
0.0f, 0.0f,
barrierData.reflect, barrierData.reflectStrengthPct,
barrierData.useHealth
);
}
finalDamage = eventDamage;
}
triggerHitFlash();
float healthBefore = currentHealth;
if (!barrierData.useHealth) {
return new ProjectileHitOutcome(
ProjectileHitResult.BLOCKED,
healthBefore, healthBefore,
0.0f, 0.0f,
barrierData.reflect, barrierData.reflectStrengthPct,
false
);
}
currentHealth -= finalDamage;
syncHealthPercent();
if (currentHealth <= 0) {
float remaining = Math.max(0.0f, finalDamage - healthBefore);
onBarrierDestroyed();
this.setDead();
return new ProjectileHitOutcome(
ProjectileHitResult.BROKEN,
healthBefore, 0.0f,
finalDamage, remaining,
barrierData.reflect, barrierData.reflectStrengthPct,
true
);
}
return new ProjectileHitOutcome(
ProjectileHitResult.BLOCKED,
healthBefore, currentHealth,
finalDamage, 0.0f,
barrierData.reflect, barrierData.reflectStrengthPct,
true
);
}
// ==================== PROJECTILE HIT ====================
/**
@@ -213,6 +213,56 @@ public class EntityEnergyDome extends EntityEnergyBarrier {
return isIncomingRay(posX, posY, posZ, prevPosX, prevPosY, prevPosZ, ownerEntityId);
}
@Override
public double[] getSurfaceNormal(double hitX, double hitY, double hitZ,
double velX, double velY, double velZ) {
double nx = hitX - this.posX;
double ny = hitY - this.posY;
double nz = hitZ - this.posZ;
double lenSq = nx * nx + ny * ny + nz * nz;
if (lenSq > 1.0e-8) {
double invLen = 1.0 / Math.sqrt(lenSq);
return new double[]{nx * invLen, ny * invLen, nz * invLen};
}
// Fallback: use negative velocity direction
double vLenSq = velX * velX + velY * velY + velZ * velZ;
if (vLenSq > 1.0e-8) {
double invVLen = 1.0 / Math.sqrt(vLenSq);
return new double[]{-velX * invVLen, -velY * invVLen, -velZ * invVLen};
}
return new double[]{0.0, 1.0, 0.0};
}
@Override
public double[] getOutsideSurfacePoint(double px, double py, double pz,
double velX, double velY, double velZ,
float bias) {
double nx = px - this.posX;
double ny = py - this.posY;
double nz = pz - this.posZ;
double len = Math.sqrt(nx * nx + ny * ny + nz * nz);
if (len < 1.0e-5) {
double vLen = Math.sqrt(velX * velX + velY * velY + velZ * velZ);
if (vLen > 1.0e-5) {
nx = -velX / vLen;
ny = -velY / vLen;
nz = -velZ / vLen;
} else {
nx = 0.0; ny = 1.0; nz = 0.0;
}
len = 1.0;
}
double invLen = 1.0 / len;
double target = domeRadius + bias;
return new double[]{
this.posX + nx * invLen * target,
this.posY + ny * invLen * target,
this.posZ + nz * invLen * target
};
}
@Override
public float getMaxExtent() {
return domeRadius;
@@ -362,6 +362,63 @@ public class EntityEnergyPanel extends EntityEnergyBarrier {
return isIncomingRay(posX, posY, posZ, prevPosX, prevPosY, prevPosZ, ownerEntityId);
}
@Override
public double[] getSurfaceNormal(double hitX, double hitY, double hitZ,
double velX, double velY, double velZ) {
float yawRad = (float) Math.toRadians(panelYaw);
double nx = -Math.sin(yawRad);
double nz = Math.cos(yawRad);
// Determine which side the hit is on
double relX = hitX - this.posX;
double relZ = hitZ - this.posZ;
double side = relX * nx + relZ * nz;
if (Math.abs(side) < 1.0e-5) {
// Near the plane: use incoming velocity to determine side
side = velX * nx + velZ * nz;
}
if (side < 0.0) {
nx = -nx;
nz = -nz;
}
return new double[]{nx, 0.0, nz};
}
@Override
public double[] getOutsideSurfacePoint(double px, double py, double pz,
double velX, double velY, double velZ,
float bias) {
float yawRad = (float) Math.toRadians(panelYaw);
double normalX = -Math.sin(yawRad);
double normalZ = Math.cos(yawRad);
double relX = px - this.posX;
double relZ = pz - this.posZ;
double signedDist = relX * normalX + relZ * normalZ;
double halfThickness = 0.25;
double side;
if (Math.abs(signedDist) > 0.035) {
side = signedDist >= 0 ? 1.0 : -1.0;
} else {
double vDot = velX * normalX + velZ * normalZ;
if (Math.abs(vDot) > 1.0e-5) {
side = vDot < 0 ? 1.0 : -1.0;
} else {
side = signedDist >= 0 ? 1.0 : -1.0;
}
}
double targetDist = side * (halfThickness + bias);
double delta = targetDist - signedDist;
return new double[]{
px + normalX * delta,
py,
pz + normalZ * delta
};
}
@Override
public float getMaxExtent() {
return Math.max(panelData.panelWidth, panelData.panelHeight) * 0.5f + 1.0f;
@@ -681,47 +681,7 @@ public abstract class EntityEnergyProjectile extends EntityEnergyAbility {
}
protected double[] getBarrierImpactNormal(EntityEnergyBarrier barrier, double velocityX, double velocityY, double velocityZ) {
if (barrier instanceof EntityEnergyDome) {
EntityEnergyDome dome = (EntityEnergyDome) barrier;
return normalizeVector(posX - dome.posX, posY - dome.posY, posZ - dome.posZ, velocityX, velocityY, velocityZ);
}
if (barrier instanceof EntityEnergyPanel) {
EntityEnergyPanel panel = (EntityEnergyPanel) barrier;
float yawRad = (float) Math.toRadians(panel.getPanelYaw());
double nx = -Math.sin(yawRad);
double nz = Math.cos(yawRad);
double relX = posX - panel.posX;
double relZ = posZ - panel.posZ;
double signedDist = relX * nx + relZ * nz;
double side = signedDist;
if (Math.abs(side) < 1.0e-5) {
side = velocityX * nx + velocityZ * nz;
}
if (side < 0.0) {
nx = -nx;
nz = -nz;
}
return normalizeVector(nx, 0.0, nz, velocityX, velocityY, velocityZ);
}
return normalizeVector(posX - barrier.posX, posY - barrier.posY, posZ - barrier.posZ, velocityX, velocityY, velocityZ);
}
protected double[] normalizeVector(double x, double y, double z, double fallbackX, double fallbackY, double fallbackZ) {
double lenSq = x * x + y * y + z * z;
if (lenSq > 1.0e-8) {
double invLen = 1.0 / Math.sqrt(lenSq);
return new double[]{x * invLen, y * invLen, z * invLen};
}
double fallbackLenSq = fallbackX * fallbackX + fallbackY * fallbackY + fallbackZ * fallbackZ;
if (fallbackLenSq > 1.0e-8) {
double invFallbackLen = 1.0 / Math.sqrt(fallbackLenSq);
return new double[]{-fallbackX * invFallbackLen, -fallbackY * invFallbackLen, -fallbackZ * invFallbackLen};
}
return new double[]{0.0, 1.0, 0.0};
return barrier.getSurfaceNormal(posX, posY, posZ, velocityX, velocityY, velocityZ);
}
protected void beginBarrierImpactPause(boolean destroyOnResume, EntityEnergyBarrier barrier) {
@@ -752,73 +712,8 @@ public abstract class EntityEnergyProjectile extends EntityEnergyAbility {
if (barrier == null) return;
float bias = getBarrierPauseOutsideDistance();
if (barrier instanceof EntityEnergyDome) {
EntityEnergyDome dome = (EntityEnergyDome) barrier;
double nx = posX - dome.posX;
double ny = posY - dome.posY;
double nz = posZ - dome.posZ;
double len = Math.sqrt(nx * nx + ny * ny + nz * nz);
if (len < 1.0e-5) {
double vLen = Math.sqrt(motionX * motionX + motionY * motionY + motionZ * motionZ);
if (vLen > 1.0e-5) {
nx = -motionX / vLen;
ny = -motionY / vLen;
nz = -motionZ / vLen;
len = 1.0;
} else {
nx = 0.0;
ny = 1.0;
nz = 0.0;
len = 1.0;
}
}
double invLen = 1.0 / len;
double target = dome.getDomeRadius() + bias;
setPosition(
dome.posX + nx * invLen * target,
dome.posY + ny * invLen * target,
dome.posZ + nz * invLen * target
);
return;
}
if (barrier instanceof EntityEnergyPanel) {
EntityEnergyPanel panel = (EntityEnergyPanel) barrier;
float yawRad = (float) Math.toRadians(panel.getPanelYaw());
double normalX = -Math.sin(yawRad);
double normalZ = Math.cos(yawRad);
double relX = posX - panel.posX;
double relZ = posZ - panel.posZ;
double signedDist = relX * normalX + relZ * normalZ;
double halfThickness = 0.25;
double side;
if (Math.abs(signedDist) > 0.035) {
side = signedDist >= 0 ? 1.0 : -1.0;
} else {
// Near the plane, use incoming direction so we don't snap through and "fling".
double vDot = motionX * normalX + motionZ * normalZ;
if (Math.abs(vDot) > 1.0e-5) {
side = vDot < 0 ? 1.0 : -1.0;
} else {
side = signedDist >= 0 ? 1.0 : -1.0;
}
}
double targetDist = side * (halfThickness + bias);
double delta = targetDist - signedDist;
setPosition(posX + normalX * delta, posY, posZ + normalZ * delta);
return;
}
double vLen = Math.sqrt(motionX * motionX + motionY * motionY + motionZ * motionZ);
if (vLen > 1.0e-5) {
setPosition(
posX - (motionX / vLen) * bias,
posY - (motionY / vLen) * bias,
posZ - (motionZ / vLen) * bias
);
}
double[] point = barrier.getOutsideSurfacePoint(posX, posY, posZ, motionX, motionY, motionZ, bias);
setPosition(point[0], point[1], point[2]);
}
protected boolean tickBarrierImpactPause() {