Added API classes to Energy Projectile

This commit is contained in:
Vidal committed 2026-02-03 17:20:36 -03:00
1 parent 7ee6c8aa53
commit bc4f82e55f
19 files changed
+506 -541

No files matched your search

+1 -1
Submodule src/api updated: 5fd3b7cb40...96b8d8a43c.
@@ -35,16 +35,24 @@ public class EnergyAnchorData implements IEnergyAnchorData {
this.anchorOffsetZ = anchorOffsetZ;
}
@Override
public AnchorPoint getAnchorPoint() {
return anchorPoint;
}
@Override
public void setAnchorPoint(AnchorPoint anchorPoint) {
this.anchorPoint = anchorPoint;
}
@Override
public int getAnchor() {
return anchorPoint.ordinal();
}
@Override
public void setAnchor(int anchor) {
this.anchorPoint = AnchorPoint.fromOrdinal(anchor);
}
@Override
public float getAnchorOffsetX() {
return anchorOffsetX;
@@ -0,0 +1,83 @@
package kamkeel.npcs.controllers.data.ability.data;
import net.minecraft.nbt.NBTTagCompound;
import noppes.npcs.api.ability.data.IEnergyHomingData;
/**
* Groups homing/movement properties for energy projectile abilities.
* Used by Orb, Disc, and Beam (not Laser or Sweeper).
*/
public class EnergyHomingData implements IEnergyHomingData {
public float speed = 0.5f;
public boolean homing = true;
public float homingStrength = 0.15f;
public float homingRange = 20.0f;
public EnergyHomingData() {}
public EnergyHomingData(float speed, boolean homing, float homingStrength, float homingRange) {
this.speed = speed;
this.homing = homing;
this.homingStrength = homingStrength;
this.homingRange = homingRange;
}
@Override
public float getSpeed() {
return speed;
}
@Override
public void setSpeed(float speed) {
this.speed = speed;
}
@Override
public boolean isHoming() {
return homing;
}
@Override
public void setHoming(boolean homing) {
this.homing = homing;
}
@Override
public float getHomingStrength() {
return homingStrength;
}
@Override
public void setHomingStrength(float homingStrength) {
this.homingStrength = homingStrength;
}
@Override
public float getHomingRange() {
return homingRange;
}
@Override
public void setHomingRange(float homingRange) {
this.homingRange = homingRange;
}
public void writeNBT(NBTTagCompound nbt) {
nbt.setFloat("speed", speed);
nbt.setBoolean("homing", homing);
nbt.setFloat("homingStrength", homingStrength);
nbt.setFloat("homingRange", homingRange);
}
public void readNBT(NBTTagCompound nbt) {
speed = nbt.hasKey("speed") ? nbt.getFloat("speed") : 0.5f;
homing = !nbt.hasKey("homing") || nbt.getBoolean("homing");
homingStrength = nbt.hasKey("homingStrength") ? nbt.getFloat("homingStrength") : 0.15f;
homingRange = nbt.hasKey("homingRange") ? nbt.getFloat("homingRange") : 20.0f;
}
public EnergyHomingData copy() {
return new EnergyHomingData(speed, homing, homingStrength, homingRange);
}
}
@@ -1,82 +1,48 @@
package kamkeel.npcs.controllers.data.ability.data;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.Vec3;
import noppes.npcs.api.ability.data.IEnergyTrajectoryData;
/**
* Groups homing/movement properties for energy projectile abilities.
* Used by Orb, Disc, and Beam (not Laser or Sweeper).
*/
import java.util.ArrayList;
import java.util.List;
public class EnergyTrajectoryData implements IEnergyTrajectoryData {
public float speed = 0.5f;
public boolean homing = true;
public float homingStrength = 0.15f;
public float homingRange = 20.0f;
public int currentPath = 0;
private List<Path> trajectory = new ArrayList<>();
public EnergyTrajectoryData() {}
public EnergyTrajectoryData(float speed, boolean homing, float homingStrength, float homingRange) {
this.speed = speed;
this.homing = homing;
this.homingStrength = homingStrength;
this.homingRange = homingRange;
public int getDelay(int path) {
if (path < 0 || path >= trajectory.size()) return -1;
return trajectory.get(path).delayTicks;
}
@Override
public float getSpeed() {
return speed;
public Vec3 getVec(int path) {
if (path < 0 || path >= trajectory.size()) return null;
return trajectory.get(path).coords;
}
@Override
public void setSpeed(float speed) {
this.speed = speed;
public double getX(int path) {
if (getVec(path) == null) return 0;
return getVec(path).xCoord;
}
@Override
public boolean isHoming() {
return homing;
public double getY(int path) {
if (getVec(path) == null) return 0;
return getVec(path).yCoord;
}
@Override
public void setHoming(boolean homing) {
this.homing = homing;
public double getZ(int path) {
if (getVec(path) == null) return 0;
return getVec(path).zCoord;
}
@Override
public float getHomingStrength() {
return homingStrength;
}
public static class Path {
public Vec3 coords;
public int delayTicks;
@Override
public void setHomingStrength(float homingStrength) {
this.homingStrength = homingStrength;
}
@Override
public float getHomingRange() {
return homingRange;
}
@Override
public void setHomingRange(float homingRange) {
this.homingRange = homingRange;
}
public void writeNBT(NBTTagCompound nbt) {
nbt.setFloat("speed", speed);
nbt.setBoolean("homing", homing);
nbt.setFloat("homingStrength", homingStrength);
nbt.setFloat("homingRange", homingRange);
}
public void readNBT(NBTTagCompound nbt) {
speed = nbt.hasKey("speed") ? nbt.getFloat("speed") : 0.5f;
homing = !nbt.hasKey("homing") || nbt.getBoolean("homing");
homingStrength = nbt.hasKey("homingStrength") ? nbt.getFloat("homingStrength") : 0.15f;
homingRange = nbt.hasKey("homingRange") ? nbt.getFloat("homingRange") : 20.0f;
}
public EnergyTrajectoryData copy() {
return new EnergyTrajectoryData(speed, homing, homingStrength, homingRange);
public Path(Vec3 coords, int delayTicks) {
this.coords = coords;
this.delayTicks = delayTicks;
}
}
}
@@ -39,7 +39,7 @@ public class AbilityBeam extends Ability implements IAbilityEnergyBeam {
// Data classes
private EnergyDisplayData colorData = new EnergyDisplayData(0xFFFFFF, 0x00AAFF, true, 0.4f, 0.5f, 6.0f);
private EnergyCombatData combatData = new EnergyCombatData(10.0f, 1.5f, 0.2f, false, 4.0f, 0.5f);
private EnergyTrajectoryData homingData = new EnergyTrajectoryData(0.4f, true, 0.1f, 15.0f);
private EnergyHomingData homingData = new EnergyHomingData(0.4f, true, 0.1f, 15.0f);
private EnergyLightningData lightningData = new EnergyLightningData();
private EnergyLifespanData lifespanData = new EnergyLifespanData(25.0f, 200);
private EnergyAnchorData anchorData = new EnergyAnchorData(AnchorPoint.RIGHT_HAND);
@@ -37,7 +37,7 @@ public class AbilityBeamDual extends Ability {
new EnergyDisplayData(0xFFFFFF, 0xFF0000, true, 0.4f, 0.5f, 6.0f),
};
private EnergyCombatData combatData = new EnergyCombatData(10.0f, 1.5f, 0.2f, false, 4.0f, 0.5f);
private EnergyTrajectoryData homingData = new EnergyTrajectoryData(0.4f, true, 0.1f, 15.0f);
private EnergyHomingData homingData = new EnergyHomingData(0.4f, true, 0.1f, 15.0f);
private EnergyLightningData[] lightningData = new EnergyLightningData[]{
new EnergyLightningData(), new EnergyLightningData()
};
@@ -125,8 +125,8 @@ public class AbilityBeamDual extends Ability {
colorData[1], combatData, homingData, lightningData[1], lifespanData,
lockMovement.locksActive());
beamEntity.setSiblingUUID(beamEntity2.getPersistentID());
beamEntity2.setSiblingUUID(beamEntity.getPersistentID());
beamEntity.setSiblingEntityId(beamEntity2.getEntityId());
beamEntity2.setSiblingEntityId(beamEntity.getEntityId());
beamEntity.setupCharging(anchorData[0], windUpTicks, offsetDist);
beamEntity2.setupCharging(anchorData[1], windUpTicks, offsetDist);
@@ -42,7 +42,7 @@ public class AbilityDisc extends Ability implements IAbilityDisc {
// Energy data classes
private EnergyDisplayData colorData = new EnergyDisplayData(0xFFFFFF, 0xFF8800, true, 0.4f, 0.5f, 5.0f);
private EnergyCombatData combatData = new EnergyCombatData(8.0f, 1.2f, 0.15f, false, 3.0f, 0.5f);
private EnergyTrajectoryData homingData = new EnergyTrajectoryData(0.6f, true, 0.12f, 18.0f);
private EnergyHomingData homingData = new EnergyHomingData(0.6f, true, 0.12f, 18.0f);
private EnergyLightningData lightningData = new EnergyLightningData();
private EnergyLifespanData lifespanData = new EnergyLifespanData(35.0f, 200);
private EnergyAnchorData anchorData = new EnergyAnchorData(AnchorPoint.RIGHT_HAND);
@@ -45,7 +45,7 @@ public class AbilityDiscDual extends Ability {
new EnergyDisplayData(0xFFFFFF, 0x8800FF, true, 0.4f, 0.5f, 5.0f)
};
private EnergyCombatData combatData = new EnergyCombatData(8.0f, 1.2f, 0.15f, false, 3.0f, 0.5f);
private EnergyTrajectoryData homingData = new EnergyTrajectoryData(0.6f, true, 0.12f, 18.0f);
private EnergyHomingData homingData = new EnergyHomingData(0.6f, true, 0.12f, 18.0f);
public final EnergyLightningData[] lightningData = new EnergyLightningData[]{
new EnergyLightningData(), new EnergyLightningData()
};
@@ -131,8 +131,8 @@ public class AbilityDiscDual extends Ability {
colorData[1], combatData, homingData, lightningData[1], lifespanData,
boomerang, boomerangDelay);
discEntity.setSiblingUUID(discEntity2.getPersistentID());
discEntity2.setSiblingUUID(discEntity.getPersistentID());
discEntity.setSiblingEntityId(discEntity2.getEntityId());
discEntity2.setSiblingEntityId(discEntity.getEntityId());
discEntity.setupCharging(anchorData[0], windUpTicks);
discEntity2.setupCharging(anchorData[1], windUpTicks);
@@ -271,6 +271,8 @@ public class AbilityLaserShot extends Ability implements IAbilityLaserShot {
AbilityFieldDefs.effectsListField("ability.effects", this::getEffects, this::setEffects),
// Visual tab
FieldDef.enumField("ability.anchorPoint", AnchorPoint.class, this::getAnchorPointEnum, this::setAnchorPointEnum)
.tab("ability.tab.visual"),
FieldDef.section("ability.section.colors").tab("ability.tab.visual"),
FieldDef.colorSubGui("ability.innerColor", this::getInnerColor, this::setInnerColor).tab("ability.tab.visual"),
FieldDef.boolField("ability.outerEnabled", this::isOuterColorEnabled, this::setOuterColorEnabled).tab("ability.tab.visual"),
@@ -38,7 +38,7 @@ public class AbilityOrb extends Ability implements IAbilityOrb {
// Data classes for energy properties
private final EnergyDisplayData colorData = new EnergyDisplayData();
private final EnergyCombatData combatData = new EnergyCombatData();
private final EnergyTrajectoryData homingData = new EnergyTrajectoryData();
private final EnergyHomingData homingData = new EnergyHomingData();
private final EnergyLightningData lightningData = new EnergyLightningData();
private final EnergyLifespanData lifespanData = new EnergyLifespanData();
private final EnergyAnchorData anchorData = new EnergyAnchorData(AnchorPoint.RIGHT_HAND);
@@ -39,7 +39,7 @@ public class AbilityOrbBarrage extends Ability {
// Data classes for energy properties
private final EnergyDisplayData colorData = new EnergyDisplayData();
private final EnergyCombatData combatData = new EnergyCombatData(4.0f, 0.0f, 0.0f, false, 1.5f, 0.5f);
private final EnergyTrajectoryData homingData = new EnergyTrajectoryData();
private final EnergyHomingData homingData = new EnergyHomingData();
private final EnergyLightningData lightningData = new EnergyLightningData();
private final EnergyLifespanData lifespanData = new EnergyLifespanData();
private final EnergyAnchorData[] anchorData = new EnergyAnchorData[]{
@@ -36,7 +36,7 @@ public class AbilityOrbDual extends Ability {
new EnergyDisplayData(), new EnergyDisplayData()
};
public final EnergyCombatData combatData = new EnergyCombatData();
public final EnergyTrajectoryData homingData = new EnergyTrajectoryData();
public final EnergyHomingData homingData = new EnergyHomingData();
public final EnergyLightningData[] lightningData = new EnergyLightningData[]{
new EnergyLightningData(), new EnergyLightningData()
};
@@ -118,8 +118,8 @@ public class AbilityOrbDual extends Ability {
spawnPos2.xCoord, spawnPos2.yCoord, spawnPos2.zCoord, orbSize,
colorData[1], combatData, homingData, lightningData[1], lifespanData);
orbEntity.setSiblingUUID(orbEntity2.getPersistentID());
orbEntity2.setSiblingUUID(orbEntity.getPersistentID());
orbEntity.setSiblingEntityId(orbEntity2.getEntityId());
orbEntity2.setSiblingEntityId(orbEntity.getEntityId());
orbEntity.setupCharging(anchorData[0], windUpTicks);
orbEntity2.setupCharging(anchorData[1], windUpTicks);
@@ -1,6 +1,5 @@
package kamkeel.npcs.entity;
import kamkeel.npcs.controllers.data.ability.AnchorPoint;
import kamkeel.npcs.controllers.data.ability.data.*;
import kamkeel.npcs.util.AnchorPointHelper;
import net.minecraft.entity.Entity;
@@ -15,7 +14,6 @@ import noppes.npcs.LogWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
* Beam projectile - head with trailing path that curves with homing.
@@ -28,13 +26,6 @@ import java.util.UUID;
*/
public class EntityAbilityBeam extends EntityAbilityProjectile {
// Beam-specific movement properties
private float speed = 0.5f;
private boolean homing = true;
private float homingStrength = 0.35f; // Increased from 0.15 for better tracking
private float homingRange = 20.0f;
private UUID siblingUUID = null;
// Beam shape properties
private float beamWidth = 0.3f;
private float headSize = 0.5f;
@@ -59,7 +50,6 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
private int chargeDuration = 40;
private int chargeTick = 0;
private float chargeOffsetDistance = 1.0f;
private EnergyAnchorData anchorData = new EnergyAnchorData(AnchorPoint.FRONT);
// Trail fading for non-anchored beams (comet effect)
private boolean fadeTrail = false;
@@ -112,20 +102,18 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
public EntityAbilityBeam(World world, EntityLivingBase owner, EntityLivingBase target,
double x, double y, double z,
float beamWidth, float headSize,
EnergyDisplayData color, EnergyCombatData combat,
EnergyTrajectoryData homing, EnergyLightningData lightning,
EnergyDisplayData display, EnergyCombatData combat,
EnergyHomingData homing, EnergyLightningData lightning,
EnergyLifespanData lifespan,
boolean anchoredMode) {
super(world);
// Initialize base properties via parent
initProjectile(owner, target, x, y, z, headSize, color, combat, lightning, lifespan);
initProjectile(owner, target, x, y, z, headSize, display, combat, lightning, lifespan);
// Beam-specific properties from homing data
this.speed = homing.speed;
this.homing = homing.homing;
this.homingStrength = homing.homingStrength;
this.homingRange = homing.homingRange;
this.homingData = homing;
this.beamWidth = beamWidth;
this.headSize = headSize;
@@ -155,16 +143,16 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
double dz = target.posZ - z;
double len = Math.sqrt(dx * dx + dy * dy + dz * dz);
if (len > 0) {
this.motionX = (dx / len) * speed;
this.motionY = (dy / len) * speed;
this.motionZ = (dz / len) * speed;
this.motionX = (dx / len) * getSpeed();
this.motionY = (dy / len) * getSpeed();
this.motionZ = (dz / len) * getSpeed();
}
} else {
float yaw = (float) Math.toRadians(owner.rotationYaw);
float pitch = (float) Math.toRadians(owner.rotationPitch);
this.motionX = -Math.sin(yaw) * Math.cos(pitch) * speed;
this.motionY = -Math.sin(pitch) * speed;
this.motionZ = Math.cos(yaw) * Math.cos(pitch) * speed;
this.motionX = -Math.sin(yaw) * Math.cos(pitch) * getSpeed();
this.motionY = -Math.sin(pitch) * getSpeed();
this.motionZ = Math.cos(yaw) * Math.cos(pitch) * getSpeed();
}
}
@@ -180,7 +168,7 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
this.motionZ = 0;
}
public void setupPreview(EntityLivingBase owner, float beamWidth, float headSize, EnergyDisplayData color, EnergyLightningData lightning, EnergyAnchorData anchor, int chargeDuration, float chargeOffsetDistance) {
public void setupPreview(EntityLivingBase owner, float beamWidth, float headSize, EnergyDisplayData display, EnergyLightningData lightning, EnergyAnchorData anchor, int chargeDuration, float chargeOffsetDistance) {
this.setPreviewMode(true);
this.setPreviewOwner(owner);
@@ -188,15 +176,8 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
this.beamWidth = beamWidth;
this.headSize = headSize;
this.size = headSize;
this.innerColor = color.innerColor;
this.outerColor = color.outerColor;
this.outerColorEnabled = color.outerColorEnabled;
this.outerColorWidth = color.outerColorWidth;
this.outerColorAlpha = color.outerColorAlpha;
this.rotationSpeed = color.rotationSpeed;
this.lightningEffect = lightning.lightningEffect;
this.lightningDensity = lightning.lightningDensity;
this.lightningRadius = lightning.lightningRadius;
this.displayData = display;
this.lightningData = lightning;
// Set charging state
this.setCharging(true);
@@ -252,15 +233,15 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
prevPosZ = posZ;
// Fire forward based on owner facing direction
Entity owner = getOwner();
Entity owner = getOwnerEntity();
if (owner != null) {
float yaw = (float) Math.toRadians(owner.rotationYaw);
float pitch = 0; // Fire horizontally
motionX = -Math.sin(yaw) * Math.cos(pitch) * speed;
motionY = -Math.sin(pitch) * speed;
motionZ = Math.cos(yaw) * Math.cos(pitch) * speed;
motionX = -Math.sin(yaw) * Math.cos(pitch) * getSpeed();
motionY = -Math.sin(pitch) * getSpeed();
motionZ = Math.cos(yaw) * Math.cos(pitch) * getSpeed();
} else {
motionX = speed;
motionX = getSpeed();
motionY = 0;
motionZ = 0;
}
@@ -303,7 +284,7 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
if (fadeTrail) trailPointAges.add(0);
// Calculate velocity toward target (head starts at origin = startX/Y/Z)
Entity owner = getOwner();
Entity owner = getOwnerEntity();
if (target != null) {
double dx = target.posX - startX;
@@ -311,16 +292,16 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
double dz = target.posZ - startZ;
double len = Math.sqrt(dx * dx + dy * dy + dz * dz);
if (len > 0) {
motionX = (dx / len) * speed;
motionY = (dy / len) * speed;
motionZ = (dz / len) * speed;
motionX = (dx / len) * getSpeed();
motionY = (dy / len) * getSpeed();
motionZ = (dz / len) * getSpeed();
}
} else if (owner != null) {
float yaw = (float) Math.toRadians(owner.rotationYaw);
float pitch = (float) Math.toRadians(owner.rotationPitch);
motionX = -Math.sin(yaw) * Math.cos(pitch) * speed;
motionY = -Math.sin(pitch) * speed;
motionZ = Math.cos(yaw) * Math.cos(pitch) * speed;
motionX = -Math.sin(yaw) * Math.cos(pitch) * getSpeed();
motionY = -Math.sin(pitch) * getSpeed();
motionZ = Math.cos(yaw) * Math.cos(pitch) * getSpeed();
}
if (DEBUG_LOGGING && !worldObj.isRemote) {
@@ -338,9 +319,9 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
headOffsetY * headOffsetY +
headOffsetZ * headOffsetZ
);
boolean exceeded = distFromOrigin >= maxDistance;
boolean exceeded = distFromOrigin >= getMaxDistance();
if (exceeded && !worldObj.isRemote && DEBUG_LOGGING) {
LogWriter.info("[Beam] DEAD: Max distance exceeded. dist=" + distFromOrigin + " max=" + maxDistance);
LogWriter.info("[Beam] DEAD: Max distance exceeded. dist=" + distFromOrigin + " max=" + getMaxDistance());
}
return exceeded;
}
@@ -394,7 +375,7 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
// Update origin if attached to owner
if (attachedToOwner) {
Entity owner = getOwner();
Entity owner = getOwnerEntity();
if (owner != null) {
startX = owner.posX;
startY = owner.posY + owner.getEyeHeight() * 0.7;
@@ -438,7 +419,7 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
private void updateCharging() {
chargeTick++;
Entity owner = getOwner();
Entity owner = getOwnerEntity();
if (owner == null || owner.isDead) {
setDead();
return;
@@ -529,7 +510,7 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
// Update origin if attached to owner
if (attachedToOwner) {
Entity owner = getOwner();
Entity owner = getOwnerEntity();
if (owner != null) {
startX = owner.posX;
startY = owner.posY + owner.getEyeHeight() * 0.7;
@@ -550,9 +531,9 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
}
private void updateHoming() {
if (!homing) return;
if (!isHoming()) return;
Entity target = getTarget();
Entity target = getTargetEntity();
if (target == null || !target.isEntityAlive()) return;
// Calculate world position of head
@@ -565,18 +546,18 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
double dz = target.posZ - headWorldZ;
double dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
if (dist <= homingRange && dist > 0) {
if (dist <= getHomingRange() && dist > 0) {
// Calculate effective homing strength - increases when closer to commit to target
float effectiveStrength = homingStrength;
if (dist < homingRange * 0.3) {
effectiveStrength = Math.min(1.0f, homingStrength * 2.5f);
} else if (dist < homingRange * 0.6) {
effectiveStrength = Math.min(0.8f, homingStrength * 1.5f);
float effectiveStrength = getHomingStrength();
if (dist < getHomingRange() * 0.3) {
effectiveStrength = Math.min(1.0f, getHomingStrength() * 2.5f);
} else if (dist < getHomingRange() * 0.6) {
effectiveStrength = Math.min(0.8f, getHomingStrength() * 1.5f);
}
double desiredVX = (dx / dist) * speed;
double desiredVY = (dy / dist) * speed;
double desiredVZ = (dz / dist) * speed;
double desiredVX = (dx / dist) * getSpeed();
double desiredVY = (dy / dist) * getSpeed();
double desiredVZ = (dz / dist) * getSpeed();
motionX += (desiredVX - motionX) * effectiveStrength;
motionY += (desiredVY - motionY) * effectiveStrength;
@@ -584,9 +565,9 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
double vLen = Math.sqrt(motionX * motionX + motionY * motionY + motionZ * motionZ);
if (vLen > 0) {
motionX = (motionX / vLen) * speed;
motionY = (motionY / vLen) * speed;
motionZ = (motionZ / vLen) * speed;
motionX = (motionX / vLen) * getSpeed();
motionY = (motionY / vLen) * getSpeed();
motionZ = (motionZ / vLen) * getSpeed();
}
}
}
@@ -604,7 +585,7 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
if (blockHit != null && blockHit.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) {
hasHit = true;
if (explosive) {
if (isExplosive()) {
posX = blockHit.hitVec.xCoord;
posY = blockHit.hitVec.yCoord;
posZ = blockHit.hitVec.zCoord;
@@ -632,7 +613,7 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
}
hasHit = true;
if (explosive) {
if (isExplosive()) {
posX = headX;
posY = headY;
posZ = headZ;
@@ -646,12 +627,6 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
}
}
@Override
protected boolean shouldIgnoreEntity(Entity entity) {
if (entity.getPersistentID().equals(siblingUUID)) return true;
return super.shouldIgnoreEntity(entity);
}
// ==================== GETTERS FOR RENDERER ====================
public float getBeamWidth() {
@@ -750,26 +725,10 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
return trailFadeTime;
}
public UUID getSiblingUUID() {
return siblingUUID;
}
public void setSiblingUUID(UUID siblingUUID) {
if (siblingUUID == null)
return;
if (this.siblingUUID == null)
this.siblingUUID = siblingUUID;
}
// ==================== NBT ====================
@Override
protected void readProjectileNBT(NBTTagCompound nbt) {
this.speed = nbt.hasKey("Speed") ? nbt.getFloat("Speed") : 0.5f;
this.homing = !nbt.hasKey("Homing") || nbt.getBoolean("Homing");
this.homingStrength = nbt.hasKey("HomingStrength") ? nbt.getFloat("HomingStrength") : 0.15f;
this.homingRange = nbt.hasKey("HomingRange") ? nbt.getFloat("HomingRange") : 20.0f;
this.beamWidth = nbt.hasKey("BeamWidth") ? nbt.getFloat("BeamWidth") : 0.3f;
this.headSize = nbt.hasKey("HeadSize") ? nbt.getFloat("HeadSize") : 0.5f;
this.headOffsetX = nbt.hasKey("HeadOffsetX") ? nbt.getDouble("HeadOffsetX") : 0;
@@ -790,7 +749,6 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
this.fadeTrail = nbt.hasKey("FadeTrail") && nbt.getBoolean("FadeTrail");
this.trailFadeTime = nbt.hasKey("TrailFadeTime") ? nbt.getInteger("TrailFadeTime") : 20;
this.anchorData.readNBT(nbt);
// Read trail points (relative to origin)
trailPoints.clear();
@@ -805,16 +763,10 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
));
}
}
this.siblingUUID = nbt.hasKey("SiblingUUID") ? UUID.fromString(nbt.getString("SiblingUUID")) : null;
}
@Override
protected void writeProjectileNBT(NBTTagCompound nbt) {
nbt.setFloat("Speed", speed);
nbt.setBoolean("Homing", homing);
nbt.setFloat("HomingStrength", homingStrength);
nbt.setFloat("HomingRange", homingRange);
nbt.setFloat("BeamWidth", beamWidth);
nbt.setFloat("HeadSize", headSize);
nbt.setDouble("HeadOffsetX", headOffsetX);
@@ -841,9 +793,5 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
trailList.appendTag(pointNbt);
}
nbt.setTag("Trail", trailList);
if (siblingUUID instanceof UUID) {
nbt.setString("SiblingUUID", siblingUUID.toString());
}
}
}
@@ -11,7 +11,6 @@ import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import java.util.List;
import java.util.UUID;
/**
* Disc projectile - flat spinning disc with optional boomerang behavior.
@@ -21,11 +20,7 @@ import java.util.UUID;
*/
public class EntityAbilityDisc extends EntityAbilityProjectile {
// Disc-specific movement properties
private float speed = 0.5f;
private boolean homing = true;
private float homingStrength = 0.35f; // Increased from 0.15 for better tracking
private float homingRange = 20.0f;
// Disc-specific movement propertie
// Boomerang properties
private boolean boomerang = false;
@@ -48,8 +43,6 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
// Data watcher index for charging state (synced to clients)
private static final int DW_CHARGING = 20;
private UUID siblingUUID = null;
public EntityAbilityDisc(World world) {
super(world);
}
@@ -88,20 +81,16 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
public EntityAbilityDisc(World world, EntityLivingBase owner, EntityLivingBase target,
double x, double y, double z,
float discRadius, float discThickness,
EnergyDisplayData color, EnergyCombatData combat,
EnergyTrajectoryData homing, EnergyLightningData lightning,
EnergyDisplayData display, EnergyCombatData combat,
EnergyHomingData homing, EnergyLightningData lightning,
EnergyLifespanData lifespan,
boolean boomerang, int boomerangDelay) {
super(world);
// Initialize base properties
initProjectile(owner, target, x, y, z, discRadius, color, combat, lightning, lifespan);
initProjectile(owner, target, x, y, z, discRadius, display, combat, lightning, lifespan);
// Disc-specific properties from homing data
this.speed = homing.speed;
this.homing = homing.homing;
this.homingStrength = homing.homingStrength;
this.homingRange = homing.homingRange;
this.homingData = homing;
this.boomerang = boomerang;
this.boomerangDelay = boomerangDelay;
@@ -116,16 +105,16 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
double dz = target.posZ - z;
double len = Math.sqrt(dx * dx + dy * dy + dz * dz);
if (len > 0) {
this.motionX = (dx / len) * speed;
this.motionY = (dy / len) * speed;
this.motionZ = (dz / len) * speed;
this.motionX = (dx / len) * getSpeed();
this.motionY = (dy / len) * getSpeed();
this.motionZ = (dz / len) * getSpeed();
}
} else {
float yaw = (float) Math.toRadians(owner.rotationYaw);
float pitch = (float) Math.toRadians(owner.rotationPitch);
this.motionX = -Math.sin(yaw) * Math.cos(pitch) * speed;
this.motionY = -Math.sin(pitch) * speed;
this.motionZ = Math.cos(yaw) * Math.cos(pitch) * speed;
this.motionX = -Math.sin(yaw) * Math.cos(pitch) * getSpeed();
this.motionY = -Math.sin(pitch) * getSpeed();
this.motionZ = Math.cos(yaw) * Math.cos(pitch) * getSpeed();
}
}
@@ -156,19 +145,13 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
* Follows anchor point and animations like in the real game.
* Can be fired when transitioning to active phase.
*/
public void setupPreview(EntityLivingBase owner, float discRadius, float discThickness, EnergyDisplayData color, EnergyLightningData lightning, EnergyAnchorData anchor, int chargeDuration) {
public void setupPreview(EntityLivingBase owner, float discRadius, float discThickness, EnergyDisplayData display, EnergyLightningData lightning, EnergyAnchorData anchor, int chargeDuration) {
this.setPreviewMode(true);
this.setPreviewOwner(owner);
// Set visual properties
this.innerColor = color.innerColor;
this.outerColor = color.outerColor;
this.outerColorEnabled = color.outerColorEnabled;
this.outerColorWidth = color.outerColorWidth;
this.rotationSpeed = color.rotationSpeed;
this.lightningEffect = lightning.lightningEffect;
this.lightningDensity = lightning.lightningDensity;
this.lightningRadius = lightning.lightningRadius;
this.displayData = display;
this.lightningData = lightning;
// Set charging state
this.setCharging(true);
@@ -218,15 +201,15 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
prevPosZ = posZ;
// Fire forward based on owner facing direction
Entity owner = getOwner();
Entity owner = getOwnerEntity();
if (owner != null) {
float yaw = (float) Math.toRadians(owner.rotationYaw);
float pitch = 0; // Fire horizontally
motionX = -Math.sin(yaw) * Math.cos(pitch) * speed;
motionY = -Math.sin(pitch) * speed;
motionZ = Math.cos(yaw) * Math.cos(pitch) * speed;
motionX = -Math.sin(yaw) * Math.cos(pitch) * getSpeed();
motionY = -Math.sin(pitch) * getSpeed();
motionZ = Math.cos(yaw) * Math.cos(pitch) * getSpeed();
} else {
motionX = speed;
motionX = getSpeed();
motionY = 0;
motionZ = 0;
}
@@ -247,7 +230,7 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
startZ = posZ;
// Calculate velocity toward target
Entity owner = getOwner();
Entity owner = getOwnerEntity();
if (target != null) {
double dx = target.posX - posX;
@@ -255,23 +238,23 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
double dz = target.posZ - posZ;
double len = Math.sqrt(dx * dx + dy * dy + dz * dz);
if (len > 0) {
motionX = (dx / len) * speed;
motionY = (dy / len) * speed;
motionZ = (dz / len) * speed;
motionX = (dx / len) * getSpeed();
motionY = (dy / len) * getSpeed();
motionZ = (dz / len) * getSpeed();
}
} else if (owner != null) {
float yaw = (float) Math.toRadians(owner.rotationYaw);
float pitch = (float) Math.toRadians(owner.rotationPitch);
motionX = -Math.sin(yaw) * Math.cos(pitch) * speed;
motionY = -Math.sin(pitch) * speed;
motionZ = Math.cos(yaw) * Math.cos(pitch) * speed;
motionX = -Math.sin(yaw) * Math.cos(pitch) * getSpeed();
motionY = -Math.sin(pitch) * getSpeed();
motionZ = Math.cos(yaw) * Math.cos(pitch) * getSpeed();
}
}
@Override
protected void updateRotation() {
// Disc spins ONLY on Y axis (flat spin like a saw blade)
this.rotationValY += rotationSpeed;
this.rotationValY += getRotationSpeed();
// No wobble - keep X and Z at 0 for stable flight
if (this.rotationValY > 360.0f) this.rotationValY -= 360.0f;
}
@@ -314,7 +297,7 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
if (this.isCollidedHorizontally || this.isCollidedVertically) {
if (!worldObj.isRemote) {
hasHit = true;
if (explosive) {
if (isExplosive()) {
doExplosion();
}
}
@@ -333,14 +316,14 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
if (boomerang) {
// If not returning yet, check if we should start returning
if (!returning && !hasHit) {
if (distTraveled >= maxDistance * 0.8 || ticksSinceMiss >= boomerangDelay) {
if (distTraveled >= getMaxDistance() * 0.8 || ticksSinceMiss >= boomerangDelay) {
returning = true;
}
}
// If returning, only die when close to owner
if (returning) {
Entity owner = getOwner();
Entity owner = getOwnerEntity();
if (owner != null) {
double distToOwner = Math.sqrt(
(posX - owner.posX) * (posX - owner.posX) +
@@ -358,7 +341,7 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
}
// Non-boomerang: standard max distance check
return distTraveled >= maxDistance;
return distTraveled >= getMaxDistance();
}
/**
@@ -372,9 +355,9 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
}
private void updateHoming() {
if (!homing) return;
if (!isHoming()) return;
Entity target = getTarget();
Entity target = getTargetEntity();
if (target == null || !target.isEntityAlive()) return;
double dx = target.posX - posX;
@@ -382,18 +365,18 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
double dz = target.posZ - posZ;
double dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
if (dist <= homingRange && dist > 0) {
if (dist <= getHomingRange() && dist > 0) {
// Calculate effective homing strength - increases when closer to commit to target
float effectiveStrength = homingStrength;
if (dist < homingRange * 0.3) {
effectiveStrength = Math.min(1.0f, homingStrength * 2.5f);
} else if (dist < homingRange * 0.6) {
effectiveStrength = Math.min(0.8f, homingStrength * 1.5f);
float effectiveStrength = getHomingStrength();
if (dist < getHomingRange() * 0.3) {
effectiveStrength = Math.min(1.0f, getHomingStrength() * 2.5f);
} else if (dist < getHomingRange() * 0.6) {
effectiveStrength = Math.min(0.8f, getHomingStrength() * 1.5f);
}
double desiredVX = (dx / dist) * speed;
double desiredVY = (dy / dist) * speed;
double desiredVZ = (dz / dist) * speed;
double desiredVX = (dx / dist) * getSpeed();
double desiredVY = (dy / dist) * getSpeed();
double desiredVZ = (dz / dist) * getSpeed();
motionX += (desiredVX - motionX) * effectiveStrength;
motionY += (desiredVY - motionY) * effectiveStrength;
@@ -401,15 +384,15 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
double vLen = Math.sqrt(motionX * motionX + motionY * motionY + motionZ * motionZ);
if (vLen > 0) {
motionX = (motionX / vLen) * speed;
motionY = (motionY / vLen) * speed;
motionZ = (motionZ / vLen) * speed;
motionX = (motionX / vLen) * getSpeed();
motionY = (motionY / vLen) * getSpeed();
motionZ = (motionZ / vLen) * getSpeed();
}
}
}
private void updateReturnToOwner() {
Entity owner = getOwner();
Entity owner = getOwnerEntity();
// If owner is gone (unloaded/dead), head back toward start position
double targetX, targetY, targetZ;
@@ -431,10 +414,10 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
if (dist > 0) {
// Stronger homing when returning
double returnStrength = Math.min(1.0, homingStrength * 2.5);
double desiredVX = (dx / dist) * speed;
double desiredVY = (dy / dist) * speed;
double desiredVZ = (dz / dist) * speed;
double returnStrength = Math.min(1.0, getHomingStrength() * 2.5);
double desiredVX = (dx / dist) * getSpeed();
double desiredVY = (dy / dist) * getSpeed();
double desiredVZ = (dz / dist) * getSpeed();
motionX += (desiredVX - motionX) * returnStrength;
motionY += (desiredVY - motionY) * returnStrength;
@@ -442,9 +425,9 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
double vLen = Math.sqrt(motionX * motionX + motionY * motionY + motionZ * motionZ);
if (vLen > 0) {
motionX = (motionX / vLen) * speed;
motionY = (motionY / vLen) * speed;
motionZ = (motionZ / vLen) * speed;
motionX = (motionX / vLen) * getSpeed();
motionY = (motionY / vLen) * getSpeed();
motionZ = (motionZ / vLen) * getSpeed();
}
}
}
@@ -457,7 +440,7 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
if (blockHit != null && blockHit.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) {
hasHit = true;
if (explosive) {
if (isExplosive()) {
posX = blockHit.hitVec.xCoord;
posY = blockHit.hitVec.yCoord;
posZ = blockHit.hitVec.zCoord;
@@ -484,7 +467,7 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
hasHit = true;
if (explosive) {
if (isExplosive()) {
doExplosion();
} else {
applyDamage(entity);
@@ -501,7 +484,7 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
private void updateCharging() {
chargeTick++;
Entity owner = getOwner();
Entity owner = getOwnerEntity();
if (owner == null || owner.isDead) {
setDead();
return;
@@ -543,14 +526,6 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
// ==================== GETTERS ====================
public float getSpeed() {
return speed;
}
public boolean isHoming() {
return homing;
}
public float getDiscRadius() {
return discRadius;
}
@@ -567,26 +542,10 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
return returning;
}
public UUID getSiblingUUID() {
return siblingUUID;
}
public void setSiblingUUID(UUID siblingUUID) {
if (siblingUUID == null)
return;
if (this.siblingUUID == null)
this.siblingUUID = siblingUUID;
}
// ==================== NBT ====================
@Override
protected void readProjectileNBT(NBTTagCompound nbt) {
this.speed = nbt.hasKey("Speed") ? nbt.getFloat("Speed") : 0.5f;
this.homing = !nbt.hasKey("Homing") || nbt.getBoolean("Homing");
this.homingStrength = nbt.hasKey("HomingStrength") ? nbt.getFloat("HomingStrength") : 0.15f;
this.homingRange = nbt.hasKey("HomingRange") ? nbt.getFloat("HomingRange") : 20.0f;
this.boomerang = nbt.hasKey("Boomerang") && nbt.getBoolean("Boomerang");
this.boomerangDelay = nbt.hasKey("BoomerangDelay") ? nbt.getInteger("BoomerangDelay") : 40;
this.discRadius = nbt.hasKey("DiscRadius") ? nbt.getFloat("DiscRadius") : 1.0f;
@@ -600,16 +559,10 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
this.chargeTick = nbt.hasKey("ChargeTick") ? nbt.getInteger("ChargeTick") : 0;
this.targetDiscRadius = nbt.hasKey("TargetDiscRadius") ? nbt.getFloat("TargetDiscRadius") : this.discRadius;
this.targetDiscThickness = nbt.hasKey("TargetDiscThickness") ? nbt.getFloat("TargetDiscThickness") : this.discThickness;
this.anchorData.readNBT(nbt);
this.siblingUUID = nbt.hasKey("SiblingUUID") ? UUID.fromString(nbt.getString("SiblingUUID")) : null;
}
@Override
protected void writeProjectileNBT(NBTTagCompound nbt) {
nbt.setFloat("Speed", speed);
nbt.setBoolean("Homing", homing);
nbt.setFloat("HomingStrength", homingStrength);
nbt.setFloat("HomingRange", homingRange);
nbt.setBoolean("Boomerang", boomerang);
nbt.setInteger("BoomerangDelay", boomerangDelay);
nbt.setFloat("DiscRadius", discRadius);
@@ -621,12 +574,5 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
nbt.setInteger("ChargeTick", chargeTick);
nbt.setFloat("TargetDiscRadius", targetDiscRadius);
nbt.setFloat("TargetDiscThickness", targetDiscThickness);
// Anchor data
this.anchorData.writeNBT(nbt);
if (siblingUUID instanceof UUID) {
nbt.setString("SiblingUUID", siblingUUID.toString());
}
}
}
@@ -90,14 +90,14 @@ public class EntityAbilityLaser extends EntityAbilityProjectile {
public EntityAbilityLaser(World world, EntityLivingBase owner, EntityLivingBase target,
double x, double y, double z,
float laserWidth,
EnergyDisplayData color, EnergyCombatData combat,
EnergyDisplayData display, EnergyCombatData combat,
EnergyLightningData lightning, EnergyLifespanData lifespan,
float expansionSpeed, int lingerTicks) {
super(world);
// Initialize base properties (laser doesn't rotate)
initProjectile(owner, target, x, y, z, laserWidth, color, combat, lightning, lifespan);
this.rotationSpeed = 0.0f;
initProjectile(owner, target, x, y, z, laserWidth, display, combat, lightning, lifespan);
this.displayData.rotationSpeed = 0.0f;
// Laser-specific properties
this.laserWidth = laserWidth;
@@ -171,8 +171,8 @@ public class EntityAbilityLaser extends EntityAbilityProjectile {
// Expand the laser
currentLength += expansionSpeed;
if (currentLength >= maxDistance) {
currentLength = maxDistance;
if (currentLength >= getMaxDistance()) {
currentLength = getMaxDistance();
fullyExtended = true;
}
@@ -206,7 +206,7 @@ public class EntityAbilityLaser extends EntityAbilityProjectile {
startZ = posZ;
// Calculate velocity toward target
Entity owner = getOwner();
Entity owner = getOwnerEntity();
if (target != null) {
double dx = target.posX - startX;
@@ -253,7 +253,7 @@ public class EntityAbilityLaser extends EntityAbilityProjectile {
endZ = blockHit.hitVec.zCoord;
fullyExtended = true;
if (explosive) {
if (isExplosive()) {
// Explode at hit point
double oldPosX = posX;
double oldPosY = posY;
@@ -275,7 +275,7 @@ public class EntityAbilityLaser extends EntityAbilityProjectile {
private void updateCharging() {
chargeTick++;
Entity owner = getOwner();
Entity owner = getOwnerEntity();
if (owner == null || owner.isDead) {
setDead();
return;
@@ -481,7 +481,7 @@ public class EntityAbilityLaser extends EntityAbilityProjectile {
* Setup this laser in preview mode for GUI display.
* Laser doesn't have charging state - spawns at active phase and fires immediately.
*/
public void setupPreview(EntityLivingBase owner, float laserWidth, EnergyDisplayData color,
public void setupPreview(EntityLivingBase owner, float laserWidth, EnergyDisplayData display,
EnergyLightningData lightning, float expansionSpeed, float maxDistance) {
this.setPreviewMode(true);
this.setPreviewOwner(owner);
@@ -489,15 +489,10 @@ public class EntityAbilityLaser extends EntityAbilityProjectile {
// Set visual properties
this.laserWidth = laserWidth;
this.size = laserWidth;
this.innerColor = color.innerColor;
this.outerColor = color.outerColor;
this.outerColorEnabled = color.outerColorEnabled;
this.outerColorWidth = color.outerColorWidth;
this.displayData = display;
this.expansionSpeed = expansionSpeed;
this.maxDistance = Math.min(maxDistance, 5.0f); // Limit for GUI preview
this.lightningEffect = lightning.lightningEffect;
this.lightningDensity = lightning.lightningDensity;
this.lightningRadius = lightning.lightningRadius;
this.lifespanData.maxDistance = Math.min(maxDistance, 5.0f); // Limit for GUI preview
this.lightningData = lightning;
// Position at chest height
double x = owner.posX;
@@ -1,6 +1,5 @@
package kamkeel.npcs.entity;
import kamkeel.npcs.controllers.data.ability.AnchorPoint;
import kamkeel.npcs.controllers.data.ability.data.*;
import kamkeel.npcs.util.AnchorPointHelper;
import net.minecraft.entity.Entity;
@@ -12,7 +11,6 @@ import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import java.util.List;
import java.util.UUID;
/**
* Orb projectile - spherical homing energy ball.
@@ -22,24 +20,15 @@ import java.util.UUID;
*/
public class EntityAbilityOrb extends EntityAbilityProjectile {
// Orb-specific movement properties
private float speed = 0.5f;
private boolean homing = true;
private float homingStrength = 0.35f; // Increased from 0.15 for better tracking
private float homingRange = 20.0f;
// Charging state (during windup)
private boolean charging = false;
private int chargeDuration = 40;
private int chargeTick = 0;
private EnergyAnchorData anchorData = new EnergyAnchorData(AnchorPoint.FRONT);
private float targetSize = 1.0f; // Full size to grow to during charging
// Data watcher index for charging state (synced to clients)
private static final int DW_CHARGING = 20;
private UUID siblingUUID = null;
public EntityAbilityOrb(World world) {
super(world);
}
@@ -77,19 +66,15 @@ public class EntityAbilityOrb extends EntityAbilityProjectile {
*/
public EntityAbilityOrb(World world, EntityLivingBase owner, EntityLivingBase target,
double x, double y, double z, float orbSize,
EnergyDisplayData color, EnergyCombatData combat,
EnergyTrajectoryData homing, EnergyLightningData lightning,
EnergyDisplayData display, EnergyCombatData combat,
EnergyHomingData homing, EnergyLightningData lightning,
EnergyLifespanData lifespan) {
super(world);
// Initialize base properties
initProjectile(owner, target, x, y, z, orbSize, color, combat, lightning, lifespan);
initProjectile(owner, target, x, y, z, orbSize, display, combat, lightning, lifespan);
// Orb-specific properties
this.speed = homing.speed;
this.homing = homing.homing;
this.homingStrength = homing.homingStrength;
this.homingRange = homing.homingRange;
this.homingData = homing;
// Calculate initial velocity toward target
if (target != null) {
@@ -136,20 +121,13 @@ public class EntityAbilityOrb extends EntityAbilityProjectile {
* Follows anchor point and animations like in the real game.
* Can be fired when transitioning to active phase.
*/
public void setupPreview(EntityLivingBase owner, float orbSize, EnergyDisplayData color, EnergyLightningData lightning, EnergyAnchorData anchor, int chargeDuration) {
public void setupPreview(EntityLivingBase owner, float orbSize, EnergyDisplayData display, EnergyLightningData lightning, EnergyAnchorData anchor, int chargeDuration) {
this.setPreviewMode(true);
this.setPreviewOwner(owner);
// Set visual properties
this.innerColor = color.innerColor;
this.outerColor = color.outerColor;
this.outerColorEnabled = color.outerColorEnabled;
this.outerColorWidth = color.outerColorWidth;
this.rotationSpeed = color.rotationSpeed;
this.lightningEffect = lightning.lightningEffect;
this.lightningDensity = lightning.lightningDensity;
this.lightningRadius = lightning.lightningRadius;
this.lightningFadeTime = lightning.lightningFadeTime;
this.displayData = display;
this.lightningData = lightning;
// Set charging state
this.setCharging(true);
@@ -198,16 +176,16 @@ public class EntityAbilityOrb extends EntityAbilityProjectile {
prevPosZ = posZ;
// Fire forward based on owner facing direction
Entity owner = getOwner();
Entity owner = getOwnerEntity();
if (owner != null) {
float yaw = (float) Math.toRadians(owner.rotationYaw);
float pitch = (float) Math.toRadians(0); // Fire horizontally
motionX = -Math.sin(yaw) * Math.cos(pitch) * speed;
motionY = -Math.sin(pitch) * speed;
motionZ = Math.cos(yaw) * Math.cos(pitch) * speed;
motionX = -Math.sin(yaw) * Math.cos(pitch) * getSpeed();
motionY = -Math.sin(pitch) * getSpeed();
motionZ = Math.cos(yaw) * Math.cos(pitch) * getSpeed();
} else {
// Default: fire forward (positive X in model space)
motionX = speed;
motionX = getSpeed();
motionY = 0;
motionZ = 0;
}
@@ -228,7 +206,7 @@ public class EntityAbilityOrb extends EntityAbilityProjectile {
startZ = posZ;
// Calculate velocity toward target
Entity owner = getOwner();
Entity owner = getOwnerEntity();
if (target != null) {
double dx = target.posX - posX;
@@ -236,16 +214,16 @@ public class EntityAbilityOrb extends EntityAbilityProjectile {
double dz = target.posZ - posZ;
double len = Math.sqrt(dx * dx + dy * dy + dz * dz);
if (len > 0) {
motionX = (dx / len) * speed;
motionY = (dy / len) * speed;
motionZ = (dz / len) * speed;
motionX = (dx / len) * getSpeed();
motionY = (dy / len) * getSpeed();
motionZ = (dz / len) * getSpeed();
}
} else if (owner != null) {
float yaw = (float) Math.toRadians(owner.rotationYaw);
float pitch = (float) Math.toRadians(owner.rotationPitch);
motionX = -Math.sin(yaw) * Math.cos(pitch) * speed;
motionY = -Math.sin(pitch) * speed;
motionZ = Math.cos(yaw) * Math.cos(pitch) * speed;
motionX = -Math.sin(yaw) * Math.cos(pitch) * getSpeed();
motionY = -Math.sin(pitch) * getSpeed();
motionZ = Math.cos(yaw) * Math.cos(pitch) * getSpeed();
}
}
@@ -277,7 +255,7 @@ public class EntityAbilityOrb extends EntityAbilityProjectile {
if (this.isCollidedHorizontally || this.isCollidedVertically) {
if (!worldObj.isRemote) {
hasHit = true;
if (explosive) {
if (isExplosive()) {
doExplosion();
}
}
@@ -296,9 +274,9 @@ public class EntityAbilityOrb extends EntityAbilityProjectile {
}
private void updateHoming() {
if (!homing) return;
if (!isHoming()) return;
Entity target = getTarget();
Entity target = getTargetEntity();
if (target == null || !target.isEntityAlive()) return;
double dx = target.posX - posX;
@@ -306,21 +284,21 @@ public class EntityAbilityOrb extends EntityAbilityProjectile {
double dz = target.posZ - posZ;
double dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
if (dist <= homingRange && dist > 0) {
if (dist <= getHomingRange() && dist > 0) {
// Calculate effective homing strength - increases when closer to commit to target
// This prevents orbiting behavior at close range
float effectiveStrength = homingStrength;
if (dist < homingRange * 0.3) {
float effectiveStrength = getHomingStrength();
if (dist < getHomingRange() * 0.3) {
// Within 30% of homing range, dramatically increase strength to commit
effectiveStrength = Math.min(1.0f, homingStrength * 2.5f);
} else if (dist < homingRange * 0.6) {
effectiveStrength = Math.min(1.0f, getHomingStrength() * 2.5f);
} else if (dist < getHomingRange() * 0.6) {
// Within 60% of homing range, moderately increase strength
effectiveStrength = Math.min(0.8f, homingStrength * 1.5f);
effectiveStrength = Math.min(0.8f, getHomingStrength() * 1.5f);
}
double desiredVX = (dx / dist) * speed;
double desiredVY = (dy / dist) * speed;
double desiredVZ = (dz / dist) * speed;
double desiredVX = (dx / dist) * getSpeed();
double desiredVY = (dy / dist) * getSpeed();
double desiredVZ = (dz / dist) * getSpeed();
motionX += (desiredVX - motionX) * effectiveStrength;
motionY += (desiredVY - motionY) * effectiveStrength;
@@ -329,9 +307,9 @@ public class EntityAbilityOrb extends EntityAbilityProjectile {
// Normalize to maintain speed
double vLen = Math.sqrt(motionX * motionX + motionY * motionY + motionZ * motionZ);
if (vLen > 0) {
motionX = (motionX / vLen) * speed;
motionY = (motionY / vLen) * speed;
motionZ = (motionZ / vLen) * speed;
motionX = (motionX / vLen) * getSpeed();
motionY = (motionY / vLen) * getSpeed();
motionZ = (motionZ / vLen) * getSpeed();
}
}
}
@@ -344,7 +322,7 @@ public class EntityAbilityOrb extends EntityAbilityProjectile {
if (blockHit != null && blockHit.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) {
hasHit = true;
if (explosive) {
if (isExplosive()) {
posX = blockHit.hitVec.xCoord;
posY = blockHit.hitVec.yCoord;
posZ = blockHit.hitVec.zCoord;
@@ -369,7 +347,7 @@ public class EntityAbilityOrb extends EntityAbilityProjectile {
hasHit = true;
if (explosive) {
if (isExplosive()) {
doExplosion();
} else {
applyDamage(entity);
@@ -386,7 +364,7 @@ public class EntityAbilityOrb extends EntityAbilityProjectile {
private void updateCharging() {
chargeTick++;
Entity owner = getOwner();
Entity owner = getOwnerEntity();
if (owner == null || owner.isDead) {
setDead();
return;
@@ -423,47 +401,15 @@ public class EntityAbilityOrb extends EntityAbilityProjectile {
// ==================== GETTERS ====================
public float getSpeed() {
return speed;
}
public boolean isHoming() {
return homing;
}
public float getHomingStrength() {
return homingStrength;
}
public float getHomingRange() {
return homingRange;
}
// Legacy getter for renderer compatibility
public float getOrbSize() {
return size;
}
public UUID getSiblingUUID() {
return siblingUUID;
}
public void setSiblingUUID(UUID siblingUUID) {
if (siblingUUID == null)
return;
if (this.siblingUUID == null)
this.siblingUUID = siblingUUID;
}
// ==================== NBT ====================
@Override
protected void readProjectileNBT(NBTTagCompound nbt) {
this.speed = nbt.hasKey("OrbSpeed") ? nbt.getFloat("OrbSpeed") : 0.5f;
this.homing = !nbt.hasKey("Homing") || nbt.getBoolean("Homing");
this.homingStrength = nbt.hasKey("HomingStrength") ? nbt.getFloat("HomingStrength") : 0.15f;
this.homingRange = nbt.hasKey("HomingRange") ? nbt.getFloat("HomingRange") : 20.0f;
// Charging state
boolean isCharging = nbt.hasKey("Charging") && nbt.getBoolean("Charging");
this.charging = isCharging;
@@ -471,27 +417,15 @@ public class EntityAbilityOrb extends EntityAbilityProjectile {
this.chargeDuration = nbt.hasKey("ChargeDuration") ? nbt.getInteger("ChargeDuration") : 40;
this.chargeTick = nbt.hasKey("ChargeTick") ? nbt.getInteger("ChargeTick") : 0;
this.targetSize = nbt.hasKey("TargetSize") ? nbt.getFloat("TargetSize") : this.size;
// Anchor data
this.anchorData.readNBT(nbt);
this.siblingUUID = nbt.hasKey("SiblingUUID") ? UUID.fromString(nbt.getString("SiblingUUID")) : null;
}
@Override
protected void writeProjectileNBT(NBTTagCompound nbt) {
nbt.setFloat("OrbSpeed", speed);
nbt.setBoolean("Homing", homing);
nbt.setFloat("HomingStrength", homingStrength);
nbt.setFloat("HomingRange", homingRange);
// Charging state
nbt.setBoolean("Charging", isCharging());
nbt.setInteger("ChargeDuration", chargeDuration);
nbt.setInteger("ChargeTick", chargeTick);
anchorData.writeNBT(nbt);
nbt.setFloat("TargetSize", targetSize);
if (siblingUUID instanceof UUID) {
nbt.setString("SiblingUUID", siblingUUID.toString());
}
}
}
@@ -5,10 +5,8 @@ import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import io.netty.buffer.ByteBuf;
import kamkeel.npcs.controllers.data.ability.AbilityEffect;
import kamkeel.npcs.controllers.data.ability.data.EnergyDisplayData;
import kamkeel.npcs.controllers.data.ability.data.EnergyCombatData;
import kamkeel.npcs.controllers.data.ability.data.EnergyLifespanData;
import kamkeel.npcs.controllers.data.ability.data.EnergyLightningData;
import kamkeel.npcs.controllers.data.ability.AnchorPoint;
import kamkeel.npcs.controllers.data.ability.data.*;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
@@ -18,7 +16,10 @@ import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.DamageSource;
import net.minecraft.world.World;
import noppes.npcs.NpcDamageSource;
import noppes.npcs.api.entity.IEnergyProjectile;
import noppes.npcs.api.entity.IEntity;
import noppes.npcs.entity.EntityNPCInterface;
import noppes.npcs.scripted.NpcAPI;
import java.util.ArrayList;
import java.util.List;
@@ -29,49 +30,42 @@ import java.util.List;
*
* Design inspired by LouisXIV's energy attack system.
*/
public abstract class EntityAbilityProjectile extends Entity implements IEntityAdditionalSpawnData {
public abstract class EntityAbilityProjectile extends Entity implements IEnergyProjectile, IEntityAdditionalSpawnData {
// ==================== VISUAL PROPERTIES ====================
protected float size = 1.0f;
protected int innerColor = 0xFFFFFF;
protected int outerColor = 0x8888FF;
protected boolean outerColorEnabled = true;
protected float outerColorWidth = 0.4f; // Additive offset from inner size
protected float outerColorAlpha = 0.5f;
protected float rotationSpeed = 4.0f;
// ==================== COMBAT PROPERTIES ====================
protected float damage = 7.0f;
protected float knockback = 1.0f;
protected float knockbackUp = 0.1f;
protected EnergyCombatData combatData = new EnergyCombatData();
// ==================== EFFECT PROPERTIES ====================
protected List<AbilityEffect> effects = new ArrayList<>();
// ==================== EXPLOSION PROPERTIES ====================
protected boolean explosive = false;
protected float explosionRadius = 3.0f;
protected float explosionDamageFalloff = 0.5f;
// ==================== LIGHTNING EFFECT PROPERTIES ====================
protected boolean lightningEffect = false;
protected float lightningDensity = 0.15f; // Bolts spawned per tick (0.15 = ~15% chance per frame)
protected float lightningRadius = 0.5f; // Max distance lightning can arc from center
protected int lightningFadeTime = 6; // Ticks before lightning fades out
protected EnergyLightningData lightningData = new EnergyLightningData();
// Client-side lightning state (not saved to NBT)
@cpw.mods.fml.relauncher.SideOnly(cpw.mods.fml.relauncher.Side.CLIENT)
public transient Object lightningState; // Actually AttachedLightningRenderer.LightningState
// ==================== LIFESPAN ====================
protected float maxDistance = 30.0f;
protected int maxLifetime = 200;
// ==================== DISPLAY PROPERTIES ====================
protected EnergyDisplayData displayData = new EnergyDisplayData();
// ==================== ANCHOR PROPERTIES ====================
protected EnergyAnchorData anchorData = new EnergyAnchorData(AnchorPoint.FRONT);
// ==================== LIFESPAN PROPERTIES ====================
protected EnergyLifespanData lifespanData = new EnergyLifespanData();
protected long deathWorldTime = -1; // World time when entity should die (-1 = not set)
// ==================== HOMING PROPERTIES ====================
protected EnergyHomingData homingData = new EnergyHomingData();
// ==================== TRACKING ====================
protected double startX, startY, startZ;
protected int ownerEntityId = -1;
protected int targetEntityId = -1;
protected int siblingEntityId = -1;
// ==================== STATE ====================
protected boolean hasHit = false;
@@ -102,9 +96,9 @@ public abstract class EntityAbilityProjectile extends Entity implements IEntityA
/**
* Initialize common properties using data classes. Call from subclass constructors.
*/
protected void initProjectile(EntityLivingBase owner, EntityLivingBase target,
protected void initProjectile(EntityLivingBase owner, EntityLivingBase target, EntityAbilityProjectile sibling,
double x, double y, double z, float size,
EnergyDisplayData color, EnergyCombatData combat,
EnergyDisplayData display, EnergyCombatData combat,
EnergyLightningData lightning, EnergyLifespanData lifespan) {
this.setPosition(x, y, z);
this.startX = x;
@@ -113,42 +107,29 @@ public abstract class EntityAbilityProjectile extends Entity implements IEntityA
this.ownerEntityId = owner.getEntityId();
this.targetEntityId = target != null ? target.getEntityId() : -1;
this.siblingEntityId = sibling != null ? sibling.getEntityId() : -1;
// Visual
this.size = size;
this.innerColor = color.innerColor;
this.outerColor = color.outerColor;
this.outerColorEnabled = color.outerColorEnabled;
this.outerColorWidth = color.outerColorWidth;
this.outerColorAlpha = color.outerColorAlpha;
this.rotationSpeed = color.rotationSpeed;
// Combat
this.damage = combat.damage;
this.knockback = combat.knockback;
this.knockbackUp = combat.knockbackUp;
// Explosion
this.explosive = combat.explosive;
this.explosionRadius = combat.explosionRadius;
this.explosionDamageFalloff = combat.explosionDamageFalloff;
// Lifespan
this.maxDistance = lifespan.maxDistance;
this.maxLifetime = lifespan.maxLifetime;
// deathWorldTime will be set on first tick when world is available
// Lightning
this.lightningEffect = lightning.lightningEffect;
this.lightningDensity = lightning.lightningDensity;
this.lightningRadius = lightning.lightningRadius;
this.lightningFadeTime = lightning.lightningFadeTime;
this.displayData = display;
this.combatData = combat;
this.lifespanData = lifespan; // deathWorldTime will be set on first tick when world is available
this.lightningData = lightning;
// Initialize render size
this.renderCurrentSize = size;
this.prevRenderSize = size;
}
// Initialize projectile without a sibling
protected void initProjectile(EntityLivingBase owner, EntityLivingBase target,
double x, double y, double z, float size,
EnergyDisplayData display, EnergyCombatData combat,
EnergyLightningData lightning, EnergyLifespanData lifespan) {
initProjectile(owner, target, null, x, y, z, size, display, combat, lightning, lifespan);
}
@Override
protected void entityInit() {
// No DataWatcher needed - using IEntityAdditionalSpawnData with NBT
@@ -206,7 +187,7 @@ public abstract class EntityAbilityProjectile extends Entity implements IEntityA
// Set death time on first tick if not already set (handles chunk load/unload)
if (deathWorldTime < 0 && worldObj != null) {
deathWorldTime = worldObj.getTotalWorldTime() + maxLifetime;
deathWorldTime = worldObj.getTotalWorldTime() + getMaxLifetime();
}
// Check lifespan using world time (survives chunk unload/reload)
@@ -235,9 +216,9 @@ public abstract class EntityAbilityProjectile extends Entity implements IEntityA
* Update rotation values. Override for custom rotation behavior.
*/
protected void updateRotation() {
this.rotationValX += rotationSpeed * 0.7f;
this.rotationValY += rotationSpeed;
this.rotationValZ += rotationSpeed * 0.5f;
this.rotationValX += getRotationSpeed() * 0.7f;
this.rotationValY += getRotationSpeed();
this.rotationValZ += getRotationSpeed() * 0.5f;
if (this.rotationValX > 360.0f) this.rotationValX -= 360.0f;
if (this.rotationValY > 360.0f) this.rotationValY -= 360.0f;
@@ -254,7 +235,7 @@ public abstract class EntityAbilityProjectile extends Entity implements IEntityA
(posY - startY) * (posY - startY) +
(posZ - startZ) * (posZ - startZ)
);
return distTraveled >= maxDistance;
return distTraveled >= getMaxDistance();
}
/**
@@ -326,12 +307,12 @@ public abstract class EntityAbilityProjectile extends Entity implements IEntityA
protected void applyDamage(EntityLivingBase target) {
if (previewMode) return; // Skip damage in preview mode
applyDamage(target, this.damage, this.knockback);
applyDamage(target, this.getDamage(), this.getKnockback());
}
protected void applyDamage(EntityLivingBase target, float dmg, float kb) {
if (previewMode) return; // Skip damage in preview mode
Entity owner = getOwner();
Entity owner = getOwnerEntity();
if (owner instanceof EntityNPCInterface) {
target.attackEntityFrom(new NpcDamageSource("npc_ability", (EntityNPCInterface) owner), dmg);
@@ -350,7 +331,7 @@ public abstract class EntityAbilityProjectile extends Entity implements IEntityA
if (len > 0) {
double kbX = (dx / len) * kb * 0.5;
double kbZ = (dz / len) * kb * 0.5;
double kbY = knockbackUp > 0 ? knockbackUp : 0.1;
double kbY = getKnockbackUp() > 0 ? getKnockbackUp() : 0.1;
target.addVelocity(kbX, kbY, kbZ);
target.velocityChanged = true;
}
@@ -376,11 +357,11 @@ public abstract class EntityAbilityProjectile extends Entity implements IEntityA
if (previewMode) return; // Skip explosion in preview mode
worldObj.playSoundEffect(posX, posY, posZ, "random.explode", 1.0f, 1.0f);
Entity owner = getOwner();
Entity owner = getOwnerEntity();
AxisAlignedBB explosionBox = AxisAlignedBB.getBoundingBox(
posX - explosionRadius, posY - explosionRadius, posZ - explosionRadius,
posX + explosionRadius, posY + explosionRadius, posZ + explosionRadius
posX - getExplosionRadius(), posY - getExplosionRadius(), posZ - getExplosionRadius(),
posX + getExplosionRadius(), posY + getExplosionRadius(), posZ + getExplosionRadius()
);
@SuppressWarnings("unchecked")
@@ -395,20 +376,16 @@ public abstract class EntityAbilityProjectile extends Entity implements IEntityA
Math.pow(target.posZ - posZ, 2)
);
if (dist <= explosionRadius) {
float falloff = 1.0f - (float) (dist / explosionRadius) * explosionDamageFalloff;
applyDamage(target, damage * falloff, knockback * falloff);
if (dist <= getExplosionRadius()) {
float falloff = 1.0f - (float) (dist / getExplosionRadius()) * getExplosionDamageFalloff();
applyDamage(target, getDamage() * falloff, getKnockback() * falloff);
}
}
}
// ==================== ENTITY HELPERS ====================
public int getOwnerEntityId() {
return ownerEntityId;
}
protected Entity getOwner() {
public Entity getOwnerEntity() {
// In preview mode, use direct reference (no world lookup)
if (previewMode && previewOwner != null) {
return previewOwner;
@@ -417,6 +394,18 @@ public abstract class EntityAbilityProjectile extends Entity implements IEntityA
return worldObj.getEntityByID(ownerEntityId);
}
@Override
public int getOwnerEntityId() {
return ownerEntityId;
}
@Override
public IEntity getOwner() {
if (previewMode) return null;
if (getOwnerEntity() == null) return null;
return NpcAPI.Instance().getIEntity(getOwnerEntity());
}
/**
* Set the preview owner for GUI preview mode.
* This allows anchor point calculations without world entity lookup.
@@ -425,16 +414,45 @@ public abstract class EntityAbilityProjectile extends Entity implements IEntityA
this.previewOwner = owner;
}
protected Entity getTarget() {
@Override
public int getTargetEntityId() {
return targetEntityId;
}
public Entity getTargetEntity() {
if (targetEntityId == -1) return null;
return worldObj.getEntityByID(targetEntityId);
}
@Override
public IEntity getTarget() {
if (getTargetEntity() == null) return null;
return NpcAPI.Instance().getIEntity(getTargetEntity());
}
@Override
public int getSiblingEntityId() {
return siblingEntityId;
}
@Override
public void setSiblingEntityId(int siblingEntityId) {
if (!(worldObj.getEntityByID(siblingEntityId) instanceof EntityAbilityProjectile)) return;
this.siblingEntityId = siblingEntityId;
}
@Override
public IEnergyProjectile getSibling() {
if (siblingEntityId == -1) return null;
return (EntityAbilityProjectile) worldObj.getEntityByID(siblingEntityId);
}
/**
* Check if an entity should be ignored for collision.
*/
protected boolean shouldIgnoreEntity(Entity entity) {
Entity owner = getOwner();
Entity owner = getOwnerEntity();
if (entity == owner) return true;
if (owner instanceof EntityNPCInterface && entity instanceof EntityNPCInterface) {
@@ -442,73 +460,166 @@ public abstract class EntityAbilityProjectile extends Entity implements IEntityA
EntityNPCInterface targetNpc = (EntityNPCInterface) entity;
if (ownerNpc.faction.id == targetNpc.faction.id) return true;
}
if (entity.getEntityId() == getSiblingEntityId())
return true;
return false;
}
// ==================== VISUAL GETTERS ====================
@Override
public float getSize() {
return size;
}
@Override
public int getInnerColor() {
return innerColor;
return displayData.getInnerColor();
}
@Override
public int getOuterColor() {
return outerColor;
return displayData.getOuterColor();
}
@Override
public boolean isOuterColorEnabled() {
return outerColorEnabled;
return displayData.isOuterColorEnabled();
}
@Override
public float getOuterColorWidth() {
return outerColorWidth;
return displayData.getOuterColorWidth();
}
@Override
public float getOuterColorAlpha() {
return outerColorAlpha;
return displayData.getOuterColorAlpha();
}
@Override
public float getRotationSpeed() {
return rotationSpeed;
return displayData.getRotationSpeed();
}
// ==================== ROTATION GETTERS ====================
@Override
public float getInterpolatedRotationX(float partialTicks) {
return this.prevRotationValX + (this.rotationValX - this.prevRotationValX) * partialTicks;
}
@Override
public float getInterpolatedRotationY(float partialTicks) {
return this.prevRotationValY + (this.rotationValY - this.prevRotationValY) * partialTicks;
}
@Override
public float getInterpolatedRotationZ(float partialTicks) {
return this.prevRotationValZ + (this.rotationValZ - this.prevRotationValZ) * partialTicks;
}
@Override
public float getInterpolatedSize(float partialTicks) {
return this.prevRenderSize + (this.renderCurrentSize - this.prevRenderSize) * partialTicks;
}
// ==================== LIGHTNING GETTERS ====================
@Override
public boolean hasLightningEffect() {
return lightningEffect;
return lightningData.isLightningEffect();
}
@Override
public float getLightningDensity() {
return lightningDensity;
return lightningData.getLightningDensity();
}
@Override
public float getLightningRadius() {
return lightningRadius;
return lightningData.getLightningRadius();
}
@Override
public int getLightningFadeTime() {
return lightningFadeTime;
return lightningData.getLightningFadeTime();
}
// ==================== LIFESPAN GETTERS ====================
@Override
public float getMaxDistance() { return lifespanData.getMaxDistance(); }
@Override
public int getMaxLifetime() { return lifespanData.getMaxLifetime(); }
// ==================== COMBAT GETTERS ====================
@Override
public float getDamage() { return combatData.getDamage(); }
@Override
public float getKnockback() { return combatData.knockback; }
@Override
public float getKnockbackUp() { return combatData.knockbackUp; }
@Override
public boolean isExplosive() { return combatData.isExplosive(); }
@Override
public float getExplosionRadius() { return combatData.explosionRadius; }
@Override
public float getExplosionDamageFalloff() { return combatData.explosionDamageFalloff; }
// ==================== VISUAL GETTERS ====================
@Override
public float getSpeed() { return homingData.getSpeed(); }
@Override
public boolean isHoming() { return homingData.isHoming(); }
@Override
public float getHomingStrength() { return homingData.getHomingStrength(); }
@Override
public float getHomingRange() { return homingData.getHomingRange(); }
// ==================== ANCHOR GETTERS ====================
public AnchorPoint getAnchorPoint() { return anchorData.getAnchorPoint(); }
@Override
public int getAnchor() { return anchorData.getAnchor(); }
@Override
public float getAnchorOffsetX() { return anchorData.getAnchorOffsetX(); }
@Override
public float getAnchorOffsetY() { return anchorData.getAnchorOffsetY(); }
@Override
public float getAnchorOffsetZ() { return anchorData.getAnchorOffsetZ(); }
// ==================== MOVEMENT GETTERS ====================
@Override public double getStartX() { return startX; }
@Override public double getStartY() { return startY; }
@Override public double getStartZ() { return startZ; }
@Override public double getMotionX() { return motionX; }
@Override public double getMotionY() { return motionY; }
@Override public double getMotionZ() { return motionZ; }
// ==================== BRIGHTNESS ====================
@Override
@@ -541,20 +652,6 @@ public abstract class EntityAbilityProjectile extends Entity implements IEntityA
*/
protected void readBaseNBT(NBTTagCompound nbt) {
this.size = nbt.getFloat("Size");
this.innerColor = nbt.getInteger("InnerColor");
this.outerColor = nbt.getInteger("OuterColor");
this.outerColorEnabled = !nbt.hasKey("OuterColorEnabled") || nbt.getBoolean("OuterColorEnabled");
this.outerColorAlpha = nbt.hasKey("OuterColorAlpha") ? nbt.getFloat("OuterColorAlpha") : 0.5f;
this.outerColorWidth = nbt.hasKey("OuterColorWidth") ? nbt.getFloat("OuterColorWidth") : 0.4f;
this.rotationSpeed = nbt.hasKey("RotationSpeed") ? nbt.getFloat("RotationSpeed") : 4.0f;
this.damage = nbt.getFloat("Damage");
this.knockback = nbt.getFloat("Knockback");
this.knockbackUp = nbt.getFloat("KnockbackUp");
this.explosive = nbt.getBoolean("Explosive");
this.explosionRadius = nbt.getFloat("ExplosionRadius");
this.explosionDamageFalloff = nbt.getFloat("ExplosionDamageFalloff");
// Read effects list
this.effects.clear();
@@ -565,8 +662,6 @@ public abstract class EntityAbilityProjectile extends Entity implements IEntityA
}
}
this.maxDistance = nbt.getFloat("MaxDistance");
this.maxLifetime = nbt.getInteger("MaxLifetime");
this.deathWorldTime = nbt.hasKey("DeathWorldTime") ? nbt.getLong("DeathWorldTime") : -1;
this.startX = nbt.getDouble("StartX");
@@ -575,21 +670,23 @@ public abstract class EntityAbilityProjectile extends Entity implements IEntityA
this.ownerEntityId = nbt.getInteger("OwnerId");
this.targetEntityId = nbt.getInteger("TargetId");
this.siblingEntityId = nbt.getInteger("SiblingId");
this.motionX = nbt.getDouble("MotionX");
this.motionY = nbt.getDouble("MotionY");
this.motionZ = nbt.getDouble("MotionZ");
// Lightning
this.lightningEffect = nbt.getBoolean("LightningEffect");
this.lightningDensity = nbt.hasKey("LightningDensity") ? nbt.getFloat("LightningDensity") : 0.15f;
this.lightningRadius = nbt.hasKey("LightningRadius") ? nbt.getFloat("LightningRadius") : 0.5f;
this.lightningFadeTime = nbt.hasKey("LightningFadeTime") ? nbt.getInteger("LightningFadeTime") : 6;
if (this.worldObj != null && this.worldObj.isRemote) {
this.renderCurrentSize = this.size;
this.prevRenderSize = this.size;
}
anchorData.readNBT(nbt);
combatData.readNBT(nbt);
displayData.readNBT(nbt);
homingData.readNBT(nbt);
lifespanData.readNBT(nbt);
lightningData.readNBT(nbt);
}
/**
@@ -597,20 +694,6 @@ public abstract class EntityAbilityProjectile extends Entity implements IEntityA
*/
protected void writeBaseNBT(NBTTagCompound nbt) {
nbt.setFloat("Size", size);
nbt.setInteger("InnerColor", innerColor);
nbt.setInteger("OuterColor", outerColor);
nbt.setBoolean("OuterColorEnabled", outerColorEnabled);
nbt.setFloat("OuterColorWidth", outerColorWidth);
nbt.setFloat("OuterColorAlpha", outerColorAlpha);
nbt.setFloat("RotationSpeed", rotationSpeed);
nbt.setFloat("Damage", damage);
nbt.setFloat("Knockback", knockback);
nbt.setFloat("KnockbackUp", knockbackUp);
nbt.setBoolean("Explosive", explosive);
nbt.setFloat("ExplosionRadius", explosionRadius);
nbt.setFloat("ExplosionDamageFalloff", explosionDamageFalloff);
// Write effects list
if (!effects.isEmpty()) {
@@ -621,9 +704,7 @@ public abstract class EntityAbilityProjectile extends Entity implements IEntityA
nbt.setTag("Effects", effectsList);
}
nbt.setFloat("MaxDistance", maxDistance);
nbt.setLong("DeathWorldTime", deathWorldTime);
nbt.setInteger("MaxLifetime", maxLifetime);
nbt.setDouble("StartX", startX);
nbt.setDouble("StartY", startY);
@@ -631,16 +712,18 @@ public abstract class EntityAbilityProjectile extends Entity implements IEntityA
nbt.setInteger("OwnerId", ownerEntityId);
nbt.setInteger("TargetId", targetEntityId);
nbt.setInteger("SiblingId", targetEntityId);
nbt.setDouble("MotionX", motionX);
nbt.setDouble("MotionY", motionY);
nbt.setDouble("MotionZ", motionZ);
// Lightning
nbt.setBoolean("LightningEffect", lightningEffect);
nbt.setFloat("LightningDensity", lightningDensity);
nbt.setFloat("LightningRadius", lightningRadius);
nbt.setInteger("LightningFadeTime", lightningFadeTime);
anchorData.writeNBT(nbt);
combatData.writeNBT(nbt);
displayData.writeNBT(nbt);
homingData.writeNBT(nbt);
lifespanData.writeNBT(nbt);
lightningData.writeNBT(nbt);
}
/**
@@ -74,7 +74,7 @@ public class EntityAbilitySweeper extends Entity implements IEntityAdditionalSpa
public EntityAbilitySweeper(World world, EntityLivingBase owner, EntityLivingBase target,
float beamLength, float beamWidth, float beamHeight,
EnergyDisplayData colorData,
EnergyDisplayData displayData,
float sweepSpeed, int numberOfRotations,
float damage, int damageInterval, boolean piercing,
boolean lockOnTarget) {
@@ -85,10 +85,10 @@ public class EntityAbilitySweeper extends Entity implements IEntityAdditionalSpa
this.beamLength = beamLength;
this.beamWidth = beamWidth;
this.beamHeight = beamHeight;
this.innerColor = colorData.innerColor;
this.outerColor = colorData.outerColor;
this.outerColorEnabled = colorData.outerColorEnabled;
this.outerColorWidth = colorData.outerColorWidth;
this.innerColor = displayData.innerColor;
this.outerColor = displayData.outerColor;
this.outerColorEnabled = displayData.outerColorEnabled;
this.outerColorWidth = displayData.outerColorWidth;
this.sweepSpeed = sweepSpeed;
this.numberOfRotations = numberOfRotations;
this.damage = damage;
@@ -109,7 +109,7 @@ public class ItemStaff extends ItemNpcInterface implements IProjectileCallback {
EnergyDisplayData colorData = new EnergyDisplayData(getOrbColor(stack, false), getOrbColor(stack, true));
EnergyLightningData lightning = new EnergyLightningData();
EnergyLifespanData lifespan = new EnergyLifespanData(100, 72000);
EnergyTrajectoryData homing = new EnergyTrajectoryData();
EnergyHomingData homing = new EnergyHomingData();
homing.speed = 0.5f;
homing.homingStrength = 0.35f;