mirror of
https://github.com/Melledy/Nebula.git
synced 2026-09-19 17:19:58 +02:00
Add preset code support to !build and !autobuild
Two new tags have been added for `!autobuild`: "-nonotes"/"-nn" = Prevents generating sub notes "-nopotentials"/"-np" = Prevents generating potentials Example: `!ab lv20 103 -nn` = Generates a level 20 record, but no sub notes will be generated.
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
package emu.nebula.command;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.List;
|
||||
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.data.GameData;
|
||||
import emu.nebula.data.resources.AffinityLevelDef;
|
||||
import emu.nebula.game.character.GameCharacter;
|
||||
import emu.nebula.game.character.GameDisc;
|
||||
@@ -10,6 +13,7 @@ import emu.nebula.game.player.Player;
|
||||
import emu.nebula.util.Utils;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntLinkedOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectSet;
|
||||
import lombok.Getter;
|
||||
@@ -235,4 +239,120 @@ public class CommandArgs {
|
||||
|
||||
return hasChanged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a preset code back into a map of ids
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
public Int2IntMap parsePresetCode(String code) {
|
||||
// Init map
|
||||
var items = new Int2IntOpenHashMap();
|
||||
|
||||
// Decode preset data from base64
|
||||
byte[] data = Utils.base64Decode(code);
|
||||
|
||||
var preset = ByteBuffer.wrap(data);
|
||||
preset.order(ByteOrder.BIG_ENDIAN);
|
||||
|
||||
// Parse character ids
|
||||
int[] charIds = new int[3];
|
||||
try {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int id = preset.getInt();
|
||||
|
||||
charIds[i] = id;
|
||||
items.put(id, 1);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Ignored
|
||||
return null;
|
||||
}
|
||||
|
||||
// Parse potentials
|
||||
try {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
int charId = charIds[i];
|
||||
|
||||
// Get potential data
|
||||
var potentials = GameData.getCharPotentialDataTable().get(charId);
|
||||
if (potentials == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Setup potentials
|
||||
int[] specificPotentialIds;
|
||||
int[] normalPotentialIds;
|
||||
int[] commonPotentialIds = potentials.getCommonPotentialIds();
|
||||
|
||||
// Check if main trekker or not
|
||||
if (i == 1) {
|
||||
specificPotentialIds = potentials.getMasterSpecificPotentialIds();
|
||||
normalPotentialIds = potentials.getMasterNormalPotentialIds();
|
||||
} else {
|
||||
specificPotentialIds = potentials.getAssistSpecificPotentialIds();
|
||||
normalPotentialIds = potentials.getAssistNormalPotentialIds();
|
||||
}
|
||||
|
||||
// Parser
|
||||
int size = (int) Math.ceil((specificPotentialIds.length + (normalPotentialIds.length * 3) + (commonPotentialIds.length * 3)) / 8D);
|
||||
byte[] potentialBytes = new byte[size];
|
||||
preset.get(potentialBytes);
|
||||
var potentialData = new BitReader(potentialBytes);
|
||||
|
||||
// Calculate levels of potentials
|
||||
for (int id : specificPotentialIds) {
|
||||
int level = potentialData.readBits(1);
|
||||
if (level > 0) {
|
||||
items.put(id, level);
|
||||
}
|
||||
}
|
||||
|
||||
for (int id : normalPotentialIds) {
|
||||
int level = potentialData.readBits(3);
|
||||
if (level > 0) {
|
||||
items.put(id, level);
|
||||
}
|
||||
}
|
||||
|
||||
for (int id : commonPotentialIds) {
|
||||
int level = potentialData.readBits(3);
|
||||
if (level > 0) {
|
||||
items.put(id, level);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Ignored
|
||||
return null;
|
||||
}
|
||||
|
||||
// Finished
|
||||
return items;
|
||||
}
|
||||
|
||||
@Getter
|
||||
private static class BitReader {
|
||||
private byte[] bits;
|
||||
private int arrayIndex;
|
||||
private int bitIndex;
|
||||
|
||||
public BitReader(byte[] bits) {
|
||||
this.bits = bits;
|
||||
}
|
||||
|
||||
public int readBits(int count) {
|
||||
int result = 0;
|
||||
for (int i = 0; i < count; i++) {
|
||||
result <<= 1;
|
||||
result |= (this.bits[arrayIndex] >> (7 - bitIndex)) & 1;
|
||||
bitIndex++;
|
||||
if (bitIndex >= 8) {
|
||||
bitIndex = 0;
|
||||
arrayIndex++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ 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(
|
||||
@@ -40,16 +39,19 @@ public class AutoBuildCommand implements CommandHandler {
|
||||
int id = Utils.parseSafeInt(arg);
|
||||
int count = 1;
|
||||
|
||||
builder.parseItem(id, count);
|
||||
if (id != 0) {
|
||||
builder.parseItem(id, count);
|
||||
} else if (!Utils.isNumeric(arg)) {
|
||||
// Might be a preset code
|
||||
var items = args.parsePresetCode(arg);
|
||||
if (items != null) {
|
||||
builder.parseItems(items);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (args.getMap() != null) {
|
||||
for (var entry : args.getMap().int2IntEntrySet()) {
|
||||
int id = entry.getIntKey();
|
||||
int count = entry.getIntValue();
|
||||
|
||||
builder.parseItem(id, count);
|
||||
}
|
||||
builder.parseItems(args.getMap());
|
||||
}
|
||||
|
||||
// Remove extra characters/discs
|
||||
@@ -104,8 +106,27 @@ public class AutoBuildCommand implements CommandHandler {
|
||||
}
|
||||
}
|
||||
|
||||
// Calcluate score
|
||||
builder.toBuild();
|
||||
|
||||
// Pick random potentials and sub notes
|
||||
this.generate(builder, targetScore);
|
||||
boolean shouldGenerateNotes = !args.hasFlag("-nn") && !args.hasFlag("-nonotes");
|
||||
boolean shouldGeneratePotentials = !args.hasFlag("-np") && !args.hasFlag("-nopotentials") ;
|
||||
|
||||
if (shouldGenerateNotes) {
|
||||
int score = Math.max(targetScore - builder.getBuild().getScore(), 0);
|
||||
|
||||
if (shouldGeneratePotentials) {
|
||||
score = (int) (score * .4D);
|
||||
}
|
||||
|
||||
this.generateSubNotes(builder, score);
|
||||
}
|
||||
|
||||
if (shouldGeneratePotentials) {
|
||||
int score = Math.max(targetScore - builder.getBuild().getScore(), 0);
|
||||
this.generatePotentials(builder, score);
|
||||
}
|
||||
|
||||
// Create record
|
||||
var build = builder.toBuild();
|
||||
@@ -246,10 +267,7 @@ public class AutoBuildCommand implements CommandHandler {
|
||||
builder.getDiscs().add(list.get(0));
|
||||
}
|
||||
|
||||
private void generate(StarTowerBuildData builder, int targetScore) {
|
||||
// Get possible sub notes
|
||||
int subNoteScore = (int) (targetScore * .4D);
|
||||
|
||||
private void generateSubNotes(StarTowerBuildData builder, int subNoteScore) {
|
||||
// Get possible drops
|
||||
var drops = new IntArrayList();
|
||||
|
||||
@@ -343,11 +361,10 @@ public class AutoBuildCommand implements CommandHandler {
|
||||
}
|
||||
|
||||
// Calcluate score
|
||||
builder.toBuild().calculateScore();
|
||||
|
||||
// Get target potential score
|
||||
int potentialScore = Math.max(targetScore - builder.getBuild().getScore(), 0);
|
||||
|
||||
builder.toBuild();
|
||||
}
|
||||
|
||||
private void generatePotentials(StarTowerBuildData builder, int potentialScore) {
|
||||
// Init weighted list of characters
|
||||
var characters = new ArrayList<GameCharacter>();
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import emu.nebula.game.player.Player;
|
||||
import emu.nebula.game.tower.StarTowerBuild;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.util.Utils;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import lombok.Getter;
|
||||
|
||||
@Command(
|
||||
@@ -35,16 +36,19 @@ public class BuildCommand implements CommandHandler {
|
||||
int id = Utils.parseSafeInt(arg);
|
||||
int count = 1;
|
||||
|
||||
builder.parseItem(id, count);
|
||||
if (id != 0) {
|
||||
builder.parseItem(id, count);
|
||||
} else if (!Utils.isNumeric(arg)) {
|
||||
// Might be a preset code
|
||||
var items = args.parsePresetCode(arg);
|
||||
if (items != null) {
|
||||
builder.parseItems(items);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (args.getMap() != null) {
|
||||
for (var entry : args.getMap().int2IntEntrySet()) {
|
||||
int id = entry.getIntKey();
|
||||
int count = entry.getIntValue();
|
||||
|
||||
builder.parseItem(id, count);
|
||||
}
|
||||
builder.parseItems(args.getMap());
|
||||
}
|
||||
|
||||
// Check if build is valid
|
||||
@@ -133,6 +137,15 @@ public class BuildCommand implements CommandHandler {
|
||||
}
|
||||
}
|
||||
|
||||
public void parseItems(Int2IntMap items) {
|
||||
for (var entry : items.int2IntEntrySet()) {
|
||||
int id = entry.getIntKey();
|
||||
int count = entry.getIntValue();
|
||||
|
||||
this.parseItem(id, count);
|
||||
}
|
||||
}
|
||||
|
||||
public void addCharacter(GameCharacter character) {
|
||||
if (this.characters.contains(character)) {
|
||||
return;
|
||||
@@ -175,6 +188,9 @@ public class BuildCommand implements CommandHandler {
|
||||
build.getCharPots().add(data.getCharId(), 1);
|
||||
}
|
||||
|
||||
// Reset secondary skills
|
||||
build.refreshSecondarySkills();
|
||||
|
||||
// Calculate score
|
||||
build.calculateScore();
|
||||
|
||||
|
||||
@@ -134,6 +134,10 @@ public class StarTowerBuild implements GameDatabaseObject {
|
||||
this.preference = state;
|
||||
Nebula.getGameDatabase().update(this, this.getUid(), "preference", this.isPreference());
|
||||
}
|
||||
|
||||
public void refreshSecondarySkills() {
|
||||
this.secondarySkills = SecondarySkillDef.calculateSecondarySkills(this.getDiscIds(), this.getSubNoteSkills());
|
||||
}
|
||||
|
||||
// Score
|
||||
|
||||
@@ -161,7 +165,7 @@ public class StarTowerBuild implements GameDatabaseObject {
|
||||
|
||||
// Check secondary skills
|
||||
if (this.getSecondarySkills() == null) {
|
||||
this.secondarySkills = SecondarySkillDef.calculateSecondarySkills(this.getDiscIds(), this.getSubNoteSkills());
|
||||
this.refreshSecondarySkills();
|
||||
}
|
||||
|
||||
// Add score from secondary skills
|
||||
|
||||
@@ -169,6 +169,10 @@ public class Utils {
|
||||
return (int) sum;
|
||||
}
|
||||
|
||||
public static boolean isNumeric(String str) {
|
||||
return str.matches("-?\\d+(\\.\\d+)?");
|
||||
}
|
||||
|
||||
public static double generateRandomDouble() {
|
||||
return ThreadLocalRandom.current().nextDouble();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user