Added EnergyAnchorData, a wrapper for anchor points which also stores 3 flat offset values

This commit is contained in:
Vidal committed 2026-01-29 20:34:10 -03:00
1 parent babe58dc34
commit da33baf971
8 files changed
+175 -109

No files matched your search

@@ -0,0 +1,54 @@
package kamkeel.npcs.controllers.data.ability.data;
import kamkeel.npcs.controllers.data.ability.AnchorPoint;
import net.minecraft.nbt.NBTTagCompound;
public class EnergyAnchorData {
public AnchorPoint anchorPoint = AnchorPoint.FRONT;
public float anchorOffsetX = 0;
public float anchorOffsetY = 0;
public float anchorOffsetZ = 0;
public EnergyAnchorData() {
}
public EnergyAnchorData(AnchorPoint anchorPoint) {
this.anchorPoint = anchorPoint;
}
public EnergyAnchorData(AnchorPoint anchorPoint, float anchorOffsetX, float anchorOffsetY, float anchorOffsetZ) {
this.anchorPoint = anchorPoint;
this.anchorOffsetX = anchorOffsetX;
this.anchorOffsetY = anchorOffsetY;
this.anchorOffsetZ = anchorOffsetZ;
}
public EnergyAnchorData(int anchorPoint) {
this.anchorPoint = AnchorPoint.fromId(anchorPoint);
}
public EnergyAnchorData(int anchorPoint, float anchorOffsetX, float anchorOffsetY, float anchorOffsetZ) {
this.anchorPoint = AnchorPoint.fromId(anchorPoint);
this.anchorOffsetX = anchorOffsetX;
this.anchorOffsetY = anchorOffsetY;
this.anchorOffsetZ = anchorOffsetZ;
}
public void writeNBT(NBTTagCompound nbt) {
nbt.setInteger("anchorPoint", anchorPoint.getId());
nbt.setFloat("anchorOffsetX", anchorOffsetX);
nbt.setFloat("anchorOffsetY", anchorOffsetY);
nbt.setFloat("anchorOffsetZ", anchorOffsetZ);
}
public void readNBT(NBTTagCompound nbt) {
this.anchorPoint = nbt.hasKey("anchorPoint") ? AnchorPoint.fromId(nbt.getInteger("anchorPoint")) : AnchorPoint.FRONT;
this.anchorOffsetX = nbt.hasKey("anchorOffsetX") ? nbt.getFloat("anchorOffsetX") : 0;
this.anchorOffsetY = nbt.hasKey("anchorOffsetY") ? nbt.getFloat("anchorOffsetY") : 0;
this.anchorOffsetZ = nbt.hasKey("anchorOffsetZ") ? nbt.getFloat("anchorOffsetZ") : 0;
}
public EnergyAnchorData copy() {
return new EnergyAnchorData(anchorPoint, anchorOffsetX, anchorOffsetY, anchorOffsetZ);
}
}
@@ -6,11 +6,7 @@ import kamkeel.npcs.controllers.data.ability.Ability;
import kamkeel.npcs.controllers.data.ability.AnchorPoint;
import kamkeel.npcs.controllers.data.ability.LockMovementType;
import kamkeel.npcs.controllers.data.ability.TargetingMode;
import kamkeel.npcs.controllers.data.ability.data.EnergyColorData;
import kamkeel.npcs.controllers.data.ability.data.EnergyCombatData;
import kamkeel.npcs.controllers.data.ability.data.EnergyHomingData;
import kamkeel.npcs.controllers.data.ability.data.EnergyLifespanData;
import kamkeel.npcs.controllers.data.ability.data.EnergyLightningData;
import kamkeel.npcs.controllers.data.ability.data.*;
import kamkeel.npcs.controllers.data.telegraph.Telegraph;
import kamkeel.npcs.controllers.data.telegraph.TelegraphInstance;
import kamkeel.npcs.controllers.data.telegraph.TelegraphType;
@@ -19,7 +15,6 @@ import kamkeel.npcs.util.AnchorPointHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.DamageSource;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
@@ -42,15 +37,13 @@ public class AbilityDisc extends Ability implements IAbilityDisc {
private boolean boomerang = false;
private int boomerangDelay = 40;
// Anchor point for charging position
private AnchorPoint anchorPoint = AnchorPoint.RIGHT_HAND;
// Energy data classes
private EnergyColorData colorData = new EnergyColorData(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 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);
// Transient state for disc entity (used during windup charging)
private transient EntityAbilityDisc discEntity = null;
@@ -115,14 +108,14 @@ public class AbilityDisc extends Ability implements IAbilityDisc {
// Spawn disc in charging mode on first tick of windup
if (tick == 1) {
// Create disc in charging mode - follows NPC based on anchor point during windup
Vec3 spawnPos = AnchorPointHelper.calculateAnchorPosition(npc, anchorPoint);
Vec3 spawnPos = AnchorPointHelper.calculateAnchorPosition(npc, anchorData);
discEntity = new EntityAbilityDisc(
world, npc, target,
spawnPos.xCoord, spawnPos.yCoord, spawnPos.zCoord,
discRadius, discThickness,
colorData, combatData, homingData, lightningData, lifespanData,
boomerang, boomerangDelay);
discEntity.setupCharging(anchorPoint, windUpTicks);
discEntity.setupCharging(anchorData, windUpTicks);
discEntity.setEffects(this.effects);
world.spawnEntityInWorld(discEntity);
@@ -184,7 +177,7 @@ public class AbilityDisc extends Ability implements IAbilityDisc {
nbt.setFloat("discThickness", discThickness);
nbt.setBoolean("boomerang", boomerang);
nbt.setInteger("boomerangDelay", boomerangDelay);
nbt.setInteger("anchorPoint", anchorPoint.getId());
anchorData.writeNBT(nbt);
colorData.writeNBT(nbt);
combatData.writeNBT(nbt);
homingData.writeNBT(nbt);
@@ -198,7 +191,7 @@ public class AbilityDisc extends Ability implements IAbilityDisc {
this.discThickness = nbt.hasKey("discThickness") ? nbt.getFloat("discThickness") : 0.2f;
this.boomerang = nbt.hasKey("boomerang") && nbt.getBoolean("boomerang");
this.boomerangDelay = nbt.hasKey("boomerangDelay") ? nbt.getInteger("boomerangDelay") : 40;
this.anchorPoint = nbt.hasKey("anchorPoint") ? AnchorPoint.fromId(nbt.getInteger("anchorPoint")) : AnchorPoint.FRONT;
anchorData.readNBT(nbt);
colorData.readNBT(nbt);
combatData.readNBT(nbt);
homingData.readNBT(nbt);
@@ -257,14 +250,20 @@ public class AbilityDisc extends Ability implements IAbilityDisc {
public void setLightningDensity(float lightningDensity) { lightningData.lightningDensity = lightningDensity; }
public float getLightningRadius() { return lightningData.lightningRadius; }
public void setLightningRadius(float lightningRadius) { lightningData.lightningRadius = lightningRadius; }
public AnchorPoint getAnchorPointEnum() { return anchorPoint; }
public void setAnchorPointEnum(AnchorPoint anchorPoint) { this.anchorPoint = anchorPoint; }
public AnchorPoint getAnchorPointEnum() { return anchorData.anchorPoint; }
public float getAnchorOffsetX() { return anchorData.anchorOffsetX; }
public float getAnchorOffsetY() { return anchorData.anchorOffsetY; }
public float getAnchorOffsetZ() { return anchorData.anchorOffsetZ; }
public void setAnchorPointEnum(AnchorPoint anchorPoint) { this.anchorData.anchorPoint = anchorPoint; }
public void setAnchorOffsetX(float x) { this.anchorData.anchorOffsetX = x; }
public void setAnchorOffsetY(float y) { this.anchorData.anchorOffsetY = y; }
public void setAnchorOffsetZ(float z) { this.anchorData.anchorOffsetZ = z; }
@Override
public int getAnchorPoint() { return anchorPoint.getId(); }
public int getAnchorPoint() { return anchorData.anchorPoint.getId(); }
@Override
public void setAnchorPoint(int point) { this.anchorPoint = AnchorPoint.fromId(point); }
public void setAnchorPoint(int point) { this.anchorData.anchorPoint = AnchorPoint.fromId(point); }
@Override
@SideOnly(Side.CLIENT)
@@ -272,7 +271,7 @@ public class AbilityDisc extends Ability implements IAbilityDisc {
if (npc == null || npc.worldObj == null) return null;
EntityAbilityDisc disc = new EntityAbilityDisc(npc.worldObj);
disc.setupPreview(npc, discRadius, discThickness, colorData, lightningData, anchorPoint, windUpTicks);
disc.setupPreview(npc, discRadius, discThickness, colorData, lightningData, anchorData, windUpTicks);
return disc;
}
@@ -6,11 +6,7 @@ import kamkeel.npcs.controllers.data.ability.Ability;
import kamkeel.npcs.controllers.data.ability.AnchorPoint;
import kamkeel.npcs.controllers.data.ability.LockMovementType;
import kamkeel.npcs.controllers.data.ability.TargetingMode;
import kamkeel.npcs.controllers.data.ability.data.EnergyColorData;
import kamkeel.npcs.controllers.data.ability.data.EnergyCombatData;
import kamkeel.npcs.controllers.data.ability.data.EnergyHomingData;
import kamkeel.npcs.controllers.data.ability.data.EnergyLightningData;
import kamkeel.npcs.controllers.data.ability.data.EnergyLifespanData;
import kamkeel.npcs.controllers.data.ability.data.*;
import kamkeel.npcs.controllers.data.telegraph.Telegraph;
import kamkeel.npcs.controllers.data.telegraph.TelegraphInstance;
import kamkeel.npcs.controllers.data.telegraph.TelegraphType;
@@ -44,9 +40,7 @@ public class AbilityEnergyBeam extends Ability implements IAbilityEnergyBeam {
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);
// Anchor point for charging position
private AnchorPoint anchorPoint = AnchorPoint.RIGHT_HAND;
private EnergyAnchorData anchorData = new EnergyAnchorData(AnchorPoint.RIGHT_HAND);
// Transient state for beam entity (used during windup charging)
private transient EntityAbilityBeam beamEntity = null;
@@ -113,14 +107,14 @@ public class AbilityEnergyBeam extends Ability implements IAbilityEnergyBeam {
float offsetDist = 1.0f;
// Create beam in charging mode - follows NPC based on anchor point during windup
Vec3 spawnPos = AnchorPointHelper.calculateAnchorPosition(npc, anchorPoint, offsetDist);
Vec3 spawnPos = AnchorPointHelper.calculateAnchorPosition(npc, anchorData, offsetDist);
beamEntity = new EntityAbilityBeam(
world, npc, target,
spawnPos.xCoord, spawnPos.yCoord, spawnPos.zCoord,
beamWidth, headSize,
colorData, combatData, homingData, lightningData, lifespanData,
lockMovement.locksActive());
beamEntity.setupCharging(anchorPoint, windUpTicks, offsetDist);
beamEntity.setupCharging(anchorData, windUpTicks, offsetDist);
beamEntity.setEffects(this.effects);
world.spawnEntityInWorld(beamEntity);
@@ -180,7 +174,7 @@ public class AbilityEnergyBeam extends Ability implements IAbilityEnergyBeam {
public void writeTypeNBT(NBTTagCompound nbt) {
nbt.setFloat("beamWidth", beamWidth);
nbt.setFloat("headSize", headSize);
nbt.setInteger("anchorPoint", anchorPoint.getId());
anchorData.writeNBT(nbt);
colorData.writeNBT(nbt);
combatData.writeNBT(nbt);
homingData.writeNBT(nbt);
@@ -192,7 +186,7 @@ public class AbilityEnergyBeam extends Ability implements IAbilityEnergyBeam {
public void readTypeNBT(NBTTagCompound nbt) {
this.beamWidth = nbt.hasKey("beamWidth") ? nbt.getFloat("beamWidth") : 0.4f;
this.headSize = nbt.hasKey("headSize") ? nbt.getFloat("headSize") : 0.6f;
this.anchorPoint = nbt.hasKey("anchorPoint") ? AnchorPoint.fromId(nbt.getInteger("anchorPoint")) : AnchorPoint.FRONT;
anchorData.readNBT(nbt);
colorData.readNBT(nbt);
combatData.readNBT(nbt);
homingData.readNBT(nbt);
@@ -259,14 +253,20 @@ public class AbilityEnergyBeam extends Ability implements IAbilityEnergyBeam {
public void setMaxLifetime(int maxLifetime) { this.lifespanData.maxLifetime = maxLifetime; }
// Getters & Setters - Anchor point
public AnchorPoint getAnchorPointEnum() { return anchorPoint; }
public void setAnchorPointEnum(AnchorPoint anchorPoint) { this.anchorPoint = anchorPoint; }
public AnchorPoint getAnchorPointEnum() { return anchorData.anchorPoint; }
public float getAnchorOffsetX() { return anchorData.anchorOffsetX; }
public float getAnchorOffsetY() { return anchorData.anchorOffsetY; }
public float getAnchorOffsetZ() { return anchorData.anchorOffsetZ; }
public void setAnchorPointEnum(AnchorPoint anchorPoint) { this.anchorData.anchorPoint = anchorPoint; }
public void setAnchorOffsetX(float x) { this.anchorData.anchorOffsetX = x; }
public void setAnchorOffsetY(float y) { this.anchorData.anchorOffsetY = y; }
public void setAnchorOffsetZ(float z) { this.anchorData.anchorOffsetZ = z; }
@Override
public int getAnchorPoint() { return anchorPoint.getId(); }
public int getAnchorPoint() { return anchorData.anchorPoint.getId(); }
@Override
public void setAnchorPoint(int point) { this.anchorPoint = AnchorPoint.fromId(point); }
public void setAnchorPoint(int point) { this.anchorData.anchorPoint = AnchorPoint.fromId(point); }
@Override
@SideOnly(Side.CLIENT)
@@ -274,7 +274,7 @@ public class AbilityEnergyBeam extends Ability implements IAbilityEnergyBeam {
if (npc == null || npc.worldObj == null) return null;
EntityAbilityBeam beam = new EntityAbilityBeam(npc.worldObj);
beam.setupPreview(npc, beamWidth, headSize, colorData, lightningData, anchorPoint, windUpTicks, 1.0f);
beam.setupPreview(npc, beamWidth, headSize, colorData, lightningData, anchorData, windUpTicks, 1.0f);
return beam;
}
@@ -6,11 +6,7 @@ import kamkeel.npcs.controllers.data.ability.Ability;
import kamkeel.npcs.controllers.data.ability.AnchorPoint;
import kamkeel.npcs.controllers.data.ability.LockMovementType;
import kamkeel.npcs.controllers.data.ability.TargetingMode;
import kamkeel.npcs.controllers.data.ability.data.EnergyColorData;
import kamkeel.npcs.controllers.data.ability.data.EnergyCombatData;
import kamkeel.npcs.controllers.data.ability.data.EnergyHomingData;
import kamkeel.npcs.controllers.data.ability.data.EnergyLightningData;
import kamkeel.npcs.controllers.data.ability.data.EnergyLifespanData;
import kamkeel.npcs.controllers.data.ability.data.*;
import kamkeel.npcs.controllers.data.telegraph.Telegraph;
import kamkeel.npcs.controllers.data.telegraph.TelegraphInstance;
import kamkeel.npcs.controllers.data.telegraph.TelegraphType;
@@ -19,7 +15,6 @@ import kamkeel.npcs.util.AnchorPointHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.DamageSource;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
@@ -38,15 +33,13 @@ public class AbilityOrb extends Ability implements IAbilityOrb {
// Ability-specific properties
private float orbSize = 1.0f;
// Anchor point for charging position
private AnchorPoint anchorPoint = AnchorPoint.RIGHT_HAND;
// Data classes for energy properties
public final EnergyColorData colorData = new EnergyColorData();
public final EnergyCombatData combatData = new EnergyCombatData();
public final EnergyHomingData homingData = new EnergyHomingData();
public final EnergyLightningData lightningData = new EnergyLightningData();
public final EnergyLifespanData lifespanData = new EnergyLifespanData();
private EnergyAnchorData anchorData = new EnergyAnchorData(AnchorPoint.RIGHT_HAND);
// Transient state for orb entity (used during windup charging)
private transient EntityAbilityOrb orbEntity = null;
@@ -110,12 +103,12 @@ public class AbilityOrb extends Ability implements IAbilityOrb {
// Spawn orb in charging mode on first tick of windup
if (tick == 1) {
// Create orb in charging mode - follows NPC based on anchor point during windup
Vec3 spawnPos = AnchorPointHelper.calculateAnchorPosition(npc, anchorPoint);
Vec3 spawnPos = AnchorPointHelper.calculateAnchorPosition(npc, anchorData);
orbEntity = new EntityAbilityOrb(
world, npc, target,
spawnPos.xCoord, spawnPos.yCoord, spawnPos.zCoord, orbSize,
colorData, combatData, homingData, lightningData, lifespanData);
orbEntity.setupCharging(anchorPoint, windUpTicks);
orbEntity.setupCharging(anchorData, windUpTicks);
orbEntity.setEffects(this.effects);
world.spawnEntityInWorld(orbEntity);
@@ -175,7 +168,7 @@ public class AbilityOrb extends Ability implements IAbilityOrb {
@Override
public void writeTypeNBT(NBTTagCompound nbt) {
nbt.setFloat("orbSize", orbSize);
nbt.setInteger("anchorPoint", anchorPoint.getId());
anchorData.writeNBT(nbt);
colorData.writeNBT(nbt);
combatData.writeNBT(nbt);
homingData.writeNBT(nbt);
@@ -188,7 +181,7 @@ public class AbilityOrb extends Ability implements IAbilityOrb {
@Override
public void readTypeNBT(NBTTagCompound nbt) {
this.orbSize = nbt.hasKey("orbSize") ? nbt.getFloat("orbSize") : 1.0f;
this.anchorPoint = nbt.hasKey("anchorPoint") ? AnchorPoint.fromId(nbt.getInteger("anchorPoint")) : AnchorPoint.FRONT;
anchorData.readNBT(nbt);
colorData.readNBT(nbt);
combatData.readNBT(nbt);
homingData.readNBT(nbt);
@@ -385,21 +378,29 @@ public class AbilityOrb extends Ability implements IAbilityOrb {
lightningData.lightningFadeTime = lightningFadeTime;
}
public AnchorPoint getAnchorPointEnum() {
return anchorPoint;
}
public AnchorPoint getAnchorPointEnum() { return anchorData.anchorPoint; }
public void setAnchorPointEnum(AnchorPoint anchorPoint) {
this.anchorPoint = anchorPoint;
}
public float getAnchorOffsetX() { return anchorData.anchorOffsetX; }
public float getAnchorOffsetY() { return anchorData.anchorOffsetY; }
public float getAnchorOffsetZ() { return anchorData.anchorOffsetZ; }
public void setAnchorPointEnum(AnchorPoint anchorPoint) { this.anchorData.anchorPoint = anchorPoint; }
public void setAnchorOffsetX(float x) { this.anchorData.anchorOffsetX = x; }
public void setAnchorOffsetY(float y) { this.anchorData.anchorOffsetY = y; }
public void setAnchorOffsetZ(float z) { this.anchorData.anchorOffsetZ = z; }
public int getAnchorPoint() {
return anchorPoint.getId();
return anchorData.anchorPoint.getId();
}
@Override
public void setAnchorPoint(int point) {
this.anchorPoint = AnchorPoint.fromId(point);
this.anchorData.anchorPoint = AnchorPoint.fromId(point);
}
@Override
@@ -408,7 +409,7 @@ public class AbilityOrb extends Ability implements IAbilityOrb {
if (npc == null || npc.worldObj == null) return null;
EntityAbilityOrb orb = new EntityAbilityOrb(npc.worldObj);
orb.setupPreview(npc, orbSize, colorData, lightningData, anchorPoint, windUpTicks);
orb.setupPreview(npc, orbSize, colorData, lightningData, anchorData, windUpTicks);
return orb;
}
@@ -1,11 +1,7 @@
package kamkeel.npcs.entity;
import kamkeel.npcs.controllers.data.ability.AnchorPoint;
import kamkeel.npcs.controllers.data.ability.data.EnergyColorData;
import kamkeel.npcs.controllers.data.ability.data.EnergyCombatData;
import kamkeel.npcs.controllers.data.ability.data.EnergyHomingData;
import kamkeel.npcs.controllers.data.ability.data.EnergyLifespanData;
import kamkeel.npcs.controllers.data.ability.data.EnergyLightningData;
import kamkeel.npcs.controllers.data.ability.data.*;
import kamkeel.npcs.util.AnchorPointHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
@@ -62,7 +58,7 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
private int chargeDuration = 40;
private int chargeTick = 0;
private float chargeOffsetDistance = 1.0f;
private AnchorPoint anchorPoint = AnchorPoint.FRONT;
private EnergyAnchorData anchorData = new EnergyAnchorData(AnchorPoint.FRONT);
// Trail fading for non-anchored beams (comet effect)
private boolean fadeTrail = false;
@@ -171,19 +167,19 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
}
}
public void setupCharging(AnchorPoint anchorPoint, int chargeDuration, float chargeOffsetDistance) {
public void setupCharging(EnergyAnchorData anchor, int chargeDuration, float chargeOffsetDistance) {
setCharging(true);
this.chargeDuration = chargeDuration;
this.chargeTick = 0;
this.chargeOffsetDistance = chargeOffsetDistance;
this.anchorPoint = anchorPoint;
this.anchorData = anchor;
this.fadeTrail = !attachedToOwner;
this.motionX = 0;
this.motionY = 0;
this.motionZ = 0;
}
public void setupPreview(EntityNPCInterface owner, float beamWidth, float headSize, EnergyColorData color, EnergyLightningData lightning, AnchorPoint anchorPoint, int chargeDuration, float chargeOffsetDistance) {
public void setupPreview(EntityNPCInterface owner, float beamWidth, float headSize, EnergyColorData color, EnergyLightningData lightning, EnergyAnchorData anchor, int chargeDuration, float chargeOffsetDistance) {
this.setPreviewMode(true);
this.setPreviewOwner(owner);
@@ -206,10 +202,10 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
this.chargeDuration = chargeDuration;
this.chargeTick = 0;
this.chargeOffsetDistance = chargeOffsetDistance;
this.anchorPoint = anchorPoint;
this.anchorData = anchor;
// Initial position at anchor point
Vec3 pos = AnchorPointHelper.calculateAnchorPosition(owner, anchorPoint, chargeOffsetDistance);
Vec3 pos = AnchorPointHelper.calculateAnchorPosition(owner, anchorData, chargeOffsetDistance);
this.setPosition(pos.xCoord, pos.yCoord, pos.zCoord);
this.prevPosX = pos.xCoord;
this.prevPosY = pos.yCoord;
@@ -450,7 +446,7 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
// Calculate position based on anchor point
Vec3 pos;
if (owner instanceof EntityLivingBase) {
pos = AnchorPointHelper.calculateAnchorPosition((EntityLivingBase) owner, anchorPoint, chargeOffsetDistance);
pos = AnchorPointHelper.calculateAnchorPosition((EntityLivingBase) owner, anchorData, chargeOffsetDistance);
} else {
// Fallback for non-living entities (shouldn't happen normally)
float yaw = (float) Math.toRadians(owner.rotationYaw);
@@ -772,10 +768,11 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
this.chargeDuration = nbt.hasKey("ChargeDuration") ? nbt.getInteger("ChargeDuration") : 40;
this.chargeTick = nbt.hasKey("ChargeTick") ? nbt.getInteger("ChargeTick") : 0;
this.chargeOffsetDistance = nbt.hasKey("ChargeOffsetDistance") ? nbt.getFloat("ChargeOffsetDistance") : 1.0f;
this.anchorPoint = nbt.hasKey("AnchorPoint") ? AnchorPoint.fromId(nbt.getInteger("AnchorPoint")) : AnchorPoint.FRONT;
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();
if (nbt.hasKey("Trail")) {
@@ -808,10 +805,11 @@ public class EntityAbilityBeam extends EntityAbilityProjectile {
nbt.setInteger("ChargeDuration", chargeDuration);
nbt.setInteger("ChargeTick", chargeTick);
nbt.setFloat("ChargeOffsetDistance", chargeOffsetDistance);
nbt.setInteger("AnchorPoint", anchorPoint.getId());
nbt.setBoolean("FadeTrail", fadeTrail);
nbt.setInteger("TrailFadeTime", trailFadeTime);
this.anchorData.writeNBT(nbt);
// Write trail points
NBTTagList trailList = new NBTTagList();
for (Vec3 point : trailPoints) {
@@ -1,11 +1,7 @@
package kamkeel.npcs.entity;
import kamkeel.npcs.controllers.data.ability.AnchorPoint;
import kamkeel.npcs.controllers.data.ability.data.EnergyColorData;
import kamkeel.npcs.controllers.data.ability.data.EnergyCombatData;
import kamkeel.npcs.controllers.data.ability.data.EnergyHomingData;
import kamkeel.npcs.controllers.data.ability.data.EnergyLifespanData;
import kamkeel.npcs.controllers.data.ability.data.EnergyLightningData;
import kamkeel.npcs.controllers.data.ability.data.*;
import kamkeel.npcs.util.AnchorPointHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
@@ -46,9 +42,9 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
private boolean charging = false;
private int chargeDuration = 40;
private int chargeTick = 0;
private AnchorPoint anchorPoint = AnchorPoint.FRONT;
private float targetDiscRadius = 1.0f; // Full radius to grow to during charging
private float targetDiscThickness = 0.2f; // Full thickness to grow to during charging
private EnergyAnchorData anchorData = new EnergyAnchorData();
// Data watcher index for charging state (synced to clients)
private static final int DW_CHARGING = 20;
@@ -137,11 +133,11 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
* The disc will grow from 0 to discRadius over chargeDuration ticks.
* Position follows the owner based on anchor point.
*/
public void setupCharging(AnchorPoint anchorPoint, int chargeDuration) {
public void setupCharging(EnergyAnchorData anchor, int chargeDuration) {
setCharging(true);
this.chargeDuration = chargeDuration;
this.chargeTick = 0;
this.anchorPoint = anchorPoint;
this.anchorData = anchor;
this.targetDiscRadius = this.discRadius;
this.targetDiscThickness = this.discThickness;
this.discRadius = 0.01f;
@@ -159,7 +155,7 @@ 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(EntityNPCInterface owner, float discRadius, float discThickness, EnergyColorData color, EnergyLightningData lightning, AnchorPoint anchorPoint, int chargeDuration) {
public void setupPreview(EntityNPCInterface owner, float discRadius, float discThickness, EnergyColorData color, EnergyLightningData lightning, EnergyAnchorData anchor, int chargeDuration) {
this.setPreviewMode(true);
this.setPreviewOwner(owner);
@@ -177,7 +173,7 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
this.setCharging(true);
this.chargeDuration = chargeDuration;
this.chargeTick = 0;
this.anchorPoint = anchorPoint;
this.anchorData = anchor;
// Store target size and start at 0 for grow effect
this.targetDiscRadius = discRadius;
@@ -187,7 +183,7 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
this.size = 0.01f;
// Initial position at anchor point
Vec3 pos = AnchorPointHelper.calculateAnchorPosition(owner, anchorPoint);
Vec3 pos = AnchorPointHelper.calculateAnchorPosition(owner, anchorData);
this.setPosition(pos.xCoord, pos.yCoord, pos.zCoord);
this.prevPosX = pos.xCoord;
this.prevPosY = pos.yCoord;
@@ -518,7 +514,7 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
// Calculate position based on anchor point
if (owner instanceof EntityLivingBase) {
Vec3 pos = AnchorPointHelper.calculateAnchorPosition((EntityLivingBase) owner, anchorPoint);
Vec3 pos = AnchorPointHelper.calculateAnchorPosition((EntityLivingBase) owner, anchorData);
setPosition(pos.xCoord, pos.yCoord, pos.zCoord);
}
@@ -589,9 +585,9 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
this.dataWatcher.updateObject(DW_CHARGING, (byte) (isCharging ? 1 : 0));
this.chargeDuration = nbt.hasKey("ChargeDuration") ? nbt.getInteger("ChargeDuration") : 40;
this.chargeTick = nbt.hasKey("ChargeTick") ? nbt.getInteger("ChargeTick") : 0;
this.anchorPoint = nbt.hasKey("AnchorPoint") ? AnchorPoint.fromId(nbt.getInteger("AnchorPoint")) : AnchorPoint.FRONT;
this.targetDiscRadius = nbt.hasKey("TargetDiscRadius") ? nbt.getFloat("TargetDiscRadius") : this.discRadius;
this.targetDiscThickness = nbt.hasKey("TargetDiscThickness") ? nbt.getFloat("TargetDiscThickness") : this.discThickness;
this.anchorData.readNBT(nbt);
}
@Override
@@ -609,8 +605,10 @@ public class EntityAbilityDisc extends EntityAbilityProjectile {
nbt.setBoolean("Charging", isCharging());
nbt.setInteger("ChargeDuration", chargeDuration);
nbt.setInteger("ChargeTick", chargeTick);
nbt.setInteger("AnchorPoint", anchorPoint.getId());
nbt.setFloat("TargetDiscRadius", targetDiscRadius);
nbt.setFloat("TargetDiscThickness", targetDiscThickness);
// Anchor data
this.anchorData.writeNBT(nbt);
}
}
@@ -1,11 +1,7 @@
package kamkeel.npcs.entity;
import kamkeel.npcs.controllers.data.ability.AnchorPoint;
import kamkeel.npcs.controllers.data.ability.data.EnergyColorData;
import kamkeel.npcs.controllers.data.ability.data.EnergyCombatData;
import kamkeel.npcs.controllers.data.ability.data.EnergyHomingData;
import kamkeel.npcs.controllers.data.ability.data.EnergyLifespanData;
import kamkeel.npcs.controllers.data.ability.data.EnergyLightningData;
import kamkeel.npcs.controllers.data.ability.data.*;
import kamkeel.npcs.util.AnchorPointHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
@@ -36,7 +32,7 @@ public class EntityAbilityOrb extends EntityAbilityProjectile {
private boolean charging = false;
private int chargeDuration = 40;
private int chargeTick = 0;
private AnchorPoint anchorPoint = AnchorPoint.FRONT;
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)
@@ -119,11 +115,11 @@ public class EntityAbilityOrb extends EntityAbilityProjectile {
* The orb will grow from 0 to orbSize over chargeDuration ticks.
* Position follows the owner based on anchor point.
*/
public void setupCharging(AnchorPoint anchorPoint, int chargeDuration) {
public void setupCharging(EnergyAnchorData anchor, int chargeDuration) {
setCharging(true);
this.chargeDuration = chargeDuration;
this.chargeTick = 0;
this.anchorPoint = anchorPoint;
this.anchorData = anchor;
this.targetSize = this.size;
this.size = 0.01f;
this.renderCurrentSize = 0.01f;
@@ -138,7 +134,7 @@ 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(EntityNPCInterface owner, float orbSize, EnergyColorData color, EnergyLightningData lightning, AnchorPoint anchorPoint, int chargeDuration) {
public void setupPreview(EntityNPCInterface owner, float orbSize, EnergyColorData color, EnergyLightningData lightning, EnergyAnchorData anchor, int chargeDuration) {
this.setPreviewMode(true);
this.setPreviewOwner(owner);
@@ -157,7 +153,7 @@ public class EntityAbilityOrb extends EntityAbilityProjectile {
this.setCharging(true);
this.chargeDuration = chargeDuration;
this.chargeTick = 0;
this.anchorPoint = anchorPoint;
this.anchorData = anchor;
// Store target size and start at 0 for grow effect
this.targetSize = orbSize;
@@ -166,7 +162,7 @@ public class EntityAbilityOrb extends EntityAbilityProjectile {
this.prevRenderSize = 0.01f;
// Initial position at anchor point
Vec3 pos = AnchorPointHelper.calculateAnchorPosition(owner, anchorPoint);
Vec3 pos = AnchorPointHelper.calculateAnchorPosition(owner, anchorData);
this.setPosition(pos.xCoord, pos.yCoord, pos.zCoord);
this.prevPosX = pos.xCoord;
this.prevPosY = pos.yCoord;
@@ -400,7 +396,7 @@ public class EntityAbilityOrb extends EntityAbilityProjectile {
// Calculate position based on anchor point
if (owner instanceof EntityLivingBase) {
Vec3 pos = AnchorPointHelper.calculateAnchorPosition((EntityLivingBase) owner, anchorPoint);
Vec3 pos = AnchorPointHelper.calculateAnchorPosition((EntityLivingBase) owner, anchorData);
setPosition(pos.xCoord, pos.yCoord, pos.zCoord);
}
}
@@ -460,8 +456,9 @@ public class EntityAbilityOrb extends EntityAbilityProjectile {
this.dataWatcher.updateObject(DW_CHARGING, (byte) (isCharging ? 1 : 0));
this.chargeDuration = nbt.hasKey("ChargeDuration") ? nbt.getInteger("ChargeDuration") : 40;
this.chargeTick = nbt.hasKey("ChargeTick") ? nbt.getInteger("ChargeTick") : 0;
this.anchorPoint = nbt.hasKey("AnchorPoint") ? AnchorPoint.fromId(nbt.getInteger("AnchorPoint")) : AnchorPoint.FRONT;
this.targetSize = nbt.hasKey("TargetSize") ? nbt.getFloat("TargetSize") : this.size;
// Anchor data
this.anchorData.readNBT(nbt);
}
@Override
@@ -474,7 +471,7 @@ public class EntityAbilityOrb extends EntityAbilityProjectile {
nbt.setBoolean("Charging", isCharging());
nbt.setInteger("ChargeDuration", chargeDuration);
nbt.setInteger("ChargeTick", chargeTick);
nbt.setInteger("AnchorPoint", anchorPoint.getId());
anchorData.writeNBT(nbt);
nbt.setFloat("TargetSize", targetSize);
}
}
@@ -1,6 +1,7 @@
package kamkeel.npcs.util;
import kamkeel.npcs.controllers.data.ability.AnchorPoint;
import kamkeel.npcs.controllers.data.ability.data.EnergyAnchorData;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.Vec3;
import noppes.npcs.constants.EnumAnimationPart;
@@ -48,17 +49,23 @@ public class AnchorPointHelper {
/**
* Calculate world position for an anchor point on an entity.
*/
public static Vec3 calculateAnchorPosition(EntityLivingBase entity, AnchorPoint anchor) {
return calculateAnchorPosition(entity, anchor, DEFAULT_FRONT_DISTANCE);
public static Vec3 calculateAnchorPosition(EntityLivingBase entity, EnergyAnchorData anchorData) {
return calculateAnchorPosition(entity, anchorData, DEFAULT_FRONT_DISTANCE);
}
/**
* Calculate world position for an anchor point with custom front offset.
*/
public static Vec3 calculateAnchorPosition(EntityLivingBase entity, AnchorPoint anchor, float frontOffset) {
public static Vec3 calculateAnchorPosition(EntityLivingBase entity, EnergyAnchorData anchorData, float frontOffset) {
float scale = getModelScale(entity);
float height = entity.height;
AnchorPoint anchor = anchorData.anchorPoint;
float anchorX = anchorData.anchorOffsetX;
float anchorY = anchorData.anchorOffsetY;
float anchorZ = anchorData.anchorOffsetZ;
double x = entity.posX;
double y = entity.posY;
double z = entity.posZ;
@@ -78,10 +85,10 @@ public class AnchorPointHelper {
break;
case RIGHT_HAND:
return calculateHandPosition(entity, true, scale);
return calculateHandPosition(entity, anchorData, true, scale);
case LEFT_HAND:
return calculateHandPosition(entity, false, scale);
return calculateHandPosition(entity, anchorData, false, scale);
case ABOVE_HEAD:
y += height * ABOVE_HEAD_HEIGHT;
@@ -92,6 +99,10 @@ public class AnchorPointHelper {
break;
}
x += anchorX * scale;
y += anchorY * scale;
z += anchorZ * scale;
return Vec3.createVectorHelper(x, y, z);
}
@@ -124,22 +135,22 @@ public class AnchorPointHelper {
/**
* Calculate hand position using animation data if available.
*/
private static Vec3 calculateHandPosition(EntityLivingBase entity, boolean rightHand, float scale) {
private static Vec3 calculateHandPosition(EntityLivingBase entity, EnergyAnchorData anchor, boolean rightHand, float scale) {
// Try to get animated position first
Vec3 animatedPos = getAnimatedHandPosition(entity, rightHand, scale);
Vec3 animatedPos = getAnimatedHandPosition(entity, anchor, rightHand, scale);
if (animatedPos != null) {
return animatedPos;
}
// Fallback to static position
return calculateFallbackHandPosition(entity, rightHand, scale);
return calculateFallbackHandPosition(entity, anchor, rightHand, scale);
}
/**
* Calculate hand position from animation data.
* Works for both NPCs and Players.
*/
private static Vec3 getAnimatedHandPosition(EntityLivingBase entity, boolean rightHand, float scale) {
private static Vec3 getAnimatedHandPosition(EntityLivingBase entity, EnergyAnchorData anchor, boolean rightHand, float scale) {
AnimationData animData = AnimationData.getData(entity);
if (animData == null || !animData.isActive() || animData.animation == null) {
return null;
@@ -235,6 +246,10 @@ public class AnchorPointHelper {
double worldY = entity.posY + shoulderHeight - blockY;
double worldZ = entity.posZ + worldOffsetZ;
worldX += anchor.anchorOffsetX * scale;
worldY += anchor.anchorOffsetY * scale;
worldZ += anchor.anchorOffsetZ * scale;
return Vec3.createVectorHelper(worldX, worldY, worldZ);
}
@@ -277,7 +292,7 @@ public class AnchorPointHelper {
* Calculate fallback hand position when no animation is active.
* Represents arms hanging at sides in default idle pose.
*/
private static Vec3 calculateFallbackHandPosition(EntityLivingBase entity, boolean rightHand, float scale) {
private static Vec3 calculateFallbackHandPosition(EntityLivingBase entity, EnergyAnchorData anchor, boolean rightHand, float scale) {
float bodyYaw = (float) Math.toRadians(entity.renderYawOffset);
// Get arm scale for EntityCustomNpc
@@ -302,6 +317,10 @@ public class AnchorPointHelper {
double y = entity.posY + entity.height * FALLBACK_ARM_HEIGHT + armLengthOffset;
double z = entity.posZ + lateralZ + forwardZ;
x += anchor.anchorOffsetX * scale;
y += anchor.anchorOffsetY * scale;
z += anchor.anchorOffsetZ * scale;
return Vec3.createVectorHelper(x, y, z);
}