From a18b7e8a2a42b6ebfeff9219bb8b1f34f4dbe4c2 Mon Sep 17 00:00:00 2001 From: Melledy <121644117+Melledy@users.noreply.github.com> Date: Mon, 17 Nov 2025 03:11:12 -0800 Subject: [PATCH] Implement attributing locking when reforging --- .../data/resources/CharGemSlotControlDef.java | 13 +++--- .../emu/nebula/game/character/Character.java | 38 +++++++++++++-- .../java/emu/nebula/util/CustomIntArray.java | 46 +++++++++++++++++++ 3 files changed, 87 insertions(+), 10 deletions(-) create mode 100644 src/main/java/emu/nebula/util/CustomIntArray.java diff --git a/src/main/java/emu/nebula/data/resources/CharGemSlotControlDef.java b/src/main/java/emu/nebula/data/resources/CharGemSlotControlDef.java index 8eaf209..72fbad9 100644 --- a/src/main/java/emu/nebula/data/resources/CharGemSlotControlDef.java +++ b/src/main/java/emu/nebula/data/resources/CharGemSlotControlDef.java @@ -3,8 +3,8 @@ package emu.nebula.data.resources; import emu.nebula.data.BaseDef; import emu.nebula.data.GameData; import emu.nebula.data.ResourceType; +import emu.nebula.util.CustomIntArray; import emu.nebula.util.WeightedList; -import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; import lombok.Getter; @@ -35,9 +35,10 @@ public class CharGemSlotControlDef extends BaseDef { } public IntList generateAttributes() { - // Generate list of attributes - var list = new IntArrayList(); - + return this.generateAttributes(new CustomIntArray()); + } + + public IntList generateAttributes(CustomIntArray list) { // Add unique attributes if (this.UniqueAttrGroupId > 0) { var group = GameData.getCharGemAttrGroupDataTable().get(this.UniqueAttrGroupId); @@ -48,7 +49,7 @@ public class CharGemSlotControlDef extends BaseDef { list.add(attributeType.getRandomValue()); } - if (list.size() >= 4) { + if (list.size() >= this.MaxAlterNum) { return list; } } @@ -66,7 +67,7 @@ public class CharGemSlotControlDef extends BaseDef { } // Add up to 4 attributes - while (list.size() < 4) { + while (list.getValueCount() < this.MaxAlterNum) { var group = random.next(); var attributeType = group.getRandomAttributeType(list); list.add(attributeType.getRandomValue()); diff --git a/src/main/java/emu/nebula/game/character/Character.java b/src/main/java/emu/nebula/game/character/Character.java index ea49d40..6fd522d 100644 --- a/src/main/java/emu/nebula/game/character/Character.java +++ b/src/main/java/emu/nebula/game/character/Character.java @@ -32,7 +32,9 @@ import emu.nebula.proto.Public.UI32; import emu.nebula.proto.PublicStarTower.StarTowerChar; import emu.nebula.proto.PublicStarTower.StarTowerCharGem; import emu.nebula.util.Bitset; +import emu.nebula.util.CustomIntArray; import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import lombok.Getter; import us.hebi.quickbuf.RepeatedInt; @@ -558,6 +560,7 @@ public class Character implements GameDatabaseObject { return change; } + @SuppressWarnings("deprecation") public synchronized PlayerChangeInfo refreshGem(int slotId, int gemIndex, RepeatedInt lockedAttributes) { // Get gem from slot var gem = this.getGemFromSlot(slotId, gemIndex); @@ -572,20 +575,47 @@ public class Character implements GameDatabaseObject { return null; } - // Make sure the player has the materials to craft the emblem - if (!getPlayer().getInventory().hasItem(gemData.getRefreshCostTid(), gemControl.getRefreshCostQty())) { + // Get locked attributes + if (lockedAttributes.length() > gemControl.getLockableNum()) { return null; } + // Calculate the materials we need + var materials = new ItemParamMap(); + materials.add(gemData.getRefreshCostTid(), gemControl.getRefreshCostQty()); + materials.add(gemControl.getLockItemTid(), gemControl.getLockItemQty() * lockedAttributes.length()); + + // Make sure the player has the materials to craft the emblem + if (!getPlayer().getInventory().hasItems(materials)) { + return null; + } + + // Create base list of attributes + var list = new CustomIntArray(); + + // Add locked attributes to list + if (lockedAttributes.length() != 0) { + var locked = new IntOpenHashSet(); + lockedAttributes.forEach(locked::add); + + for (int i = 0; i < gem.getAttributes().length; i++) { + int attr = gem.getAttributes()[i]; + + if (locked.contains(attr)) { + list.add(i, attr); + } + } + } + // Generate attributes and create gem - var attributes = gemControl.generateAttributes(); + var attributes = gemControl.generateAttributes(list); gem.setNewAttributes(attributes); // Save to database this.save(); // Consume materials - var change = getPlayer().getInventory().removeItem(gemData.getRefreshCostTid(), gemControl.getRefreshCostQty()); + var change = getPlayer().getInventory().removeItems(materials); // Set change info extra info change.setExtraData(gem); diff --git a/src/main/java/emu/nebula/util/CustomIntArray.java b/src/main/java/emu/nebula/util/CustomIntArray.java new file mode 100644 index 0000000..cc318f3 --- /dev/null +++ b/src/main/java/emu/nebula/util/CustomIntArray.java @@ -0,0 +1,46 @@ +package emu.nebula.util; + +import it.unimi.dsi.fastutil.ints.IntArrayList; + +public class CustomIntArray extends IntArrayList { + private static final long serialVersionUID = -3887905394107667439L; + + public CustomIntArray() { + super(); + } + + public void add(int index, int value) { + while (index > this.size()) { + super.add(0); + } + + super.add(index, value); + } + + @Override + public boolean add(int value) { + for (int i = 0; i < this.size(); i++) { + if (this.getInt(i) == 0) { + this.set(i, value); + return true; + } + } + + return super.add(value); + } + + /** + * Returns the amount of non-zero values in this array + */ + public int getValueCount() { + int realSize = 0; + + for (int i = 0; i < super.size(); i++) { + if (this.getInt(i) != 0) { + realSize++; + } + } + + return realSize; + } +}