mirror of
https://github.com/Melledy/Nebula.git
synced 2025-12-22 09:14:35 +01:00
Implement !autobuild command
The `!autobuild` (or `!ab`) command allows you to build a record without needing to add every id. Missing trekkers/discs/potentials/melodies will be auto selected by the server. Usage: `!autobuild [character/disc/potential/melody ids...] lv[target record level] s[target record score]` Examples: `!autobuild s99999` = Creates a record with a random main trekker with the max score. `!autobuild 103 lv30` = Creates a record with this trekker at record rank 30. `!autobuild 155 132 107 s25000` = Creates a record with these trekkers with a record score of about 25000. `!autobuild 103 510301 510302 510303 510304 lv20` = Creates a record with this trekker and these potentials at record rank 20. Notes: - Target level overrides target score. So a command of `!autobuild lv30 s1000` would have a record rank of 30 and NOT a score of 1000. - If there is no target level or score, the command will default to a target level of 40. - You can only add trekkers/discs that you own.
This commit is contained in:
@@ -47,6 +47,10 @@ public class GameConstants {
|
|||||||
public static final int CHARACTER_MAX_GEM_PRESETS = 3;
|
public static final int CHARACTER_MAX_GEM_PRESETS = 3;
|
||||||
public static final int CHARACTER_MAX_GEM_SLOTS = 3;
|
public static final int CHARACTER_MAX_GEM_SLOTS = 3;
|
||||||
|
|
||||||
|
public static final int CHARACTER_TAG_VANGUARD = 101;
|
||||||
|
public static final int CHARACTER_TAG_VERSATILE = 102;
|
||||||
|
public static final int CHARACTER_TAG_SUPPORT = 103;
|
||||||
|
|
||||||
public static final int MAX_FORMATIONS = 6;
|
public static final int MAX_FORMATIONS = 6;
|
||||||
public static final int MAX_SHOWCASE_IDS = 5;
|
public static final int MAX_SHOWCASE_IDS = 5;
|
||||||
|
|
||||||
|
|||||||
443
src/main/java/emu/nebula/command/commands/AutoBuildCommand.java
Normal file
443
src/main/java/emu/nebula/command/commands/AutoBuildCommand.java
Normal file
@@ -0,0 +1,443 @@
|
|||||||
|
package emu.nebula.command.commands;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import emu.nebula.GameConstants;
|
||||||
|
import emu.nebula.command.Command;
|
||||||
|
import emu.nebula.command.CommandArgs;
|
||||||
|
import emu.nebula.command.CommandHandler;
|
||||||
|
import emu.nebula.command.commands.BuildCommand.StarTowerBuildData;
|
||||||
|
import emu.nebula.data.GameData;
|
||||||
|
import emu.nebula.game.character.GameCharacter;
|
||||||
|
import emu.nebula.game.character.GameDisc;
|
||||||
|
import emu.nebula.game.inventory.ItemParamMap;
|
||||||
|
import emu.nebula.net.NetMsgId;
|
||||||
|
import emu.nebula.util.Utils;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||||
|
|
||||||
|
@Command(
|
||||||
|
label = "autobuild",
|
||||||
|
aliases = {"ab"},
|
||||||
|
permission = "player.build",
|
||||||
|
requireTarget = true,
|
||||||
|
desc = "!autobuild [character/disc/potential/melody ids...] lv[target record level] s[target record score] = Generates a record for the player with the target score/record level"
|
||||||
|
)
|
||||||
|
public class AutoBuildCommand implements CommandHandler {
|
||||||
|
private static final int[] COMMON_SUB_NOTE_SKILLS = new int[] {
|
||||||
|
90011, 90012, 90013, 90014, 90015, 90016, 90017
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String execute(CommandArgs args) {
|
||||||
|
// Create record
|
||||||
|
var target = args.getTarget();
|
||||||
|
var builder = new StarTowerBuildData(target);
|
||||||
|
|
||||||
|
// Parse items
|
||||||
|
for (String arg : args.getList()) {
|
||||||
|
int id = Utils.parseSafeInt(arg);
|
||||||
|
int count = 1;
|
||||||
|
|
||||||
|
builder.parseItem(id, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.getMap() != null) {
|
||||||
|
for (var entry : args.getMap().int2IntEntrySet()) {
|
||||||
|
int id = entry.getIntKey();
|
||||||
|
int count = entry.getIntValue();
|
||||||
|
|
||||||
|
builder.parseItem(id, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove extra characters/discs
|
||||||
|
while (builder.getCharacters().size() > 3) {
|
||||||
|
builder.getCharacters().removeLast();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (builder.getDiscs().size() > 6) {
|
||||||
|
builder.getDiscs().removeLast();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add random characters/discs
|
||||||
|
if (builder.getCharacters().size() < 3) {
|
||||||
|
int count = 3 - builder.getCharacters().size();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
this.pickRandomCharacter(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (builder.getCharacters().size() < 3) {
|
||||||
|
return "Error: Not enough trekkers in the record";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (builder.getDiscs().size() < 6) {
|
||||||
|
int count = 6 - builder.getDiscs().size();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
this.pickRandomDisc(builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get target score
|
||||||
|
int targetScore = 0;
|
||||||
|
int targetLevel = 0;
|
||||||
|
|
||||||
|
if (args.getSkill() < 0) {
|
||||||
|
targetLevel = 40;
|
||||||
|
} else {
|
||||||
|
targetScore = args.getSkill();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.getLevel() > 0) {
|
||||||
|
// Target level overrides target score.
|
||||||
|
targetLevel = args.getLevel();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetLevel > 0) {
|
||||||
|
var data = GameData.getStarTowerBuildRankDataTable().get(targetLevel);
|
||||||
|
if (data != null) {
|
||||||
|
targetScore = data.getMinGrade();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pick random potentials and sub notes
|
||||||
|
this.generate(builder, targetScore);
|
||||||
|
|
||||||
|
// Create record
|
||||||
|
var build = builder.toBuild();
|
||||||
|
|
||||||
|
// Add to star tower manager
|
||||||
|
target.getStarTowerManager().addBuild(build);
|
||||||
|
|
||||||
|
// Send package to player
|
||||||
|
target.addNextPackage(NetMsgId.st_import_build_notify, build.toProto());
|
||||||
|
|
||||||
|
// Send result to player
|
||||||
|
String result = "Generated record for " + target.getName();
|
||||||
|
|
||||||
|
if (args.getSender() == null) {
|
||||||
|
result += " (This command may take time to update on the client)";
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pickRandomCharacter(StarTowerBuildData builder) {
|
||||||
|
// Random list
|
||||||
|
var list = new ArrayList<GameCharacter>();
|
||||||
|
|
||||||
|
// Create list of possible characters to add
|
||||||
|
var characters = builder.getPlayer().getCharacters().getCharacterCollection()
|
||||||
|
.stream()
|
||||||
|
.filter(c -> !builder.getCharacters().contains(c))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
// Check if record is empty
|
||||||
|
if (builder.getCharacters().isEmpty()) {
|
||||||
|
// Get random vanguard trekker
|
||||||
|
for (var character : characters) {
|
||||||
|
if (character.getData().getDes().getTag().contains(GameConstants.CHARACTER_TAG_VANGUARD)) {
|
||||||
|
list.add(character);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add any trekker if we dont have any vanguard trekkers
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
list.addAll(characters);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Get element of main trekker
|
||||||
|
var main = builder.getCharacters().get(0);
|
||||||
|
var element = main.getElementType();
|
||||||
|
|
||||||
|
// Get trekkers of the same element
|
||||||
|
for (var character : characters) {
|
||||||
|
if (character.getData().getElementType() == element) {
|
||||||
|
list.add(character);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add any trekker if we dont have any trekkers of the same element
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
list.addAll(characters);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shuffle list to make it random
|
||||||
|
Collections.shuffle(list);
|
||||||
|
|
||||||
|
// Add first support trekker we find
|
||||||
|
for (var character : list) {
|
||||||
|
if (character.getData().getDes().getTag().contains(GameConstants.CHARACTER_TAG_SUPPORT)) {
|
||||||
|
builder.getCharacters().add(character);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have no support trekkers, then we look for versatile trekkers
|
||||||
|
for (var character : list) {
|
||||||
|
if (character.getData().getDes().getTag().contains(GameConstants.CHARACTER_TAG_VERSATILE)) {
|
||||||
|
builder.getCharacters().add(character);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add random trekker from list
|
||||||
|
if (list.size() > 0) {
|
||||||
|
builder.getCharacters().add(Utils.randomElement(list));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pickRandomDisc(StarTowerBuildData builder) {
|
||||||
|
// Get element of main trekker
|
||||||
|
var main = builder.getCharacters().get(0);
|
||||||
|
var element = main.getElementType();
|
||||||
|
|
||||||
|
// Random list
|
||||||
|
var list = new ArrayList<GameDisc>();
|
||||||
|
|
||||||
|
// Create list of possible discs to add
|
||||||
|
var discs = builder.getPlayer().getCharacters().getDiscCollection()
|
||||||
|
.stream()
|
||||||
|
.filter(d -> !builder.getDiscs().contains(d))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
// Get discs of the same element
|
||||||
|
for (var disc : discs) {
|
||||||
|
if (disc.getData().getElementType() == element) {
|
||||||
|
list.add(disc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
list.addAll(discs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// End early if list is still empty
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shuffle list to make it random
|
||||||
|
Collections.shuffle(list);
|
||||||
|
|
||||||
|
// Find random disc
|
||||||
|
for (var disc : list) {
|
||||||
|
var item = GameData.getItemDataTable().get(disc.getDiscId());
|
||||||
|
if (item.getRarity() == 1) {
|
||||||
|
builder.getDiscs().add(disc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var disc : list) {
|
||||||
|
var item = GameData.getItemDataTable().get(disc.getDiscId());
|
||||||
|
if (item.getRarity() == 2) {
|
||||||
|
builder.getDiscs().add(disc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Just add the first disc that we can find
|
||||||
|
builder.getDiscs().add(list.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generate(StarTowerBuildData builder, int targetScore) {
|
||||||
|
// Get possible sub notes
|
||||||
|
int subNoteScore = (int) (targetScore * .4D);
|
||||||
|
|
||||||
|
// Get possible drops
|
||||||
|
var drops = new IntArrayList();
|
||||||
|
|
||||||
|
for (var character : builder.getCharacters()) {
|
||||||
|
var element = character.getData().getElementType();
|
||||||
|
|
||||||
|
if (element.getSubNoteSkillItemId() == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!drops.contains(element.getSubNoteSkillItemId())) {
|
||||||
|
drops.add(element.getSubNoteSkillItemId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var disc : builder.getDiscs()) {
|
||||||
|
var element = disc.getData().getElementType();
|
||||||
|
|
||||||
|
if (element.getSubNoteSkillItemId() == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!drops.contains(element.getSubNoteSkillItemId())) {
|
||||||
|
drops.add(element.getSubNoteSkillItemId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int id : COMMON_SUB_NOTE_SKILLS) {
|
||||||
|
drops.add(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Randomize sub note ids
|
||||||
|
Collections.shuffle(drops);
|
||||||
|
|
||||||
|
// Distribute sub notes randomly
|
||||||
|
int amount = (int) Math.ceil(subNoteScore / 15D);
|
||||||
|
int totalSubNotes = amount;
|
||||||
|
|
||||||
|
// Allocate budget for each sub note
|
||||||
|
var budget = new ItemParamMap();
|
||||||
|
double totalValue = 0;
|
||||||
|
|
||||||
|
for (int subNote : drops) {
|
||||||
|
int value = Utils.randomRange(1, 10);
|
||||||
|
budget.add(subNote, value);
|
||||||
|
totalValue += value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add random sub notes
|
||||||
|
for (int subNote : drops) {
|
||||||
|
// Get budgeted value
|
||||||
|
int value = budget.get(subNote);
|
||||||
|
int count = (int) Math.ceil((value / totalValue) * totalSubNotes);
|
||||||
|
|
||||||
|
// Get current sub notes
|
||||||
|
int cur = builder.getBuild().getSubNoteSkills().get(subNote);
|
||||||
|
int max = Math.max(99 - cur, 0);
|
||||||
|
|
||||||
|
// Clamp
|
||||||
|
count = Math.min(Math.min(count, amount), max);
|
||||||
|
amount -= count;
|
||||||
|
|
||||||
|
// Add sub notes
|
||||||
|
builder.getBuild().getSubNoteSkills().add(subNote, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add leftover sub notes
|
||||||
|
if (amount > 0) {
|
||||||
|
// Randomize again
|
||||||
|
Collections.shuffle(drops);
|
||||||
|
|
||||||
|
// Add to first sub note that has less than 99
|
||||||
|
for (int subNote : drops) {
|
||||||
|
// End if we have no more sub notes to give
|
||||||
|
if (amount <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get current sub notes
|
||||||
|
int cur = builder.getBuild().getSubNoteSkills().get(subNote);
|
||||||
|
if (cur >= 99) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add
|
||||||
|
int count = Math.min(99 - cur, amount);
|
||||||
|
amount -= count;
|
||||||
|
|
||||||
|
builder.getBuild().getSubNoteSkills().add(subNote, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calcluate score
|
||||||
|
builder.toBuild().calculateScore();
|
||||||
|
|
||||||
|
// Get target potential score
|
||||||
|
int potentialScore = Math.max(targetScore - builder.getBuild().getScore(), 0);
|
||||||
|
|
||||||
|
// Init weighted list of characters
|
||||||
|
var characters = new ArrayList<GameCharacter>();
|
||||||
|
|
||||||
|
characters.add(builder.getCharacters().get(0));
|
||||||
|
characters.add(builder.getCharacters().get(0)); // Main character gets an extra chance to get more potentials
|
||||||
|
characters.add(builder.getCharacters().get(1));
|
||||||
|
characters.add(builder.getCharacters().get(2));
|
||||||
|
|
||||||
|
Collections.shuffle(characters);
|
||||||
|
|
||||||
|
// Get current amount of special potentials
|
||||||
|
var specialCounter = new ItemParamMap();
|
||||||
|
|
||||||
|
for (var entry : builder.getBuild().getPotentials()) {
|
||||||
|
var potential = GameData.getPotentialDataTable().get(entry.getIntKey());
|
||||||
|
if (potential == null) continue;
|
||||||
|
|
||||||
|
if (potential.isSpecial()) {
|
||||||
|
specialCounter.add(potential.getCharId(), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache main trekker
|
||||||
|
var main = builder.getCharacters().get(0);
|
||||||
|
|
||||||
|
// Get random potentials
|
||||||
|
while (potentialScore > 0) {
|
||||||
|
// End
|
||||||
|
if (potentialScore <= 0 || characters.isEmpty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get random character
|
||||||
|
var character = Utils.randomElement(characters);
|
||||||
|
|
||||||
|
// Get character potential data
|
||||||
|
var data = GameData.getCharPotentialDataTable().get(character.getCharId());
|
||||||
|
|
||||||
|
if (data == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we should give a special potential
|
||||||
|
int sp = specialCounter.get(character.getCharId());
|
||||||
|
boolean special = false;
|
||||||
|
|
||||||
|
if (sp < 2 && potentialScore >= 180) {
|
||||||
|
special = Utils.randomChance(.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (special) {
|
||||||
|
specialCounter.add(character.getCharId(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get possible potential list
|
||||||
|
var list = data.getPotentialList(main == character, special);
|
||||||
|
|
||||||
|
// Remove potentials we already have maxed out
|
||||||
|
var potentials = new IntArrayList();
|
||||||
|
|
||||||
|
for (int id : list) {
|
||||||
|
// Get potential data
|
||||||
|
var potential = GameData.getPotentialDataTable().get(id);
|
||||||
|
if (potential == null) continue;
|
||||||
|
|
||||||
|
// Filter out max level ones
|
||||||
|
int curLevel = builder.getBuild().getPotentials().get(id);
|
||||||
|
int maxLevel = potential.getMaxLevel();
|
||||||
|
|
||||||
|
if (curLevel >= maxLevel) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add
|
||||||
|
potentials.add(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove character if we dont have any possible potentials for it
|
||||||
|
if (potentials.isEmpty()) {
|
||||||
|
characters.removeIf(c -> c == character);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get random potential
|
||||||
|
int id = Utils.randomElement(potentials);
|
||||||
|
var potential = GameData.getPotentialDataTable().get(id);
|
||||||
|
|
||||||
|
// Add
|
||||||
|
builder.getBuild().getPotentials().add(id, 1);
|
||||||
|
|
||||||
|
// Decrement score
|
||||||
|
potentialScore -= potential.getBuildScore(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -35,7 +35,7 @@ public class BuildCommand implements CommandHandler {
|
|||||||
int id = Utils.parseSafeInt(arg);
|
int id = Utils.parseSafeInt(arg);
|
||||||
int count = 1;
|
int count = 1;
|
||||||
|
|
||||||
this.parseItem(builder, id, count);
|
builder.parseItem(id, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.getMap() != null) {
|
if (args.getMap() != null) {
|
||||||
@@ -43,7 +43,7 @@ public class BuildCommand implements CommandHandler {
|
|||||||
int id = entry.getIntKey();
|
int id = entry.getIntKey();
|
||||||
int count = entry.getIntValue();
|
int count = entry.getIntValue();
|
||||||
|
|
||||||
this.parseItem(builder, id, count);
|
builder.parseItem(id, count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,55 +66,17 @@ public class BuildCommand implements CommandHandler {
|
|||||||
target.addNextPackage(NetMsgId.st_import_build_notify, build.toProto());
|
target.addNextPackage(NetMsgId.st_import_build_notify, build.toProto());
|
||||||
|
|
||||||
// Send result to player
|
// Send result to player
|
||||||
return "Created record for " + target.getName() + " (This command make take time to update on the client)";
|
String result = "Created record for " + target.getName();
|
||||||
}
|
|
||||||
|
if (args.getSender() == null) {
|
||||||
private void parseItem(StarTowerBuildData builder, int id, int count) {
|
result += " (This command may take time to update on the client)";
|
||||||
// Get item data
|
|
||||||
var itemData = GameData.getItemDataTable().get(id);
|
|
||||||
if (itemData == null) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clamp
|
return result;
|
||||||
count = Math.max(count, 1);
|
|
||||||
|
|
||||||
// Parse by item id
|
|
||||||
switch (itemData.getItemSubType()) {
|
|
||||||
case Char -> {
|
|
||||||
var character = builder.getPlayer().getCharacters().getCharacterById(id);
|
|
||||||
if (character == null || !character.getData().isAvailable()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.addCharacter(character);
|
|
||||||
}
|
|
||||||
case Disc -> {
|
|
||||||
var disc = builder.getPlayer().getCharacters().getDiscById(id);
|
|
||||||
if (disc == null || !disc.getData().isAvailable()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.addDisc(disc);
|
|
||||||
}
|
|
||||||
case Potential, SpecificPotential -> {
|
|
||||||
var potentialData = GameData.getPotentialDataTable().get(id);
|
|
||||||
if (potentialData == null) break;
|
|
||||||
|
|
||||||
int level = Math.min(count, potentialData.getMaxLevel());
|
|
||||||
builder.getBuild().getPotentials().add(id, level);
|
|
||||||
}
|
|
||||||
case SubNoteSkill -> {
|
|
||||||
builder.getBuild().getSubNoteSkills().add(id, count);
|
|
||||||
}
|
|
||||||
default -> {
|
|
||||||
// Ignored
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private static class StarTowerBuildData {
|
public static class StarTowerBuildData {
|
||||||
private Player player;
|
private Player player;
|
||||||
private StarTowerBuild build;
|
private StarTowerBuild build;
|
||||||
private List<GameCharacter> characters;
|
private List<GameCharacter> characters;
|
||||||
@@ -127,6 +89,50 @@ public class BuildCommand implements CommandHandler {
|
|||||||
this.discs = new ArrayList<>();
|
this.discs = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void parseItem(int id, int count) {
|
||||||
|
// Get item data
|
||||||
|
var itemData = GameData.getItemDataTable().get(id);
|
||||||
|
if (itemData == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clamp
|
||||||
|
count = Math.max(count, 1);
|
||||||
|
|
||||||
|
// Parse by item id
|
||||||
|
switch (itemData.getItemSubType()) {
|
||||||
|
case Char -> {
|
||||||
|
var character = this.getPlayer().getCharacters().getCharacterById(id);
|
||||||
|
if (character == null || !character.getData().isAvailable()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addCharacter(character);
|
||||||
|
}
|
||||||
|
case Disc -> {
|
||||||
|
var disc = this.getPlayer().getCharacters().getDiscById(id);
|
||||||
|
if (disc == null || !disc.getData().isAvailable()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addDisc(disc);
|
||||||
|
}
|
||||||
|
case Potential, SpecificPotential -> {
|
||||||
|
var potentialData = GameData.getPotentialDataTable().get(id);
|
||||||
|
if (potentialData == null) break;
|
||||||
|
|
||||||
|
int level = Math.min(count, potentialData.getMaxLevel());
|
||||||
|
this.getBuild().getPotentials().add(id, level);
|
||||||
|
}
|
||||||
|
case SubNoteSkill -> {
|
||||||
|
this.getBuild().getSubNoteSkills().add(id, count);
|
||||||
|
}
|
||||||
|
default -> {
|
||||||
|
// Ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void addCharacter(GameCharacter character) {
|
public void addCharacter(GameCharacter character) {
|
||||||
if (this.characters.contains(character)) {
|
if (this.characters.contains(character)) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package emu.nebula.data.resources;
|
|||||||
|
|
||||||
import emu.nebula.data.BaseDef;
|
import emu.nebula.data.BaseDef;
|
||||||
import emu.nebula.data.ResourceType;
|
import emu.nebula.data.ResourceType;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntList;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@@ -19,4 +21,31 @@ public class CharPotentialDef extends BaseDef {
|
|||||||
public int getId() {
|
public int getId() {
|
||||||
return Id;
|
return Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IntList getPotentialList(boolean main, boolean special) {
|
||||||
|
// Create list
|
||||||
|
var list = new IntArrayList();
|
||||||
|
|
||||||
|
//
|
||||||
|
if (main) {
|
||||||
|
if (special) {
|
||||||
|
list.addElements(0, this.getMasterSpecificPotentialIds());
|
||||||
|
} else {
|
||||||
|
list.addElements(0, this.getMasterNormalPotentialIds());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (special) {
|
||||||
|
list.addElements(0, this.getAssistSpecificPotentialIds());
|
||||||
|
} else {
|
||||||
|
list.addElements(0, this.getAssistNormalPotentialIds());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!special) {
|
||||||
|
list.addElements(0, this.getCommonPotentialIds());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Complete
|
||||||
|
return list;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import lombok.Getter;
|
|||||||
@ResourceType(name = "CharacterDes.json", loadPriority = LoadPriority.LOW)
|
@ResourceType(name = "CharacterDes.json", loadPriority = LoadPriority.LOW)
|
||||||
public class CharacterDesDef extends BaseDef {
|
public class CharacterDesDef extends BaseDef {
|
||||||
private int Id;
|
private int Id;
|
||||||
private int[] Tag;
|
private IntOpenHashSet Tag;
|
||||||
private IntOpenHashSet PreferTags;
|
private IntOpenHashSet PreferTags;
|
||||||
private IntOpenHashSet HateTags;
|
private IntOpenHashSet HateTags;
|
||||||
|
|
||||||
|
|||||||
@@ -22,14 +22,14 @@ public class PotentialDef extends BaseDef {
|
|||||||
return Id;
|
return Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRare() {
|
public boolean isSpecial() {
|
||||||
return this.BranchType != 3;
|
return this.BranchType != 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getMaxLevel() {
|
public int getMaxLevel() {
|
||||||
// Check if regular potential
|
// Check if regular potential
|
||||||
if (this.BranchType == 3) {
|
if (this.BranchType == 3) {
|
||||||
return this.BuildScore.length;
|
return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special potential should always have a max level of 1
|
// Special potential should always have a max level of 1
|
||||||
|
|||||||
@@ -421,7 +421,7 @@ public class StarTowerGame {
|
|||||||
this.getPotentials().put(id, nextLevel);
|
this.getPotentials().put(id, nextLevel);
|
||||||
|
|
||||||
// Add to rare potential count
|
// Add to rare potential count
|
||||||
if (potentialData.isRare()) {
|
if (potentialData.isSpecial()) {
|
||||||
this.getRarePotentialCount().add(potentialData.getCharId(), 1);
|
this.getRarePotentialCount().add(potentialData.getCharId(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,46 +574,26 @@ public class StarTowerGame {
|
|||||||
/**
|
/**
|
||||||
* Creates a potential selector for the specified character
|
* Creates a potential selector for the specified character
|
||||||
*/
|
*/
|
||||||
public StarTowerPotentialCase createPotentialSelector(int charId, boolean rare) {
|
public StarTowerPotentialCase createPotentialSelector(int charId, boolean special) {
|
||||||
// Check character id
|
// Check character id
|
||||||
if (charId <= 0) {
|
if (charId <= 0) {
|
||||||
charId = this.getRandomCharId();
|
charId = this.getRandomCharId();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure character can't have more than 2 rare potentials
|
// Make sure character can't have more than 2 rare potentials
|
||||||
if (rare && this.getRarePotentialCount(charId) >= 2) {
|
if (special && this.getRarePotentialCount(charId) >= 2) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get character potentials
|
// Get character potentials
|
||||||
var data = GameData.getCharPotentialDataTable().get(charId);
|
var data = GameData.getCharPotentialDataTable().get(charId);
|
||||||
|
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Random potentials list
|
// Random potentials list
|
||||||
var list = new IntArrayList();
|
var list = data.getPotentialList(this.getCharIds()[0] == charId, special);
|
||||||
|
|
||||||
// Add potentials based on character role
|
|
||||||
boolean isMainCharacter = this.getCharIds()[0] == charId;
|
|
||||||
|
|
||||||
if (isMainCharacter) {
|
|
||||||
if (rare) {
|
|
||||||
list.addElements(0, data.getMasterSpecificPotentialIds());
|
|
||||||
} else {
|
|
||||||
list.addElements(0, data.getMasterNormalPotentialIds());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (rare) {
|
|
||||||
list.addElements(0, data.getAssistSpecificPotentialIds());
|
|
||||||
} else {
|
|
||||||
list.addElements(0, data.getAssistNormalPotentialIds());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rare) {
|
|
||||||
list.addElements(0, data.getCommonPotentialIds());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove potentials we already have maxed out
|
// Remove potentials we already have maxed out
|
||||||
var potentials = new IntArrayList();
|
var potentials = new IntArrayList();
|
||||||
@@ -674,7 +654,7 @@ public class StarTowerGame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Creator potential selector case
|
// Creator potential selector case
|
||||||
if (rare) {
|
if (special) {
|
||||||
return new StarTowerSelectSpecialPotentialCase(this, charId, selector);
|
return new StarTowerSelectSpecialPotentialCase(this, charId, selector);
|
||||||
} else {
|
} else {
|
||||||
return new StarTowerPotentialCase(this, charId, selector);
|
return new StarTowerPotentialCase(this, charId, selector);
|
||||||
|
|||||||
Reference in New Issue
Block a user