mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-12 06:07:27 +00:00
Fixes to some GUI and Chained Abiltiy Logic for Clearing States
This commit is contained in:
1 parent
48f6c162d5
commit
40a02b73e2
8 files changed
+196
-65
No files matched your search
@@ -14,6 +14,7 @@ import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.StatCollector;
|
||||
import net.minecraft.world.World;
|
||||
import noppes.npcs.DataAbilities;
|
||||
import noppes.npcs.NpcDamageSource;
|
||||
@@ -281,6 +282,17 @@ public abstract class Ability implements IAbility, IAbilityAction {
|
||||
public void onComplete(EntityLivingBase caster, EntityLivingBase target) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the ability enters BURST_DELAY between burst iterations.
|
||||
* Override in subclasses to reset transient state that should not carry
|
||||
* across burst repetitions (e.g., movement direction, hit entity lists).
|
||||
* <p>
|
||||
* Unlike {@link #cleanup()}, this does NOT kill spawned entities (they may
|
||||
* still be in flight for overlap mode).
|
||||
*/
|
||||
public void resetForBurst() {
|
||||
}
|
||||
|
||||
public void onDamageTaken(EntityLivingBase caster, EntityLivingBase attacker, DamageSource source, float damage) {
|
||||
}
|
||||
|
||||
@@ -535,6 +547,10 @@ public abstract class Ability implements IAbility, IAbilityAction {
|
||||
.tab("General"));
|
||||
defs.add(FieldDef.stringField("gui.displayName", this::getRawDisplayName, this::setDisplayName)
|
||||
.tab("General"));
|
||||
defs.add(FieldDef.labelField("ability.validFor", () ->
|
||||
StatCollector.translateToLocal("ability.validFor") + ": \u00A7e"
|
||||
+ StatCollector.translateToLocal("ability.userType." + getAllowedBy().name()))
|
||||
.tab("General"));
|
||||
defs.add(FieldDef.row(
|
||||
FieldDef.intField("ability.weight", this::getWeight, this::setWeight).range(1, 1000),
|
||||
FieldDef.boolField("gui.enabled", this::isEnabled, this::setEnabled)
|
||||
@@ -979,9 +995,9 @@ public abstract class Ability implements IAbility, IAbilityAction {
|
||||
if (phase == AbilityPhase.ACTIVE) {
|
||||
// Check if more burst iterations remain
|
||||
if (burstEnabled && burstAmount > 0 && burstIndex < burstAmount) {
|
||||
// Don't cleanup here - entities may still be in flight
|
||||
// For non-overlap: cleaned up when next burst starts (in onExecute)
|
||||
// For overlap: entities continue flying indefinitely
|
||||
// Reset transient state for next burst iteration (e.g., movement direction, hit lists)
|
||||
// Does NOT kill entities - they may still be in flight (overlap mode)
|
||||
resetForBurst();
|
||||
burstIndex++;
|
||||
phase = AbilityPhase.BURST_DELAY;
|
||||
currentTick = 0;
|
||||
|
||||
@@ -171,6 +171,12 @@ public class AbilityCharge extends AbilityMovement implements IAbilityCharge {
|
||||
hitEntities.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetForBurst() {
|
||||
super.resetForBurst();
|
||||
hitEntities.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getTelegraphLength() {
|
||||
return maxRange;
|
||||
|
||||
@@ -196,6 +196,12 @@ public class AbilityDash extends AbilityMovement implements IAbilityDash {
|
||||
chosenDirection = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetForBurst() {
|
||||
super.resetForBurst();
|
||||
chosenDirection = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxPreviewDuration() {
|
||||
return (int) Math.ceil(dashDistance / dashSpeed) + 5;
|
||||
|
||||
@@ -53,6 +53,12 @@ public abstract class AbilityMovement extends Ability {
|
||||
maxActiveTicks = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetForBurst() {
|
||||
movementDirection = null;
|
||||
maxActiveTicks = 0;
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// DIRECTION HELPERS
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
+1
@@ -68,6 +68,7 @@ public abstract class AbilityEnergyProjectile<E extends EntityEnergyProjectile>
|
||||
this.homingData = homingData;
|
||||
this.lifespanData = lifespanData;
|
||||
this.trajectoryData = new EnergyTrajectoryData();
|
||||
this.burstOverlap = true;
|
||||
initProjectiles(1);
|
||||
}
|
||||
|
||||
|
||||
@@ -616,8 +616,10 @@ public abstract class AbstractDataAbilities {
|
||||
return;
|
||||
}
|
||||
|
||||
// Auto-complete for burst overlap mode
|
||||
// Auto-complete for burst overlap mode only.
|
||||
// Non-overlap waits for all entities to die naturally (via allDead check in onActiveTick).
|
||||
if (currentAbility.isBurstEnabled()
|
||||
&& currentAbility.isBurstOverlap()
|
||||
&& currentAbility.getBurstIndex() < currentAbility.getBurstAmount()
|
||||
&& currentAbility.getPhase() == AbilityPhase.ACTIVE
|
||||
&& currentAbility.isReadyForBurstCompletion(currentAbility.getCurrentTick())) {
|
||||
@@ -682,10 +684,12 @@ public abstract class AbstractDataAbilities {
|
||||
|
||||
// Chain mode: advance to next entry instead of completing
|
||||
if (currentChain != null) {
|
||||
// AFTER semantics: delay from the CURRENT (just-completed) entry
|
||||
ChainedAbilityEntry completedEntry = currentChain.getEntries().get(chainEntryIndex);
|
||||
int delay = completedEntry.getDelayTicks();
|
||||
|
||||
chainEntryIndex++;
|
||||
if (chainEntryIndex < currentChain.getEntries().size()) {
|
||||
ChainedAbilityEntry nextEntry = currentChain.getEntries().get(chainEntryIndex);
|
||||
|
||||
// Check if target died and retarget
|
||||
if (target != null && target.isDead) {
|
||||
target = retargetForChain();
|
||||
@@ -695,13 +699,9 @@ public abstract class AbstractDataAbilities {
|
||||
}
|
||||
}
|
||||
|
||||
int delay = nextEntry.getDelayTicks();
|
||||
if (delay > 0) {
|
||||
chainDelayRemaining = delay;
|
||||
currentAbility = null;
|
||||
} else {
|
||||
startChainEntry(target);
|
||||
}
|
||||
// Enforce minimum 1-tick delay between chain entries
|
||||
chainDelayRemaining = Math.max(1, delay);
|
||||
currentAbility = null;
|
||||
return;
|
||||
}
|
||||
// All entries complete
|
||||
@@ -819,14 +819,7 @@ public abstract class AbstractDataAbilities {
|
||||
chainEntryIndex = 0;
|
||||
chainDelayRemaining = -1;
|
||||
|
||||
// Check if first entry has a delay
|
||||
ChainedAbilityEntry firstEntry = chain.getEntries().get(0);
|
||||
int delay = firstEntry.getDelayTicks();
|
||||
if (delay > 0) {
|
||||
chainDelayRemaining = delay;
|
||||
return true;
|
||||
}
|
||||
|
||||
// AFTER semantics: no delay before first entry (delay applies after each entry completes)
|
||||
return startChainEntry(target);
|
||||
}
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC
|
||||
|
||||
// ── Pending: chain editing ────────────────────────────────────────────────
|
||||
private ChainedAbility pendingChain = null;
|
||||
private int pendingChainSlotIdx = -1;
|
||||
|
||||
// ── Pending: inline chain-entry editing ──────────────────────────────────
|
||||
private boolean editingChainEntry = false;
|
||||
@@ -233,17 +234,22 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC
|
||||
// Check if selected slot is editable
|
||||
boolean selectedIsBuiltIn = false;
|
||||
boolean selectedIsChainEntry = selectedEntryIndex >= 0;
|
||||
if (selectedSlotIndex >= 0 && selectedSlotIndex < npcSlots.size() && !selectedIsChainEntry) {
|
||||
boolean selectedIsRefChainEntry = false;
|
||||
if (selectedSlotIndex >= 0 && selectedSlotIndex < npcSlots.size()) {
|
||||
AbilityAction sel = npcSlots.get(selectedSlotIndex);
|
||||
if (!sel.isChain()) {
|
||||
if (!selectedIsChainEntry && !sel.isChain()) {
|
||||
Ability a = sel.getAbility();
|
||||
if (a != null && a.isBuiltIn()) selectedIsBuiltIn = true;
|
||||
}
|
||||
// Sub-entries of reference chains are not directly editable from the NPC list
|
||||
if (selectedIsChainEntry && sel.isChainReference()) {
|
||||
selectedIsRefChainEntry = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Right side buttons: Edit and Up/Down carrots with Save button
|
||||
addButton(new GuiNpcButton(BTN_EDIT, guiLeft + 210, y + 145, 55, 20, "gui.edit"));
|
||||
getButton(BTN_EDIT).setEnabled(selectedSlotIndex >= 0 && !selectedIsBuiltIn);
|
||||
getButton(BTN_EDIT).setEnabled(selectedSlotIndex >= 0 && !selectedIsBuiltIn && !selectedIsRefChainEntry);
|
||||
|
||||
// Up/Down carrot buttons
|
||||
addButton(new GuiNpcButton(BTN_MOVE_UP, guiLeft + 270, y + 145, 20, 20, "<"));
|
||||
@@ -354,6 +360,7 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC
|
||||
ChainedAbility chain = slot.getInlineChain();
|
||||
if (chain != null) {
|
||||
pendingChain = chain;
|
||||
pendingChainSlotIdx = selectedSlotIndex;
|
||||
setSubGui(new SubGuiChainedAbilityConfig(chain, this, true, npcSlots));
|
||||
}
|
||||
}
|
||||
@@ -484,6 +491,7 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC
|
||||
newChain.setId(UUID.randomUUID().toString());
|
||||
newChain.setName("NewChain");
|
||||
pendingChain = newChain;
|
||||
pendingChainSlotIdx = -1;
|
||||
setSubGui(new SubGuiChainedAbilityConfig(newChain, this, true, npcSlots));
|
||||
return;
|
||||
}
|
||||
@@ -837,8 +845,10 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC
|
||||
@Override
|
||||
public void customScrollDoubleClicked(String selection, GuiCustomScroll scroll) {
|
||||
if (scroll == npcAbilitiesScroll && selectedSlotIndex >= 0 && selectedSlotIndex < npcSlots.size()) {
|
||||
// Double-click mirrors Edit button logic
|
||||
buttonEvent(new GuiNpcButton(BTN_EDIT, 0, 0, 0, 0, ""));
|
||||
GuiNpcButton editBtn = getButton(BTN_EDIT);
|
||||
if (editBtn != null && editBtn.enabled) {
|
||||
buttonEvent(new GuiNpcButton(BTN_EDIT, 0, 0, 0, 0, ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -918,22 +928,17 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC
|
||||
|
||||
private void handleChainConfigClosed() {
|
||||
if (pendingChain != null) {
|
||||
boolean found = false;
|
||||
for (int i = 0; i < npcSlots.size(); i++) {
|
||||
AbilityAction slot = npcSlots.get(i);
|
||||
if (slot.isInlineChain() && slot.getInlineChain() == pendingChain) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (pendingChainSlotIdx < 0) {
|
||||
// New chain — add to NPC slots
|
||||
npcSlots.add(AbilityAction.inlineChain(pendingChain));
|
||||
selectedSlotIndex = npcSlots.size() - 1;
|
||||
selectedEntryIndex = -1;
|
||||
selectedAbilityIndex = selectedSlotIndex;
|
||||
if (npcAbilitiesScroll != null) npcAbilitiesScroll.resetScroll();
|
||||
}
|
||||
// Existing slot (pendingChainSlotIdx >= 0): already updated in-place, nothing to add
|
||||
pendingChain = null;
|
||||
pendingChainSlotIdx = -1;
|
||||
}
|
||||
updateNpcAbilitiesList();
|
||||
save();
|
||||
@@ -953,6 +958,7 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC
|
||||
ChainedAbility chain = slot.getInlineChain();
|
||||
if (chain != null) {
|
||||
pendingChain = chain;
|
||||
pendingChainSlotIdx = selectedSlotIndex;
|
||||
setSubGui(new SubGuiChainedAbilityConfig(chain, this, true, npcSlots));
|
||||
}
|
||||
updateNpcAbilitiesList();
|
||||
@@ -962,6 +968,7 @@ public class GuiNPCAbilities extends GuiNPCInterface2 implements IScrollData, IC
|
||||
ChainedAbility chain = slot.getChainedAbility();
|
||||
if (chain != null) {
|
||||
pendingChain = chain;
|
||||
pendingChainSlotIdx = selectedSlotIndex;
|
||||
setSubGui(new SubGuiChainedAbilityConfig(chain, this, true, npcSlots));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,14 @@ package noppes.npcs.client.gui.advanced;
|
||||
import kamkeel.npcs.controllers.AbilityController;
|
||||
import kamkeel.npcs.controllers.data.ability.Ability;
|
||||
import kamkeel.npcs.controllers.data.ability.AbilityAction;
|
||||
import kamkeel.npcs.controllers.data.ability.AbilityVariant;
|
||||
import kamkeel.npcs.controllers.data.ability.ChainedAbility;
|
||||
import kamkeel.npcs.controllers.data.ability.ChainedAbilityEntry;
|
||||
import kamkeel.npcs.controllers.data.ability.Condition;
|
||||
import kamkeel.npcs.controllers.data.ability.IChainedAbilityFieldProvider;
|
||||
import kamkeel.npcs.controllers.data.ability.UserType;
|
||||
import kamkeel.npcs.network.PacketClient;
|
||||
import kamkeel.npcs.network.packets.request.ability.CustomAbilitySavePacket;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.StatCollector;
|
||||
@@ -79,6 +82,7 @@ public class SubGuiChainedAbilityConfig extends SubGuiInterface implements IText
|
||||
private final ChainedAbility chain;
|
||||
private final IChainedAbilityConfigCallback callback;
|
||||
private final boolean npcContext;
|
||||
private final boolean readOnlyEntries;
|
||||
private final List<AbilityAction> npcSlots;
|
||||
private int activeTab = TAB_GENERAL;
|
||||
|
||||
@@ -94,6 +98,8 @@ public class SubGuiChainedAbilityConfig extends SubGuiInterface implements IText
|
||||
|
||||
// Entry editing
|
||||
private int editingEntryIndex = -1;
|
||||
private String pendingTypeId;
|
||||
private boolean editingParentAbility = false;
|
||||
|
||||
// Condition editing
|
||||
private int editingConditionIndex = -1;
|
||||
@@ -105,14 +111,20 @@ public class SubGuiChainedAbilityConfig extends SubGuiInterface implements IText
|
||||
private final List<Integer> consumedSlotIndices = new ArrayList<>();
|
||||
|
||||
public SubGuiChainedAbilityConfig(ChainedAbility chain, IChainedAbilityConfigCallback callback) {
|
||||
this(chain, callback, false, null);
|
||||
this(chain, callback, false, null, false);
|
||||
}
|
||||
|
||||
public SubGuiChainedAbilityConfig(ChainedAbility chain, IChainedAbilityConfigCallback callback,
|
||||
boolean npcContext, List<AbilityAction> npcSlots) {
|
||||
this(chain, callback, npcContext, npcSlots, false);
|
||||
}
|
||||
|
||||
public SubGuiChainedAbilityConfig(ChainedAbility chain, IChainedAbilityConfigCallback callback,
|
||||
boolean npcContext, List<AbilityAction> npcSlots, boolean readOnlyEntries) {
|
||||
this.chain = chain;
|
||||
this.callback = callback;
|
||||
this.npcContext = npcContext;
|
||||
this.readOnlyEntries = readOnlyEntries;
|
||||
this.npcSlots = npcSlots;
|
||||
this.entries = new ArrayList<>(chain.getEntries());
|
||||
this.conditions = new ArrayList<>(chain.getConditions());
|
||||
@@ -129,6 +141,11 @@ public class SubGuiChainedAbilityConfig extends SubGuiInterface implements IText
|
||||
|
||||
fieldDefs.add(FieldDef.stringField("gui.name", chain::getName, chain::setName).tab("General"));
|
||||
fieldDefs.add(FieldDef.stringField("gui.displayName", chain::getRawDisplayName, chain::setDisplayName).tab("General"));
|
||||
// Computed "Valid For" label (derived from child abilities)
|
||||
fieldDefs.add(FieldDef.labelField("ability.validFor", () -> {
|
||||
UserType ut = computeAllowedBy();
|
||||
return StatCollector.translateToLocal("ability.validFor") + ": \u00A7e" + StatCollector.translateToLocal("ability.userType." + ut.name());
|
||||
}).tab("General"));
|
||||
fieldDefs.add(FieldDef.boolField("gui.enabled", chain::isEnabled, chain::setEnabled).tab("General"));
|
||||
fieldDefs.add(FieldDef.intField("ability.weight", chain::getWeight, chain::setWeight).range(1, 100).tab("General"));
|
||||
fieldDefs.add(FieldDef.boolField("ability.windUpAll", chain::isWindUpAll, chain::setWindUpAll).tab("General"));
|
||||
@@ -140,12 +157,6 @@ public class SubGuiChainedAbilityConfig extends SubGuiInterface implements IText
|
||||
FieldDef.floatField("ability.maxRange", chain::getMaxRange, chain::setMaxRange).range(0, 64)
|
||||
).tab("Target"));
|
||||
|
||||
// Computed "Valid For" label (derived from child abilities)
|
||||
fieldDefs.add(FieldDef.labelField("ability.validFor", () -> {
|
||||
UserType ut = computeAllowedBy();
|
||||
return StatCollector.translateToLocal("ability.validFor") + ": \u00A7e" + StatCollector.translateToLocal("ability.userType." + ut.name());
|
||||
}).tab("Target"));
|
||||
|
||||
// External field providers (e.g., DBC Addon injecting an "Icon" tab)
|
||||
if (AbilityController.Instance != null) {
|
||||
for (IChainedAbilityFieldProvider provider : AbilityController.Instance.getChainedFieldProviders()) {
|
||||
@@ -307,34 +318,46 @@ public class SubGuiChainedAbilityConfig extends SubGuiInterface implements IText
|
||||
btnLabel = "\u00A7e> " + (resolved != null ? resolved.getDisplayName() : refName);
|
||||
}
|
||||
}
|
||||
sw.addButton(new GuiNpcButton(ENTRY_BASE + i * ENTRY_STRIDE, L_LABEL_X + 15, y, 140, 20, btnLabel));
|
||||
|
||||
// Delay label + field
|
||||
sw.addLabel(new GuiNpcLabel(labelCounter++, "ability.delay", L_LABEL_X + 160, y + 5, 0xAAAAAA));
|
||||
GuiNpcTextField delayField = new GuiNpcTextField(ENTRY_BASE + i * ENTRY_STRIDE + 1, this, fontRendererObj,
|
||||
L_LABEL_X + 195, y, 40, 20, String.valueOf(entry.getDelayTicks()));
|
||||
delayField.setIntegersOnly();
|
||||
delayField.setMinMaxDefault(0, 6000, 0);
|
||||
sw.addTextField(delayField);
|
||||
|
||||
// Up button
|
||||
if (i > 0) {
|
||||
sw.addButton(new GuiNpcButton(ENTRY_BASE + i * ENTRY_STRIDE + 2, L_LABEL_X + 240, y, 20, 20, "\u2191"));
|
||||
GuiNpcButton entryBtn = new GuiNpcButton(ENTRY_BASE + i * ENTRY_STRIDE, L_LABEL_X + 15, y, 140, 20, btnLabel);
|
||||
if (readOnlyEntries) {
|
||||
entryBtn.setEnabled(false);
|
||||
}
|
||||
sw.addButton(entryBtn);
|
||||
|
||||
// Down button
|
||||
if (i < entries.size() - 1) {
|
||||
sw.addButton(new GuiNpcButton(ENTRY_BASE + i * ENTRY_STRIDE + 3, L_LABEL_X + 263, y, 20, 20, "\u2193"));
|
||||
if (!readOnlyEntries) {
|
||||
// Delay label + field
|
||||
sw.addLabel(new GuiNpcLabel(labelCounter++, "ability.delay", L_LABEL_X + 160, y + 5, 0xAAAAAA));
|
||||
GuiNpcTextField delayField = new GuiNpcTextField(ENTRY_BASE + i * ENTRY_STRIDE + 1, this, fontRendererObj,
|
||||
L_LABEL_X + 195, y, 40, 20, String.valueOf(entry.getDelayTicks()));
|
||||
delayField.setIntegersOnly();
|
||||
delayField.setMinMaxDefault(0, 6000, 0);
|
||||
sw.addTextField(delayField);
|
||||
|
||||
// Up button
|
||||
if (i > 0) {
|
||||
sw.addButton(new GuiNpcButton(ENTRY_BASE + i * ENTRY_STRIDE + 2, L_LABEL_X + 240, y, 20, 20, "\u2191"));
|
||||
}
|
||||
|
||||
// Down button
|
||||
if (i < entries.size() - 1) {
|
||||
sw.addButton(new GuiNpcButton(ENTRY_BASE + i * ENTRY_STRIDE + 3, L_LABEL_X + 263, y, 20, 20, "\u2193"));
|
||||
}
|
||||
|
||||
// Delete button
|
||||
sw.addButton(new GuiNpcButton(ENTRY_BASE + i * ENTRY_STRIDE + 4, L_LABEL_X + 288, y, 20, 20, "X"));
|
||||
} else {
|
||||
// Read-only: show delay as label only
|
||||
int delay = entry.getDelayTicks();
|
||||
if (delay > 0) {
|
||||
sw.addLabel(new GuiNpcLabel(labelCounter++, delay + "t", L_LABEL_X + 165, y + 5, 0x888888));
|
||||
}
|
||||
}
|
||||
|
||||
// Delete button
|
||||
sw.addButton(new GuiNpcButton(ENTRY_BASE + i * ENTRY_STRIDE + 4, L_LABEL_X + 288, y, 20, 20, "X"));
|
||||
|
||||
y += ROW_H;
|
||||
}
|
||||
|
||||
// Add entry button
|
||||
if (entries.size() < MAX_ENTRIES) {
|
||||
// Add entry button (hidden in read-only mode)
|
||||
if (!readOnlyEntries && entries.size() < MAX_ENTRIES) {
|
||||
sw.addButton(new GuiNpcButton(BTN_ADD_ENTRY, L_LABEL_X, y, 80, 20, "gui.add"));
|
||||
y += ROW_H;
|
||||
}
|
||||
@@ -512,11 +535,11 @@ public class SubGuiChainedAbilityConfig extends SubGuiInterface implements IText
|
||||
if (entryIndex < 0 || entryIndex >= entries.size()) return false;
|
||||
|
||||
switch (action) {
|
||||
case 0: // Entry name button — reference: select ability; inline: edit config
|
||||
case 0: // Entry name button — reference: clone/modify dialog; inline: edit config
|
||||
ChainedAbilityEntry clickedEntry = entries.get(entryIndex);
|
||||
if (clickedEntry.isReference()) {
|
||||
editingEntryIndex = entryIndex;
|
||||
setSubGui(new SubGuiAbilitySelect());
|
||||
setSubGui(new SubGuiAbilityEditMode());
|
||||
} else if (clickedEntry.isInline() && clickedEntry.getInlineAbility() != null) {
|
||||
editingEntryIndex = entryIndex;
|
||||
setSubGui(new SubGuiAbilityConfig(clickedEntry.getInlineAbility(), this));
|
||||
@@ -626,13 +649,24 @@ public class SubGuiChainedAbilityConfig extends SubGuiInterface implements IText
|
||||
initGui();
|
||||
return;
|
||||
}
|
||||
if (subgui instanceof SubGuiAbilityVariantSelect) {
|
||||
handleVariantSelectClosed((SubGuiAbilityVariantSelect) subgui);
|
||||
if (!hasSubGui()) initGui();
|
||||
return;
|
||||
}
|
||||
if (subgui instanceof SubGuiAbilityTypeSelect) {
|
||||
handleTypeSelectClosed((SubGuiAbilityTypeSelect) subgui);
|
||||
if (!hasSubGui()) initGui();
|
||||
return;
|
||||
}
|
||||
if (subgui instanceof SubGuiAbilityEditMode) {
|
||||
handleEditModeClosed((SubGuiAbilityEditMode) subgui);
|
||||
if (!hasSubGui()) initGui();
|
||||
return;
|
||||
}
|
||||
if (subgui instanceof SubGuiAbilityConfig) {
|
||||
editingEntryIndex = -1;
|
||||
editingParentAbility = false;
|
||||
initGui();
|
||||
return;
|
||||
}
|
||||
@@ -687,8 +721,17 @@ public class SubGuiChainedAbilityConfig extends SubGuiInterface implements IText
|
||||
private void handleTypeSelectClosed(SubGuiAbilityTypeSelect gui) {
|
||||
String typeId = gui.getSelectedTypeId();
|
||||
if (typeId != null) {
|
||||
List<AbilityVariant> variants = AbilityController.Instance.getVariantsForType(typeId);
|
||||
if (variants.size() > 1) {
|
||||
pendingTypeId = typeId;
|
||||
setSubGui(new SubGuiAbilityVariantSelect(variants));
|
||||
return;
|
||||
}
|
||||
Ability newAbility = AbilityController.Instance.create(typeId);
|
||||
if (newAbility != null) {
|
||||
if (variants.size() == 1) {
|
||||
variants.get(0).apply(newAbility);
|
||||
}
|
||||
newAbility.setId(java.util.UUID.randomUUID().toString());
|
||||
entries.add(ChainedAbilityEntry.inline(newAbility, 0));
|
||||
editingEntryIndex = entries.size() - 1;
|
||||
@@ -697,6 +740,53 @@ public class SubGuiChainedAbilityConfig extends SubGuiInterface implements IText
|
||||
}
|
||||
}
|
||||
|
||||
private void handleVariantSelectClosed(SubGuiAbilityVariantSelect gui) {
|
||||
int idx = gui.getSelectedIndex();
|
||||
if (idx >= 0 && pendingTypeId != null) {
|
||||
Ability newAbility = AbilityController.Instance.create(pendingTypeId);
|
||||
if (newAbility != null) {
|
||||
gui.getVariants().get(idx).apply(newAbility);
|
||||
newAbility.setId(java.util.UUID.randomUUID().toString());
|
||||
entries.add(ChainedAbilityEntry.inline(newAbility, 0));
|
||||
editingEntryIndex = entries.size() - 1;
|
||||
pendingTypeId = null;
|
||||
setSubGui(new SubGuiAbilityConfig(newAbility, this));
|
||||
return;
|
||||
}
|
||||
}
|
||||
pendingTypeId = null;
|
||||
}
|
||||
|
||||
private void handleEditModeClosed(SubGuiAbilityEditMode gui) {
|
||||
int mode = gui.getResult();
|
||||
if (mode < 0 || editingEntryIndex < 0 || editingEntryIndex >= entries.size()) {
|
||||
editingEntryIndex = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
ChainedAbilityEntry entry = entries.get(editingEntryIndex);
|
||||
|
||||
if (mode == SubGuiAbilityEditMode.MODE_CLONE_MODIFY) {
|
||||
if (entry.convertToInline()) {
|
||||
Ability a = entry.getInlineAbility();
|
||||
if (a != null) {
|
||||
a.setId(java.util.UUID.randomUUID().toString());
|
||||
setSubGui(new SubGuiAbilityConfig(a, this));
|
||||
return;
|
||||
}
|
||||
}
|
||||
editingEntryIndex = -1;
|
||||
} else if (mode == SubGuiAbilityEditMode.MODE_MODIFY_PARENT) {
|
||||
Ability resolved = entry.resolve();
|
||||
if (resolved != null) {
|
||||
editingParentAbility = true;
|
||||
setSubGui(resolved.createConfigGui(this));
|
||||
return;
|
||||
}
|
||||
editingEntryIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
private void handleConditionEditClosed(SubGuiConditionEdit gui) {
|
||||
Condition result = gui.getResult();
|
||||
if (result != null && editingConditionIndex >= 0) {
|
||||
@@ -715,6 +805,12 @@ public class SubGuiChainedAbilityConfig extends SubGuiInterface implements IText
|
||||
|
||||
@Override
|
||||
public void onAbilitySaved(Ability ability) {
|
||||
if (editingParentAbility) {
|
||||
// Persist the global parent ability to the server
|
||||
PacketClient.sendClient(new CustomAbilitySavePacket(ability.writeNBT()));
|
||||
editingParentAbility = false;
|
||||
return;
|
||||
}
|
||||
// Inline ability mutated in-place; entry already holds the reference
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user