diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyPanelData.java b/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyPanelData.java index c57e0bbf5..aaef76cf6 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyPanelData.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyPanelData.java @@ -10,6 +10,8 @@ public class EnergyPanelData { public float panelWidth = 3.0f; public float panelHeight = 3.0f; public float heightOffset = 0.0f; + public float offsetX = 0.0f; + public float offsetZ = 0.0f; // Launch properties (Wall only) public boolean launching = false; @@ -90,6 +92,8 @@ public class EnergyPanelData { nbt.setFloat("panelWidth", panelWidth); nbt.setFloat("panelHeight", panelHeight); nbt.setFloat("panelHeightOffset", heightOffset); + nbt.setFloat("panelOffsetX", offsetX); + nbt.setFloat("panelOffsetZ", offsetZ); nbt.setBoolean("panelLaunching", launching); nbt.setFloat("panelLaunchSpeed", launchSpeed); nbt.setFloat("panelLaunchDamage", launchDamage); @@ -100,6 +104,8 @@ public class EnergyPanelData { panelWidth = nbt.hasKey("panelWidth") ? nbt.getFloat("panelWidth") : 3.0f; panelHeight = nbt.hasKey("panelHeight") ? nbt.getFloat("panelHeight") : 3.0f; heightOffset = nbt.hasKey("panelHeightOffset") ? nbt.getFloat("panelHeightOffset") : 0.0f; + offsetX = nbt.hasKey("panelOffsetX") ? nbt.getFloat("panelOffsetX") : 0.0f; + offsetZ = nbt.hasKey("panelOffsetZ") ? nbt.getFloat("panelOffsetZ") : 0.0f; launching = nbt.hasKey("panelLaunching") && nbt.getBoolean("panelLaunching"); launchSpeed = nbt.hasKey("panelLaunchSpeed") ? nbt.getFloat("panelLaunchSpeed") : 0.5f; launchDamage = nbt.hasKey("panelLaunchDamage") ? nbt.getFloat("panelLaunchDamage") : 8.0f; @@ -108,6 +114,8 @@ public class EnergyPanelData { public EnergyPanelData copy() { EnergyPanelData copy = new EnergyPanelData(panelWidth, panelHeight, heightOffset); + copy.offsetX = offsetX; + copy.offsetZ = offsetZ; copy.launching = launching; copy.launchSpeed = launchSpeed; copy.launchDamage = launchDamage; diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityBarrier.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityBarrier.java index d1054e858..d18a8f2eb 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityBarrier.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityBarrier.java @@ -21,6 +21,11 @@ public abstract class AbilityBarrier extends AbilityEnergy { protected final EnergyBarrierData barrierData; + // Spawn position offsets (relative to caster) + protected float offsetX = 0.0f; + protected float offsetY = 0.0f; + protected float offsetZ = 0.0f; + // Runtime entity tracking protected transient EntityAbilityBarrier barrierEntity; @@ -157,10 +162,16 @@ public abstract class AbilityBarrier extends AbilityEnergy { writeBarrierTypeNBT(nbt); writeEnergyNBT(nbt); barrierData.writeNBT(nbt); + nbt.setFloat("barrierOffsetX", offsetX); + nbt.setFloat("barrierOffsetY", offsetY); + nbt.setFloat("barrierOffsetZ", offsetZ); } @Override public final void readTypeNBT(NBTTagCompound nbt) { + offsetX = nbt.hasKey("barrierOffsetX") ? nbt.getFloat("barrierOffsetX") : 0.0f; + offsetY = nbt.hasKey("barrierOffsetY") ? nbt.getFloat("barrierOffsetY") : 0.0f; + offsetZ = nbt.hasKey("barrierOffsetZ") ? nbt.getFloat("barrierOffsetZ") : 0.0f; readBarrierTypeNBT(nbt); readEnergyNBT(nbt); barrierData.readNBT(nbt); @@ -288,6 +299,31 @@ public abstract class AbilityBarrier extends AbilityEnergy { barrierData.meleeDamageMultiplier = mult; } + // Offset data + public float getOffsetX() { + return offsetX; + } + + public void setOffsetX(float offsetX) { + this.offsetX = offsetX; + } + + public float getOffsetY() { + return offsetY; + } + + public void setOffsetY(float offsetY) { + this.offsetY = offsetY; + } + + public float getOffsetZ() { + return offsetZ; + } + + public void setOffsetZ(float offsetZ) { + this.offsetZ = offsetZ; + } + // ==================== GUI ==================== @SideOnly(Side.CLIENT) @@ -296,6 +332,14 @@ public abstract class AbilityBarrier extends AbilityEnergy { // Type-specific fields first addBarrierTypeDefinitions(defs); + // Offset section + defs.add(FieldDef.section("ability.section.offset")); + defs.add(FieldDef.row( + FieldDef.floatField("ability.offsetX", this::getOffsetX, this::setOffsetX).min(Float.NEGATIVE_INFINITY), + FieldDef.floatField("ability.offsetY", this::getOffsetY, this::setOffsetY).min(Float.NEGATIVE_INFINITY) + )); + defs.add(FieldDef.floatField("ability.offsetZ", this::getOffsetZ, this::setOffsetZ).min(Float.NEGATIVE_INFINITY)); + // Barrier section defs.add(FieldDef.section("ability.section.barrier")); defs.add(FieldDef.boolField("ability.useHealth", this::isUseHealth, this::setUseHealth)); diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityDome.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityDome.java index 99b431477..ee978df13 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityDome.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityDome.java @@ -50,10 +50,11 @@ public class AbilityDome extends AbilityBarrier { protected EntityAbilityBarrier createBarrierEntity(EntityLivingBase caster, EntityLivingBase target) { EntityAbilityDome dome = new EntityAbilityDome( caster.worldObj, caster, - caster.posX, caster.posY, caster.posZ, + caster.posX + offsetX, caster.posY + offsetY, caster.posZ + offsetZ, domeRadius, displayData.copy(), lightningData.copy(), barrierData.copy() ); dome.setFollowCaster(followCaster); + dome.setOffsets(offsetX, offsetY, offsetZ); dome.setSourceAbility(this); return dome; } diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityShield.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityShield.java index f7cbaa8fd..04407bdd6 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityShield.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityShield.java @@ -51,13 +51,15 @@ public class AbilityShield extends AbilityBarrier { @Override protected EntityAbilityBarrier createBarrierEntity(EntityLivingBase caster, EntityLivingBase target) { - EnergyPanelData panelData = new EnergyPanelData(shieldWidth, shieldHeight, 0.0f); + EnergyPanelData panelData = new EnergyPanelData(shieldWidth, shieldHeight, offsetY); + panelData.offsetX = offsetX; + panelData.offsetZ = offsetZ; float frontDist = 1.5f; float yawRad = (float) Math.toRadians(caster.rotationYaw); - double spawnX = caster.posX + (-Math.sin(yawRad) * frontDist); + double spawnX = caster.posX + (-Math.sin(yawRad) * frontDist) + offsetX; double spawnY = caster.posY + (caster.height * 0.5f); - double spawnZ = caster.posZ + (Math.cos(yawRad) * frontDist); + double spawnZ = caster.posZ + (Math.cos(yawRad) * frontDist) + offsetZ; EntityAbilityPanel panel = new EntityAbilityPanel( caster.worldObj, caster, diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityWall.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityWall.java index 1d820851d..7044e71b9 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityWall.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityWall.java @@ -87,14 +87,21 @@ public class AbilityWall extends AbilityBarrier { yaw = caster.rotationYaw; } + placeX += offsetX; + placeY += offsetY; + placeZ += offsetZ; + EntityAbilityPanel.PanelMode mode = panelData.launching ? EntityAbilityPanel.PanelMode.LAUNCHED : EntityAbilityPanel.PanelMode.PLACED; + EnergyPanelData data = panelData.copy(); + data.heightOffset = 0.0f; // Y offset now handled by base class via placeY + EntityAbilityPanel panel = new EntityAbilityPanel( caster.worldObj, caster, placeX, placeY, placeZ, yaw, mode, - displayData.copy(), lightningData.copy(), barrierData.copy(), panelData.copy() + displayData.copy(), lightningData.copy(), barrierData.copy(), data ); panel.setSourceAbility(this); return panel; @@ -134,6 +141,11 @@ public class AbilityWall extends AbilityBarrier { @Override protected void readBarrierTypeNBT(NBTTagCompound nbt) { panelData.readNBT(nbt); + // Migrate legacy heightOffset → base class offsetY + if (!nbt.hasKey("barrierOffsetY") && panelData.heightOffset != 0.0f) { + offsetY = panelData.heightOffset; + panelData.heightOffset = 0.0f; + } } // ==================== GETTERS & SETTERS ==================== @@ -158,14 +170,6 @@ public class AbilityWall extends AbilityBarrier { panelData.setPanelHeight(height); } - public float getHeightOffset() { - return panelData.heightOffset; - } - - public void setHeightOffset(float offset) { - panelData.heightOffset = offset; - } - public boolean isLaunching() { return panelData.launching; } @@ -208,8 +212,6 @@ public class AbilityWall extends AbilityBarrier { FieldDef.floatField("gui.width", this::getPanelWidth, this::setPanelWidth).range(0.5f, 100.0f), FieldDef.floatField("gui.height", this::getPanelHeight, this::setPanelHeight).range(0.5f, 100.0f) )); - defs.add(FieldDef.floatField("ability.heightOffset", this::getHeightOffset, this::setHeightOffset) - .min(Float.NEGATIVE_INFINITY)); defs.add(FieldDef.section("ability.section.launch")); defs.add(FieldDef.boolField("gui.enabled", this::isLaunching, this::setLaunching) .hover("ability.hover.launching")); diff --git a/src/main/java/kamkeel/npcs/entity/EntityAbilityDome.java b/src/main/java/kamkeel/npcs/entity/EntityAbilityDome.java index 5bdb82a09..3c5caf4f2 100644 --- a/src/main/java/kamkeel/npcs/entity/EntityAbilityDome.java +++ b/src/main/java/kamkeel/npcs/entity/EntityAbilityDome.java @@ -30,6 +30,9 @@ public class EntityAbilityDome extends EntityAbilityBarrier { protected float domeRadius = 5.0f; protected float targetDomeRadius = 5.0f; protected boolean followCaster = false; + protected float offsetX = 0.0f; + protected float offsetY = 0.0f; + protected float offsetZ = 0.0f; // Server-side melee detection state private boolean inTickMelee = false; @@ -81,11 +84,11 @@ public class EntityAbilityDome extends EntityAbilityBarrier { if (followCaster) { Entity owner = ownerEntityId >= 0 ? worldObj.getEntityByID(ownerEntityId) : null; if (owner != null) { - this.setPosition(owner.posX, owner.posY, owner.posZ); + this.setPosition(owner.posX + offsetX, owner.posY + offsetY, owner.posZ + offsetZ); // Sync prevPos with owner's prevPos for smooth interpolation - this.prevPosX = owner.prevPosX; - this.prevPosY = owner.prevPosY; - this.prevPosZ = owner.prevPosZ; + this.prevPosX = owner.prevPosX + offsetX; + this.prevPosY = owner.prevPosY + offsetY; + this.prevPosZ = owner.prevPosZ + offsetZ; } } @@ -589,6 +592,12 @@ public class EntityAbilityDome extends EntityAbilityBarrier { this.followCaster = follow; } + public void setOffsets(float x, float y, float z) { + this.offsetX = x; + this.offsetY = y; + this.offsetZ = z; + } + @Override @SideOnly(Side.CLIENT) public void setPositionAndRotation2(double x, double y, double z, float yaw, float pitch, int increments) { @@ -631,6 +640,9 @@ public class EntityAbilityDome extends EntityAbilityBarrier { nbt.setFloat("DomeRadius", domeRadius); nbt.setFloat("TargetDomeRadius", targetDomeRadius); nbt.setBoolean("FollowCaster", followCaster); + nbt.setFloat("OffsetX", offsetX); + nbt.setFloat("OffsetY", offsetY); + nbt.setFloat("OffsetZ", offsetZ); } @Override @@ -639,5 +651,8 @@ public class EntityAbilityDome extends EntityAbilityBarrier { this.setDomeRadius(sanitize(nbt.getFloat("DomeRadius"), 5.0f, MAX_ENTITY_RADIUS)); this.targetDomeRadius = sanitize(nbt.hasKey("TargetDomeRadius") ? nbt.getFloat("TargetDomeRadius") : domeRadius, 5.0f, MAX_ENTITY_RADIUS); this.followCaster = nbt.hasKey("FollowCaster") && nbt.getBoolean("FollowCaster"); + this.offsetX = nbt.hasKey("OffsetX") ? nbt.getFloat("OffsetX") : 0.0f; + this.offsetY = nbt.hasKey("OffsetY") ? nbt.getFloat("OffsetY") : 0.0f; + this.offsetZ = nbt.hasKey("OffsetZ") ? nbt.getFloat("OffsetZ") : 0.0f; } } diff --git a/src/main/java/kamkeel/npcs/entity/EntityAbilityPanel.java b/src/main/java/kamkeel/npcs/entity/EntityAbilityPanel.java index e4df1dee6..90cd9885a 100644 --- a/src/main/java/kamkeel/npcs/entity/EntityAbilityPanel.java +++ b/src/main/java/kamkeel/npcs/entity/EntityAbilityPanel.java @@ -157,17 +157,17 @@ public class EntityAbilityPanel extends EntityAbilityBarrier { // Follow owner position float frontDist = 1.5f; float yawRad = (float) Math.toRadians(panelYaw); - double newX = owner.posX + (-Math.sin(yawRad) * frontDist); + double newX = owner.posX + (-Math.sin(yawRad) * frontDist) + panelData.offsetX; double newY = owner.posY + panelData.heightOffset + (owner.height * 0.5f); - double newZ = owner.posZ + (Math.cos(yawRad) * frontDist); + double newZ = owner.posZ + (Math.cos(yawRad) * frontDist) + panelData.offsetZ; this.setPosition(newX, newY, newZ); // Sync prevPos with owner's prevPos for smooth interpolation float prevYawRad = (float) Math.toRadians(owner.prevRotationYaw); - this.prevPosX = owner.prevPosX + (-Math.sin(prevYawRad) * frontDist); + this.prevPosX = owner.prevPosX + (-Math.sin(prevYawRad) * frontDist) + panelData.offsetX; this.prevPosY = owner.prevPosY + panelData.heightOffset + (owner.height * 0.5f); - this.prevPosZ = owner.prevPosZ + (Math.cos(prevYawRad) * frontDist); + this.prevPosZ = owner.prevPosZ + (Math.cos(prevYawRad) * frontDist) + panelData.offsetZ; } @Override diff --git a/src/main/resources/assets/customnpcs/lang/en_US.lang b/src/main/resources/assets/customnpcs/lang/en_US.lang index 9caf6027a..c407a411b 100644 --- a/src/main/resources/assets/customnpcs/lang/en_US.lang +++ b/src/main/resources/assets/customnpcs/lang/en_US.lang @@ -2090,9 +2090,14 @@ ability.domeRadius=Dome Radius ability.useHealth=Use Health ability.maxHealth=Max Health ability.useDuration=Use Duration +ability.duration=Duration ability.defaultMultiplier=Default Multiplier ability.innerAlpha=Inner Alpha ability.heightOffset=Height Offset +ability.section.offset=Offset +ability.offsetX=X Offset +ability.offsetY=Y Offset +ability.offsetZ=Z Offset ability.solid=Solid ability.knockbackEnabled=Knockback