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 25cb77747..5d793f5ec 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/Ability.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/Ability.java @@ -1233,6 +1233,7 @@ public abstract class Ability implements IAbility, IAbilityAction { public boolean checkConditions(EntityLivingBase caster, EntityLivingBase target) { for (AbilityCondition c : conditions) { + if (!c.getUserType().allowsNpc()) continue; if (!c.check(caster, target)) return false; } return true; @@ -1243,6 +1244,7 @@ public abstract class Ability implements IAbility, IAbilityAction { */ public boolean checkConditionsForPlayer(EntityLivingBase caster) { for (AbilityCondition c : conditions) { + if (!c.getUserType().allowsPlayer()) continue; if (c.requiresTarget()) continue; if (!c.check(caster, null)) return false; } 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 index 15d345a4c..95d38bf9b 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/conditions/AbilityCondition.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/conditions/AbilityCondition.java @@ -9,6 +9,7 @@ import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.LogWriter; import noppes.npcs.client.gui.builder.FieldDef; +import java.util.ArrayList; import java.util.List; import java.util.function.Supplier; @@ -16,6 +17,7 @@ public abstract class AbilityCondition { protected String typeId = ""; protected String name = ""; protected UserType userType = UserType.BOTH; + protected ConditionFilter conditionFilter = ConditionFilter.CASTER; /** * Check if this condition is met. @@ -34,10 +36,6 @@ public abstract class AbilityCondition { return userType; } - public void setUserType(UserType userType) { - this.userType = userType; - } - public String getTypeId() { return typeId; } @@ -46,14 +44,32 @@ public abstract class AbilityCondition { return name; } + public ConditionFilter getFilter() { + return conditionFilter; + } + + public void setFilter(ConditionFilter filter) { + this.conditionFilter = filter; + } + @SideOnly(Side.CLIENT) - public abstract List getAbilityDefinitions(List defs); + public abstract void getConditionDefinitions(List defs); + + @SideOnly(Side.CLIENT) + public final List getAllDefinitions() { + List defs = new ArrayList<>(); + + defs.add(FieldDef.enumField("condition.filter", ConditionFilter.class, this::getFilter, this::setFilter)); + getConditionDefinitions(defs); + return defs; + } public final NBTTagCompound writeNBT() { NBTTagCompound nbt = new NBTTagCompound(); - nbt.setInteger("userType", getUserType().ordinal()); - nbt.setString("type", getTypeId()); + nbt.setString("typeId", getTypeId()); nbt.setString("name", getName()); + nbt.setInteger("userType", getUserType().ordinal()); + nbt.setInteger("filter", getUserType().ordinal()); writeTypeNBT(nbt); return nbt; } @@ -63,14 +79,15 @@ public abstract class AbilityCondition { public abstract void readTypeNBT(NBTTagCompound nbt); public final void readNBT(NBTTagCompound nbt) { - typeId = nbt.getString("type"); + typeId = nbt.getString("typeId"); name = nbt.getString("name"); userType = UserType.fromOrdinal(nbt.getInteger("userType")); + conditionFilter = ConditionFilter.fromOrdinal(nbt.getInteger("filter")); readTypeNBT(nbt); } public static AbilityCondition fromNBT(NBTTagCompound nbt) { - String typeId = nbt.getString("type"); + String typeId = nbt.getString("typeId"); Supplier factory = AbilityController.Instance.getConditionType(typeId); if (factory == null) { LogWriter.info("AbilityController: Unknown condition type: " + typeId); diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/conditions/ConditionFilter.java b/src/main/java/kamkeel/npcs/controllers/data/ability/conditions/ConditionFilter.java new file mode 100644 index 000000000..6c8e0c24e --- /dev/null +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/conditions/ConditionFilter.java @@ -0,0 +1,39 @@ +package kamkeel.npcs.controllers.data.ability.conditions; + +import kamkeel.npcs.controllers.data.ability.UserType; + +public enum ConditionFilter { + CASTER, + TARGET, + BOTH; + + public boolean checksCaster() { + return this == CASTER || this == BOTH; + } + + public boolean checksTarget() { + return this == TARGET || this == BOTH; + } + + public static ConditionFilter fromOrdinal(int ordinal) { + ConditionFilter[] values = values(); + if (ordinal >= 0 && ordinal < values.length) { + return values[ordinal]; + } + return BOTH; + } + + @Override + public String toString() { + switch (this) { + case BOTH: + return "condition.filter.both"; + case CASTER: + return "condition.filter.caster"; + case TARGET: + return "condition.filter.target"; + default: + return name(); + } + } +} 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 index 3d647475f..803fc978c 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/conditions/ConditionHPThreshold.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/conditions/ConditionHPThreshold.java @@ -1,11 +1,9 @@ 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{ @@ -16,13 +14,13 @@ public class ConditionHPThreshold extends AbilityCondition{ ABOVE { @Override public boolean test(float value, float threshold) { - return value > threshold; + return value >= threshold; } }, BELOW { @Override public boolean test(float value, float threshold) { - return value < threshold; + return value <= threshold; } }; @@ -35,12 +33,23 @@ public class ConditionHPThreshold extends AbilityCondition{ } return ABOVE; } + + @Override + public String toString() { + switch (this) { + case ABOVE: + return "condition.hp_above"; + case BELOW: + return "condition.hp_below"; + default: + return name(); + } + } } public ConditionHPThreshold() { this.typeId = "condition.cnpc.hp_threshold"; - this.name = "Health Threshold"; - this.userType = UserType.NPC_ONLY; + this.name = "condition.hp_threshold"; } @Override @@ -56,10 +65,10 @@ public class ConditionHPThreshold extends AbilityCondition{ boolean casterCheck = thresholdType.test(casterHp, threshold); boolean targetCheck = thresholdType.test(targetHp, threshold); - switch (getUserType()) { + switch (getFilter()) { case BOTH: return casterCheck && targetCheck; - case PLAYER_ONLY: + case CASTER: return casterCheck; default: return targetCheck; @@ -83,8 +92,10 @@ public class ConditionHPThreshold extends AbilityCondition{ } @Override - public List getAbilityDefinitions(List defs) { - return Collections.emptyList(); + public void getConditionDefinitions(List defs) { + defs.add(FieldDef.floatField("condition.threshold", this::getThreshold, this::setThreshold).min(0)); + defs.add(FieldDef.enumField("condition.threshold_type", ThresholdType.class, + this::getThresholdType, this::setThresholdType)); } @Override 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 index 385e7eb99..22465b593 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/conditions/ConditionHitCount.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/conditions/ConditionHitCount.java @@ -6,16 +6,15 @@ 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{ +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.name = "condition.hit_count"; this.userType = UserType.NPC_ONLY; } @@ -49,8 +48,9 @@ public class ConditionHitCount extends AbilityCondition{ } @Override - public List getAbilityDefinitions(List defs) { - return Collections.emptyList(); + public void getConditionDefinitions(List defs) { + defs.add(FieldDef.intField("condition.required_hits", this::getRequiredHits, this::setRequiredHits).min(1)); + defs.add(FieldDef.intField("condition.within_ticks", this::getWithinTicks, this::setWithinTicks).min(0)); } @Override 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 edbf676fb..b611e4e6b 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/SubGuiAbilityConfig.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/SubGuiAbilityConfig.java @@ -1,7 +1,7 @@ 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.conditions.AbilityCondition; import kamkeel.npcs.controllers.data.ability.gui.AbilityFieldBuilder; import net.minecraft.client.gui.GuiButton; import net.minecraft.nbt.NBTTagCompound; @@ -49,7 +49,7 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi private List fieldDefs; private List customTabNames; - private List conditions; + private List conditions; private int editingConditionIndex = -1; private AbilityFieldBuilder builder; @@ -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,32 @@ 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++) { + AbilityCondition 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 float getConditionThreshold(Condition cond) { -// NBTTagCompound nbt = cond.writeNBT(); -// return nbt.hasKey("threshold") ? nbt.getFloat("threshold") : 0.5f; -// } + private String getConditionDisplayName(AbilityCondition cond) { + if (cond == null) return "None"; + String name = cond.getName(); + return StatCollector.translateToLocal(name); + } // ═══════════════════════════════════════════════════════════════════════════ // BUTTON EVENTS @@ -382,7 +363,7 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi if (subgui instanceof SubGuiConditionEdit) { SubGuiConditionEdit condEdit = (SubGuiConditionEdit) subgui; - Condition result = condEdit.getResult(); + AbilityCondition result = condEdit.getResult(); if (result != null && editingConditionIndex >= 0) { if (editingConditionIndex < conditions.size()) { conditions.set(editingConditionIndex, result); @@ -408,8 +389,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 (AbilityCondition c : conditions) ability.addCondition(c); } public void loadAbility(Ability loadedAbility) { @@ -418,7 +399,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 35b9e9f7c..9783bb9a7 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/SubGuiChainedAbilityConfig.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/SubGuiChainedAbilityConfig.java @@ -6,7 +6,6 @@ import kamkeel.npcs.controllers.data.ability.AbilityAction; import kamkeel.npcs.controllers.data.ability.AbilityVariant; import kamkeel.npcs.controllers.data.ability.ChainedAbility; import kamkeel.npcs.controllers.data.ability.ChainedAbilityEntry; -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; @@ -14,7 +13,6 @@ 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; -import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.StatCollector; import noppes.npcs.client.gui.builder.FieldDef; import noppes.npcs.client.gui.builder.GuiFieldBuilder; @@ -23,16 +21,12 @@ 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 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 java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; @@ -94,7 +88,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<>(); @@ -133,7 +127,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(); @@ -429,50 +423,31 @@ 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++) { + AbilityCondition 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; } - private String getConditionDisplayName(Condition cond) { + private String getConditionDisplayName(AbilityCondition 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; + String name = cond.getName(); + return StatCollector.translateToLocal(name); } // ═══════════════════════════════════════════════════════════════════════════ @@ -623,29 +598,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; } @@ -850,14 +825,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); -// } -// } + AbilityCondition result = gui.getResult(); + if (result != null && editingConditionIndex >= 0) { + if (editingConditionIndex < conditions.size()) { + conditions.set(editingConditionIndex, result); + } else { + conditions.add(result); + } + } editingConditionIndex = -1; } @@ -895,10 +870,10 @@ public class SubGuiChainedAbilityConfig extends SubGuiInterface implements IText } // Conditions -// chain.getConditions().clear(); -// for (Condition c : conditions) { -// chain.getConditions().add(c); -// } + chain.getConditions().clear(); + for (AbilityCondition c : conditions) { + chain.getConditions().add(c); + } // Remove consumed NPC slots (descending order to preserve indices) if (npcSlots != null && !consumedSlotIndices.isEmpty()) { diff --git a/src/main/java/noppes/npcs/client/gui/advanced/SubGuiConditionEdit.java b/src/main/java/noppes/npcs/client/gui/advanced/SubGuiConditionEdit.java index d941f19ec..d90f0b6d6 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/SubGuiConditionEdit.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/SubGuiConditionEdit.java @@ -1,190 +1,159 @@ package noppes.npcs.client.gui.advanced; -import kamkeel.npcs.controllers.data.ability.Condition; +import kamkeel.npcs.controllers.AbilityController; +import kamkeel.npcs.controllers.data.ability.conditions.AbilityCondition; import net.minecraft.client.gui.GuiButton; -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.ITextfieldListener; -import noppes.npcs.client.gui.util.SubGuiInterface; +import noppes.npcs.client.gui.builder.FieldDef; +import noppes.npcs.client.gui.util.*; +import kamkeel.npcs.controllers.data.ability.gui.AbilityFieldBuilder; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; /** - * SubGui for editing a single ability condition. - * Allows selecting condition type and configuring its parameters. + * SubGui for editing a single AbilityCondition. + * + * Type selection stays manual (we need to swap the condition object). + * Field rendering is fully delegated to AbilityCondition#getAbilityDefinitions(), + * mirroring the pattern used in SubGuiAbilityConfig. */ -public class SubGuiConditionEdit extends SubGuiInterface implements ITextfieldListener { +public class SubGuiConditionEdit extends SubGuiInterface implements ITextfieldListener, ISubGuiListener { - // 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 int DECLARATIVE_ID_START = 1000; + private static final int CLEAR_ID_START = 2000; + private static final int LABEL_ID_START = 3000; - private static final String[] CONDITION_TYPE_IDS = { - "hp_above", - "hp_below", - "target_hp_above", - "target_hp_below", - "hit_count" - }; + private static final int BTN_TYPE = 1; + private static final int BTN_CANCEL = 10; + private static final int BTN_DONE = 11; - // Current condition being edited - private Condition condition; - private Condition result; + private AbilityCondition condition; + private AbilityCondition result; - // State + private final String[] conditionTypeIds; + private final String[] conditionTypeNames; 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; + private AbilityFieldBuilder builder; + + public SubGuiConditionEdit(AbilityCondition existing) { this.result = null; + conditionTypeIds = AbilityController.Instance.getConditionTypes(); + conditionTypeNames = new String[conditionTypeIds.length]; + for (int i = 0; i < conditionTypeIds.length; i++) { + Supplier factory = AbilityController.Instance.getConditionType(conditionTypeIds[i]); + conditionTypeNames[i] = factory != null ? factory.get().getName() : conditionTypeIds[i]; + } + if (existing != null) { - String typeId = existing.getTypeId(); - for (int i = 0; i < CONDITION_TYPE_IDS.length; i++) { - if (CONDITION_TYPE_IDS[i].equals(typeId)) { + for (int i = 0; i < conditionTypeIds.length; i++) { + if (conditionTypeIds[i].equals(existing.getTypeId())) { selectedTypeIndex = i; break; } } - loadFromCondition(existing); + this.condition = existing; + } else { + this.condition = spawnCondition(selectedTypeIndex); } setBackground("menubg.png"); - xSize = 220; - ySize = 140; + xSize = 240; + ySize = 180; } - 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; - } + private AbilityCondition spawnCondition(int typeIndex) { + if (typeIndex < 0 || typeIndex >= conditionTypeIds.length) return null; + Supplier factory = AbilityController.Instance.getConditionType(conditionTypeIds[typeIndex]); + return factory != null ? factory.get() : null; } @Override public void initGui() { + GuiNpcTextField.unfocus(); super.initGui(); - int y = guiTop + 8; - int labelX = guiLeft + 8; - int fieldX = guiLeft + 90; + int swX = guiLeft + 4; + int swY = guiTop + 5; + int swW = xSize - 8; + int swH = ySize - 35; - // Title - addLabel(new GuiNpcLabel(0, "condition.edit", labelX, y)); - y += 18; - - // Condition Type selector - addLabel(new GuiNpcLabel(1, "gui.type", labelX, y + 5)); - GuiNpcButton typeBtn = new GuiNpcButton(1, fieldX, y, 115, 20, CONDITION_TYPES, selectedTypeIndex); - typeBtn.setHoverText("condition.hover.type"); + int labelY = guiTop + 8; + addLabel(new GuiNpcLabel(0, "gui.type", guiLeft + 8, labelY + 5)); + GuiNpcButton typeBtn = new GuiNpcButton(BTN_TYPE, guiLeft + 80, labelY, 155, 20, conditionTypeNames, selectedTypeIndex); addButton(typeBtn); - 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, "" + requiredHits); - hitsField.setIntegersOnly(); - hitsField.setMinMaxDefault(1, 100, 3); - hitsField.setHoverText("condition.hover.hits"); - addTextField(hitsField); - y += 24; + swY += 26; + swH -= 26; - addLabel(new GuiNpcLabel(3, "condition.within", labelX, y + 5)); - GuiNpcTextField ticksField = new GuiNpcTextField(3, this, fontRendererObj, fieldX, y, 40, 20, "" + withinTicks); - ticksField.setIntegersOnly(); - ticksField.setMinMaxDefault(1, 1200, 60); - ticksField.setHoverText("condition.hover.within"); - 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, "" + percent); - thresholdField.setIntegersOnly(); - thresholdField.setMinMaxDefault(1, 99, 50); - thresholdField.setHoverText("condition.hover.threshold"); - addTextField(thresholdField); - addLabel(new GuiNpcLabel(4, "%", fieldX + 45, y + 5)); + List fields = new ArrayList<>(); + if (condition != null) { + fields = condition.getAllDefinitions(); } - // 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")); + builder = new AbilityFieldBuilder(this, fontRendererObj); + builder.startIds(DECLARATIVE_ID_START, CLEAR_ID_START, LABEL_ID_START); + builder.startY(5); + + builder.buildScrollWindow(fields, swX, swY, swW, swH); + + int btnY = guiTop + ySize - 26; + addButton(new GuiNpcButton(BTN_CANCEL, guiLeft + 8, btnY, 60, 20, "gui.cancel")); + addButton(new GuiNpcButton(BTN_DONE, guiLeft + xSize - 68, btnY, 60, 20, "gui.done")); } @Override public void buttonEvent(GuiButton guibutton) { int id = guibutton.id; - if (id == 1) { - // Type changed - selectedTypeIndex = ((GuiNpcButton) guibutton).getValue(); + if (id == BTN_TYPE) { + int newIndex = ((GuiNpcButton) guibutton).getValue(); + if (newIndex != selectedTypeIndex) { + selectedTypeIndex = newIndex; + condition = spawnCondition(selectedTypeIndex); + } initGui(); - } else if (id == 10) { - // Cancel - close without saving + return; + } + + if (id == BTN_CANCEL) { result = null; close(); - } else if (id == 11) { - // Done - create condition and close - result = createCondition(); + return; + } + + if (id == BTN_DONE) { + result = condition; close(); + return; + } + + if (builder != null && builder.handleButtonEvent(id, guibutton)) { + if (!hasSubGui()) { + initGui(); + } } } @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; + if (textField.id < DECLARATIVE_ID_START) return; + if (builder != null && builder.handleTextFieldEvent(textField.id, textField)) { + initGui(); } } - 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; + @Override + public void subGuiClosed(SubGuiInterface subgui) { + if (builder != null && builder.handleSubGuiClosed(subgui)) { + initGui(); } } - /** - * Get the resulting condition after dialog closes. - * Returns null if cancelled or no valid condition. - */ - public Condition getResult() { + public AbilityCondition getResult() { return result; } } diff --git a/src/main/resources/assets/customnpcs/lang/en_US.lang b/src/main/resources/assets/customnpcs/lang/en_US.lang index 55e94b72d..c6d745706 100644 --- a/src/main/resources/assets/customnpcs/lang/en_US.lang +++ b/src/main/resources/assets/customnpcs/lang/en_US.lang @@ -2079,14 +2079,18 @@ gui.players=Players # 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.filter=Filter Type +condition.filter.target=Target +condition.filter.caster=Caster +condition.filter.both=Both condition.hit_count=Hit Count -condition.percent=Threshold -condition.hits=Required Hits -condition.within=Within (ticks) +condition.hp_threshold=HP Threshold +condition.hp_above=HP Above +condition.hp_below=HP Below +condition.threshold=Threshold +condition.threshold_type=Threshold Type +condition.required_hits=Required Hits +condition.within_ticks=Within (ticks) # Condition Hover Tooltips condition.hover.type=Condition type that must be met for ability to activate