package emu.grasscutter.data.excels; import java.util.Arrays; import java.util.List; import java.util.Objects; import com.google.gson.annotations.SerializedName; import emu.grasscutter.data.GameResource; import emu.grasscutter.data.ResourceType; import emu.grasscutter.data.common.ItemUseData; import emu.grasscutter.game.inventory.*; import emu.grasscutter.game.props.FightProperty; import emu.grasscutter.game.props.ItemUseOp; import emu.grasscutter.game.props.ItemUseTarget; import emu.grasscutter.game.props.ItemUseAction.ItemUseAction; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; import lombok.Getter; @ResourceType(name = {"MaterialExcelConfigData.json", "WeaponExcelConfigData.json", "ReliquaryExcelConfigData.json", "HomeWorldFurnitureExcelConfigData.json" }) @Getter public class ItemData extends GameResource { // Main @Getter(onMethod = @__(@Override)) private int id; private int stackLimit = 1; private int maxUseCount; private int rankLevel; private String effectName; private int rank; private int weight; private int gadgetId; private int[] destroyReturnMaterial; private int[] destroyReturnMaterialCount; // Enums private ItemType itemType = ItemType.ITEM_NONE; private MaterialType materialType = MaterialType.MATERIAL_NONE; private EquipType equipType = EquipType.EQUIP_NONE; private String effectType; private String destroyRule; // Food private String foodQuality; private int[] satiationParams; // Usable item private ItemUseTarget useTarget = ItemUseTarget.ITEM_USE_TARGET_NONE; private List itemUse; private List itemUseActions; private boolean useOnGain = false; // Relic private int mainPropDepotId; private int appendPropDepotId; private int appendPropNum; private int setId; private int[] addPropLevels; private int baseConvExp; private int maxLevel; // Weapon private int weaponPromoteId; private int weaponBaseExp; private int storyId; private int avatarPromoteId; private int awakenMaterial; private int[] awakenCosts; private int[] skillAffix; private WeaponProperty[] weaponProp; // Hash private long nameTextMapHash; // Furniture private int comfort; private List furnType; private List furnitureGadgetID; @SerializedName(value="roomSceneId", alternate={"BMEPAMCNABE", "DANFGGLKLNO", "JFDLJGDFIGL", "OHIANNAEEAK"}) private int roomSceneId; // Custom private transient IntSet addPropLevelSet; public WeaponProperty[] getWeaponProperties() { return this.weaponProp; } public boolean canAddRelicProp(int level) { return this.addPropLevelSet != null && this.addPropLevelSet.contains(level); } public boolean isEquip() { return this.itemType == ItemType.ITEM_RELIQUARY || this.itemType == ItemType.ITEM_WEAPON; } @Override public void onLoad() { if (this.itemType == ItemType.ITEM_RELIQUARY) { if (this.addPropLevels != null && this.addPropLevels.length > 0) { this.addPropLevelSet = new IntOpenHashSet(this.addPropLevels); } } else if (this.itemType == ItemType.ITEM_WEAPON) { this.equipType = EquipType.EQUIP_WEAPON; } else { this.equipType = EquipType.EQUIP_NONE; } if (this.weaponProp != null) { this.weaponProp = Arrays.stream(this.weaponProp).filter(prop -> prop.getPropType() != null).toArray(WeaponProperty[]::new); } if (this.getFurnType() != null) { this.furnType = this.furnType.stream().filter(x -> x > 0).toList(); } if (this.getFurnitureGadgetID() != null) { this.furnitureGadgetID = this.furnitureGadgetID.stream().filter(x -> x > 0).toList(); } // Prevent material type from being null this.materialType = this.materialType == null ? MaterialType.MATERIAL_NONE : this.materialType; if (this.itemUse != null && !this.itemUse.isEmpty()) { this.itemUseActions = this.itemUse.stream() .filter(x -> x.getUseOp() != ItemUseOp.ITEM_USE_NONE) .map(ItemUseAction::fromItemUseData) .filter(Objects::nonNull) .toList(); } } @Getter public static class WeaponProperty { private FightProperty propType; private float initValue; private String type; } }