mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-12-17 01:15:52 +01:00
Remove GiveAll, GiveArt, GiveChar commands
This commit is contained in:
@@ -1,184 +0,0 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.GameConstants;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.excels.AvatarData;
|
||||
import emu.grasscutter.data.excels.ItemData;
|
||||
import emu.grasscutter.game.avatar.Avatar;
|
||||
import emu.grasscutter.game.inventory.GameItem;
|
||||
import emu.grasscutter.game.inventory.ItemType;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(label = "giveall", usage = "giveall [amount]", aliases = {"givea"}, permission = "player.giveall", permissionTargeted = "player.giveall.others", threading = true, description = "commands.giveAll.description")
|
||||
public final class GiveAllCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
int amount = 99999;
|
||||
|
||||
switch (args.size()) {
|
||||
case 0:
|
||||
break;
|
||||
case 1: // [amount]
|
||||
try {
|
||||
amount = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.amount"));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default: // invalid
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.giveAll.usage"));
|
||||
return;
|
||||
}
|
||||
|
||||
this.giveAllItems(targetPlayer, amount);
|
||||
CommandHandler.sendMessage(sender, translate(targetPlayer, "commands.giveAll.success", targetPlayer.getNickname()));
|
||||
}
|
||||
|
||||
public void giveAllItems(Player player, int amount) {
|
||||
CommandHandler.sendMessage(player, translate(player, "commands.giveAll.started"));
|
||||
|
||||
for (AvatarData avatarData: GameData.getAvatarDataMap().values()) {
|
||||
//Exclude test avatar
|
||||
if (isTestAvatar(avatarData.getId())) continue;
|
||||
|
||||
Avatar avatar = new Avatar(avatarData);
|
||||
avatar.setLevel(90);
|
||||
avatar.setPromoteLevel(6);
|
||||
|
||||
// Add constellations.
|
||||
int talentBase = switch (avatar.getAvatarId()) {
|
||||
case 10000005 -> 70;
|
||||
case 10000006 -> 40;
|
||||
default -> (avatar.getAvatarId()-10000000)*10;
|
||||
};
|
||||
|
||||
for(int i = 1;i <= 6;++i){
|
||||
avatar.getTalentIdList().add(talentBase + i);
|
||||
}
|
||||
|
||||
// Handle skill depot for traveller.
|
||||
if (avatar.getAvatarId() == GameConstants.MAIN_CHARACTER_MALE) {
|
||||
avatar.setSkillDepotData(GameData.getAvatarSkillDepotDataMap().get(504));
|
||||
}
|
||||
else if(avatar.getAvatarId() == GameConstants.MAIN_CHARACTER_FEMALE) {
|
||||
avatar.setSkillDepotData(GameData.getAvatarSkillDepotDataMap().get(704));
|
||||
}
|
||||
|
||||
// This will handle stats and talents
|
||||
avatar.recalcStats();
|
||||
// Don't try to add each avatar to the current team
|
||||
player.addAvatar(avatar, false);
|
||||
}
|
||||
|
||||
//some test items
|
||||
List<GameItem> itemList = new ArrayList<>();
|
||||
for (ItemData itemdata: GameData.getItemDataMap().values()) {
|
||||
//Exclude test item
|
||||
if (isTestItem(itemdata.getId())) continue;
|
||||
|
||||
if (itemdata.isEquip()) {
|
||||
if (itemdata.getItemType() == ItemType.ITEM_WEAPON) {
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
GameItem item = new GameItem(itemdata);
|
||||
item.setLevel(90);
|
||||
item.setPromoteLevel(6);
|
||||
item.setRefinement(4);
|
||||
itemList.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
GameItem item = new GameItem(itemdata);
|
||||
item.setCount(amount);
|
||||
itemList.add(item);
|
||||
}
|
||||
}
|
||||
int packetNum = 10;
|
||||
int itemLength = itemList.size();
|
||||
int number = itemLength / packetNum;
|
||||
int remainder = itemLength % packetNum;
|
||||
int offset = 0;
|
||||
for (int i = 0; i < packetNum; ++i) {
|
||||
if (remainder > 0) {
|
||||
player.getInventory().addItems(itemList.subList(i * number + offset, (i + 1) * number + offset + 1));
|
||||
--remainder;
|
||||
++offset;
|
||||
}
|
||||
else {
|
||||
player.getInventory().addItems(itemList.subList(i * number + offset, (i + 1) * number + offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isTestAvatar(int avatarId) {
|
||||
return avatarId < 10000002 || avatarId >= 11000000;
|
||||
}
|
||||
|
||||
public boolean isTestItem(int itemId) {
|
||||
for (Range range: testItemRanges) {
|
||||
if (range.check(itemId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return testItemsList.contains(itemId);
|
||||
}
|
||||
|
||||
static class Range {
|
||||
private final int min, max;
|
||||
|
||||
public Range(int min, int max) {
|
||||
if(min > max){
|
||||
min ^= max;
|
||||
max ^= min;
|
||||
min ^= max;
|
||||
}
|
||||
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
public boolean check(int value) {
|
||||
return value >= this.min && value <= this.max;
|
||||
}
|
||||
}
|
||||
|
||||
private static final Range[] testItemRanges = new Range[] {
|
||||
new Range(106, 139),
|
||||
new Range(1000, 1099),
|
||||
new Range(2001, 3022),
|
||||
new Range(23300, 23340),
|
||||
new Range(23383, 23385),
|
||||
new Range(78310, 78554),
|
||||
new Range(99310, 99554),
|
||||
new Range(100001, 100187),
|
||||
new Range(100210, 100214),
|
||||
new Range(100303, 100398),
|
||||
new Range(100414, 100425),
|
||||
new Range(100454, 103008),
|
||||
new Range(109000, 109492),
|
||||
new Range(115001, 118004),
|
||||
new Range(141001, 141072),
|
||||
new Range(220050, 221016),
|
||||
};
|
||||
private static final Integer[] testItemsIds = new Integer[] {
|
||||
210, 211, 314, 315, 317, 1005, 1007, 1105, 1107, 1201, 1202,10366,
|
||||
101212, 11411, 11506, 11507, 11508, 12505, 12506, 12508, 12509, 13503,
|
||||
13506, 14411, 14503, 14505, 14508, 15504, 15505, 15506,
|
||||
20001, 10002, 10003, 10004, 10005, 10006, 10008,100231,100232,100431,
|
||||
101689,105001,105004, 106000,106001,108000,110000
|
||||
};
|
||||
|
||||
private static final Collection<Integer> testItemsList = Arrays.asList(testItemsIds);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,208 +0,0 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.excels.ItemData;
|
||||
import emu.grasscutter.game.inventory.GameItem;
|
||||
import emu.grasscutter.game.inventory.ItemType;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.ActionReason;
|
||||
import emu.grasscutter.game.inventory.EquipType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import static java.util.Map.entry;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(label = "giveart", usage = "giveart <artifactId> <mainPropId> [<appendPropId>[,<times>]]... [level]", aliases = {"gart"}, permission = "player.giveart", permissionTargeted = "player.giveart.others", description = "commands.giveArtifact.description")
|
||||
public final class GiveArtifactCommand implements CommandHandler {
|
||||
private static final Map<String, Map<EquipType, Integer>> mainPropMap = Map.ofEntries(
|
||||
entry("hp", Map.ofEntries(entry(EquipType.EQUIP_BRACER, 14001))),
|
||||
entry("hp%", Map.ofEntries(entry(EquipType.EQUIP_SHOES, 10980), entry(EquipType.EQUIP_RING, 50980), entry(EquipType.EQUIP_DRESS, 30980))),
|
||||
entry("atk", Map.ofEntries(entry(EquipType.EQUIP_NECKLACE, 12001))),
|
||||
entry("atk%", Map.ofEntries(entry(EquipType.EQUIP_SHOES, 10990), entry(EquipType.EQUIP_RING, 50990), entry(EquipType.EQUIP_DRESS, 30990))),
|
||||
entry("def%", Map.ofEntries(entry(EquipType.EQUIP_SHOES, 10970), entry(EquipType.EQUIP_RING, 50970), entry(EquipType.EQUIP_DRESS, 30970))),
|
||||
entry("er", Map.ofEntries(entry(EquipType.EQUIP_SHOES, 10960))),
|
||||
entry("em", Map.ofEntries(entry(EquipType.EQUIP_SHOES, 10950), entry(EquipType.EQUIP_RING, 50880), entry(EquipType.EQUIP_DRESS, 30930))),
|
||||
entry("hb", Map.ofEntries(entry(EquipType.EQUIP_DRESS, 30940))),
|
||||
entry("cdmg", Map.ofEntries(entry(EquipType.EQUIP_DRESS, 30950))),
|
||||
entry("cr", Map.ofEntries(entry(EquipType.EQUIP_DRESS, 30960))),
|
||||
entry("phys%", Map.ofEntries(entry(EquipType.EQUIP_RING, 50890))),
|
||||
entry("dendro%", Map.ofEntries(entry(EquipType.EQUIP_RING, 50900))),
|
||||
entry("geo%", Map.ofEntries(entry(EquipType.EQUIP_RING, 50910))),
|
||||
entry("anemo%", Map.ofEntries(entry(EquipType.EQUIP_RING, 50920))),
|
||||
entry("hydro%", Map.ofEntries(entry(EquipType.EQUIP_RING, 50930))),
|
||||
entry("cryo%", Map.ofEntries(entry(EquipType.EQUIP_RING, 50940))),
|
||||
entry("electro%", Map.ofEntries(entry(EquipType.EQUIP_RING, 50950))),
|
||||
entry("pyro%", Map.ofEntries(entry(EquipType.EQUIP_RING, 50960)))
|
||||
);
|
||||
private static final Map<String, String> appendPropMap = Map.ofEntries(
|
||||
entry("hp", "0102"),
|
||||
entry("hp%", "0103"),
|
||||
entry("atk", "0105"),
|
||||
entry("atk%", "0106"),
|
||||
entry("def", "0108"),
|
||||
entry("def%", "0109"),
|
||||
entry("er", "0123"),
|
||||
entry("em", "0124"),
|
||||
entry("cr", "0120"),
|
||||
entry("cdmg", "0122")
|
||||
);
|
||||
|
||||
private int getAppendPropId(String substatText, ItemData itemData) {
|
||||
int res;
|
||||
|
||||
// If the given substat text is an integer, we just use that
|
||||
// as the append prop ID.
|
||||
try {
|
||||
res = Integer.parseInt(substatText);
|
||||
return res;
|
||||
}
|
||||
catch (NumberFormatException ignores) {
|
||||
// No need to handle this here. We just continue with the
|
||||
// possibility of the argument being a substat string.
|
||||
}
|
||||
|
||||
// If the argument was not an integer, we try to determine
|
||||
// the append prop ID from the given text + artifact information.
|
||||
// A substat string has the format `substat_tier`, with the
|
||||
// `_tier` part being optional.
|
||||
String[] substatArgs = substatText.split("_");
|
||||
String substatType;
|
||||
int substatTier;
|
||||
|
||||
if (substatArgs.length == 1) {
|
||||
substatType = substatArgs[0];
|
||||
substatTier =
|
||||
itemData.getRankLevel() == 1 ? 2
|
||||
: itemData.getRankLevel() == 2 ? 3
|
||||
: 4;
|
||||
}
|
||||
else if (substatArgs.length == 2) {
|
||||
substatType = substatArgs[0];
|
||||
substatTier = Integer.parseInt(substatArgs[1]);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
// Check if the specified tier is legal for the artifact rarity.
|
||||
if (substatTier < 1 || substatTier > 4) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
if (itemData.getRankLevel() == 1 && substatTier > 2) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
if (itemData.getRankLevel() == 2 && substatTier > 3) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
// Check if the given substat type string is a legal stat.
|
||||
if (!appendPropMap.containsKey(substatType)) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
// Build the append prop ID.
|
||||
return Integer.parseInt(Integer.toString(itemData.getRankLevel()) + appendPropMap.get(substatType) + Integer.toString(substatTier));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
// Sanity check
|
||||
if (args.size() < 2) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.giveArtifact.usage"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the artifact piece ID from the arguments.
|
||||
int itemId;
|
||||
try {
|
||||
itemId = Integer.parseInt(args.remove(0));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.giveArtifact.id_error"));
|
||||
return;
|
||||
}
|
||||
|
||||
ItemData itemData = GameData.getItemDataMap().get(itemId);
|
||||
if (itemData.getItemType() != ItemType.ITEM_RELIQUARY) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.giveArtifact.id_error"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the main stat from the arguments.
|
||||
// If the given argument is an integer, we use that.
|
||||
// If not, we check if the argument string is in the main prop map.
|
||||
String mainPropIdString = args.remove(0);
|
||||
int mainPropId;
|
||||
|
||||
try {
|
||||
mainPropId = Integer.parseInt(mainPropIdString);
|
||||
} catch (NumberFormatException ignored) {
|
||||
mainPropId = -1;
|
||||
}
|
||||
|
||||
if (mainPropMap.containsKey(mainPropIdString) && mainPropMap.get(mainPropIdString).containsKey(itemData.getEquipType())) {
|
||||
mainPropId = mainPropMap.get(mainPropIdString).get(itemData.getEquipType());
|
||||
}
|
||||
|
||||
if (mainPropId == -1) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.execution.argument_error"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the level from the arguments.
|
||||
int level = 1;
|
||||
try {
|
||||
int last = Integer.parseInt(args.get(args.size()-1));
|
||||
if (last > 0 && last < 22) { // Luckily appendPropIds aren't in the range of [1,21]
|
||||
level = last;
|
||||
args.remove(args.size()-1);
|
||||
}
|
||||
} catch (NumberFormatException ignored) { // Could be a stat,times string so no need to panic
|
||||
}
|
||||
|
||||
// Get substats.
|
||||
ArrayList<Integer> appendPropIdList = new ArrayList<>();
|
||||
try {
|
||||
// Every remaining argument is a substat.
|
||||
args.forEach(it -> {
|
||||
// The substat syntax permits specifying a number of rolls for the given
|
||||
// substat. Split the string into stat and number if that is the case here.
|
||||
String[] arr;
|
||||
int n = 1;
|
||||
if ((arr = it.split(",")).length == 2) {
|
||||
it = arr[0];
|
||||
n = Integer.parseInt(arr[1]);
|
||||
if (n > 200) {
|
||||
n = 200;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the substat ID.
|
||||
int appendPropId = getAppendPropId(it, itemData);
|
||||
|
||||
// Add the current substat.
|
||||
appendPropIdList.addAll(Collections.nCopies(n, appendPropId));
|
||||
});
|
||||
} catch (Exception ignored) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.execution.argument_error"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Create item for the artifact.
|
||||
GameItem item = new GameItem(itemData);
|
||||
item.setLevel(level);
|
||||
item.setMainPropId(mainPropId);
|
||||
item.getAppendPropIdList().clear();
|
||||
item.getAppendPropIdList().addAll(appendPropIdList);
|
||||
targetPlayer.getInventory().addItem(item, ActionReason.SubfieldDrop);
|
||||
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.giveArtifact.success", Integer.toString(itemId), Integer.toString(targetPlayer.getUid())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.GameConstants;
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.excels.AvatarData;
|
||||
import emu.grasscutter.game.avatar.Avatar;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(label = "givechar", usage = "givechar <avatarId> [level]", aliases = {"givec"}, permission = "player.givechar", permissionTargeted = "player.givechar.others", description = "commands.giveChar.description")
|
||||
public final class GiveCharCommand implements CommandHandler {
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
int avatarId;
|
||||
int level = 1;
|
||||
|
||||
switch (args.size()) {
|
||||
case 2:
|
||||
try {
|
||||
level = Integer.parseInt(args.get(1));
|
||||
} catch (NumberFormatException ignored) {
|
||||
// TODO: Parse from avatar name using GM Handbook.
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.avatarLevel"));
|
||||
return;
|
||||
} // Cheeky fall-through to parse first argument too
|
||||
case 1:
|
||||
try {
|
||||
avatarId = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException ignored) {
|
||||
// TODO: Parse from avatar name using GM Handbook.
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.avatarId"));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.giveChar.usage"));
|
||||
return;
|
||||
}
|
||||
|
||||
AvatarData avatarData = GameData.getAvatarDataMap().get(avatarId);
|
||||
if (avatarData == null) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.avatarId"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check level.
|
||||
if (level > 90) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.avatarLevel"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate ascension level.
|
||||
int ascension;
|
||||
if (level <= 40) {
|
||||
ascension = (int) Math.ceil(level / 20f) - 1;
|
||||
} else {
|
||||
ascension = (int) Math.ceil(level / 10f) - 3;
|
||||
ascension = Math.min(ascension, 6);
|
||||
}
|
||||
|
||||
Avatar avatar = new Avatar(avatarId);
|
||||
avatar.setLevel(level);
|
||||
avatar.setPromoteLevel(ascension);
|
||||
|
||||
// Handle skill depot for traveller.
|
||||
if (avatar.getAvatarId() == GameConstants.MAIN_CHARACTER_MALE) {
|
||||
avatar.setSkillDepotData(GameData.getAvatarSkillDepotDataMap().get(504));
|
||||
}
|
||||
else if(avatar.getAvatarId() == GameConstants.MAIN_CHARACTER_FEMALE) {
|
||||
avatar.setSkillDepotData(GameData.getAvatarSkillDepotDataMap().get(704));
|
||||
}
|
||||
|
||||
// This will handle stats and talents
|
||||
avatar.recalcStats();
|
||||
|
||||
targetPlayer.addAvatar(avatar);
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.giveChar.given", Integer.toString(avatarId), Integer.toString(level), Integer.toString(targetPlayer.getUid())));
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,37 @@
|
||||
package emu.grasscutter.command.commands;
|
||||
|
||||
import emu.grasscutter.GameConstants;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.data.GameData;
|
||||
import emu.grasscutter.data.GameDepot;
|
||||
import emu.grasscutter.data.excels.AvatarData;
|
||||
import emu.grasscutter.data.excels.ItemData;
|
||||
import emu.grasscutter.data.excels.ReliquaryAffixData;
|
||||
import emu.grasscutter.data.excels.ReliquaryMainPropData;
|
||||
import emu.grasscutter.game.avatar.Avatar;
|
||||
import emu.grasscutter.game.inventory.GameItem;
|
||||
import emu.grasscutter.game.inventory.ItemType;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.ActionReason;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.utils.SparseSet;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(label = "give", usage = "give <itemId|itemName> [amount] [level]", aliases = {
|
||||
@Command(label = "give", usage = "give <itemId|avatarId|\"all\"|\"weapons\"|\"mats\"|\"avatars\"> [lv<level>] [r<refinement>] [x<amount>] | give <artifactId> [lv<level>] [x<amount>] [mainPropId] [<appendPropId>[,<times>]]...", aliases = {
|
||||
"g", "item", "giveitem"}, permission = "player.give", permissionTargeted = "player.give.others", description = "commands.give.description")
|
||||
public final class GiveCommand implements CommandHandler {
|
||||
Pattern lvlRegex = Pattern.compile("l(?:vl?)?(\\d+)"); // Java is a joke of a proglang that doesn't have raw string literals
|
||||
Pattern refineRegex = Pattern.compile("r(\\d+)");
|
||||
Pattern amountRegex = Pattern.compile("((?<=x)\\d+|\\d+(?=x)(?!x\\d))");
|
||||
private static Pattern lvlRegex = Pattern.compile("l(?:vl?)?(\\d+)"); // Java doesn't have raw string literals :(
|
||||
private static Pattern refineRegex = Pattern.compile("r(\\d+)");
|
||||
private static Pattern constellationRegex = Pattern.compile("c(\\d+)");
|
||||
private static Pattern amountRegex = Pattern.compile("((?<=x)\\d+|\\d+(?=x)(?!x\\d))");
|
||||
|
||||
private int matchIntOrNeg(Pattern pattern, String arg) {
|
||||
private static int matchIntOrNeg(Pattern pattern, String arg) {
|
||||
Matcher match = pattern.matcher(arg);
|
||||
if (match.find()) {
|
||||
return Integer.parseInt(match.group(1)); // This should be exception-safe as only \d+ can be passed to it (i.e. non-empty string of pure digits)
|
||||
@@ -31,27 +39,50 @@ public final class GiveCommand implements CommandHandler {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
int item;
|
||||
int lvl = 1;
|
||||
int amount = 1;
|
||||
int refinement = 0;
|
||||
private static enum GiveAllType {
|
||||
NONE,
|
||||
ALL,
|
||||
WEAPONS,
|
||||
MATS,
|
||||
AVATARS
|
||||
}
|
||||
|
||||
for (int i = args.size()-1; i>=0; i--) { // Reverse iteration as we are deleting elements
|
||||
private static class GiveItemParameters {
|
||||
public int id;
|
||||
public int lvl = 0;
|
||||
public int amount = 1;
|
||||
public int refinement = 1;
|
||||
public int constellation = -1;
|
||||
public int mainPropId = -1;
|
||||
public List<Integer> appendPropIdList;
|
||||
public ItemData data;
|
||||
public AvatarData avatarData;
|
||||
public GiveAllType giveAllType = GiveAllType.NONE;
|
||||
};
|
||||
|
||||
private static GiveItemParameters parseArgs(Player sender, List<String> args) throws IllegalArgumentException {
|
||||
GiveItemParameters param = new GiveItemParameters();
|
||||
|
||||
// Extract any tagged arguments (e.g. "lv90", "x100", "r5")
|
||||
for (int i = args.size() - 1; i >= 0; i--) { // Reverse iteration as we are deleting elements
|
||||
String arg = args.get(i).toLowerCase();
|
||||
boolean deleteArg = false;
|
||||
int argNum;
|
||||
// Note that a single argument can actually match all of these, e.g. "lv90r5x100"
|
||||
if ((argNum = matchIntOrNeg(lvlRegex, arg)) != -1) {
|
||||
lvl = argNum;
|
||||
param.lvl = argNum;
|
||||
deleteArg = true;
|
||||
}
|
||||
if ((argNum = matchIntOrNeg(refineRegex, arg)) != -1) {
|
||||
refinement = argNum;
|
||||
param.refinement = argNum;
|
||||
deleteArg = true;
|
||||
}
|
||||
if ((argNum = matchIntOrNeg(constellationRegex, arg)) != -1) {
|
||||
param.constellation = argNum;
|
||||
deleteArg = true;
|
||||
}
|
||||
if ((argNum = matchIntOrNeg(amountRegex, arg)) != -1) {
|
||||
amount = argNum;
|
||||
param.amount = argNum;
|
||||
deleteArg = true;
|
||||
}
|
||||
if (deleteArg) {
|
||||
@@ -59,112 +90,387 @@ public final class GiveCommand implements CommandHandler {
|
||||
}
|
||||
}
|
||||
|
||||
switch (args.size()) {
|
||||
case 4: // <itemId|itemName> [amount] [level] [refinement]
|
||||
try {
|
||||
refinement = Integer.parseInt(args.get(3));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.itemRefinement"));
|
||||
return;
|
||||
} // Fallthrough
|
||||
case 3: // <itemId|itemName> [amount] [level]
|
||||
try {
|
||||
lvl = Integer.parseInt(args.get(2));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.itemLevel"));
|
||||
return;
|
||||
} // Fallthrough
|
||||
case 2: // <itemId|itemName> [amount]
|
||||
try {
|
||||
amount = Integer.parseInt(args.get(1));
|
||||
} catch (NumberFormatException ignored) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.amount"));
|
||||
return;
|
||||
} // Fallthrough
|
||||
case 1: // <itemId|itemName>
|
||||
try {
|
||||
item = Integer.parseInt(args.get(0));
|
||||
} catch (NumberFormatException ignored) {
|
||||
// TODO: Parse from item name using GM Handbook.
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.itemId"));
|
||||
return;
|
||||
}
|
||||
// At this point, first remaining argument MUST be itemId/avatarId
|
||||
if (args.size() < 1) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.give.usage"); // Reachable if someone does `/give lv90` or similar
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
String id = args.remove(0);
|
||||
boolean isRelic = false;
|
||||
|
||||
switch (id) {
|
||||
case "all":
|
||||
param.giveAllType = GiveAllType.ALL;
|
||||
break;
|
||||
default: // *No args*
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.give.usage"));
|
||||
return;
|
||||
case "weapons":
|
||||
param.giveAllType = GiveAllType.WEAPONS;
|
||||
break;
|
||||
case "mats":
|
||||
param.giveAllType = GiveAllType.MATS;
|
||||
break;
|
||||
case "avatars":
|
||||
param.giveAllType = GiveAllType.AVATARS;
|
||||
break;
|
||||
default:
|
||||
try {
|
||||
param.id = Integer.parseInt(id);
|
||||
param.data = GameData.getItemDataMap().get(param.id);
|
||||
if ((param.id > 10_000_000) && (param.id < 12_000_000))
|
||||
param.avatarData = GameData.getAvatarDataMap().get(param.id);
|
||||
else if ((param.id > 1000) && (param.id < 1100))
|
||||
param.avatarData = GameData.getAvatarDataMap().get(param.id - 1000 + 10_000_000);
|
||||
isRelic = ((param.data != null) && (param.data.getItemType() == ItemType.ITEM_RELIQUARY));
|
||||
} catch (NumberFormatException e) {
|
||||
// TODO: Parse from item name using GM Handbook.
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.generic.invalid.itemId");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
ItemData itemData = GameData.getItemDataMap().get(item);
|
||||
if (itemData == null) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.generic.invalid.itemId"));
|
||||
if (param.amount < 1) param.amount = 1;
|
||||
if (param.refinement < 1) param.refinement = 1;
|
||||
if (param.refinement > 5) param.refinement = 5;
|
||||
if (isRelic) {
|
||||
// Input 0-20 to match game, instead of 1-21 which is the real level
|
||||
if (param.lvl < 0) param.lvl = 0;
|
||||
if (param.lvl > 20) param.lvl = 20;
|
||||
param.lvl += 1;
|
||||
if (illegalRelicIds.contains(param.id))
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.give.illegal_relic");
|
||||
} else {
|
||||
// Suitable for Avatars and Weapons
|
||||
if (param.lvl < 1) param.lvl = 1;
|
||||
if (param.lvl > 90) param.lvl = 90;
|
||||
}
|
||||
|
||||
if (isRelic && !args.isEmpty()) {
|
||||
try {
|
||||
parseRelicArgs(param, args);
|
||||
} catch (IllegalArgumentException e) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.execution.argument_error");
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.give.usage_relic");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
return param;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Player sender, Player targetPlayer, List<String> args) {
|
||||
if (args.size() < 1) { // *No args*
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.give.usage");
|
||||
return;
|
||||
}
|
||||
if (refinement != 0) {
|
||||
if (itemData.getItemType() == ItemType.ITEM_WEAPON) {
|
||||
if (refinement < 1 || refinement > 5) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.give.refinement_must_between_1_and_5"));
|
||||
try {
|
||||
GiveItemParameters param = parseArgs(sender, args);
|
||||
|
||||
switch (param.giveAllType) {
|
||||
case ALL:
|
||||
giveAll(targetPlayer, param);
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.give.giveall_success");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.give.refinement_only_applicable_weapons"));
|
||||
case WEAPONS:
|
||||
giveAllWeapons(targetPlayer, param);
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.give.giveall_success");
|
||||
return;
|
||||
case MATS:
|
||||
giveAllMats(targetPlayer, param);
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.give.giveall_success");
|
||||
return;
|
||||
case AVATARS:
|
||||
giveAllAvatars(targetPlayer, param);
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.give.giveall_success");
|
||||
return;
|
||||
case NONE:
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if this is an avatar
|
||||
if (param.avatarData != null) {
|
||||
Avatar avatar = makeAvatar(param);
|
||||
targetPlayer.addAvatar(avatar);
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.give.given_avatar", Integer.toString(param.id), Integer.toString(param.lvl), Integer.toString(targetPlayer.getUid()));
|
||||
return;
|
||||
}
|
||||
// If it's not an avatar, it needs to be a valid item
|
||||
if (param.data == null) {
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.generic.invalid.itemId");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (param.data.getItemType()) {
|
||||
case ITEM_WEAPON:
|
||||
targetPlayer.getInventory().addItems(makeUnstackableItems(param), ActionReason.SubfieldDrop);
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.give.given_with_level_and_refinement", Integer.toString(param.id), Integer.toString(param.lvl), Integer.toString(param.refinement), Integer.toString(param.amount), Integer.toString(targetPlayer.getUid()));
|
||||
return;
|
||||
case ITEM_RELIQUARY:
|
||||
targetPlayer.getInventory().addItems(makeArtifacts(param), ActionReason.SubfieldDrop);
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.give.given_level", Integer.toString(param.id), Integer.toString(param.lvl), Integer.toString(param.amount), Integer.toString(targetPlayer.getUid()));
|
||||
//CommandHandler.sendTranslatedMessage(sender, "commands.giveArtifact.success", Integer.toString(param.id), Integer.toString(targetPlayer.getUid()));
|
||||
return;
|
||||
default:
|
||||
targetPlayer.getInventory().addItem(new GameItem(param.data, param.amount), ActionReason.SubfieldDrop);
|
||||
CommandHandler.sendTranslatedMessage(sender, "commands.give.given", Integer.toString(param.amount), Integer.toString(param.id), Integer.toString(targetPlayer.getUid()));
|
||||
return;
|
||||
}
|
||||
} catch (IllegalArgumentException ignored) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.item(targetPlayer, itemData, amount, lvl, refinement);
|
||||
private static Avatar makeAvatar(GiveItemParameters param) {
|
||||
return makeAvatar(param.avatarData, param.lvl, Avatar.getMinPromoteLevel(param.lvl), 0);
|
||||
}
|
||||
|
||||
if (!itemData.isEquip()) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.give.given", Integer.toString(amount), Integer.toString(item), Integer.toString(targetPlayer.getUid())));
|
||||
} else if (itemData.getItemType() == ItemType.ITEM_WEAPON) {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.give.given_with_level_and_refinement", Integer.toString(item), Integer.toString(lvl), Integer.toString(refinement), Integer.toString(amount), Integer.toString(targetPlayer.getUid())));
|
||||
} else {
|
||||
CommandHandler.sendMessage(sender, translate(sender, "commands.give.given_level", Integer.toString(item), Integer.toString(lvl), Integer.toString(amount), Integer.toString(targetPlayer.getUid())));
|
||||
private static Avatar makeAvatar(AvatarData avatarData, int level, int promoteLevel, int constellation) {
|
||||
// Calculate ascension level.
|
||||
Avatar avatar = new Avatar(avatarData);
|
||||
avatar.setLevel(level);
|
||||
avatar.setPromoteLevel(promoteLevel);
|
||||
|
||||
// Add constellations.
|
||||
int talentBase = switch (avatar.getAvatarId()) {
|
||||
case 10000005 -> 70;
|
||||
case 10000006 -> 40;
|
||||
default -> (avatar.getAvatarId() - 10000000) * 10;
|
||||
};
|
||||
|
||||
for (int i = 1; i <= constellation; i++) {
|
||||
avatar.getTalentIdList().add(talentBase + i);
|
||||
}
|
||||
|
||||
// Main character needs skill depot manually added.
|
||||
if (avatar.getAvatarId() == GameConstants.MAIN_CHARACTER_MALE) {
|
||||
avatar.setSkillDepotData(GameData.getAvatarSkillDepotDataMap().get(504));
|
||||
}
|
||||
else if(avatar.getAvatarId() == GameConstants.MAIN_CHARACTER_FEMALE) {
|
||||
avatar.setSkillDepotData(GameData.getAvatarSkillDepotDataMap().get(704));
|
||||
}
|
||||
|
||||
avatar.recalcStats();
|
||||
|
||||
return avatar;
|
||||
}
|
||||
|
||||
private static void giveAllAvatars(Player player, GiveItemParameters param) {
|
||||
int promoteLevel = Avatar.getMinPromoteLevel(param.lvl);
|
||||
if (param.constellation < 0) {
|
||||
param.constellation = 6;
|
||||
}
|
||||
for (AvatarData avatarData : GameData.getAvatarDataMap().values()) {
|
||||
// Exclude test avatars
|
||||
int id = avatarData.getId();
|
||||
if (id < 10000002 || id >= 11000000) continue;
|
||||
|
||||
// Don't try to add each avatar to the current team
|
||||
player.addAvatar(makeAvatar(avatarData, param.lvl, promoteLevel, param.constellation), false);
|
||||
}
|
||||
}
|
||||
|
||||
private void item(Player player, ItemData itemData, int amount, int lvl, int refinement) {
|
||||
if (itemData.isEquip()) {
|
||||
List<GameItem> items = new LinkedList<>();
|
||||
for (int i = 0; i < amount; i++) {
|
||||
GameItem item = new GameItem(itemData);
|
||||
if (item.isEquipped()) {
|
||||
// check item max level
|
||||
if (item.getItemType() == ItemType.ITEM_WEAPON) {
|
||||
if (lvl > 90) lvl = 90;
|
||||
} else {
|
||||
if (lvl > 21) lvl = 21;
|
||||
}
|
||||
}
|
||||
item.setCount(amount);
|
||||
item.setLevel(lvl);
|
||||
if (lvl > 80) {
|
||||
item.setPromoteLevel(6);
|
||||
} else if (lvl > 70) {
|
||||
item.setPromoteLevel(5);
|
||||
} else if (lvl > 60) {
|
||||
item.setPromoteLevel(4);
|
||||
} else if (lvl > 50) {
|
||||
item.setPromoteLevel(3);
|
||||
} else if (lvl > 40) {
|
||||
item.setPromoteLevel(2);
|
||||
} else if (lvl > 20) {
|
||||
item.setPromoteLevel(1);
|
||||
}
|
||||
if (item.getItemType() == ItemType.ITEM_WEAPON) {
|
||||
if (refinement > 0) {
|
||||
item.setRefinement(refinement - 1);
|
||||
} else {
|
||||
item.setRefinement(0);
|
||||
}
|
||||
}
|
||||
items.add(item);
|
||||
private static List<GameItem> makeUnstackableItems(GiveItemParameters param) {
|
||||
int promoteLevel = GameItem.getMinPromoteLevel(param.lvl);
|
||||
int totalExp = 0;
|
||||
if (param.data.getItemType() == ItemType.ITEM_WEAPON) {
|
||||
int rankLevel = param.data.getRankLevel();
|
||||
for (int i = 1; i < param.lvl; i++)
|
||||
totalExp += GameData.getWeaponExpRequired(rankLevel, i);
|
||||
}
|
||||
|
||||
List<GameItem> items = new ArrayList<>(param.amount);
|
||||
for (int i = 0; i < param.amount; i++) {
|
||||
GameItem item = new GameItem(param.data);
|
||||
item.setLevel(param.lvl);
|
||||
if (item.getItemType() == ItemType.ITEM_WEAPON) {
|
||||
item.setPromoteLevel(promoteLevel);
|
||||
item.setTotalExp(totalExp);
|
||||
item.setRefinement(param.refinement - 1); // Actual refinement data is 0..4 not 1..5
|
||||
}
|
||||
player.getInventory().addItems(items, ActionReason.SubfieldDrop);
|
||||
} else {
|
||||
GameItem item = new GameItem(itemData);
|
||||
item.setCount(amount);
|
||||
player.getInventory().addItem(item, ActionReason.SubfieldDrop);
|
||||
items.add(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
private static List<GameItem> makeArtifacts(GiveItemParameters param) {
|
||||
param.lvl = Math.min(param.lvl, param.data.getMaxLevel());
|
||||
int rank = param.data.getRankLevel();
|
||||
int totalExp = 0;
|
||||
for (int i = 1; i < param.lvl; i++)
|
||||
totalExp += GameData.getRelicExpRequired(rank, i);
|
||||
|
||||
List<GameItem> items = new ArrayList<>(param.amount);
|
||||
for (int i = 0; i < param.amount; i++) {
|
||||
// Create item for the artifact.
|
||||
GameItem item = new GameItem(param.data);
|
||||
item.setLevel(param.lvl);
|
||||
item.setTotalExp(totalExp);
|
||||
int numAffixes = param.data.getAppendPropNum() + (param.lvl-1)/4;
|
||||
if (param.mainPropId > 0) // Keep random mainProp if we didn't specify one
|
||||
item.setMainPropId(param.mainPropId);
|
||||
if (param.appendPropIdList != null) {
|
||||
item.getAppendPropIdList().clear();
|
||||
item.getAppendPropIdList().addAll(param.appendPropIdList);
|
||||
}
|
||||
// If we didn't include enough substats, top them up to the appropriate level at random
|
||||
item.addAppendProps(numAffixes - item.getAppendPropIdList().size());
|
||||
items.add(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
private static int getArtifactMainProp(ItemData itemData, FightProperty prop) throws IllegalArgumentException {
|
||||
if (prop != FightProperty.FIGHT_PROP_NONE)
|
||||
for (ReliquaryMainPropData data : GameDepot.getRelicMainPropList(itemData.getMainPropDepotId()))
|
||||
if (data.getWeight() > 0 && data.getFightProp() == prop)
|
||||
return data.getId();
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
private static List<Integer> getArtifactAffixes(ItemData itemData, FightProperty prop) throws IllegalArgumentException {
|
||||
if (prop == FightProperty.FIGHT_PROP_NONE) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
List<Integer> affixes = new ArrayList<>();
|
||||
for (ReliquaryAffixData data : GameDepot.getRelicAffixList(itemData.getAppendPropDepotId())) {
|
||||
if (data.getWeight() > 0 && data.getFightProp() == prop) {
|
||||
affixes.add(data.getId());
|
||||
}
|
||||
}
|
||||
return affixes;
|
||||
}
|
||||
|
||||
private static int getAppendPropId(String substatText, ItemData itemData) throws IllegalArgumentException {
|
||||
// If the given substat text is an integer, we just use that as the append prop ID.
|
||||
try {
|
||||
return Integer.parseInt(substatText);
|
||||
} catch (NumberFormatException ignored) {
|
||||
// If the argument was not an integer, we try to determine
|
||||
// the append prop ID from the given text + artifact information.
|
||||
// A substat string has the format `substat_tier`, with the
|
||||
// `_tier` part being optional, defaulting to the maximum.
|
||||
String[] substatArgs = substatText.split("_");
|
||||
String substatType = substatArgs[0];
|
||||
|
||||
int substatTier = 4;
|
||||
if (substatArgs.length > 1) {
|
||||
substatTier = Integer.parseInt(substatArgs[1]);
|
||||
}
|
||||
|
||||
List<Integer> substats = getArtifactAffixes(itemData, FightProperty.getPropByShortName(substatType));
|
||||
|
||||
if (substats.isEmpty()) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
substatTier -= 1; // 1-indexed to 0-indexed
|
||||
substatTier = Math.min(Math.max(0, substatTier), substats.size() - 1);
|
||||
return substats.get(substatTier);
|
||||
}
|
||||
}
|
||||
|
||||
private static void parseRelicArgs(GiveItemParameters param, List<String> args) throws IllegalArgumentException {
|
||||
// Get the main stat from the arguments.
|
||||
// If the given argument is an integer, we use that.
|
||||
// If not, we check if the argument string is in the main prop map.
|
||||
String mainPropIdString = args.remove(0);
|
||||
|
||||
try {
|
||||
param.mainPropId = Integer.parseInt(mainPropIdString);
|
||||
} catch (NumberFormatException ignored) {
|
||||
// This can in turn throw an exception which we don't want to catch here.
|
||||
param.mainPropId = getArtifactMainProp(param.data, FightProperty.getPropByShortName(mainPropIdString));
|
||||
}
|
||||
|
||||
// Get substats.
|
||||
param.appendPropIdList = new ArrayList<>();
|
||||
// Every remaining argument is a substat.
|
||||
for (String prop : args) {
|
||||
// The substat syntax permits specifying a number of rolls for the given
|
||||
// substat. Split the string into stat and number if that is the case here.
|
||||
String[] arr = prop.split(",");
|
||||
prop = arr[0];
|
||||
int n = 1;
|
||||
if (arr.length > 1) {
|
||||
n = Math.min(Integer.parseInt(arr[1]), 200);
|
||||
}
|
||||
|
||||
// Determine the substat ID.
|
||||
int appendPropId = getAppendPropId(prop, param.data);
|
||||
|
||||
// Add the current substat.
|
||||
for (int i = 0; i < n; i++) {
|
||||
param.appendPropIdList.add(appendPropId);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static void addItemsChunked(Player player, List<GameItem> items, int packetSize) {
|
||||
// Send the items in multiple packets
|
||||
int lastIdx = items.size() - 1;
|
||||
for (int i = 0; i <= lastIdx; i += packetSize) {
|
||||
player.getInventory().addItems(items.subList(i, Math.min(i + packetSize, lastIdx)));
|
||||
}
|
||||
}
|
||||
|
||||
private static void giveAllMats(Player player, GiveItemParameters param) {
|
||||
List<GameItem> itemList = new ArrayList<>();
|
||||
for (ItemData itemdata : GameData.getItemDataMap().values()) {
|
||||
int id = itemdata.getId();
|
||||
if (id < 100_000) continue; // Nothing meaningful below this
|
||||
if (illegalItemIds.contains(id)) continue;
|
||||
if (itemdata.isEquip()) continue;
|
||||
|
||||
GameItem item = new GameItem(itemdata);
|
||||
item.setCount(param.amount);
|
||||
itemList.add(item);
|
||||
}
|
||||
|
||||
addItemsChunked(player, itemList, 100);
|
||||
}
|
||||
|
||||
private static void giveAllWeapons(Player player, GiveItemParameters param) {
|
||||
int promoteLevel = GameItem.getMinPromoteLevel(param.lvl);
|
||||
int quantity = Math.min(param.amount, 5);
|
||||
int refinement = param.refinement - 1;
|
||||
|
||||
List<GameItem> itemList = new ArrayList<>();
|
||||
for (ItemData itemdata : GameData.getItemDataMap().values()) {
|
||||
int id = itemdata.getId();
|
||||
if (id < 11100 || id > 16000) continue; // All extant weapons are within this range
|
||||
if (illegalWeaponIds.contains(id)) continue;
|
||||
if (!itemdata.isEquip()) continue;
|
||||
if (itemdata.getItemType() != ItemType.ITEM_WEAPON) continue;
|
||||
|
||||
for (int i = 0; i < quantity; i++) {
|
||||
GameItem item = new GameItem(itemdata);
|
||||
item.setLevel(param.lvl);
|
||||
item.setPromoteLevel(promoteLevel);
|
||||
item.setRefinement(refinement);
|
||||
itemList.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
addItemsChunked(player, itemList, 100);
|
||||
}
|
||||
|
||||
private static void giveAll(Player player, GiveItemParameters param) {
|
||||
giveAllAvatars(player, param);
|
||||
giveAllMats(player, param);
|
||||
giveAllWeapons(player, param);
|
||||
}
|
||||
|
||||
private static final SparseSet illegalWeaponIds = new SparseSet("""
|
||||
10000-10008, 11411, 11506-11508, 12505, 12506, 12508, 12509,
|
||||
13503, 13506, 14411, 14503, 14505, 14508, 15504-15506
|
||||
""");
|
||||
|
||||
private static final SparseSet illegalRelicIds = new SparseSet("""
|
||||
20001, 23300-23340, 23383-23385, 78310-78554, 99310-99554
|
||||
""");
|
||||
|
||||
private static final SparseSet illegalItemIds = new SparseSet("""
|
||||
100086, 100087, 100100-101000, 101106-101110, 101306, 101500-104000,
|
||||
105001, 105004, 106000-107000, 107011, 108000, 109000-110000,
|
||||
115000-130000, 200200-200899, 220050, 220054
|
||||
""");
|
||||
}
|
||||
|
||||
@@ -4,15 +4,12 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import emu.grasscutter.Grasscutter;
|
||||
import emu.grasscutter.command.Command;
|
||||
import emu.grasscutter.command.CommandHandler;
|
||||
import emu.grasscutter.game.entity.EntityAvatar;
|
||||
import emu.grasscutter.game.player.Player;
|
||||
import emu.grasscutter.game.props.FightProperty;
|
||||
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
|
||||
import emu.grasscutter.utils.Language;
|
||||
|
||||
import static emu.grasscutter.utils.Language.translate;
|
||||
|
||||
@Command(label = "setstats", usage = "setstats|stats <stat> <value>", aliases = {"stats"}, permission = "player.setstats", permissionTargeted = "player.setstats.others", description = "commands.setStats.description")
|
||||
@@ -20,157 +17,50 @@ public final class SetStatsCommand implements CommandHandler {
|
||||
static class Stat {
|
||||
String name;
|
||||
FightProperty prop;
|
||||
boolean percent;
|
||||
|
||||
public Stat(String name, FightProperty prop, boolean percent) {
|
||||
public Stat(FightProperty prop) {
|
||||
this.name = prop.toString();
|
||||
this.prop = prop;
|
||||
}
|
||||
|
||||
public Stat(String name, FightProperty prop) {
|
||||
this.name = name;
|
||||
this.prop = prop;
|
||||
this.percent = percent;
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Stat> stats = new HashMap<>();
|
||||
Map<String, Stat> stats;
|
||||
|
||||
public SetStatsCommand() {
|
||||
// Default stats
|
||||
stats.put("maxhp", new Stat(FightProperty.FIGHT_PROP_MAX_HP.toString(), FightProperty.FIGHT_PROP_MAX_HP, false));
|
||||
stats.put("hp", new Stat(FightProperty.FIGHT_PROP_CUR_HP.toString(), FightProperty.FIGHT_PROP_CUR_HP, false));
|
||||
stats.put("atk", new Stat(FightProperty.FIGHT_PROP_CUR_ATTACK.toString(), FightProperty.FIGHT_PROP_CUR_ATTACK, false));
|
||||
stats.put("atkb", new Stat(FightProperty.FIGHT_PROP_BASE_ATTACK.toString(), FightProperty.FIGHT_PROP_BASE_ATTACK, false)); // This doesn't seem to get used to recalculate ATK, so it's only useful for stuff like Bennett's buff.
|
||||
stats.put("def", new Stat(FightProperty.FIGHT_PROP_DEFENSE.toString(), FightProperty.FIGHT_PROP_DEFENSE, false));
|
||||
stats.put("em", new Stat(FightProperty.FIGHT_PROP_ELEMENT_MASTERY.toString(), FightProperty.FIGHT_PROP_ELEMENT_MASTERY, false));
|
||||
stats.put("er", new Stat(FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY.toString(), FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY, true));
|
||||
stats.put("crate", new Stat(FightProperty.FIGHT_PROP_CRITICAL.toString(), FightProperty.FIGHT_PROP_CRITICAL, true));
|
||||
stats.put("cdmg", new Stat(FightProperty.FIGHT_PROP_CRITICAL_HURT.toString(), FightProperty.FIGHT_PROP_CRITICAL_HURT, true));
|
||||
stats.put("dmg", new Stat(FightProperty.FIGHT_PROP_ADD_HURT.toString(), FightProperty.FIGHT_PROP_ADD_HURT, true)); // This seems to get reset after attacks
|
||||
stats.put("eanemo", new Stat(FightProperty.FIGHT_PROP_WIND_ADD_HURT.toString(), FightProperty.FIGHT_PROP_WIND_ADD_HURT, true));
|
||||
stats.put("ecryo", new Stat(FightProperty.FIGHT_PROP_ICE_ADD_HURT.toString(), FightProperty.FIGHT_PROP_ICE_ADD_HURT, true));
|
||||
stats.put("edendro", new Stat(FightProperty.FIGHT_PROP_GRASS_ADD_HURT.toString(), FightProperty.FIGHT_PROP_GRASS_ADD_HURT, true));
|
||||
stats.put("eelectro", new Stat(FightProperty.FIGHT_PROP_ELEC_ADD_HURT.toString(), FightProperty.FIGHT_PROP_ELEC_ADD_HURT, true));
|
||||
stats.put("egeo", new Stat(FightProperty.FIGHT_PROP_ROCK_ADD_HURT.toString(), FightProperty.FIGHT_PROP_ROCK_ADD_HURT, true));
|
||||
stats.put("ehydro", new Stat(FightProperty.FIGHT_PROP_WATER_ADD_HURT.toString(), FightProperty.FIGHT_PROP_WATER_ADD_HURT, true));
|
||||
stats.put("epyro", new Stat(FightProperty.FIGHT_PROP_FIRE_ADD_HURT.toString(), FightProperty.FIGHT_PROP_FIRE_ADD_HURT, true));
|
||||
stats.put("ephys", new Stat(FightProperty.FIGHT_PROP_PHYSICAL_ADD_HURT.toString(), FightProperty.FIGHT_PROP_PHYSICAL_ADD_HURT, true));
|
||||
stats.put("resall", new Stat(FightProperty.FIGHT_PROP_SUB_HURT.toString(), FightProperty.FIGHT_PROP_SUB_HURT, true)); // This seems to get reset after attacks
|
||||
stats.put("resanemo", new Stat(FightProperty.FIGHT_PROP_WIND_SUB_HURT.toString(), FightProperty.FIGHT_PROP_WIND_SUB_HURT, true));
|
||||
stats.put("rescryo", new Stat(FightProperty.FIGHT_PROP_ICE_SUB_HURT.toString(), FightProperty.FIGHT_PROP_ICE_SUB_HURT, true));
|
||||
stats.put("resdendro", new Stat(FightProperty.FIGHT_PROP_GRASS_SUB_HURT.toString(), FightProperty.FIGHT_PROP_GRASS_SUB_HURT, true));
|
||||
stats.put("reselectro", new Stat(FightProperty.FIGHT_PROP_ELEC_SUB_HURT.toString(), FightProperty.FIGHT_PROP_ELEC_SUB_HURT, true));
|
||||
stats.put("resgeo", new Stat(FightProperty.FIGHT_PROP_ROCK_SUB_HURT.toString(), FightProperty.FIGHT_PROP_ROCK_SUB_HURT, true));
|
||||
stats.put("reshydro", new Stat(FightProperty.FIGHT_PROP_WATER_SUB_HURT.toString(), FightProperty.FIGHT_PROP_WATER_SUB_HURT, true));
|
||||
stats.put("respyro", new Stat(FightProperty.FIGHT_PROP_FIRE_SUB_HURT.toString(), FightProperty.FIGHT_PROP_FIRE_SUB_HURT, true));
|
||||
stats.put("resphys", new Stat(FightProperty.FIGHT_PROP_PHYSICAL_SUB_HURT.toString(), FightProperty.FIGHT_PROP_PHYSICAL_SUB_HURT, true));
|
||||
stats.put("cdr", new Stat(FightProperty.FIGHT_PROP_SKILL_CD_MINUS_RATIO.toString(), FightProperty.FIGHT_PROP_SKILL_CD_MINUS_RATIO, true));
|
||||
stats.put("heal", new Stat(FightProperty.FIGHT_PROP_HEAL_ADD.toString(), FightProperty.FIGHT_PROP_HEAL_ADD, true));
|
||||
stats.put("heali", new Stat(FightProperty.FIGHT_PROP_HEALED_ADD.toString(), FightProperty.FIGHT_PROP_HEALED_ADD, true));
|
||||
stats.put("shield", new Stat(FightProperty.FIGHT_PROP_SHIELD_COST_MINUS_RATIO.toString(), FightProperty.FIGHT_PROP_SHIELD_COST_MINUS_RATIO, true));
|
||||
stats.put("defi", new Stat(FightProperty.FIGHT_PROP_DEFENCE_IGNORE_RATIO.toString(), FightProperty.FIGHT_PROP_DEFENCE_IGNORE_RATIO, true));
|
||||
// Compatibility aliases
|
||||
stats.put("mhp", stats.get("maxhp"));
|
||||
stats.put("cr", stats.get("crate"));
|
||||
stats.put("cd", stats.get("cdmg"));
|
||||
stats.put("edend", stats.get("edendro"));
|
||||
stats.put("eelec", stats.get("eelectro"));
|
||||
stats.put("ethunder", stats.get("eelectro"));
|
||||
|
||||
this.stats = new HashMap<>();
|
||||
for (String key : FightProperty.getShortNames()) {
|
||||
this.stats.put(key, new Stat(FightProperty.getPropByShortName(key)));
|
||||
}
|
||||
// Full FightProperty enum that won't be advertised but can be used by devs
|
||||
// They have a prefix to avoid the "hp" clash
|
||||
stats.put("_none", new Stat("NONE", FightProperty.FIGHT_PROP_NONE, true));
|
||||
stats.put("_base_hp", new Stat("BASE_HP", FightProperty.FIGHT_PROP_BASE_HP, false));
|
||||
stats.put("_hp", new Stat("HP", FightProperty.FIGHT_PROP_HP, false));
|
||||
stats.put("_hp_percent", new Stat("HP_PERCENT", FightProperty.FIGHT_PROP_HP_PERCENT, true));
|
||||
stats.put("_base_attack", new Stat("BASE_ATTACK", FightProperty.FIGHT_PROP_BASE_ATTACK, false));
|
||||
stats.put("_attack", new Stat("ATTACK", FightProperty.FIGHT_PROP_ATTACK, false));
|
||||
stats.put("_attack_percent", new Stat("ATTACK_PERCENT", FightProperty.FIGHT_PROP_ATTACK_PERCENT, true));
|
||||
stats.put("_base_defense", new Stat("BASE_DEFENSE", FightProperty.FIGHT_PROP_BASE_DEFENSE, false));
|
||||
stats.put("_defense", new Stat("DEFENSE", FightProperty.FIGHT_PROP_DEFENSE, false));
|
||||
stats.put("_defense_percent", new Stat("DEFENSE_PERCENT", FightProperty.FIGHT_PROP_DEFENSE_PERCENT, true));
|
||||
stats.put("_base_speed", new Stat("BASE_SPEED", FightProperty.FIGHT_PROP_BASE_SPEED, true));
|
||||
stats.put("_speed_percent", new Stat("SPEED_PERCENT", FightProperty.FIGHT_PROP_SPEED_PERCENT, true));
|
||||
stats.put("_hp_mp_percent", new Stat("HP_MP_PERCENT", FightProperty.FIGHT_PROP_HP_MP_PERCENT, true));
|
||||
stats.put("_attack_mp_percent", new Stat("ATTACK_MP_PERCENT", FightProperty.FIGHT_PROP_ATTACK_MP_PERCENT, true));
|
||||
stats.put("_critical", new Stat("CRITICAL", FightProperty.FIGHT_PROP_CRITICAL, true));
|
||||
stats.put("_anti_critical", new Stat("ANTI_CRITICAL", FightProperty.FIGHT_PROP_ANTI_CRITICAL, true));
|
||||
stats.put("_critical_hurt", new Stat("CRITICAL_HURT", FightProperty.FIGHT_PROP_CRITICAL_HURT, true));
|
||||
stats.put("_charge_efficiency", new Stat("CHARGE_EFFICIENCY", FightProperty.FIGHT_PROP_CHARGE_EFFICIENCY, true));
|
||||
stats.put("_add_hurt", new Stat("ADD_HURT", FightProperty.FIGHT_PROP_ADD_HURT, true));
|
||||
stats.put("_sub_hurt", new Stat("SUB_HURT", FightProperty.FIGHT_PROP_SUB_HURT, true));
|
||||
stats.put("_heal_add", new Stat("HEAL_ADD", FightProperty.FIGHT_PROP_HEAL_ADD, true));
|
||||
stats.put("_healed_add", new Stat("HEALED_ADD", FightProperty.FIGHT_PROP_HEALED_ADD, false));
|
||||
stats.put("_element_mastery", new Stat("ELEMENT_MASTERY", FightProperty.FIGHT_PROP_ELEMENT_MASTERY, true));
|
||||
stats.put("_physical_sub_hurt", new Stat("PHYSICAL_SUB_HURT", FightProperty.FIGHT_PROP_PHYSICAL_SUB_HURT, true));
|
||||
stats.put("_physical_add_hurt", new Stat("PHYSICAL_ADD_HURT", FightProperty.FIGHT_PROP_PHYSICAL_ADD_HURT, true));
|
||||
stats.put("_defence_ignore_ratio", new Stat("DEFENCE_IGNORE_RATIO", FightProperty.FIGHT_PROP_DEFENCE_IGNORE_RATIO, true));
|
||||
stats.put("_defence_ignore_delta", new Stat("DEFENCE_IGNORE_DELTA", FightProperty.FIGHT_PROP_DEFENCE_IGNORE_DELTA, true));
|
||||
stats.put("_fire_add_hurt", new Stat("FIRE_ADD_HURT", FightProperty.FIGHT_PROP_FIRE_ADD_HURT, true));
|
||||
stats.put("_elec_add_hurt", new Stat("ELEC_ADD_HURT", FightProperty.FIGHT_PROP_ELEC_ADD_HURT, true));
|
||||
stats.put("_water_add_hurt", new Stat("WATER_ADD_HURT", FightProperty.FIGHT_PROP_WATER_ADD_HURT, true));
|
||||
stats.put("_grass_add_hurt", new Stat("GRASS_ADD_HURT", FightProperty.FIGHT_PROP_GRASS_ADD_HURT, true));
|
||||
stats.put("_wind_add_hurt", new Stat("WIND_ADD_HURT", FightProperty.FIGHT_PROP_WIND_ADD_HURT, true));
|
||||
stats.put("_rock_add_hurt", new Stat("ROCK_ADD_HURT", FightProperty.FIGHT_PROP_ROCK_ADD_HURT, true));
|
||||
stats.put("_ice_add_hurt", new Stat("ICE_ADD_HURT", FightProperty.FIGHT_PROP_ICE_ADD_HURT, true));
|
||||
stats.put("_hit_head_add_hurt", new Stat("HIT_HEAD_ADD_HURT", FightProperty.FIGHT_PROP_HIT_HEAD_ADD_HURT, true));
|
||||
stats.put("_fire_sub_hurt", new Stat("FIRE_SUB_HURT", FightProperty.FIGHT_PROP_FIRE_SUB_HURT, true));
|
||||
stats.put("_elec_sub_hurt", new Stat("ELEC_SUB_HURT", FightProperty.FIGHT_PROP_ELEC_SUB_HURT, true));
|
||||
stats.put("_water_sub_hurt", new Stat("WATER_SUB_HURT", FightProperty.FIGHT_PROP_WATER_SUB_HURT, true));
|
||||
stats.put("_grass_sub_hurt", new Stat("GRASS_SUB_HURT", FightProperty.FIGHT_PROP_GRASS_SUB_HURT, true));
|
||||
stats.put("_wind_sub_hurt", new Stat("WIND_SUB_HURT", FightProperty.FIGHT_PROP_WIND_SUB_HURT, true));
|
||||
stats.put("_rock_sub_hurt", new Stat("ROCK_SUB_HURT", FightProperty.FIGHT_PROP_ROCK_SUB_HURT, true));
|
||||
stats.put("_ice_sub_hurt", new Stat("ICE_SUB_HURT", FightProperty.FIGHT_PROP_ICE_SUB_HURT, true));
|
||||
stats.put("_effect_hit", new Stat("EFFECT_HIT", FightProperty.FIGHT_PROP_EFFECT_HIT, true));
|
||||
stats.put("_effect_resist", new Stat("EFFECT_RESIST", FightProperty.FIGHT_PROP_EFFECT_RESIST, true));
|
||||
stats.put("_freeze_resist", new Stat("FREEZE_RESIST", FightProperty.FIGHT_PROP_FREEZE_RESIST, true));
|
||||
stats.put("_torpor_resist", new Stat("TORPOR_RESIST", FightProperty.FIGHT_PROP_TORPOR_RESIST, true));
|
||||
stats.put("_dizzy_resist", new Stat("DIZZY_RESIST", FightProperty.FIGHT_PROP_DIZZY_RESIST, true));
|
||||
stats.put("_freeze_shorten", new Stat("FREEZE_SHORTEN", FightProperty.FIGHT_PROP_FREEZE_SHORTEN, true));
|
||||
stats.put("_torpor_shorten", new Stat("TORPOR_SHORTEN", FightProperty.FIGHT_PROP_TORPOR_SHORTEN, true));
|
||||
stats.put("_dizzy_shorten", new Stat("DIZZY_SHORTEN", FightProperty.FIGHT_PROP_DIZZY_SHORTEN, true));
|
||||
stats.put("_max_fire_energy", new Stat("MAX_FIRE_ENERGY", FightProperty.FIGHT_PROP_MAX_FIRE_ENERGY, true));
|
||||
stats.put("_max_elec_energy", new Stat("MAX_ELEC_ENERGY", FightProperty.FIGHT_PROP_MAX_ELEC_ENERGY, true));
|
||||
stats.put("_max_water_energy", new Stat("MAX_WATER_ENERGY", FightProperty.FIGHT_PROP_MAX_WATER_ENERGY, true));
|
||||
stats.put("_max_grass_energy", new Stat("MAX_GRASS_ENERGY", FightProperty.FIGHT_PROP_MAX_GRASS_ENERGY, true));
|
||||
stats.put("_max_wind_energy", new Stat("MAX_WIND_ENERGY", FightProperty.FIGHT_PROP_MAX_WIND_ENERGY, true));
|
||||
stats.put("_max_ice_energy", new Stat("MAX_ICE_ENERGY", FightProperty.FIGHT_PROP_MAX_ICE_ENERGY, true));
|
||||
stats.put("_max_rock_energy", new Stat("MAX_ROCK_ENERGY", FightProperty.FIGHT_PROP_MAX_ROCK_ENERGY, true));
|
||||
stats.put("_skill_cd_minus_ratio", new Stat("SKILL_CD_MINUS_RATIO", FightProperty.FIGHT_PROP_SKILL_CD_MINUS_RATIO, true));
|
||||
stats.put("_shield_cost_minus_ratio", new Stat("SHIELD_COST_MINUS_RATIO", FightProperty.FIGHT_PROP_SHIELD_COST_MINUS_RATIO, true));
|
||||
stats.put("_cur_fire_energy", new Stat("CUR_FIRE_ENERGY", FightProperty.FIGHT_PROP_CUR_FIRE_ENERGY, false));
|
||||
stats.put("_cur_elec_energy", new Stat("CUR_ELEC_ENERGY", FightProperty.FIGHT_PROP_CUR_ELEC_ENERGY, false));
|
||||
stats.put("_cur_water_energy", new Stat("CUR_WATER_ENERGY", FightProperty.FIGHT_PROP_CUR_WATER_ENERGY, false));
|
||||
stats.put("_cur_grass_energy", new Stat("CUR_GRASS_ENERGY", FightProperty.FIGHT_PROP_CUR_GRASS_ENERGY, false));
|
||||
stats.put("_cur_wind_energy", new Stat("CUR_WIND_ENERGY", FightProperty.FIGHT_PROP_CUR_WIND_ENERGY, false));
|
||||
stats.put("_cur_ice_energy", new Stat("CUR_ICE_ENERGY", FightProperty.FIGHT_PROP_CUR_ICE_ENERGY, false));
|
||||
stats.put("_cur_rock_energy", new Stat("CUR_ROCK_ENERGY", FightProperty.FIGHT_PROP_CUR_ROCK_ENERGY, false));
|
||||
stats.put("_cur_hp", new Stat("CUR_HP", FightProperty.FIGHT_PROP_CUR_HP, false));
|
||||
stats.put("_max_hp", new Stat("MAX_HP", FightProperty.FIGHT_PROP_MAX_HP, false));
|
||||
stats.put("_cur_attack", new Stat("CUR_ATTACK", FightProperty.FIGHT_PROP_CUR_ATTACK, false));
|
||||
stats.put("_cur_defense", new Stat("CUR_DEFENSE", FightProperty.FIGHT_PROP_CUR_DEFENSE, false));
|
||||
stats.put("_cur_speed", new Stat("CUR_SPEED", FightProperty.FIGHT_PROP_CUR_SPEED, true));
|
||||
stats.put("_nonextra_attack", new Stat("NONEXTRA_ATTACK", FightProperty.FIGHT_PROP_NONEXTRA_ATTACK, true));
|
||||
stats.put("_nonextra_defense", new Stat("NONEXTRA_DEFENSE", FightProperty.FIGHT_PROP_NONEXTRA_DEFENSE, true));
|
||||
stats.put("_nonextra_critical", new Stat("NONEXTRA_CRITICAL", FightProperty.FIGHT_PROP_NONEXTRA_CRITICAL, true));
|
||||
stats.put("_nonextra_anti_critical", new Stat("NONEXTRA_ANTI_CRITICAL", FightProperty.FIGHT_PROP_NONEXTRA_ANTI_CRITICAL, true));
|
||||
stats.put("_nonextra_critical_hurt", new Stat("NONEXTRA_CRITICAL_HURT", FightProperty.FIGHT_PROP_NONEXTRA_CRITICAL_HURT, true));
|
||||
stats.put("_nonextra_charge_efficiency", new Stat("NONEXTRA_CHARGE_EFFICIENCY", FightProperty.FIGHT_PROP_NONEXTRA_CHARGE_EFFICIENCY, true));
|
||||
stats.put("_nonextra_element_mastery", new Stat("NONEXTRA_ELEMENT_MASTERY", FightProperty.FIGHT_PROP_NONEXTRA_ELEMENT_MASTERY, true));
|
||||
stats.put("_nonextra_physical_sub_hurt", new Stat("NONEXTRA_PHYSICAL_SUB_HURT", FightProperty.FIGHT_PROP_NONEXTRA_PHYSICAL_SUB_HURT, true));
|
||||
stats.put("_nonextra_fire_add_hurt", new Stat("NONEXTRA_FIRE_ADD_HURT", FightProperty.FIGHT_PROP_NONEXTRA_FIRE_ADD_HURT, true));
|
||||
stats.put("_nonextra_elec_add_hurt", new Stat("NONEXTRA_ELEC_ADD_HURT", FightProperty.FIGHT_PROP_NONEXTRA_ELEC_ADD_HURT, true));
|
||||
stats.put("_nonextra_water_add_hurt", new Stat("NONEXTRA_WATER_ADD_HURT", FightProperty.FIGHT_PROP_NONEXTRA_WATER_ADD_HURT, true));
|
||||
stats.put("_nonextra_grass_add_hurt", new Stat("NONEXTRA_GRASS_ADD_HURT", FightProperty.FIGHT_PROP_NONEXTRA_GRASS_ADD_HURT, true));
|
||||
stats.put("_nonextra_wind_add_hurt", new Stat("NONEXTRA_WIND_ADD_HURT", FightProperty.FIGHT_PROP_NONEXTRA_WIND_ADD_HURT, true));
|
||||
stats.put("_nonextra_rock_add_hurt", new Stat("NONEXTRA_ROCK_ADD_HURT", FightProperty.FIGHT_PROP_NONEXTRA_ROCK_ADD_HURT, true));
|
||||
stats.put("_nonextra_ice_add_hurt", new Stat("NONEXTRA_ICE_ADD_HURT", FightProperty.FIGHT_PROP_NONEXTRA_ICE_ADD_HURT, true));
|
||||
stats.put("_nonextra_fire_sub_hurt", new Stat("NONEXTRA_FIRE_SUB_HURT", FightProperty.FIGHT_PROP_NONEXTRA_FIRE_SUB_HURT, true));
|
||||
stats.put("_nonextra_elec_sub_hurt", new Stat("NONEXTRA_ELEC_SUB_HURT", FightProperty.FIGHT_PROP_NONEXTRA_ELEC_SUB_HURT, true));
|
||||
stats.put("_nonextra_water_sub_hurt", new Stat("NONEXTRA_WATER_SUB_HURT", FightProperty.FIGHT_PROP_NONEXTRA_WATER_SUB_HURT, true));
|
||||
stats.put("_nonextra_grass_sub_hurt", new Stat("NONEXTRA_GRASS_SUB_HURT", FightProperty.FIGHT_PROP_NONEXTRA_GRASS_SUB_HURT, true));
|
||||
stats.put("_nonextra_wind_sub_hurt", new Stat("NONEXTRA_WIND_SUB_HURT", FightProperty.FIGHT_PROP_NONEXTRA_WIND_SUB_HURT, true));
|
||||
stats.put("_nonextra_rock_sub_hurt", new Stat("NONEXTRA_ROCK_SUB_HURT", FightProperty.FIGHT_PROP_NONEXTRA_ROCK_SUB_HURT, true));
|
||||
stats.put("_nonextra_ice_sub_hurt", new Stat("NONEXTRA_ICE_SUB_HURT", FightProperty.FIGHT_PROP_NONEXTRA_ICE_SUB_HURT, true));
|
||||
stats.put("_nonextra_skill_cd_minus_ratio", new Stat("NONEXTRA_SKILL_CD_MINUS_RATIO", FightProperty.FIGHT_PROP_NONEXTRA_SKILL_CD_MINUS_RATIO, true));
|
||||
stats.put("_nonextra_shield_cost_minus_ratio", new Stat("NONEXTRA_SHIELD_COST_MINUS_RATIO", FightProperty.FIGHT_PROP_NONEXTRA_SHIELD_COST_MINUS_RATIO, true));
|
||||
stats.put("_nonextra_physical_add_hurt", new Stat("NONEXTRA_PHYSICAL_ADD_HURT", FightProperty.FIGHT_PROP_NONEXTRA_PHYSICAL_ADD_HURT, true));
|
||||
for (FightProperty prop : FightProperty.values()) {
|
||||
String name = prop.toString().substring(10); // FIGHT_PROP_BASE_HP -> _BASE_HP
|
||||
String key = name.toLowerCase(); // _BASE_HP -> _base_hp
|
||||
name = name.substring(1); // _BASE_HP -> BASE_HP
|
||||
this.stats.put(key, new Stat(name, prop));
|
||||
}
|
||||
|
||||
// Compatibility aliases
|
||||
this.stats.put("mhp", this.stats.get("maxhp"));
|
||||
this.stats.put("hp", new Stat(FightProperty.FIGHT_PROP_CUR_HP)); // Overrides FIGHT_PROP_HP
|
||||
this.stats.put("atk", new Stat(FightProperty.FIGHT_PROP_CUR_ATTACK)); // Overrides FIGHT_PROP_ATTACK
|
||||
this.stats.put("atkb", new Stat(FightProperty.FIGHT_PROP_BASE_ATTACK)); // This doesn't seem to get used to recalculate ATK, so it's only useful for stuff like Bennett's buff.
|
||||
this.stats.put("eanemo", this.stats.get("anemo%"));
|
||||
this.stats.put("ecryo", this.stats.get("cryo%"));
|
||||
this.stats.put("edendro", this.stats.get("dendro%"));
|
||||
this.stats.put("edend", this.stats.get("dendro%"));
|
||||
this.stats.put("eelectro", this.stats.get("electro%"));
|
||||
this.stats.put("eelec", this.stats.get("electro%"));
|
||||
this.stats.put("ethunder", this.stats.get("electro%"));
|
||||
this.stats.put("egeo", this.stats.get("geo%"));
|
||||
this.stats.put("ehydro", this.stats.get("hydro%"));
|
||||
this.stats.put("epyro", this.stats.get("pyro%"));
|
||||
this.stats.put("ephys", this.stats.get("phys%"));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -206,8 +96,8 @@ public final class SetStatsCommand implements CommandHandler {
|
||||
Stat stat = stats.get(statStr);
|
||||
entity.setFightProperty(stat.prop, value);
|
||||
entity.getWorld().broadcastPacket(new PacketEntityFightPropUpdateNotify(entity, stat.prop));
|
||||
if (stat.percent) {
|
||||
valueStr = String.format("%.1f%%", value*100f);
|
||||
if (FightProperty.isPercentage(stat.prop)) {
|
||||
valueStr = String.format("%.1f%%", value * 100f);
|
||||
} else {
|
||||
valueStr = String.format("%.0f", value);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user