Skip to content
Snippets Groups Projects
Commit 13a7f086 authored by GanyusLeftHorn's avatar GanyusLeftHorn Committed by Melledy
Browse files

Add character's specialty food.

parent d95a30a1
Branches
Tags
No related merge requests found
...@@ -99,6 +99,7 @@ public class GameData { ...@@ -99,6 +99,7 @@ public class GameData {
private static final Int2ObjectMap<BattlePassMissionData> battlePassMissionDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap<BattlePassMissionData> battlePassMissionDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<BattlePassRewardData> battlePassRewardDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap<BattlePassRewardData> battlePassRewardDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<CookRecipeData> cookRecipeDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap<CookRecipeData> cookRecipeDataMap = new Int2ObjectOpenHashMap<>();
private static final Int2ObjectMap<CookBonusData> cookBonusDataMap = new Int2ObjectOpenHashMap<>();
@Getter private static final Int2ObjectMap<ActivityData> activityDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap<ActivityData> activityDataMap = new Int2ObjectOpenHashMap<>();
@Getter private static final Int2ObjectMap<ActivityWatcherData> activityWatcherDataMap = new Int2ObjectOpenHashMap<>(); @Getter private static final Int2ObjectMap<ActivityWatcherData> activityWatcherDataMap = new Int2ObjectOpenHashMap<>();
...@@ -441,4 +442,8 @@ public class GameData { ...@@ -441,4 +442,8 @@ public class GameData {
public static Int2ObjectMap<CookRecipeData> getCookRecipeDataMap() { public static Int2ObjectMap<CookRecipeData> getCookRecipeDataMap() {
return cookRecipeDataMap; return cookRecipeDataMap;
} }
public static Int2ObjectMap<CookBonusData> getCookBonusDataMap() {
return cookBonusDataMap;
}
} }
package emu.grasscutter.data.excels;
import java.util.List;
import emu.grasscutter.data.GameResource;
import emu.grasscutter.data.ResourceType;
import emu.grasscutter.data.ResourceType.LoadPriority;
import emu.grasscutter.data.common.ItemParamData;
@ResourceType(name = {"CookBonusExcelConfigData.json"}, loadPriority = LoadPriority.LOW)
public class CookBonusData extends GameResource {
private int avatarId;
private int recipeId;
private int[] paramVec;
private int[] complexParamVec;
@Override
public int getId() {
return this.avatarId;
}
public int getAvatarId() {
return avatarId;
}
public int getRecipeId() {
return recipeId;
}
public int[] getParamVec() {
return paramVec;
}
public int[] getComplexParamVec() {
return complexParamVec;
}
public int getReplacementItemId() {
return this.paramVec[0];
}
@Override
public void onLoad() {
}
}
...@@ -20,6 +20,7 @@ import emu.grasscutter.server.packet.send.PacketCookDataNotify; ...@@ -20,6 +20,7 @@ import emu.grasscutter.server.packet.send.PacketCookDataNotify;
import emu.grasscutter.server.packet.send.PacketCookRecipeDataNotify; import emu.grasscutter.server.packet.send.PacketCookRecipeDataNotify;
import emu.grasscutter.server.packet.send.PacketPlayerCookArgsRsp; import emu.grasscutter.server.packet.send.PacketPlayerCookArgsRsp;
import emu.grasscutter.server.packet.send.PacketPlayerCookRsp; import emu.grasscutter.server.packet.send.PacketPlayerCookRsp;
import io.netty.util.internal.ThreadLocalRandom;
public class CookingManager { public class CookingManager {
private static final int MANUAL_PERFECT_COOK_QUALITY = 3; private static final int MANUAL_PERFECT_COOK_QUALITY = 3;
...@@ -46,33 +47,44 @@ public class CookingManager { ...@@ -46,33 +47,44 @@ public class CookingManager {
* Unlocking for recipies. * Unlocking for recipies.
********************/ ********************/
public synchronized boolean unlockRecipe(GameItem recipeItem) { public synchronized boolean unlockRecipe(GameItem recipeItem) {
// Make sure this is actually a cooking recipe. // Make sure this is actually a cooking recipe.
if (!recipeItem.getItemData().getItemUse().get(0).getUseOp().equals("ITEM_USE_UNLOCK_COOK_RECIPE")) { if (!recipeItem.getItemData().getItemUse().get(0).getUseOp().equals("ITEM_USE_UNLOCK_COOK_RECIPE")) {
return false; return false;
} }
// Determine the recipe we should unlock. // Determine the recipe we should unlock.
int recipeId = Integer.parseInt(recipeItem.getItemData().getItemUse().get(0).getUseParam().get(0)); int recipeId = Integer.parseInt(recipeItem.getItemData().getItemUse().get(0).getUseParam().get(0));
// Remove the item from the player's inventory. // Remove the item from the player's inventory.
// We need to do this here, before sending CookRecipeDataNotify, or the the UI won't correctly update. // We need to do this here, before sending CookRecipeDataNotify, or the the UI won't correctly update.
player.getInventory().removeItem(recipeItem, 1); player.getInventory().removeItem(recipeItem, 1);
// Tell the client that this blueprint is now unlocked and add the unlocked item to the player. // Tell the client that this blueprint is now unlocked and add the unlocked item to the player.
this.player.getUnlockedRecipies().put(recipeId, 0); this.player.getUnlockedRecipies().put(recipeId, 0);
this.player.sendPacket(new PacketCookRecipeDataNotify(recipeId)); this.player.sendPacket(new PacketCookRecipeDataNotify(recipeId));
return true; return true;
} }
/******************** /********************
* Perform cooking. * Perform cooking.
********************/ ********************/
private double getSpecialtyChance(ItemData cookedItem) {
// Chances taken from the Wiki.
return switch (cookedItem.getRankLevel()) {
case 1 -> 0.25;
case 2 -> 0.2;
case 3 -> 0.15;
default -> 0;
};
}
public void handlePlayerCookReq(PlayerCookReq req) { public void handlePlayerCookReq(PlayerCookReq req) {
// Get info from the request. // Get info from the request.
int recipeId = req.getRecipeId(); int recipeId = req.getRecipeId();
int quality = req.getQteQuality(); int quality = req.getQteQuality();
int count = req.getCookCount(); int count = req.getCookCount();
int avatar = req.getAssistAvatar();
// Get recipe data. // Get recipe data.
var recipeData = GameData.getCookRecipeDataMap().get(recipeId); var recipeData = GameData.getCookRecipeDataMap().get(recipeId);
...@@ -85,12 +97,12 @@ public class CookingManager { ...@@ -85,12 +97,12 @@ public class CookingManager {
int proficiency = this.player.getUnlockedRecipies().getOrDefault(recipeId, 0); int proficiency = this.player.getUnlockedRecipies().getOrDefault(recipeId, 0);
// Try consuming materials. // Try consuming materials.
boolean success = player.getInventory().payItems(recipeData.getInputVec().toArray(new ItemParamData[0]), count, ActionReason.Cook); boolean success = player.getInventory().payItems(recipeData.getInputVec().toArray(new ItemParamData[0]), count, ActionReason.Cook);
if (!success) { if (!success) {
this.player.sendPacket(new PacketPlayerCookRsp(Retcode.RET_FAIL)); //ToDo: Probably the wrong return code. this.player.sendPacket(new PacketPlayerCookRsp(Retcode.RET_FAIL));
} }
// Obtain results. // Get result item information.
int qualityIndex = int qualityIndex =
quality == 0 quality == 0
? 2 ? 2
...@@ -99,8 +111,34 @@ public class CookingManager { ...@@ -99,8 +111,34 @@ public class CookingManager {
ItemParamData resultParam = recipeData.getQualityOutputVec().get(qualityIndex); ItemParamData resultParam = recipeData.getQualityOutputVec().get(qualityIndex);
ItemData resultItemData = GameData.getItemDataMap().get(resultParam.getItemId()); ItemData resultItemData = GameData.getItemDataMap().get(resultParam.getItemId());
GameItem cookResult = new GameItem(resultItemData, resultParam.getCount() * count); // Handle character's specialties.
this.player.getInventory().addItem(cookResult); int specialtyCount = 0;
double specialtyChance = this.getSpecialtyChance(resultItemData);
var bonusData = GameData.getCookBonusDataMap().get(avatar);
if (bonusData != null && recipeId == bonusData.getRecipeId()) {
// Roll for specialy replacements.
for (int i = 0; i < count; i++) {
if (ThreadLocalRandom.current().nextDouble() <= specialtyChance) {
specialtyCount++;
}
}
}
// Obtain results.
List<GameItem> cookResults = new ArrayList<>();
int normalCount = count - specialtyCount;
GameItem cookResultNormal = new GameItem(resultItemData, resultParam.getCount() * normalCount);
cookResults.add(cookResultNormal);
this.player.getInventory().addItem(cookResultNormal);
if (specialtyCount > 0) {
ItemData specialtyItemData = GameData.getItemDataMap().get(bonusData.getReplacementItemId());
GameItem cookResultSpecialty = new GameItem(specialtyItemData, resultParam.getCount() * specialtyCount);
cookResults.add(cookResultSpecialty);
this.player.getInventory().addItem(cookResultSpecialty);
}
// Increase player proficiency, if this was a manual perfect cook. // Increase player proficiency, if this was a manual perfect cook.
if (quality == MANUAL_PERFECT_COOK_QUALITY) { if (quality == MANUAL_PERFECT_COOK_QUALITY) {
...@@ -109,10 +147,9 @@ public class CookingManager { ...@@ -109,10 +147,9 @@ public class CookingManager {
} }
// Send response. // Send response.
this.player.sendPacket(new PacketPlayerCookRsp(cookResult, quality, count, recipeId, proficiency)); this.player.sendPacket(new PacketPlayerCookRsp(cookResults, quality, count, recipeId, proficiency));
} }
/******************** /********************
* Cooking arguments. * Cooking arguments.
********************/ ********************/
......
package emu.grasscutter.server.packet.send; package emu.grasscutter.server.packet.send;
import java.util.List;
import emu.grasscutter.game.inventory.GameItem; import emu.grasscutter.game.inventory.GameItem;
import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
...@@ -19,23 +21,25 @@ public class PacketPlayerCookRsp extends BasePacket { ...@@ -19,23 +21,25 @@ public class PacketPlayerCookRsp extends BasePacket {
this.setData(proto); this.setData(proto);
} }
public PacketPlayerCookRsp(GameItem output, int quality, int count, int recipeId, int proficiency) { public PacketPlayerCookRsp(List<GameItem> output, int quality, int count, int recipeId, int proficiency) {
super(PacketOpcodes.PlayerCookRsp); super(PacketOpcodes.PlayerCookRsp);
PlayerCookRsp proto = PlayerCookRsp.newBuilder() PlayerCookRsp.Builder proto = PlayerCookRsp.newBuilder()
.setRecipeData( .setRecipeData(
CookRecipeData.newBuilder() CookRecipeData.newBuilder()
.setRecipeId(recipeId) .setRecipeId(recipeId)
.setProficiency(proficiency) .setProficiency(proficiency)
) )
.setQteQuality(quality) .setQteQuality(quality)
.addItemList( .setCookCount(count);
for (var item : output) {
proto.addItemList(
ItemParam.newBuilder() ItemParam.newBuilder()
.setItemId(output.getItemId()) .setItemId(item.getItemId())
.setCount(output.getCount()) .setCount(item.getCount())
) );
.setCookCount(count) }
.build();
this.setData(proto); this.setData(proto);
} }
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment