diff --git a/src/main/java/kamkeel/npcs/controllers/AbilityController.java b/src/main/java/kamkeel/npcs/controllers/AbilityController.java index 1c993e818..f226a505c 100644 --- a/src/main/java/kamkeel/npcs/controllers/AbilityController.java +++ b/src/main/java/kamkeel/npcs/controllers/AbilityController.java @@ -1,6 +1,9 @@ package kamkeel.npcs.controllers; import kamkeel.npcs.controllers.data.ability.*; +import kamkeel.npcs.controllers.data.ability.conditions.AbilityCondition; +import kamkeel.npcs.controllers.data.ability.conditions.ConditionHPThreshold; +import kamkeel.npcs.controllers.data.ability.conditions.ConditionHitCount; import kamkeel.npcs.controllers.data.ability.type.AbilityCharge; import kamkeel.npcs.controllers.data.ability.type.AbilityCutter; import kamkeel.npcs.controllers.data.ability.type.AbilityDash; @@ -54,7 +57,7 @@ public class AbilityController implements IAbilityHandler { private final List fieldProviders = new ArrayList<>(); private final List chainedFieldProviders = new ArrayList<>(); private final List extenders = new ArrayList<>(); - private final Map> conditionTypes = new HashMap<>(); + private final Map> conditionTypes = new HashMap<>(); private final List> flightCheckers = new ArrayList<>(); // ── Legacy Migration ───────────────────────────────────────────────────── @@ -147,7 +150,8 @@ public class AbilityController implements IAbilityHandler { } private void registerBuiltinConditionTypes() { - registerCondition(IAbilityCondition.ConditionHPAbove::new); + registerCondition(ConditionHPThreshold::new); + registerCondition(ConditionHitCount::new); } // ═══════════════════════════════════════════════════════════════════════════ @@ -880,8 +884,8 @@ public class AbilityController implements IAbilityHandler { return extenders; } - public void registerCondition(Supplier conditionFactory) { - IAbilityCondition temp = conditionFactory.get(); + public void registerCondition(Supplier conditionFactory) { + AbilityCondition temp = conditionFactory.get(); String typeId = temp.getTypeId(); if (conditionTypes.containsKey(typeId)) { LogWriter.info("AbilityController: Overwriting Condition type: " + typeId); @@ -889,7 +893,7 @@ public class AbilityController implements IAbilityHandler { conditionTypes.put(typeId, conditionFactory); } - public Supplier getConditionType(String key) { + public Supplier getConditionType(String key) { return conditionTypes.get(key); } 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 3563fe892..25cb77747 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/Ability.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/Ability.java @@ -3,6 +3,7 @@ package kamkeel.npcs.controllers.data.ability; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import kamkeel.npcs.controllers.AbilityController; +import kamkeel.npcs.controllers.data.ability.conditions.AbilityCondition; import kamkeel.npcs.controllers.data.telegraph.Telegraph; import kamkeel.npcs.controllers.data.telegraph.TelegraphInstance; import kamkeel.npcs.controllers.data.telegraph.TelegraphType; @@ -58,7 +59,7 @@ public abstract class Ability implements IAbility, IAbilityAction { // Selection protected int weight = 10; protected boolean enabled = true; - protected List conditions = new ArrayList<>(); + protected List conditions = new ArrayList<>(); // Targeting protected TargetingMode targetingMode = TargetingMode.AGGRO_TARGET; @@ -1231,7 +1232,7 @@ public abstract class Ability implements IAbility, IAbilityAction { // ═══════════════════════════════════════════════════════════════════ public boolean checkConditions(EntityLivingBase caster, EntityLivingBase target) { - for (Condition c : conditions) { + for (AbilityCondition c : conditions) { if (!c.check(caster, target)) return false; } return true; @@ -1241,7 +1242,7 @@ public abstract class Ability implements IAbility, IAbilityAction { * Check conditions for a player caster, skipping target-requiring conditions. */ public boolean checkConditionsForPlayer(EntityLivingBase caster) { - for (Condition c : conditions) { + for (AbilityCondition c : conditions) { if (c.requiresTarget()) continue; if (!c.check(caster, null)) return false; } @@ -1310,7 +1311,7 @@ public abstract class Ability implements IAbility, IAbilityAction { // Conditions NBTTagList condList = new NBTTagList(); - for (Condition c : conditions) condList.appendTag(c.writeNBT()); + for (AbilityCondition c : conditions) condList.appendTag(c.writeNBT()); nbt.setTag("conditions", condList); // Effects @@ -1397,7 +1398,7 @@ public abstract class Ability implements IAbility, IAbilityAction { conditions.clear(); NBTTagList condList = nbt.getTagList("conditions", 10); for (int i = 0; i < condList.tagCount(); i++) { - Condition c = Condition.fromNBT(condList.getCompoundTagAt(i)); + AbilityCondition c = AbilityCondition.fromNBT(condList.getCompoundTagAt(i)); if (c != null) conditions.add(c); } @@ -1935,11 +1936,11 @@ public abstract class Ability implements IAbility, IAbilityAction { return customData; } - public List getConditions() { + public List getConditions() { return conditions; } - public void addCondition(Condition c) { + public void addCondition(AbilityCondition c) { conditions.add(c); } diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/ChainedAbility.java b/src/main/java/kamkeel/npcs/controllers/data/ability/ChainedAbility.java index 5de37416e..5a80166c7 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/ChainedAbility.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/ChainedAbility.java @@ -1,6 +1,7 @@ package kamkeel.npcs.controllers.data.ability; import kamkeel.npcs.controllers.AbilityController; +import kamkeel.npcs.controllers.data.ability.conditions.AbilityCondition; import net.minecraft.entity.EntityLivingBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; @@ -57,7 +58,7 @@ public class ChainedAbility implements IChainedAbility, IAbilityAction { /** * Chain-level conditions (individual ability conditions are ignored). */ - private List conditions = new ArrayList<>(); + private List conditions = new ArrayList<>(); /** * Ordered list of ability entries to execute. @@ -185,11 +186,11 @@ public class ChainedAbility implements IChainedAbility, IAbilityAction { return UserType.NPC_ONLY; } - public List getConditions() { + public List getConditions() { return conditions; } - public void setConditions(List conditions) { + public void setConditions(List conditions) { this.conditions = conditions != null ? conditions : new ArrayList<>(); } @@ -279,7 +280,7 @@ public class ChainedAbility implements IChainedAbility, IAbilityAction { * Check all chain-level conditions against the caster and target. */ public boolean checkConditions(EntityLivingBase caster, EntityLivingBase target) { - for (Condition c : conditions) { + for (AbilityCondition c : conditions) { if (!c.check(caster, target)) { return false; } @@ -291,7 +292,7 @@ public class ChainedAbility implements IChainedAbility, IAbilityAction { * Check conditions for player use (skip target-requiring conditions). */ public boolean checkConditionsForPlayer(EntityLivingBase caster) { - for (Condition c : conditions) { + for (AbilityCondition c : conditions) { if (c.requiresTarget()) continue; if (!c.check(caster, null)) { return false; @@ -382,7 +383,7 @@ public class ChainedAbility implements IChainedAbility, IAbilityAction { // Conditions NBTTagList condList = new NBTTagList(); - for (Condition c : conditions) { + for (AbilityCondition c : conditions) { condList.appendTag(c.writeNBT()); } nbt.setTag("Conditions", condList); @@ -416,7 +417,7 @@ public class ChainedAbility implements IChainedAbility, IAbilityAction { conditions.clear(); NBTTagList condList = nbt.getTagList("Conditions", 10); for (int i = 0; i < condList.tagCount(); i++) { - Condition c = Condition.fromNBT(condList.getCompoundTagAt(i)); + AbilityCondition c = AbilityCondition.fromNBT(condList.getCompoundTagAt(i)); if (c != null) { conditions.add(c); } diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/ConditionField.java b/src/main/java/kamkeel/npcs/controllers/data/ability/ConditionField.java deleted file mode 100644 index d96178759..000000000 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/ConditionField.java +++ /dev/null @@ -1,197 +0,0 @@ -package kamkeel.npcs.controllers.data.ability; - -import net.minecraft.nbt.NBTTagCompound; - -public abstract class ConditionField { - protected final String key; - protected final String label; - protected final Class type; // Float.class, Integer.class, etc - protected T value; - - public ConditionField(String key, String label, Class type, T defaultValue) { - this.key = key; - this.label = label; - this.type = type; - this.value = defaultValue; - } - - public T getValue() { - return value; - } - - public void setValue(T value) { - this.value = value; - } - - public String getKey() { - return key; - } - - public String getLabel() { - return label; - } - - public Class getType() { - return type; - } - - public abstract void writeNBT(NBTTagCompound nbt); - - public abstract void readNBT(NBTTagCompound nbt); - - public static ConditionField intField(String key, String label, int defaultValue) { - return intField(key, label, defaultValue, 0, Integer.MAX_VALUE); - } - - public static ConditionField intField(String key, String label, int defaultValue, int min, int max) { - return new NumberField<>(key, label, Integer.class, defaultValue, min, max); - } - - public static ConditionField doubleField(String key, String label, double defaultValue) { - return doubleField(key, label, defaultValue, 0, Double.MAX_VALUE); - } - - public static ConditionField doubleField(String key, String label, double defaultValue, double min, double max) { - return new NumberField<>(key, label, Double.class, defaultValue, min, max); - } - - public static ConditionField floatField(String key, String label, float defaultValue) { - return floatField(key, label, defaultValue, 0, Float.MAX_VALUE); - } - - public static ConditionField floatField(String key, String label, float defaultValue, float min, float max) { - return new NumberField<>(key, label, Float.class, defaultValue, min, max); - } - - public static ConditionField stringField(String key, String label) { - return new StringField(key, label, ""); - } - - public static ConditionField stringField(String key, String label, String defaultValue) { - return new StringField(key, label, defaultValue); - } - - public static ConditionField booleanField(String key, String label, boolean defaultValue) { - return new BoolField(key, label, defaultValue); - } - - public static > ConditionField enumField(String key, String label, E defaultValue, Class enumClass) { - return new EnumField<>(key, label, defaultValue, enumClass); - } - - public static > ConditionField enumField(String key, String label, E defaultValue) { - return new EnumField<>(key, label, defaultValue, defaultValue.getDeclaringClass()); - } - - private static class NumberField> extends ConditionField { - private T min; - private T max; - - public NumberField(String key, String label, Class type, T defaultValue, T min, T max) { - super(key, label, type, defaultValue); - this.min = min; - this.max = max; - } - - @Override - public void setValue(T value) { - if (value.compareTo(min) < 0) { - this.value = min; - } else if (value.compareTo(max) > 0) { - this.value = max; - } else { - this.value = value; - } - } - - public NumberField min(T value) { - this.min = value; - return this; - } - - public NumberField max(T value) { - this.max = value; - return this; - } - - @Override - public void writeNBT(NBTTagCompound nbt) { - if (value instanceof Integer) nbt.setInteger(key, (Integer) value); - else if (value instanceof Float) nbt.setFloat(key, (Float) value); - else if (value instanceof Double) nbt.setDouble(key, (Double) value); - else if (value instanceof Long) nbt.setLong(key, (Long) value); - } - - @Override - @SuppressWarnings("unchecked") - public void readNBT(NBTTagCompound nbt) { - if (!nbt.hasKey(key)) return; - T v; - Class t = type; - if (t == Integer.class) v = (T) (Integer) nbt.getInteger(key); - else if (t == Float.class) v = (T) (Float) nbt.getFloat(key); - else if (t == Double.class) v = (T) (Double) nbt.getDouble(key); - else if (t == Long.class) v = (T) (Long) nbt.getLong(key); - else return; - setValue(v); - } - } - - private static class StringField extends ConditionField { - public StringField(String key, String label, String defaultValue) { - super(key, label, String.class, defaultValue); - } - - @Override - public void writeNBT(NBTTagCompound nbt) { - nbt.setString(key, value); - } - - @Override - public void readNBT(NBTTagCompound nbt) { - setValue(nbt.getString(key)); - } - } - - private static class BoolField extends ConditionField { - public BoolField(String key, String label, boolean defaultValue) { - super(key, label, Boolean.class, defaultValue); - } - - @Override - public void writeNBT(NBTTagCompound nbt) { - nbt.setBoolean(key, value); - } - - @Override - public void readNBT(NBTTagCompound nbt) { - setValue(nbt.getBoolean(key)); - } - } - - private static class EnumField> extends ConditionField { - private final E[] options; - - public EnumField(String key, String label, E defaultValue, Class enumClass) { - super(key, label, enumClass, defaultValue); - this.options = enumClass.getEnumConstants(); - } - - public E[] getOptions() { - return options; - } - - @Override - public void writeNBT(NBTTagCompound nbt) { - nbt.setString(key, value.name()); - } - - @Override - public void readNBT(NBTTagCompound nbt) { - if (!nbt.hasKey(key)) return; - try { - setValue(Enum.valueOf(type, nbt.getString(key))); - } catch (IllegalArgumentException ignored) {} - } - } -} diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/IAbilityAction.java b/src/main/java/kamkeel/npcs/controllers/data/ability/IAbilityAction.java index a1f4ac777..612cd9145 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/IAbilityAction.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/IAbilityAction.java @@ -1,5 +1,6 @@ package kamkeel.npcs.controllers.data.ability; +import kamkeel.npcs.controllers.data.ability.conditions.AbilityCondition; import net.minecraft.entity.EntityLivingBase; import net.minecraft.nbt.NBTTagCompound; @@ -30,7 +31,7 @@ public interface IAbilityAction { UserType getAllowedBy(); - List getConditions(); + List getConditions(); boolean checkConditions(EntityLivingBase caster, EntityLivingBase target); diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/IAbilityCondition.java b/src/main/java/kamkeel/npcs/controllers/data/ability/IAbilityCondition.java deleted file mode 100644 index 2c1b7e670..000000000 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/IAbilityCondition.java +++ /dev/null @@ -1,94 +0,0 @@ -package kamkeel.npcs.controllers.data.ability; - -import kamkeel.npcs.controllers.AbilityController; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.nbt.NBTTagCompound; -import noppes.npcs.LogWriter; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.function.Supplier; - -public interface IAbilityCondition { - /** - * Check if this condition is met. - * - * @param caster The entity that would use the ability (NPC or Player) - * @param target The current target (may be null for self-targeting abilities or players) - * @return true if the condition is satisfied - */ - boolean check(EntityLivingBase caster, EntityLivingBase target); - - UserType getUserType(); - - String getTypeId(); - - List> getFields(); - - default NBTTagCompound writeNBT() { - NBTTagCompound nbt = new NBTTagCompound(); - nbt.setInteger("userType", getUserType().ordinal()); - nbt.setString("type", getTypeId()); - for (ConditionField field : getFields()) { - field.writeNBT(nbt); - } - return nbt; - } - - default void readNBT(NBTTagCompound nbt) { - for (ConditionField field : getFields()) { - field.readNBT(nbt); - } - } - - static IAbilityCondition fromNBT(NBTTagCompound nbt) { - String typeId = nbt.getString("type"); - Supplier factory = AbilityController.Instance.getConditionType(typeId); - if (factory == null) { - LogWriter.info("AbilityController: Unknown condition type: " + typeId); - return null; - } - IAbilityCondition condition = factory.get(); - condition.readNBT(nbt); - - return condition; - } - - class ConditionHPAbove implements IAbilityCondition { - ConditionField threshold = ConditionField.floatField("threshold", "threshold", 0.5f); - - public ConditionHPAbove() { - } - - @Override - public boolean check(EntityLivingBase caster, EntityLivingBase target) { - return caster.getHealth() / caster.getMaxHealth() > threshold.getValue(); - } - - @Override - public UserType getUserType() { - return UserType.BOTH; - } - - @Override - public String getTypeId() { - return "hp_above"; - } - - public float getThreshold() { - return threshold.getValue(); - } - - public void setThreshold(float threshold) { - this.threshold.setValue(threshold); - } - - @Override - public List> getFields() { - return Arrays.asList( - threshold - ); - } - } -} diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/conditions/AbilityCondition.java b/src/main/java/kamkeel/npcs/controllers/data/ability/conditions/AbilityCondition.java new file mode 100644 index 000000000..15d345a4c --- /dev/null +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/conditions/AbilityCondition.java @@ -0,0 +1,84 @@ +package kamkeel.npcs.controllers.data.ability.conditions; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import kamkeel.npcs.controllers.AbilityController; +import kamkeel.npcs.controllers.data.ability.UserType; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.LogWriter; +import noppes.npcs.client.gui.builder.FieldDef; + +import java.util.List; +import java.util.function.Supplier; + +public abstract class AbilityCondition { + protected String typeId = ""; + protected String name = ""; + protected UserType userType = UserType.BOTH; + + /** + * Check if this condition is met. + * + * @param caster The entity that would use the ability (NPC or Player) + * @param target The current target (may be null for self-targeting abilities or players) + * @return true if the condition is satisfied + */ + public abstract boolean check(EntityLivingBase caster, EntityLivingBase target); + + public boolean requiresTarget() { + return false; + } + + public UserType getUserType() { + return userType; + } + + public void setUserType(UserType userType) { + this.userType = userType; + } + + public String getTypeId() { + return typeId; + } + + public String getName() { + return name; + } + + @SideOnly(Side.CLIENT) + public abstract List getAbilityDefinitions(List defs); + + public final NBTTagCompound writeNBT() { + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setInteger("userType", getUserType().ordinal()); + nbt.setString("type", getTypeId()); + nbt.setString("name", getName()); + writeTypeNBT(nbt); + return nbt; + } + + public abstract void writeTypeNBT(NBTTagCompound nbt); + + public abstract void readTypeNBT(NBTTagCompound nbt); + + public final void readNBT(NBTTagCompound nbt) { + typeId = nbt.getString("type"); + name = nbt.getString("name"); + userType = UserType.fromOrdinal(nbt.getInteger("userType")); + readTypeNBT(nbt); + } + + public static AbilityCondition fromNBT(NBTTagCompound nbt) { + String typeId = nbt.getString("type"); + Supplier factory = AbilityController.Instance.getConditionType(typeId); + if (factory == null) { + LogWriter.info("AbilityController: Unknown condition type: " + typeId); + return null; + } + AbilityCondition condition = factory.get(); + condition.readNBT(nbt); + + return condition; + } +} diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/conditions/ConditionHPThreshold.java b/src/main/java/kamkeel/npcs/controllers/data/ability/conditions/ConditionHPThreshold.java new file mode 100644 index 000000000..3d647475f --- /dev/null +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/conditions/ConditionHPThreshold.java @@ -0,0 +1,99 @@ +package kamkeel.npcs.controllers.data.ability.conditions; + +import kamkeel.npcs.controllers.data.ability.UserType; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.client.gui.builder.FieldDef; + +import java.util.Collections; +import java.util.List; + +public class ConditionHPThreshold extends AbilityCondition{ + private float threshold = 0.5f; // 50% + private ThresholdType thresholdType = ThresholdType.ABOVE; + + public enum ThresholdType { + ABOVE { + @Override + public boolean test(float value, float threshold) { + return value > threshold; + } + }, + BELOW { + @Override + public boolean test(float value, float threshold) { + return value < threshold; + } + }; + + public abstract boolean test(float value, float threshold); + + public static ThresholdType fromOrdinal(int ordinal) { + ThresholdType[] values = values(); + if (ordinal >= 0 && ordinal < values.length) { + return values[ordinal]; + } + return ABOVE; + } + } + + public ConditionHPThreshold() { + this.typeId = "condition.cnpc.hp_threshold"; + this.name = "Health Threshold"; + this.userType = UserType.NPC_ONLY; + } + + @Override + public boolean check(EntityLivingBase caster, EntityLivingBase target) { + float casterHP = caster.getHealth() / caster.getMaxHealth(); + float targetHP = target.getHealth() / target.getMaxHealth(); + + + return compare(casterHP, targetHP); + } + + public boolean compare(float casterHp, float targetHp) { + boolean casterCheck = thresholdType.test(casterHp, threshold); + boolean targetCheck = thresholdType.test(targetHp, threshold); + + switch (getUserType()) { + case BOTH: + return casterCheck && targetCheck; + case PLAYER_ONLY: + return casterCheck; + default: + return targetCheck; + } + } + + public float getThreshold() { + return threshold; + } + + public void setThreshold(float threshold) { + this.threshold = Math.max(0, threshold); + } + + public ThresholdType getThresholdType() { + return thresholdType; + } + + public void setThresholdType(ThresholdType thresholdType) { + this.thresholdType = thresholdType; + } + + @Override + public List getAbilityDefinitions(List defs) { + return Collections.emptyList(); + } + + @Override + public void writeTypeNBT(NBTTagCompound nbt) { + nbt.setFloat("threshold", threshold); + } + + @Override + public void readTypeNBT(NBTTagCompound nbt) { + threshold = nbt.getFloat("threshold"); + } +} diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/conditions/ConditionHitCount.java b/src/main/java/kamkeel/npcs/controllers/data/ability/conditions/ConditionHitCount.java new file mode 100644 index 000000000..385e7eb99 --- /dev/null +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/conditions/ConditionHitCount.java @@ -0,0 +1,67 @@ +package kamkeel.npcs.controllers.data.ability.conditions; + +import kamkeel.npcs.controllers.data.ability.UserType; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.client.gui.builder.FieldDef; +import noppes.npcs.entity.EntityNPCInterface; + +import java.util.Collections; +import java.util.List; + +public class ConditionHitCount extends AbilityCondition{ + private int requiredHits = 3; + private int withinTicks = 60; + + public ConditionHitCount() { + this.typeId = "condition.cnpc.hit_count"; + this.name = "Hit Count"; + this.userType = UserType.NPC_ONLY; + } + + @Override + public boolean check(EntityLivingBase caster, EntityLivingBase target) { + if (caster instanceof EntityNPCInterface) { + EntityNPCInterface npc = (EntityNPCInterface) caster; + if (npc.abilities != null) { + return npc.abilities.getRecentHitCount(withinTicks) >= requiredHits; + } + } + + // For players, hit count tracking is not yet supported + return false; + } + + public int getRequiredHits() { + return requiredHits; + } + + public void setRequiredHits(int requiredHits) { + this.requiredHits = Math.max(0, requiredHits); + } + + public int getWithinTicks() { + return withinTicks; + } + + public void setWithinTicks(int withinTicks) { + this.withinTicks = Math.max(0, withinTicks); + } + + @Override + public List getAbilityDefinitions(List defs) { + return Collections.emptyList(); + } + + @Override + public void writeTypeNBT(NBTTagCompound nbt) { + nbt.setInteger("requiredHits", requiredHits); + nbt.setInteger("withinTicks", withinTicks); + } + + @Override + public void readTypeNBT(NBTTagCompound nbt) { + requiredHits = nbt.getInteger("requiredHits"); + withinTicks = nbt.getInteger("withinTicks"); + } +} 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 3aa153f59..edbf676fb 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/SubGuiAbilityConfig.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/SubGuiAbilityConfig.java @@ -60,7 +60,7 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi public SubGuiAbilityConfig(Ability ability, IAbilityConfigCallback callback) { this.ability = ability; this.callback = callback; - this.conditions = new ArrayList<>(ability.getConditions()); +// this.conditions = new ArrayList<>(ability.getConditions()); this.fieldDefs = ability.getAllDefinitions(); discoverCustomTabs(); @@ -230,51 +230,51 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi // ═══════════════════════════════════════════════════════════════════════════ private int renderConditions(GuiScrollWindow sw, int y, int labelCounter) { - y += 3; - sw.addLabel(new GuiNpcLabel(labelCounter, "ability.conditions", L_LABEL_X, y + 2, 0xFFFF55)); - y += 15; - - for (int i = 0; i < conditions.size() && i < 3; i++) { - Condition cond = conditions.get(i); - String condName = getConditionDisplayName(cond); - sw.addButton(new GuiNpcButton(50 + i * 10, L_LABEL_X, y, 140, 20, condName)); - sw.addButton(new GuiNpcButton(51 + i * 10, L_LABEL_X + 145, y, 40, 20, "gui.edit")); - sw.addButton(new GuiNpcButton(52 + i * 10, L_LABEL_X + 190, y, 20, 20, "X")); - y += 22; - } - - if (conditions.size() < 3) { - sw.addButton(new GuiNpcButton(80, L_LABEL_X, y, 50, 20, "gui.add")); - y += ROW_H; - } - +// y += 3; +// sw.addLabel(new GuiNpcLabel(labelCounter, "ability.conditions", L_LABEL_X, y + 2, 0xFFFF55)); +// y += 15; +// +// for (int i = 0; i < conditions.size() && i < 3; i++) { +// Condition cond = conditions.get(i); +// String condName = getConditionDisplayName(cond); +// sw.addButton(new GuiNpcButton(50 + i * 10, L_LABEL_X, y, 140, 20, condName)); +// sw.addButton(new GuiNpcButton(51 + i * 10, L_LABEL_X + 145, y, 40, 20, "gui.edit")); +// sw.addButton(new GuiNpcButton(52 + i * 10, L_LABEL_X + 190, y, 20, 20, "X")); +// y += 22; +// } +// +// if (conditions.size() < 3) { +// sw.addButton(new GuiNpcButton(80, L_LABEL_X, y, 50, 20, "gui.add")); +// y += ROW_H; +// } +// return y; } - 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 hc = (Condition.ConditionHitCount) cond; - return StatCollector.translateToLocal("condition.hit_count") + ": " + hc.getRequiredHits() + "/" + hc.getWithinTicks() + "t"; - default: - return typeId; - } - } +// 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 hc = (Condition.ConditionHitCount) cond; +// return StatCollector.translateToLocal("condition.hit_count") + ": " + hc.getRequiredHits() + "/" + hc.getWithinTicks() + "t"; +// default: +// return typeId; +// } +// } - private float getConditionThreshold(Condition cond) { - NBTTagCompound nbt = cond.writeNBT(); - return nbt.hasKey("threshold") ? nbt.getFloat("threshold") : 0.5f; - } +// private float getConditionThreshold(Condition cond) { +// NBTTagCompound nbt = cond.writeNBT(); +// return nbt.hasKey("threshold") ? nbt.getFloat("threshold") : 0.5f; +// } // ═══════════════════════════════════════════════════════════════════════════ // BUTTON EVENTS @@ -408,8 +408,8 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi } protected void applyToAbility() { - ability.getConditions().clear(); - for (Condition c : conditions) ability.addCondition(c); +// ability.getConditions().clear(); +// for (Condition c : conditions) ability.addCondition(c); } public void loadAbility(Ability loadedAbility) { @@ -418,7 +418,7 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi nbt.setString("typeId", ability.getTypeId()); ability.readNBT(nbt); - this.conditions = new ArrayList<>(ability.getConditions()); +// this.conditions = new ArrayList<>(ability.getConditions()); this.fieldDefs = ability.getAllDefinitions(); discoverCustomTabs(); initGui(); diff --git a/src/main/java/noppes/npcs/client/gui/advanced/SubGuiChainedAbilityConfig.java b/src/main/java/noppes/npcs/client/gui/advanced/SubGuiChainedAbilityConfig.java index 565443c3d..35b9e9f7c 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/SubGuiChainedAbilityConfig.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/SubGuiChainedAbilityConfig.java @@ -10,6 +10,7 @@ import kamkeel.npcs.controllers.data.ability.Condition; import kamkeel.npcs.controllers.data.ability.AbilityIconData; import kamkeel.npcs.controllers.data.ability.IChainedAbilityFieldProvider; import kamkeel.npcs.controllers.data.ability.UserType; +import kamkeel.npcs.controllers.data.ability.conditions.AbilityCondition; import kamkeel.npcs.network.PacketClient; import kamkeel.npcs.network.packets.request.ability.CustomAbilitySavePacket; import net.minecraft.client.gui.GuiButton; @@ -22,11 +23,14 @@ import noppes.npcs.client.gui.util.GuiNpcButton; import noppes.npcs.client.gui.util.GuiNpcLabel; import noppes.npcs.client.gui.util.GuiNpcTextField; import noppes.npcs.client.gui.util.GuiScrollWindow; -import noppes.npcs.client.gui.util.IAbilityConfigCallback; +import kamkeel.npcs.controllers.data.ability.Ability; +import kamkeel.npcs.controllers.data.ability.AbilityAction; +import kamkeel.npcs.controllers.data.ability.ChainedAbility; +import noppes.npcs.client.gui.util.*; + +import java.util.ArrayList; import noppes.npcs.client.gui.util.IChainedAbilityConfigCallback; -import noppes.npcs.client.gui.util.ISubGuiListener; -import noppes.npcs.client.gui.util.ITextfieldListener; -import noppes.npcs.client.gui.util.SubGuiInterface; + import java.util.ArrayList; import java.util.Collections; @@ -34,6 +38,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Set; + /** * SubGui for editing a {@link ChainedAbility}. * Core tabs: General, Entries, Conditions. @@ -89,7 +94,7 @@ public class SubGuiChainedAbilityConfig extends SubGuiInterface implements IText private List fieldDefs; private List entries; - private List conditions; +// private List conditions; // Dynamic tabs injected by field providers (e.g., "Icon") private List extraTabs = new ArrayList<>(); @@ -128,7 +133,7 @@ public class SubGuiChainedAbilityConfig extends SubGuiInterface implements IText this.readOnlyEntries = readOnlyEntries; this.npcSlots = npcSlots; this.entries = new ArrayList<>(chain.getEntries()); - this.conditions = new ArrayList<>(chain.getConditions()); +// this.conditions = new ArrayList<>(chain.getConditions()); buildFieldDefs(); @@ -424,23 +429,23 @@ public class SubGuiChainedAbilityConfig extends SubGuiInterface implements IText } private int renderConditions(GuiScrollWindow sw, int y, int labelCounter) { - y += 3; - sw.addLabel(new GuiNpcLabel(labelCounter, "ability.conditions", L_LABEL_X, y + 2, 0xFFFF55)); - y += 15; - - for (int i = 0; i < conditions.size() && i < 3; i++) { - Condition cond = conditions.get(i); - String condName = getConditionDisplayName(cond); - sw.addButton(new GuiNpcButton(COND_BASE + i * COND_STRIDE, L_LABEL_X, y, 140, 20, condName)); - sw.addButton(new GuiNpcButton(COND_BASE + i * COND_STRIDE + 1, L_LABEL_X + 145, y, 40, 20, "gui.edit")); - sw.addButton(new GuiNpcButton(COND_BASE + i * COND_STRIDE + 2, L_LABEL_X + 190, y, 20, 20, "X")); - y += 22; - } - - if (conditions.size() < 3) { - sw.addButton(new GuiNpcButton(BTN_ADD_COND, L_LABEL_X, y, 50, 20, "gui.add")); - y += ROW_H; - } +// y += 3; +// sw.addLabel(new GuiNpcLabel(labelCounter, "ability.conditions", L_LABEL_X, y + 2, 0xFFFF55)); +// y += 15; +// +// for (int i = 0; i < conditions.size() && i < 3; i++) { +// Condition cond = conditions.get(i); +// String condName = getConditionDisplayName(cond); +// sw.addButton(new GuiNpcButton(COND_BASE + i * COND_STRIDE, L_LABEL_X, y, 140, 20, condName)); +// sw.addButton(new GuiNpcButton(COND_BASE + i * COND_STRIDE + 1, L_LABEL_X + 145, y, 40, 20, "gui.edit")); +// sw.addButton(new GuiNpcButton(COND_BASE + i * COND_STRIDE + 2, L_LABEL_X + 190, y, 20, 20, "X")); +// y += 22; +// } +// +// if (conditions.size() < 3) { +// sw.addButton(new GuiNpcButton(BTN_ADD_COND, L_LABEL_X, y, 50, 20, "gui.add")); +// y += ROW_H; +// } return y; } @@ -618,29 +623,29 @@ public class SubGuiChainedAbilityConfig extends SubGuiInterface implements IText } private boolean handleConditionButton(int id) { - if (id >= COND_BASE && id < COND_END) { - int condIndex = (id - COND_BASE) / COND_STRIDE; - int action = (id - COND_BASE) % COND_STRIDE; - if (action == 0 || action == 1) { - if (condIndex < conditions.size()) { - editingConditionIndex = condIndex; - setSubGui(new SubGuiConditionEdit(conditions.get(condIndex))); - } - } else if (action == 2) { - if (condIndex < conditions.size()) { - conditions.remove(condIndex); - initGui(); - } - } - return true; - } - if (id == BTN_ADD_COND) { - if (conditions.size() < 3) { - editingConditionIndex = conditions.size(); - setSubGui(new SubGuiConditionEdit(null)); - } - return true; - } +// if (id >= COND_BASE && id < COND_END) { +// int condIndex = (id - COND_BASE) / COND_STRIDE; +// int action = (id - COND_BASE) % COND_STRIDE; +// if (action == 0 || action == 1) { +// if (condIndex < conditions.size()) { +// editingConditionIndex = condIndex; +// setSubGui(new SubGuiConditionEdit(conditions.get(condIndex))); +// } +// } else if (action == 2) { +// if (condIndex < conditions.size()) { +// conditions.remove(condIndex); +// initGui(); +// } +// } +// return true; +// } +// if (id == BTN_ADD_COND) { +// if (conditions.size() < 3) { +// editingConditionIndex = conditions.size(); +// setSubGui(new SubGuiConditionEdit(null)); +// } +// return true; +// } return false; } @@ -845,14 +850,14 @@ public class SubGuiChainedAbilityConfig extends SubGuiInterface implements IText } private void handleConditionEditClosed(SubGuiConditionEdit gui) { - Condition result = gui.getResult(); - if (result != null && editingConditionIndex >= 0) { - if (editingConditionIndex < conditions.size()) { - conditions.set(editingConditionIndex, result); - } else { - conditions.add(result); - } - } +// Condition result = gui.getResult(); +// if (result != null && editingConditionIndex >= 0) { +// if (editingConditionIndex < conditions.size()) { +// conditions.set(editingConditionIndex, result); +// } else { +// conditions.add(result); +// } +// } editingConditionIndex = -1; } @@ -890,10 +895,10 @@ public class SubGuiChainedAbilityConfig extends SubGuiInterface implements IText } // Conditions - chain.getConditions().clear(); - for (Condition c : conditions) { - chain.getConditions().add(c); - } +// chain.getConditions().clear(); +// for (Condition c : conditions) { +// chain.getConditions().add(c); +// } // Remove consumed NPC slots (descending order to preserve indices) if (npcSlots != null && !consumedSlotIndices.isEmpty()) {