From 37c08183323b6937e3a882f7cc76e4f88fa307fc Mon Sep 17 00:00:00 2001 From: Phong940253 Date: Sun, 6 Aug 2023 22:52:09 +0700 Subject: [PATCH] implement feature character bonuses for combine & fix num result combine the wrong --- .../java/emu/grasscutter/data/GameData.java | 4 + .../data/excels/CombineBonusData.java | 23 ++++ .../game/combine/CombineManger.java | 129 +++++++++++++++++- .../game/combine/CombineResult.java | 43 +----- .../server/packet/recv/HandlerCombineReq.java | 8 +- 5 files changed, 163 insertions(+), 44 deletions(-) create mode 100644 src/main/java/emu/grasscutter/data/excels/CombineBonusData.java diff --git a/src/main/java/emu/grasscutter/data/GameData.java b/src/main/java/emu/grasscutter/data/GameData.java index 3b99f1f26..8c4cd3aaf 100644 --- a/src/main/java/emu/grasscutter/data/GameData.java +++ b/src/main/java/emu/grasscutter/data/GameData.java @@ -207,6 +207,10 @@ public final class GameData { @Getter private static final Int2ObjectMap combineDataMap = new Int2ObjectOpenHashMap<>(); + @Getter + private static final Int2ObjectMap combineBonusDataMap = + new Int2ObjectOpenHashMap<>(); + @Getter private static final Int2ObjectMap cookBonusDataMap = new Int2ObjectOpenHashMap<>(); diff --git a/src/main/java/emu/grasscutter/data/excels/CombineBonusData.java b/src/main/java/emu/grasscutter/data/excels/CombineBonusData.java new file mode 100644 index 000000000..743fd6791 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/CombineBonusData.java @@ -0,0 +1,23 @@ +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.data.ResourceType.LoadPriority; +import java.util.List; +import lombok.Getter; +import lombok.Setter; + +@ResourceType( + name = {"CombineBonusExcelConfigData.json"}, + loadPriority = LoadPriority.LOW) +public class CombineBonusData extends GameResource { + @Getter @Setter private int avatarId; + @Getter @Setter private int combineType; + @Getter @Setter private String bonusType; + @Getter @Setter private List paramVec; + + @Override + public int getId() { + return this.avatarId; + } +} diff --git a/src/main/java/emu/grasscutter/game/combine/CombineManger.java b/src/main/java/emu/grasscutter/game/combine/CombineManger.java index 090c82024..c42f93d16 100644 --- a/src/main/java/emu/grasscutter/game/combine/CombineManger.java +++ b/src/main/java/emu/grasscutter/game/combine/CombineManger.java @@ -4,7 +4,9 @@ import emu.grasscutter.Grasscutter; import emu.grasscutter.data.DataLoader; import emu.grasscutter.data.GameData; import emu.grasscutter.data.common.ItemParamData; +import emu.grasscutter.data.excels.CombineBonusData; import emu.grasscutter.data.excels.CombineData; +import emu.grasscutter.game.avatar.Avatar; import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.player.Player; import emu.grasscutter.game.props.ActionReason; @@ -16,9 +18,11 @@ import emu.grasscutter.server.packet.send.PacketCombineFormulaDataNotify; import emu.grasscutter.server.packet.send.PacketCombineRsp; import emu.grasscutter.server.packet.send.PacketReliquaryDecomposeRsp; import emu.grasscutter.utils.Utils; +import io.netty.util.internal.ThreadLocalRandom; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; public class CombineManger extends BaseGameSystem { @@ -53,7 +57,7 @@ public class CombineManger extends BaseGameSystem { return true; } - public CombineResult combineItem(Player player, int cid, int count) { + public CombineResult combineItem(Player player, int cid, int count, long avatarGuid) { // check config exist if (!GameData.getCombineDataMap().containsKey(cid)) { player.getWorld().getHost().sendPacket(new PacketCombineRsp()); @@ -87,11 +91,124 @@ public class CombineManger extends BaseGameSystem { result.setMaterial(List.of()); result.setResult( List.of( - new ItemParamData( - combineData.getResultItemId(), combineData.getResultItemCount() * count))); - // TODO lucky characters - result.setExtra(List.of()); - result.setBack(List.of()); + new ItemParamData(combineData.getResultItemId(), combineData.getResultItemCount()))); + // lucky characters + int luckyCount = 0; + Avatar avatar = player.getAvatars().getAvatarByGuid(avatarGuid); + CombineBonusData combineBonusData = GameData.getCombineBonusDataMap().get(avatar.getAvatarId()); + if (combineBonusData != null + && combineData.getCombineType() == combineBonusData.getCombineType()) { + double luckyChange = combineBonusData.getParamVec().get(0); + for (int i = 0; i < count; i++) { + if (ThreadLocalRandom.current().nextDouble() <= luckyChange) { + luckyCount++; + } + } + } + + result.setExtra(new ArrayList()); + result.setBack(new ArrayList()); + result.setRandom(new ArrayList()); + + // add lucky items + if (luckyCount > 0) { + switch (combineBonusData.getBonusType()) { + case "COMBINE_BONUS_DOUBLE" -> { + var combineExtra = new ItemParamData(combineData.getResultItemId(), luckyCount * 2); + player.getInventory().addItem(combineExtra); + result.getExtra().add(combineExtra); + } + case "COMBINE_BONUS_REFUND" -> { + if (combineData.getMaterialItems().size() == 1) { + var combineBack = + new ItemParamData(combineData.getMaterialItems().get(0).getItemId(), luckyCount); + player.getInventory().addItem(combineBack); + result.getBack().add(combineBack); + } else { + HashMap mapIdCount = new HashMap<>(); + for (int i = 0; i < luckyCount; i++) { + var randomId = + combineData + .getMaterialItems() + .get( + ThreadLocalRandom.current() + .nextInt(combineData.getMaterialItems().size())) + .getItemId(); + mapIdCount.put(randomId, mapIdCount.getOrDefault(randomId, 0) + 1); + } + + for (var entry : mapIdCount.entrySet()) { + var combineBack = new ItemParamData(entry.getKey(), entry.getValue()); + player.getInventory().addItem(combineBack); + result.getBack().add(combineBack); + } + } + } + case "COMBINE_BONUS_REFUND_RANDOM" -> { + // for yae miko, "Has a 25% chance to get 1 regional Character Talent Material (base + // material excluded) when crafting. The rarity is that of the base material." from wiki + // map of material id to region id + HashMap itemToRegion = + new HashMap<>() { + { + put(104301, 1); + put(104304, 1); + put(104307, 1); + put(104310, 2); + put(104313, 2); + put(104316, 2); + put(104320, 3); + put(104323, 3); + put(104326, 3); + put(104329, 4); + put(104332, 4); + put(104335, 4); + } + }; + + // get list of material id with every region + HashMap> regionToId = new HashMap<>(); + for (var entry : itemToRegion.entrySet()) { + regionToId.putIfAbsent(entry.getValue(), new ArrayList<>()); + regionToId.get(entry.getValue()).add(entry.getKey()); + } + + // check material id in itemToRegion + var itemId = combineData.getMaterialItems().get(0).getItemId(); + int rank = 0; // rank of material + if (itemToRegion.get(itemId) != null) rank = 1; + if (itemToRegion.get(itemId - 1) != null) { + rank = 2; + itemId -= 1; + } + + if (rank >= 1) { // if material is regional + // get list of material id with same region + List listIdRandom = regionToId.get(itemToRegion.get(itemId)); + // remove material id from list + listIdRandom.remove(Integer.valueOf(itemId)); + + HashMap mapIdCount = new HashMap<>(); + // pick random material from list with luckyCount + for (int i = 0; i < luckyCount; i++) { + var randomId = + listIdRandom.get(ThreadLocalRandom.current().nextInt(listIdRandom.size())); + mapIdCount.put(randomId, mapIdCount.getOrDefault(randomId, 0) + 1); + } + + // add to random list + for (var entry : mapIdCount.entrySet()) { + // if rank 2, add 1 to material id + var combineRandom = + new ItemParamData( + (rank == 2) ? entry.getKey() + 1 : entry.getKey(), entry.getValue()); + player.getInventory().addItem(combineRandom); + result.getRandom().add(combineRandom); + } + } + } + } + } return result; } diff --git a/src/main/java/emu/grasscutter/game/combine/CombineResult.java b/src/main/java/emu/grasscutter/game/combine/CombineResult.java index df8ace74b..8c59c37ce 100644 --- a/src/main/java/emu/grasscutter/game/combine/CombineResult.java +++ b/src/main/java/emu/grasscutter/game/combine/CombineResult.java @@ -2,42 +2,13 @@ package emu.grasscutter.game.combine; import emu.grasscutter.data.common.ItemParamData; import java.util.List; +import lombok.Getter; +import lombok.Setter; public class CombineResult { - private List material; - private List result; - private List extra; - private List back; - - public List getMaterial() { - return material; - } - - public void setMaterial(List material) { - this.material = material; - } - - public List getResult() { - return result; - } - - public void setResult(List result) { - this.result = result; - } - - public List getExtra() { - return extra; - } - - public void setExtra(List extra) { - this.extra = extra; - } - - public List getBack() { - return back; - } - - public void setBack(List back) { - this.back = back; - } + @Getter @Setter private List material; + @Getter @Setter private List result; + @Getter @Setter private List extra; + @Getter @Setter private List back; + @Getter @Setter private List random; } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombineReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombineReq.java index fa8bd96d3..dc0b889ed 100644 --- a/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombineReq.java +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerCombineReq.java @@ -23,7 +23,11 @@ public class HandlerCombineReq extends PacketHandler { session .getServer() .getCombineSystem() - .combineItem(session.getPlayer(), req.getCombineId(), req.getCombineCount()); + .combineItem( + session.getPlayer(), + req.getCombineId(), + req.getCombineCount(), + req.getAvatarGuid()); if (result == null) { return; @@ -36,7 +40,7 @@ public class HandlerCombineReq extends PacketHandler { toItemParamList(result.getResult()), toItemParamList(result.getExtra()), toItemParamList(result.getBack()), - toItemParamList(result.getBack()))); + toItemParamList(result.getRandom()))); } private List toItemParamList(List list) {