mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-13 00:47:50 +00:00
1466 lines
66 KiB
Java
1466 lines
66 KiB
Java
package noppes.npcs.client.gui.advanced;
|
|
|
|
import kamkeel.npcs.controllers.data.ability.Ability;
|
|
import kamkeel.npcs.controllers.data.ability.AbilityController;
|
|
import kamkeel.npcs.controllers.data.ability.TargetingMode;
|
|
import kamkeel.npcs.controllers.data.ability.telegraph.TelegraphType;
|
|
import kamkeel.npcs.controllers.data.ability.type.*;
|
|
import noppes.npcs.client.gui.SubGuiColorSelector;
|
|
import noppes.npcs.client.gui.select.GuiAnimationSelection;
|
|
import noppes.npcs.client.gui.select.GuiSoundSelection;
|
|
import net.minecraft.client.gui.GuiButton;
|
|
import net.minecraft.nbt.NBTTagCompound;
|
|
import noppes.npcs.client.gui.util.*;
|
|
|
|
/**
|
|
* SubGui for editing ability configuration with tabbed interface.
|
|
* Tabs: General, Type (if has type settings), Timing, Effects, Telegraph (if supported)
|
|
*/
|
|
public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldListener, ISubGuiListener {
|
|
|
|
private static final int TAB_GENERAL = 0;
|
|
private static final int TAB_TYPE = 1;
|
|
private static final int TAB_TIMING = 2;
|
|
private static final int TAB_EFFECTS = 3;
|
|
private static final int TAB_TELEGRAPH = 4;
|
|
|
|
private final Ability ability;
|
|
private final IAbilityConfigCallback parent;
|
|
private int activeTab = TAB_GENERAL;
|
|
|
|
// Cached values - General
|
|
private String name;
|
|
private boolean enabled;
|
|
private int weight;
|
|
private float minRange;
|
|
private float maxRange;
|
|
private TargetingMode targetingMode;
|
|
|
|
// Cached values - Timing
|
|
private int cooldownTicks;
|
|
private int windUpTicks;
|
|
private int activeTicks;
|
|
private int recoveryTicks;
|
|
private boolean interruptible;
|
|
private float interruptThreshold;
|
|
private boolean lockMovement;
|
|
|
|
// Cached values - Telegraph
|
|
private boolean showTelegraph;
|
|
private int windUpColor;
|
|
private int activeColor;
|
|
private int editingColorId = 0; // Track which color button was clicked (22=windUp, 24=active)
|
|
|
|
// Cached values - Effects (sounds/animations)
|
|
private String windUpSound;
|
|
private String activeSound;
|
|
private int windUpAnimationId;
|
|
private int activeAnimationId;
|
|
private String windUpAnimationName = null; // Cached name from selector
|
|
private String activeAnimationName = null; // Cached name from selector
|
|
private int editingSoundId = 0; // Track which sound button was clicked (30=windUp, 31=active)
|
|
private int editingAnimationId = 0; // Track which animation button was clicked (32=windUp, 33=active)
|
|
|
|
// Ability type features
|
|
private final boolean supportsTelegraph;
|
|
private final boolean targetingModeLocked;
|
|
private final boolean hasTypeSettings;
|
|
|
|
public SubGuiAbilityConfig(Ability ability, IAbilityConfigCallback parent) {
|
|
this.ability = ability;
|
|
this.parent = parent;
|
|
|
|
// Cache values from ability
|
|
this.name = ability.getName() != null ? ability.getName() : "";
|
|
this.enabled = ability.isEnabled();
|
|
this.weight = ability.getWeight();
|
|
this.minRange = ability.getMinRange();
|
|
this.maxRange = ability.getMaxRange();
|
|
this.targetingMode = ability.getTargetingMode();
|
|
|
|
this.cooldownTicks = ability.getCooldownTicks();
|
|
this.windUpTicks = ability.getWindUpTicks();
|
|
this.activeTicks = ability.getActiveTicks();
|
|
this.recoveryTicks = ability.getRecoveryTicks();
|
|
this.interruptible = ability.isInterruptible();
|
|
this.interruptThreshold = ability.getInterruptThreshold();
|
|
this.lockMovement = ability.isLockMovement();
|
|
|
|
this.showTelegraph = ability.isShowTelegraph();
|
|
this.windUpColor = ability.getWindUpColor();
|
|
this.activeColor = ability.getActiveColor();
|
|
|
|
this.windUpSound = ability.getWindUpSound();
|
|
this.activeSound = ability.getActiveSound();
|
|
this.windUpAnimationId = ability.getWindUpAnimationId();
|
|
this.activeAnimationId = ability.getActiveAnimationId();
|
|
|
|
// Determine ability type features
|
|
TelegraphType defaultType = ability.getTelegraphType();
|
|
this.supportsTelegraph = defaultType != null && defaultType != TelegraphType.NONE;
|
|
this.targetingModeLocked = ability.isTargetingModeLocked();
|
|
this.hasTypeSettings = ability.hasTypeSettings();
|
|
|
|
setBackground("menubg.png");
|
|
xSize = 276;
|
|
ySize = 216;
|
|
}
|
|
|
|
@Override
|
|
public void initGui() {
|
|
super.initGui();
|
|
|
|
int y = guiTop + 4;
|
|
int tabWidth = 60;
|
|
int tabX = guiLeft + 4;
|
|
|
|
// Tab buttons at top - dynamically sized based on available tabs
|
|
addButton(new GuiNpcButton(90, tabX, y, tabWidth, 20, "ability.tab.general"));
|
|
tabX += tabWidth + 2;
|
|
|
|
if (hasTypeSettings) {
|
|
addButton(new GuiNpcButton(91, tabX, y, tabWidth, 20, "ability.tab.type"));
|
|
tabX += tabWidth + 2;
|
|
}
|
|
|
|
addButton(new GuiNpcButton(92, tabX, y, tabWidth, 20, "ability.tab.timing"));
|
|
tabX += tabWidth + 2;
|
|
|
|
addButton(new GuiNpcButton(94, tabX, y, tabWidth, 20, "ability.tab.effects"));
|
|
tabX += tabWidth + 2;
|
|
|
|
if (supportsTelegraph) {
|
|
addButton(new GuiNpcButton(93, tabX, y, tabWidth, 20, "ability.tab.telegraph"));
|
|
}
|
|
|
|
// Highlight active tab
|
|
getButton(90).setEnabled(activeTab != TAB_GENERAL);
|
|
if (hasTypeSettings) {
|
|
getButton(91).setEnabled(activeTab != TAB_TYPE);
|
|
}
|
|
getButton(92).setEnabled(activeTab != TAB_TIMING);
|
|
getButton(94).setEnabled(activeTab != TAB_EFFECTS);
|
|
if (supportsTelegraph) {
|
|
getButton(93).setEnabled(activeTab != TAB_TELEGRAPH);
|
|
}
|
|
|
|
y += 24;
|
|
|
|
// Draw content based on active tab
|
|
switch (activeTab) {
|
|
case TAB_GENERAL:
|
|
initGeneralTab(y);
|
|
break;
|
|
case TAB_TYPE:
|
|
initTypeTab(y);
|
|
break;
|
|
case TAB_TIMING:
|
|
initTimingTab(y);
|
|
break;
|
|
case TAB_EFFECTS:
|
|
initEffectsTab(y);
|
|
break;
|
|
case TAB_TELEGRAPH:
|
|
initTelegraphTab(y);
|
|
break;
|
|
}
|
|
|
|
// Bottom row - Enabled on left, Done/Cancel on right
|
|
addLabel(new GuiNpcLabel(99, "gui.enabled", guiLeft + 8, guiTop + ySize - 19));
|
|
GuiNpcButton enabledBtn = new GuiNpcButton(2, guiLeft + 55, guiTop + ySize - 24, 50, 20, new String[]{"gui.no", "gui.yes"}, enabled ? 1 : 0);
|
|
enabledBtn.setTextColor(enabled ? 0x00FF00 : 0xFF0000);
|
|
addButton(enabledBtn);
|
|
|
|
addButton(new GuiNpcButton(66, guiLeft + xSize - 130, guiTop + ySize - 24, 60, 20, "gui.done"));
|
|
addButton(new GuiNpcButton(67, guiLeft + xSize - 65, guiTop + ySize - 24, 60, 20, "gui.cancel"));
|
|
}
|
|
|
|
private void initGeneralTab(int startY) {
|
|
int y = startY;
|
|
int labelX = guiLeft + 8;
|
|
int fieldX = guiLeft + 85;
|
|
int col2LabelX = guiLeft + 145;
|
|
int col2FieldX = guiLeft + 205;
|
|
|
|
// Row 1: Name + Weight
|
|
addLabel(new GuiNpcLabel(1, "gui.name", labelX, y + 5));
|
|
addTextField(new GuiNpcTextField(1, this, fontRendererObj, fieldX, y, 100, 20, name));
|
|
|
|
addLabel(new GuiNpcLabel(3, "ability.weight", col2LabelX, y + 5));
|
|
GuiNpcTextField weightField = new GuiNpcTextField(3, this, fontRendererObj, col2FieldX, y, 50, 20, String.valueOf(weight));
|
|
weightField.setIntegersOnly();
|
|
weightField.setMinMaxDefault(1, 1000, 10);
|
|
addTextField(weightField);
|
|
|
|
y += 24;
|
|
|
|
// Row 2: Min Range + Max Range
|
|
addLabel(new GuiNpcLabel(5, "ability.minRange", labelX, y + 5));
|
|
GuiNpcTextField minRangeField = new GuiNpcTextField(5, this, fontRendererObj, fieldX, y, 50, 20, String.valueOf((int) minRange));
|
|
minRangeField.setIntegersOnly();
|
|
minRangeField.setMinMaxDefault(0, 100, 0);
|
|
addTextField(minRangeField);
|
|
|
|
addLabel(new GuiNpcLabel(6, "ability.maxRange", col2LabelX, y + 5));
|
|
GuiNpcTextField maxRangeField = new GuiNpcTextField(6, this, fontRendererObj, col2FieldX, y, 50, 20, String.valueOf((int) maxRange));
|
|
maxRangeField.setIntegersOnly();
|
|
maxRangeField.setMinMaxDefault(1, 100, 20);
|
|
addTextField(maxRangeField);
|
|
|
|
y += 24;
|
|
|
|
// Row 3: Targeting Mode (if not locked)
|
|
if (!targetingModeLocked) {
|
|
addLabel(new GuiNpcLabel(4, "ability.targeting", labelX, y + 5));
|
|
String[] targetingModes = getAvailableTargetingModes();
|
|
int selectedIndex = getTargetingModeIndex(targetingMode);
|
|
addButton(new GuiNpcButton(4, fieldX, y, 80, 20, targetingModes, selectedIndex));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get available targeting modes for the current ability.
|
|
* Some abilities restrict which modes can be used.
|
|
*/
|
|
private String[] getAvailableTargetingModes() {
|
|
TargetingMode[] modes = ability.getAllowedTargetingModes();
|
|
if (modes == null) {
|
|
modes = TargetingMode.values();
|
|
}
|
|
String[] result = new String[modes.length];
|
|
for (int i = 0; i < modes.length; i++) {
|
|
result[i] = "ability.target." + modes[i].name().toLowerCase();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Get the index of current targeting mode in the allowed modes array.
|
|
*/
|
|
private int getTargetingModeIndex(TargetingMode mode) {
|
|
TargetingMode[] modes = ability.getAllowedTargetingModes();
|
|
if (modes == null) {
|
|
return mode.ordinal();
|
|
}
|
|
for (int i = 0; i < modes.length; i++) {
|
|
if (modes[i] == mode) return i;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
private void initTypeTab(int startY) {
|
|
// Delegate to type-specific rendering
|
|
if (ability instanceof AbilitySlam) {
|
|
initSlamSettings(startY, (AbilitySlam) ability);
|
|
} else if (ability instanceof AbilityCharge) {
|
|
initChargeSettings(startY, (AbilityCharge) ability);
|
|
} else if (ability instanceof AbilityHeavyHit) {
|
|
initHeavyHitSettings(startY, (AbilityHeavyHit) ability);
|
|
} else if (ability instanceof AbilityCutter) {
|
|
initCutterSettings(startY, (AbilityCutter) ability);
|
|
} else if (ability instanceof AbilityOrb) {
|
|
initOrbSettings(startY, (AbilityOrb) ability);
|
|
} else if (ability instanceof AbilityVortex) {
|
|
initVortexSettings(startY, (AbilityVortex) ability);
|
|
} else if (ability instanceof AbilityShockwave) {
|
|
initShockwaveSettings(startY, (AbilityShockwave) ability);
|
|
} else if (ability instanceof AbilityDash) {
|
|
initDashSettings(startY, (AbilityDash) ability);
|
|
} else if (ability instanceof AbilityTeleport) {
|
|
initTeleportSettings(startY, (AbilityTeleport) ability);
|
|
} else if (ability instanceof AbilityProjectile) {
|
|
initProjectileSettings(startY, (AbilityProjectile) ability);
|
|
} else if (ability instanceof AbilityBeam) {
|
|
initBeamSettings(startY, (AbilityBeam) ability);
|
|
} else if (ability instanceof AbilityGuard) {
|
|
initGuardSettings(startY, (AbilityGuard) ability);
|
|
} else if (ability instanceof AbilityHeal) {
|
|
initHealSettings(startY, (AbilityHeal) ability);
|
|
} else if (ability instanceof AbilityHazard) {
|
|
initHazardSettings(startY, (AbilityHazard) ability);
|
|
} else if (ability instanceof AbilityTrap) {
|
|
initTrapSettings(startY, (AbilityTrap) ability);
|
|
}
|
|
}
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// TYPE-SPECIFIC SETTINGS
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
private void initSlamSettings(int startY, AbilitySlam slam) {
|
|
int y = startY;
|
|
int labelX = guiLeft + 8;
|
|
int fieldX = guiLeft + 85;
|
|
int col2LabelX = guiLeft + 145;
|
|
int col2FieldX = guiLeft + 205;
|
|
|
|
// Row 1: Damage + Radius
|
|
addLabel(new GuiNpcLabel(100, "ability.damage", labelX, y + 5));
|
|
addTextField(createFloatField(100, fieldX, y, 50, slam.getDamage()));
|
|
|
|
addLabel(new GuiNpcLabel(101, "ability.radius", col2LabelX, y + 5));
|
|
addTextField(createFloatField(101, col2FieldX, y, 50, slam.getRadius()));
|
|
|
|
y += 24;
|
|
|
|
// Row 2: Knockback + Leap Speed
|
|
addLabel(new GuiNpcLabel(102, "ability.knockback", labelX, y + 5));
|
|
addTextField(createFloatField(102, fieldX, y, 50, slam.getKnockbackStrength()));
|
|
|
|
addLabel(new GuiNpcLabel(103, "ability.leapSpeed", col2LabelX, y + 5));
|
|
addTextField(createFloatField(103, col2FieldX, y, 50, slam.getLeapSpeed()));
|
|
|
|
y += 24;
|
|
|
|
// Row 3: Min/Max Leap Distance
|
|
addLabel(new GuiNpcLabel(104, "ability.minDist", labelX, y + 5));
|
|
addTextField(createFloatField(104, fieldX, y, 50, slam.getMinLeapDistance()));
|
|
|
|
addLabel(new GuiNpcLabel(105, "ability.maxDist", col2LabelX, y + 5));
|
|
addTextField(createFloatField(105, col2FieldX, y, 50, slam.getMaxLeapDistance()));
|
|
}
|
|
|
|
private void initChargeSettings(int startY, AbilityCharge charge) {
|
|
int y = startY;
|
|
int labelX = guiLeft + 8;
|
|
int fieldX = guiLeft + 85;
|
|
int col2LabelX = guiLeft + 145;
|
|
int col2FieldX = guiLeft + 205;
|
|
|
|
// Row 1: Damage + Speed
|
|
addLabel(new GuiNpcLabel(100, "ability.damage", labelX, y + 5));
|
|
addTextField(createFloatField(100, fieldX, y, 50, charge.getDamage()));
|
|
|
|
addLabel(new GuiNpcLabel(101, "ability.speed", col2LabelX, y + 5));
|
|
addTextField(createFloatField(101, col2FieldX, y, 50, charge.getChargeSpeed()));
|
|
|
|
y += 24;
|
|
|
|
// Row 2: Knockback + Knockback Up
|
|
addLabel(new GuiNpcLabel(102, "ability.knockback", labelX, y + 5));
|
|
addTextField(createFloatField(102, fieldX, y, 50, charge.getKnockback()));
|
|
|
|
addLabel(new GuiNpcLabel(103, "ability.knockbackUp", col2LabelX, y + 5));
|
|
addTextField(createFloatField(103, col2FieldX, y, 50, charge.getKnockbackUp()));
|
|
|
|
y += 24;
|
|
|
|
// Row 3: Max Distance + Hit Radius
|
|
addLabel(new GuiNpcLabel(104, "ability.maxDist", labelX, y + 5));
|
|
addTextField(createFloatField(104, fieldX, y, 50, charge.getMaxDistance()));
|
|
|
|
addLabel(new GuiNpcLabel(105, "ability.hitRadius", col2LabelX, y + 5));
|
|
addTextField(createFloatField(105, col2FieldX, y, 50, charge.getHitRadius()));
|
|
}
|
|
|
|
private void initHeavyHitSettings(int startY, AbilityHeavyHit hit) {
|
|
int y = startY;
|
|
int labelX = guiLeft + 8;
|
|
int fieldX = guiLeft + 85;
|
|
int col2LabelX = guiLeft + 145;
|
|
int col2FieldX = guiLeft + 205;
|
|
|
|
// Row 1: Damage + Knockback
|
|
addLabel(new GuiNpcLabel(100, "ability.damage", labelX, y + 5));
|
|
addTextField(createFloatField(100, fieldX, y, 50, hit.getDamage()));
|
|
|
|
addLabel(new GuiNpcLabel(101, "ability.knockback", col2LabelX, y + 5));
|
|
addTextField(createFloatField(101, col2FieldX, y, 50, hit.getKnockback()));
|
|
|
|
y += 24;
|
|
|
|
// Row 2: Knockback Up + Stun Ticks
|
|
addLabel(new GuiNpcLabel(102, "ability.knockbackUp", labelX, y + 5));
|
|
addTextField(createFloatField(102, fieldX, y, 50, hit.getKnockbackUp()));
|
|
|
|
addLabel(new GuiNpcLabel(103, "ability.stunTicks", col2LabelX, y + 5));
|
|
addTextField(createIntField(103, col2FieldX, y, 50, hit.getStunTicks()));
|
|
}
|
|
|
|
private void initCutterSettings(int startY, AbilityCutter cutter) {
|
|
int y = startY;
|
|
int labelX = guiLeft + 8;
|
|
int fieldX = guiLeft + 85;
|
|
int col2LabelX = guiLeft + 145;
|
|
int col2FieldX = guiLeft + 205;
|
|
|
|
// Row 1: Arc Angle + Range
|
|
addLabel(new GuiNpcLabel(100, "ability.arcAngle", labelX, y + 5));
|
|
addTextField(createFloatField(100, fieldX, y, 50, cutter.getArcAngle()));
|
|
|
|
addLabel(new GuiNpcLabel(101, "ability.range", col2LabelX, y + 5));
|
|
addTextField(createFloatField(101, col2FieldX, y, 50, cutter.getRange()));
|
|
|
|
y += 24;
|
|
|
|
// Row 2: Damage + Knockback
|
|
addLabel(new GuiNpcLabel(102, "ability.damage", labelX, y + 5));
|
|
addTextField(createFloatField(102, fieldX, y, 50, cutter.getDamage()));
|
|
|
|
addLabel(new GuiNpcLabel(103, "ability.knockback", col2LabelX, y + 5));
|
|
addTextField(createFloatField(103, col2FieldX, y, 50, cutter.getKnockback()));
|
|
|
|
y += 24;
|
|
|
|
// Row 3: Sweep Waves + Wave Interval
|
|
addLabel(new GuiNpcLabel(104, "ability.sweepWaves", labelX, y + 5));
|
|
addTextField(createIntField(104, fieldX, y, 50, cutter.getSweepWaves()));
|
|
|
|
addLabel(new GuiNpcLabel(105, "ability.waveInterval", col2LabelX, y + 5));
|
|
addTextField(createIntField(105, col2FieldX, y, 50, cutter.getWaveInterval()));
|
|
|
|
y += 24;
|
|
|
|
// Row 4: Rotation Speed + Piercing
|
|
addLabel(new GuiNpcLabel(106, "ability.rotSpeed", labelX, y + 5));
|
|
addTextField(createFloatField(106, fieldX, y, 50, cutter.getRotationSpeed()));
|
|
|
|
addLabel(new GuiNpcLabel(107, "ability.piercing", col2LabelX, y + 5));
|
|
addButton(new GuiNpcButton(107, col2FieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, cutter.isPiercing() ? 1 : 0));
|
|
}
|
|
|
|
private void initOrbSettings(int startY, AbilityOrb orb) {
|
|
int y = startY;
|
|
int labelX = guiLeft + 8;
|
|
int fieldX = guiLeft + 85;
|
|
int col2LabelX = guiLeft + 145;
|
|
int col2FieldX = guiLeft + 205;
|
|
|
|
// Row 1: Speed + Size
|
|
addLabel(new GuiNpcLabel(100, "ability.orbSpeed", labelX, y + 5));
|
|
addTextField(createFloatField(100, fieldX, y, 50, orb.getOrbSpeed()));
|
|
|
|
addLabel(new GuiNpcLabel(101, "ability.orbSize", col2LabelX, y + 5));
|
|
addTextField(createFloatField(101, col2FieldX, y, 50, orb.getOrbSize()));
|
|
|
|
y += 24;
|
|
|
|
// Row 2: Damage + Knockback
|
|
addLabel(new GuiNpcLabel(102, "ability.damage", labelX, y + 5));
|
|
addTextField(createFloatField(102, fieldX, y, 50, orb.getDamage()));
|
|
|
|
addLabel(new GuiNpcLabel(103, "ability.knockback", col2LabelX, y + 5));
|
|
addTextField(createFloatField(103, col2FieldX, y, 50, orb.getKnockback()));
|
|
|
|
y += 24;
|
|
|
|
// Row 3: Max Distance + Max Lifetime
|
|
addLabel(new GuiNpcLabel(104, "ability.maxDist", labelX, y + 5));
|
|
addTextField(createFloatField(104, fieldX, y, 50, orb.getMaxDistance()));
|
|
|
|
addLabel(new GuiNpcLabel(105, "ability.lifetime", col2LabelX, y + 5));
|
|
addTextField(createIntField(105, col2FieldX, y, 50, orb.getMaxLifetime()));
|
|
|
|
y += 24;
|
|
|
|
// Row 4: Homing + Explosive
|
|
addLabel(new GuiNpcLabel(106, "ability.homing", labelX, y + 5));
|
|
addButton(new GuiNpcButton(106, fieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, orb.isHoming() ? 1 : 0));
|
|
|
|
addLabel(new GuiNpcLabel(107, "ability.explosive", col2LabelX, y + 5));
|
|
GuiNpcButton explosiveBtn = new GuiNpcButton(107, col2FieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, orb.isExplosive() ? 1 : 0);
|
|
explosiveBtn.setHoverText("ability.explosive.noBlockDamage");
|
|
addButton(explosiveBtn);
|
|
|
|
y += 24;
|
|
|
|
// Row 5: Explosion Radius (only shown when explosive)
|
|
if (orb.isExplosive()) {
|
|
addLabel(new GuiNpcLabel(108, "ability.explRadius", labelX, y + 5));
|
|
addTextField(createFloatField(108, fieldX, y, 50, orb.getExplosionRadius()));
|
|
}
|
|
}
|
|
|
|
private void initVortexSettings(int startY, AbilityVortex pull) {
|
|
int y = startY;
|
|
int labelX = guiLeft + 8;
|
|
int fieldX = guiLeft + 85;
|
|
int col2LabelX = guiLeft + 145;
|
|
int col2FieldX = guiLeft + 205;
|
|
|
|
// Row 1: Pull Radius + Pull Strength
|
|
addLabel(new GuiNpcLabel(100, "ability.pullRadius", labelX, y + 5));
|
|
addTextField(createFloatField(100, fieldX, y, 50, pull.getPullRadius()));
|
|
|
|
addLabel(new GuiNpcLabel(101, "ability.pullStrength", col2LabelX, y + 5));
|
|
addTextField(createFloatField(101, col2FieldX, y, 50, pull.getPullStrength()));
|
|
|
|
y += 24;
|
|
|
|
// Row 2: Damage + Pull To Distance
|
|
addLabel(new GuiNpcLabel(102, "ability.damage", labelX, y + 5));
|
|
addTextField(createFloatField(102, fieldX, y, 50, pull.getDamage()));
|
|
|
|
addLabel(new GuiNpcLabel(103, "ability.pullTo", col2LabelX, y + 5));
|
|
addTextField(createFloatField(103, col2FieldX, y, 50, pull.getPullToDistance()));
|
|
|
|
y += 24;
|
|
|
|
// Row 3: Stun Duration + Root Duration
|
|
addLabel(new GuiNpcLabel(104, "ability.stunDur", labelX, y + 5));
|
|
addTextField(createIntField(104, fieldX, y, 50, pull.getStunDuration()));
|
|
|
|
addLabel(new GuiNpcLabel(105, "ability.rootDur", col2LabelX, y + 5));
|
|
addTextField(createIntField(105, col2FieldX, y, 50, pull.getRootDuration()));
|
|
|
|
y += 24;
|
|
|
|
// Row 4: AOE + Max Targets
|
|
addLabel(new GuiNpcLabel(106, "ability.aoe", labelX, y + 5));
|
|
addButton(new GuiNpcButton(106, fieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, pull.isAoe() ? 1 : 0));
|
|
|
|
addLabel(new GuiNpcLabel(107, "ability.maxTargets", col2LabelX, y + 5));
|
|
addTextField(createIntField(107, col2FieldX, y, 50, pull.getMaxTargets()));
|
|
}
|
|
|
|
private void initShockwaveSettings(int startY, AbilityShockwave shock) {
|
|
int y = startY;
|
|
int labelX = guiLeft + 8;
|
|
int fieldX = guiLeft + 85;
|
|
int col2LabelX = guiLeft + 145;
|
|
int col2FieldX = guiLeft + 205;
|
|
|
|
// Row 1: Push Radius + Push Strength
|
|
addLabel(new GuiNpcLabel(100, "ability.pushRadius", labelX, y + 5));
|
|
addTextField(createFloatField(100, fieldX, y, 50, shock.getPushRadius()));
|
|
|
|
addLabel(new GuiNpcLabel(101, "ability.pushStrength", col2LabelX, y + 5));
|
|
addTextField(createFloatField(101, col2FieldX, y, 50, shock.getPushStrength()));
|
|
|
|
y += 24;
|
|
|
|
// Row 2: Damage + Push Up
|
|
addLabel(new GuiNpcLabel(102, "ability.damage", labelX, y + 5));
|
|
addTextField(createFloatField(102, fieldX, y, 50, shock.getDamage()));
|
|
|
|
addLabel(new GuiNpcLabel(103, "ability.knockbackUp", col2LabelX, y + 5));
|
|
addTextField(createFloatField(103, col2FieldX, y, 50, shock.getPushUp()));
|
|
|
|
y += 24;
|
|
|
|
// Row 3: Stun Duration + Max Targets
|
|
addLabel(new GuiNpcLabel(104, "ability.stunDur", labelX, y + 5));
|
|
addTextField(createIntField(104, fieldX, y, 50, shock.getStunDuration()));
|
|
|
|
addLabel(new GuiNpcLabel(105, "ability.maxTargets", col2LabelX, y + 5));
|
|
addTextField(createIntField(105, col2FieldX, y, 50, shock.getMaxTargets()));
|
|
}
|
|
|
|
private void initDashSettings(int startY, AbilityDash dash) {
|
|
int y = startY;
|
|
int labelX = guiLeft + 8;
|
|
int fieldX = guiLeft + 85;
|
|
int col2LabelX = guiLeft + 145;
|
|
int col2FieldX = guiLeft + 205;
|
|
|
|
// Row 1: Dash Mode
|
|
addLabel(new GuiNpcLabel(100, "ability.dashMode", labelX, y + 5));
|
|
String[] modes = new String[]{"ability.dash.aggressive", "ability.dash.defensive"};
|
|
addButton(new GuiNpcButton(100, fieldX, y, 90, 20, modes, dash.getDashMode().ordinal()));
|
|
|
|
y += 24;
|
|
|
|
// Row 2: Distance + Speed
|
|
addLabel(new GuiNpcLabel(101, "ability.distance", labelX, y + 5));
|
|
addTextField(createFloatField(101, fieldX, y, 50, dash.getDashDistance()));
|
|
|
|
addLabel(new GuiNpcLabel(102, "ability.speed", col2LabelX, y + 5));
|
|
addTextField(createFloatField(102, col2FieldX, y, 50, dash.getDashSpeed()));
|
|
}
|
|
|
|
private void initTeleportSettings(int startY, AbilityTeleport tp) {
|
|
int y = startY;
|
|
int labelX = guiLeft + 8;
|
|
int fieldX = guiLeft + 85;
|
|
int col2LabelX = guiLeft + 145;
|
|
int col2FieldX = guiLeft + 205;
|
|
|
|
// Row 1: Blink Count + Blink Delay
|
|
addLabel(new GuiNpcLabel(100, "ability.blinkCount", labelX, y + 5));
|
|
addTextField(createIntField(100, fieldX, y, 50, tp.getBlinkCount()));
|
|
|
|
addLabel(new GuiNpcLabel(101, "ability.blinkDelay", col2LabelX, y + 5));
|
|
addTextField(createIntField(101, col2FieldX, y, 50, tp.getBlinkDelayTicks()));
|
|
|
|
y += 24;
|
|
|
|
// Row 2: Blink Radius + Min Radius
|
|
addLabel(new GuiNpcLabel(102, "ability.blinkRadius", labelX, y + 5));
|
|
addTextField(createFloatField(102, fieldX, y, 50, tp.getBlinkRadius()));
|
|
|
|
addLabel(new GuiNpcLabel(103, "ability.minRadius", col2LabelX, y + 5));
|
|
addTextField(createFloatField(103, col2FieldX, y, 50, tp.getMinBlinkRadius()));
|
|
|
|
y += 24;
|
|
|
|
// Row 3: Damage + Damage Radius
|
|
addLabel(new GuiNpcLabel(104, "ability.damage", labelX, y + 5));
|
|
addTextField(createFloatField(104, fieldX, y, 50, tp.getDamage()));
|
|
|
|
addLabel(new GuiNpcLabel(105, "ability.dmgRadius", col2LabelX, y + 5));
|
|
addTextField(createFloatField(105, col2FieldX, y, 50, tp.getDamageRadius()));
|
|
|
|
y += 24;
|
|
|
|
// Row 4: Line of Sight + Damage At Start
|
|
addLabel(new GuiNpcLabel(106, "ability.lineOfSight", labelX, y + 5));
|
|
addButton(new GuiNpcButton(106, fieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, tp.isRequireLineOfSight() ? 1 : 0));
|
|
|
|
addLabel(new GuiNpcLabel(107, "ability.dmgAtStart", col2LabelX, y + 5));
|
|
addButton(new GuiNpcButton(107, col2FieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, tp.isDamageAtStart() ? 1 : 0));
|
|
}
|
|
|
|
private void initProjectileSettings(int startY, AbilityProjectile proj) {
|
|
int y = startY;
|
|
int labelX = guiLeft + 8;
|
|
int fieldX = guiLeft + 85;
|
|
int col2LabelX = guiLeft + 145;
|
|
int col2FieldX = guiLeft + 205;
|
|
|
|
// Row 1: Damage + Speed
|
|
addLabel(new GuiNpcLabel(100, "ability.damage", labelX, y + 5));
|
|
addTextField(createFloatField(100, fieldX, y, 50, proj.getDamage()));
|
|
|
|
addLabel(new GuiNpcLabel(101, "ability.speed", col2LabelX, y + 5));
|
|
addTextField(createFloatField(101, col2FieldX, y, 50, proj.getSpeed()));
|
|
|
|
y += 24;
|
|
|
|
// Row 2: Knockback + Explosion Radius
|
|
addLabel(new GuiNpcLabel(102, "ability.knockback", labelX, y + 5));
|
|
addTextField(createFloatField(102, fieldX, y, 50, proj.getKnockback()));
|
|
|
|
addLabel(new GuiNpcLabel(103, "ability.explRadius", col2LabelX, y + 5));
|
|
addTextField(createFloatField(103, col2FieldX, y, 50, proj.getExplosionRadius()));
|
|
|
|
y += 24;
|
|
|
|
// Row 3: Explosive + Homing
|
|
addLabel(new GuiNpcLabel(104, "ability.explosive", labelX, y + 5));
|
|
GuiNpcButton projExplosiveBtn = new GuiNpcButton(104, fieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, proj.isExplosive() ? 1 : 0);
|
|
projExplosiveBtn.setHoverText("ability.explosive.noBlockDamage");
|
|
addButton(projExplosiveBtn);
|
|
|
|
addLabel(new GuiNpcLabel(105, "ability.homing", col2LabelX, y + 5));
|
|
addButton(new GuiNpcButton(105, col2FieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, proj.isHoming() ? 1 : 0));
|
|
}
|
|
|
|
private void initBeamSettings(int startY, AbilityBeam beam) {
|
|
int y = startY;
|
|
int labelX = guiLeft + 8;
|
|
int fieldX = guiLeft + 85;
|
|
int col2LabelX = guiLeft + 145;
|
|
int col2FieldX = guiLeft + 205;
|
|
|
|
// Row 1: Length + Width
|
|
addLabel(new GuiNpcLabel(100, "ability.beamLength", labelX, y + 5));
|
|
addTextField(createFloatField(100, fieldX, y, 50, beam.getBeamLength()));
|
|
|
|
addLabel(new GuiNpcLabel(101, "ability.beamWidth", col2LabelX, y + 5));
|
|
addTextField(createFloatField(101, col2FieldX, y, 50, beam.getBeamWidth()));
|
|
|
|
y += 24;
|
|
|
|
// Row 2: Damage + Damage Interval
|
|
addLabel(new GuiNpcLabel(102, "ability.damage", labelX, y + 5));
|
|
addTextField(createFloatField(102, fieldX, y, 50, beam.getDamage()));
|
|
|
|
addLabel(new GuiNpcLabel(103, "ability.dmgInterval", col2LabelX, y + 5));
|
|
addTextField(createIntField(103, col2FieldX, y, 50, beam.getDamageInterval()));
|
|
|
|
y += 24;
|
|
|
|
// Row 3: Sweep Angle + Sweep Speed
|
|
addLabel(new GuiNpcLabel(104, "ability.sweepAngle", labelX, y + 5));
|
|
addTextField(createFloatField(104, fieldX, y, 50, beam.getSweepAngle()));
|
|
|
|
addLabel(new GuiNpcLabel(105, "ability.sweepSpeed", col2LabelX, y + 5));
|
|
addTextField(createFloatField(105, col2FieldX, y, 50, beam.getSweepSpeed()));
|
|
|
|
y += 24;
|
|
|
|
// Row 4: Piercing + Lock On Target
|
|
addLabel(new GuiNpcLabel(106, "ability.piercing", labelX, y + 5));
|
|
addButton(new GuiNpcButton(106, fieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, beam.isPiercing() ? 1 : 0));
|
|
|
|
addLabel(new GuiNpcLabel(107, "ability.lockTarget", col2LabelX, y + 5));
|
|
addButton(new GuiNpcButton(107, col2FieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, beam.isLockOnTarget() ? 1 : 0));
|
|
}
|
|
|
|
private void initGuardSettings(int startY, AbilityGuard guard) {
|
|
int y = startY;
|
|
int labelX = guiLeft + 8;
|
|
int fieldX = guiLeft + 85;
|
|
int col2LabelX = guiLeft + 145;
|
|
int col2FieldX = guiLeft + 205;
|
|
|
|
// Row 1: Damage Reduction + Counter Damage
|
|
addLabel(new GuiNpcLabel(100, "ability.dmgReduce", labelX, y + 5));
|
|
addTextField(createFloatField(100, fieldX, y, 50, guard.getDamageReduction()));
|
|
|
|
addLabel(new GuiNpcLabel(101, "ability.counterDmg", col2LabelX, y + 5));
|
|
addTextField(createFloatField(101, col2FieldX, y, 50, guard.getCounterDamage()));
|
|
|
|
y += 24;
|
|
|
|
// Row 2: Can Counter + Counter Chance
|
|
addLabel(new GuiNpcLabel(102, "ability.canCounter", labelX, y + 5));
|
|
addButton(new GuiNpcButton(102, fieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, guard.isCanCounter() ? 1 : 0));
|
|
|
|
addLabel(new GuiNpcLabel(103, "ability.counterChance", col2LabelX, y + 5));
|
|
addTextField(createFloatField(103, col2FieldX, y, 50, guard.getCounterChance()));
|
|
}
|
|
|
|
private void initHealSettings(int startY, AbilityHeal heal) {
|
|
int y = startY;
|
|
int labelX = guiLeft + 8;
|
|
int fieldX = guiLeft + 85;
|
|
int col2LabelX = guiLeft + 145;
|
|
int col2FieldX = guiLeft + 205;
|
|
|
|
// Row 1: Heal Amount + Heal Percent
|
|
addLabel(new GuiNpcLabel(100, "ability.healAmount", labelX, y + 5));
|
|
addTextField(createFloatField(100, fieldX, y, 50, heal.getHealAmount()));
|
|
|
|
addLabel(new GuiNpcLabel(101, "ability.healPercent", col2LabelX, y + 5));
|
|
addTextField(createFloatField(101, col2FieldX, y, 50, heal.getHealPercent()));
|
|
|
|
y += 24;
|
|
|
|
// Row 2: Heal Radius + Instant Heal
|
|
addLabel(new GuiNpcLabel(102, "ability.healRadius", labelX, y + 5));
|
|
addTextField(createFloatField(102, fieldX, y, 50, heal.getHealRadius()));
|
|
|
|
addLabel(new GuiNpcLabel(103, "ability.instant", col2LabelX, y + 5));
|
|
addButton(new GuiNpcButton(103, col2FieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, heal.isInstantHeal() ? 1 : 0));
|
|
|
|
y += 24;
|
|
|
|
// Row 3: Heal Self + Heal Allies
|
|
addLabel(new GuiNpcLabel(104, "ability.healSelf", labelX, y + 5));
|
|
addButton(new GuiNpcButton(104, fieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, heal.isHealSelf() ? 1 : 0));
|
|
|
|
addLabel(new GuiNpcLabel(105, "ability.healAllies", col2LabelX, y + 5));
|
|
addButton(new GuiNpcButton(105, col2FieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, heal.isHealAllies() ? 1 : 0));
|
|
}
|
|
|
|
private void initHazardSettings(int startY, AbilityHazard hazard) {
|
|
int y = startY;
|
|
int labelX = guiLeft + 8;
|
|
int fieldX = guiLeft + 85;
|
|
int col2LabelX = guiLeft + 145;
|
|
int col2FieldX = guiLeft + 205;
|
|
|
|
// Row 1: Radius + Damage Per Tick
|
|
addLabel(new GuiNpcLabel(100, "ability.radius", labelX, y + 5));
|
|
addTextField(createFloatField(100, fieldX, y, 50, hazard.getRadius()));
|
|
|
|
addLabel(new GuiNpcLabel(101, "ability.dmgPerTick", col2LabelX, y + 5));
|
|
addTextField(createFloatField(101, col2FieldX, y, 50, hazard.getDamagePerTick()));
|
|
|
|
y += 24;
|
|
|
|
// Row 2: Damage Interval + Debuff Duration
|
|
addLabel(new GuiNpcLabel(102, "ability.dmgInterval", labelX, y + 5));
|
|
addTextField(createIntField(102, fieldX, y, 50, hazard.getDamageInterval()));
|
|
|
|
addLabel(new GuiNpcLabel(103, "ability.debuffDur", col2LabelX, y + 5));
|
|
addTextField(createIntField(103, col2FieldX, y, 50, hazard.getDebuffDuration()));
|
|
|
|
y += 24;
|
|
|
|
// Row 3: Shape + Placement
|
|
addLabel(new GuiNpcLabel(104, "ability.shape", labelX, y + 5));
|
|
String[] shapes = new String[]{"ability.shape.circle", "ability.shape.ring", "ability.shape.cone"};
|
|
addButton(new GuiNpcButton(104, fieldX, y, 60, 20, shapes, hazard.getShape().ordinal()));
|
|
|
|
addLabel(new GuiNpcLabel(105, "ability.placement", col2LabelX, y + 5));
|
|
String[] placements = new String[]{"ability.place.caster", "ability.place.target", "ability.place.followCaster", "ability.place.followTarget"};
|
|
addButton(new GuiNpcButton(105, col2FieldX, y, 60, 20, placements, hazard.getPlacement().ordinal()));
|
|
|
|
y += 24;
|
|
|
|
// Row 4: Affects Caster + Ignore Invuln Frames
|
|
addLabel(new GuiNpcLabel(106, "ability.affectsCaster", labelX, y + 5));
|
|
addButton(new GuiNpcButton(106, fieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, hazard.isAffectsCaster() ? 1 : 0));
|
|
|
|
addLabel(new GuiNpcLabel(107, "ability.ignoreInvuln", col2LabelX, y + 5));
|
|
addButton(new GuiNpcButton(107, col2FieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, hazard.isIgnoreInvulnFrames() ? 1 : 0));
|
|
}
|
|
|
|
private void initTrapSettings(int startY, AbilityTrap trap) {
|
|
int y = startY;
|
|
int labelX = guiLeft + 8;
|
|
int fieldX = guiLeft + 85;
|
|
int col2LabelX = guiLeft + 145;
|
|
int col2FieldX = guiLeft + 205;
|
|
|
|
// Row 1: Trigger Radius + Damage
|
|
addLabel(new GuiNpcLabel(100, "ability.triggerRadius", labelX, y + 5));
|
|
addTextField(createFloatField(100, fieldX, y, 50, trap.getTriggerRadius()));
|
|
|
|
addLabel(new GuiNpcLabel(101, "ability.damage", col2LabelX, y + 5));
|
|
addTextField(createFloatField(101, col2FieldX, y, 50, trap.getDamage()));
|
|
|
|
y += 24;
|
|
|
|
// Row 2: Arm Time + Max Triggers
|
|
addLabel(new GuiNpcLabel(102, "ability.armTime", labelX, y + 5));
|
|
addTextField(createIntField(102, fieldX, y, 50, trap.getArmTime()));
|
|
|
|
addLabel(new GuiNpcLabel(103, "ability.maxTriggers", col2LabelX, y + 5));
|
|
addTextField(createIntField(103, col2FieldX, y, 50, trap.getMaxTriggers()));
|
|
|
|
y += 24;
|
|
|
|
// Row 3: Knockback + Root Duration
|
|
addLabel(new GuiNpcLabel(104, "ability.knockback", labelX, y + 5));
|
|
addTextField(createFloatField(104, fieldX, y, 50, trap.getKnockback()));
|
|
|
|
addLabel(new GuiNpcLabel(105, "ability.rootDur", col2LabelX, y + 5));
|
|
addTextField(createIntField(105, col2FieldX, y, 50, trap.getRootDuration()));
|
|
|
|
y += 24;
|
|
|
|
// Row 4: Placement + Visible
|
|
addLabel(new GuiNpcLabel(106, "ability.placement", labelX, y + 5));
|
|
String[] placements = new String[]{"ability.place.caster", "ability.place.target", "ability.place.ahead"};
|
|
addButton(new GuiNpcButton(106, fieldX, y, 60, 20, placements, trap.getPlacement().ordinal()));
|
|
|
|
addLabel(new GuiNpcLabel(107, "ability.visible", col2LabelX, y + 5));
|
|
addButton(new GuiNpcButton(107, col2FieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, trap.isVisible() ? 1 : 0));
|
|
}
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// HELPER METHODS FOR FIELD CREATION
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
private GuiNpcTextField createFloatField(int id, int x, int y, int width, float value) {
|
|
GuiNpcTextField field = new GuiNpcTextField(id, this, fontRendererObj, x, y, width, 20, String.format("%.1f", value));
|
|
return field;
|
|
}
|
|
|
|
private GuiNpcTextField createIntField(int id, int x, int y, int width, int value) {
|
|
GuiNpcTextField field = new GuiNpcTextField(id, this, fontRendererObj, x, y, width, 20, String.valueOf(value));
|
|
field.setIntegersOnly();
|
|
return field;
|
|
}
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// TIMING TAB
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
private void initTimingTab(int startY) {
|
|
int y = startY;
|
|
int labelX = guiLeft + 8;
|
|
int fieldX = guiLeft + 85;
|
|
int col2LabelX = guiLeft + 145;
|
|
int col2FieldX = guiLeft + 205;
|
|
|
|
// Row 1: Cooldown + Windup
|
|
addLabel(new GuiNpcLabel(10, "ability.cooldown", labelX, y + 5));
|
|
GuiNpcTextField cooldownField = new GuiNpcTextField(10, this, fontRendererObj, fieldX, y, 50, 20, String.valueOf(cooldownTicks));
|
|
cooldownField.setIntegersOnly();
|
|
cooldownField.setMinMaxDefault(0, 10000, 100);
|
|
addTextField(cooldownField);
|
|
|
|
addLabel(new GuiNpcLabel(11, "ability.windup", col2LabelX, y + 5));
|
|
GuiNpcTextField windupField = new GuiNpcTextField(11, this, fontRendererObj, col2FieldX, y, 50, 20, String.valueOf(windUpTicks));
|
|
windupField.setIntegersOnly();
|
|
windupField.setMinMaxDefault(0, 1000, 20);
|
|
addTextField(windupField);
|
|
|
|
y += 24;
|
|
|
|
// Row 2: Active + Recovery
|
|
addLabel(new GuiNpcLabel(12, "ability.active", labelX, y + 5));
|
|
GuiNpcTextField activeField = new GuiNpcTextField(12, this, fontRendererObj, fieldX, y, 50, 20, String.valueOf(activeTicks));
|
|
activeField.setIntegersOnly();
|
|
activeField.setMinMaxDefault(1, 1000, 10);
|
|
addTextField(activeField);
|
|
|
|
addLabel(new GuiNpcLabel(13, "ability.recovery", col2LabelX, y + 5));
|
|
GuiNpcTextField recoveryField = new GuiNpcTextField(13, this, fontRendererObj, col2FieldX, y, 50, 20, String.valueOf(recoveryTicks));
|
|
recoveryField.setIntegersOnly();
|
|
recoveryField.setMinMaxDefault(0, 1000, 20);
|
|
addTextField(recoveryField);
|
|
|
|
y += 28;
|
|
|
|
// Row 3: Interruptible + Threshold
|
|
addLabel(new GuiNpcLabel(14, "ability.interruptible", labelX, y + 5));
|
|
addButton(new GuiNpcButton(14, fieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, interruptible ? 1 : 0));
|
|
|
|
addLabel(new GuiNpcLabel(15, "ability.threshold", col2LabelX, y + 5));
|
|
GuiNpcTextField thresholdField = new GuiNpcTextField(15, this, fontRendererObj, col2FieldX, y, 50, 20, String.valueOf((int) interruptThreshold));
|
|
thresholdField.setIntegersOnly();
|
|
thresholdField.setMinMaxDefault(0, 1000, 10);
|
|
thresholdField.setEnabled(interruptible);
|
|
addTextField(thresholdField);
|
|
|
|
y += 28;
|
|
|
|
// Row 4: Lock Movement
|
|
addLabel(new GuiNpcLabel(16, "ability.lockMove", labelX, y + 5));
|
|
addButton(new GuiNpcButton(16, fieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, lockMovement ? 1 : 0));
|
|
}
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// EFFECTS TAB (Sounds & Animations)
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
private void initEffectsTab(int startY) {
|
|
int y = startY;
|
|
int labelX = guiLeft + 8;
|
|
int fieldX = guiLeft + 100;
|
|
int btnX = guiLeft + 215;
|
|
|
|
// Row 1: Wind Up Sound
|
|
addLabel(new GuiNpcLabel(30, "ability.windUpSound", labelX, y + 5));
|
|
String windUpSoundDisplay = windUpSound != null && !windUpSound.isEmpty() ? truncateString(windUpSound, 15) : "None";
|
|
addButton(new GuiNpcButton(30, fieldX, y, 110, 20, windUpSoundDisplay));
|
|
addButton(new GuiNpcButton(35, btnX, y, 20, 20, "X"));
|
|
|
|
y += 25;
|
|
|
|
// Row 2: Active Sound
|
|
addLabel(new GuiNpcLabel(31, "ability.activeSound", labelX, y + 5));
|
|
String activeSoundDisplay = activeSound != null && !activeSound.isEmpty() ? truncateString(activeSound, 15) : "None";
|
|
addButton(new GuiNpcButton(31, fieldX, y, 110, 20, activeSoundDisplay));
|
|
addButton(new GuiNpcButton(36, btnX, y, 20, 20, "X"));
|
|
|
|
y += 30;
|
|
|
|
// Row 3: Wind Up Animation
|
|
addLabel(new GuiNpcLabel(32, "ability.windUpAnim", labelX, y + 5));
|
|
String windUpAnimName = getAnimationName(windUpAnimationId, true);
|
|
addButton(new GuiNpcButton(32, fieldX, y, 110, 20, windUpAnimName));
|
|
addButton(new GuiNpcButton(37, btnX, y, 20, 20, "X"));
|
|
|
|
y += 25;
|
|
|
|
// Row 4: Active Animation
|
|
addLabel(new GuiNpcLabel(33, "ability.activeAnim", labelX, y + 5));
|
|
String activeAnimName = getAnimationName(activeAnimationId, false);
|
|
addButton(new GuiNpcButton(33, fieldX, y, 110, 20, activeAnimName));
|
|
addButton(new GuiNpcButton(38, btnX, y, 20, 20, "X"));
|
|
}
|
|
|
|
private String truncateString(String str, int maxLen) {
|
|
if (str == null) return "";
|
|
if (str.length() <= maxLen) return str;
|
|
// Try to show the end part (more useful for resource paths)
|
|
int lastSlash = str.lastIndexOf('/');
|
|
if (lastSlash >= 0 && str.length() - lastSlash <= maxLen) {
|
|
return "..." + str.substring(lastSlash);
|
|
}
|
|
return "..." + str.substring(str.length() - maxLen + 3);
|
|
}
|
|
|
|
private String getAnimationName(int animId, boolean isWindUp) {
|
|
if (animId < 0) return "None";
|
|
// Use cached name if available
|
|
String cachedName = isWindUp ? windUpAnimationName : activeAnimationName;
|
|
if (cachedName != null && !cachedName.isEmpty()) {
|
|
return cachedName;
|
|
}
|
|
return "ID: " + animId;
|
|
}
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// TELEGRAPH TAB
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
private void initTelegraphTab(int startY) {
|
|
int y = startY;
|
|
int labelX = guiLeft + 8;
|
|
int fieldX = guiLeft + 110;
|
|
|
|
// Row 1: Show Telegraph
|
|
addLabel(new GuiNpcLabel(20, "ability.showTelegraph", labelX, y + 5));
|
|
addButton(new GuiNpcButton(20, fieldX, y, 50, 20, new String[]{"gui.no", "gui.yes"}, showTelegraph ? 1 : 0));
|
|
|
|
y += 25;
|
|
|
|
// Row 2: Wind Up Color
|
|
addLabel(new GuiNpcLabel(21, "ability.windUpColor", labelX, y + 5));
|
|
String windUpHex = String.format("%06X", windUpColor & 0xFFFFFF);
|
|
GuiNpcButton windUpBtn = new GuiNpcButton(22, fieldX, y, 70, 20, windUpHex);
|
|
windUpBtn.setEnabled(showTelegraph);
|
|
windUpBtn.setTextColor(windUpColor & 0xFFFFFF);
|
|
addButton(windUpBtn);
|
|
|
|
y += 25;
|
|
|
|
// Row 3: Active Color
|
|
addLabel(new GuiNpcLabel(23, "ability.activeColor", labelX, y + 5));
|
|
String activeHex = String.format("%06X", activeColor & 0xFFFFFF);
|
|
GuiNpcButton activeBtn = new GuiNpcButton(24, fieldX, y, 70, 20, activeHex);
|
|
activeBtn.setEnabled(showTelegraph);
|
|
activeBtn.setTextColor(activeColor & 0xFFFFFF);
|
|
addButton(activeBtn);
|
|
|
|
y += 30;
|
|
|
|
// Info: Telegraph type
|
|
String typeKey = "ability.telegraph." + ability.getTelegraphType().name().toLowerCase();
|
|
addLabel(new GuiNpcLabel(25, "ability.telegraphType", labelX, y));
|
|
addLabel(new GuiNpcLabel(26, typeKey, fieldX, y));
|
|
|
|
y += 18;
|
|
|
|
// Info note
|
|
addLabel(new GuiNpcLabel(27, "ability.telegraphSizeNote", labelX, y));
|
|
}
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// BUTTON EVENTS
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
@Override
|
|
public void buttonEvent(GuiButton guibutton) {
|
|
int id = guibutton.id;
|
|
|
|
// Tab switching
|
|
if (id == 90) {
|
|
activeTab = TAB_GENERAL;
|
|
initGui();
|
|
return;
|
|
}
|
|
if (id == 91 && hasTypeSettings) {
|
|
activeTab = TAB_TYPE;
|
|
initGui();
|
|
return;
|
|
}
|
|
if (id == 92) {
|
|
activeTab = TAB_TIMING;
|
|
initGui();
|
|
return;
|
|
}
|
|
if (id == 93 && supportsTelegraph) {
|
|
activeTab = TAB_TELEGRAPH;
|
|
initGui();
|
|
return;
|
|
}
|
|
if (id == 94) {
|
|
activeTab = TAB_EFFECTS;
|
|
initGui();
|
|
return;
|
|
}
|
|
|
|
// Enabled button (bottom left)
|
|
if (id == 2) {
|
|
enabled = ((GuiNpcButton) guibutton).getValue() == 1;
|
|
initGui(); // Refresh to update button color
|
|
}
|
|
// Targeting mode
|
|
else if (id == 4) {
|
|
TargetingMode[] modes = ability.getAllowedTargetingModes();
|
|
int idx = ((GuiNpcButton) guibutton).getValue();
|
|
if (modes != null && idx < modes.length) {
|
|
targetingMode = modes[idx];
|
|
} else {
|
|
targetingMode = TargetingMode.values()[idx];
|
|
}
|
|
}
|
|
|
|
// Timing tab
|
|
else if (id == 14) {
|
|
interruptible = ((GuiNpcButton) guibutton).getValue() == 1;
|
|
initGui();
|
|
} else if (id == 16) {
|
|
lockMovement = ((GuiNpcButton) guibutton).getValue() == 1;
|
|
}
|
|
|
|
// Telegraph tab
|
|
else if (id == 20) {
|
|
showTelegraph = ((GuiNpcButton) guibutton).getValue() == 1;
|
|
initGui();
|
|
}
|
|
// Wind Up color button - open color selector
|
|
else if (id == 22) {
|
|
editingColorId = 22;
|
|
setSubGui(new SubGuiColorSelector(windUpColor));
|
|
}
|
|
// Active color button - open color selector
|
|
else if (id == 24) {
|
|
editingColorId = 24;
|
|
setSubGui(new SubGuiColorSelector(activeColor));
|
|
}
|
|
|
|
// Effects tab - Sound buttons
|
|
else if (id == 30) {
|
|
editingSoundId = 30;
|
|
setSubGui(new GuiSoundSelection(windUpSound));
|
|
}
|
|
else if (id == 31) {
|
|
editingSoundId = 31;
|
|
setSubGui(new GuiSoundSelection(activeSound));
|
|
}
|
|
// Sound clear buttons
|
|
else if (id == 35) {
|
|
windUpSound = "";
|
|
initGui();
|
|
}
|
|
else if (id == 36) {
|
|
activeSound = "";
|
|
initGui();
|
|
}
|
|
// Animation buttons
|
|
else if (id == 32) {
|
|
editingAnimationId = 32;
|
|
setSubGui(new GuiAnimationSelection(windUpAnimationId));
|
|
}
|
|
else if (id == 33) {
|
|
editingAnimationId = 33;
|
|
setSubGui(new GuiAnimationSelection(activeAnimationId));
|
|
}
|
|
// Animation clear buttons
|
|
else if (id == 37) {
|
|
windUpAnimationId = -1;
|
|
windUpAnimationName = null;
|
|
initGui();
|
|
}
|
|
else if (id == 38) {
|
|
activeAnimationId = -1;
|
|
activeAnimationName = null;
|
|
initGui();
|
|
}
|
|
|
|
// Type-specific buttons (100+)
|
|
else if (id >= 100) {
|
|
handleTypeButton(id, (GuiNpcButton) guibutton);
|
|
}
|
|
|
|
// Done/Cancel
|
|
else if (id == 66) {
|
|
applyToAbility();
|
|
parent.onAbilitySaved(ability);
|
|
close();
|
|
} else if (id == 67) {
|
|
close();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called when an ability is loaded from saved presets.
|
|
*/
|
|
public void loadAbility(Ability loadedAbility) {
|
|
if (loadedAbility == null) return;
|
|
|
|
// Copy all values from loaded ability to current ability
|
|
NBTTagCompound nbt = loadedAbility.writeNBT();
|
|
// Keep the current typeId since we can't change types mid-edit
|
|
nbt.setString("typeId", ability.getTypeId());
|
|
ability.readNBT(nbt);
|
|
|
|
// Update cached values
|
|
this.name = ability.getName() != null ? ability.getName() : "";
|
|
this.enabled = ability.isEnabled();
|
|
this.weight = ability.getWeight();
|
|
this.minRange = ability.getMinRange();
|
|
this.maxRange = ability.getMaxRange();
|
|
this.targetingMode = ability.getTargetingMode();
|
|
|
|
this.cooldownTicks = ability.getCooldownTicks();
|
|
this.windUpTicks = ability.getWindUpTicks();
|
|
this.activeTicks = ability.getActiveTicks();
|
|
this.recoveryTicks = ability.getRecoveryTicks();
|
|
this.interruptible = ability.isInterruptible();
|
|
this.interruptThreshold = ability.getInterruptThreshold();
|
|
this.lockMovement = ability.isLockMovement();
|
|
|
|
this.showTelegraph = ability.isShowTelegraph();
|
|
this.windUpColor = ability.getWindUpColor();
|
|
this.activeColor = ability.getActiveColor();
|
|
|
|
initGui();
|
|
}
|
|
|
|
private void handleTypeButton(int id, GuiNpcButton button) {
|
|
int value = button.getValue();
|
|
|
|
if (ability instanceof AbilityDash) {
|
|
AbilityDash dash = (AbilityDash) ability;
|
|
if (id == 100) dash.setDashMode(AbilityDash.DashMode.values()[value]);
|
|
} else if (ability instanceof AbilityCutter) {
|
|
AbilityCutter cutter = (AbilityCutter) ability;
|
|
if (id == 107) cutter.setPiercing(value == 1);
|
|
} else if (ability instanceof AbilityOrb) {
|
|
AbilityOrb orb = (AbilityOrb) ability;
|
|
if (id == 106) orb.setHoming(value == 1);
|
|
else if (id == 107) {
|
|
orb.setExplosive(value == 1);
|
|
initGui(); // Refresh to show/hide explosion radius field
|
|
}
|
|
} else if (ability instanceof AbilityVortex) {
|
|
AbilityVortex pull = (AbilityVortex) ability;
|
|
if (id == 106) pull.setAoe(value == 1);
|
|
} else if (ability instanceof AbilityTeleport) {
|
|
AbilityTeleport tp = (AbilityTeleport) ability;
|
|
if (id == 106) tp.setRequireLineOfSight(value == 1);
|
|
else if (id == 107) tp.setDamageAtStart(value == 1);
|
|
} else if (ability instanceof AbilityProjectile) {
|
|
AbilityProjectile proj = (AbilityProjectile) ability;
|
|
if (id == 104) proj.setExplosive(value == 1);
|
|
else if (id == 105) proj.setHoming(value == 1);
|
|
} else if (ability instanceof AbilityBeam) {
|
|
AbilityBeam beam = (AbilityBeam) ability;
|
|
if (id == 106) beam.setPiercing(value == 1);
|
|
else if (id == 107) beam.setLockOnTarget(value == 1);
|
|
} else if (ability instanceof AbilityGuard) {
|
|
AbilityGuard guard = (AbilityGuard) ability;
|
|
if (id == 102) guard.setCanCounter(value == 1);
|
|
} else if (ability instanceof AbilityHeal) {
|
|
AbilityHeal heal = (AbilityHeal) ability;
|
|
if (id == 103) heal.setInstantHeal(value == 1);
|
|
else if (id == 104) heal.setHealSelf(value == 1);
|
|
else if (id == 105) heal.setHealAllies(value == 1);
|
|
} else if (ability instanceof AbilityHazard) {
|
|
AbilityHazard hazard = (AbilityHazard) ability;
|
|
if (id == 104) hazard.setShape(AbilityHazard.HazardShape.values()[value]);
|
|
else if (id == 105) hazard.setPlacement(AbilityHazard.PlacementMode.values()[value]);
|
|
else if (id == 106) hazard.setAffectsCaster(value == 1);
|
|
else if (id == 107) hazard.setIgnoreInvulnFrames(value == 1);
|
|
} else if (ability instanceof AbilityTrap) {
|
|
AbilityTrap trap = (AbilityTrap) ability;
|
|
if (id == 106) trap.setPlacement(AbilityTrap.TrapPlacement.values()[value]);
|
|
else if (id == 107) trap.setVisible(value == 1);
|
|
}
|
|
}
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// TEXT FIELD EVENTS
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
@Override
|
|
public void unFocused(GuiNpcTextField textField) {
|
|
int id = textField.id;
|
|
|
|
// General tab
|
|
if (id == 1) {
|
|
name = textField.getText();
|
|
} else if (id == 3) {
|
|
weight = textField.getInteger();
|
|
} else if (id == 5) {
|
|
minRange = textField.getInteger();
|
|
} else if (id == 6) {
|
|
maxRange = textField.getInteger();
|
|
}
|
|
|
|
// Timing tab
|
|
else if (id == 10) {
|
|
cooldownTicks = textField.getInteger();
|
|
} else if (id == 11) {
|
|
windUpTicks = textField.getInteger();
|
|
} else if (id == 12) {
|
|
activeTicks = textField.getInteger();
|
|
} else if (id == 13) {
|
|
recoveryTicks = textField.getInteger();
|
|
} else if (id == 15) {
|
|
interruptThreshold = textField.getInteger();
|
|
}
|
|
|
|
// Type-specific fields (100+)
|
|
else if (id >= 100) {
|
|
handleTypeTextField(id, textField);
|
|
}
|
|
}
|
|
|
|
private void handleTypeTextField(int id, GuiNpcTextField field) {
|
|
if (ability instanceof AbilitySlam) {
|
|
AbilitySlam slam = (AbilitySlam) ability;
|
|
if (id == 100) slam.setDamage(parseFloat(field, slam.getDamage()));
|
|
else if (id == 101) slam.setRadius(parseFloat(field, slam.getRadius()));
|
|
else if (id == 102) slam.setKnockbackStrength(parseFloat(field, slam.getKnockbackStrength()));
|
|
else if (id == 103) slam.setLeapSpeed(parseFloat(field, slam.getLeapSpeed()));
|
|
else if (id == 104) slam.setMinLeapDistance(parseFloat(field, slam.getMinLeapDistance()));
|
|
else if (id == 105) slam.setMaxLeapDistance(parseFloat(field, slam.getMaxLeapDistance()));
|
|
} else if (ability instanceof AbilityCharge) {
|
|
AbilityCharge charge = (AbilityCharge) ability;
|
|
if (id == 100) charge.setDamage(parseFloat(field, charge.getDamage()));
|
|
else if (id == 101) charge.setChargeSpeed(parseFloat(field, charge.getChargeSpeed()));
|
|
else if (id == 102) charge.setKnockback(parseFloat(field, charge.getKnockback()));
|
|
else if (id == 103) charge.setKnockbackUp(parseFloat(field, charge.getKnockbackUp()));
|
|
else if (id == 104) charge.setMaxDistance(parseFloat(field, charge.getMaxDistance()));
|
|
else if (id == 105) charge.setHitRadius(parseFloat(field, charge.getHitRadius()));
|
|
} else if (ability instanceof AbilityHeavyHit) {
|
|
AbilityHeavyHit hit = (AbilityHeavyHit) ability;
|
|
if (id == 100) hit.setDamage(parseFloat(field, hit.getDamage()));
|
|
else if (id == 101) hit.setKnockback(parseFloat(field, hit.getKnockback()));
|
|
else if (id == 102) hit.setKnockbackUp(parseFloat(field, hit.getKnockbackUp()));
|
|
else if (id == 103) hit.setStunTicks(field.getInteger());
|
|
} else if (ability instanceof AbilityCutter) {
|
|
AbilityCutter cutter = (AbilityCutter) ability;
|
|
if (id == 100) cutter.setArcAngle(parseFloat(field, cutter.getArcAngle()));
|
|
else if (id == 101) cutter.setRange(parseFloat(field, cutter.getRange()));
|
|
else if (id == 102) cutter.setDamage(parseFloat(field, cutter.getDamage()));
|
|
else if (id == 103) cutter.setKnockback(parseFloat(field, cutter.getKnockback()));
|
|
else if (id == 104) cutter.setSweepWaves(field.getInteger());
|
|
else if (id == 105) cutter.setWaveInterval(field.getInteger());
|
|
else if (id == 106) cutter.setRotationSpeed(parseFloat(field, cutter.getRotationSpeed()));
|
|
} else if (ability instanceof AbilityOrb) {
|
|
AbilityOrb orb = (AbilityOrb) ability;
|
|
if (id == 100) orb.setOrbSpeed(parseFloat(field, orb.getOrbSpeed()));
|
|
else if (id == 101) orb.setOrbSize(parseFloat(field, orb.getOrbSize()));
|
|
else if (id == 102) orb.setDamage(parseFloat(field, orb.getDamage()));
|
|
else if (id == 103) orb.setKnockback(parseFloat(field, orb.getKnockback()));
|
|
else if (id == 104) orb.setMaxDistance(parseFloat(field, orb.getMaxDistance()));
|
|
else if (id == 105) orb.setMaxLifetime(field.getInteger());
|
|
else if (id == 108) orb.setExplosionRadius(parseFloat(field, orb.getExplosionRadius()));
|
|
} else if (ability instanceof AbilityVortex) {
|
|
AbilityVortex pull = (AbilityVortex) ability;
|
|
if (id == 100) pull.setPullRadius(parseFloat(field, pull.getPullRadius()));
|
|
else if (id == 101) pull.setPullStrength(parseFloat(field, pull.getPullStrength()));
|
|
else if (id == 102) pull.setDamage(parseFloat(field, pull.getDamage()));
|
|
else if (id == 103) pull.setPullToDistance(parseFloat(field, pull.getPullToDistance()));
|
|
else if (id == 104) pull.setStunDuration(field.getInteger());
|
|
else if (id == 105) pull.setRootDuration(field.getInteger());
|
|
else if (id == 107) pull.setMaxTargets(field.getInteger());
|
|
} else if (ability instanceof AbilityShockwave) {
|
|
AbilityShockwave shock = (AbilityShockwave) ability;
|
|
if (id == 100) shock.setPushRadius(parseFloat(field, shock.getPushRadius()));
|
|
else if (id == 101) shock.setPushStrength(parseFloat(field, shock.getPushStrength()));
|
|
else if (id == 102) shock.setDamage(parseFloat(field, shock.getDamage()));
|
|
else if (id == 103) shock.setPushUp(parseFloat(field, shock.getPushUp()));
|
|
else if (id == 104) shock.setStunDuration(field.getInteger());
|
|
else if (id == 105) shock.setMaxTargets(field.getInteger());
|
|
} else if (ability instanceof AbilityDash) {
|
|
AbilityDash dash = (AbilityDash) ability;
|
|
if (id == 101) dash.setDashDistance(parseFloat(field, dash.getDashDistance()));
|
|
else if (id == 102) dash.setDashSpeed(parseFloat(field, dash.getDashSpeed()));
|
|
} else if (ability instanceof AbilityTeleport) {
|
|
AbilityTeleport tp = (AbilityTeleport) ability;
|
|
if (id == 100) tp.setBlinkCount(field.getInteger());
|
|
else if (id == 101) tp.setBlinkDelayTicks(field.getInteger());
|
|
else if (id == 102) tp.setBlinkRadius(parseFloat(field, tp.getBlinkRadius()));
|
|
else if (id == 103) tp.setMinBlinkRadius(parseFloat(field, tp.getMinBlinkRadius()));
|
|
else if (id == 104) tp.setDamage(parseFloat(field, tp.getDamage()));
|
|
else if (id == 105) tp.setDamageRadius(parseFloat(field, tp.getDamageRadius()));
|
|
} else if (ability instanceof AbilityProjectile) {
|
|
AbilityProjectile proj = (AbilityProjectile) ability;
|
|
if (id == 100) proj.setDamage(parseFloat(field, proj.getDamage()));
|
|
else if (id == 101) proj.setSpeed(parseFloat(field, proj.getSpeed()));
|
|
else if (id == 102) proj.setKnockback(parseFloat(field, proj.getKnockback()));
|
|
else if (id == 103) proj.setExplosionRadius(parseFloat(field, proj.getExplosionRadius()));
|
|
} else if (ability instanceof AbilityBeam) {
|
|
AbilityBeam beam = (AbilityBeam) ability;
|
|
if (id == 100) beam.setBeamLength(parseFloat(field, beam.getBeamLength()));
|
|
else if (id == 101) beam.setBeamWidth(parseFloat(field, beam.getBeamWidth()));
|
|
else if (id == 102) beam.setDamage(parseFloat(field, beam.getDamage()));
|
|
else if (id == 103) beam.setDamageInterval(field.getInteger());
|
|
else if (id == 104) beam.setSweepAngle(parseFloat(field, beam.getSweepAngle()));
|
|
else if (id == 105) beam.setSweepSpeed(parseFloat(field, beam.getSweepSpeed()));
|
|
} else if (ability instanceof AbilityGuard) {
|
|
AbilityGuard guard = (AbilityGuard) ability;
|
|
if (id == 100) guard.setDamageReduction(parseFloat(field, guard.getDamageReduction()));
|
|
else if (id == 101) guard.setCounterDamage(parseFloat(field, guard.getCounterDamage()));
|
|
else if (id == 103) guard.setCounterChance(parseFloat(field, guard.getCounterChance()));
|
|
} else if (ability instanceof AbilityHeal) {
|
|
AbilityHeal heal = (AbilityHeal) ability;
|
|
if (id == 100) heal.setHealAmount(parseFloat(field, heal.getHealAmount()));
|
|
else if (id == 101) heal.setHealPercent(parseFloat(field, heal.getHealPercent()));
|
|
else if (id == 102) heal.setHealRadius(parseFloat(field, heal.getHealRadius()));
|
|
} else if (ability instanceof AbilityHazard) {
|
|
AbilityHazard hazard = (AbilityHazard) ability;
|
|
if (id == 100) hazard.setRadius(parseFloat(field, hazard.getRadius()));
|
|
else if (id == 101) hazard.setDamagePerTick(parseFloat(field, hazard.getDamagePerTick()));
|
|
else if (id == 102) hazard.setDamageInterval(field.getInteger());
|
|
else if (id == 103) hazard.setDebuffDuration(field.getInteger());
|
|
} else if (ability instanceof AbilityTrap) {
|
|
AbilityTrap trap = (AbilityTrap) ability;
|
|
if (id == 100) trap.setTriggerRadius(parseFloat(field, trap.getTriggerRadius()));
|
|
else if (id == 101) trap.setDamage(parseFloat(field, trap.getDamage()));
|
|
else if (id == 102) trap.setArmTime(field.getInteger());
|
|
else if (id == 103) trap.setMaxTriggers(field.getInteger());
|
|
else if (id == 104) trap.setKnockback(parseFloat(field, trap.getKnockback()));
|
|
else if (id == 105) trap.setRootDuration(field.getInteger());
|
|
}
|
|
}
|
|
|
|
private float parseFloat(GuiNpcTextField field, float defaultValue) {
|
|
try {
|
|
return Float.parseFloat(field.getText());
|
|
} catch (NumberFormatException e) {
|
|
return defaultValue;
|
|
}
|
|
}
|
|
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
// APPLY TO ABILITY
|
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
|
|
private void applyToAbility() {
|
|
// General
|
|
ability.setName(name);
|
|
ability.setEnabled(enabled);
|
|
ability.setWeight(weight);
|
|
ability.setMinRange(minRange);
|
|
ability.setMaxRange(maxRange);
|
|
ability.setTargetingMode(targetingMode);
|
|
|
|
// Timing
|
|
ability.setCooldownTicks(cooldownTicks);
|
|
ability.setWindUpTicks(windUpTicks);
|
|
ability.setActiveTicks(activeTicks);
|
|
ability.setRecoveryTicks(recoveryTicks);
|
|
ability.setInterruptible(interruptible);
|
|
ability.setInterruptThreshold(interruptThreshold);
|
|
ability.setLockMovement(lockMovement);
|
|
|
|
// Telegraph
|
|
ability.setShowTelegraph(showTelegraph);
|
|
ability.setWindUpColor(windUpColor);
|
|
ability.setActiveColor(activeColor);
|
|
|
|
// Effects (sounds/animations)
|
|
ability.setWindUpSound(windUpSound);
|
|
ability.setActiveSound(activeSound);
|
|
ability.setWindUpAnimationId(windUpAnimationId);
|
|
ability.setActiveAnimationId(activeAnimationId);
|
|
|
|
// Type-specific values are applied directly in handleTypeTextField and handleTypeButton
|
|
}
|
|
|
|
@Override
|
|
public void subGuiClosed(SubGuiInterface subgui) {
|
|
if (subgui instanceof SubGuiColorSelector) {
|
|
SubGuiColorSelector colorSelector = (SubGuiColorSelector) subgui;
|
|
// Color selector returns RGB without alpha, so we need to add appropriate alpha
|
|
// Wind up color uses 0x80 alpha (semi-transparent), active uses 0xC0 (more opaque)
|
|
int rgb = colorSelector.color & 0x00FFFFFF;
|
|
if (editingColorId == 22) {
|
|
windUpColor = 0x80000000 | rgb;
|
|
} else if (editingColorId == 24) {
|
|
activeColor = 0xC0000000 | rgb;
|
|
}
|
|
editingColorId = 0;
|
|
initGui();
|
|
} else if (subgui instanceof GuiSoundSelection) {
|
|
GuiSoundSelection soundSelector = (GuiSoundSelection) subgui;
|
|
if (soundSelector.selectedResource != null) {
|
|
String sound = soundSelector.selectedResource.toString();
|
|
if (editingSoundId == 30) {
|
|
windUpSound = sound;
|
|
} else if (editingSoundId == 31) {
|
|
activeSound = sound;
|
|
}
|
|
}
|
|
editingSoundId = 0;
|
|
initGui();
|
|
} else if (subgui instanceof GuiAnimationSelection) {
|
|
GuiAnimationSelection animSelector = (GuiAnimationSelection) subgui;
|
|
// Update if user selected something or cleared
|
|
if (editingAnimationId == 32) {
|
|
windUpAnimationId = animSelector.selectedAnimationId;
|
|
windUpAnimationName = animSelector.getSelectedName();
|
|
} else if (editingAnimationId == 33) {
|
|
activeAnimationId = animSelector.selectedAnimationId;
|
|
activeAnimationName = animSelector.getSelectedName();
|
|
}
|
|
editingAnimationId = 0;
|
|
initGui();
|
|
}
|
|
}
|
|
}
|