mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-12 20:07:32 +00:00
Ki Redirection for Barriers, Color Shifting, Better Logic Handling for Built in DBC Ki Abilities
This commit is contained in:
1 parent
40613fa56a
commit
d6eccdd556
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() {
|
||||
|
||||
Reference in new issue
Block a user