From 9f8f742a0ecc0f83700d4b6c4c069a65a9d07cc3 Mon Sep 17 00:00:00 2001 From: Kam Date: Wed, 18 Feb 2026 22:41:19 -0500 Subject: [PATCH 1/3] Beta 4 --- build.gradle | 2 +- src/main/java/noppes/npcs/CustomNpcs.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 0babda6bb..ef7d8145f 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { id 'idea' } -version = "1.11-beta3" +version = "1.11-beta4" group= "kamkeel.customnpc-plus" archivesBaseName = "CustomNPC-Plus" diff --git a/src/main/java/noppes/npcs/CustomNpcs.java b/src/main/java/noppes/npcs/CustomNpcs.java index 185131a15..f7c76f555 100644 --- a/src/main/java/noppes/npcs/CustomNpcs.java +++ b/src/main/java/noppes/npcs/CustomNpcs.java @@ -121,7 +121,7 @@ import java.util.HashSet; import java.util.Set; import java.util.function.Consumer; -@Mod(modid = "customnpcs", name = "CustomNPC+", version = "1.11-beta3") +@Mod(modid = "customnpcs", name = "CustomNPC+", version = "1.11-beta4") public class CustomNpcs { @SidedProxy(clientSide = "noppes.npcs.client.ClientProxy", serverSide = "noppes.npcs.CommonProxy") From e5fc58366b0124cdc6da1b019b27e9ae9608cb9e Mon Sep 17 00:00:00 2001 From: Kam Date: Wed, 18 Feb 2026 23:16:01 -0500 Subject: [PATCH 2/3] Fix Death Ability Bug --- .../noppes/npcs/ScriptPlayerEventHandler.java | 6 +- .../controllers/data/PlayerAbilityData.java | 62 ++++++++++++++----- 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/src/main/java/noppes/npcs/ScriptPlayerEventHandler.java b/src/main/java/noppes/npcs/ScriptPlayerEventHandler.java index 81ff9ed6b..13205e0f4 100644 --- a/src/main/java/noppes/npcs/ScriptPlayerEventHandler.java +++ b/src/main/java/noppes/npcs/ScriptPlayerEventHandler.java @@ -650,10 +650,12 @@ public class ScriptPlayerEventHandler { return; if (event.player.worldObj instanceof WorldServer && event.player instanceof EntityPlayerMP) { - // Cancel any executing ability on respawn + // Reset ability state for reconstructed entity and re-sync to client. + // The death handler already interrupted the ability (with events/cooldowns), + // so this just cleans up transient state and syncs the new entity. PlayerData playerData = PlayerData.get(event.player); if (playerData != null) { - playerData.abilityData.interruptCurrentAbility(); + playerData.abilityData.resetOnRespawn(); } PlayerDataScript handler = ScriptController.Instance.getPlayerScripts(event.player); diff --git a/src/main/java/noppes/npcs/controllers/data/PlayerAbilityData.java b/src/main/java/noppes/npcs/controllers/data/PlayerAbilityData.java index f06c21686..dfc26c95d 100644 --- a/src/main/java/noppes/npcs/controllers/data/PlayerAbilityData.java +++ b/src/main/java/noppes/npcs/controllers/data/PlayerAbilityData.java @@ -607,17 +607,25 @@ public class PlayerAbilityData extends AbstractDataAbilities implements IPlayerA } // ═══════════════════════════════════════════════════════════════════ - // DIMENSION CHANGE RESET + // ENTITY RECONSTRUCTION RESET // ═══════════════════════════════════════════════════════════════════ /** - * Fully reset ability state when changing dimensions. - * Unlike interruptCurrentAbility(), this does NOT roll any cooldowns - * and ensures the player can immediately use abilities in the new dimension. - * Also re-syncs to client since the entity may be re-created. + * Handle entity reconstruction events (dimension change, death/respawn, etc.). + * Cleans up any executing ability state without firing script events (those were + * already fired on the original entity), clears transient runtime state, and + * re-syncs ability data to the client on the new entity. + *

+ * This should be called whenever the player's entity object is recreated by Forge, + * since the client-side entity loses all synced ability state. + * + * @param clearCooldowns true to fully reset cooldowns (dimension change), + * false to preserve cooldowns (death/respawn — interrupt already rolled them) + * @param clearToggles true to clear active toggles (death/respawn), + * false to keep them (dimension change) */ - public void resetOnDimensionChange() { - // Clean up any executing ability without rolling cooldowns + public void onEntityReconstructed(boolean clearCooldowns, boolean clearToggles) { + // Clean up any executing ability silently (no script events — already fired on old entity) if (currentAbility != null && currentAbility.isExecuting()) { removeTelegraph(currentAbility); currentAbility.cleanup(); @@ -637,20 +645,46 @@ public class PlayerAbilityData extends AbstractDataAbilities implements IPlayerA currentAbilityKey = null; currentTarget = null; - // Reset cooldowns completely - cooldownEndTime = 0; + if (clearCooldowns) { + cooldownEndTime = 0; + } interruptCooldownRolled = false; - // Sync cleared state to client - EntityPlayer player = playerData.player; - if (player != null) { - syncAbilityStateClear(player); + if (clearToggles) { + clearActiveToggles(); } - // Re-sync ability data (unlocked list, selection) to client + // Force-send cleared lock state to client. We must always send this + // (not gated by lastSyncedFlags != 0) because the NEW entity's client + // may have stale lock state from before the reconstruction. + lastSyncedFlags = 0; + EntityPlayer player = playerData.player; + if (player instanceof EntityPlayerMP) { + PlayerAbilityStatePacket.sendToPlayer((EntityPlayerMP) player, (byte) 0, 0, 0); + } + + // Re-sync full ability data (unlocked list, selection, toggles) to client syncToClient(); } + /** + * Fully reset ability state when changing dimensions. + * Clears cooldowns so the player can immediately use abilities in the new dimension. + * Keeps active toggles (dimension change shouldn't reset ongoing effects). + */ + public void resetOnDimensionChange() { + onEntityReconstructed(true, false); + } + + /** + * Reset ability state after death/respawn. + * Preserves cooldowns (interrupt on death already rolled them) but clears + * active toggles (death should end ongoing effects). + */ + public void resetOnRespawn() { + onEntityReconstructed(false, true); + } + // ═══════════════════════════════════════════════════════════════════ // DAMAGE HANDLING // ═══════════════════════════════════════════════════════════════════ From e91fe89e6a6d4792f45b016ad068a0ebb88b9b75 Mon Sep 17 00:00:00 2001 From: Kam Date: Thu, 19 Feb 2026 01:35:21 -0500 Subject: [PATCH 3/3] Add Inner Alpha Handling --- .../client/renderer/RenderAbilityBeam.java | 28 +++++++------- .../client/renderer/RenderAbilityDisc.java | 2 +- .../client/renderer/RenderAbilityLaser.java | 2 +- .../client/renderer/RenderEnergySlicer.java | 4 +- .../data/ability/type/AbilityZone.java | 38 +++++++++++++++++-- 5 files changed, 54 insertions(+), 20 deletions(-) diff --git a/src/main/java/kamkeel/npcs/client/renderer/RenderAbilityBeam.java b/src/main/java/kamkeel/npcs/client/renderer/RenderAbilityBeam.java index d1b969921..deced23a0 100644 --- a/src/main/java/kamkeel/npcs/client/renderer/RenderAbilityBeam.java +++ b/src/main/java/kamkeel/npcs/client/renderer/RenderAbilityBeam.java @@ -74,18 +74,20 @@ public class RenderAbilityBeam extends RenderEnergyAbility { // Render tail orb at origin (0,0,0) - only in anchored mode // Don't render if head is too close to origin (would cause overlap/extra orb appearance) if (beam.shouldRenderTailOrb() && headDistFromOrigin > headSize * 0.5) { - renderTailOrb(headSize * 0.8f, innerColor, outerColor, beam.isOuterColorEnabled(), beam.getOuterColorWidth(), outerAlpha); + renderTailOrb(headSize * 0.8f, innerColor, outerColor, beam.isOuterColorEnabled(), beam.getOuterColorWidth(), outerAlpha, beam.getInnerAlpha()); } + float innerAlpha = beam.getInnerAlpha(); + // Render trail segments with smooth connections (with fading for non-anchored) if (beam.hasFadingTrail()) { - renderFadingTrail(beam, trail, beamWidth, innerColor, outerColor, beam.isOuterColorEnabled(), beam.getOuterColorWidth()); + renderFadingTrail(beam, trail, beamWidth, innerColor, outerColor, beam.isOuterColorEnabled(), beam.getOuterColorWidth(), innerAlpha); } else { - renderSmoothTrail(trail, beamWidth, innerColor, outerColor, beam.isOuterColorEnabled(), beam.getOuterColorWidth()); + renderSmoothTrail(trail, beamWidth, innerColor, outerColor, beam.isOuterColorEnabled(), beam.getOuterColorWidth(), innerAlpha); } // Render head at interpolated offset position - renderHead(beam, headOffsetX, headOffsetY, headOffsetZ, headSize, innerColor, outerColor, outerAlpha, partialTicks); + renderHead(beam, headOffsetX, headOffsetY, headOffsetZ, headSize, innerColor, outerColor, outerAlpha, innerAlpha, partialTicks); GL11.glPopMatrix(); @@ -139,7 +141,7 @@ public class RenderAbilityBeam extends RenderEnergyAbility { // Render inner core GL11.glScalef(innerScale, innerScale, innerScale); - renderCube(innerColor, 1.0f, 0.5f); + renderCube(innerColor, beam.getInnerAlpha(), 0.5f); GL11.glPopMatrix(); GL11.glPopMatrix(); @@ -149,7 +151,7 @@ public class RenderAbilityBeam extends RenderEnergyAbility { * Render the tail orb at the origin (where the beam emanates from). * This orb does not rotate - it's a stable anchor point. */ - private void renderTailOrb(float size, int innerColor, int outerColor, boolean outerColorEnabled, float outerColorWidth, float outerAlpha) { + private void renderTailOrb(float size, int innerColor, int outerColor, boolean outerColorEnabled, float outerColorWidth, float outerAlpha, float innerAlpha) { GL11.glPushMatrix(); // Already at origin (0,0,0) @@ -171,7 +173,7 @@ public class RenderAbilityBeam extends RenderEnergyAbility { // Render inner core (solid) GL11.glPushMatrix(); GL11.glScalef(size * innerScale, size * innerScale, size * innerScale); - renderCube(innerColor, 1.0f, 0.5f); + renderCube(innerColor, innerAlpha, 0.5f); GL11.glPopMatrix(); GL11.glPopMatrix(); @@ -182,7 +184,7 @@ public class RenderAbilityBeam extends RenderEnergyAbility { * Uses averaged perpendicular vectors at connection points to prevent gaps. */ private void renderSmoothTrail(List trail, float width, int innerColor, int outerColor, - boolean outerColorEnabled, float outerColorWidth) { + boolean outerColorEnabled, float outerColorWidth, float innerAlpha) { if (trail.size() < 2) return; int trailSize = trail.size(); @@ -205,7 +207,7 @@ public class RenderAbilityBeam extends RenderEnergyAbility { } // Render inner core trail - renderTrailTube(trail, perpFrames, innerWidth, innerColor, 0.9f, false); + renderTrailTube(trail, perpFrames, innerWidth, innerColor, innerAlpha, false); } /** @@ -213,7 +215,7 @@ public class RenderAbilityBeam extends RenderEnergyAbility { * Older trail points fade out based on their age. */ private void renderFadingTrail(EntityAbilityBeam beam, List trail, float width, int innerColor, int outerColor, - boolean outerColorEnabled, float outerColorWidth) { + boolean outerColorEnabled, float outerColorWidth, float innerAlpha) { if (trail.size() < 2) return; List ages = beam.getTrailPointAges(); @@ -235,7 +237,7 @@ public class RenderAbilityBeam extends RenderEnergyAbility { } // Render inner core trail with fading - renderFadingTrailTube(trail, perpFrames, ages, fadeTime, innerWidth, innerColor, 0.9f); + renderFadingTrailTube(trail, perpFrames, ages, fadeTime, innerWidth, innerColor, innerAlpha); } /** @@ -541,7 +543,7 @@ public class RenderAbilityBeam extends RenderEnergyAbility { * Coordinates are relative to origin. */ private void renderHead(EntityAbilityBeam beam, double x, double y, double z, - float size, int innerColor, int outerColor, float outerAlpha, float partialTicks) { + float size, int innerColor, int outerColor, float outerAlpha, float innerAlpha, float partialTicks) { GL11.glPushMatrix(); GL11.glTranslated(x, y, z); @@ -580,7 +582,7 @@ public class RenderAbilityBeam extends RenderEnergyAbility { // Render inner core GL11.glScalef(innerScale, innerScale, innerScale); - renderCube(innerColor, 1.0f, 0.5f); + renderCube(innerColor, innerAlpha, 0.5f); GL11.glPopMatrix(); GL11.glPopMatrix(); diff --git a/src/main/java/kamkeel/npcs/client/renderer/RenderAbilityDisc.java b/src/main/java/kamkeel/npcs/client/renderer/RenderAbilityDisc.java index 7f1a2e12c..d013dd306 100644 --- a/src/main/java/kamkeel/npcs/client/renderer/RenderAbilityDisc.java +++ b/src/main/java/kamkeel/npcs/client/renderer/RenderAbilityDisc.java @@ -67,7 +67,7 @@ public class RenderAbilityDisc extends RenderEnergyAbility { } // Render inner square (solid) - renderFlatSquare(disc.getInnerColor(), 1.0f, radius * innerScale, thickness * 1.2f); + renderFlatSquare(disc.getInnerColor(), disc.getInnerAlpha(), radius * innerScale, thickness * 1.2f); GL11.glPopMatrix(); GL11.glPopMatrix(); diff --git a/src/main/java/kamkeel/npcs/client/renderer/RenderAbilityLaser.java b/src/main/java/kamkeel/npcs/client/renderer/RenderAbilityLaser.java index 543dba44c..d24bc1bc9 100644 --- a/src/main/java/kamkeel/npcs/client/renderer/RenderAbilityLaser.java +++ b/src/main/java/kamkeel/npcs/client/renderer/RenderAbilityLaser.java @@ -117,7 +117,7 @@ public class RenderAbilityLaser extends RenderEnergyAbility { renderBeamRectangle(renderStartX, renderStartY, renderStartZ, renderEndX, renderEndY, renderEndZ, horzX, horzY, horzZ, vertX, vertY, vertZ, - innerWidth, laser.getInnerColor(), alpha); + innerWidth, laser.getInnerColor(), alpha * laser.getInnerAlpha()); // Render lightning along the laser beam if (laser.hasLightningEffect() && laser.getCurrentLength() > 0.1f) { diff --git a/src/main/java/kamkeel/npcs/client/renderer/RenderEnergySlicer.java b/src/main/java/kamkeel/npcs/client/renderer/RenderEnergySlicer.java index b5ee31568..e2aa0868f 100644 --- a/src/main/java/kamkeel/npcs/client/renderer/RenderEnergySlicer.java +++ b/src/main/java/kamkeel/npcs/client/renderer/RenderEnergySlicer.java @@ -53,8 +53,8 @@ public class RenderEnergySlicer extends RenderEnergyAbility { GL11.glDepthMask(true); } - // Render inner blade (solid core, alpha 1.0 like Orb pattern) - renderBlade(slicer.getInnerColor(), 1.0f, + // Render inner blade (solid core) + renderBlade(slicer.getInnerColor(), slicer.getInnerAlpha(), width * 0.5f * innerScale, thickness, 0.03f); GL11.glPopMatrix(); diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityZone.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityZone.java index 0b233a637..b5cc53a9e 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityZone.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityZone.java @@ -519,6 +519,30 @@ public abstract class AbilityZone extends Ability { colorData.outerColorEnabled = enabled; } + public float getInnerAlpha() { + return colorData.innerAlpha; + } + + public void setInnerAlpha(float alpha) { + colorData.innerAlpha = alpha; + } + + public float getOuterColorWidth() { + return colorData.outerColorWidth; + } + + public void setOuterColorWidth(float width) { + colorData.outerColorWidth = width; + } + + public float getOuterColorAlpha() { + return colorData.outerColorAlpha; + } + + public void setOuterColorAlpha(float alpha) { + colorData.outerColorAlpha = alpha; + } + public boolean isGroundFill() { return groundFill; } @@ -711,12 +735,20 @@ public abstract class AbilityZone extends Ability { .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.row( + FieldDef.colorSubGui("ability.innerColor", this::getInnerColor, this::setInnerColor), + FieldDef.floatField("ability.innerAlpha", this::getInnerAlpha, this::setInnerAlpha).range(0, 1) + ).tab("ability.tab.visual"), FieldDef.boolField("ability.outerEnabled", this::isOuterColorEnabled, this::setOuterColorEnabled) .tab("ability.tab.visual"), FieldDef.colorSubGui("ability.outerColor", this::getOuterColor, this::setOuterColor) - .tab("ability.tab.visual").visibleWhen(this::isOuterColorEnabled) + .tab("ability.tab.visual").visibleWhen(this::isOuterColorEnabled), + FieldDef.row( + FieldDef.floatField("ability.outerWidth", this::getOuterColorWidth, this::setOuterColorWidth) + .visibleWhen(this::isOuterColorEnabled), + FieldDef.floatField("ability.outerAlpha", this::getOuterColorAlpha, this::setOuterColorAlpha) + .range(0, 1).visibleWhen(this::isOuterColorEnabled) + ).tab("ability.tab.visual") )); }