From 56f09e87a17cacb83108a8a800efb45468563bed Mon Sep 17 00:00:00 2001 From: StartForKiller Date: Sat, 3 Jun 2023 15:16:24 -0400 Subject: [PATCH] Fix ore dropping and implement subfields --- .../java/emu/grasscutter/data/GameData.java | 7 ++ .../emu/grasscutter/data/ResourceLoader.java | 33 +++++++++ .../data/server/DropSubfieldMapping.java | 10 +++ .../data/server/DropTableExcelConfigData.java | 24 ++++++ .../data/server/SubfieldMapping.java | 15 ++++ .../game/ability/AbilityLocalIdGenerator.java | 4 +- .../grasscutter/game/entity/GameEntity.java | 74 ++++++++++++++++++- .../emu/grasscutter/scripts/ScriptLib.java | 10 +++ 8 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 src/main/java/emu/grasscutter/data/server/DropSubfieldMapping.java create mode 100644 src/main/java/emu/grasscutter/data/server/DropTableExcelConfigData.java create mode 100644 src/main/java/emu/grasscutter/data/server/SubfieldMapping.java diff --git a/src/main/java/emu/grasscutter/data/GameData.java b/src/main/java/emu/grasscutter/data/GameData.java index 3e83a13f1..fd91b091c 100644 --- a/src/main/java/emu/grasscutter/data/GameData.java +++ b/src/main/java/emu/grasscutter/data/GameData.java @@ -37,8 +37,11 @@ import emu.grasscutter.data.excels.world.WeatherData; import emu.grasscutter.data.excels.world.WorldAreaData; import emu.grasscutter.data.excels.world.WorldLevelData; import emu.grasscutter.data.server.ActivityCondGroup; +import emu.grasscutter.data.server.DropSubfieldMapping; +import emu.grasscutter.data.server.DropTableExcelConfigData; import emu.grasscutter.data.server.GadgetMapping; import emu.grasscutter.data.server.MonsterMapping; +import emu.grasscutter.data.server.SubfieldMapping; import emu.grasscutter.game.dungeons.DungeonDropEntry; import emu.grasscutter.game.quest.QuestEncryptionKey; import emu.grasscutter.game.quest.RewindData; @@ -451,6 +454,10 @@ public final class GameData { private static final Int2ObjectMap gadgetMappingMap = new Int2ObjectOpenHashMap<>(); + @Getter private static final Int2ObjectMap subfieldMappingMap = new Int2ObjectOpenHashMap<>(); + @Getter private static final Int2ObjectMap dropSubfieldMappingMap = new Int2ObjectOpenHashMap<>(); + @Getter private static final Int2ObjectMap dropTableExcelConfigDataMap = new Int2ObjectOpenHashMap<>(); + @Getter private static final Int2ObjectMap monsterMappingMap = new Int2ObjectOpenHashMap<>(); diff --git a/src/main/java/emu/grasscutter/data/ResourceLoader.java b/src/main/java/emu/grasscutter/data/ResourceLoader.java index c967fe0a1..9caa7a613 100644 --- a/src/main/java/emu/grasscutter/data/ResourceLoader.java +++ b/src/main/java/emu/grasscutter/data/ResourceLoader.java @@ -116,6 +116,7 @@ public final class ResourceLoader { loadConfigLevelEntityData(); loadQuestShareConfig(); loadGadgetMappings(); + loadSubfieldMappings(); loadMonsterMappings(); loadActivityCondGroups(); loadGroupReplacements(); @@ -805,6 +806,38 @@ public final class ResourceLoader { } } + private static void loadSubfieldMappings() { + try { + val subfieldMap = GameData.getSubfieldMappingMap(); + try { + JsonUtils.loadToList(getResourcePath("Server/SubfieldMapping.json"), SubfieldMapping.class).forEach(entry -> subfieldMap.put(entry.getEntityId(), entry));; + } catch (IOException | NullPointerException ignored) {} + Grasscutter.getLogger().debug("Loaded {} subfield mappings.", subfieldMap.size()); + } catch (Exception e) { + Grasscutter.getLogger().error("Unable to load subfield mappings.", e); + } + + try { + val dropSubfieldMap = GameData.getDropSubfieldMappingMap(); + try { + JsonUtils.loadToList(getResourcePath("Server/DropSubfieldMapping.json"), DropSubfieldMapping.class).forEach(entry -> dropSubfieldMap.put(entry.getDropId(), entry));; + } catch (IOException | NullPointerException ignored) {} + Grasscutter.getLogger().debug("Loaded {} drop subfield mappings.", dropSubfieldMap.size()); + } catch (Exception e) { + Grasscutter.getLogger().error("Unable to load drop subfield mappings.", e); + } + + try { + val dropTableExcelConfigDataMap = GameData.getDropTableExcelConfigDataMap(); + try { + JsonUtils.loadToList(getResourcePath("Server/DropTableExcelConfigData.json"), DropTableExcelConfigData.class).forEach(entry -> dropTableExcelConfigDataMap.put(entry.getId(), entry));; + } catch (IOException | NullPointerException ignored) {} + Grasscutter.getLogger().debug("Loaded {} drop table configs.", dropTableExcelConfigDataMap.size()); + } catch (Exception e) { + Grasscutter.getLogger().error("Unable to load drop table config data.", e); + } + } + private static void loadMonsterMappings() { try { var monsterMap = GameData.getMonsterMappingMap(); diff --git a/src/main/java/emu/grasscutter/data/server/DropSubfieldMapping.java b/src/main/java/emu/grasscutter/data/server/DropSubfieldMapping.java new file mode 100644 index 000000000..6ecdc42ad --- /dev/null +++ b/src/main/java/emu/grasscutter/data/server/DropSubfieldMapping.java @@ -0,0 +1,10 @@ +package emu.grasscutter.data.server; + +import lombok.Data; + +@Data +public class DropSubfieldMapping { + private int dropId; + private int levelLimit; + private int itemId; +} diff --git a/src/main/java/emu/grasscutter/data/server/DropTableExcelConfigData.java b/src/main/java/emu/grasscutter/data/server/DropTableExcelConfigData.java new file mode 100644 index 000000000..b88017a5d --- /dev/null +++ b/src/main/java/emu/grasscutter/data/server/DropTableExcelConfigData.java @@ -0,0 +1,24 @@ +package emu.grasscutter.data.server; + +import lombok.Data; + +@Data +public class DropTableExcelConfigData { + private int id; + private int randomType; + private int dropLevel; + private DropVectorEntry[] dropVec; + private int nodeType; + private boolean fallToGround; + private int sourceType; + private int everydayLimit; + private int historyLimit; + private int activityLimit; + + @Data + public class DropVectorEntry { + private int itemId; + private String countRange; + private int weight; + } +} diff --git a/src/main/java/emu/grasscutter/data/server/SubfieldMapping.java b/src/main/java/emu/grasscutter/data/server/SubfieldMapping.java new file mode 100644 index 000000000..0a4afe1a4 --- /dev/null +++ b/src/main/java/emu/grasscutter/data/server/SubfieldMapping.java @@ -0,0 +1,15 @@ +package emu.grasscutter.data.server; + +import lombok.Data; + +@Data +public class SubfieldMapping { + private int entityId; + private SubfieldMappingEntry[] subfields; + + @Data + public class SubfieldMappingEntry { + private String subfieldName; + private int drop_id; + } +} diff --git a/src/main/java/emu/grasscutter/game/ability/AbilityLocalIdGenerator.java b/src/main/java/emu/grasscutter/game/ability/AbilityLocalIdGenerator.java index 216221a31..93218c8a8 100644 --- a/src/main/java/emu/grasscutter/game/ability/AbilityLocalIdGenerator.java +++ b/src/main/java/emu/grasscutter/game/ability/AbilityLocalIdGenerator.java @@ -42,9 +42,9 @@ public class AbilityLocalIdGenerator { if(actions[i].actions != null) this.initializeActionLocalIds(actions[i].actions, localIdToAction); else { - if (actions[i].successActions[i] != null) + if (actions[i].successActions != null) this.initializeActionLocalIds(actions[i].successActions, localIdToAction); //Need to check this specific order - if (actions[i].failActions[i] != null) + if (actions[i].failActions != null) this.initializeActionLocalIds(actions[i].failActions, localIdToAction); } } diff --git a/src/main/java/emu/grasscutter/game/entity/GameEntity.java b/src/main/java/emu/grasscutter/game/entity/GameEntity.java index b33840f71..476b87312 100644 --- a/src/main/java/emu/grasscutter/game/entity/GameEntity.java +++ b/src/main/java/emu/grasscutter/game/entity/GameEntity.java @@ -1,5 +1,6 @@ package emu.grasscutter.game.entity; +import emu.grasscutter.data.GameData; import emu.grasscutter.game.ability.*; import emu.grasscutter.game.player.Player; import emu.grasscutter.game.props.*; @@ -14,9 +15,10 @@ import emu.grasscutter.scripts.data.controller.EntityController; import emu.grasscutter.server.event.entity.*; import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; import it.unimi.dsi.fastutil.ints.*; -import java.util.*; import lombok.*; +import java.util.*; + public abstract class GameEntity { @Getter private final Scene scene; @Getter protected int id; @@ -226,6 +228,76 @@ public abstract class GameEntity { public void onRemoved() {} + private int[] parseCountRange(String range) { + var split = range.split(";"); + if(split.length == 1) return new int[] {Integer.parseInt(split[0]), Integer.parseInt(split[0])}; + return new int[] {Integer.parseInt(split[0]), Integer.parseInt(split[1])}; + } + + public boolean dropSubfieldItem(int dropId) { + var drop = GameData.getDropSubfieldMappingMap().get(dropId); + if(drop == null) return false; + var dropTableEntry = GameData.getDropTableExcelConfigDataMap().get(drop.getItemId()); + if(dropTableEntry == null) return false; + + Int2ObjectMap itemsToDrop = new Int2ObjectOpenHashMap<>(); + switch (dropTableEntry.getRandomType()) { + case 0: //select one + { + int weightCount = 0; + for(var entry : dropTableEntry.getDropVec()) weightCount += entry.getWeight(); + + int randomValue = new Random().nextInt(weightCount); + + weightCount = 0; + for(var entry : dropTableEntry.getDropVec()) { + if(randomValue >= weightCount && randomValue < (weightCount + entry.getWeight())) { + var countRange = parseCountRange(entry.getCountRange()); + itemsToDrop.put(entry.getItemId(), Integer.valueOf((new Random().nextBoolean() ? countRange[0] : countRange[1]))); + } + } + } + break; + case 1: //Select various + { + for(var entry : dropTableEntry.getDropVec()) { + if(entry.getWeight() < new Random().nextInt(10000)) { + var countRange = parseCountRange(entry.getCountRange()); + itemsToDrop.put(entry.getItemId(), Integer.valueOf((new Random().nextBoolean() ? countRange[0] : countRange[1]))); + } + } + } + break; + } + + for (var entry : itemsToDrop.int2ObjectEntrySet()) { + var item = new EntityItem( + scene, + null, + GameData.getItemDataMap().get(entry.getIntKey()), + getPosition().nearby2d(1f).addY(0.5f), + entry.getValue(), + true); + + scene.addEntity(item); + } + + return true; + } + + public boolean dropSubfield(String subfieldName) { + var subfieldMapping = GameData.getSubfieldMappingMap().get(getEntityTypeId()); + if (subfieldMapping == null || subfieldMapping.getSubfields() == null) return false; + + for (var entry : subfieldMapping.getSubfields()) { + if (entry.getSubfieldName().compareTo(subfieldName) == 0) { + return dropSubfieldItem(entry.getDrop_id()); + } + } + + return false; + } + public void onTick(int sceneTime) { if (entityController != null) { entityController.onTimer(this, sceneTime); diff --git a/src/main/java/emu/grasscutter/scripts/ScriptLib.java b/src/main/java/emu/grasscutter/scripts/ScriptLib.java index 0a90b51e4..dd975f6a3 100644 --- a/src/main/java/emu/grasscutter/scripts/ScriptLib.java +++ b/src/main/java/emu/grasscutter/scripts/ScriptLib.java @@ -1599,6 +1599,16 @@ public class ScriptLib { return 0; } + public int DropSubfield(LuaTable table) { + String subfield_name = table.get("subfield_name").toString(); + var entity = getCurrentEntity(); + if(!entity.isPresent()) return -1; + + entity.get().dropSubfield(subfield_name); + + return -1; + } + public int[] GetGatherConfigIdList() { EntityGadget gadget = getCurrentEntityGadget();