mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-13 19:34:09 +00:00
Fields Builder for Ability GUIs
This commit is contained in:
1 parent
0ff501bb16
commit
911f185400
29 files changed
+1223
-605
No files matched your search
@@ -19,10 +19,12 @@ import noppes.npcs.client.gui.advanced.SubGuiAbilityConfig;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.controllers.AnimationController;
|
||||
import noppes.npcs.controllers.data.Animation;
|
||||
import noppes.npcs.controllers.data.Frame;
|
||||
import noppes.npcs.entity.EntityNPCInterface;
|
||||
import noppes.npcs.scripted.NpcAPI;
|
||||
import noppes.npcs.scripted.event.AbilityEvent;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.gui.ColumnHint;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.FieldDef;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.TabTarget;
|
||||
|
||||
@@ -60,6 +62,7 @@ public abstract class Ability implements IAbility {
|
||||
// Timing (ticks)
|
||||
protected int cooldownTicks = 0; // Added to global cooldown after ability completes
|
||||
protected int windUpTicks = 20;
|
||||
protected boolean syncWindupWithAnimation = true;
|
||||
protected int dazedTicks = 80; // Only used when interrupted during WINDUP (if interruptible)
|
||||
|
||||
// Interruption
|
||||
@@ -325,49 +328,70 @@ public abstract class Ability implements IAbility {
|
||||
defs.add(FieldDef.stringField("gui.name", this::getName, this::setName)
|
||||
.tab(TabTarget.GENERAL));
|
||||
defs.add(FieldDef.intField("ability.weight", this::getWeight, this::setWeight)
|
||||
.tab(TabTarget.GENERAL).range(1, 1000));
|
||||
defs.add(FieldDef.enumField("ability.lockMove", LockMovementType.class,
|
||||
this::getLockMovement, this::setLockMovement)
|
||||
.tab(TabTarget.GENERAL).range(1, 1000).column(ColumnHint.LEFT));
|
||||
defs.add(FieldDef.boolField("gui.enabled", this::isEnabled, this::setEnabled)
|
||||
.tab(TabTarget.GENERAL).column(ColumnHint.RIGHT));
|
||||
defs.add(FieldDef.section("ability.section.timing").tab(TabTarget.GENERAL));
|
||||
defs.add(FieldDef.intField("ability.windUpTicks", this::getRawWindUpTicks, this::setWindUpTicks)
|
||||
.tab(TabTarget.GENERAL).range(0, 1000).column(ColumnHint.LEFT)
|
||||
.visibleWhen(() -> !isSyncWindupWithAnimation()));
|
||||
defs.add(FieldDef.labelField("ability.windUpTicks", () -> getWindUpTicks() + "t")
|
||||
.tab(TabTarget.GENERAL).column(ColumnHint.LEFT)
|
||||
.visibleWhen(this::isSyncWindupWithAnimation));
|
||||
defs.add(FieldDef.boolField("ability.syncWindup", this::isSyncWindupWithAnimation, this::setSyncWindupWithAnimation)
|
||||
.tab(TabTarget.GENERAL).hover("ability.hover.sync").column(ColumnHint.RIGHT)
|
||||
.visibleWhen(this::hasWindUpAnimation));
|
||||
defs.add(FieldDef.intField("ability.cooldownTicks", this::getCooldownTicks, this::setCooldownTicks)
|
||||
.tab(TabTarget.GENERAL).range(0, 10000));
|
||||
defs.add(FieldDef.section("ability.section.movement").tab(TabTarget.GENERAL));
|
||||
defs.add(FieldDef.stringEnumField("ability.lockMovement", LockMovementType.getDisplayKeys(),
|
||||
() -> this.getLockMovement().getDisplayKey(),
|
||||
v -> {
|
||||
String[] keys = LockMovementType.getDisplayKeys();
|
||||
for (int i = 0; i < keys.length; i++) {
|
||||
if (keys[i].equals(v)) { this.setLockMovement(LockMovementType.fromOrdinal(i)); break; }
|
||||
}
|
||||
})
|
||||
.tab(TabTarget.GENERAL).hover("ability.hover.lockMove"));
|
||||
defs.add(FieldDef.boolField("ability.interruptible", this::isInterruptible, this::setInterruptible)
|
||||
.tab(TabTarget.GENERAL).hover("ability.hover.interruptible"));
|
||||
defs.add(FieldDef.intField("ability.dazed", this::getDazedTicks, this::setDazedTicks)
|
||||
.tab(TabTarget.GENERAL).hover("ability.hover.interruptible").column(ColumnHint.LEFT));
|
||||
defs.add(FieldDef.intField("ability.dazedTicks", this::getDazedTicks, this::setDazedTicks)
|
||||
.tab(TabTarget.GENERAL).range(0, 1000)
|
||||
.visibleWhen(this::isInterruptible));
|
||||
defs.add(FieldDef.intField("ability.windup", this::getWindUpTicks, this::setWindUpTicks)
|
||||
.tab(TabTarget.GENERAL).range(0, 1000));
|
||||
defs.add(FieldDef.intField("ability.cooldown", this::getCooldownTicks, this::setCooldownTicks)
|
||||
.tab(TabTarget.GENERAL).range(0, 10000));
|
||||
defs.add(FieldDef.boolField("gui.enabled", this::isEnabled, this::setEnabled)
|
||||
.tab(TabTarget.GENERAL));
|
||||
.visibleWhen(this::isInterruptible).column(ColumnHint.RIGHT));
|
||||
|
||||
// Target tab
|
||||
defs.add(FieldDef.intField("ability.minRange", () -> (int) getMinRange(), v -> setMinRange(v))
|
||||
.tab(TabTarget.TARGET).range(0, 100));
|
||||
.tab(TabTarget.TARGET).range(0, 100).column(ColumnHint.LEFT));
|
||||
defs.add(FieldDef.intField("ability.maxRange", () -> (int) getMaxRange(), v -> setMaxRange(v))
|
||||
.tab(TabTarget.TARGET).range(1, 100));
|
||||
.tab(TabTarget.TARGET).range(1, 100).column(ColumnHint.RIGHT));
|
||||
if (!isTargetingModeLocked()) {
|
||||
defs.add(FieldDef.enumField("ability.targeting", TargetingMode.class,
|
||||
defs.add(FieldDef.enumField("ability.targetingMode", TargetingMode.class,
|
||||
this::getTargetingMode, this::setTargetingMode)
|
||||
.tab(TabTarget.TARGET).hover("ability.hover.targeting"));
|
||||
}
|
||||
|
||||
// Effects tab
|
||||
// Effects tab - Sounds
|
||||
defs.add(FieldDef.section("ability.section.sounds").tab(TabTarget.EFFECTS));
|
||||
defs.add(FieldDef.soundSubGui("ability.windUpSound", this::getWindUpSound, this::setWindUpSound)
|
||||
.tab(TabTarget.EFFECTS));
|
||||
defs.add(FieldDef.soundSubGui("ability.activeSound", this::getActiveSound, this::setActiveSound)
|
||||
.tab(TabTarget.EFFECTS));
|
||||
defs.add(FieldDef.animSubGui("ability.windUpAnim",
|
||||
// Effects tab - Animations
|
||||
defs.add(FieldDef.section("ability.section.animations").tab(TabTarget.EFFECTS));
|
||||
defs.add(FieldDef.animSubGui("ability.windUpAnimation",
|
||||
this::getWindUpAnimationId, this::setWindUpAnimationId,
|
||||
this::getWindUpAnimationName, this::setWindUpAnimationName)
|
||||
.tab(TabTarget.EFFECTS));
|
||||
defs.add(FieldDef.animSubGui("ability.activeAnim",
|
||||
defs.add(FieldDef.animSubGui("ability.activeAnimation",
|
||||
this::getActiveAnimationId, this::setActiveAnimationId,
|
||||
this::getActiveAnimationName, this::setActiveAnimationName)
|
||||
.tab(TabTarget.EFFECTS));
|
||||
|
||||
// Effects tab - Telegraph
|
||||
TelegraphType tType = getTelegraphType();
|
||||
if (tType != null && tType != TelegraphType.NONE) {
|
||||
defs.add(FieldDef.section("ability.section.telegraph").tab(TabTarget.EFFECTS)
|
||||
.tooltip("telegraph." + tType.name().toLowerCase()));
|
||||
defs.add(FieldDef.boolField("ability.showTelegraph", this::isShowTelegraph, this::setShowTelegraph)
|
||||
.tab(TabTarget.EFFECTS).hover("ability.hover.showTelegraph"));
|
||||
defs.add(FieldDef.colorSubGui("ability.windUpColor", this::getWindUpColor, this::setWindUpColor)
|
||||
@@ -847,6 +871,7 @@ public abstract class Ability implements IAbility {
|
||||
nbt.setFloat("maxRange", maxRange);
|
||||
nbt.setInteger("cooldown", cooldownTicks);
|
||||
nbt.setInteger("windUp", windUpTicks);
|
||||
nbt.setBoolean("syncWindup", syncWindupWithAnimation);
|
||||
nbt.setInteger("recovery", dazedTicks);
|
||||
nbt.setBoolean("interruptible", interruptible);
|
||||
nbt.setInteger("lockMovement", lockMovement.ordinal());
|
||||
@@ -894,6 +919,7 @@ public abstract class Ability implements IAbility {
|
||||
maxRange = nbt.getFloat("maxRange");
|
||||
cooldownTicks = nbt.getInteger("cooldown");
|
||||
windUpTicks = nbt.getInteger("windUp");
|
||||
syncWindupWithAnimation = !nbt.hasKey("syncWindup") || nbt.getBoolean("syncWindup");
|
||||
dazedTicks = nbt.getInteger("recovery");
|
||||
interruptible = nbt.getBoolean("interruptible");
|
||||
lockMovement = LockMovementType.fromOrdinal(nbt.getInteger("lockMovement"));
|
||||
@@ -1036,6 +1062,10 @@ public abstract class Ability implements IAbility {
|
||||
}
|
||||
|
||||
public int getWindUpTicks() {
|
||||
return calculateWindupFromAnimation();
|
||||
}
|
||||
|
||||
public int getRawWindUpTicks() {
|
||||
return windUpTicks;
|
||||
}
|
||||
|
||||
@@ -1043,6 +1073,45 @@ public abstract class Ability implements IAbility {
|
||||
this.windUpTicks = Math.max(0, windUpTicks);
|
||||
}
|
||||
|
||||
public boolean isSyncWindupWithAnimation() {
|
||||
return syncWindupWithAnimation;
|
||||
}
|
||||
|
||||
public boolean hasWindUpAnimation() {
|
||||
return (windUpAnimationName != null && !windUpAnimationName.isEmpty()) || windUpAnimationId >= 0;
|
||||
}
|
||||
|
||||
public void setSyncWindupWithAnimation(boolean syncWindupWithAnimation) {
|
||||
this.syncWindupWithAnimation = syncWindupWithAnimation;
|
||||
}
|
||||
|
||||
private int calculateWindupFromAnimation() {
|
||||
if (!syncWindupWithAnimation) {
|
||||
return windUpTicks;
|
||||
}
|
||||
|
||||
if (AnimationController.Instance == null) {
|
||||
return windUpTicks;
|
||||
}
|
||||
|
||||
Animation animation = null;
|
||||
if (windUpAnimationName != null && !windUpAnimationName.isEmpty()) {
|
||||
animation = (Animation) AnimationController.Instance.get(windUpAnimationName);
|
||||
} else if (windUpAnimationId >= 0) {
|
||||
animation = (Animation) AnimationController.Instance.get(windUpAnimationId);
|
||||
}
|
||||
|
||||
if (animation == null || animation.frames.isEmpty()) {
|
||||
return windUpTicks;
|
||||
}
|
||||
|
||||
int totalDuration = 0;
|
||||
for (Frame frame : animation.frames) {
|
||||
totalDuration += frame.getDuration();
|
||||
}
|
||||
return totalDuration;
|
||||
}
|
||||
|
||||
public int getDazedTicks() {
|
||||
return dazedTicks;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,13 @@ public class AbilityEffect {
|
||||
return potionId;
|
||||
}
|
||||
|
||||
public static String[] getLangKeys() {
|
||||
EffectType[] types = values();
|
||||
String[] keys = new String[types.length];
|
||||
for (int i = 0; i < types.length; i++) keys[i] = types[i].langKey;
|
||||
return keys;
|
||||
}
|
||||
|
||||
public static EffectType fromOrdinal(int ordinal) {
|
||||
EffectType[] values = values();
|
||||
if (ordinal >= 0 && ordinal < values.length) {
|
||||
|
||||
@@ -52,4 +52,17 @@ public enum AnchorPoint {
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
switch (this) {
|
||||
case FRONT: return "ability.anchor.front";
|
||||
case CENTER: return "ability.anchor.center";
|
||||
case RIGHT_HAND: return "ability.anchor.rightHand";
|
||||
case LEFT_HAND: return "ability.anchor.leftHand";
|
||||
case ABOVE_HEAD: return "ability.anchor.aboveHead";
|
||||
case CHEST: return "ability.anchor.chest";
|
||||
default: return name();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,5 +22,16 @@ public enum TargetingMode {
|
||||
/**
|
||||
* AOE centered on target
|
||||
*/
|
||||
AOE_TARGET
|
||||
AOE_TARGET;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
switch (this) {
|
||||
case AGGRO_TARGET: return "ability.target.aggro_target";
|
||||
case SELF: return "ability.target.self";
|
||||
case AOE_SELF: return "ability.target.aoe_self";
|
||||
case AOE_TARGET: return "ability.target.aoe_target";
|
||||
default: return name();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package kamkeel.npcs.controllers.data.ability.gui;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.AbilityEffect;
|
||||
import noppes.npcs.client.gui.SubGuiColorSelector;
|
||||
import noppes.npcs.client.gui.advanced.ability.SubGuiAbilityEffects;
|
||||
import noppes.npcs.client.gui.select.GuiAnimationSelection;
|
||||
import noppes.npcs.client.gui.select.GuiSoundSelection;
|
||||
import noppes.npcs.client.gui.util.SubGuiInterface;
|
||||
@@ -26,6 +25,7 @@ public class FieldDef {
|
||||
private Supplier<Object> getter;
|
||||
private Consumer<Object> setter;
|
||||
private BooleanSupplier visibleWhen = () -> true;
|
||||
private BooleanSupplier enabledWhen = () -> true;
|
||||
private String tooltip = null;
|
||||
private String hoverText = null;
|
||||
|
||||
@@ -57,6 +57,10 @@ public class FieldDef {
|
||||
// STATIC FACTORIES
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
public static FieldDef section(String label) {
|
||||
return new FieldDef(label, FieldType.SECTION_HEADER);
|
||||
}
|
||||
|
||||
public static FieldDef floatField(String label, Supplier<Float> getter, Consumer<Float> setter) {
|
||||
FieldDef def = new FieldDef(label, FieldType.FLOAT);
|
||||
def.getter = () -> getter.get();
|
||||
@@ -102,6 +106,20 @@ public class FieldDef {
|
||||
return def;
|
||||
}
|
||||
|
||||
public static FieldDef labelField(String label, Supplier<String> textSupplier) {
|
||||
FieldDef def = new FieldDef(label, FieldType.LABEL);
|
||||
def.getter = () -> textSupplier.get();
|
||||
return def;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static FieldDef effectsListField(String label, Supplier<List<AbilityEffect>> getter, Consumer<List<AbilityEffect>> setter) {
|
||||
FieldDef def = new FieldDef(label, FieldType.EFFECTS_LIST);
|
||||
def.getter = () -> getter.get();
|
||||
def.setter = v -> setter.accept((List<AbilityEffect>) v);
|
||||
return def;
|
||||
}
|
||||
|
||||
public static FieldDef subGuiField(String label, Supplier<SubGuiInterface> factory, Consumer<SubGuiInterface> resultHandler) {
|
||||
FieldDef def = new FieldDef(label, FieldType.SUB_GUI);
|
||||
def.subGuiFactory = factory;
|
||||
@@ -121,15 +139,6 @@ public class FieldDef {
|
||||
.buttonTextColor(() -> getter.get() & 0xFFFFFF);
|
||||
}
|
||||
|
||||
public static FieldDef effectsSubGui(String label, Supplier<List<AbilityEffect>> getter, Consumer<List<AbilityEffect>> setter) {
|
||||
return subGuiField(label,
|
||||
() -> new SubGuiAbilityEffects(getter.get()),
|
||||
gui -> {
|
||||
List<AbilityEffect> r = ((SubGuiAbilityEffects) gui).getResult();
|
||||
if (r != null) setter.accept(r);
|
||||
});
|
||||
}
|
||||
|
||||
public static FieldDef soundSubGui(String label, Supplier<String> getter, Consumer<String> setter) {
|
||||
return subGuiField(label,
|
||||
() -> new GuiSoundSelection(getter.get()),
|
||||
@@ -139,7 +148,7 @@ public class FieldDef {
|
||||
})
|
||||
.buttonLabel(() -> {
|
||||
String s = getter.get();
|
||||
return s == null || s.isEmpty() ? "gui.none" : truncateEnd(s, 10);
|
||||
return s == null || s.isEmpty() ? "gui.none" : s;
|
||||
})
|
||||
.clearable(() -> setter.accept(""));
|
||||
}
|
||||
@@ -161,7 +170,7 @@ public class FieldDef {
|
||||
})
|
||||
.buttonLabel(() -> {
|
||||
String name = nameGetter.get();
|
||||
if (name != null && !name.isEmpty()) return truncateEnd(name, 8);
|
||||
if (name != null && !name.isEmpty()) return name;
|
||||
int id = idGetter.get();
|
||||
return id >= 0 ? "ID: " + id : "gui.none";
|
||||
})
|
||||
@@ -199,6 +208,11 @@ public class FieldDef {
|
||||
return this;
|
||||
}
|
||||
|
||||
public FieldDef enabledWhen(BooleanSupplier condition) {
|
||||
this.enabledWhen = condition;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FieldDef tooltip(String tooltip) {
|
||||
this.tooltip = tooltip;
|
||||
return this;
|
||||
@@ -234,6 +248,7 @@ public class FieldDef {
|
||||
public String getCustomTabName() { return customTabName; }
|
||||
public ColumnHint getColumn() { return column; }
|
||||
public boolean isVisible() { return visibleWhen.getAsBoolean(); }
|
||||
public boolean isEnabled() { return enabledWhen.getAsBoolean(); }
|
||||
public String getTooltip() { return tooltip; }
|
||||
public String getHoverText() { return hoverText; }
|
||||
public float getMin() { return min; }
|
||||
@@ -271,17 +286,4 @@ public class FieldDef {
|
||||
return buttonTextColorSupplier != null ? buttonTextColorSupplier.get() : null;
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// HELPERS
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
static String truncateEnd(String str, int maxLen) {
|
||||
if (str == null) return "";
|
||||
if (str.length() <= maxLen) return str;
|
||||
int lastSlash = str.lastIndexOf('/');
|
||||
if (lastSlash >= 0 && str.length() - lastSlash <= maxLen) {
|
||||
return "..." + str.substring(lastSlash);
|
||||
}
|
||||
return "..." + str.substring(str.length() - maxLen + 3);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,359 @@
|
||||
package kamkeel.npcs.controllers.data.ability.gui;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.AbilityEffect;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.util.StatCollector;
|
||||
import noppes.npcs.client.gui.util.GuiNpcButton;
|
||||
import noppes.npcs.client.gui.util.GuiNpcButtonYesNo;
|
||||
import noppes.npcs.client.gui.util.GuiNpcLabel;
|
||||
import noppes.npcs.client.gui.util.GuiNpcTextField;
|
||||
import noppes.npcs.client.gui.util.GuiScrollWindow;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Reusable builder that converts a list of {@link FieldDef} into positioned
|
||||
* GUI widgets inside a {@link GuiScrollWindow}.
|
||||
*/
|
||||
public class FieldDefinitionsBuilder {
|
||||
|
||||
// Layout defaults
|
||||
private int contentRight = 330;
|
||||
private int colLLabel = 5;
|
||||
private int colLField = 75;
|
||||
private int colLWidth = 70;
|
||||
private int colRLabel = 178;
|
||||
private int colRField = 248;
|
||||
private int colRWidth = 70;
|
||||
private int rowHeight = 24;
|
||||
private int labelPadding = 8;
|
||||
|
||||
// Dependencies
|
||||
private final GuiScreen parent;
|
||||
private final GuiScrollWindow sw;
|
||||
private final FontRenderer fontRenderer;
|
||||
|
||||
// ID counters
|
||||
private int widgetId;
|
||||
private int clearId;
|
||||
private int labelId;
|
||||
|
||||
// Starting Y
|
||||
private int startY = 5;
|
||||
|
||||
// Output maps
|
||||
private final Map<Integer, FieldDef> buttonFieldMap = new HashMap<>();
|
||||
private final Map<Integer, FieldDef> textFieldMap = new HashMap<>();
|
||||
private final Map<Integer, FieldDef> clearFieldMap = new HashMap<>();
|
||||
|
||||
// Effects list metadata: widgetId -> [effectIndex, action]
|
||||
// action: 0=type, 1=duration(text), 2=amp, 3=delete, 4=add
|
||||
private final Map<Integer, int[]> effectWidgetMeta = new HashMap<>();
|
||||
|
||||
public FieldDefinitionsBuilder(GuiScreen parent, GuiScrollWindow sw, FontRenderer fontRenderer) {
|
||||
this.parent = parent;
|
||||
this.sw = sw;
|
||||
this.fontRenderer = fontRenderer;
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// CONFIG CHAINING
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
public FieldDefinitionsBuilder contentRight(int v) { this.contentRight = v; return this; }
|
||||
public FieldDefinitionsBuilder startIds(int widget, int clear, int label) {
|
||||
this.widgetId = widget; this.clearId = clear; this.labelId = label; return this;
|
||||
}
|
||||
public FieldDefinitionsBuilder startY(int y) { this.startY = y; return this; }
|
||||
public FieldDefinitionsBuilder rowHeight(int h) { this.rowHeight = h; return this; }
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// BUILD
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* Processes all fields and adds widgets to the scroll window.
|
||||
* @return the final Y position after all fields
|
||||
*/
|
||||
public int build(List<FieldDef> fields) {
|
||||
buttonFieldMap.clear();
|
||||
textFieldMap.clear();
|
||||
clearFieldMap.clear();
|
||||
effectWidgetMeta.clear();
|
||||
|
||||
int y = startY;
|
||||
|
||||
for (int i = 0; i < fields.size(); i++) {
|
||||
FieldDef def = fields.get(i);
|
||||
|
||||
// Section header
|
||||
if (def.getType() == FieldType.SECTION_HEADER) {
|
||||
y += 3;
|
||||
String sectionText = StatCollector.translateToLocal(def.getLabel());
|
||||
if (def.getTooltip() != null && !def.getTooltip().isEmpty()) {
|
||||
sectionText += " (" + StatCollector.translateToLocal(def.getTooltip()) + ")";
|
||||
}
|
||||
sw.addLabel(new GuiNpcLabel(labelId++, sectionText, colLLabel, y + 2, 0xFFFF55));
|
||||
y += 15;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Effects list renders its own multi-row block
|
||||
if (def.getType() == FieldType.EFFECTS_LIST) {
|
||||
y = renderEffectsList(def, y);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Two-column pair: LEFT followed by RIGHT
|
||||
if (def.getColumn() == ColumnHint.LEFT
|
||||
&& i + 1 < fields.size()
|
||||
&& fields.get(i + 1).getColumn() == ColumnHint.RIGHT
|
||||
&& fields.get(i + 1).getType() != FieldType.SECTION_HEADER) {
|
||||
renderFieldAt(def, colLLabel, colLField, colLWidth, y);
|
||||
|
||||
i++;
|
||||
FieldDef rightDef = fields.get(i);
|
||||
renderFieldAt(rightDef, colRLabel, colRField, colRWidth, y);
|
||||
|
||||
y += rowHeight;
|
||||
} else {
|
||||
// Full-width: compute fieldX from label pixel width
|
||||
int fieldW = getFullFieldWidth(def);
|
||||
String translated = StatCollector.translateToLocal(def.getLabel());
|
||||
int labelW = fontRenderer.getStringWidth(translated);
|
||||
int fieldX = colLLabel + labelW + labelPadding;
|
||||
|
||||
renderFieldAt(def, colLLabel, fieldX, fieldW, y);
|
||||
y += rowHeight;
|
||||
}
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// FIELD RENDERING
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private void renderFieldAt(FieldDef def, int labelX, int fieldX, int fieldW, int y) {
|
||||
sw.addLabel(new GuiNpcLabel(labelId++, def.getLabel(), labelX, y + 5, 0xFFFFFF));
|
||||
|
||||
String hover = def.getHoverText() != null ? def.getHoverText() : def.getTooltip();
|
||||
|
||||
switch (def.getType()) {
|
||||
case FLOAT: {
|
||||
float fVal = def.getValue() instanceof Number ? ((Number) def.getValue()).floatValue() : 0f;
|
||||
GuiNpcTextField tf = new GuiNpcTextField(widgetId, parent, fontRenderer, fieldX, y, fieldW, 20, String.valueOf(fVal));
|
||||
tf.setFloatsOnly();
|
||||
if (def.hasRange()) tf.setMinMaxDefaultFloat(def.getMin(), def.getMax(), fVal);
|
||||
if (!def.isEnabled()) tf.setEnabled(false);
|
||||
if (hover != null) tf.setHoverText(hover);
|
||||
sw.addTextField(tf);
|
||||
textFieldMap.put(widgetId, def);
|
||||
widgetId++;
|
||||
clearId++;
|
||||
break;
|
||||
}
|
||||
case INT: {
|
||||
int iVal = def.getValue() instanceof Number ? ((Number) def.getValue()).intValue() : 0;
|
||||
GuiNpcTextField tf = new GuiNpcTextField(widgetId, parent, fontRenderer, fieldX, y, fieldW, 20, String.valueOf(iVal));
|
||||
tf.setIntegersOnly();
|
||||
if (def.hasRange()) tf.setMinMaxDefault((int) def.getMin(), (int) def.getMax(), iVal);
|
||||
if (!def.isEnabled()) tf.setEnabled(false);
|
||||
if (hover != null) tf.setHoverText(hover);
|
||||
sw.addTextField(tf);
|
||||
textFieldMap.put(widgetId, def);
|
||||
widgetId++;
|
||||
clearId++;
|
||||
break;
|
||||
}
|
||||
case STRING: {
|
||||
String sVal = def.getValue() != null ? def.getValue().toString() : "";
|
||||
GuiNpcTextField tf = new GuiNpcTextField(widgetId, parent, fontRenderer, fieldX, y, fieldW, 20, sVal);
|
||||
if (!def.isEnabled()) tf.setEnabled(false);
|
||||
if (hover != null) tf.setHoverText(hover);
|
||||
sw.addTextField(tf);
|
||||
textFieldMap.put(widgetId, def);
|
||||
widgetId++;
|
||||
clearId++;
|
||||
break;
|
||||
}
|
||||
case LABEL: {
|
||||
String text = def.getValue() != null ? def.getValue().toString() : "";
|
||||
sw.addLabel(new GuiNpcLabel(labelId++, text, fieldX, y + 5, 0xAAAAAA));
|
||||
widgetId++;
|
||||
clearId++;
|
||||
break;
|
||||
}
|
||||
case BOOLEAN: {
|
||||
boolean bVal = def.getValue() instanceof Boolean ? (Boolean) def.getValue() : false;
|
||||
GuiNpcButtonYesNo btn = new GuiNpcButtonYesNo(widgetId, fieldX, y, fieldW, 20, bVal);
|
||||
if ("gui.enabled".equals(def.getLabel()) && def.getTab() == TabTarget.GENERAL) {
|
||||
btn.setTextColor(bVal ? 0x00FF00 : 0xFF0000);
|
||||
}
|
||||
if (!def.isEnabled()) btn.setEnabled(false);
|
||||
if (hover != null) btn.setHoverText(hover);
|
||||
sw.addButton(btn);
|
||||
buttonFieldMap.put(widgetId, def);
|
||||
widgetId++;
|
||||
clearId++;
|
||||
break;
|
||||
}
|
||||
case ENUM: {
|
||||
Class<? extends Enum<?>> enumClass = def.getEnumClass();
|
||||
if (enumClass != null) {
|
||||
Enum<?>[] constants = enumClass.getEnumConstants();
|
||||
String[] names = new String[constants.length];
|
||||
for (int i = 0; i < constants.length; i++) names[i] = constants[i].toString();
|
||||
int selected = def.getValue() instanceof Enum ? ((Enum<?>) def.getValue()).ordinal() : 0;
|
||||
GuiNpcButton btn = new GuiNpcButton(widgetId, fieldX, y, fieldW, 20, names, selected);
|
||||
if (!def.isEnabled()) btn.setEnabled(false);
|
||||
if (hover != null) btn.setHoverText(hover);
|
||||
sw.addButton(btn);
|
||||
buttonFieldMap.put(widgetId, def);
|
||||
}
|
||||
widgetId++;
|
||||
clearId++;
|
||||
break;
|
||||
}
|
||||
case STRING_ENUM: {
|
||||
String[] values = def.getStringEnumValues();
|
||||
if (values != null && values.length > 0) {
|
||||
String curVal = def.getStringEnumValue();
|
||||
int selected = 0;
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
if (values[i].equals(curVal)) { selected = i; break; }
|
||||
}
|
||||
GuiNpcButton btn = new GuiNpcButton(widgetId, fieldX, y, fieldW, 20, values, selected);
|
||||
if (!def.isEnabled()) btn.setEnabled(false);
|
||||
if (hover != null) btn.setHoverText(hover);
|
||||
sw.addButton(btn);
|
||||
buttonFieldMap.put(widgetId, def);
|
||||
}
|
||||
widgetId++;
|
||||
clearId++;
|
||||
break;
|
||||
}
|
||||
case SUB_GUI: {
|
||||
String btnText = def.getButtonLabel();
|
||||
int btnW;
|
||||
if (def.hasClearAction()) {
|
||||
btnW = contentRight - 22 - fieldX;
|
||||
GuiNpcButton clearBtn = new GuiNpcButton(clearId, contentRight - 20, y, 20, 20, "X");
|
||||
sw.addButton(clearBtn);
|
||||
clearFieldMap.put(clearId, def);
|
||||
} else {
|
||||
btnW = contentRight - fieldX;
|
||||
}
|
||||
GuiNpcButton btn = new GuiNpcButton(widgetId, fieldX, y, btnW, 20, btnText);
|
||||
Integer textColor = def.getButtonTextColor();
|
||||
if (textColor != null) btn.setTextColor(textColor);
|
||||
if (!def.isEnabled()) btn.setEnabled(false);
|
||||
if (hover != null) btn.setHoverText(hover);
|
||||
sw.addButton(btn);
|
||||
buttonFieldMap.put(widgetId, def);
|
||||
widgetId++;
|
||||
clearId++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// EFFECTS LIST RENDERING
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private int renderEffectsList(FieldDef def, int y) {
|
||||
// Section header
|
||||
y += 3;
|
||||
sw.addLabel(new GuiNpcLabel(labelId++, def.getLabel(), colLLabel, y + 2, 0xFFFF55));
|
||||
y += 15;
|
||||
|
||||
List<AbilityEffect> effects = (List<AbilityEffect>) def.getValue();
|
||||
if (effects == null) effects = new ArrayList<>();
|
||||
|
||||
String[] typeNames = AbilityEffect.EffectType.getLangKeys();
|
||||
String[] ampValues = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
|
||||
|
||||
for (int e = 0; e < effects.size() && e < 5; e++) {
|
||||
AbilityEffect effect = effects.get(e);
|
||||
|
||||
// Type selector button
|
||||
int typeIdx = effect.getType().ordinal();
|
||||
GuiNpcButton typeBtn = new GuiNpcButton(widgetId, colLLabel, y, 100, 20, typeNames, typeIdx);
|
||||
sw.addButton(typeBtn);
|
||||
buttonFieldMap.put(widgetId, def);
|
||||
effectWidgetMeta.put(widgetId, new int[]{e, 0});
|
||||
widgetId++;
|
||||
|
||||
// Duration text field
|
||||
GuiNpcTextField durField = new GuiNpcTextField(widgetId, parent, fontRenderer,
|
||||
colLLabel + 104, y, 50, 20, String.valueOf(effect.getDurationTicks()));
|
||||
durField.setIntegersOnly();
|
||||
durField.setMinMaxDefault(1, 12000, 60);
|
||||
sw.addTextField(durField);
|
||||
textFieldMap.put(widgetId, def);
|
||||
effectWidgetMeta.put(widgetId, new int[]{e, 1});
|
||||
widgetId++;
|
||||
|
||||
// Amplifier selector (0-10)
|
||||
GuiNpcButton ampBtn = new GuiNpcButton(widgetId, colLLabel + 158, y, 40, 20, ampValues, effect.getAmplifier());
|
||||
sw.addButton(ampBtn);
|
||||
buttonFieldMap.put(widgetId, def);
|
||||
effectWidgetMeta.put(widgetId, new int[]{e, 2});
|
||||
widgetId++;
|
||||
|
||||
// Delete button
|
||||
GuiNpcButton delBtn = new GuiNpcButton(clearId, colLLabel + 202, y, 20, 20, "X");
|
||||
sw.addButton(delBtn);
|
||||
clearFieldMap.put(clearId, def);
|
||||
effectWidgetMeta.put(clearId, new int[]{e, 3});
|
||||
clearId++;
|
||||
|
||||
y += rowHeight;
|
||||
}
|
||||
|
||||
// Add button (if < 5 effects)
|
||||
if (effects.size() < 5) {
|
||||
GuiNpcButton addBtn = new GuiNpcButton(widgetId, colLLabel, y, 50, 20, "gui.add");
|
||||
sw.addButton(addBtn);
|
||||
buttonFieldMap.put(widgetId, def);
|
||||
effectWidgetMeta.put(widgetId, new int[]{effects.size(), 4});
|
||||
widgetId++;
|
||||
clearId++;
|
||||
y += rowHeight;
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
private int getFullFieldWidth(FieldDef def) {
|
||||
switch (def.getType()) {
|
||||
case FLOAT:
|
||||
case INT: return 60;
|
||||
case STRING: return 200;
|
||||
case BOOLEAN: return 50;
|
||||
case LABEL: return 60;
|
||||
case ENUM:
|
||||
case STRING_ENUM: return 120;
|
||||
case SUB_GUI: return def.hasClearAction() ? 175 : 200;
|
||||
default: return 80;
|
||||
}
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// GETTERS
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
public Map<Integer, FieldDef> getButtonFieldMap() { return buttonFieldMap; }
|
||||
public Map<Integer, FieldDef> getTextFieldMap() { return textFieldMap; }
|
||||
public Map<Integer, FieldDef> getClearFieldMap() { return clearFieldMap; }
|
||||
public Map<Integer, int[]> getEffectWidgetMeta() { return effectWidgetMeta; }
|
||||
public int getNextLabelId() { return labelId; }
|
||||
}
|
||||
@@ -7,5 +7,8 @@ public enum FieldType {
|
||||
ENUM,
|
||||
STRING_ENUM,
|
||||
SUB_GUI,
|
||||
STRING
|
||||
STRING,
|
||||
SECTION_HEADER,
|
||||
LABEL,
|
||||
EFFECTS_LIST
|
||||
}
|
||||
@@ -5,6 +5,5 @@ public enum TabTarget {
|
||||
TYPE,
|
||||
TARGET,
|
||||
EFFECTS,
|
||||
VISUAL,
|
||||
CUSTOM
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import net.minecraft.util.Vec3;
|
||||
import net.minecraft.world.World;
|
||||
import noppes.npcs.entity.EntityNPCInterface;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.gui.ColumnHint;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.FieldDef;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.TabTarget;
|
||||
import noppes.npcs.api.ability.type.IAbilityCharge;
|
||||
@@ -403,11 +404,11 @@ public class AbilityCharge extends Ability implements IAbilityCharge {
|
||||
@Override
|
||||
public List<FieldDef> getFieldDefinitions() {
|
||||
return Arrays.asList(
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage),
|
||||
FieldDef.floatField("stats.speed", this::getChargeSpeed, this::setChargeSpeed),
|
||||
FieldDef.floatField("ability.knockback", this::getKnockback, this::setKnockback),
|
||||
FieldDef.floatField("ability.hitWidth", this::getHitWidth, this::setHitWidth),
|
||||
FieldDef.effectsSubGui("ability.effects", this::getEffects, this::setEffects)
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("ability.chargeSpeed", this::getChargeSpeed, this::setChargeSpeed).column(ColumnHint.RIGHT),
|
||||
FieldDef.floatField("ability.knockback", this::getKnockback, this::setKnockback).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("ability.hitWidth", this::getHitWidth, this::setHitWidth).column(ColumnHint.RIGHT),
|
||||
FieldDef.effectsListField("ability.effects", this::getEffects, this::setEffects)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import noppes.npcs.entity.EntityNPCInterface;
|
||||
|
||||
import noppes.npcs.api.ability.type.IAbilityCutter;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.gui.ColumnHint;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.FieldDef;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.TabTarget;
|
||||
|
||||
@@ -30,7 +31,16 @@ public class AbilityCutter extends Ability implements IAbilityCutter {
|
||||
|
||||
public enum SweepMode {
|
||||
SWIPE,
|
||||
SPIN
|
||||
SPIN;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
switch (this) {
|
||||
case SWIPE: return "ability.sweep.swipe";
|
||||
case SPIN: return "ability.sweep.spin";
|
||||
default: return name();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private float arcAngle = 90.0f;
|
||||
@@ -308,20 +318,21 @@ public class AbilityCutter extends Ability implements IAbilityCutter {
|
||||
@Override
|
||||
public List<FieldDef> getFieldDefinitions() {
|
||||
return Arrays.asList(
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage),
|
||||
FieldDef.floatField("gui.range", this::getRange, this::setRange),
|
||||
FieldDef.floatField("ability.arcAngle", this::getArcAngle, this::setArcAngle),
|
||||
FieldDef.floatField("ability.innerRadius", this::getInnerRadius, this::setInnerRadius),
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("gui.range", this::getRange, this::setRange).column(ColumnHint.RIGHT),
|
||||
FieldDef.floatField("ability.knockback", this::getKnockback, this::setKnockback),
|
||||
FieldDef.floatField("ability.sweepSpeed", this::getSweepSpeed, this::setSweepSpeed),
|
||||
FieldDef.section("ability.section.sweep"),
|
||||
FieldDef.enumField("ability.sweepMode", SweepMode.class, this::getSweepModeEnum, this::setSweepModeEnum)
|
||||
.hover("ability.hover.sweepMode"),
|
||||
FieldDef.boolField("ability.piercing", this::isPiercing, this::setPiercing)
|
||||
.hover("ability.hover.piercing"),
|
||||
FieldDef.intField("ability.duration", this::getSpinDurationTicks, this::setSpinDurationTicks)
|
||||
FieldDef.floatField("ability.arcAngle", this::getArcAngle, this::setArcAngle).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("ability.innerRadius", this::getInnerRadius, this::setInnerRadius).column(ColumnHint.RIGHT),
|
||||
FieldDef.floatField("ability.sweepSpeed", this::getSweepSpeed, this::setSweepSpeed),
|
||||
FieldDef.intField("ability.spinDuration", this::getSpinDurationTicks, this::setSpinDurationTicks)
|
||||
.range(1, 1000)
|
||||
.visibleWhen(() -> this.getSweepModeEnum() == SweepMode.SPIN),
|
||||
FieldDef.effectsSubGui("ability.effects", this::getEffects, this::setEffects)
|
||||
FieldDef.boolField("ability.piercing", this::isPiercing, this::setPiercing)
|
||||
.hover("ability.hover.piercing"),
|
||||
FieldDef.effectsListField("ability.effects", this::getEffects, this::setEffects)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import net.minecraft.util.Vec3;
|
||||
import net.minecraft.world.World;
|
||||
import noppes.npcs.entity.EntityNPCInterface;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.gui.ColumnHint;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.FieldDef;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.TabTarget;
|
||||
import noppes.npcs.api.ability.type.IAbilityDash;
|
||||
@@ -31,7 +32,16 @@ public class AbilityDash extends Ability implements IAbilityDash {
|
||||
*/
|
||||
public enum DashMode {
|
||||
AGGRESSIVE,
|
||||
DEFENSIVE
|
||||
DEFENSIVE;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
switch (this) {
|
||||
case AGGRESSIVE: return "ability.dash.aggressive";
|
||||
case DEFENSIVE: return "ability.dash.defensive";
|
||||
default: return name();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -347,10 +357,10 @@ public class AbilityDash extends Ability implements IAbilityDash {
|
||||
@Override
|
||||
public List<FieldDef> getFieldDefinitions() {
|
||||
return Arrays.asList(
|
||||
FieldDef.enumField("ability.mode", DashMode.class, this::getDashModeEnum, this::setDashModeEnum)
|
||||
FieldDef.enumField("ability.dashMode", DashMode.class, this::getDashModeEnum, this::setDashModeEnum)
|
||||
.hover("ability.hover.dashMode"),
|
||||
FieldDef.floatField("ability.dashDist", this::getDashDistance, this::setDashDistance),
|
||||
FieldDef.floatField("ability.dashSpeed", this::getDashSpeed, this::setDashSpeed)
|
||||
FieldDef.floatField("ability.dashDistance", this::getDashDistance, this::setDashDistance).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("ability.dashSpeed", this::getDashSpeed, this::setDashSpeed).column(ColumnHint.RIGHT)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,8 @@ import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.Vec3;
|
||||
import net.minecraft.world.World;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.ColumnHint;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.FieldDef;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.TabTarget;
|
||||
import noppes.npcs.api.ability.type.IAbilityDisc;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -280,51 +280,53 @@ public class AbilityDisc extends Ability implements IAbilityDisc {
|
||||
public List<FieldDef> getFieldDefinitions() {
|
||||
return Arrays.asList(
|
||||
// Type tab
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage),
|
||||
FieldDef.floatField("stats.speed", this::getSpeed, this::setSpeed),
|
||||
FieldDef.floatField("ability.discRadius", this::getDiscRadius, this::setDiscRadius),
|
||||
FieldDef.floatField("ability.discThickness", this::getDiscThickness, this::setDiscThickness),
|
||||
FieldDef.boolField("ability.homing", this::isHoming, this::setHoming)
|
||||
.hover("ability.hover.homing"),
|
||||
FieldDef.floatField("ability.homingStr", this::getHomingStrength, this::setHomingStrength)
|
||||
.visibleWhen(this::isHoming),
|
||||
FieldDef.boolField("ability.boomerang", this::isBoomerang, this::setBoomerang)
|
||||
.hover("ability.hover.boomerang"),
|
||||
FieldDef.intField("ability.boomerangDelay", this::getBoomerangDelay, this::setBoomerangDelay)
|
||||
.visibleWhen(this::isBoomerang),
|
||||
FieldDef.boolField("ability.explosive", this::isExplosive, this::setExplosive)
|
||||
.hover("ability.hover.explosive"),
|
||||
FieldDef.floatField("ability.explosionRad", this::getExplosionRadius, this::setExplosionRadius)
|
||||
.visibleWhen(this::isExplosive),
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("stats.speed", this::getSpeed, this::setSpeed).column(ColumnHint.RIGHT),
|
||||
FieldDef.floatField("ability.knockback", this::getKnockback, this::setKnockback),
|
||||
FieldDef.floatField("ability.maxDist", this::getMaxDistance, this::setMaxDistance),
|
||||
FieldDef.intField("ability.lifetime", this::getMaxLifetime, this::setMaxLifetime),
|
||||
FieldDef.effectsSubGui("ability.effects", this::getEffects, this::setEffects),
|
||||
FieldDef.section("ability.section.disc"),
|
||||
FieldDef.floatField("gui.radius", this::getDiscRadius, this::setDiscRadius).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("gui.thickness", this::getDiscThickness, this::setDiscThickness).column(ColumnHint.RIGHT),
|
||||
FieldDef.floatField("ability.maxDistance", this::getMaxDistance, this::setMaxDistance).column(ColumnHint.LEFT),
|
||||
FieldDef.intField("ability.lifetime", this::getMaxLifetime, this::setMaxLifetime).column(ColumnHint.RIGHT),
|
||||
FieldDef.section("ability.section.homing"),
|
||||
FieldDef.boolField("gui.enabled", this::isHoming, this::setHoming)
|
||||
.hover("ability.hover.homing"),
|
||||
FieldDef.floatField("gui.strength", this::getHomingStrength, this::setHomingStrength)
|
||||
.visibleWhen(this::isHoming),
|
||||
FieldDef.section("ability.section.boomerang"),
|
||||
FieldDef.boolField("gui.enabled", this::isBoomerang, this::setBoomerang)
|
||||
.hover("ability.hover.boomerang"),
|
||||
FieldDef.intField("gui.delay", this::getBoomerangDelay, this::setBoomerangDelay)
|
||||
.visibleWhen(this::isBoomerang),
|
||||
FieldDef.section("ability.section.explosive"),
|
||||
FieldDef.boolField("gui.enabled", this::isExplosive, this::setExplosive)
|
||||
.hover("ability.hover.explosive"),
|
||||
FieldDef.floatField("gui.radius", this::getExplosionRadius, this::setExplosionRadius)
|
||||
.visibleWhen(this::isExplosive),
|
||||
FieldDef.effectsListField("ability.effects", this::getEffects, this::setEffects),
|
||||
// Visual tab
|
||||
FieldDef.enumField("ability.anchorPoint", AnchorPoint.class, this::getAnchorPointEnum, this::setAnchorPointEnum)
|
||||
.tab(TabTarget.VISUAL),
|
||||
.customTab("ability.tab.visual"),
|
||||
FieldDef.section("ability.section.colors").customTab("ability.tab.visual"),
|
||||
FieldDef.colorSubGui("ability.innerColor", this::getInnerColor, this::setInnerColor)
|
||||
.tab(TabTarget.VISUAL),
|
||||
FieldDef.colorSubGui("ability.outerColor", this::getOuterColor, this::setOuterColor)
|
||||
.tab(TabTarget.VISUAL),
|
||||
.customTab("ability.tab.visual"),
|
||||
FieldDef.boolField("ability.outerEnabled", this::isOuterColorEnabled, this::setOuterColorEnabled)
|
||||
.tab(TabTarget.VISUAL),
|
||||
.customTab("ability.tab.visual"),
|
||||
FieldDef.colorSubGui("ability.outerColor", this::getOuterColor, this::setOuterColor)
|
||||
.customTab("ability.tab.visual").visibleWhen(this::isOuterColorEnabled),
|
||||
FieldDef.floatField("ability.outerWidth", this::getOuterColorWidth, this::setOuterColorWidth)
|
||||
.tab(TabTarget.VISUAL)
|
||||
.visibleWhen(this::isOuterColorEnabled),
|
||||
.customTab("ability.tab.visual").visibleWhen(this::isOuterColorEnabled).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("ability.outerAlpha", this::getOuterColorAlpha, this::setOuterColorAlpha)
|
||||
.tab(TabTarget.VISUAL).range(0, 1)
|
||||
.visibleWhen(this::isOuterColorEnabled),
|
||||
.customTab("ability.tab.visual").range(0, 1).visibleWhen(this::isOuterColorEnabled).column(ColumnHint.RIGHT),
|
||||
FieldDef.section("ability.section.effects").customTab("ability.tab.visual"),
|
||||
FieldDef.floatField("ability.rotationSpeed", this::getRotationSpeed, this::setRotationSpeed)
|
||||
.tab(TabTarget.VISUAL),
|
||||
.customTab("ability.tab.visual"),
|
||||
FieldDef.boolField("ability.lightning", this::hasLightningEffect, this::setLightningEffect)
|
||||
.tab(TabTarget.VISUAL),
|
||||
FieldDef.floatField("ability.lightningDensity", this::getLightningDensity, this::setLightningDensity)
|
||||
.tab(TabTarget.VISUAL).range(0.01f, 5.0f)
|
||||
.visibleWhen(this::hasLightningEffect),
|
||||
FieldDef.floatField("ability.lightningRadius", this::getLightningRadius, this::setLightningRadius)
|
||||
.tab(TabTarget.VISUAL).range(0.1f, 10.0f)
|
||||
.visibleWhen(this::hasLightningEffect)
|
||||
.customTab("ability.tab.visual"),
|
||||
FieldDef.floatField("gui.density", this::getLightningDensity, this::setLightningDensity)
|
||||
.customTab("ability.tab.visual").range(0.01f, 5.0f).visibleWhen(this::hasLightningEffect).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("gui.radius", this::getLightningRadius, this::setLightningRadius)
|
||||
.customTab("ability.tab.visual").range(0.1f, 10.0f).visibleWhen(this::hasLightningEffect).column(ColumnHint.RIGHT)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,8 @@ import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.Vec3;
|
||||
import net.minecraft.world.World;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.ColumnHint;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.FieldDef;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.TabTarget;
|
||||
import noppes.npcs.api.ability.type.IAbilityEnergyBeam;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -283,49 +283,50 @@ public class AbilityEnergyBeam extends Ability implements IAbilityEnergyBeam {
|
||||
public List<FieldDef> getFieldDefinitions() {
|
||||
return Arrays.asList(
|
||||
// Type tab
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage),
|
||||
FieldDef.floatField("stats.speed", this::getSpeed, this::setSpeed),
|
||||
FieldDef.floatField("ability.beamWidth", this::getBeamWidth, this::setBeamWidth),
|
||||
FieldDef.floatField("ability.headSize", this::getHeadSize, this::setHeadSize),
|
||||
FieldDef.boolField("ability.homing", this::isHoming, this::setHoming)
|
||||
.hover("ability.hover.homing"),
|
||||
FieldDef.floatField("ability.homingStr", this::getHomingStrength, this::setHomingStrength)
|
||||
.visibleWhen(this::isHoming),
|
||||
FieldDef.floatField("ability.homingRange", this::getHomingRange, this::setHomingRange)
|
||||
.visibleWhen(this::isHoming),
|
||||
FieldDef.floatField("ability.maxDist", this::getMaxDistance, this::setMaxDistance),
|
||||
FieldDef.boolField("ability.explosive", this::isExplosive, this::setExplosive)
|
||||
.hover("ability.hover.explosive"),
|
||||
FieldDef.floatField("ability.explosionRad", this::getExplosionRadius, this::setExplosionRadius)
|
||||
.visibleWhen(this::isExplosive),
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("stats.speed", this::getSpeed, this::setSpeed).column(ColumnHint.RIGHT),
|
||||
FieldDef.floatField("ability.knockback", this::getKnockback, this::setKnockback),
|
||||
FieldDef.intField("ability.lifetime", this::getMaxLifetime, this::setMaxLifetime),
|
||||
FieldDef.effectsSubGui("ability.effects", this::getEffects, this::setEffects),
|
||||
FieldDef.section("ability.section.beam"),
|
||||
FieldDef.floatField("ability.beamWidth", this::getBeamWidth, this::setBeamWidth).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("ability.headSize", this::getHeadSize, this::setHeadSize).column(ColumnHint.RIGHT),
|
||||
FieldDef.floatField("ability.maxDistance", this::getMaxDistance, this::setMaxDistance).column(ColumnHint.LEFT),
|
||||
FieldDef.intField("ability.lifetime", this::getMaxLifetime, this::setMaxLifetime).column(ColumnHint.RIGHT),
|
||||
FieldDef.section("ability.section.homing"),
|
||||
FieldDef.boolField("gui.enabled", this::isHoming, this::setHoming)
|
||||
.hover("ability.hover.homing"),
|
||||
FieldDef.floatField("gui.strength", this::getHomingStrength, this::setHomingStrength)
|
||||
.visibleWhen(this::isHoming).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("gui.range", this::getHomingRange, this::setHomingRange)
|
||||
.visibleWhen(this::isHoming).column(ColumnHint.RIGHT),
|
||||
FieldDef.section("ability.section.explosive"),
|
||||
FieldDef.boolField("gui.enabled", this::isExplosive, this::setExplosive)
|
||||
.hover("ability.hover.explosive"),
|
||||
FieldDef.floatField("gui.radius", this::getExplosionRadius, this::setExplosionRadius)
|
||||
.visibleWhen(this::isExplosive),
|
||||
FieldDef.effectsListField("ability.effects", this::getEffects, this::setEffects),
|
||||
// Visual tab
|
||||
FieldDef.enumField("ability.anchorPoint", AnchorPoint.class, this::getAnchorPointEnum, this::setAnchorPointEnum)
|
||||
.tab(TabTarget.VISUAL),
|
||||
.customTab("ability.tab.visual"),
|
||||
FieldDef.section("ability.section.colors").customTab("ability.tab.visual"),
|
||||
FieldDef.colorSubGui("ability.innerColor", this::getInnerColor, this::setInnerColor)
|
||||
.tab(TabTarget.VISUAL),
|
||||
FieldDef.colorSubGui("ability.outerColor", this::getOuterColor, this::setOuterColor)
|
||||
.tab(TabTarget.VISUAL),
|
||||
.customTab("ability.tab.visual"),
|
||||
FieldDef.boolField("ability.outerEnabled", this::isOuterColorEnabled, this::setOuterColorEnabled)
|
||||
.tab(TabTarget.VISUAL),
|
||||
.customTab("ability.tab.visual"),
|
||||
FieldDef.colorSubGui("ability.outerColor", this::getOuterColor, this::setOuterColor)
|
||||
.customTab("ability.tab.visual").visibleWhen(this::isOuterColorEnabled),
|
||||
FieldDef.floatField("ability.outerWidth", this::getOuterColorWidth, this::setOuterColorWidth)
|
||||
.tab(TabTarget.VISUAL)
|
||||
.visibleWhen(this::isOuterColorEnabled),
|
||||
.customTab("ability.tab.visual").visibleWhen(this::isOuterColorEnabled).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("ability.outerAlpha", this::getOuterColorAlpha, this::setOuterColorAlpha)
|
||||
.tab(TabTarget.VISUAL).range(0, 1)
|
||||
.visibleWhen(this::isOuterColorEnabled),
|
||||
.customTab("ability.tab.visual").range(0, 1).visibleWhen(this::isOuterColorEnabled).column(ColumnHint.RIGHT),
|
||||
FieldDef.section("ability.section.effects").customTab("ability.tab.visual"),
|
||||
FieldDef.floatField("ability.rotationSpeed", this::getRotationSpeed, this::setRotationSpeed)
|
||||
.tab(TabTarget.VISUAL),
|
||||
.customTab("ability.tab.visual"),
|
||||
FieldDef.boolField("ability.lightning", this::hasLightningEffect, this::setLightningEffect)
|
||||
.tab(TabTarget.VISUAL),
|
||||
FieldDef.floatField("ability.lightningDensity", this::getLightningDensity, this::setLightningDensity)
|
||||
.tab(TabTarget.VISUAL).range(0.01f, 5.0f)
|
||||
.visibleWhen(this::hasLightningEffect),
|
||||
FieldDef.floatField("ability.lightningRadius", this::getLightningRadius, this::setLightningRadius)
|
||||
.tab(TabTarget.VISUAL).range(0.1f, 10.0f)
|
||||
.visibleWhen(this::hasLightningEffect)
|
||||
.customTab("ability.tab.visual"),
|
||||
FieldDef.floatField("gui.density", this::getLightningDensity, this::setLightningDensity)
|
||||
.customTab("ability.tab.visual").range(0.01f, 5.0f).visibleWhen(this::hasLightningEffect).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("gui.radius", this::getLightningRadius, this::setLightningRadius)
|
||||
.customTab("ability.tab.visual").range(0.1f, 10.0f).visibleWhen(this::hasLightningEffect).column(ColumnHint.RIGHT)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import noppes.npcs.entity.EntityNPCInterface;
|
||||
|
||||
import noppes.npcs.api.ability.type.IAbilityGuard;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.gui.ColumnHint;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.FieldDef;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.TabTarget;
|
||||
|
||||
@@ -44,7 +45,16 @@ public class AbilityGuard extends Ability implements IAbilityGuard {
|
||||
|
||||
public enum CounterType {
|
||||
FLAT,
|
||||
PERCENT
|
||||
PERCENT;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
switch (this) {
|
||||
case FLAT: return "ability.counter.flat";
|
||||
case PERCENT: return "ability.counter.percent";
|
||||
default: return name();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AbilityGuard() {
|
||||
@@ -287,23 +297,21 @@ public class AbilityGuard extends Ability implements IAbilityGuard {
|
||||
@Override
|
||||
public List<FieldDef> getFieldDefinitions() {
|
||||
return Arrays.asList(
|
||||
FieldDef.intField("ability.duration", this::getDurationTicks, this::setDurationTicks)
|
||||
.range(1, 1000),
|
||||
FieldDef.floatField("ability.dmgReduce", this::getDamageReduction, this::setDamageReduction),
|
||||
FieldDef.boolField("ability.canCounter", this::isCanCounter, this::setCanCounter)
|
||||
.hover("ability.hover.canCounter"),
|
||||
FieldDef.enumField("ability.counterType", CounterType.class, this::getCounterTypeEnum, this::setCounterTypeEnum)
|
||||
.hover("ability.hover.counterType")
|
||||
FieldDef.intField("ability.duration", this::getDurationTicks, this::setDurationTicks).range(1, 1000),
|
||||
FieldDef.floatField("ability.damageReduction", this::getDamageReduction, this::setDamageReduction),
|
||||
FieldDef.section("ability.section.counter"),
|
||||
FieldDef.boolField("gui.enabled", this::isCanCounter, this::setCanCounter).hover("ability.hover.canCounter"),
|
||||
FieldDef.enumField("gui.type", CounterType.class, this::getCounterTypeEnum, this::setCounterTypeEnum)
|
||||
.hover("ability.hover.counterType").visibleWhen(this::isCanCounter),
|
||||
FieldDef.floatField("gui.value", this::getCounterValue, this::setCounterValue)
|
||||
.visibleWhen(this::isCanCounter).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("gui.chance", this::getCounterChance, this::setCounterChance)
|
||||
.visibleWhen(this::isCanCounter).column(ColumnHint.RIGHT),
|
||||
FieldDef.stringField("gui.sound", this::getCounterSound, this::setCounterSound)
|
||||
.visibleWhen(this::isCanCounter),
|
||||
FieldDef.floatField("ability.counterValue", this::getCounterValue, this::setCounterValue)
|
||||
FieldDef.intField("gui.animation", this::getCounterAnimationId, this::setCounterAnimationId)
|
||||
.visibleWhen(this::isCanCounter),
|
||||
FieldDef.floatField("ability.counterChance", this::getCounterChance, this::setCounterChance)
|
||||
.visibleWhen(this::isCanCounter),
|
||||
FieldDef.stringField("ability.counterSound", this::getCounterSound, this::setCounterSound)
|
||||
.visibleWhen(this::isCanCounter),
|
||||
FieldDef.intField("ability.counterAnim", this::getCounterAnimationId, this::setCounterAnimationId)
|
||||
.visibleWhen(this::isCanCounter),
|
||||
FieldDef.effectsSubGui("ability.effects", this::getEffects, this::setEffects)
|
||||
FieldDef.effectsListField("ability.effects", this::getEffects, this::setEffects)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import noppes.npcs.entity.EntityNPCInterface;
|
||||
|
||||
import noppes.npcs.api.ability.type.IAbilityHazard;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.gui.ColumnHint;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.FieldDef;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.TabTarget;
|
||||
|
||||
@@ -34,14 +35,35 @@ public class AbilityHazard extends Ability implements IAbilityHazard {
|
||||
public enum HazardShape {
|
||||
CIRCLE,
|
||||
RING,
|
||||
CONE
|
||||
CONE;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
switch (this) {
|
||||
case CIRCLE: return "ability.shape.circle";
|
||||
case RING: return "ability.shape.ring";
|
||||
case CONE: return "ability.shape.cone";
|
||||
default: return name();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum PlacementMode {
|
||||
AT_CASTER,
|
||||
AT_TARGET,
|
||||
FOLLOW_CASTER,
|
||||
FOLLOW_TARGET
|
||||
FOLLOW_TARGET;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
switch (this) {
|
||||
case AT_CASTER: return "ability.placement.atCaster";
|
||||
case AT_TARGET: return "ability.placement.atTarget";
|
||||
case FOLLOW_CASTER: return "ability.placement.followCaster";
|
||||
case FOLLOW_TARGET: return "ability.placement.followTarget";
|
||||
default: return name();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int durationTicks = 100;
|
||||
@@ -612,22 +634,24 @@ public class AbilityHazard extends Ability implements IAbilityHazard {
|
||||
@Override
|
||||
public List<FieldDef> getFieldDefinitions() {
|
||||
return Arrays.asList(
|
||||
FieldDef.intField("ability.duration", this::getDurationTicks, this::setDurationTicks)
|
||||
.range(1, 2000),
|
||||
FieldDef.intField("ability.duration", this::getDurationTicks, this::setDurationTicks).range(1, 2000),
|
||||
FieldDef.enumField("ability.shape", HazardShape.class, this::getShapeEnum, this::setShapeEnum)
|
||||
.hover("ability.hover.shape"),
|
||||
FieldDef.enumField("ability.placement", PlacementMode.class, this::getPlacementEnum, this::setPlacementEnum)
|
||||
.hover("ability.hover.placement"),
|
||||
FieldDef.floatField("ability.radius", this::getRadius, this::setRadius),
|
||||
FieldDef.floatField("ability.innerRadius", this::getInnerRadius, this::setInnerRadius),
|
||||
FieldDef.floatField("ability.dmgPerSec", this::getDamagePerSecond, this::setDamagePerSecond),
|
||||
FieldDef.intField("ability.dmgInterval", this::getDamageInterval, this::setDamageInterval),
|
||||
FieldDef.intField("ability.slownessLvl", this::getSlownessLevel, this::setSlownessLevel),
|
||||
FieldDef.intField("ability.debuffDur", this::getDebuffDuration, this::setDebuffDuration),
|
||||
FieldDef.intField("ability.poisonLvl", this::getPoisonLevel, this::setPoisonLevel),
|
||||
FieldDef.section("ability.section.area"),
|
||||
FieldDef.floatField("gui.radius", this::getRadius, this::setRadius).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("ability.innerRadius", this::getInnerRadius, this::setInnerRadius).column(ColumnHint.RIGHT),
|
||||
FieldDef.section("ability.section.damage"),
|
||||
FieldDef.floatField("ability.damagePerSecond", this::getDamagePerSecond, this::setDamagePerSecond).column(ColumnHint.LEFT),
|
||||
FieldDef.intField("ability.damageInterval", this::getDamageInterval, this::setDamageInterval).column(ColumnHint.RIGHT),
|
||||
FieldDef.section("ability.section.debuffs"),
|
||||
FieldDef.intField("ability.slownessLevel", this::getSlownessLevel, this::setSlownessLevel).column(ColumnHint.LEFT),
|
||||
FieldDef.intField("ability.debuffDuration", this::getDebuffDuration, this::setDebuffDuration).column(ColumnHint.RIGHT),
|
||||
FieldDef.intField("ability.poisonLevel", this::getPoisonLevel, this::setPoisonLevel),
|
||||
FieldDef.boolField("ability.affectsCaster", this::isAffectsCaster, this::setAffectsCaster)
|
||||
.hover("ability.hover.affectsCaster"),
|
||||
FieldDef.effectsSubGui("ability.effects", this::getEffects, this::setEffects)
|
||||
FieldDef.effectsListField("ability.effects", this::getEffects, this::setEffects)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.world.World;
|
||||
import noppes.npcs.entity.EntityNPCInterface;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.gui.ColumnHint;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.FieldDef;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.TabTarget;
|
||||
import noppes.npcs.api.ability.type.IAbilityHeal;
|
||||
@@ -285,18 +286,18 @@ public class AbilityHeal extends Ability implements IAbilityHeal {
|
||||
@Override
|
||||
public List<FieldDef> getFieldDefinitions() {
|
||||
return Arrays.asList(
|
||||
FieldDef.boolField("dialog.instant", this::isInstantHeal, this::setInstantHeal)
|
||||
FieldDef.boolField("ability.instantHeal", this::isInstantHeal, this::setInstantHeal)
|
||||
.hover("ability.hover.instant"),
|
||||
FieldDef.intField("ability.duration", this::getDurationTicks, this::setDurationTicks)
|
||||
.range(1, 1000)
|
||||
.visibleWhen(() -> !this.isInstantHeal()),
|
||||
FieldDef.floatField("ability.healAmount", this::getHealAmount, this::setHealAmount),
|
||||
FieldDef.floatField("ability.healPercent", this::getHealPercent, this::setHealPercent),
|
||||
.range(1, 1000).visibleWhen(() -> !this.isInstantHeal()),
|
||||
FieldDef.section("ability.section.healing"),
|
||||
FieldDef.floatField("ability.healAmount", this::getHealAmount, this::setHealAmount).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("ability.healPercent", this::getHealPercent, this::setHealPercent).column(ColumnHint.RIGHT),
|
||||
FieldDef.floatField("ability.healRadius", this::getHealRadius, this::setHealRadius),
|
||||
FieldDef.boolField("ability.healSelf", this::isHealSelf, this::setHealSelf)
|
||||
.hover("ability.hover.healSelf"),
|
||||
.hover("ability.hover.healSelf").column(ColumnHint.LEFT),
|
||||
FieldDef.boolField("ability.healAllies", this::isHealAllies, this::setHealAllies)
|
||||
.hover("ability.hover.healAllies")
|
||||
.hover("ability.hover.healAllies").column(ColumnHint.RIGHT)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import kamkeel.npcs.controllers.data.telegraph.TelegraphType;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.world.World;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.ColumnHint;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.FieldDef;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.TabTarget;
|
||||
import noppes.npcs.api.ability.type.IAbilityHeavyHit;
|
||||
@@ -110,9 +111,9 @@ public class AbilityHeavyHit extends Ability implements IAbilityHeavyHit {
|
||||
@Override
|
||||
public List<FieldDef> getFieldDefinitions() {
|
||||
return Arrays.asList(
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage),
|
||||
FieldDef.floatField("ability.knockback", this::getKnockback, this::setKnockback),
|
||||
FieldDef.effectsSubGui("ability.effects", this::getEffects, this::setEffects)
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("ability.knockback", this::getKnockback, this::setKnockback).column(ColumnHint.RIGHT),
|
||||
FieldDef.effectsListField("ability.effects", this::getEffects, this::setEffects)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -6,8 +6,8 @@ import kamkeel.npcs.controllers.data.ability.Ability;
|
||||
import kamkeel.npcs.controllers.data.ability.LockMovementType;
|
||||
import kamkeel.npcs.controllers.data.ability.TargetingMode;
|
||||
import kamkeel.npcs.controllers.data.ability.data.EnergyColorData;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.ColumnHint;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.FieldDef;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.TabTarget;
|
||||
import kamkeel.npcs.controllers.data.ability.data.EnergyCombatData;
|
||||
import kamkeel.npcs.controllers.data.ability.data.EnergyLifespanData;
|
||||
import kamkeel.npcs.controllers.data.ability.data.EnergyLightningData;
|
||||
@@ -231,39 +231,34 @@ public class AbilityLaserShot extends Ability implements IAbilityLaserShot {
|
||||
return Arrays.asList(
|
||||
// Type tab
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage),
|
||||
FieldDef.floatField("ability.laserWidth", this::getLaserWidth, this::setLaserWidth),
|
||||
FieldDef.floatField("ability.expansionSpeed", this::getExpansionSpeed, this::setExpansionSpeed),
|
||||
FieldDef.intField("ability.lingerTicks", this::getLingerTicks, this::setLingerTicks),
|
||||
FieldDef.floatField("ability.maxDist", this::getMaxDistance, this::setMaxDistance),
|
||||
FieldDef.intField("ability.lifetime", this::getMaxLifetime, this::setMaxLifetime),
|
||||
FieldDef.boolField("ability.explosive", this::isExplosive, this::setExplosive)
|
||||
.hover("ability.hover.explosive"),
|
||||
FieldDef.floatField("ability.explosionRad", this::getExplosionRadius, this::setExplosionRadius)
|
||||
.visibleWhen(this::isExplosive),
|
||||
FieldDef.floatField("ability.knockback", this::getKnockback, this::setKnockback),
|
||||
FieldDef.floatField("ability.knockbackUp", this::getKnockbackUp, this::setKnockbackUp),
|
||||
FieldDef.effectsSubGui("ability.effects", this::getEffects, this::setEffects),
|
||||
FieldDef.floatField("ability.knockback", this::getKnockback, this::setKnockback).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("ability.knockbackUp", this::getKnockbackUp, this::setKnockbackUp).column(ColumnHint.RIGHT),
|
||||
FieldDef.section("ability.section.beam"),
|
||||
FieldDef.floatField("ability.laserWidth", this::getLaserWidth, this::setLaserWidth).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("ability.expansionSpeed", this::getExpansionSpeed, this::setExpansionSpeed).column(ColumnHint.RIGHT),
|
||||
FieldDef.intField("ability.lingerTicks", this::getLingerTicks, this::setLingerTicks).column(ColumnHint.LEFT),
|
||||
FieldDef.intField("ability.lifetime", this::getMaxLifetime, this::setMaxLifetime).column(ColumnHint.RIGHT),
|
||||
FieldDef.floatField("ability.maxDistance", this::getMaxDistance, this::setMaxDistance),
|
||||
FieldDef.section("ability.section.explosive"),
|
||||
FieldDef.boolField("gui.enabled", this::isExplosive, this::setExplosive).hover("ability.hover.explosive"),
|
||||
FieldDef.floatField("gui.radius", this::getExplosionRadius, this::setExplosionRadius).visibleWhen(this::isExplosive),
|
||||
FieldDef.effectsListField("ability.effects", this::getEffects, this::setEffects),
|
||||
// Visual tab
|
||||
FieldDef.colorSubGui("ability.innerColor", this::getInnerColor, this::setInnerColor)
|
||||
.tab(TabTarget.VISUAL),
|
||||
FieldDef.section("ability.section.colors").customTab("ability.tab.visual"),
|
||||
FieldDef.colorSubGui("ability.innerColor", this::getInnerColor, this::setInnerColor).customTab("ability.tab.visual"),
|
||||
FieldDef.boolField("ability.outerEnabled", this::isOuterColorEnabled, this::setOuterColorEnabled).customTab("ability.tab.visual"),
|
||||
FieldDef.colorSubGui("ability.outerColor", this::getOuterColor, this::setOuterColor)
|
||||
.tab(TabTarget.VISUAL),
|
||||
FieldDef.boolField("ability.outerEnabled", this::isOuterColorEnabled, this::setOuterColorEnabled)
|
||||
.tab(TabTarget.VISUAL),
|
||||
.customTab("ability.tab.visual").visibleWhen(this::isOuterColorEnabled),
|
||||
FieldDef.floatField("ability.outerWidth", this::getOuterColorWidth, this::setOuterColorWidth)
|
||||
.tab(TabTarget.VISUAL)
|
||||
.visibleWhen(this::isOuterColorEnabled),
|
||||
.customTab("ability.tab.visual").visibleWhen(this::isOuterColorEnabled).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("ability.outerAlpha", this::getOuterColorAlpha, this::setOuterColorAlpha)
|
||||
.tab(TabTarget.VISUAL).range(0, 1)
|
||||
.visibleWhen(this::isOuterColorEnabled),
|
||||
FieldDef.boolField("ability.lightning", this::hasLightningEffect, this::setLightningEffect)
|
||||
.tab(TabTarget.VISUAL),
|
||||
FieldDef.floatField("ability.lightningDensity", this::getLightningDensity, this::setLightningDensity)
|
||||
.tab(TabTarget.VISUAL).range(0.01f, 5.0f)
|
||||
.visibleWhen(this::hasLightningEffect),
|
||||
FieldDef.floatField("ability.lightningRadius", this::getLightningRadius, this::setLightningRadius)
|
||||
.tab(TabTarget.VISUAL).range(0.1f, 10.0f)
|
||||
.visibleWhen(this::hasLightningEffect)
|
||||
.customTab("ability.tab.visual").range(0, 1).visibleWhen(this::isOuterColorEnabled).column(ColumnHint.RIGHT),
|
||||
FieldDef.section("ability.section.effects").customTab("ability.tab.visual"),
|
||||
FieldDef.boolField("ability.lightning", this::hasLightningEffect, this::setLightningEffect).customTab("ability.tab.visual"),
|
||||
FieldDef.floatField("gui.density", this::getLightningDensity, this::setLightningDensity)
|
||||
.customTab("ability.tab.visual").range(0.01f, 5.0f).visibleWhen(this::hasLightningEffect).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("gui.radius", this::getLightningRadius, this::setLightningRadius)
|
||||
.customTab("ability.tab.visual").range(0.1f, 10.0f).visibleWhen(this::hasLightningEffect).column(ColumnHint.RIGHT)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,8 @@ import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.Vec3;
|
||||
import net.minecraft.world.World;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.ColumnHint;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.FieldDef;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.TabTarget;
|
||||
import noppes.npcs.api.ability.type.IAbilityOrb;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -419,47 +419,38 @@ public class AbilityOrb extends Ability implements IAbilityOrb {
|
||||
public List<FieldDef> getFieldDefinitions() {
|
||||
return Arrays.asList(
|
||||
// Type tab
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage),
|
||||
FieldDef.floatField("stats.speed", this::getOrbSpeed, this::setOrbSpeed),
|
||||
FieldDef.floatField("stats.size", this::getOrbSize, this::setOrbSize),
|
||||
FieldDef.floatField("ability.maxDist", this::getMaxDistance, this::setMaxDistance),
|
||||
FieldDef.boolField("ability.homing", this::isHoming, this::setHoming)
|
||||
.hover("ability.hover.homing"),
|
||||
FieldDef.floatField("ability.homingStr", this::getHomingStrength, this::setHomingStrength)
|
||||
.visibleWhen(this::isHoming),
|
||||
FieldDef.boolField("ability.explosive", this::isExplosive, this::setExplosive)
|
||||
.hover("ability.hover.explosive"),
|
||||
FieldDef.floatField("ability.explosionRad", this::getExplosionRadius, this::setExplosionRadius)
|
||||
.visibleWhen(this::isExplosive),
|
||||
FieldDef.floatField("ability.knockback", this::getKnockback, this::setKnockback),
|
||||
FieldDef.intField("ability.lifetime", this::getMaxLifetime, this::setMaxLifetime),
|
||||
FieldDef.effectsSubGui("ability.effects", this::getEffects, this::setEffects),
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("stats.speed", this::getOrbSpeed, this::setOrbSpeed).column(ColumnHint.RIGHT),
|
||||
FieldDef.floatField("stats.size", this::getOrbSize, this::setOrbSize).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("ability.knockback", this::getKnockback, this::setKnockback).column(ColumnHint.RIGHT),
|
||||
FieldDef.floatField("ability.maxDistance", this::getMaxDistance, this::setMaxDistance).column(ColumnHint.LEFT),
|
||||
FieldDef.intField("ability.lifetime", this::getMaxLifetime, this::setMaxLifetime).column(ColumnHint.RIGHT),
|
||||
FieldDef.section("ability.section.homing"),
|
||||
FieldDef.boolField("gui.enabled", this::isHoming, this::setHoming).hover("ability.hover.homing"),
|
||||
FieldDef.floatField("gui.strength", this::getHomingStrength, this::setHomingStrength).visibleWhen(this::isHoming),
|
||||
FieldDef.section("ability.section.explosive"),
|
||||
FieldDef.boolField("gui.enabled", this::isExplosive, this::setExplosive).hover("ability.hover.explosive"),
|
||||
FieldDef.floatField("gui.radius", this::getExplosionRadius, this::setExplosionRadius).visibleWhen(this::isExplosive),
|
||||
FieldDef.effectsListField("ability.effects", this::getEffects, this::setEffects),
|
||||
// Visual tab
|
||||
FieldDef.enumField("ability.anchorPoint", AnchorPoint.class, this::getAnchorPointEnum, this::setAnchorPointEnum)
|
||||
.tab(TabTarget.VISUAL),
|
||||
FieldDef.colorSubGui("ability.innerColor", this::getInnerColor, this::setInnerColor)
|
||||
.tab(TabTarget.VISUAL),
|
||||
FieldDef.floatField("ability.rotationSpeed", this::getRotationSpeed, this::setRotationSpeed)
|
||||
.tab(TabTarget.VISUAL),
|
||||
FieldDef.boolField("ability.outerEnabled", this::isOuterColorEnabled, this::setOuterColorEnabled)
|
||||
.tab(TabTarget.VISUAL),
|
||||
FieldDef.floatField("ability.outerAlpha", this::getOuterColorAlpha, this::setOuterColorAlpha)
|
||||
.tab(TabTarget.VISUAL).range(0, 1)
|
||||
.visibleWhen(this::isOuterColorEnabled),
|
||||
.customTab("ability.tab.visual"),
|
||||
FieldDef.section("ability.section.colors").customTab("ability.tab.visual"),
|
||||
FieldDef.colorSubGui("ability.innerColor", this::getInnerColor, this::setInnerColor).customTab("ability.tab.visual"),
|
||||
FieldDef.boolField("ability.outerEnabled", this::isOuterColorEnabled, this::setOuterColorEnabled).customTab("ability.tab.visual"),
|
||||
FieldDef.colorSubGui("ability.outerColor", this::getOuterColor, this::setOuterColor)
|
||||
.tab(TabTarget.VISUAL)
|
||||
.visibleWhen(this::isOuterColorEnabled),
|
||||
.customTab("ability.tab.visual").visibleWhen(this::isOuterColorEnabled),
|
||||
FieldDef.floatField("ability.outerWidth", this::getOuterColorWidth, this::setOuterColorWidth)
|
||||
.tab(TabTarget.VISUAL)
|
||||
.visibleWhen(this::isOuterColorEnabled),
|
||||
FieldDef.boolField("ability.lightning", this::hasLightningEffect, this::setLightningEffect)
|
||||
.tab(TabTarget.VISUAL),
|
||||
FieldDef.floatField("ability.lightningDensity", this::getLightningDensity, this::setLightningDensity)
|
||||
.tab(TabTarget.VISUAL).range(0.01f, 5.0f)
|
||||
.visibleWhen(this::hasLightningEffect),
|
||||
FieldDef.floatField("ability.lightningRadius", this::getLightningRadius, this::setLightningRadius)
|
||||
.tab(TabTarget.VISUAL).range(0.1f, 10.0f)
|
||||
.visibleWhen(this::hasLightningEffect)
|
||||
.customTab("ability.tab.visual").visibleWhen(this::isOuterColorEnabled).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("ability.outerAlpha", this::getOuterColorAlpha, this::setOuterColorAlpha)
|
||||
.customTab("ability.tab.visual").range(0, 1).visibleWhen(this::isOuterColorEnabled).column(ColumnHint.RIGHT),
|
||||
FieldDef.section("ability.section.effects").customTab("ability.tab.visual"),
|
||||
FieldDef.floatField("ability.rotationSpeed", this::getRotationSpeed, this::setRotationSpeed).customTab("ability.tab.visual"),
|
||||
FieldDef.boolField("ability.lightning", this::hasLightningEffect, this::setLightningEffect).customTab("ability.tab.visual"),
|
||||
FieldDef.floatField("gui.density", this::getLightningDensity, this::setLightningDensity)
|
||||
.customTab("ability.tab.visual").range(0.01f, 5.0f).visibleWhen(this::hasLightningEffect).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("gui.radius", this::getLightningRadius, this::setLightningRadius)
|
||||
.customTab("ability.tab.visual").range(0.1f, 10.0f).visibleWhen(this::hasLightningEffect).column(ColumnHint.RIGHT)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import noppes.npcs.entity.EntityNPCInterface;
|
||||
|
||||
import noppes.npcs.api.ability.type.IAbilityProjectile;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.gui.ColumnHint;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.FieldDef;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.TabTarget;
|
||||
|
||||
@@ -255,19 +256,17 @@ public class AbilityProjectile extends Ability implements IAbilityProjectile {
|
||||
@Override
|
||||
public List<FieldDef> getFieldDefinitions() {
|
||||
return Arrays.asList(
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage),
|
||||
FieldDef.floatField("stats.speed", this::getSpeed, this::setSpeed),
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("stats.speed", this::getSpeed, this::setSpeed).column(ColumnHint.RIGHT),
|
||||
FieldDef.floatField("ability.knockback", this::getKnockback, this::setKnockback),
|
||||
FieldDef.stringEnumField("ability.projType", new String[]{"fireball", "arrow", "magic"}, this::getProjectileType, this::setProjectileType),
|
||||
FieldDef.boolField("ability.explosive", this::isExplosive, this::setExplosive)
|
||||
.hover("ability.hover.explosive"),
|
||||
FieldDef.floatField("ability.explosionRad", this::getExplosionRadius, this::setExplosionRadius)
|
||||
.visibleWhen(this::isExplosive),
|
||||
FieldDef.boolField("ability.homing", this::isHoming, this::setHoming)
|
||||
.hover("ability.hover.homing"),
|
||||
FieldDef.floatField("ability.homingStr", this::getHomingStrength, this::setHomingStrength)
|
||||
.visibleWhen(this::isHoming),
|
||||
FieldDef.effectsSubGui("ability.effects", this::getEffects, this::setEffects)
|
||||
FieldDef.stringEnumField("ability.projectileType", new String[]{"fireball", "arrow", "magic"}, this::getProjectileType, this::setProjectileType),
|
||||
FieldDef.section("ability.section.homing"),
|
||||
FieldDef.boolField("gui.enabled", this::isHoming, this::setHoming).hover("ability.hover.homing"),
|
||||
FieldDef.floatField("gui.strength", this::getHomingStrength, this::setHomingStrength).visibleWhen(this::isHoming),
|
||||
FieldDef.section("ability.section.explosive"),
|
||||
FieldDef.boolField("gui.enabled", this::isExplosive, this::setExplosive).hover("ability.hover.explosive"),
|
||||
FieldDef.floatField("gui.radius", this::getExplosionRadius, this::setExplosionRadius).visibleWhen(this::isExplosive),
|
||||
FieldDef.effectsListField("ability.effects", this::getEffects, this::setEffects)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.world.World;
|
||||
import noppes.npcs.entity.EntityNPCInterface;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.gui.ColumnHint;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.FieldDef;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.TabTarget;
|
||||
import noppes.npcs.api.ability.type.IAbilityShockwave;
|
||||
@@ -171,10 +172,11 @@ public class AbilityShockwave extends Ability implements IAbilityShockwave {
|
||||
public List<FieldDef> getFieldDefinitions() {
|
||||
return Arrays.asList(
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage),
|
||||
FieldDef.floatField("ability.pushRadius", this::getPushRadius, this::setPushRadius),
|
||||
FieldDef.floatField("ability.pushStrength", this::getPushStrength, this::setPushStrength),
|
||||
FieldDef.section("ability.section.push"),
|
||||
FieldDef.floatField("gui.radius", this::getPushRadius, this::setPushRadius).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("gui.strength", this::getPushStrength, this::setPushStrength).column(ColumnHint.RIGHT),
|
||||
FieldDef.intField("ability.maxTargets", this::getMaxTargets, this::setMaxTargets),
|
||||
FieldDef.effectsSubGui("ability.effects", this::getEffects, this::setEffects)
|
||||
FieldDef.effectsListField("ability.effects", this::getEffects, this::setEffects)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ import noppes.npcs.entity.EntityNPCInterface;
|
||||
import noppes.npcs.api.ability.type.IAbilitySlam;
|
||||
import somehussar.gui.annotationHandling.GuiEditable;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.gui.ColumnHint;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.FieldDef;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.TabTarget;
|
||||
import java.util.Arrays;
|
||||
@@ -572,11 +573,12 @@ public class AbilitySlam extends Ability implements IAbilitySlam {
|
||||
public List<FieldDef> getFieldDefinitions() {
|
||||
return Arrays.asList(
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage),
|
||||
FieldDef.floatField("ability.radius", this::getRadius, this::setRadius),
|
||||
FieldDef.floatField("ability.knockback", this::getKnockbackStrength, this::setKnockbackStrength),
|
||||
FieldDef.floatField("ability.leapSpeed", this::getLeapSpeed, this::setLeapSpeed),
|
||||
FieldDef.floatField("ability.leapHeight", this::getLeapHeight, this::setLeapHeight),
|
||||
FieldDef.effectsSubGui("ability.effects", this::getEffects, this::setEffects)
|
||||
FieldDef.floatField("gui.radius", this::getRadius, this::setRadius).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("ability.knockback", this::getKnockbackStrength, this::setKnockbackStrength).column(ColumnHint.RIGHT),
|
||||
FieldDef.section("ability.section.leap"),
|
||||
FieldDef.floatField("gui.speed", this::getLeapSpeed, this::setLeapSpeed).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("gui.height", this::getLeapHeight, this::setLeapHeight).column(ColumnHint.RIGHT),
|
||||
FieldDef.effectsListField("ability.effects", this::getEffects, this::setEffects)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,8 @@ import kamkeel.npcs.controllers.data.ability.Ability;
|
||||
import kamkeel.npcs.controllers.data.ability.LockMovementType;
|
||||
import kamkeel.npcs.controllers.data.ability.TargetingMode;
|
||||
import kamkeel.npcs.controllers.data.ability.data.EnergyColorData;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.ColumnHint;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.FieldDef;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.TabTarget;
|
||||
import kamkeel.npcs.controllers.data.telegraph.Telegraph;
|
||||
import kamkeel.npcs.controllers.data.telegraph.TelegraphInstance;
|
||||
import kamkeel.npcs.controllers.data.telegraph.TelegraphType;
|
||||
@@ -203,29 +203,29 @@ public class AbilitySweeper extends Ability implements IAbilitySweeper {
|
||||
@Override
|
||||
public List<FieldDef> getFieldDefinitions() {
|
||||
return Arrays.asList(
|
||||
// Type tab
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage),
|
||||
FieldDef.intField("ability.dmgInterval", this::getDamageInterval, this::setDamageInterval),
|
||||
FieldDef.floatField("ability.beamLength", this::getBeamLength, this::setBeamLength),
|
||||
FieldDef.floatField("ability.beamWidth", this::getBeamWidth, this::setBeamWidth),
|
||||
FieldDef.floatField("ability.beamHeight", this::getBeamHeight, this::setBeamHeight),
|
||||
FieldDef.floatField("ability.sweepSpeed", this::getSweepSpeed, this::setSweepSpeed),
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage).column(ColumnHint.LEFT),
|
||||
FieldDef.intField("ability.damageInterval", this::getDamageInterval, this::setDamageInterval).column(ColumnHint.RIGHT),
|
||||
FieldDef.section("ability.section.beam"),
|
||||
FieldDef.floatField("gui.length", this::getBeamLength, this::setBeamLength).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("gui.width", this::getBeamWidth, this::setBeamWidth).column(ColumnHint.RIGHT),
|
||||
FieldDef.floatField("gui.height", this::getBeamHeight, this::setBeamHeight).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("ability.sweepSpeed", this::getSweepSpeed, this::setSweepSpeed).column(ColumnHint.RIGHT),
|
||||
FieldDef.intField("ability.rotations", this::getNumberOfRotations, this::setNumberOfRotations),
|
||||
FieldDef.boolField("ability.piercing", this::isPiercing, this::setPiercing)
|
||||
.hover("ability.hover.piercing"),
|
||||
.hover("ability.hover.piercing").column(ColumnHint.LEFT),
|
||||
FieldDef.boolField("ability.lockTarget", this::isLockOnTarget, this::setLockOnTarget)
|
||||
.hover("ability.hover.lockTarget"),
|
||||
FieldDef.effectsSubGui("ability.effects", this::getEffects, this::setEffects),
|
||||
.hover("ability.hover.lockTarget").column(ColumnHint.RIGHT),
|
||||
FieldDef.effectsListField("ability.effects", this::getEffects, this::setEffects),
|
||||
// Visual tab
|
||||
FieldDef.section("ability.section.colors").customTab("ability.tab.visual"),
|
||||
FieldDef.colorSubGui("ability.innerColor", this::getInnerColor, this::setInnerColor)
|
||||
.tab(TabTarget.VISUAL),
|
||||
FieldDef.colorSubGui("ability.outerColor", this::getOuterColor, this::setOuterColor)
|
||||
.tab(TabTarget.VISUAL),
|
||||
.customTab("ability.tab.visual"),
|
||||
FieldDef.boolField("ability.outerEnabled", this::isOuterColorEnabled, this::setOuterColorEnabled)
|
||||
.tab(TabTarget.VISUAL),
|
||||
.customTab("ability.tab.visual"),
|
||||
FieldDef.colorSubGui("ability.outerColor", this::getOuterColor, this::setOuterColor)
|
||||
.customTab("ability.tab.visual").visibleWhen(this::isOuterColorEnabled),
|
||||
FieldDef.floatField("ability.outerWidth", this::getOuterColorWidth, this::setOuterColorWidth)
|
||||
.tab(TabTarget.VISUAL)
|
||||
.visibleWhen(this::isOuterColorEnabled)
|
||||
.customTab("ability.tab.visual").visibleWhen(this::isOuterColorEnabled)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import noppes.npcs.entity.EntityNPCInterface;
|
||||
|
||||
import noppes.npcs.api.ability.type.IAbilityTeleport;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.gui.ColumnHint;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.FieldDef;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.TabTarget;
|
||||
|
||||
@@ -34,7 +35,17 @@ public class AbilityTeleport extends Ability implements IAbilityTeleport {
|
||||
public enum TeleportMode {
|
||||
BLINK,
|
||||
BEHIND,
|
||||
SINGLE
|
||||
SINGLE;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
switch (this) {
|
||||
case BLINK: return "ability.teleport.blink";
|
||||
case BEHIND: return "ability.teleport.behind";
|
||||
case SINGLE: return "ability.teleport.single";
|
||||
default: return name();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final Random RANDOM = new Random();
|
||||
@@ -534,21 +545,22 @@ public class AbilityTeleport extends Ability implements IAbilityTeleport {
|
||||
FieldDef.floatField("ability.blinkRadius", this::getBlinkRadius, this::setBlinkRadius)
|
||||
.visibleWhen(() -> this.getModeEnum() == TeleportMode.BLINK || this.getModeEnum() == TeleportMode.SINGLE),
|
||||
FieldDef.intField("ability.blinkCount", this::getBlinkCount, this::setBlinkCount)
|
||||
.visibleWhen(() -> this.getModeEnum() == TeleportMode.BLINK),
|
||||
.visibleWhen(() -> this.getModeEnum() == TeleportMode.BLINK).column(ColumnHint.LEFT),
|
||||
FieldDef.intField("ability.blinkDelay", this::getBlinkDelayTicks, this::setBlinkDelayTicks)
|
||||
.visibleWhen(() -> this.getModeEnum() == TeleportMode.BLINK),
|
||||
.visibleWhen(() -> this.getModeEnum() == TeleportMode.BLINK).column(ColumnHint.RIGHT),
|
||||
FieldDef.floatField("ability.behindDistance", this::getBehindDistance, this::setBehindDistance)
|
||||
.visibleWhen(() -> this.getModeEnum() == TeleportMode.BEHIND),
|
||||
FieldDef.boolField("ability.lineOfSight", this::isRequireLineOfSight, this::setRequireLineOfSight)
|
||||
.hover("ability.hover.lineOfSight")
|
||||
.visibleWhen(() -> this.getModeEnum() == TeleportMode.BLINK || this.getModeEnum() == TeleportMode.SINGLE),
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage),
|
||||
FieldDef.floatField("ability.dmgRadius", this::getDamageRadius, this::setDamageRadius),
|
||||
FieldDef.boolField("ability.dmgAtStart", this::isDamageAtStart, this::setDamageAtStart)
|
||||
.hover("ability.hover.dmgAtStart"),
|
||||
FieldDef.boolField("ability.dmgAtEnd", this::isDamageAtEnd, this::setDamageAtEnd)
|
||||
.hover("ability.hover.dmgAtEnd"),
|
||||
FieldDef.effectsSubGui("ability.effects", this::getEffects, this::setEffects)
|
||||
FieldDef.section("ability.section.damage"),
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("gui.radius", this::getDamageRadius, this::setDamageRadius).column(ColumnHint.RIGHT),
|
||||
FieldDef.boolField("ability.damageAtStart", this::isDamageAtStart, this::setDamageAtStart)
|
||||
.hover("ability.hover.dmgAtStart").column(ColumnHint.LEFT),
|
||||
FieldDef.boolField("ability.damageAtEnd", this::isDamageAtEnd, this::setDamageAtEnd)
|
||||
.hover("ability.hover.dmgAtEnd").column(ColumnHint.RIGHT),
|
||||
FieldDef.effectsListField("ability.effects", this::getEffects, this::setEffects)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import noppes.npcs.entity.EntityNPCInterface;
|
||||
|
||||
import noppes.npcs.api.ability.type.IAbilityTrap;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.gui.ColumnHint;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.FieldDef;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.TabTarget;
|
||||
|
||||
@@ -33,7 +34,17 @@ public class AbilityTrap extends Ability implements IAbilityTrap {
|
||||
public enum TrapPlacement {
|
||||
AT_CASTER,
|
||||
AT_TARGET,
|
||||
AHEAD_OF_CASTER
|
||||
AHEAD_OF_CASTER;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
switch (this) {
|
||||
case AT_CASTER: return "ability.trapPlace.atCaster";
|
||||
case AT_TARGET: return "ability.trapPlace.atTarget";
|
||||
case AHEAD_OF_CASTER: return "ability.trapPlace.aheadOfCaster";
|
||||
default: return name();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int durationTicks = 200;
|
||||
@@ -465,13 +476,16 @@ public class AbilityTrap extends Ability implements IAbilityTrap {
|
||||
.range(1, 2000),
|
||||
FieldDef.enumField("ability.placement", TrapPlacement.class, this::getPlacementEnum, this::setPlacementEnum)
|
||||
.hover("ability.hover.placement"),
|
||||
FieldDef.floatField("ability.triggerRad", this::getTriggerRadius, this::setTriggerRadius),
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage),
|
||||
FieldDef.floatField("ability.dmgRadius", this::getDamageRadius, this::setDamageRadius),
|
||||
FieldDef.intField("ability.armTime", this::getArmTime, this::setArmTime),
|
||||
FieldDef.intField("ability.maxTriggers", this::getMaxTriggers, this::setMaxTriggers),
|
||||
FieldDef.section("ability.section.trigger"),
|
||||
FieldDef.floatField("gui.radius", this::getTriggerRadius, this::setTriggerRadius).column(ColumnHint.LEFT),
|
||||
FieldDef.intField("ability.armTime", this::getArmTime, this::setArmTime).column(ColumnHint.RIGHT),
|
||||
FieldDef.intField("ability.maxTriggers", this::getMaxTriggers, this::setMaxTriggers).column(ColumnHint.LEFT),
|
||||
FieldDef.intField("ability.triggerCooldown", this::getTriggerCooldown, this::setTriggerCooldown).column(ColumnHint.RIGHT),
|
||||
FieldDef.section("ability.section.damage"),
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("gui.radius", this::getDamageRadius, this::setDamageRadius).column(ColumnHint.RIGHT),
|
||||
FieldDef.floatField("ability.knockback", this::getKnockback, this::setKnockback),
|
||||
FieldDef.effectsSubGui("ability.effects", this::getEffects, this::setEffects)
|
||||
FieldDef.effectsListField("ability.effects", this::getEffects, this::setEffects)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.world.World;
|
||||
import noppes.npcs.entity.EntityNPCInterface;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.gui.ColumnHint;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.FieldDef;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.TabTarget;
|
||||
import noppes.npcs.api.ability.type.IAbilityVortex;
|
||||
@@ -304,17 +305,22 @@ public class AbilityVortex extends Ability implements IAbilityVortex {
|
||||
@Override
|
||||
public List<FieldDef> getFieldDefinitions() {
|
||||
return Arrays.asList(
|
||||
FieldDef.floatField("ability.pullRadius", this::getPullRadius, this::setPullRadius),
|
||||
FieldDef.floatField("ability.pullStrength", this::getPullStrength, this::setPullStrength),
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage),
|
||||
FieldDef.floatField("ability.knockback", this::getKnockback, this::setKnockback),
|
||||
FieldDef.boolField("ability.aoe", this::isAoe, this::setAoe)
|
||||
FieldDef.floatField("ability.pullRadius", this::getPullRadius, this::setPullRadius).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("ability.pullStrength", this::getPullStrength, this::setPullStrength).column(ColumnHint.RIGHT),
|
||||
FieldDef.section("ability.section.damage"),
|
||||
FieldDef.floatField("enchantment.damage", this::getDamage, this::setDamage).column(ColumnHint.LEFT),
|
||||
FieldDef.floatField("ability.knockback", this::getKnockback, this::setKnockback).column(ColumnHint.RIGHT),
|
||||
FieldDef.section("ability.section.aoe"),
|
||||
FieldDef.boolField("gui.enabled", this::isAoe, this::setAoe)
|
||||
.hover("ability.hover.aoe"),
|
||||
FieldDef.intField("ability.maxTargets", this::getMaxTargets, this::setMaxTargets),
|
||||
FieldDef.boolField("ability.dmgOnPull", this::isDamageOnPull, this::setDamageOnPull)
|
||||
FieldDef.intField("ability.maxTargets", this::getMaxTargets, this::setMaxTargets)
|
||||
.visibleWhen(this::isAoe),
|
||||
FieldDef.section("ability.section.pullDamage"),
|
||||
FieldDef.boolField("gui.enabled", this::isDamageOnPull, this::setDamageOnPull)
|
||||
.hover("ability.hover.dmgOnPull"),
|
||||
FieldDef.floatField("ability.pullDamage", this::getPullDamage, this::setPullDamage),
|
||||
FieldDef.effectsSubGui("ability.effects", this::getEffects, this::setEffects)
|
||||
FieldDef.floatField("enchantment.damage", this::getPullDamage, this::setPullDamage)
|
||||
.visibleWhen(this::isDamageOnPull),
|
||||
FieldDef.effectsListField("ability.effects", this::getEffects, this::setEffects)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
package noppes.npcs.client.gui.advanced;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.Ability;
|
||||
import kamkeel.npcs.controllers.data.ability.AbilityEffect;
|
||||
import kamkeel.npcs.controllers.data.ability.Condition;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.FieldDef;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.FieldDefinitionsBuilder;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.FieldType;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.TabTarget;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
@@ -19,58 +21,62 @@ import noppes.npcs.client.gui.util.ITextfieldListener;
|
||||
import noppes.npcs.client.gui.util.SubGuiInterface;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldListener, ISubGuiListener {
|
||||
|
||||
private static final int DECLARATIVE_ID_START = 1000;
|
||||
private static final int CLEAR_ID_START = 2000;
|
||||
private static final int LABEL_ID_START = 3000;
|
||||
|
||||
// Fixed tab indices
|
||||
private static final int TAB_GENERAL = 0;
|
||||
private static final int TAB_TYPE = 1;
|
||||
private static final int TAB_TARGET = 2;
|
||||
private static final int TAB_EFFECTS = 3;
|
||||
private static final int TAB_VISUAL = 4;
|
||||
// Custom tabs start at index 4
|
||||
|
||||
private static final int L_LABEL_X = 5;
|
||||
private static final int ROW_H = 24;
|
||||
|
||||
private final Ability ability;
|
||||
private final IAbilityConfigCallback callback;
|
||||
private int activeTab = TAB_GENERAL;
|
||||
|
||||
private List<FieldDef> fieldDefs;
|
||||
private boolean hasTypeFields;
|
||||
private boolean hasVisualFields;
|
||||
private List<String> customTabNames;
|
||||
|
||||
// Conditions are complex (list with add/edit/remove) - cached separately
|
||||
private List<Condition> conditions;
|
||||
private int editingConditionIndex = -1;
|
||||
|
||||
// Event routing
|
||||
private final Map<Integer, FieldDef> buttonFieldMap = new HashMap<>();
|
||||
private final Map<Integer, FieldDef> textFieldMap = new HashMap<>();
|
||||
private final Map<Integer, FieldDef> clearFieldMap = new HashMap<>();
|
||||
private FieldDefinitionsBuilder builder;
|
||||
private FieldDef activeSubGuiField = null;
|
||||
|
||||
// Scroll position preservation per tab
|
||||
private float[] tabScrollY;
|
||||
|
||||
public SubGuiAbilityConfig(Ability ability, IAbilityConfigCallback callback) {
|
||||
this.ability = ability;
|
||||
this.callback = callback;
|
||||
this.conditions = new ArrayList<>(ability.getConditions());
|
||||
|
||||
this.fieldDefs = ability.getAllFieldDefinitions();
|
||||
this.hasTypeFields = hasFieldsForTab(TabTarget.TYPE);
|
||||
this.hasVisualFields = hasFieldsForTab(TabTarget.VISUAL);
|
||||
discoverCustomTabs();
|
||||
|
||||
setBackground("menubg.png", 217);
|
||||
xSize = 356;
|
||||
ySize = 200;
|
||||
}
|
||||
|
||||
private boolean hasFieldsForTab(TabTarget target) {
|
||||
private void discoverCustomTabs() {
|
||||
customTabNames = new ArrayList<>();
|
||||
for (FieldDef def : fieldDefs) {
|
||||
if (def.getTab() == target) return true;
|
||||
if (def.getTab() == TabTarget.CUSTOM && def.getCustomTabName() != null
|
||||
&& !customTabNames.contains(def.getCustomTabName())) {
|
||||
customTabNames.add(def.getCustomTabName());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
tabScrollY = new float[4 + customTabNames.size()];
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
@@ -79,23 +85,24 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
|
||||
@Override
|
||||
public void initGui() {
|
||||
super.initGui();
|
||||
buttonFieldMap.clear();
|
||||
textFieldMap.clear();
|
||||
clearFieldMap.clear();
|
||||
// Save scroll position before super clears scroll windows
|
||||
GuiScrollWindow oldSw = getScrollableGui(0);
|
||||
if (oldSw != null && activeTab < tabScrollY.length) {
|
||||
tabScrollY[activeTab] = oldSw.nextScrollY;
|
||||
}
|
||||
|
||||
// Tab buttons
|
||||
super.initGui();
|
||||
|
||||
// Tab buttons — always show General, Type, Target, Effects
|
||||
GuiMenuTopButton generalTab = new GuiMenuTopButton(90, guiLeft + 4, guiTop - 17, "menu.general");
|
||||
generalTab.active = (activeTab == TAB_GENERAL);
|
||||
addTopButton(generalTab);
|
||||
GuiMenuTopButton lastTab = generalTab;
|
||||
|
||||
if (hasTypeFields) {
|
||||
GuiMenuTopButton typeTab = new GuiMenuTopButton(91, lastTab, "gui.type");
|
||||
typeTab.active = (activeTab == TAB_TYPE);
|
||||
addTopButton(typeTab);
|
||||
lastTab = typeTab;
|
||||
}
|
||||
GuiMenuTopButton typeTab = new GuiMenuTopButton(91, lastTab, "gui.type");
|
||||
typeTab.active = (activeTab == TAB_TYPE);
|
||||
addTopButton(typeTab);
|
||||
lastTab = typeTab;
|
||||
|
||||
GuiMenuTopButton targetTab = new GuiMenuTopButton(92, lastTab, "script.target");
|
||||
targetTab.active = (activeTab == TAB_TARGET);
|
||||
@@ -107,194 +114,117 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
addTopButton(effectsTab);
|
||||
lastTab = effectsTab;
|
||||
|
||||
if (hasVisualFields) {
|
||||
GuiMenuTopButton visualTab = new GuiMenuTopButton(94, lastTab, "ability.tab.visual");
|
||||
visualTab.active = (activeTab == TAB_VISUAL);
|
||||
addTopButton(visualTab);
|
||||
// Custom tabs (Visual, etc.)
|
||||
for (int i = 0; i < customTabNames.size(); i++) {
|
||||
GuiMenuTopButton ct = new GuiMenuTopButton(94 + i, lastTab, customTabNames.get(i));
|
||||
ct.active = (activeTab == 4 + i);
|
||||
addTopButton(ct);
|
||||
lastTab = ct;
|
||||
}
|
||||
|
||||
GuiMenuTopButton closeBtn = new GuiMenuTopButton(-1000, guiLeft + xSize - 22, guiTop - 17, "X");
|
||||
addTopButton(closeBtn);
|
||||
|
||||
// Scroll window for tab content
|
||||
// Scroll window
|
||||
int swX = guiLeft + 4;
|
||||
int swY = guiTop + 5;
|
||||
int swW = xSize - 8;
|
||||
int swH = ySize - 10;
|
||||
|
||||
GuiScrollWindow sw = new GuiScrollWindow(this, swX, swY, swW, swH, 0);
|
||||
sw.backgroundColor = 0x88000000;
|
||||
addScrollableGui(0, sw);
|
||||
|
||||
TabTarget tabTarget = tabTargetForIndex(activeTab);
|
||||
int y = 5;
|
||||
int idCounter = DECLARATIVE_ID_START;
|
||||
int clearCounter = CLEAR_ID_START;
|
||||
int labelCounter = LABEL_ID_START;
|
||||
|
||||
// General tab: show type label at top
|
||||
// General tab: type label at top
|
||||
if (activeTab == TAB_GENERAL) {
|
||||
sw.addLabel(new GuiNpcLabel(1, "gui.type", 5, y + 5));
|
||||
sw.addLabel(new GuiNpcLabel(2, ability.getTypeId(), 50, y + 5));
|
||||
y += 24;
|
||||
sw.addLabel(new GuiNpcLabel(labelCounter++, "gui.type", 5, y + 5, 0xFFFFFF));
|
||||
sw.addLabel(new GuiNpcLabel(labelCounter++, ability.getTypeId(), 55, y + 5, 0xFFFFFF));
|
||||
y += ROW_H;
|
||||
}
|
||||
|
||||
// Render declarative fields for this tab
|
||||
List<FieldDef> tabFields = getVisibleFieldsForTab(tabTarget);
|
||||
for (FieldDef def : tabFields) {
|
||||
int widgetId = idCounter++;
|
||||
int clearId = clearCounter++;
|
||||
y = renderField(sw, def, widgetId, clearId, y);
|
||||
}
|
||||
// Build declarative fields using the builder
|
||||
List<FieldDef> tabFields = getVisibleFieldsForTab(activeTab);
|
||||
builder = new FieldDefinitionsBuilder(this, sw, fontRendererObj)
|
||||
.startIds(DECLARATIVE_ID_START, CLEAR_ID_START, labelCounter)
|
||||
.startY(y);
|
||||
|
||||
// Target tab: append conditions list
|
||||
y = builder.build(tabFields);
|
||||
|
||||
// Conditions on target tab
|
||||
if (activeTab == TAB_TARGET) {
|
||||
y = renderConditions(sw, y);
|
||||
y = renderConditions(sw, y, builder.getNextLabelId());
|
||||
}
|
||||
|
||||
sw.maxScrollY = Math.max(y - swH, 0);
|
||||
addScrollableGui(0, sw);
|
||||
}
|
||||
|
||||
private TabTarget tabTargetForIndex(int tab) {
|
||||
switch (tab) {
|
||||
case TAB_GENERAL: return TabTarget.GENERAL;
|
||||
case TAB_TYPE: return TabTarget.TYPE;
|
||||
case TAB_TARGET: return TabTarget.TARGET;
|
||||
case TAB_EFFECTS: return TabTarget.EFFECTS;
|
||||
case TAB_VISUAL: return TabTarget.VISUAL;
|
||||
default: return TabTarget.TYPE;
|
||||
// Restore scroll position
|
||||
if (activeTab < tabScrollY.length) {
|
||||
float restored = Math.min(tabScrollY[activeTab], sw.maxScrollY);
|
||||
sw.nextScrollY = restored;
|
||||
sw.scrollY = restored;
|
||||
}
|
||||
}
|
||||
|
||||
private List<FieldDef> getVisibleFieldsForTab(TabTarget target) {
|
||||
private List<FieldDef> getVisibleFieldsForTab(int tabIndex) {
|
||||
List<FieldDef> result = new ArrayList<>();
|
||||
for (FieldDef def : fieldDefs) {
|
||||
if (def.getTab() == target && def.isVisible()) {
|
||||
result.add(def);
|
||||
|
||||
if (tabIndex >= 4) {
|
||||
// Custom tab — match by custom tab name
|
||||
int customIndex = tabIndex - 4;
|
||||
if (customIndex >= 0 && customIndex < customTabNames.size()) {
|
||||
String tabName = customTabNames.get(customIndex);
|
||||
for (FieldDef def : fieldDefs) {
|
||||
if (def.getTab() == TabTarget.CUSTOM
|
||||
&& tabName.equals(def.getCustomTabName())
|
||||
&& def.isVisible()) {
|
||||
result.add(def);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Fixed tab
|
||||
TabTarget target;
|
||||
switch (tabIndex) {
|
||||
case TAB_GENERAL: target = TabTarget.GENERAL; break;
|
||||
case TAB_TYPE: target = TabTarget.TYPE; break;
|
||||
case TAB_TARGET: target = TabTarget.TARGET; break;
|
||||
case TAB_EFFECTS: target = TabTarget.EFFECTS; break;
|
||||
default: target = TabTarget.TYPE; break;
|
||||
}
|
||||
for (FieldDef def : fieldDefs) {
|
||||
if (def.getTab() == target && def.isVisible()) {
|
||||
result.add(def);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// FIELD RENDERING
|
||||
// CONDITIONS (Target tab)
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private int renderField(GuiScrollWindow sw, FieldDef def, int widgetId, int clearId, int y) {
|
||||
int labelX = 5;
|
||||
int fieldX = 100;
|
||||
int fieldW = 60;
|
||||
|
||||
sw.addLabel(new GuiNpcLabel(widgetId, def.getLabel(), labelX, y + 5));
|
||||
|
||||
switch (def.getType()) {
|
||||
case FLOAT: {
|
||||
float fVal = def.getValue() instanceof Number ? ((Number) def.getValue()).floatValue() : 0f;
|
||||
GuiNpcTextField tf = new GuiNpcTextField(widgetId, this, fontRendererObj, fieldX, y, fieldW, 20, String.format("%.2f", fVal));
|
||||
tf.setFloatsOnly();
|
||||
if (def.hasRange()) tf.setMinMaxDefaultFloat(def.getMin(), def.getMax(), fVal);
|
||||
if (def.getTooltip() != null) tf.setHoverText(def.getTooltip());
|
||||
sw.addTextField(tf);
|
||||
textFieldMap.put(widgetId, def);
|
||||
break;
|
||||
}
|
||||
case INT: {
|
||||
int iVal = def.getValue() instanceof Number ? ((Number) def.getValue()).intValue() : 0;
|
||||
GuiNpcTextField tf = new GuiNpcTextField(widgetId, this, fontRendererObj, fieldX, y, fieldW, 20, String.valueOf(iVal));
|
||||
tf.setIntegersOnly();
|
||||
if (def.hasRange()) tf.setMinMaxDefault((int) def.getMin(), (int) def.getMax(), iVal);
|
||||
if (def.getTooltip() != null) tf.setHoverText(def.getTooltip());
|
||||
sw.addTextField(tf);
|
||||
textFieldMap.put(widgetId, def);
|
||||
break;
|
||||
}
|
||||
case STRING: {
|
||||
String sVal = def.getValue() != null ? def.getValue().toString() : "";
|
||||
GuiNpcTextField tf = new GuiNpcTextField(widgetId, this, fontRendererObj, fieldX, y, fieldW + 40, 20, sVal);
|
||||
if (def.getTooltip() != null) tf.setHoverText(def.getTooltip());
|
||||
sw.addTextField(tf);
|
||||
textFieldMap.put(widgetId, def);
|
||||
break;
|
||||
}
|
||||
case BOOLEAN: {
|
||||
boolean bVal = def.getValue() instanceof Boolean ? (Boolean) def.getValue() : false;
|
||||
GuiNpcButton btn = new GuiNpcButton(widgetId, fieldX, y, 40, 20, new String[]{"gui.no", "gui.yes"}, bVal ? 1 : 0);
|
||||
if (def.getHoverText() != null) btn.setHoverText(def.getHoverText());
|
||||
sw.addButton(btn);
|
||||
buttonFieldMap.put(widgetId, def);
|
||||
break;
|
||||
}
|
||||
case ENUM: {
|
||||
Class<? extends Enum<?>> enumClass = def.getEnumClass();
|
||||
if (enumClass != null) {
|
||||
Enum<?>[] constants = enumClass.getEnumConstants();
|
||||
String[] names = new String[constants.length];
|
||||
for (int i = 0; i < constants.length; i++) names[i] = constants[i].toString();
|
||||
int selected = def.getValue() instanceof Enum ? ((Enum<?>) def.getValue()).ordinal() : 0;
|
||||
GuiNpcButton btn = new GuiNpcButton(widgetId, fieldX, y, 80, 20, names, selected);
|
||||
if (def.getHoverText() != null) btn.setHoverText(def.getHoverText());
|
||||
sw.addButton(btn);
|
||||
buttonFieldMap.put(widgetId, def);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case STRING_ENUM: {
|
||||
String[] values = def.getStringEnumValues();
|
||||
if (values != null && values.length > 0) {
|
||||
String curVal = def.getStringEnumValue();
|
||||
int selected = 0;
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
if (values[i].equals(curVal)) { selected = i; break; }
|
||||
}
|
||||
GuiNpcButton btn = new GuiNpcButton(widgetId, fieldX, y, 80, 20, values, selected);
|
||||
if (def.getHoverText() != null) btn.setHoverText(def.getHoverText());
|
||||
sw.addButton(btn);
|
||||
buttonFieldMap.put(widgetId, def);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SUB_GUI: {
|
||||
String btnText = def.getButtonLabel();
|
||||
int btnW = def.hasClearAction() ? 60 : 80;
|
||||
GuiNpcButton btn = new GuiNpcButton(widgetId, fieldX, y, btnW, 20, btnText);
|
||||
Integer textColor = def.getButtonTextColor();
|
||||
if (textColor != null) btn.setTextColor(textColor);
|
||||
if (def.getHoverText() != null) btn.setHoverText(def.getHoverText());
|
||||
sw.addButton(btn);
|
||||
buttonFieldMap.put(widgetId, def);
|
||||
|
||||
if (def.hasClearAction()) {
|
||||
GuiNpcButton clearBtn = new GuiNpcButton(clearId, fieldX + btnW + 5, y, 20, 20, "X");
|
||||
sw.addButton(clearBtn);
|
||||
clearFieldMap.put(clearId, def);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return y + 24;
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// CONDITIONS (Target tab special handling)
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
private int renderConditions(GuiScrollWindow sw, int y) {
|
||||
int x = 5;
|
||||
|
||||
sw.addLabel(new GuiNpcLabel(50, "ability.conditions", x, y));
|
||||
y += 14;
|
||||
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, x, y, 140, 20, condName));
|
||||
sw.addButton(new GuiNpcButton(51 + i * 10, x + 145, y, 40, 20, "gui.edit"));
|
||||
sw.addButton(new GuiNpcButton(52 + i * 10, x + 190, y, 20, 20, "X"));
|
||||
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, x, y, 50, 20, "gui.add"));
|
||||
y += 24;
|
||||
sw.addButton(new GuiNpcButton(80, L_LABEL_X, y, 50, 20, "gui.add"));
|
||||
y += ROW_H;
|
||||
}
|
||||
|
||||
return y;
|
||||
@@ -334,12 +264,17 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
public void buttonEvent(GuiButton guibutton) {
|
||||
int id = guibutton.id;
|
||||
|
||||
// Tab switching
|
||||
// Tab switching — fixed tabs
|
||||
if (id == 90) { activeTab = TAB_GENERAL; initGui(); return; }
|
||||
if (id == 91) { activeTab = TAB_TYPE; initGui(); return; }
|
||||
if (id == 92) { activeTab = TAB_TARGET; initGui(); return; }
|
||||
if (id == 93) { activeTab = TAB_EFFECTS; initGui(); return; }
|
||||
if (id == 94) { activeTab = TAB_VISUAL; initGui(); return; }
|
||||
// Custom tabs (94+)
|
||||
if (id >= 94 && id < 94 + customTabNames.size()) {
|
||||
activeTab = 4 + (id - 94);
|
||||
initGui();
|
||||
return;
|
||||
}
|
||||
if (id == -1000) { close(); return; }
|
||||
|
||||
// Condition buttons (50-80)
|
||||
@@ -367,9 +302,19 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear buttons
|
||||
// Clear buttons (effects delete or SUB_GUI clear)
|
||||
if (id >= CLEAR_ID_START) {
|
||||
FieldDef def = clearFieldMap.get(id);
|
||||
// Check effects list delete first
|
||||
int[] meta = builder.getEffectWidgetMeta().get(id);
|
||||
if (meta != null && meta[1] == 3) {
|
||||
FieldDef def = builder.getClearFieldMap().get(id);
|
||||
if (def != null && def.getType() == FieldType.EFFECTS_LIST) {
|
||||
handleEffectButton(def, meta, guibutton);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// SUB_GUI clear
|
||||
FieldDef def = builder.getClearFieldMap().get(id);
|
||||
if (def != null && def.hasClearAction()) {
|
||||
def.getClearAction().run();
|
||||
initGui();
|
||||
@@ -379,9 +324,16 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
|
||||
// Declarative field buttons
|
||||
if (id >= DECLARATIVE_ID_START) {
|
||||
FieldDef def = buttonFieldMap.get(id);
|
||||
FieldDef def = builder.getButtonFieldMap().get(id);
|
||||
if (def == null) return;
|
||||
|
||||
// Effects list buttons (type, amp, add)
|
||||
int[] meta = builder.getEffectWidgetMeta().get(id);
|
||||
if (meta != null && def.getType() == FieldType.EFFECTS_LIST) {
|
||||
handleEffectButton(def, meta, guibutton);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (def.getType()) {
|
||||
case BOOLEAN:
|
||||
def.setValue(((GuiNpcButton) guibutton).getValue() == 1);
|
||||
@@ -412,16 +364,63 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void handleEffectButton(FieldDef def, int[] meta, GuiButton btn) {
|
||||
List<AbilityEffect> effects = (List<AbilityEffect>) def.getValue();
|
||||
if (effects == null) return;
|
||||
int effectIdx = meta[0];
|
||||
int action = meta[1];
|
||||
|
||||
switch (action) {
|
||||
case 0: // Type changed
|
||||
if (effectIdx < effects.size()) {
|
||||
effects.get(effectIdx).setType(AbilityEffect.EffectType.fromOrdinal(((GuiNpcButton) btn).getValue()));
|
||||
}
|
||||
break;
|
||||
case 2: // Amp changed
|
||||
if (effectIdx < effects.size()) {
|
||||
effects.get(effectIdx).setAmplifier(((GuiNpcButton) btn).getValue());
|
||||
}
|
||||
break;
|
||||
case 3: // Delete
|
||||
if (effectIdx < effects.size()) {
|
||||
effects.remove(effectIdx);
|
||||
initGui();
|
||||
}
|
||||
break;
|
||||
case 4: // Add
|
||||
if (effects.size() < 5) {
|
||||
effects.add(new AbilityEffect(AbilityEffect.EffectType.SLOWNESS, 60, 0));
|
||||
initGui();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// TEXT FIELD EVENTS
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void unFocused(GuiNpcTextField textField) {
|
||||
int id = textField.id;
|
||||
if (id < DECLARATIVE_ID_START) return;
|
||||
|
||||
FieldDef def = textFieldMap.get(id);
|
||||
// Check effects list duration fields
|
||||
int[] meta = builder.getEffectWidgetMeta().get(id);
|
||||
if (meta != null && meta[1] == 1) {
|
||||
FieldDef def = builder.getTextFieldMap().get(id);
|
||||
if (def != null && def.getType() == FieldType.EFFECTS_LIST) {
|
||||
List<AbilityEffect> effects = (List<AbilityEffect>) def.getValue();
|
||||
if (effects != null && meta[0] < effects.size()) {
|
||||
effects.get(meta[0]).setDurationTicks(textField.getInteger());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
FieldDef def = builder.getTextFieldMap().get(id);
|
||||
if (def == null) return;
|
||||
|
||||
switch (def.getType()) {
|
||||
@@ -480,10 +479,8 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
}
|
||||
|
||||
protected void applyToAbility() {
|
||||
// Conditions are the only cached values - write them back
|
||||
ability.getConditions().clear();
|
||||
for (Condition c : conditions) ability.addCondition(c);
|
||||
// All other fields write directly to ability via FieldDef lambdas
|
||||
}
|
||||
|
||||
public void loadAbility(Ability loadedAbility) {
|
||||
@@ -494,8 +491,7 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
|
||||
this.conditions = new ArrayList<>(ability.getConditions());
|
||||
this.fieldDefs = ability.getAllFieldDefinitions();
|
||||
this.hasTypeFields = hasFieldsForTab(TabTarget.TYPE);
|
||||
this.hasVisualFields = hasFieldsForTab(TabTarget.VISUAL);
|
||||
discoverCustomTabs();
|
||||
initGui();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package noppes.npcs.client.gui.util;
|
||||
|
||||
import kamkeel.npcs.util.TextSplitter;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.ScaledResolution;
|
||||
import net.minecraft.client.renderer.RenderHelper;
|
||||
@@ -151,8 +152,23 @@ public class GuiNpcButton extends GuiButton {
|
||||
public void drawButton(Minecraft mc, int mouseX, int mouseY) {
|
||||
if (!this.visible)
|
||||
return;
|
||||
// Auto-truncate display text if wider than button
|
||||
String original = this.displayString;
|
||||
FontRenderer fr = mc.fontRenderer;
|
||||
if (fr != null) {
|
||||
int maxTextWidth = this.width - 6;
|
||||
if (fr.getStringWidth(original) > maxTextWidth) {
|
||||
String ellipsis = "...";
|
||||
int targetWidth = maxTextWidth - fr.getStringWidth(ellipsis);
|
||||
if (targetWidth > 0) {
|
||||
this.displayString = fr.trimStringToWidth(original, targetWidth) + ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
// First, draw the button normally using the superclass method.
|
||||
super.drawButton(mc, mouseX, mouseY);
|
||||
// Restore original display string
|
||||
this.displayString = original;
|
||||
// Then, if an icon texture is set, draw it.
|
||||
if (iconTexture != null) {
|
||||
mc.getTextureManager().bindTexture(iconTexture);
|
||||
|
||||
Reference in new issue
Block a user