From ac49114c45ea439fc4510daeffcf03061e1cb83e Mon Sep 17 00:00:00 2001 From: Melledy <52122272+Melledy@users.noreply.github.com> Date: Thu, 16 Jun 2022 07:54:53 -0700 Subject: [PATCH] Add embryos for all skill depots for the main characters --- .../java/emu/grasscutter/data/GameData.java | 5 ++ .../java/emu/grasscutter/data/GameDepot.java | 13 ++++ .../emu/grasscutter/data/ResourceLoader.java | 56 +++++---------- .../data/excels/AvatarSkillDepotData.java | 12 ++++ .../data/excels/WorldAreaData.java | 32 +++++++++ .../grasscutter/game/props/ElementType.java | 22 ++++-- .../HandlerAvatarChangeElementTypeReq.java | 68 +++++++++++++++++++ .../PacketAvatarChangeElementTypeRsp.java | 24 +++++++ .../PacketAvatarSkillDepotChangeNotify.java | 26 +++++++ 9 files changed, 214 insertions(+), 44 deletions(-) create mode 100644 src/main/java/emu/grasscutter/data/excels/WorldAreaData.java create mode 100644 src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarChangeElementTypeReq.java create mode 100644 src/main/java/emu/grasscutter/server/packet/send/PacketAvatarChangeElementTypeRsp.java create mode 100644 src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillDepotChangeNotify.java diff --git a/src/main/java/emu/grasscutter/data/GameData.java b/src/main/java/emu/grasscutter/data/GameData.java index 8fc78cf81..fb3d10bff 100644 --- a/src/main/java/emu/grasscutter/data/GameData.java +++ b/src/main/java/emu/grasscutter/data/GameData.java @@ -77,6 +77,7 @@ public class GameData { private static final ArrayList codexReliquaryArrayList = new ArrayList<>(); private static final Int2ObjectMap fetterCharacterCardDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap rewardDataMap = new Int2ObjectOpenHashMap<>(); + private static final Int2ObjectMap worldAreaDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap worldLevelDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap dailyDungeonDataMap = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap dungeonDataMap = new Int2ObjectOpenHashMap<>(); @@ -319,6 +320,10 @@ public class GameData { public static ArrayList getcodexReliquaryArrayList(){return codexReliquaryArrayList;} + public static Int2ObjectMap getWorldAreaDataMap() { + return worldAreaDataMap; + } + public static Int2ObjectMap getWorldLevelDataMap() { return worldLevelDataMap; } diff --git a/src/main/java/emu/grasscutter/data/GameDepot.java b/src/main/java/emu/grasscutter/data/GameDepot.java index 851e6c464..d28b38960 100644 --- a/src/main/java/emu/grasscutter/data/GameDepot.java +++ b/src/main/java/emu/grasscutter/data/GameDepot.java @@ -1,12 +1,16 @@ package emu.grasscutter.data; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.danilopianini.util.FlexibleQuadTree; import org.danilopianini.util.SpatialIndex; import emu.grasscutter.Grasscutter; +import emu.grasscutter.data.ResourceLoader.AvatarConfig; +import emu.grasscutter.data.ResourceLoader.AvatarConfigAbility; import emu.grasscutter.data.excels.ReliquaryAffixData; import emu.grasscutter.data.excels.ReliquaryMainPropData; import emu.grasscutter.game.world.SpawnDataEntry; @@ -19,6 +23,7 @@ public class GameDepot { private static Int2ObjectMap> relicMainPropDepot = new Int2ObjectOpenHashMap<>(); private static Int2ObjectMap> relicAffixDepot = new Int2ObjectOpenHashMap<>(); + private static Map playerAbilities = new HashMap<>(); private static Int2ObjectMap> spawnLists = new Int2ObjectOpenHashMap<>(); public static void load() { @@ -61,4 +66,12 @@ public class GameDepot { public static SpatialIndex getSpawnListById(int sceneId) { return getSpawnLists().computeIfAbsent(sceneId, id -> new FlexibleQuadTree<>()); } + + public static Map getPlayerAbilities() { + return playerAbilities; + } + + public static void setPlayerAbilities(Map playerAbilities) { + GameDepot.playerAbilities = playerAbilities; + } } diff --git a/src/main/java/emu/grasscutter/data/ResourceLoader.java b/src/main/java/emu/grasscutter/data/ResourceLoader.java index b0892b28f..785ef4780 100644 --- a/src/main/java/emu/grasscutter/data/ResourceLoader.java +++ b/src/main/java/emu/grasscutter/data/ResourceLoader.java @@ -66,37 +66,6 @@ public class ResourceLoader { loadQuests(); // Load scene points - must be done AFTER resources are loaded loadScenePoints(); - // Custom - TODO move this somewhere else - try { - GameData.getAvatarSkillDepotDataMap().get(504).setAbilities( - new AbilityEmbryoEntry( - "", - new String[] { - "Avatar_PlayerBoy_ExtraAttack_Wind", - "Avatar_Player_UziExplode_Mix", - "Avatar_Player_UziExplode", - "Avatar_Player_UziExplode_Strike_01", - "Avatar_Player_UziExplode_Strike_02", - "Avatar_Player_WindBreathe", - "Avatar_Player_WindBreathe_CameraController" - } - )); - GameData.getAvatarSkillDepotDataMap().get(704).setAbilities( - new AbilityEmbryoEntry( - "", - new String[] { - "Avatar_PlayerGirl_ExtraAttack_Wind", - "Avatar_Player_UziExplode_Mix", - "Avatar_Player_UziExplode", - "Avatar_Player_UziExplode_Strike_01", - "Avatar_Player_UziExplode_Strike_02", - "Avatar_Player_WindBreathe", - "Avatar_Player_WindBreathe_CameraController" - } - )); - } catch (Exception e) { - Grasscutter.getLogger().error("Error loading abilities", e); - } } public static void loadResources() { @@ -244,6 +213,16 @@ public class ResourceLoader { AbilityEmbryoEntry al = new AbilityEmbryoEntry(avatarName, config.abilities.stream().map(Object::toString).toArray(size -> new String[s])); embryoList.add(al); } + + File playerElementsFile = new File(Utils.toFilePath(RESOURCE("BinOutput/AbilityGroup/AbilityGroup_Other_PlayerElementAbility.json"))); + + if (playerElementsFile.exists()) { + try (FileReader fileReader = new FileReader(playerElementsFile)) { + GameDepot.setPlayerAbilities(Grasscutter.getGsonFactory().fromJson(fileReader, new TypeToken>(){}.getType())); + } catch (Exception e) { + e.printStackTrace(); + } + } } if (embryoList == null || embryoList.isEmpty()) { @@ -417,14 +396,15 @@ public class ResourceLoader { // BinOutput configs - private static class AvatarConfig { + public static class AvatarConfig { + @SerializedName(value="abilities", alternate={"targetAbilities"}) public ArrayList abilities; - - private static class AvatarConfigAbility { - public String abilityName; - public String toString() { - return abilityName; - } + } + + public static class AvatarConfigAbility { + public String abilityName; + public String toString() { + return abilityName; } } diff --git a/src/main/java/emu/grasscutter/data/excels/AvatarSkillDepotData.java b/src/main/java/emu/grasscutter/data/excels/AvatarSkillDepotData.java index 152ec31bd..4dd5c7e25 100644 --- a/src/main/java/emu/grasscutter/data/excels/AvatarSkillDepotData.java +++ b/src/main/java/emu/grasscutter/data/excels/AvatarSkillDepotData.java @@ -3,7 +3,10 @@ package emu.grasscutter.data.excels; import java.util.List; import emu.grasscutter.data.GameData; +import emu.grasscutter.data.GameDepot; import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceLoader.AvatarConfig; +import emu.grasscutter.data.ResourceLoader.AvatarConfigAbility; import emu.grasscutter.data.ResourceType; import emu.grasscutter.data.ResourceType.LoadPriority; import emu.grasscutter.data.binout.AbilityEmbryoEntry; @@ -95,12 +98,21 @@ public class AvatarSkillDepotData extends GameResource { @Override public void onLoad() { + // Set energy skill data this.energySkillData = GameData.getAvatarSkillDataMap().get(this.energySkill); if (getEnergySkillData() != null) { this.elementType = getEnergySkillData().getCostElemType(); } else { this.elementType = ElementType.None; } + // Set embryo abilities (if player skill depot) + if (getSkillDepotAbilityGroup() != null && getSkillDepotAbilityGroup().length() > 0) { + AvatarConfig config = GameDepot.getPlayerAbilities().get(getSkillDepotAbilityGroup()); + + if (config != null) { + this.setAbilities(new AbilityEmbryoEntry(getSkillDepotAbilityGroup(), config.abilities.stream().map(Object::toString).toArray(String[]::new))); + } + } } public static class InherentProudSkillOpens { diff --git a/src/main/java/emu/grasscutter/data/excels/WorldAreaData.java b/src/main/java/emu/grasscutter/data/excels/WorldAreaData.java new file mode 100644 index 000000000..edd80e805 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/excels/WorldAreaData.java @@ -0,0 +1,32 @@ +package emu.grasscutter.data.excels; + +import emu.grasscutter.data.GameResource; +import emu.grasscutter.data.ResourceType; +import emu.grasscutter.game.props.ElementType; + +@ResourceType(name = "WorldAreaConfigData.json") +public class WorldAreaData extends GameResource { + private int ID; + private int AreaID1; + private int AreaID2; + private int SceneID; + private ElementType elementType; + + @Override + public int getId() { + return (this.AreaID2 << 16) + this.AreaID1; + } + + public int getSceneID() { + return this.SceneID; + } + + public ElementType getElementType() { + return this.elementType; + } + + @Override + public void onLoad() { + + } +} diff --git a/src/main/java/emu/grasscutter/game/props/ElementType.java b/src/main/java/emu/grasscutter/game/props/ElementType.java index 12a30f6fc..80b6cf968 100644 --- a/src/main/java/emu/grasscutter/game/props/ElementType.java +++ b/src/main/java/emu/grasscutter/game/props/ElementType.java @@ -10,14 +10,14 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; public enum ElementType { None (0, FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY), - Fire (1, FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY, 10101, "TeamResonance_Fire_Lv2"), - Water (2, FightProperty.FIGHT_PROP_CUR_WATER_ENERGY, FightProperty.FIGHT_PROP_MAX_WATER_ENERGY, 10201, "TeamResonance_Water_Lv2"), + Fire (1, FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY, 10101, "TeamResonance_Fire_Lv2", 2), + Water (2, FightProperty.FIGHT_PROP_CUR_WATER_ENERGY, FightProperty.FIGHT_PROP_MAX_WATER_ENERGY, 10201, "TeamResonance_Water_Lv2", 3), Grass (3, FightProperty.FIGHT_PROP_CUR_GRASS_ENERGY, FightProperty.FIGHT_PROP_MAX_GRASS_ENERGY), - Electric (4, FightProperty.FIGHT_PROP_CUR_ELEC_ENERGY, FightProperty.FIGHT_PROP_MAX_ELEC_ENERGY, 10401, "TeamResonance_Electric_Lv2"), - Ice (5, FightProperty.FIGHT_PROP_CUR_ICE_ENERGY, FightProperty.FIGHT_PROP_MAX_ICE_ENERGY, 10601, "TeamResonance_Ice_Lv2"), + Electric (4, FightProperty.FIGHT_PROP_CUR_ELEC_ENERGY, FightProperty.FIGHT_PROP_MAX_ELEC_ENERGY, 10401, "TeamResonance_Electric_Lv2", 7), + Ice (5, FightProperty.FIGHT_PROP_CUR_ICE_ENERGY, FightProperty.FIGHT_PROP_MAX_ICE_ENERGY, 10601, "TeamResonance_Ice_Lv2", 5), Frozen (6, FightProperty.FIGHT_PROP_CUR_ICE_ENERGY, FightProperty.FIGHT_PROP_MAX_ICE_ENERGY), - Wind (7, FightProperty.FIGHT_PROP_CUR_WIND_ENERGY, FightProperty.FIGHT_PROP_MAX_WIND_ENERGY, 10301, "TeamResonance_Wind_Lv2"), - Rock (8, FightProperty.FIGHT_PROP_CUR_ROCK_ENERGY, FightProperty.FIGHT_PROP_MAX_ROCK_ENERGY, 10701, "TeamResonance_Rock_Lv2"), + Wind (7, FightProperty.FIGHT_PROP_CUR_WIND_ENERGY, FightProperty.FIGHT_PROP_MAX_WIND_ENERGY, 10301, "TeamResonance_Wind_Lv2", 4), + Rock (8, FightProperty.FIGHT_PROP_CUR_ROCK_ENERGY, FightProperty.FIGHT_PROP_MAX_ROCK_ENERGY, 10701, "TeamResonance_Rock_Lv2", 6), AntiFire (9, FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY), Default (255, FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY, 10801, "TeamResonance_AllDifferent"); @@ -25,6 +25,7 @@ public enum ElementType { private final int teamResonanceId; private final FightProperty curEnergyProp; private final FightProperty maxEnergyProp; + private int depotValue; private final int configHash; private static final Int2ObjectMap map = new Int2ObjectOpenHashMap<>(); private static final Map stringMap = new HashMap<>(); @@ -51,6 +52,11 @@ public enum ElementType { this.configHash = 0; } } + + private ElementType(int value, FightProperty curEnergyProp, FightProperty maxEnergyProp, int teamResonanceId, String configName, int depotValue) { + this(value, curEnergyProp, maxEnergyProp, teamResonanceId, configName); + this.depotValue = depotValue; + } public int getValue() { return value; @@ -64,6 +70,10 @@ public enum ElementType { return maxEnergyProp; } + public int getDepotValue() { + return depotValue; + } + public int getTeamResonanceId() { return teamResonanceId; } diff --git a/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarChangeElementTypeReq.java b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarChangeElementTypeReq.java new file mode 100644 index 000000000..4c6e4085a --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/recv/HandlerAvatarChangeElementTypeReq.java @@ -0,0 +1,68 @@ +package emu.grasscutter.server.packet.recv; + +import emu.grasscutter.GameConstants; +import emu.grasscutter.data.GameData; +import emu.grasscutter.data.excels.AvatarSkillDepotData; +import emu.grasscutter.data.excels.WorldAreaData; +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.game.entity.EntityAvatar; +import emu.grasscutter.net.packet.Opcodes; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarChangeElementTypeReqOuterClass.AvatarChangeElementTypeReq; +import emu.grasscutter.net.proto.RetcodeOuterClass.Retcode; +import emu.grasscutter.net.packet.PacketHandler; +import emu.grasscutter.server.game.GameSession; +import emu.grasscutter.server.packet.send.PacketAbilityChangeNotify; +import emu.grasscutter.server.packet.send.PacketAvatarChangeElementTypeRsp; +import emu.grasscutter.server.packet.send.PacketAvatarFightPropNotify; +import emu.grasscutter.server.packet.send.PacketAvatarSkillDepotChangeNotify; + +@Opcodes(PacketOpcodes.AvatarChangeElementTypeReq) +public class HandlerAvatarChangeElementTypeReq extends PacketHandler { + + @Override + public void handle(GameSession session, byte[] header, byte[] payload) throws Exception { + AvatarChangeElementTypeReq req = AvatarChangeElementTypeReq.parseFrom(payload); + + WorldAreaData area = GameData.getWorldAreaDataMap().get(req.getAreaId()); + + if (area == null || area.getElementType() == null || area.getElementType().getDepotValue() <= 0) { + session.send(new PacketAvatarChangeElementTypeRsp(Retcode.RET_SVR_ERROR_VALUE)); + return; + } + + // Get current avatar, should be one of the main characters + EntityAvatar mainCharacterEntity = session.getPlayer().getTeamManager().getCurrentAvatarEntity(); + + int intialSkillDepotId = 0; + if (mainCharacterEntity.getAvatar().getAvatarId() == GameConstants.MAIN_CHARACTER_MALE) { + intialSkillDepotId = 500; + } else if (mainCharacterEntity.getAvatar().getAvatarId() == GameConstants.MAIN_CHARACTER_FEMALE) { + intialSkillDepotId = 700; + } else { + session.send(new PacketAvatarChangeElementTypeRsp(Retcode.RET_SVR_ERROR_VALUE)); + return; + } + intialSkillDepotId += area.getElementType().getDepotValue(); + + // Sanity checks for skill depots + Avatar mainCharacter = mainCharacterEntity.getAvatar(); + AvatarSkillDepotData skillDepot = GameData.getAvatarSkillDepotDataMap().get(intialSkillDepotId); + if (skillDepot == null || skillDepot.getId() == mainCharacter.getSkillDepotId()) { + session.send(new PacketAvatarChangeElementTypeRsp(Retcode.RET_SVR_ERROR_VALUE)); + return; + } + + // Success + session.send(new PacketAvatarChangeElementTypeRsp()); + + // Set skill depot + mainCharacter.setSkillDepotData(skillDepot); + + // Ability change packet + session.send(new PacketAvatarSkillDepotChangeNotify(mainCharacter)); + session.send(new PacketAbilityChangeNotify(mainCharacterEntity)); + session.send(new PacketAvatarFightPropNotify(mainCharacter)); + } + +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarChangeElementTypeRsp.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarChangeElementTypeRsp.java new file mode 100644 index 000000000..fe65f7905 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarChangeElementTypeRsp.java @@ -0,0 +1,24 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarChangeElementTypeRspOuterClass.AvatarChangeElementTypeRsp; + +public class PacketAvatarChangeElementTypeRsp extends BasePacket { + + public PacketAvatarChangeElementTypeRsp() { + super(PacketOpcodes.AvatarChangeElementTypeRsp); + } + + public PacketAvatarChangeElementTypeRsp(int retcode) { + super(PacketOpcodes.AvatarChangeElementTypeRsp); + + if (retcode > 0) { + AvatarChangeElementTypeRsp proto = AvatarChangeElementTypeRsp.newBuilder() + .setRetcode(retcode) + .build(); + + this.setData(proto); + } + } +} diff --git a/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillDepotChangeNotify.java b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillDepotChangeNotify.java new file mode 100644 index 000000000..609e137f9 --- /dev/null +++ b/src/main/java/emu/grasscutter/server/packet/send/PacketAvatarSkillDepotChangeNotify.java @@ -0,0 +1,26 @@ +package emu.grasscutter.server.packet.send; + +import emu.grasscutter.game.avatar.Avatar; +import emu.grasscutter.net.packet.BasePacket; +import emu.grasscutter.net.packet.PacketOpcodes; +import emu.grasscutter.net.proto.AvatarSkillDepotChangeNotifyOuterClass.AvatarSkillDepotChangeNotify; + +public class PacketAvatarSkillDepotChangeNotify extends BasePacket { + + public PacketAvatarSkillDepotChangeNotify(Avatar avatar) { + super(PacketOpcodes.AvatarSkillDepotChangeNotify); + + AvatarSkillDepotChangeNotify proto = AvatarSkillDepotChangeNotify.newBuilder() + .setAvatarGuid(avatar.getGuid()) + .setEntityId(avatar.getEntityId()) + .setSkillDepotId(avatar.getSkillDepotId()) + .setCoreProudSkillLevel(avatar.getCoreProudSkillLevel()) + .addAllTalentIdList(avatar.getTalentIdList()) + .addAllProudSkillList(avatar.getProudSkillList()) + .putAllSkillLevelMap(avatar.getSkillLevelMap()) + .putAllProudSkillExtraLevelMap(avatar.getProudSkillBonusMap()) + .build(); + + this.setData(proto); + } +}