Skip to content
4 changes: 4 additions & 0 deletions src/main/java/emu/grasscutter/data/GameData.java
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,10 @@ public final class GameData {
@Getter
private static final Int2ObjectMap<CombineData> combineDataMap = new Int2ObjectOpenHashMap<>();

@Getter
private static final Int2ObjectMap<CombineBonusData> combineBonusDataMap =
new Int2ObjectOpenHashMap<>();

@Getter
private static final Int2ObjectMap<CookBonusData> cookBonusDataMap =
new Int2ObjectOpenHashMap<>();
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/emu/grasscutter/data/excels/CombineBonusData.java
Original file line number Diff line number Diff line change
@@ -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"},
Comment thread
Phong940253 marked this conversation as resolved.
Outdated
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<Double> paramVec;

@Override
public int getId() {
return this.avatarId;
}
}
127 changes: 121 additions & 6 deletions src/main/java/emu/grasscutter/game/combine/CombineManger.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
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;
Expand All @@ -16,9 +18,12 @@
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.Map;
import java.util.List;

public class CombineManger extends BaseGameSystem {
Expand Down Expand Up @@ -53,7 +58,7 @@ public boolean unlockCombineDiagram(Player player, int combineId) {
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());
Expand Down Expand Up @@ -87,11 +92,121 @@ public CombineResult combineItem(Player player, int cid, int count) {
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<ItemParamData>());
result.setBack(new ArrayList<ItemParamData>());
result.setRandom(new ArrayList<ItemParamData>());

// add lucky items
if (luckyCount > 0) {
switch (combineBonusData.getBonusType()) {
Comment thread
Phong940253 marked this conversation as resolved.
Outdated
case "COMBINE_BONUS_DOUBLE" -> {
var combineExtra = new ItemParamData(combineData.getResultItemId(), luckyCount);
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<Integer, Integer> 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
Map<Integer, Integer> itemToRegion = Map.of(
104301, 1,
104304, 1,
104307, 1,
104310, 2,
104313, 2,
104316, 2,
104320, 3,
104323, 3,
104326, 3,
104329, 4,
104332, 4,
104335, 4
);
Comment thread
Phong940253 marked this conversation as resolved.
Outdated

// get list of material id with every region
HashMap<Integer, List<Integer>> 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<Integer> listIdRandom = regionToId.get(itemToRegion.get(itemId));
// remove material id from list
listIdRandom.remove(Integer.valueOf(itemId));

HashMap<Integer, Integer> 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;
}
Expand Down
43 changes: 7 additions & 36 deletions src/main/java/emu/grasscutter/game/combine/CombineResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,13 @@

import emu.grasscutter.data.common.ItemParamData;
import java.util.List;
import lombok.Getter;
import lombok.Setter;

Comment thread
Phong940253 marked this conversation as resolved.
public class CombineResult {
private List<ItemParamData> material;
private List<ItemParamData> result;
private List<ItemParamData> extra;
private List<ItemParamData> back;

public List<ItemParamData> getMaterial() {
return material;
}

public void setMaterial(List<ItemParamData> material) {
this.material = material;
}

public List<ItemParamData> getResult() {
return result;
}

public void setResult(List<ItemParamData> result) {
this.result = result;
}

public List<ItemParamData> getExtra() {
return extra;
}

public void setExtra(List<ItemParamData> extra) {
this.extra = extra;
}

public List<ItemParamData> getBack() {
return back;
}

public void setBack(List<ItemParamData> back) {
this.back = back;
}
@Getter @Setter private List<ItemParamData> material;
@Getter @Setter private List<ItemParamData> result;
@Getter @Setter private List<ItemParamData> extra;
@Getter @Setter private List<ItemParamData> back;
@Getter @Setter private List<ItemParamData> random;
Comment thread
Phong940253 marked this conversation as resolved.
Outdated
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ public void handle(GameSession session, byte[] header, byte[] payload) throws Ex
session
.getServer()
.getCombineSystem()
.combineItem(session.getPlayer(), req.getCombineId(), req.getCombineCount());
.combineItem(
session.getPlayer(),
req.getCombineId(),
req.getCombineCount(),
req.getAvatarGuid());

if (result == null) {
return;
Expand All @@ -36,7 +40,7 @@ public void handle(GameSession session, byte[] header, byte[] payload) throws Ex
toItemParamList(result.getResult()),
toItemParamList(result.getExtra()),
toItemParamList(result.getBack()),
toItemParamList(result.getBack())));
toItemParamList(result.getRandom())));
}

private List<ItemParamOuterClass.ItemParam> toItemParamList(List<ItemParamData> list) {
Expand Down