From fdb2ff98d8192cf73737c8fc629165d03f0891ab Mon Sep 17 00:00:00 2001 From: Kam Date: Sat, 10 Jan 2026 23:06:13 -0500 Subject: [PATCH] Large Ability changes, cleanup, langs, fixes. --- src/api | 2 +- .../controllers/data/ability/Ability.java | 7 +- .../data/ability/AbilityController.java | 39 ++- .../data/ability/type/AbilityBeam.java | 4 +- .../data/ability/type/AbilityCharge.java | 4 +- .../data/ability/type/AbilityCutter.java | 4 +- .../data/ability/type/AbilityDash.java | 4 +- .../data/ability/type/AbilityGuard.java | 4 +- .../data/ability/type/AbilityHazard.java | 4 +- .../data/ability/type/AbilityHeal.java | 4 +- .../data/ability/type/AbilityHeavyHit.java | 4 +- .../data/ability/type/AbilityOrb.java | 4 +- .../data/ability/type/AbilityProjectile.java | 4 +- .../data/ability/type/AbilityShockwave.java | 4 +- .../data/ability/type/AbilitySlam.java | 19 +- .../data/ability/type/AbilityTeleport.java | 4 +- .../data/ability/type/AbilityTrap.java | 4 +- .../data/ability/type/AbilityVortex.java | 4 +- .../client/gui/advanced/GuiNPCAbilities.java | 80 ++---- .../gui/advanced/SubGuiAbilityConfig.java | 268 ++++++++++++------ .../gui/advanced/SubGuiConditionEdit.java | 181 ++++++++++++ .../advanced/ability/SubGuiAbilityBeam.java | 2 +- .../advanced/ability/SubGuiAbilityCharge.java | 2 +- .../advanced/ability/SubGuiAbilityCutter.java | 2 +- .../advanced/ability/SubGuiAbilityDash.java | 2 +- .../advanced/ability/SubGuiAbilityGuard.java | 2 +- .../advanced/ability/SubGuiAbilityHazard.java | 2 +- .../advanced/ability/SubGuiAbilityHeal.java | 2 +- .../ability/SubGuiAbilityHeavyHit.java | 2 +- .../advanced/ability/SubGuiAbilityOrb.java | 2 +- .../ability/SubGuiAbilityProjectile.java | 2 +- .../ability/SubGuiAbilityShockwave.java | 2 +- .../advanced/ability/SubGuiAbilitySlam.java | 2 +- .../ability/SubGuiAbilityTeleport.java | 2 +- .../advanced/ability/SubGuiAbilityTrap.java | 2 +- .../advanced/ability/SubGuiAbilityVortex.java | 2 +- .../assets/customnpcs/lang/en_US.lang | 49 +++- 37 files changed, 517 insertions(+), 214 deletions(-) create mode 100644 src/main/java/noppes/npcs/client/gui/advanced/SubGuiConditionEdit.java diff --git a/src/api b/src/api index 3ac76848d..5cd088851 160000 --- a/src/api +++ b/src/api @@ -1 +1 @@ -Subproject commit 3ac76848d32724eff763f2c0c2b8054e40a96e68 +Subproject commit 5cd0888511c6ab16fa454919c6269e4013bbc965 diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/Ability.java b/src/main/java/kamkeel/npcs/controllers/data/ability/Ability.java index f9b126336..b6c392b5c 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/Ability.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/Ability.java @@ -12,9 +12,10 @@ import net.minecraft.nbt.NBTTagList; import net.minecraft.util.DamageSource; import net.minecraft.world.World; import noppes.npcs.DataAbilities; +import noppes.npcs.NpcDamageSource; import noppes.npcs.api.INbt; import noppes.npcs.api.ability.IAbility; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.entity.EntityNPCInterface; import noppes.npcs.scripted.NpcAPI; @@ -31,7 +32,7 @@ public abstract class Ability implements IAbility { protected String id; protected String name; - protected String typeId; // e.g., "cnpc:slam", "mymod:custom_ability" + protected String typeId; // e.g., "ability.cnpc.slam" (also used as lang key) // Selection protected int weight = 10; @@ -136,7 +137,7 @@ public abstract class Ability implements IAbility { // Apply damage if (finalDamage > 0) { - hitEntity.attackEntityFrom(DamageSource.causeMobDamage(npc), finalDamage); + hitEntity.attackEntityFrom(new NpcDamageSource("mob", npc), finalDamage); } // Apply knockback if any diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/AbilityController.java b/src/main/java/kamkeel/npcs/controllers/data/ability/AbilityController.java index 4fc00f7ec..685e5403d 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/AbilityController.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/AbilityController.java @@ -22,6 +22,7 @@ public class AbilityController implements IAbilityHandler { public static AbilityController Instance; private final Map> factories = new LinkedHashMap<>(); + private final Map> factoriesByTypeId = new LinkedHashMap<>(); private final Map savedAbilities = new LinkedHashMap<>(); public AbilityController() { @@ -177,12 +178,13 @@ public class AbilityController implements IAbilityHandler { @Override public String[] getTypes() { - return factories.keySet().toArray(new String[0]); + // Return the ability typeIds (lang keys), not the factory keys + return factoriesByTypeId.keySet().toArray(new String[0]); } @Override public boolean hasType(String typeId) { - return factories.containsKey(typeId); + return factories.containsKey(typeId) || factoriesByTypeId.containsKey(typeId); } @Override @@ -208,14 +210,19 @@ public class AbilityController implements IAbilityHandler { * Register a new ability type. * Call during FMLInitializationEvent. * - * @param typeId The unique type ID (e.g., "cnpc:slam", "mymod:custom_ability") + * @param factoryKey The factory key (e.g., "cnpc:slam", "mymod:custom_ability") * @param factory Factory lambda that creates a new instance */ - public void registerType(String typeId, Supplier factory) { - if (factories.containsKey(typeId)) { - LogWriter.info("AbilityController: Overwriting existing ability type: " + typeId); + public void registerType(String factoryKey, Supplier factory) { + if (factories.containsKey(factoryKey)) { + LogWriter.info("AbilityController: Overwriting existing ability type: " + factoryKey); } - factories.put(typeId, factory); + factories.put(factoryKey, factory); + + // Also register by the ability's actual typeId (lang key) + Ability temp = factory.get(); + String abilityTypeId = temp.getTypeId(); + factoriesByTypeId.put(abilityTypeId, factory); } /** @@ -229,6 +236,10 @@ public class AbilityController implements IAbilityHandler { String typeId = nbt.getString("typeId"); Supplier factory = factories.get(typeId); + if (factory == null) { + // Try looking up by ability typeId (lang key) + factory = factoriesByTypeId.get(typeId); + } if (factory == null) { LogWriter.info("AbilityController: Unknown ability type: " + typeId); return null; @@ -241,15 +252,19 @@ public class AbilityController implements IAbilityHandler { /** * Create a new empty ability of the given type. + * @param factoryKey The factory key (e.g., "cnpc:slam") or the ability typeId (e.g., "ability.cnpc.slam") */ - public Ability create(String typeId) { - Supplier factory = factories.get(typeId); + public Ability create(String factoryKey) { + // Try direct lookup first (factory key) + Supplier factory = factories.get(factoryKey); + if (factory == null) { + // Try looking up by ability typeId + factory = factoriesByTypeId.get(factoryKey); + } if (factory == null) { return null; } - Ability ability = factory.get(); - ability.typeId = typeId; - return ability; + return factory.get(); } /** diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityBeam.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityBeam.java index f76ec7406..2dc67e5c0 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityBeam.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityBeam.java @@ -4,7 +4,7 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import kamkeel.npcs.controllers.data.ability.Ability; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityBeam; import kamkeel.npcs.controllers.data.ability.TargetingMode; @@ -45,7 +45,7 @@ public class AbilityBeam extends Ability { private transient Set hitThisTick = new HashSet<>(); public AbilityBeam() { - this.typeId = "cnpc:beam"; + this.typeId = "ability.cnpc.beam"; this.name = "Beam"; this.targetingMode = TargetingMode.AGGRO_TARGET; this.maxRange = 15.0f; diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityCharge.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityCharge.java index 271abe2ee..f2a88edb6 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityCharge.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityCharge.java @@ -14,7 +14,7 @@ import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.DamageSource; import net.minecraft.util.Vec3; import net.minecraft.world.World; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityCharge; import noppes.npcs.entity.EntityNPCInterface; @@ -43,7 +43,7 @@ public class AbilityCharge extends Ability { private transient float lockedYaw; public AbilityCharge() { - this.typeId = "cnpc:charge"; + this.typeId = "ability.cnpc.charge"; this.name = "Charge"; this.targetingMode = TargetingMode.AGGRO_TARGET; this.maxRange = 20.0f; diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityCutter.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityCutter.java index 26b930d56..5e81501a9 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityCutter.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityCutter.java @@ -12,7 +12,7 @@ import net.minecraft.potion.PotionEffect; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.DamageSource; import net.minecraft.world.World; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityCutter; import noppes.npcs.entity.EntityNPCInterface; @@ -58,7 +58,7 @@ public class AbilityCutter extends Ability { private transient float currentRotation = 0.0f; public AbilityCutter() { - this.typeId = "cnpc:cutter"; + this.typeId = "ability.cnpc.cutter"; this.name = "Cutter"; this.targetingMode = TargetingMode.AOE_SELF; this.maxRange = 8.0f; diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityDash.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityDash.java index 0e35e8f0e..920e57f96 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityDash.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityDash.java @@ -4,7 +4,7 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import kamkeel.npcs.controllers.data.ability.Ability; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityDash; import kamkeel.npcs.controllers.data.ability.TargetingMode; @@ -82,7 +82,7 @@ public class AbilityDash extends Ability { private transient DashDirection chosenDirection; public AbilityDash() { - this.typeId = "cnpc:dash"; + this.typeId = "ability.cnpc.dash"; this.name = "Dash"; this.targetingMode = TargetingMode.AGGRO_TARGET; this.maxRange = 20.0f; diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityGuard.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityGuard.java index b48e353b1..8afc45063 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityGuard.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityGuard.java @@ -4,7 +4,7 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import kamkeel.npcs.controllers.data.ability.Ability; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityGuard; import kamkeel.npcs.controllers.data.ability.TargetingMode; @@ -36,7 +36,7 @@ public class AbilityGuard extends Ability { private transient boolean counterTriggered; public AbilityGuard() { - this.typeId = "cnpc:guard"; + this.typeId = "ability.cnpc.guard"; this.name = "Guard"; this.targetingMode = TargetingMode.SELF; this.lockMovement = true; diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityHazard.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityHazard.java index bcca99eac..9ac5509d5 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityHazard.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityHazard.java @@ -4,7 +4,7 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import kamkeel.npcs.controllers.data.ability.Ability; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityHazard; import kamkeel.npcs.controllers.data.ability.TargetingMode; @@ -77,7 +77,7 @@ public class AbilityHazard extends Ability { private transient Set damagedThisTick = new HashSet<>(); public AbilityHazard() { - this.typeId = "cnpc:hazard"; + this.typeId = "ability.cnpc.hazard"; this.name = "Hazard"; this.targetingMode = TargetingMode.AGGRO_TARGET; this.maxRange = 15.0f; diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityHeal.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityHeal.java index 4c6dd6c76..4a393682b 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityHeal.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityHeal.java @@ -10,7 +10,7 @@ import net.minecraft.entity.EntityLivingBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.AxisAlignedBB; import net.minecraft.world.World; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityHeal; import noppes.npcs.entity.EntityNPCInterface; @@ -36,7 +36,7 @@ public class AbilityHeal extends Ability { private transient List healedAllies = new ArrayList<>(); public AbilityHeal() { - this.typeId = "cnpc:heal"; + this.typeId = "ability.cnpc.heal"; this.name = "Heal"; this.targetingMode = TargetingMode.SELF; this.lockMovement = true; diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityHeavyHit.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityHeavyHit.java index 4d62d610d..b76412606 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityHeavyHit.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityHeavyHit.java @@ -4,7 +4,7 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import kamkeel.npcs.controllers.data.ability.Ability; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityHeavyHit; import kamkeel.npcs.controllers.data.ability.TargetingMode; @@ -28,7 +28,7 @@ public class AbilityHeavyHit extends Ability { private int stunTicks = 40; public AbilityHeavyHit() { - this.typeId = "cnpc:heavy_hit"; + this.typeId = "ability.cnpc.heavy_hit"; this.name = "Heavy Hit"; this.targetingMode = TargetingMode.AGGRO_TARGET; this.maxRange = 3.0f; diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityOrb.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityOrb.java index 41148c953..afc8f6eb8 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityOrb.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityOrb.java @@ -4,7 +4,7 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import kamkeel.npcs.controllers.data.ability.Ability; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityOrb; import kamkeel.npcs.controllers.data.ability.TargetingMode; @@ -53,7 +53,7 @@ public class AbilityOrb extends Ability { private transient int ticksAlive = 0; public AbilityOrb() { - this.typeId = "cnpc:orb"; + this.typeId = "ability.cnpc.orb"; this.name = "Orb"; this.targetingMode = TargetingMode.AGGRO_TARGET; this.maxRange = 25.0f; diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityProjectile.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityProjectile.java index 0adcc48e2..b5f47e8b1 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityProjectile.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityProjectile.java @@ -10,7 +10,7 @@ import net.minecraft.entity.EntityLivingBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.DamageSource; import net.minecraft.world.World; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityProjectile; import noppes.npcs.entity.EntityNPCInterface; @@ -34,7 +34,7 @@ public class AbilityProjectile extends Ability { private float homingStrength = 0.1f; public AbilityProjectile() { - this.typeId = "cnpc:projectile"; + this.typeId = "ability.cnpc.projectile"; this.name = "Projectile"; this.targetingMode = TargetingMode.AGGRO_TARGET; this.minRange = 5.0f; diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityShockwave.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityShockwave.java index f5e7d9a97..1204dbc4d 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityShockwave.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityShockwave.java @@ -12,7 +12,7 @@ import net.minecraft.potion.PotionEffect; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.DamageSource; import net.minecraft.world.World; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityShockwave; import noppes.npcs.entity.EntityNPCInterface; @@ -37,7 +37,7 @@ public class AbilityShockwave extends Ability { private transient boolean executed = false; public AbilityShockwave() { - this.typeId = "cnpc:shockwave"; + this.typeId = "ability.cnpc.shockwave"; this.name = "Shockwave"; this.targetingMode = TargetingMode.AOE_SELF; this.maxRange = 15.0f; diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilitySlam.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilitySlam.java index a35ea1f7a..1d72f23cc 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilitySlam.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilitySlam.java @@ -13,7 +13,7 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.DamageSource; import net.minecraft.util.MathHelper; import net.minecraft.world.World; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.advanced.ability.SubGuiAbilitySlam; import noppes.npcs.entity.EntityNPCInterface; @@ -47,7 +47,7 @@ public class AbilitySlam extends Ability { private transient int maxAirTicks = 60; // Timeout to prevent stuck in air public AbilitySlam() { - this.typeId = "cnpc:slam"; + this.typeId = "ability.cnpc.slam"; this.name = "Slam"; this.targetingMode = TargetingMode.AOE_SELF; // Can also be AOE_TARGET to leap to target this.windUpTicks = 30; @@ -127,6 +127,9 @@ public class AbilitySlam extends Ability { hasLanded = false; airTicks = 0; + // Reset fall distance to prevent fall damage during slam + npc.fallDistance = 0; + // Calculate and apply leap velocity launchTowardTarget(npc); } @@ -230,6 +233,9 @@ public class AbilitySlam extends Ability { airTicks++; + // Continuously reset fall distance during slam to prevent fall damage + npc.fallDistance = 0; + // Check for landing if (npc.onGround && airTicks > 3) { // Landed! @@ -258,6 +264,9 @@ public class AbilitySlam extends Ability { hasLanded = true; npc.setNpcJumpingState(false); + // Reset fall distance to prevent fall damage on landing + npc.fallDistance = 0; + // Stop horizontal momentum npc.motionX = 0; npc.motionZ = 0; @@ -415,9 +424,9 @@ public class AbilitySlam extends Ability { @Override public void readTypeNBT(NBTTagCompound nbt) { - damage = nbt.getFloat("damage"); - radius = nbt.getFloat("radius"); - knockbackStrength = nbt.getFloat("knockback"); + damage = nbt.hasKey("damage") ? nbt.getFloat("damage") : 20.0f; + radius = nbt.hasKey("radius") ? nbt.getFloat("radius") : 5.0f; + knockbackStrength = nbt.hasKey("knockback") ? nbt.getFloat("knockback") : 1.5f; leapSpeed = nbt.hasKey("leapSpeed") ? nbt.getFloat("leapSpeed") : 1.0f; minLeapDistance = nbt.hasKey("minLeapDistance") ? nbt.getFloat("minLeapDistance") : 2.0f; maxLeapDistance = nbt.hasKey("maxLeapDistance") ? nbt.getFloat("maxLeapDistance") : 15.0f; diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityTeleport.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityTeleport.java index 789685755..f4a4780e8 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityTeleport.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityTeleport.java @@ -4,7 +4,7 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import kamkeel.npcs.controllers.data.ability.Ability; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityTeleport; import kamkeel.npcs.controllers.data.ability.TargetingMode; @@ -60,7 +60,7 @@ public class AbilityTeleport extends Ability { private transient int ticksSinceLastBlink = 0; public AbilityTeleport() { - this.typeId = "cnpc:teleport"; + this.typeId = "ability.cnpc.teleport"; this.name = "Teleport"; this.targetingMode = TargetingMode.AGGRO_TARGET; this.maxRange = 30.0f; diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityTrap.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityTrap.java index 47c4e7dc0..64e6e07bb 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityTrap.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityTrap.java @@ -13,7 +13,7 @@ import net.minecraft.potion.PotionEffect; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.DamageSource; import net.minecraft.world.World; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityTrap; import noppes.npcs.entity.EntityNPCInterface; @@ -68,7 +68,7 @@ public class AbilityTrap extends Ability { private transient Set triggeredEntities = new HashSet<>(); public AbilityTrap() { - this.typeId = "cnpc:trap"; + this.typeId = "ability.cnpc.trap"; this.name = "Trap"; this.targetingMode = TargetingMode.AGGRO_TARGET; this.maxRange = 15.0f; diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityVortex.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityVortex.java index 6c34a3945..ab368cdba 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityVortex.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityVortex.java @@ -4,7 +4,7 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import kamkeel.npcs.controllers.data.ability.Ability; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityVortex; import kamkeel.npcs.controllers.data.ability.TargetingMode; @@ -47,7 +47,7 @@ public class AbilityVortex extends Ability { private transient boolean pullComplete = false; public AbilityVortex() { - this.typeId = "cnpc:vortex"; + this.typeId = "ability.cnpc.vortex"; this.name = "Vortex"; this.targetingMode = TargetingMode.AOE_SELF; this.maxRange = 15.0f; diff --git a/src/main/java/noppes/npcs/client/gui/advanced/GuiNPCAbilities.java b/src/main/java/noppes/npcs/client/gui/advanced/GuiNPCAbilities.java index 900144ec2..584bd8238 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/GuiNPCAbilities.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/GuiNPCAbilities.java @@ -17,6 +17,7 @@ import noppes.npcs.entity.EntityNPCInterface; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.UUID; import java.util.Vector; /** @@ -31,6 +32,9 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC // All available ability types (typeId -> index) private final HashMap allAbilityTypes = new HashMap<>(); + // Display name to typeId mapping for the available types scroll + private final HashMap displayNameToTypeId = new HashMap<>(); + // NPC's current abilities private final List npcAbilities = new ArrayList<>(); @@ -131,18 +135,20 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC if (id == 70) { if (availableTypesScroll.hasSelected()) { String displayName = availableTypesScroll.getSelected(); - String typeId = getTypeIdFromDisplayName(displayName); - Ability newAbility = AbilityController.Instance.create(typeId); - if (newAbility != null) { - newAbility.setId("ability_" + System.currentTimeMillis()); - // Don't set custom name - let it default to type name - npcAbilities.add(newAbility); - // Auto-select the newly added ability - selectedAbilityIndex = npcAbilities.size() - 1; - updateNpcAbilitiesList(); - selectAbilityByIndex(selectedAbilityIndex); - initGui(); - save(); + String typeId = displayNameToTypeId.get(displayName); + if (typeId != null) { + Ability newAbility = AbilityController.Instance.create(typeId); + if (newAbility != null) { + newAbility.setId(UUID.randomUUID().toString()); + // Don't set custom name - let it default to type name + npcAbilities.add(newAbility); + // Auto-select the newly added ability + selectedAbilityIndex = npcAbilities.size() - 1; + updateNpcAbilitiesList(); + selectAbilityByIndex(selectedAbilityIndex); + initGui(); + save(); + } } } return; @@ -274,27 +280,18 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC private List getFilteredTypeList() { List list = new ArrayList<>(); + displayNameToTypeId.clear(); for (String typeId : allAbilityTypes.keySet()) { - String displayName = getDisplayName(typeId); - if (search.isEmpty() || typeId.toLowerCase().contains(search) || displayName.toLowerCase().contains(search)) { + String displayName = I18n.format(typeId); + // Search matches either the display name or the typeId + if (search.isEmpty() || displayName.toLowerCase().contains(search) || typeId.toLowerCase().contains(search)) { list.add(displayName); + displayNameToTypeId.put(displayName, typeId); } } return list; } - /** - * Gets the typeId from a display name shown in the available types list. - */ - private String getTypeIdFromDisplayName(String displayName) { - for (String typeId : allAbilityTypes.keySet()) { - if (getDisplayName(typeId).equals(displayName)) { - return typeId; - } - } - return displayName; - } - private void updateNpcAbilitiesList() { List list = new ArrayList<>(); for (int i = 0; i < npcAbilities.size(); i++) { @@ -335,35 +332,10 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC /** * Gets the localized display name for an ability type. - * Uses lang key "ability.type.cnpc_slam" for "cnpc:slam" + * The typeId IS the lang key (e.g., "ability.cnpc.slam"). */ private String getDisplayName(String typeId) { - // Convert "cnpc:slam" to lang key "ability.type.cnpc_slam" - String langKey = "ability.type." + typeId.replace(":", "_"); - String translated = I18n.format(langKey); - - // If translation exists and is different from key, use it - if (!translated.equals(langKey)) { - return translated; - } - - // Fallback: Convert "cnpc:slam" to "Slam" - if (typeId.contains(":")) { - String name = typeId.substring(typeId.indexOf(":") + 1); - name = name.replace("_", " "); - StringBuilder sb = new StringBuilder(); - for (String word : name.split(" ")) { - if (word.length() > 0) { - sb.append(Character.toUpperCase(word.charAt(0))); - if (word.length() > 1) { - sb.append(word.substring(1)); - } - sb.append(" "); - } - } - return sb.toString().trim(); - } - return typeId; + return I18n.format(typeId); } public void save() { @@ -386,7 +358,7 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC */ public void loadAbility(Ability loadedAbility) { if (loadedAbility != null) { - loadedAbility.setId("ability_" + System.currentTimeMillis()); + loadedAbility.setId(UUID.randomUUID().toString()); npcAbilities.add(loadedAbility); // Auto-select the newly added ability selectedAbilityIndex = npcAbilities.size() - 1; diff --git a/src/main/java/noppes/npcs/client/gui/advanced/SubGuiAbilityConfig.java b/src/main/java/noppes/npcs/client/gui/advanced/SubGuiAbilityConfig.java index b5d31d70f..6d12693bb 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/SubGuiAbilityConfig.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/SubGuiAbilityConfig.java @@ -1,23 +1,28 @@ package noppes.npcs.client.gui.advanced; import kamkeel.npcs.controllers.data.ability.Ability; +import kamkeel.npcs.controllers.data.ability.Condition; import kamkeel.npcs.controllers.data.ability.TargetingMode; import kamkeel.npcs.controllers.data.ability.telegraph.TelegraphType; import net.minecraft.client.gui.GuiButton; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.StatCollector; import noppes.npcs.client.gui.SubGuiColorSelector; import noppes.npcs.client.gui.select.GuiAnimationSelection; import noppes.npcs.client.gui.select.GuiSoundSelection; import noppes.npcs.client.gui.util.*; +import java.util.ArrayList; +import java.util.List; + /** * Base SubGui for editing ability configuration with tabbed interface. * Uses GuiMenuTopButton for navigation tabs. * * Tabs: - * - General: Type ID, Name, Weight, Lock Movement, Interruptible, Timing (Windup/Active/Recovery/Cooldown) + * - General: Name, Weight, Lock Movement, Interruptible, Timing * - Type: Type-specific settings per Ability (override in subclasses) - * - Target: Min/Max Range, Targeting Mode, Conditions + * - Target: Min/Max Range, Targeting Mode, Conditions (up to 3) * - Effects: Sounds, Animations, Telegraph settings, Colors * * Subclasses should override initTypeTab() and handleTypeButton()/handleTypeTextField() @@ -57,6 +62,7 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi protected float minRange; protected float maxRange; protected TargetingMode targetingMode; + protected List conditions; // ═══════════════════════════════════════════════════════════════════════════ // CACHED VALUES - Effects Tab @@ -77,6 +83,7 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi protected int editingColorId = 0; protected int editingSoundId = 0; protected int editingAnimationId = 0; + protected int editingConditionIndex = -1; // ═══════════════════════════════════════════════════════════════════════════ // ABILITY TYPE FEATURES @@ -106,6 +113,7 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi this.minRange = ability.getMinRange(); this.maxRange = ability.getMaxRange(); this.targetingMode = ability.getTargetingMode(); + this.conditions = new ArrayList<>(ability.getConditions()); // Effects this.windUpSound = ability.getWindUpSound(); @@ -125,8 +133,8 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi this.hasTypeSettings = ability.hasTypeSettings(); setBackground("menubg.png"); - xSize = 420; - ySize = 216; + xSize = 356; + ySize = 200; } @Override @@ -158,11 +166,11 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi effectsTab.active = (activeTab == TAB_EFFECTS); addTopButton(effectsTab); - // Close button on top right - GuiMenuTopButton closeBtn = new GuiMenuTopButton(67, guiLeft + xSize - 22, guiTop - 17, "X"); + // Close button (X) in top menu bar - use -1000 to avoid any ID conflicts + GuiMenuTopButton closeBtn = new GuiMenuTopButton(-1000, guiLeft + xSize - 22, guiTop - 17, "X"); addTopButton(closeBtn); - int contentY = guiTop + 4; + int contentY = guiTop + 5; // ═══════════════════════════════════════════════════════════════════════ // TAB CONTENT @@ -183,70 +191,66 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi } // ═══════════════════════════════════════════════════════════════════════ - // BOTTOM ROW - Enabled toggle and Done button + // BOTTOM ROW - Enabled toggle // ═══════════════════════════════════════════════════════════════════════ - addLabel(new GuiNpcLabel(99, "gui.enabled", guiLeft + 8, guiTop + ySize - 19)); - GuiNpcButton enabledBtn = new GuiNpcButton(2, guiLeft + 55, guiTop + ySize - 24, 50, 20, new String[]{"gui.no", "gui.yes"}, enabled ? 1 : 0); + addLabel(new GuiNpcLabel(99, "gui.enabled", guiLeft + 8, guiTop + ySize - 18)); + GuiNpcButton enabledBtn = new GuiNpcButton(2, guiLeft + 55, guiTop + ySize - 24, 40, 20, new String[]{"gui.no", "gui.yes"}, enabled ? 1 : 0); enabledBtn.setTextColor(enabled ? 0x00FF00 : 0xFF0000); addButton(enabledBtn); - - addButton(new GuiNpcButton(66, guiLeft + xSize - 65, guiTop + ySize - 24, 60, 20, "gui.done")); } // ═══════════════════════════════════════════════════════════════════════════ // GENERAL TAB - // Type ID (label), Name, Weight, Lock Movement, Interruptible, - // Ticks: Windup, Active, Recovery, Cooldown // ═══════════════════════════════════════════════════════════════════════════ private void initGeneralTab(int startY) { int y = startY; int col1LabelX = guiLeft + 8; - int col1FieldX = guiLeft + 75; - int col2LabelX = guiLeft + 215; - int col2FieldX = guiLeft + 290; + int col1FieldX = guiLeft + 70; + int col2LabelX = guiLeft + 180; + int col2FieldX = guiLeft + 248; - // Row 1: Type ID (read-only) + Name - addLabel(new GuiNpcLabel(1, "ability.typeId", col1LabelX, y + 5)); + // Row 1: Type (read-only) + Name + addLabel(new GuiNpcLabel(1, "gui.type", col1LabelX, y + 5)); addLabel(new GuiNpcLabel(2, ability.getTypeId(), col1FieldX, y + 5)); addLabel(new GuiNpcLabel(3, "gui.name", col2LabelX, y + 5)); - GuiNpcTextField nameField = new GuiNpcTextField(1, this, fontRendererObj, col2FieldX, y, 120, 20, name); + GuiNpcTextField nameField = new GuiNpcTextField(1, this, fontRendererObj, col2FieldX, y, 100, 20, name); addTextField(nameField); y += 24; // Row 2: Weight + Lock Movement addLabel(new GuiNpcLabel(4, "ability.weight", col1LabelX, y + 5)); - GuiNpcTextField weightField = new GuiNpcTextField(3, this, fontRendererObj, col1FieldX, y, 50, 20, String.valueOf(weight)); + GuiNpcTextField weightField = new GuiNpcTextField(3, this, fontRendererObj, col1FieldX, y, 40, 20, String.valueOf(weight)); weightField.setIntegersOnly(); weightField.setMinMaxDefault(1, 1000, 10); addTextField(weightField); addLabel(new GuiNpcLabel(5, "ability.lockMove", col2LabelX, y + 5)); - addButton(new GuiNpcButton(16, col2FieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, lockMovement ? 1 : 0)); + addButton(new GuiNpcButton(16, col2FieldX, y, 40, 20, new String[]{"gui.no", "gui.yes"}, lockMovement ? 1 : 0)); y += 24; - // Row 3: Interruptible (no threshold anymore - just a toggle) + // Row 3: Interruptible addLabel(new GuiNpcLabel(6, "ability.interruptible", col1LabelX, y + 5)); - addButton(new GuiNpcButton(14, col1FieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, interruptible ? 1 : 0)); + addButton(new GuiNpcButton(14, guiLeft + 85, y, 40, 20, new String[]{"gui.no", "gui.yes"}, interruptible ? 1 : 0)); - y += 30; + y += 28; // Separator - Timing section header - addLabel(new GuiNpcLabel(7, "§n" + "ability.timing", col1LabelX, y)); + addLabel(new GuiNpcLabel(7, "ability.timing", col1LabelX, y)); y += 14; // Row 4: Windup Ticks + Active Ticks addLabel(new GuiNpcLabel(10, "ability.windup", col1LabelX, y + 5)); - GuiNpcTextField windupField = new GuiNpcTextField(11, this, fontRendererObj, col1FieldX, y, 50, 20, String.valueOf(windUpTicks)); + GuiNpcTextField windupField = new GuiNpcTextField(11, this, fontRendererObj, col1FieldX, y, 40, 20, String.valueOf(windUpTicks)); windupField.setIntegersOnly(); windupField.setMinMaxDefault(0, 1000, 20); addTextField(windupField); addLabel(new GuiNpcLabel(11, "ability.active", col2LabelX, y + 5)); - GuiNpcTextField activeField = new GuiNpcTextField(12, this, fontRendererObj, col2FieldX, y, 50, 20, String.valueOf(activeTicks)); + GuiNpcTextField activeField = new GuiNpcTextField(12, this, fontRendererObj, col2FieldX, y, 40, 20, String.valueOf(activeTicks)); activeField.setIntegersOnly(); activeField.setMinMaxDefault(1, 1000, 10); addTextField(activeField); @@ -255,13 +259,13 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi // Row 5: Recovery Ticks + Cooldown Ticks addLabel(new GuiNpcLabel(12, "ability.recovery", col1LabelX, y + 5)); - GuiNpcTextField recoveryField = new GuiNpcTextField(13, this, fontRendererObj, col1FieldX, y, 50, 20, String.valueOf(recoveryTicks)); + GuiNpcTextField recoveryField = new GuiNpcTextField(13, this, fontRendererObj, col1FieldX, y, 40, 20, String.valueOf(recoveryTicks)); recoveryField.setIntegersOnly(); recoveryField.setMinMaxDefault(0, 1000, 20); addTextField(recoveryField); addLabel(new GuiNpcLabel(13, "ability.cooldown", col2LabelX, y + 5)); - GuiNpcTextField cooldownField = new GuiNpcTextField(10, this, fontRendererObj, col2FieldX, y, 50, 20, String.valueOf(cooldownTicks)); + GuiNpcTextField cooldownField = new GuiNpcTextField(10, this, fontRendererObj, col2FieldX, y, 40, 20, String.valueOf(cooldownTicks)); cooldownField.setIntegersOnly(); cooldownField.setMinMaxDefault(0, 10000, 100); addTextField(cooldownField); @@ -301,25 +305,24 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi // ═══════════════════════════════════════════════════════════════════════════ // TARGET TAB - // Min/Max Range, Targeting Mode, Conditions // ═══════════════════════════════════════════════════════════════════════════ private void initTargetTab(int startY) { int y = startY; int col1LabelX = guiLeft + 8; - int col1FieldX = guiLeft + 85; - int col2LabelX = guiLeft + 215; - int col2FieldX = guiLeft + 290; + int col1FieldX = guiLeft + 70; + int col2LabelX = guiLeft + 180; + int col2FieldX = guiLeft + 248; // Row 1: Min Range + Max Range addLabel(new GuiNpcLabel(20, "ability.minRange", col1LabelX, y + 5)); - GuiNpcTextField minRangeField = new GuiNpcTextField(5, this, fontRendererObj, col1FieldX, y, 50, 20, String.valueOf((int) minRange)); + GuiNpcTextField minRangeField = new GuiNpcTextField(5, this, fontRendererObj, col1FieldX, y, 40, 20, String.valueOf((int) minRange)); minRangeField.setIntegersOnly(); minRangeField.setMinMaxDefault(0, 100, 0); addTextField(minRangeField); addLabel(new GuiNpcLabel(21, "ability.maxRange", col2LabelX, y + 5)); - GuiNpcTextField maxRangeField = new GuiNpcTextField(6, this, fontRendererObj, col2FieldX, y, 50, 20, String.valueOf((int) maxRange)); + GuiNpcTextField maxRangeField = new GuiNpcTextField(6, this, fontRendererObj, col2FieldX, y, 40, 20, String.valueOf((int) maxRange)); maxRangeField.setIntegersOnly(); maxRangeField.setMinMaxDefault(1, 100, 20); addTextField(maxRangeField); @@ -331,21 +334,67 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi if (!targetingModeLocked) { String[] targetingModes = getAvailableTargetingModes(); int selectedIndex = getTargetingModeIndex(targetingMode); - addButton(new GuiNpcButton(4, col1FieldX, y, 100, 20, targetingModes, selectedIndex)); + addButton(new GuiNpcButton(4, col1FieldX, y, 90, 20, targetingModes, selectedIndex)); } else { - // Show as label if locked String modeName = "ability.target." + targetingMode.name().toLowerCase(); addLabel(new GuiNpcLabel(23, modeName, col1FieldX, y + 5)); } - y += 30; + y += 28; - // Separator - Conditions section header - addLabel(new GuiNpcLabel(24, "§n" + "ability.conditions", col1LabelX, y)); + // ───────────────────────────────────────────────────────────────────── + // CONDITIONS SECTION (up to 3) + // ───────────────────────────────────────────────────────────────────── + addLabel(new GuiNpcLabel(24, "ability.conditions", col1LabelX, y)); y += 14; - // TODO: Add conditions UI here - addLabel(new GuiNpcLabel(25, "ability.conditionsNote", col1LabelX, y + 5)); + // Display existing conditions (similar to Marks pattern) + for (int i = 0; i < conditions.size() && i < 3; i++) { + Condition cond = conditions.get(i); + String condName = getConditionDisplayName(cond); + + // Condition type button + addButton(new GuiNpcButton(50 + i * 10, col1LabelX, y, 140, 20, condName)); + + // Edit button + addButton(new GuiNpcButton(51 + i * 10, col1LabelX + 145, y, 40, 20, "gui.edit")); + + // Delete button + addButton(new GuiNpcButton(52 + i * 10, col1LabelX + 190, y, 20, 20, "X")); + + y += 22; + } + + // Add button (if less than 3 conditions) + if (conditions.size() < 3) { + addButton(new GuiNpcButton(80, col1LabelX, y, 50, 20, "gui.add")); + } + } + + private String getConditionDisplayName(Condition cond) { + if (cond == null) return "None"; + String typeId = cond.getTypeId(); + switch (typeId) { + case "hp_above": + return StatCollector.translateToLocal("condition.hp_above") + " " + (int)(getConditionThreshold(cond) * 100) + "%"; + case "hp_below": + return StatCollector.translateToLocal("condition.hp_below") + " " + (int)(getConditionThreshold(cond) * 100) + "%"; + case "target_hp_above": + return StatCollector.translateToLocal("condition.target_hp_above") + " " + (int)(getConditionThreshold(cond) * 100) + "%"; + case "target_hp_below": + return StatCollector.translateToLocal("condition.target_hp_below") + " " + (int)(getConditionThreshold(cond) * 100) + "%"; + case "hit_count": + Condition.ConditionHitCount hitCount = (Condition.ConditionHitCount) cond; + return StatCollector.translateToLocal("condition.hit_count") + ": " + hitCount.getRequiredHits() + "/" + hitCount.getWithinTicks() + "t"; + default: + return typeId; + } + } + + private float getConditionThreshold(Condition cond) { + // Read threshold from NBT since inner classes don't expose it + NBTTagCompound nbt = cond.writeNBT(); + return nbt.hasKey("threshold") ? nbt.getFloat("threshold") : 0.5f; } private String[] getAvailableTargetingModes() { @@ -373,85 +422,85 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi // ═══════════════════════════════════════════════════════════════════════════ // EFFECTS TAB - // Sounds, Animations, Telegraph, Colors // ═══════════════════════════════════════════════════════════════════════════ private void initEffectsTab(int startY) { int y = startY; int col1LabelX = guiLeft + 8; - int col1FieldX = guiLeft + 100; - int col1ClearX = guiLeft + 185; - int col2LabelX = guiLeft + 215; - int col2FieldX = guiLeft + 290; + int col1FieldX = guiLeft + 85; + int col1ClearX = guiLeft + 160; + int col2LabelX = guiLeft + 185; + int col2FieldX = guiLeft + 255; // ───────────────────────────────────────────────────────────────────── // SOUNDS SECTION // ───────────────────────────────────────────────────────────────────── - addLabel(new GuiNpcLabel(30, "§n" + "ability.sounds", col1LabelX, y)); + addLabel(new GuiNpcLabel(30, "ability.sounds", col1LabelX, y)); y += 14; // Wind Up Sound addLabel(new GuiNpcLabel(31, "ability.windUpSound", col1LabelX, y + 5)); - String windUpSoundDisplay = windUpSound != null && !windUpSound.isEmpty() ? truncateString(windUpSound, 12) : "None"; - addButton(new GuiNpcButton(30, col1FieldX, y, 80, 20, windUpSoundDisplay)); + String windUpSoundDisplay = windUpSound != null && !windUpSound.isEmpty() ? truncateString(windUpSound, 10) : StatCollector.translateToLocal("gui.none"); + addButton(new GuiNpcButton(30, col1FieldX, y, 70, 20, windUpSoundDisplay)); addButton(new GuiNpcButton(35, col1ClearX, y, 20, 20, "X")); // Active Sound addLabel(new GuiNpcLabel(32, "ability.activeSound", col2LabelX, y + 5)); - String activeSoundDisplay = activeSound != null && !activeSound.isEmpty() ? truncateString(activeSound, 12) : "None"; - addButton(new GuiNpcButton(31, col2FieldX, y, 80, 20, activeSoundDisplay)); - addButton(new GuiNpcButton(36, col2FieldX + 85, y, 20, 20, "X")); + String activeSoundDisplay = activeSound != null && !activeSound.isEmpty() ? truncateString(activeSound, 10) : StatCollector.translateToLocal("gui.none"); + addButton(new GuiNpcButton(31, col2FieldX, y, 70, 20, activeSoundDisplay)); + addButton(new GuiNpcButton(36, col2FieldX + 75, y, 20, 20, "X")); - y += 28; + y += 26; // ───────────────────────────────────────────────────────────────────── // ANIMATIONS SECTION // ───────────────────────────────────────────────────────────────────── - addLabel(new GuiNpcLabel(33, "§n" + "ability.animations", col1LabelX, y)); + addLabel(new GuiNpcLabel(33, "ability.animations", col1LabelX, y)); y += 14; // Wind Up Animation addLabel(new GuiNpcLabel(34, "ability.windUpAnim", col1LabelX, y + 5)); String windUpAnimName = getAnimationName(windUpAnimationId, true); - addButton(new GuiNpcButton(32, col1FieldX, y, 80, 20, windUpAnimName)); + addButton(new GuiNpcButton(32, col1FieldX, y, 70, 20, windUpAnimName)); addButton(new GuiNpcButton(37, col1ClearX, y, 20, 20, "X")); // Active Animation addLabel(new GuiNpcLabel(35, "ability.activeAnim", col2LabelX, y + 5)); String activeAnimName = getAnimationName(activeAnimationId, false); - addButton(new GuiNpcButton(33, col2FieldX, y, 80, 20, activeAnimName)); - addButton(new GuiNpcButton(38, col2FieldX + 85, y, 20, 20, "X")); + addButton(new GuiNpcButton(33, col2FieldX, y, 70, 20, activeAnimName)); + addButton(new GuiNpcButton(38, col2FieldX + 75, y, 20, 20, "X")); - y += 28; + y += 26; // ───────────────────────────────────────────────────────────────────── // TELEGRAPH SECTION (only if supported) // ───────────────────────────────────────────────────────────────────── if (supportsTelegraph) { - addLabel(new GuiNpcLabel(40, "§n" + "ability.telegraph", col1LabelX, y)); + addLabel(new GuiNpcLabel(40, "ability.telegraph", col1LabelX, y)); y += 14; - // Show Telegraph + Type + // Show Telegraph addLabel(new GuiNpcLabel(41, "ability.showTelegraph", col1LabelX, y + 5)); - addButton(new GuiNpcButton(20, col1FieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, showTelegraph ? 1 : 0)); + addButton(new GuiNpcButton(20, guiLeft + 95, y, 40, 20, new String[]{"gui.no", "gui.yes"}, showTelegraph ? 1 : 0)); + // Telegraph Type (separate column) String typeKey = ability.getTelegraphType().name().toLowerCase(); - addLabel(new GuiNpcLabel(42, "ability.telegraphType", col2LabelX, y + 5)); - addLabel(new GuiNpcLabel(43, "ability.telegraph." + typeKey, col2FieldX, y + 5)); + addLabel(new GuiNpcLabel(42, "ability.telegraphType", guiLeft + 200, y + 5)); + addLabel(new GuiNpcLabel(43, "ability.telegraph." + typeKey, guiLeft + 280, y + 5)); y += 24; // Colors addLabel(new GuiNpcLabel(44, "ability.windUpColor", col1LabelX, y + 5)); String windUpHex = String.format("%06X", windUpColor & 0xFFFFFF); - GuiNpcButton windUpColorBtn = new GuiNpcButton(22, col1FieldX, y, 60, 20, windUpHex); + GuiNpcButton windUpColorBtn = new GuiNpcButton(22, guiLeft + 95, y, 55, 20, windUpHex); windUpColorBtn.setEnabled(showTelegraph); windUpColorBtn.setTextColor(windUpColor & 0xFFFFFF); addButton(windUpColorBtn); - addLabel(new GuiNpcLabel(45, "ability.activeColor", col2LabelX, y + 5)); + addLabel(new GuiNpcLabel(45, "ability.activeColor", guiLeft + 200, y + 5)); String activeHex = String.format("%06X", activeColor & 0xFFFFFF); - GuiNpcButton activeColorBtn = new GuiNpcButton(24, col2FieldX, y, 60, 20, activeHex); + GuiNpcButton activeColorBtn = new GuiNpcButton(24, guiLeft + 280, y, 55, 20, activeHex); activeColorBtn.setEnabled(showTelegraph); activeColorBtn.setTextColor(activeColor & 0xFFFFFF); addButton(activeColorBtn); @@ -469,10 +518,10 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi } private String getAnimationName(int animId, boolean isWindUp) { - if (animId < 0) return "None"; + if (animId < 0) return StatCollector.translateToLocal("gui.none"); String cachedName = isWindUp ? windUpAnimationName : activeAnimationName; if (cachedName != null && !cachedName.isEmpty()) { - return truncateString(cachedName, 10); + return truncateString(cachedName, 8); } return "ID: " + animId; } @@ -532,6 +581,39 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi } } + // Close button (X in top menu) - use -1000 to avoid any ID conflicts + else if (id == -1000) { + close(); + return; + } + + // Target tab - Condition buttons (50-79) + else if (id >= 50 && id < 80) { + int condIndex = (id - 50) / 10; + int action = (id - 50) % 10; + + if (action == 0 || action == 1) { + // Click on condition name or Edit button - open edit subgui + if (condIndex < conditions.size()) { + editingConditionIndex = condIndex; + setSubGui(new SubGuiConditionEdit(conditions.get(condIndex))); + } + } else if (action == 2) { + // Delete button + if (condIndex < conditions.size()) { + conditions.remove(condIndex); + initGui(); + } + } + } + // Add condition button + else if (id == 80) { + if (conditions.size() < 3) { + editingConditionIndex = conditions.size(); + setSubGui(new SubGuiConditionEdit(null)); + } + } + // Effects tab - Telegraph else if (id == 20) { showTelegraph = ((GuiNpcButton) guibutton).getValue() == 1; @@ -589,17 +671,6 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi else if (id >= 100) { handleTypeButton(id, (GuiNpcButton) guibutton); } - - // Done button - else if (id == 66) { - applyToAbility(); - callback.onAbilitySaved(ability); - close(); - } - // Close button (X in top right) - else if (id == 67) { - close(); - } } // ═══════════════════════════════════════════════════════════════════════════ @@ -680,9 +751,37 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi } editingAnimationId = 0; initGui(); + } else if (subgui instanceof SubGuiConditionEdit) { + SubGuiConditionEdit condEdit = (SubGuiConditionEdit) subgui; + Condition result = condEdit.getResult(); + if (result != null && editingConditionIndex >= 0) { + if (editingConditionIndex < conditions.size()) { + conditions.set(editingConditionIndex, result); + } else { + conditions.add(result); + } + } + editingConditionIndex = -1; + initGui(); } } + // ═══════════════════════════════════════════════════════════════════════════ + // CLOSE - Save before closing + // ═══════════════════════════════════════════════════════════════════════════ + + @Override + public void close() { + // Apply all cached values to the ability before closing + applyToAbility(); + + // Notify callback that ability was saved + callback.onAbilitySaved(ability); + + // Close the GUI + super.close(); + } + // ═══════════════════════════════════════════════════════════════════════════ // APPLY TO ABILITY // ═══════════════════════════════════════════════════════════════════════════ @@ -706,6 +805,12 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi ability.setMaxRange(maxRange); ability.setTargetingMode(targetingMode); + // Conditions + ability.getConditions().clear(); + for (Condition c : conditions) { + ability.addCondition(c); + } + // Effects ability.setWindUpSound(windUpSound); ability.setActiveSound(activeSound); @@ -747,6 +852,7 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi this.minRange = ability.getMinRange(); this.maxRange = ability.getMaxRange(); this.targetingMode = ability.getTargetingMode(); + this.conditions = new ArrayList<>(ability.getConditions()); this.showTelegraph = ability.isShowTelegraph(); this.windUpColor = ability.getWindUpColor(); diff --git a/src/main/java/noppes/npcs/client/gui/advanced/SubGuiConditionEdit.java b/src/main/java/noppes/npcs/client/gui/advanced/SubGuiConditionEdit.java new file mode 100644 index 000000000..f0d4f2734 --- /dev/null +++ b/src/main/java/noppes/npcs/client/gui/advanced/SubGuiConditionEdit.java @@ -0,0 +1,181 @@ +package noppes.npcs.client.gui.advanced; + +import kamkeel.npcs.controllers.data.ability.Condition; +import net.minecraft.client.gui.GuiButton; +import noppes.npcs.client.gui.util.*; + +/** + * SubGui for editing a single ability condition. + * Allows selecting condition type and configuring its parameters. + */ +public class SubGuiConditionEdit extends SubGuiInterface implements ITextfieldListener { + + // Condition types + private static final String[] CONDITION_TYPES = { + "condition.hp_above", + "condition.hp_below", + "condition.target_hp_above", + "condition.target_hp_below", + "condition.hit_count" + }; + + private static final String[] CONDITION_TYPE_IDS = { + "hp_above", + "hp_below", + "target_hp_above", + "target_hp_below", + "hit_count" + }; + + // Current condition being edited + private Condition condition; + private Condition result; + + // State + private int selectedTypeIndex = 0; + private float threshold = 0.5f; // For HP conditions (0.0-1.0) + private int requiredHits = 3; // For hit_count + private int withinTicks = 60; // For hit_count + + public SubGuiConditionEdit(Condition existing) { + this.condition = existing; + this.result = null; + + if (existing != null) { + String typeId = existing.getTypeId(); + for (int i = 0; i < CONDITION_TYPE_IDS.length; i++) { + if (CONDITION_TYPE_IDS[i].equals(typeId)) { + selectedTypeIndex = i; + break; + } + } + loadFromCondition(existing); + } + + setBackground("menubg.png"); + xSize = 220; + ySize = 140; + } + + private void loadFromCondition(Condition cond) { + String typeId = cond.getTypeId(); + if (typeId.equals("hit_count")) { + Condition.ConditionHitCount hitCount = (Condition.ConditionHitCount) cond; + requiredHits = hitCount.getRequiredHits(); + withinTicks = hitCount.getWithinTicks(); + } else { + // HP-based conditions + net.minecraft.nbt.NBTTagCompound nbt = cond.writeNBT(); + threshold = nbt.hasKey("threshold") ? nbt.getFloat("threshold") : 0.5f; + } + } + + @Override + public void initGui() { + super.initGui(); + + int y = guiTop + 8; + int labelX = guiLeft + 8; + int fieldX = guiLeft + 90; + + // Title + addLabel(new GuiNpcLabel(0, "condition.edit", labelX, y)); + y += 18; + + // Condition Type selector + addLabel(new GuiNpcLabel(1, "gui.type", labelX, y + 5)); + addButton(new GuiNpcButton(1, fieldX, y, 115, 20, CONDITION_TYPES, selectedTypeIndex)); + y += 26; + + // Type-specific fields + String typeId = CONDITION_TYPE_IDS[selectedTypeIndex]; + if (typeId.equals("hit_count")) { + // Hit count fields + addLabel(new GuiNpcLabel(2, "condition.hits", labelX, y + 5)); + GuiNpcTextField hitsField = new GuiNpcTextField(2, this, fontRendererObj, fieldX, y, 40, 20, String.valueOf(requiredHits)); + hitsField.setIntegersOnly(); + hitsField.setMinMaxDefault(1, 100, 3); + addTextField(hitsField); + y += 24; + + addLabel(new GuiNpcLabel(3, "condition.within", labelX, y + 5)); + GuiNpcTextField ticksField = new GuiNpcTextField(3, this, fontRendererObj, fieldX, y, 40, 20, String.valueOf(withinTicks)); + ticksField.setIntegersOnly(); + ticksField.setMinMaxDefault(1, 1200, 60); + addTextField(ticksField); + } else { + // HP threshold field (as percentage) + addLabel(new GuiNpcLabel(2, "condition.percent", labelX, y + 5)); + int percent = (int)(threshold * 100); + GuiNpcTextField thresholdField = new GuiNpcTextField(4, this, fontRendererObj, fieldX, y, 40, 20, String.valueOf(percent)); + thresholdField.setIntegersOnly(); + thresholdField.setMinMaxDefault(1, 99, 50); + addTextField(thresholdField); + addLabel(new GuiNpcLabel(4, "%", fieldX + 45, y + 5)); + } + + // Bottom buttons + addButton(new GuiNpcButton(10, guiLeft + 8, guiTop + ySize - 28, 60, 20, "gui.cancel")); + addButton(new GuiNpcButton(11, guiLeft + xSize - 68, guiTop + ySize - 28, 60, 20, "gui.done")); + } + + @Override + public void buttonEvent(GuiButton guibutton) { + int id = guibutton.id; + + if (id == 1) { + // Type changed + selectedTypeIndex = ((GuiNpcButton) guibutton).getValue(); + initGui(); + } else if (id == 10) { + // Cancel - close without saving + result = null; + close(); + } else if (id == 11) { + // Done - create condition and close + result = createCondition(); + close(); + } + } + + @Override + public void unFocused(GuiNpcTextField textField) { + int id = textField.id; + + if (id == 2) { + requiredHits = textField.getInteger(); + } else if (id == 3) { + withinTicks = textField.getInteger(); + } else if (id == 4) { + int percent = textField.getInteger(); + threshold = percent / 100.0f; + } + } + + private Condition createCondition() { + String typeId = CONDITION_TYPE_IDS[selectedTypeIndex]; + + switch (typeId) { + case "hp_above": + return new Condition.ConditionHPAbove(threshold); + case "hp_below": + return new Condition.ConditionHPBelow(threshold); + case "target_hp_above": + return new Condition.ConditionTargetHPAbove(threshold); + case "target_hp_below": + return new Condition.ConditionTargetHPBelow(threshold); + case "hit_count": + return new Condition.ConditionHitCount(requiredHits, withinTicks); + default: + return null; + } + } + + /** + * Get the resulting condition after dialog closes. + * Returns null if cancelled or no valid condition. + */ + public Condition getResult() { + return result; + } +} diff --git a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityBeam.java b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityBeam.java index 1cf699aa8..e951e5fbd 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityBeam.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityBeam.java @@ -1,7 +1,7 @@ package noppes.npcs.client.gui.advanced.ability; import kamkeel.npcs.controllers.data.ability.type.AbilityBeam; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.util.GuiNpcButton; import noppes.npcs.client.gui.util.GuiNpcLabel; diff --git a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityCharge.java b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityCharge.java index d926ebe0f..009cf0efc 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityCharge.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityCharge.java @@ -1,7 +1,7 @@ package noppes.npcs.client.gui.advanced.ability; import kamkeel.npcs.controllers.data.ability.type.AbilityCharge; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.util.GuiNpcLabel; import noppes.npcs.client.gui.util.GuiNpcTextField; diff --git a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityCutter.java b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityCutter.java index b7bf6e1fc..965becf29 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityCutter.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityCutter.java @@ -1,7 +1,7 @@ package noppes.npcs.client.gui.advanced.ability; import kamkeel.npcs.controllers.data.ability.type.AbilityCutter; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.util.GuiNpcButton; import noppes.npcs.client.gui.util.GuiNpcLabel; diff --git a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityDash.java b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityDash.java index d4efd7adc..2d0d5c33a 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityDash.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityDash.java @@ -1,7 +1,7 @@ package noppes.npcs.client.gui.advanced.ability; import kamkeel.npcs.controllers.data.ability.type.AbilityDash; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.util.GuiNpcButton; import noppes.npcs.client.gui.util.GuiNpcLabel; diff --git a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityGuard.java b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityGuard.java index 76dcc009a..009b21755 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityGuard.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityGuard.java @@ -1,7 +1,7 @@ package noppes.npcs.client.gui.advanced.ability; import kamkeel.npcs.controllers.data.ability.type.AbilityGuard; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.util.GuiNpcButton; import noppes.npcs.client.gui.util.GuiNpcLabel; diff --git a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityHazard.java b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityHazard.java index e7f70941b..def67e71d 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityHazard.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityHazard.java @@ -1,7 +1,7 @@ package noppes.npcs.client.gui.advanced.ability; import kamkeel.npcs.controllers.data.ability.type.AbilityHazard; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.util.GuiNpcButton; import noppes.npcs.client.gui.util.GuiNpcLabel; diff --git a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityHeal.java b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityHeal.java index e0acdfec9..365460672 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityHeal.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityHeal.java @@ -1,7 +1,7 @@ package noppes.npcs.client.gui.advanced.ability; import kamkeel.npcs.controllers.data.ability.type.AbilityHeal; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.util.GuiNpcButton; import noppes.npcs.client.gui.util.GuiNpcLabel; diff --git a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityHeavyHit.java b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityHeavyHit.java index d29861f00..e569b9baf 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityHeavyHit.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityHeavyHit.java @@ -1,7 +1,7 @@ package noppes.npcs.client.gui.advanced.ability; import kamkeel.npcs.controllers.data.ability.type.AbilityHeavyHit; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.util.GuiNpcLabel; import noppes.npcs.client.gui.util.GuiNpcTextField; diff --git a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityOrb.java b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityOrb.java index 066cfc48a..5c82c42f8 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityOrb.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityOrb.java @@ -1,7 +1,7 @@ package noppes.npcs.client.gui.advanced.ability; import kamkeel.npcs.controllers.data.ability.type.AbilityOrb; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.util.GuiNpcButton; import noppes.npcs.client.gui.util.GuiNpcLabel; diff --git a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityProjectile.java b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityProjectile.java index 0bf698103..cbde41b7f 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityProjectile.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityProjectile.java @@ -1,7 +1,7 @@ package noppes.npcs.client.gui.advanced.ability; import kamkeel.npcs.controllers.data.ability.type.AbilityProjectile; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.util.GuiNpcButton; import noppes.npcs.client.gui.util.GuiNpcLabel; diff --git a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityShockwave.java b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityShockwave.java index 2fd0825b5..12342f8ed 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityShockwave.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityShockwave.java @@ -1,7 +1,7 @@ package noppes.npcs.client.gui.advanced.ability; import kamkeel.npcs.controllers.data.ability.type.AbilityShockwave; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.util.GuiNpcButton; import noppes.npcs.client.gui.util.GuiNpcLabel; diff --git a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilitySlam.java b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilitySlam.java index 4486b6e44..5afe2276b 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilitySlam.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilitySlam.java @@ -1,7 +1,7 @@ package noppes.npcs.client.gui.advanced.ability; import kamkeel.npcs.controllers.data.ability.type.AbilitySlam; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.util.GuiNpcButton; import noppes.npcs.client.gui.util.GuiNpcLabel; diff --git a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityTeleport.java b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityTeleport.java index 5a0152fd4..1f6a74ab0 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityTeleport.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityTeleport.java @@ -1,7 +1,7 @@ package noppes.npcs.client.gui.advanced.ability; import kamkeel.npcs.controllers.data.ability.type.AbilityTeleport; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.util.GuiNpcButton; import noppes.npcs.client.gui.util.GuiNpcLabel; diff --git a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityTrap.java b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityTrap.java index e6aa67172..fd1a67bc6 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityTrap.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityTrap.java @@ -1,7 +1,7 @@ package noppes.npcs.client.gui.advanced.ability; import kamkeel.npcs.controllers.data.ability.type.AbilityTrap; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.util.GuiNpcButton; import noppes.npcs.client.gui.util.GuiNpcLabel; diff --git a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityVortex.java b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityVortex.java index c36a6f9f4..6978abce7 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityVortex.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/ability/SubGuiAbilityVortex.java @@ -1,7 +1,7 @@ package noppes.npcs.client.gui.advanced.ability; import kamkeel.npcs.controllers.data.ability.type.AbilityVortex; -import noppes.npcs.client.gui.advanced.IAbilityConfigCallback; +import noppes.npcs.client.gui.util.IAbilityConfigCallback; import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig; import noppes.npcs.client.gui.util.GuiNpcButton; import noppes.npcs.client.gui.util.GuiNpcLabel; diff --git a/src/main/resources/assets/customnpcs/lang/en_US.lang b/src/main/resources/assets/customnpcs/lang/en_US.lang index d487bac93..cd1982f21 100644 --- a/src/main/resources/assets/customnpcs/lang/en_US.lang +++ b/src/main/resources/assets/customnpcs/lang/en_US.lang @@ -1486,21 +1486,21 @@ ability.windUpAnim=Wind Up Anim ability.activeAnim=Active Anim gui.animations=Animations -ability.type.cnpc_slam=Slam -ability.type.cnpc_heavy_hit=Heavy Hit -ability.type.cnpc_cutter=Cutter -ability.type.cnpc_beam=Beam -ability.type.cnpc_projectile=Projectile -ability.type.cnpc_orb=Orb -ability.type.cnpc_charge=Charge -ability.type.cnpc_dash=Dash -ability.type.cnpc_teleport=Teleport -ability.type.cnpc_vortex=Vortex -ability.type.cnpc_shockwave=Shockwave -ability.type.cnpc_guard=Guard -ability.type.cnpc_heal=Heal -ability.type.cnpc_hazard=Hazard -ability.type.cnpc_trap=Trap +ability.cnpc.slam=Slam +ability.cnpc.heavy_hit=Heavy Hit +ability.cnpc.cutter=Cutter +ability.cnpc.beam=Beam +ability.cnpc.projectile=Projectile +ability.cnpc.orb=Orb +ability.cnpc.charge=Charge +ability.cnpc.dash=Dash +ability.cnpc.teleport=Teleport +ability.cnpc.vortex=Vortex +ability.cnpc.shockwave=Shockwave +ability.cnpc.guard=Guard +ability.cnpc.heal=Heal +ability.cnpc.hazard=Hazard +ability.cnpc.trap=Trap # Ability GUI - Type Tab ability.tab.type=Type @@ -1631,3 +1631,22 @@ ability.activeColor=Active Color # Shockwave Settings ability.pushRadius=Push Radius ability.pushStrength=Push Str + +# Ability Config GUI +ability.typeId=Type ID +ability.tab.target=Target +ability.conditions=Conditions +ability.noTypeSettings=No type-specific settings +ability.sounds=Sounds +ability.animations=Animations + +# Conditions +condition.edit=Edit Condition +condition.hp_above=NPC HP Above +condition.hp_below=NPC HP Below +condition.target_hp_above=Target HP Above +condition.target_hp_below=Target HP Below +condition.hit_count=Hit Count +condition.percent=Threshold +condition.hits=Required Hits +condition.within=Within (ticks)