diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index e193c8f..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,14 +0,0 @@ -# These are supported funding model platforms - -custom: ["paypal.me/sydmontague"] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] -patreon: SydMontague - -# github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] -# patreon: # Replace with a single Patreon username -# open_collective: # Replace with a single Open Collective username -# ko_fi: # Replace with a single Ko-fi username -# tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel -# community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry -# liberapay: # Replace with a single Liberapay username -# issuehunt: # Replace with a single IssueHunt username -# otechie: # Replace with a single Otechie username \ No newline at end of file diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index fb20b84..694b2d8 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -83,7 +83,7 @@ jobs: with: name: ${{ matrix.packageName }} path: | - target/Decode-Randomizer.jar + target/Decode-TextMod.jar target/armips${{matrix.executableExtension}} target/3dstex${{matrix.executableExtension}} target/3dstool${{matrix.executableExtension}} diff --git a/.gitignore b/.gitignore index 4d6e1c7..0127ba3 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,7 @@ # Testing stuff config.yml -*.cci \ No newline at end of file +*.cci +/.vscode +/renamingPresets +dependency-reduced-pom.xml diff --git a/README.MD b/README.MD index 315fbd7..0425ff6 100644 --- a/README.MD +++ b/README.MD @@ -1,6 +1,7 @@ -# Digimon World Re:Digitize Decode Randomizer +# Digimon World Re:Digitize Undub/Text Modification Tool +This software allows replacing and modifying strings in the 2013 released 3DS game "Digimon World Re:Digitize Decode". -This software allows randomizing several aspects of the 2013 released 3DS game "Digimon World Re:Digitize Decode". +The main motivation for creating this tool was tool is and was replacing the dub terminology of the game's English translation patch by Operation Decoded, with the original terms. # Usage @@ -10,70 +11,126 @@ Before using this software make sure you * have Java 11 or higher installed * you can download it from [Adoptium](https://adoptium.net/) * have a dumped ROM of the game in .CCI/.3DS or .CIA format - * the ROM can have the English translation patch applied - * other modifications can generally be compatible as well, but success may vary + * the ROM should have the English translation patch applied + * Replacing Japanese text *might* work (untested). * have enough empty disk space for all files created during the randomization - * 5-10 GiB on the drive you installed the randomizer on should suffice + * 5-10 GiB on the drive you installed the textmod tool on should suffice ## Setup -Download the appropriate version for your OS from the [releases tab](https://github.com/SydMontague/DecodeRandomizer/releases) and unpack the downloaded .zip archive in the location you want to install the randomizer at. +Download the appropriate version for your OS from the [releases tab](https://github.com/Thertzlor/DecodeTextMod/releases) and unpack the downloaded .zip archive in the location you want to install the textmod tool at. -Run the `Decode-Randomizer.jar`, press the "Select Base ROM" button and navigate to ROM you want to use as base for the randomizer. -After the ROM has been successfully unpacked you'll be presented with the randomization options. +Run the `Decode-TextMod.jar`, press the "Select Base ROM" button and navigate to ROM you want to use as base for the textmod tool. +After the ROM has been successfully unpacked you'll be presented with the editing options. + +The program starts with the default "undub" preset which replaces localized Digimon names and terms with their original counterparts, so if that's all you want you don't need to change any settings, just hit "Save Changes" which will generate your new rom. + +> [!NOTE] +The replacement process *will* take a while, since it requires opening, editing and re-packing basically every script file in the game, so it might take around ten minutes, depending on your PC. # Current Features -## Randomization - -* Digimon Properties - * Attribute (Vaccine, Virus, Data) - * Sleep Schedule - * Favorite Food - * Base Weight - * Combat Speed - * Training Type - * Size (joke option, might break things) -* Skills and Finisher - * MP Costs - * Power - * Status - * Status Chance - * Cooldown - * Learn Rate -* Evolutions - * Requirements - * Paths - * Statsgains -* Enemies NPCs - * Digimon - * Stats - * Skills - * Drops -* Player character and starter Digimon - * You can also use it to set it to a certain character or Digimon -* Other - * Type Alignments (i.e. X is strong against Y) - * Treasure Hunt items - * map item spawns +## Undub/Text Replacement + +* Fully functioning Undubbing preset. +* Support for user provided renaming presets enabling replacing any term or phrase in the game script. + * Selectors for specific files/lines inside files + * Regex support + * Exclusion patterns and paths. + +### Undub/Editing Settings + +* **`Replace terms in ALL text`** +Replaces the terms of a list such as DigimonNames.csv not just in that list but will also replace it in all general scripts such as NPC dialogue. +* **`use manual CSV`** +Enable this option if you are **not** using the built-in undub replacment, but your own csv replacements via the `renamingPresets` folder. +* **`camelCase names`** +Use the camelCase format for Digimon names such as "WarGreymon" instead of "War Greymon". +* **`Always use 'Black' as prefix`** +The black variant of Agumon is technically called "Agumon (Black)" but with this option its name will be rendered as "BlackAgumon" +* **`Ogremon spelling`** +The undub patch will use the official "Orgemon" spelling by default, this option changes it to the widely used "Ogremon" +* **`Picklemon spelling`** +By default the undub patch will use the spelling "Piccolomon" but if you really like pickles you can enable this option and stick with the official spelling, "Picklemon" + +The two last buttons should only be of interest if you are planning to create your own text editing presets: +* **`Export CSVs for current names`** +Exports the contents of the following files in the currently unpacked ROM into the `renamingPresets` directory: + * AccessoryNames.csv, CardNames1.csv, CardNames2.csv, CardSetNames.csv, CharacterNames.csv, DigimonNames.csv, FinisherNames.csv, GlossaryNames.csv, ItemNames.csv, KeyItemNames.csv, MedalNames.csv, NatureNames.csv, SkillNames.csv +* **`Export CSVs for built-in preset`** +Exports the CSV replacement files for the built-in undub preset into the `renamingPresets` directory, to make it easily usable as a base for custom patches. + -## Patches -* Increased view distance -* Increased movement speed -* Increase skill learning chance from brains training -* Start with 5 MP Discs instead of Meat - * to help with running out of MP in the first fight -* add 19 previously unobtainable Digimon to the roster +## Name Randomization +This feature, which is disabled by default, is basically a silly tribute to the fact that this is forked from a randomizer tool. + +The names of... +* Digimon +* Finisher +* Skills +* Characters +* Items +* Medals + +Can be randomized, so you can have some silly playthrough where you never know which item actually does what and who is who. + +Each category can be toggled separately. ## Known Issues / Caveats -Certain seed/settings combinations might be unplayable, for example if your starting move is too weak/expensive or if your Digimon is scaled too large to be able to hit. -Use another seed or disable the respective settings to solve this. +There are some parts of the replacement logic such as the functionality adjusting articles, that generally assume English grammar. + +# Text Replacement Format +> [!NOTE] +This information is only relevant if you wish to create your own text replacement presets. +It also assumes assumes that you have already extracted the game's script data into CSV. + +To create your own replacement patch simply create a folder in the same directory as the TextMod tool called `renamingPresets` containing replacement files provided in utf8 encoded csv files. + +## Naming +Each file in the folder, [except for a number of special cases](#special-files), targets one of the game's script files based on its name, which is converted into a path: + +`keep-15.csv` will target the file `Keep\languageKeep.res\btx_15.csv`. +`map-text-are_npc353_text-1` will target the file `map\text\are_npc353_text.pack\btx_1.csv` + +... and so on. +## CSV Structure +The CSV structure in each file consists of the following columns: +`index;original;replace;excludeTerms;excludePaths` + +If a value for the `index` column is provided, a *targeted replacment*, the entire line the index points to will be replaced with the content of the `replace` column. In this mode the 'original' column only serves a visual hint when creating the patch. + +If the index is provided as `0`, a *general replacement*, all instances of the string in the `original` column are replaced with the string in the `replacement` column for that file. + +The column `excludeTerms` is used to prevent the replacement of the `original` value in specific contexts. +For example, even though we want to replace the term "Champion" with "Adult" when it refers to the level of a Digimon, we do not want the line `"You're the Champion"` to become `"You're the Adult"`, so we add the exclusion term `"You're the $"` to our replacement definition; `$` is automatically substituted with the content of the `original` column. +Several excluded paths can be provided, separated by commas. +For example: + +```csv +index;original;replace;excludeTerms;excludePaths +0;Champion;Adult;Colosseum $,You're the $; +``` + +The column `excludePaths` prevents the replacement in certain folders, files or specific lines in a file. +For example the following line will replace the term "Fresh" with "Baby I" except in line 4227 of btx_14 within LanguageKeep_jp.res: +`0;Fresh;Baby I;$ly;*\LanguageKeep_jp.res\14:4227` +Omitting `:4227` prevents any replacments in that file and `*\LanguageKeep_jp.res\*` prevents it for all files on that path. Multiple paths can be defined, separated by commas. + +The special value `all` will exclude a replacement from the effect of the `replace terms in ALL text` toggle. + +## Special Files +There are two special files, `_general.csv` and `_general_digimon.csv` which both do not target specific script files, but will simply replace the specified terms and replacements throughout the game. +The only difference between the two is that the contents of `_general_digimon.csv` are affected by Digimon name specific settings such as `camelCase names` and `Always use 'Black' as prefix`, see [editing Settings](#undubediting-settings). # Planned Features -* more fine control for everything +* Global string randomization. + +# Credits +* SydMontague for the DecodeTools and Decode Randomizer tools which this software is based on. +* A large number of replacements for the undub preset were taken from the non-dub translation patch for "Digimon World: Re:Digitize (PSP)" +* The rest were mostly compiled from Wikimon. # Contact -* Discord: SydMontague#8056, or in either the [Digimon Modding Community](https://discord.gg/cb5AuxU6su) or [Digimon Discord Community](https://discord.gg/0VODO3ww0zghqOCO) +* Discord: Theigno#6256, or in either the [Digimon Modding Community](https://discord.gg/cb5AuxU6su) or [Digimon Discord Community](https://discord.gg/0VODO3ww0zghqOCO) * directly on GitHub -* E-Mail: sydmontague@web.de -* Reddit: [/u/Sydmontague](https://reddit.com/u/sydmontague) \ No newline at end of file +* E-Mail: yggdrasilwiz9000@yahoo.com diff --git a/pom.xml b/pom.xml index 76f300e..9234e63 100644 --- a/pom.xml +++ b/pom.xml @@ -1,10 +1,9 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 net.digimonworld - decode-randomizer - 0.1.0-beta-preview5 + decode-textmod + 0.5.0 UTF-8 @@ -68,7 +67,7 @@ true - Decode-Randomizer + Decode-TextMod @@ -86,8 +85,8 @@ javafx-maven-plugin 0.0.5 - randomizer - net.digimonworld.decode.decode_randomizer/net.digimonworld.decode.randomizer.Launcher + textmod + net.digimonworld.decode.decode_textmod/net.digimonworld.decode.textmod.Launcher 2 true true @@ -106,9 +105,8 @@ - - net.digimonworld.decode.randomizer.Launcher + + net.digimonworld.decode.textmod.Launcher diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 5e3fb26..69f13e6 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -8,6 +8,6 @@ requires java.logging; requires com.amihaiemil.eoyaml; - opens net.digimonworld.decode.randomizer to javafx.fxml; - exports net.digimonworld.decode.randomizer; + opens net.digimonworld.decode.textmod to javafx.fxml; + exports net.digimonworld.decode.textmod; } \ No newline at end of file diff --git a/src/main/java/net/digimonworld/decode/randomizer/Launcher.java b/src/main/java/net/digimonworld/decode/randomizer/Launcher.java deleted file mode 100644 index fa64078..0000000 --- a/src/main/java/net/digimonworld/decode/randomizer/Launcher.java +++ /dev/null @@ -1,7 +0,0 @@ -package net.digimonworld.decode.randomizer; - -public class Launcher { - public static void main(String[] args) { - DecodeRandomizer.main(args); - } -} diff --git a/src/main/java/net/digimonworld/decode/randomizer/settings/DigimonSettings.java b/src/main/java/net/digimonworld/decode/randomizer/settings/DigimonSettings.java deleted file mode 100644 index 3646c4e..0000000 --- a/src/main/java/net/digimonworld/decode/randomizer/settings/DigimonSettings.java +++ /dev/null @@ -1,294 +0,0 @@ -package net.digimonworld.decode.randomizer.settings; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.Optional; -import java.util.Random; - -import com.amihaiemil.eoyaml.YamlMapping; - -import javafx.beans.property.BooleanProperty; -import javafx.beans.property.SimpleBooleanProperty; -import javafx.geometry.Pos; -import javafx.scene.control.TitledPane; -import javafx.scene.layout.VBox; -import net.digimonworld.decode.randomizer.RandoLogger.LogLevel; -import net.digimonworld.decode.randomizer.RandomizationContext; -import net.digimonworld.decode.randomizer.utils.JavaFXUtils; -import net.digimonworld.decodetools.data.keepdata.Digimon; -import net.digimonworld.decodetools.data.keepdata.DigimonRaising; -import net.digimonworld.decodetools.data.keepdata.GlobalKeepData; -import net.digimonworld.decodetools.data.keepdata.Item; -import net.digimonworld.decodetools.data.keepdata.Item.ItemType; -import net.digimonworld.decodetools.data.keepdata.LanguageKeep; -import net.digimonworld.decodetools.data.keepdata.enums.Attribute; -import net.digimonworld.decodetools.data.keepdata.enums.Level; - -public class DigimonSettings implements Setting { - private static final Attribute[] ATTRIBUTE_LIST = new Attribute[] { Attribute.DATA, Attribute.VACCINE, Attribute.VIRUS }; - - BooleanProperty randomizeAttribute = new SimpleBooleanProperty(); - BooleanProperty randomizeCombatSpeed = new SimpleBooleanProperty(); - BooleanProperty randomizeSleepSchedule = new SimpleBooleanProperty(); - BooleanProperty randomizeFavoriteFood = new SimpleBooleanProperty(); - BooleanProperty randomizeTrainingType = new SimpleBooleanProperty(); - BooleanProperty randomizeBaseWeight = new SimpleBooleanProperty(); - BooleanProperty randomizeScale = new SimpleBooleanProperty(); - - @Override - public TitledPane create(GlobalKeepData data, LanguageKeep language) { - VBox vbox = new VBox(4); - TitledPane pane = new TitledPane("Digimon", vbox); - vbox.setAlignment(Pos.TOP_RIGHT); - pane.setCollapsible(false); - - vbox.getChildren().addAll(JavaFXUtils.buildToggleSwitch("Attribute", Optional.empty(), Optional.of(randomizeAttribute)), - JavaFXUtils.buildToggleSwitch("Combat Speed", Optional.empty(), Optional.of(randomizeCombatSpeed)), - JavaFXUtils.buildToggleSwitch("Sleep Schedule", Optional.empty(), Optional.of(randomizeSleepSchedule)), - JavaFXUtils.buildToggleSwitch("Favorite Food", Optional.empty(), Optional.of(randomizeFavoriteFood)), - JavaFXUtils.buildToggleSwitch("Training Type", Optional.empty(), Optional.of(randomizeTrainingType)), - JavaFXUtils.buildToggleSwitch("Base Weight", Optional.empty(), Optional.of(randomizeBaseWeight)), - JavaFXUtils.buildToggleSwitch("Scale", - Optional.of("Randomize the size of Digimon between 0.5 and 2.0 their vanilla size."), - Optional.of(randomizeScale))); - - return pane; - } - - @Override - public void randomize(RandomizationContext context) { - if (randomizeAttribute.get()) - randomizeAttributes(context); - if (randomizeCombatSpeed.get()) - randomizeCombatSpeed(context); - if (randomizeSleepSchedule.get()) - randomizeSleepSchedule(context); - if (randomizeFavoriteFood.get()) - randomizeFavoriteFood(context); - if (randomizeTrainingType.get()) - randomizeTrainingType(context); - if (randomizeBaseWeight.get()) - randomizeBaseWeight(context); - if (randomizeScale.get()) - randomizeScale(context); - } - - private void randomizeScale(RandomizationContext context) { - Random rand = new Random(context.getInitialSeed() * "Scale".hashCode()); - - context.logLine(LogLevel.ALWAYS, "Randomizing Digimon Scale..."); - - for (ListIterator itr = context.getGlobalKeepData().getDigimonData().listIterator(); itr.hasNext();) { - int i = itr.nextIndex(); - Digimon a = itr.next(); - - float val = rand.nextFloat(); - if(val > 0.5f) - val = 1f + 2f * (val - 0.5f); - else - val = 1f + (val - 0.5f); - - float newScale = a.getScale() * val; - context.logLine(LogLevel.CASUAL, - String.format(FORMAT_FLOAT, - context.getLanguageKeep().getDigimonNames().getStringById(i + 1), - "Scale", - a.getScale(), - newScale)); - a.setScale(newScale); - a.setDigiviceScale(a.getDigiviceScale() / val); - } - } - - private void randomizeBaseWeight(RandomizationContext context) { - Random rand = new Random(context.getInitialSeed() * "BaseWeight".hashCode()); - - context.logLine(LogLevel.ALWAYS, "Randomizing Digimon Base Weight..."); - - for (ListIterator itr = context.getGlobalKeepData().getRaiseData().listIterator(); itr.hasNext();) { - int i = itr.nextIndex(); - DigimonRaising a = itr.next(); - Digimon digimon = context.getGlobalKeepData().getDigimonData().get(i); - - if (digimon.getLevel() == Level.NONE || digimon.getLevel() == Level.UNUSED || a.getBaseWeight() == 0) - continue; - - int level = Math.max(digimon.getLevel().ordinal() - 1, 1) + (a.getBaseWeight() == 100 ? 1 : 0); - int newWeight = 5 * level + rand.nextInt(5 * level + 10 * (level - 1)); - - context.logLine(LogLevel.CASUAL, - String.format(FORMAT_INT, - context.getLanguageKeep().getDigimonNames().getStringById(i + 1), - "Base Weight", - a.getBaseWeight(), - newWeight)); - a.setBaseWeight((short) newWeight); - } - - context.logLine(LogLevel.ALWAYS, ""); - } - - private void randomizeTrainingType(RandomizationContext context) { - Random rand = new Random(context.getInitialSeed() * "TrainingType".hashCode()); - - context.logLine(LogLevel.ALWAYS, "Randomizing Digimon Training Types..."); - - for (ListIterator itr = context.getGlobalKeepData().getRaiseData().listIterator(); itr.hasNext();) { - int i = itr.nextIndex(); - DigimonRaising a = itr.next(); - - if (a.getTrainingType() > 5) - continue; - - int newType = rand.nextInt(6); - context.logLine(LogLevel.CASUAL, - String.format(FORMAT_INT, - context.getLanguageKeep().getDigimonNames().getStringById(i + 1), - "Training Type", - a.getTrainingType(), - newType)); - a.setTrainingType((byte) newType); - } - - context.logLine(LogLevel.ALWAYS, ""); - } - - private void randomizeFavoriteFood(RandomizationContext context) { - Random rand = new Random(context.getInitialSeed() * "FavoriteFood".hashCode()); - - context.logLine(LogLevel.ALWAYS, "Randomizing Digimon Favorite Food..."); - - List foodItems = new ArrayList<>(); - for (ListIterator itr = context.getGlobalKeepData().getItems().listIterator(); itr.hasNext();) { - int id = itr.nextIndex() + 1; - Item item = itr.next(); - - if (item.getType() == ItemType.FOOD) - foodItems.add(id); - } - - for (ListIterator itr = context.getGlobalKeepData().getRaiseData().listIterator(); itr.hasNext();) { - int i = itr.nextIndex(); - DigimonRaising a = itr.next(); - - if (a.getFavoriteFood() == 0) - continue; - - int newFavFood = foodItems.get(rand.nextInt(foodItems.size())); - context.logLine(LogLevel.CASUAL, - String.format(FORMAT_STRING, - context.getLanguageKeep().getDigimonNames().getStringById(i + 1), - "Favorite Food", - context.getLanguageKeep().getItemNames().getStringById(a.getFavoriteFood()), - context.getLanguageKeep().getItemNames().getStringById(newFavFood))); - a.setFavoriteFood(newFavFood); - } - - context.logLine(LogLevel.ALWAYS, ""); - } - - private void randomizeSleepSchedule(RandomizationContext context) { - Random rand = new Random(context.getInitialSeed() * "SleepSchedule".hashCode()); - - context.logLine(LogLevel.ALWAYS, "Randomizing Digimon Sleep Schedules..."); - - for (ListIterator itr = context.getGlobalKeepData().getRaiseData().listIterator(); itr.hasNext();) { - int i = itr.nextIndex(); - DigimonRaising a = itr.next(); - - if (a.getSleepSchedule() < 2) - continue; - - int newSchedule = 3 + rand.nextInt(6); - context.logLine(LogLevel.CASUAL, - String.format(FORMAT_INT, - context.getLanguageKeep().getDigimonNames().getStringById(i + 1), - "Sleep Schedule", - a.getSleepSchedule(), - newSchedule)); - a.setSleepSchedule(newSchedule); - } - - context.logLine(LogLevel.ALWAYS, ""); - } - - private void randomizeCombatSpeed(RandomizationContext context) { - Random rand = new Random(context.getInitialSeed() * "CombatSpeed".hashCode()); - - context.logLine(LogLevel.ALWAYS, "Randomizing Digimon Combat Speed..."); - - for (ListIterator itr = context.getGlobalKeepData().getDigimonData().listIterator(); itr.hasNext();) { - int i = itr.nextIndex(); - Digimon a = itr.next(); - - float newSpeed = 3.5f + 5f * rand.nextFloat(); - context.logLine(LogLevel.CASUAL, - String.format(FORMAT_FLOAT, - context.getLanguageKeep().getDigimonNames().getStringById(i + 1), - "Combat Speed", - a.getCombatSpeed(), - newSpeed)); - a.setCombatSpeed(newSpeed); - } - - context.logLine(LogLevel.ALWAYS, ""); - } - - private void randomizeAttributes(RandomizationContext context) { - Random rand = new Random(context.getInitialSeed() * "Attribute".hashCode()); - - context.logLine(LogLevel.ALWAYS, "Randomizing Digimon Attributes..."); - - for (ListIterator itr = context.getGlobalKeepData().getDigimonData().listIterator(); itr.hasNext();) { - int i = itr.nextIndex(); - Digimon a = itr.next(); - - if (a.getAttribute() == Attribute.NONE || a.getAttribute() == Attribute.UNKNOWN || a.getAttribute() == Attribute.FREE) - continue; - - Attribute newAttribute = ATTRIBUTE_LIST[rand.nextInt(3)]; - context.logLine(LogLevel.CASUAL, - String.format(FORMAT_STRING, - context.getLanguageKeep().getDigimonNames().getStringById(i + 1), - "Attribute", - a.getAttribute(), - newAttribute)); - a.setAttribute(newAttribute); - } - - context.logLine(LogLevel.ALWAYS, ""); - } - - @Override - public Map serialize() { - Map map = new HashMap<>(); - - map.put("randomizeAttribute", randomizeAttribute.get()); - map.put("randomizeBaseWeight", randomizeBaseWeight.get()); - map.put("randomizeCombatSpeed", randomizeCombatSpeed.get()); - map.put("randomizeFavoriteFood", randomizeFavoriteFood.get()); - map.put("randomizeSleepSchedule", randomizeSleepSchedule.get()); - map.put("randomizeTrainingType", randomizeTrainingType.get()); - map.put("randomizeScale", randomizeScale.get()); - - return map; - } - - @Override - public void load(YamlMapping map) { - if (map == null) - return; - - this.randomizeAttribute.set(Boolean.parseBoolean(map.string("randomizeAttribute"))); - this.randomizeBaseWeight.set(Boolean.parseBoolean(map.string("randomizeBaseWeight"))); - this.randomizeCombatSpeed.set(Boolean.parseBoolean(map.string("randomizeCombatSpeed"))); - this.randomizeFavoriteFood.set(Boolean.parseBoolean(map.string("randomizeFavoriteFood"))); - this.randomizeSleepSchedule.set(Boolean.parseBoolean(map.string("randomizeSleepSchedule"))); - this.randomizeTrainingType.set(Boolean.parseBoolean(map.string("randomizeTrainingType"))); - this.randomizeScale.set(Boolean.parseBoolean(map.string("randomizeScale"))); - } - -} diff --git a/src/main/java/net/digimonworld/decode/randomizer/settings/EvolutionSettings.java b/src/main/java/net/digimonworld/decode/randomizer/settings/EvolutionSettings.java deleted file mode 100644 index 80f9816..0000000 --- a/src/main/java/net/digimonworld/decode/randomizer/settings/EvolutionSettings.java +++ /dev/null @@ -1,449 +0,0 @@ -package net.digimonworld.decode.randomizer.settings; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.Optional; -import java.util.Random; -import java.util.Set; -import java.util.function.IntSupplier; -import java.util.stream.Collectors; - -import com.amihaiemil.eoyaml.YamlMapping; - -import net.digimonworld.decodetools.data.keepdata.Digimon; -import net.digimonworld.decodetools.data.keepdata.DigimonRaising; -import net.digimonworld.decodetools.data.keepdata.EvoRequirement; -import net.digimonworld.decodetools.data.keepdata.EvoRequirement.Comperator; -import net.digimonworld.decodetools.data.keepdata.EvoRequirement.Operator; -import net.digimonworld.decodetools.data.keepdata.EvoRequirement.Requirement; -import net.digimonworld.decodetools.data.keepdata.EvoRequirement.SuperGroup; -import net.digimonworld.decodetools.data.keepdata.EvoRequirement.Type; -import net.digimonworld.decodetools.data.keepdata.GlobalKeepData; -import net.digimonworld.decodetools.data.keepdata.LanguageKeep; -import net.digimonworld.decodetools.data.keepdata.enums.Level; -import javafx.beans.property.BooleanProperty; -import javafx.beans.property.SimpleBooleanProperty; -import javafx.geometry.Pos; -import javafx.scene.control.TitledPane; -import javafx.scene.layout.VBox; -import net.digimonworld.decode.randomizer.RandoLogger.LogLevel; -import net.digimonworld.decode.randomizer.RandomizationContext; -import net.digimonworld.decode.randomizer.utils.JavaFXUtils; - -public class EvolutionSettings implements Setting { - - private BooleanProperty randomizeRequirements = new SimpleBooleanProperty(); - private BooleanProperty randomizePaths = new SimpleBooleanProperty(); - private BooleanProperty randomizeStatsgains = new SimpleBooleanProperty(); - - @Override - public TitledPane create(GlobalKeepData inputData, LanguageKeep languageKeep) { - VBox vbox = new VBox(4); - TitledPane pane = new TitledPane("Evolution", vbox); - vbox.setAlignment(Pos.TOP_RIGHT); - pane.setCollapsible(false); - - vbox.getChildren().addAll(JavaFXUtils.buildToggleSwitch("Requirements", Optional.empty(), Optional.of(randomizeRequirements)), - JavaFXUtils.buildToggleSwitch("Paths", Optional.empty(), Optional.of(randomizePaths)), - JavaFXUtils.buildToggleSwitch("Stats Gains", Optional.empty(), Optional.of(randomizeStatsgains))); - - return pane; - } - - @Override - public void randomize(RandomizationContext context) { - if (randomizeRequirements.get()) - randomizeRequirements(context); - if (randomizePaths.get()) - randomizePaths(context); - if (randomizeStatsgains.get()) - randomizeStatsgains(context); - } - - private void randomizeStatsgains(RandomizationContext context) { - Random rand = new Random(context.getInitialSeed() * "StatsGains".hashCode()); - - for (ListIterator itr = context.getGlobalKeepData().getDigimonData().listIterator(); itr.hasNext();) { - int id = itr.nextIndex(); - Digimon digi = itr.next(); - DigimonRaising raise = context.getGlobalKeepData().getRaiseData().get(id); - String name = context.getLanguageKeep().getDigimonNames().getStringById(id + 1); - - if ((digi.getUnk38() & 1) == 1 && raise.getGainHP() != 0) { - IntSupplier gen = getStatsGainGenerator(digi.getLevel(), rand); - - context.logLine(LogLevel.CASUAL, String.format("=== %s's Stats Gains ===", name)); - context.logLine(LogLevel.CASUAL, - String.format("Old: %5d %5d %4d %4d %4d %4d", - raise.getGainHP(), - raise.getGainMP(), - raise.getGainOFF(), - raise.getGainDEF(), - raise.getGainSPD(), - raise.getGainBRN())); - - raise.setGainHP((short) (gen.getAsInt() * 10)); - raise.setGainMP((short) (gen.getAsInt() * 10)); - raise.setGainOFF((short) gen.getAsInt()); - raise.setGainDEF((short) gen.getAsInt()); - raise.setGainSPD((short) gen.getAsInt()); - raise.setGainBRN((short) gen.getAsInt()); - - context.logLine(LogLevel.CASUAL, - String.format("New: %5d %5d %4d %4d %4d %4d", - raise.getGainHP(), - raise.getGainMP(), - raise.getGainOFF(), - raise.getGainDEF(), - raise.getGainSPD(), - raise.getGainBRN())); - context.logLine(LogLevel.CASUAL, ""); - } - } - } - - public IntSupplier getStatsGainGenerator(Level level, Random rand) { - switch (level) { - case BABY1: - return () -> 8 + rand.nextInt(10); - case BABY2: - return () -> 16 + rand.nextInt(19); - case CHILD: - return () -> 30 + rand.nextInt(101); - case ADULT: - return () -> 120 + rand.nextInt(101); - case PERFECT: - return () -> 250 + rand.nextInt(251); - case ULTIMATE: - return () -> 430 + rand.nextInt(571); - default: - return () -> 0; - } - } - - private void randomizePaths(RandomizationContext context) { - Random rand = new Random(context.getInitialSeed() * "EvoPaths".hashCode()); - - Map> digimonMap = new EnumMap<>(Level.class); - - for (ListIterator itr = context.getGlobalKeepData().getDigimonData().listIterator(); itr.hasNext();) { - int id = itr.nextIndex(); - Digimon digi = itr.next(); - - if ((digi.getUnk38() & 1) == 1 && id != 67) { - digimonMap.computeIfAbsent(digi.getLevel(), a -> new ArrayList()).add(id); - DigimonRaising raise = context.getGlobalKeepData().getRaiseData().get(id); - if (digi.getLevel() != Level.BABY2) - raise.setEvolveFrom(new short[5]); - if (digi.getLevel() != Level.BABY1) - raise.setEvolveTo(new short[6]); - } - } - - LinkedList listBaby2 = new LinkedList<>(digimonMap.get(Level.BABY2)); - LinkedList listAdult = new LinkedList<>(digimonMap.get(Level.ADULT)); - LinkedList listChild = new LinkedList<>(digimonMap.get(Level.CHILD)); - LinkedList listPerfect = new LinkedList<>(digimonMap.get(Level.PERFECT)); - LinkedList listUltimate = new LinkedList<>(digimonMap.get(Level.ULTIMATE)); - - Map> baby2Targets = distributeEvolutionPaths(rand, listBaby2, listChild, 5, () -> 5); - Map> childTargets = distributeEvolutionPaths(rand, listChild, listAdult, 5, () -> 5); - Map> adultTargets = distributeEvolutionPaths(rand, listAdult, listPerfect, 3, () -> 3); - Map> perfectTargets = distributeEvolutionPaths(rand, listPerfect, listUltimate, 3, () -> 1 + rand.nextInt(3)); - - baby2Targets.forEach((digimonId, targetSet) -> setEvolutions(digimonId, targetSet, context)); - childTargets.forEach((digimonId, targetSet) -> setEvolutions(digimonId, targetSet, context)); - adultTargets.forEach((digimonId, targetSet) -> setEvolutions(digimonId, targetSet, context)); - perfectTargets.forEach((digimonId, targetSet) -> setEvolutions(digimonId, targetSet, context)); - } - - private void setEvolutions(Integer digimonId, Set targetSet, RandomizationContext context) { - DigimonRaising digi = context.getGlobalKeepData().getRaiseData().get(digimonId); - String name1 = context.getLanguageKeep().getDigimonNames().getStringById(digimonId + 1); - String namesNew = targetSet.stream().map(c -> context.getLanguageKeep().getDigimonNames().getStringById(c + 1)).collect(Collectors.joining(" ")); - - int i = 0; - for (Integer target : targetSet) { - DigimonRaising digi2 = context.getGlobalKeepData().getRaiseData().get(target); - - for (int j = 0; j < 6; j++) - if (digi2.getEvolveFrom(j) == 0) { - digi2.setEvolveFrom(j, (short) (digimonId + 1)); - break; - } - - digi.setEvolveTo(i++, (short) (target + 1)); - } - - context.logLine(LogLevel.CASUAL, String.format("=== %s's Evolutions ===", name1)); - context.logLine(LogLevel.CASUAL, String.format("New: %s", namesNew)); - context.logLine(LogLevel.CASUAL, ""); - } - - private Map> distributeEvolutionPaths(Random rand, List from, List to, int max1, IntSupplier max2) { - Map> map = new HashMap<>(); - - for (Integer i : to) { - boolean notFound = true; - while (notFound) { - int target = from.get(rand.nextInt(from.size())); - Set set = map.computeIfAbsent(target, a -> new HashSet<>()); - if (set.size() < max1) - notFound = !set.add(i); - } - } - - LinkedList clonedTo = new LinkedList<>(); - clonedTo.addAll(to); - clonedTo.addAll(to); - clonedTo.addAll(to); - clonedTo.addAll(to); - - for (Integer i : from) { - Set set = map.computeIfAbsent(i, a -> new HashSet<>()); - int limit = max2.getAsInt(); - while (set.size() < limit) - set.add(clonedTo.poll()); - } - - return map; - } - - private void randomizeRequirements(RandomizationContext context) { - Random rand = new Random(context.getInitialSeed() * "EvoRequirements".hashCode()); - - context.logLine(LogLevel.ALWAYS, "Randomizing Evolution Requirements..."); - - for (ListIterator itr = context.getGlobalKeepData().getDigimonData().listIterator(); itr.hasNext();) { - int i = itr.nextIndex(); - Digimon a = itr.next(); - - if (((a.getUnk38() & 1) != 1)) - continue; - - EvoRequirement evo = context.getGlobalKeepData().getEvoRequirements().get(i); - List requirements = evo.getRequirements(); - - switch (a.getLevel()) { - case CHILD: - requirements.add(new Requirement(SuperGroup.BONUS, (byte) requirements.size(), Operator.AND, Comperator.GREATER_THAN, Type.HAPPINESS, 0)); - break; - case ADULT: - requirements = generateAdultRequirements(rand); - break; - case PERFECT: - requirements = generatePerfectRequirements(rand); - break; - case ULTIMATE: - requirements = generateUltimateRequirements(rand); - break; - default: - break; - } - - String digimonName = context.getLanguageKeep().getDigimonNames().getStringById(i + 1); - context.logLine(LogLevel.CASUAL, String.format("=== %s ===", digimonName)); - context.logLine(LogLevel.CASUAL, "== Old =="); - evo.getRequirements().forEach(b -> context.logLine(LogLevel.CASUAL, b.toString())); - context.logLine(LogLevel.CASUAL, "== New =="); - requirements.forEach(b -> context.logLine(LogLevel.CASUAL, b.toString())); - context.logLine(LogLevel.CASUAL, ""); - - evo.setRequirements(requirements); - } - } - - private List generateUltimateRequirements(Random rand) { - byte quotaId = 0; - int numStats = 3 + rand.nextInt(4); - int numBonus = 1 + rand.nextInt(2); - - List list = new ArrayList<>(); - list.add(new Requirement(SuperGroup.QUOTA, quotaId++, Operator.QUOTA, Comperator.QUOTA, Type.QUOTA, numStats + 2)); - - LinkedList queue = new LinkedList<>(Arrays.asList(Type.HP, Type.MP, Type.OFFENSE, Type.DEFENSE, Type.SPEED, Type.BRAINS)); - LinkedList bonusQueue = new LinkedList<>(Arrays.asList(Type.HAPPINESS, Type.DISCIPLINE, Type.BATTLES)); - Collections.shuffle(queue, rand); - Collections.shuffle(bonusQueue, rand); - - for (int i = 0; i < numStats; i++) { - Type t = queue.poll(); - int val = 300 + rand.nextInt(500); - if (t == Type.HP || t == Type.MP) - val *= 10; - - list.add(new Requirement(SuperGroup.NORMAL, quotaId++, Operator.AND, Comperator.GREATER_THAN, t, val)); - } - - Comperator mode = rand.nextBoolean() ? Comperator.GREATER_THAN : Comperator.LESS_THAN; - list.add(new Requirement(SuperGroup.NORMAL, quotaId++, Operator.AND, mode, Type.WEIGHT, 25 + rand.nextInt(50))); - - if (rand.nextBoolean()) - list.add(new Requirement(SuperGroup.NORMAL, (byte) 5, Operator.AND, Comperator.LESS_THAN, Type.CARE, rand.nextInt(20))); - else - list.add(new Requirement(SuperGroup.NORMAL, (byte) 5, Operator.AND, Comperator.GREATER_THAN, Type.CARE, 1 + rand.nextInt(6))); - - for (int i = 0; i < numBonus; i++) - switch (bonusQueue.poll()) { - case HAPPINESS: - list.add(new Requirement(SuperGroup.BONUS, quotaId++, Operator.AND, Comperator.GREATER_THAN, Type.HAPPINESS, 70 + rand.nextInt(30))); - break; - case DISCIPLINE: - list.add(new Requirement(SuperGroup.BONUS, quotaId++, Operator.AND, rand.nextBoolean() ? Comperator.GREATER_THAN : Comperator.LESS_THAN, - Type.DISCIPLINE, rand.nextInt(100))); - break; - case BATTLES: - list.add(new Requirement(SuperGroup.BONUS, quotaId++, Operator.AND, rand.nextBoolean() ? Comperator.GREATER_THAN : Comperator.LESS_THAN, - Type.BATTLES, 25 + rand.nextInt(50))); - break; - default: - break; - } - - list.add(new Requirement(SuperGroup.BONUS, quotaId++, Operator.AND, Comperator.GREATER_THAN, Type.TECHS, 25 + rand.nextInt(30))); - list.add(new Requirement(SuperGroup.BONUS, quotaId, Operator.AND, Comperator.GREATER_THAN, Type.DECODE_LEVEL, 10 + rand.nextInt(10))); - - return list; - } - - private List generatePerfectRequirements(Random rand) { - List list = new ArrayList<>(); - list.add(new Requirement(SuperGroup.QUOTA, (byte) 0, Operator.QUOTA, Comperator.QUOTA, Type.QUOTA, 5)); - - LinkedList queue1 = new LinkedList<>(Arrays.asList(Type.HP, Type.MP)); - LinkedList queue2 = new LinkedList<>(Arrays.asList(Type.OFFENSE, Type.DEFENSE)); - LinkedList queue3 = new LinkedList<>(Arrays.asList(Type.SPEED, Type.BRAINS)); - Collections.shuffle(queue1, rand); - Collections.shuffle(queue2, rand); - Collections.shuffle(queue3, rand); - int numStats1 = 1 + rand.nextInt(2); - int numStats2 = 1 + rand.nextInt(2); - int numStats3 = 1 + rand.nextInt(2); - - for (int i = 0; i < numStats1; i++) { - int val = 1000 + rand.nextInt(300) * 10; - list.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, queue1.poll(), val)); - } - for (int i = 0; i < numStats2; i++) { - int val = 100 + rand.nextInt(300); - list.add(new Requirement(SuperGroup.NORMAL, (byte) 2, Operator.AND, Comperator.GREATER_THAN, queue2.poll(), val)); - } - for (int i = 0; i < numStats3; i++) { - int val = 100 + rand.nextInt(300); - list.add(new Requirement(SuperGroup.NORMAL, (byte) 3, Operator.AND, Comperator.GREATER_THAN, queue3.poll(), val)); - } - - Comperator mode = rand.nextBoolean() ? Comperator.GREATER_THAN : Comperator.LESS_THAN; - list.add(new Requirement(SuperGroup.NORMAL, (byte) 4, Operator.AND, mode, Type.WEIGHT, 20 + rand.nextInt(45))); - - if (rand.nextBoolean()) - list.add(new Requirement(SuperGroup.NORMAL, (byte) 5, Operator.AND, Comperator.LESS_THAN, Type.CARE, rand.nextInt(20))); - else - list.add(new Requirement(SuperGroup.NORMAL, (byte) 5, Operator.AND, Comperator.GREATER_THAN, Type.CARE, 1 + rand.nextInt(6))); - - LinkedList bonusQueue = new LinkedList<>(Arrays.asList(Type.HAPPINESS, Type.DISCIPLINE, Type.BATTLES)); - Collections.shuffle(bonusQueue, rand); - - int numBonus = 1 + (rand.nextFloat() < 0.25 ? 1 : 0); - for (int i = 0; i < numBonus; i++) - switch (bonusQueue.poll()) { - case HAPPINESS: - list.add(new Requirement(SuperGroup.BONUS, (byte) (6 + i), Operator.AND, Comperator.GREATER_THAN, Type.HAPPINESS, 70 + rand.nextInt(30))); - break; - case DISCIPLINE: - list.add(new Requirement(SuperGroup.BONUS, (byte) (6 + i), Operator.AND, - rand.nextBoolean() ? Comperator.GREATER_THAN : Comperator.LESS_THAN, Type.DISCIPLINE, 50 + rand.nextInt(46))); - break; - case BATTLES: - list.add(new Requirement(SuperGroup.BONUS, (byte) (6 + i), Operator.AND, - rand.nextBoolean() ? Comperator.GREATER_THAN : Comperator.LESS_THAN, Type.BATTLES, 20 + rand.nextInt(25))); - break; - default: - break; - } - - list.add(new Requirement(SuperGroup.BONUS, (byte) (6 + numBonus), Operator.AND, Comperator.GREATER_THAN, Type.TECHS, 25 + rand.nextInt(30))); - list.add(new Requirement(SuperGroup.BONUS, (byte) (7 + numBonus), Operator.AND, Comperator.GREATER_THAN, Type.DECODE_LEVEL, 10 + rand.nextInt(10))); - - return list; - } - - private List generateAdultRequirements(Random rand) { - List list = new ArrayList<>(); - list.add(new Requirement(SuperGroup.QUOTA, (byte) 0, Operator.QUOTA, Comperator.QUOTA, Type.QUOTA, 3)); - - LinkedList queue = new LinkedList<>(Arrays.asList(Type.HP, Type.MP, Type.OFFENSE, Type.DEFENSE, Type.SPEED, Type.BRAINS)); - Collections.shuffle(queue, rand); - - int numStats = 1 + rand.nextInt(5); - for (int i = 0; i < numStats; i++) { - Type t = queue.poll(); - int val = 50 + rand.nextInt(120); - if (t == Type.HP || t == Type.MP) - val *= 10; - - list.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, t, val)); - } - - Comperator mode = rand.nextBoolean() ? Comperator.GREATER_THAN : Comperator.LESS_THAN; - list.add(new Requirement(SuperGroup.NORMAL, (byte) 2, Operator.AND, mode, Type.WEIGHT, 5 + rand.nextInt(40))); - - if (rand.nextBoolean()) - list.add(new Requirement(SuperGroup.NORMAL, (byte) 3, Operator.AND, Comperator.LESS_THAN, Type.CARE, rand.nextInt(11))); - else - list.add(new Requirement(SuperGroup.NORMAL, (byte) 3, Operator.AND, Comperator.GREATER_THAN, Type.CARE, 1 + rand.nextInt(3))); - - LinkedList bonusQueue = new LinkedList<>(Arrays.asList(Type.HAPPINESS, Type.DISCIPLINE, Type.BATTLES)); - Collections.shuffle(bonusQueue, rand); - - switch (bonusQueue.poll()) { - case HAPPINESS: - list.add(new Requirement(SuperGroup.BONUS, (byte) 4, Operator.AND, Comperator.GREATER_THAN, Type.HAPPINESS, 50 + rand.nextInt(46))); - break; - case DISCIPLINE: - list.add(new Requirement(SuperGroup.BONUS, (byte) 4, Operator.AND, rand.nextBoolean() ? Comperator.GREATER_THAN : Comperator.LESS_THAN, - Type.DISCIPLINE, 50 + rand.nextInt(46))); - break; - case BATTLES: - list.add(new Requirement(SuperGroup.BONUS, (byte) 4, Operator.AND, rand.nextBoolean() ? Comperator.GREATER_THAN : Comperator.LESS_THAN, - Type.BATTLES, 5 + rand.nextInt(26))); - break; - default: - break; - } - - list.add(new Requirement(SuperGroup.BONUS, (byte) 5, Operator.AND, Comperator.GREATER_THAN, Type.TECHS, 10 + rand.nextInt(30))); - list.add(new Requirement(SuperGroup.BONUS, (byte) 6, Operator.AND, Comperator.GREATER_THAN, Type.DECODE_LEVEL, 5 + rand.nextInt(13))); - - return list; - } - - @Override - public Map serialize() { - Map map = new HashMap<>(); - - map.put("randomizeRequirements", randomizeRequirements.get()); - map.put("randomizePaths", randomizePaths.get()); - map.put("randomizeStatsgains", randomizeStatsgains.get()); - - return map; - } - - @Override - public void load(YamlMapping map) { - if (map == null) - return; - - this.randomizeRequirements.set(Boolean.parseBoolean(map.string("randomizeRequirements"))); - this.randomizePaths.set(Boolean.parseBoolean(map.string("randomizePaths"))); - this.randomizeStatsgains.set(Boolean.parseBoolean(map.string("randomizeStatsgains"))); - } -} diff --git a/src/main/java/net/digimonworld/decode/randomizer/settings/PatchSettings.java b/src/main/java/net/digimonworld/decode/randomizer/settings/PatchSettings.java deleted file mode 100644 index 0a96c36..0000000 --- a/src/main/java/net/digimonworld/decode/randomizer/settings/PatchSettings.java +++ /dev/null @@ -1,1107 +0,0 @@ -package net.digimonworld.decode.randomizer.settings; - -import java.awt.image.BufferedImage; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Optional; - -import com.amihaiemil.eoyaml.YamlMapping; - -import javafx.beans.property.BooleanProperty; -import javafx.beans.property.DoubleProperty; -import javafx.beans.property.SimpleBooleanProperty; -import javafx.beans.property.SimpleDoubleProperty; -import javafx.geometry.Pos; -import javafx.scene.control.Label; -import javafx.scene.control.Slider; -import javafx.scene.control.TitledPane; -import javafx.scene.layout.HBox; -import javafx.scene.layout.VBox; -import net.digimonworld.decode.randomizer.RandoLogger.LogLevel; -import net.digimonworld.decode.randomizer.RandomizationContext; -import net.digimonworld.decode.randomizer.utils.JavaFXUtils; -import net.digimonworld.decodetools.data.keepdata.AccessoryOrder; -import net.digimonworld.decodetools.PixelFormat; -import net.digimonworld.decodetools.data.DigimonList; -import net.digimonworld.decodetools.data.digimon.PartnerDigimon; -import net.digimonworld.decodetools.data.keepdata.Digimon; -import net.digimonworld.decodetools.data.keepdata.DigimonRaising; -import net.digimonworld.decodetools.data.keepdata.EvoRequirement.Comperator; -import net.digimonworld.decodetools.data.keepdata.EvoRequirement.Operator; -import net.digimonworld.decodetools.data.keepdata.EvoRequirement.Requirement; -import net.digimonworld.decodetools.data.keepdata.EvoRequirement.SuperGroup; -import net.digimonworld.decodetools.data.keepdata.EvoRequirement.Type; -import net.digimonworld.decodetools.data.keepdata.GlobalKeepData; -import net.digimonworld.decodetools.data.keepdata.LanguageKeep; -import net.digimonworld.decodetools.res.kcap.AbstractKCAP; -import net.digimonworld.decodetools.res.kcap.GMIPKCAP; -import net.digimonworld.decodetools.res.payload.GMIOPayload; -import net.digimonworld.decodetools.res.payload.GMIOPayload.TextureFiltering; -import net.digimonworld.decodetools.res.payload.GMIOPayload.TextureWrap; -import net.digimonworld.decodetools.res.payload.GMIOPayload.UnknownEnum; -import net.digimonworld.decodetools.res.payload.GenericPayload; - -public class PatchSettings implements Setting { - - // TODO evo priority - // TODO faster menus/training - // TODO increase MP recovery rate - // TODO remove intro cutscene - - private BooleanProperty patchViewDistance = new SimpleBooleanProperty(); - private BooleanProperty patchBrainsChance = new SimpleBooleanProperty(); - private DoubleProperty patchBrainsChanceFactor = new SimpleDoubleProperty(); - private BooleanProperty patchStartMPDisc = new SimpleBooleanProperty(); - private BooleanProperty patchDisable90FBattles = new SimpleBooleanProperty(); - private BooleanProperty patchMovementSpeed = new SimpleBooleanProperty(); - private BooleanProperty patchAddRecolorDigimon = new SimpleBooleanProperty(); - private BooleanProperty patchListOrder = new SimpleBooleanProperty(); - - @Override - public TitledPane create(GlobalKeepData inputData, LanguageKeep languageKeep) { - VBox vbox = new VBox(4); - TitledPane pane = new TitledPane("Patches", vbox); - vbox.setAlignment(Pos.TOP_RIGHT); - pane.setCollapsible(false); - - Slider brainChanceSlider = new Slider(1D, 10D, 1D); - brainChanceSlider.setShowTickLabels(true); - brainChanceSlider.setShowTickMarks(true); - brainChanceSlider.setMajorTickUnit(1D); - brainChanceSlider.setMinorTickCount(3); - brainChanceSlider.setSnapToTicks(true); - brainChanceSlider.setBlockIncrement(0.25D); - brainChanceSlider.disableProperty().bind(patchBrainsChance.not()); - - Label lbl = new Label("100%"); - lbl.textProperty().bind(brainChanceSlider.valueProperty().multiply(100D).asString("%4.0f%%")); - lbl.setMinWidth(45); - lbl.setAlignment(Pos.CENTER_RIGHT); - - patchBrainsChanceFactor.bindBidirectional(brainChanceSlider.valueProperty()); - - vbox.getChildren() - .addAll(JavaFXUtils.buildToggleSwitch("View Distance", - Optional.of("Increases view distance, allowing to see Digimon from a further distance."), - Optional.of(patchViewDistance)), - JavaFXUtils.buildToggleSwitch("Increase Movement Speed", - Optional.of("Increases running speed of player and enenmies."), - Optional.of(patchMovementSpeed)), - JavaFXUtils.buildToggleSwitch("Brain Learn Chance", Optional.empty(), Optional.of(patchBrainsChance)), - new HBox(brainChanceSlider, lbl), - JavaFXUtils.buildToggleSwitch("Start with MP Disc", - Optional.of("Replaces the starting Meat with MP Discs.\nStrongly recommended when playing with randomized MP costs!"), - Optional.of(patchStartMPDisc)), - JavaFXUtils.buildToggleSwitch("Skip 90F Battles", - Optional.of("Disabled the battles on 90F where you control your allies.\nThis is useful to prevent these fight from being unwinnable."), - Optional.of(patchDisable90FBattles)), - JavaFXUtils.buildToggleSwitch("Enable additional Digimon", - Optional.of("Makes 19 previously unobtainable recolor Digimon available.\nBlackAgumon, BlackGabumon, Tsukaimon, Psychemon,\nSnowAgumon, Solarmon, BlackGarurumon, Gururumon,\nYellowGrowlmon, BlackGrowlmon, IceDevimon,\nGeremon, MetalGreymon (Virus), BlackWarGrowlmon,\nOrangeWarGrowlmon, BlackWereGarurumon, BlackWarGreymon,\nBlackMetalGarurumon, ChaosDukemon"), - Optional.of(patchAddRecolorDigimon)), - JavaFXUtils.buildToggleSwitch("Sort Lists Alphabetically", - Optional.of("Sort Digimon Evolution List & Accessories alphabetically"), - Optional.of(patchListOrder))); - return pane; - } - - @Override - public void randomize(RandomizationContext context) { - if (patchViewDistance.get()) - patchViewDistance(context); - if (patchBrainsChance.get()) - patchBrainsChance(context); - if (patchStartMPDisc.get()) - patchStartMPDisc(context); - if (patchDisable90FBattles.get()) - disable90FBattles(context); - if (patchMovementSpeed.get()) - patchMovementSpeed(context); - if (patchAddRecolorDigimon.get()) - patchAddRecolorDigimon(context); - if (patchListOrder.get()) - patchListOrder(context); - } - - private void sortAccessoryOrder(RandomizationContext context) { - List accorder = new ArrayList<>(context.getGlobalKeepData().getAccessoryOrder()); - var accNames = context.getLanguageKeep().getAccessoryNames(); - accorder.sort(Comparator.comparing(order -> accNames.getStringById(order.getId()))); - - int accOrder = 1; - for (AccessoryOrder acccorderdata : accorder) - acccorderdata.setAccId(accOrder++); - } - - private void sortDigimonOrder(RandomizationContext context) { - List list = new ArrayList<>(context.getGlobalKeepData().getDigimonData()); - var names = context.getLanguageKeep().getDigimonNames(); - list.sort(Comparator.comparing(Digimon::getLevel).thenComparing(a -> names.getStringById(a.getId()))); - - short evoListPos = 1; - for (Digimon digimon : list) - digimon.setEvoListPos(evoListPos++); - } - - private void patchListOrder(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Patching List Order..."); - - sortAccessoryOrder(context); - sortDigimonOrder(context); - } - - private void patchAddRecolorDigimon(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Adding new Digimon..."); - - addBlackAgumon(context); - addBlackGabumon(context); - addTsukaimon(context); - addPsychemon(context); - addSnowAgumon(context); - addSolarmon(context); - - addBlackGarurumon(context); - addGururumon(context); - addOrangeGrowlmon(context); - addBlackGrowlmon(context); - addIceDevimon(context); - addGeremon(context); - - addMetalGreymonVirus(context); - addWarGrowlmonBlack(context); - addWarGrowlmonOrange(context); - addBlackWereGarurumon(context); - - addBlackWarGreymon(context); - addChaosDukemon(context); - addBlackMetalGarurumon(context); - } - - private void addBlackAgumon(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Adding BlackAgumon..."); - - GlobalKeepData keep = context.getGlobalKeepData(); - final short ownId = DigimonList.BLACKAGUMON; - final short baseId = DigimonList.AGUMON; - - // Digimon Data - applyBaseData(context, ownId, baseId, (short) 100); - - // Raise Data - DigimonRaising raise = context.getGlobalKeepData().getRaiseData().get(ownId - 1); - raise.setSleepSchedule(5); - raise.setFavoriteFood(39); - raise.setTrainingType((byte) 0); - raise.setLikedAreas((short) 4128); - raise.setDislikedAreas((short) 272); - raise.setGains(500, 1200, 50, 70, 90, 40); - - // Evo Requirements - List requirements = new ArrayList<>(); - requirements.add(new Requirement(SuperGroup.QUOTA, (byte) 0, Operator.QUOTA, Comperator.QUOTA, Type.QUOTA, 2)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.HIGHEST, Type.MP_DIV10, 0)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 2, Operator.AND, Comperator.LESS_THAN, Type.WEIGHT, 12)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 3, Operator.AND, Comperator.EQUALS, Type.DIGIMON, DigimonList.KOROMON)); - - keep.getEvoRequirements().get(ownId - 1).setRequirements(requirements); - - // Evo Paths - setEvolveFrom(keep, ownId, DigimonList.KOROMON); - setEvolveTo(keep, ownId, DigimonList.BLACK_WARGROWLMON, DigimonList.GREYMON, DigimonList.SEADRAMON, DigimonList.GROWLMON, DigimonList.WOODMON); - - setDescriptionString(context, ownId, "Focus on MP and low weight.\nEvolves from Koromon."); - } - - private void addBlackGabumon(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Adding BlackGabumon..."); - - GlobalKeepData keep = context.getGlobalKeepData(); - final short ownId = DigimonList.BLACKGABUMON; - final short baseId = DigimonList.GABUMON; - - // Digimon Data - applyBaseData(context, ownId, baseId, (short) 101); - - // Raise Data - DigimonRaising raise = context.getGlobalKeepData().getRaiseData().get(ownId - 1); - raise.setSleepSchedule(5); - raise.setFavoriteFood(39); - raise.setTrainingType((byte) 1); - raise.setLikedAreas((short) 516); - raise.setDislikedAreas((short) 160); - raise.setGains(800, 1000, 50, 80, 80, 40); - - // Evo Requirements - List requirements = new ArrayList<>(); - requirements.add(new Requirement(SuperGroup.QUOTA, (byte) 0, Operator.QUOTA, Comperator.QUOTA, Type.QUOTA, 2)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.HIGHEST, Type.MP_DIV10, 0)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 2, Operator.AND, Comperator.GREATER_THAN, Type.WEIGHT, 14)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 3, Operator.AND, Comperator.EQUALS, Type.DIGIMON, DigimonList.TSUNOMON)); - - keep.getEvoRequirements().get(ownId - 1).setRequirements(requirements); - - // Evo Paths - setEvolveFrom(keep, ownId, DigimonList.TSUNOMON); - setEvolveTo(keep, ownId, DigimonList.BLACKGARURUMON, DigimonList.GARURUMON, DigimonList.GAOGAMON, DigimonList.VEEDRAMON, DigimonList.LEOMON); - - setDescriptionString(context, ownId, "Focus on MP and high weight.\nEvolves from Tsunomon."); - } - - private void addTsukaimon(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Adding Tsukaimon..."); - - GlobalKeepData keep = context.getGlobalKeepData(); - final short ownId = DigimonList.TSUKAIMON; - final short baseId = DigimonList.PATAMON; - - // Digimon Data - applyBaseData(context, ownId, baseId, (short) 102); - - // Raise Data - DigimonRaising raise = context.getGlobalKeepData().getRaiseData().get(ownId - 1); - raise.setSleepSchedule(7); - raise.setFavoriteFood(45); - raise.setTrainingType((byte) 3); - raise.setLikedAreas((short) 160); - raise.setDislikedAreas((short) 516); - raise.setGains(700, 500, 80, 40, 100, 80); - - // Evo Requirements - List requirements = new ArrayList<>(); - requirements.add(new Requirement(SuperGroup.QUOTA, (byte) 0, Operator.QUOTA, Comperator.QUOTA, Type.QUOTA, 2)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.HIGHEST, Type.SPEED, 0)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 2, Operator.AND, Comperator.GREATER_THAN, Type.WEIGHT, 15)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 3, Operator.AND, Comperator.EQUALS, Type.DIGIMON, DigimonList.TOKOMON)); - - keep.getEvoRequirements().get(ownId - 1).setRequirements(requirements); - - // Evo Paths - setEvolveFrom(keep, ownId, DigimonList.TOKOMON); - setEvolveTo(keep, ownId, DigimonList.DEVIMON, DigimonList.BLACKGATOMON, DigimonList.OGREMON, DigimonList.AIRDRAMON, DigimonList.KABUTERIMON); - - setDescriptionString(context, ownId, "Focus on Speed and high weight.\nEvolves from Tokomon."); - } - - private void addPsychemon(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Adding Psychemon..."); - - GlobalKeepData keep = context.getGlobalKeepData(); - final short ownId = DigimonList.PSYCHEMON; - final short baseId = DigimonList.GABUMON; - - // Digimon Data - applyBaseData(context, ownId, baseId, (short) 103); - - // Raise Data - DigimonRaising raise = context.getGlobalKeepData().getRaiseData().get(ownId - 1); - raise.setSleepSchedule(8); - raise.setFavoriteFood(39); - raise.setTrainingType((byte) 4); - raise.setLikedAreas((short) 160); - raise.setDislikedAreas((short) 516); - raise.setGains(300, 500, 130, 130, 40, 40); - - // Evo Requirements - List requirements = new ArrayList<>(); - requirements.add(new Requirement(SuperGroup.QUOTA, (byte) 0, Operator.QUOTA, Comperator.QUOTA, Type.QUOTA, 2)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.HIGHEST, Type.HP_DIV10, 0)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 2, Operator.AND, Comperator.GREATER_THAN, Type.WEIGHT, 13)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 3, Operator.AND, Comperator.EQUALS, Type.DIGIMON, DigimonList.WANYAMON)); - - keep.getEvoRequirements().get(ownId - 1).setRequirements(requirements); - - // Evo Paths - setEvolveFrom(keep, ownId, DigimonList.WANYAMON); - setEvolveTo(keep, ownId, DigimonList.GURURUMON, DigimonList.KYUBIMON, DigimonList.BAKEMON, DigimonList.TOGEMON, DigimonList.KUWAGAMON); - - setDescriptionString(context, ownId, "Focus on HP and high weight.\nEvolves from Wanyamon.\n\nDon't trust this false prophet."); - } - - private void addSnowAgumon(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Adding SnowAgumon..."); - - GlobalKeepData keep = context.getGlobalKeepData(); - final short ownId = DigimonList.SNOWAGUMON; - final short baseId = DigimonList.AGUMON; - - // Digimon Data - applyBaseData(context, ownId, baseId, (short) 104); - - // Raise Data - DigimonRaising raise = keep.getRaiseData().get(ownId - 1); - raise.setSleepSchedule(3); - raise.setFavoriteFood(39); - raise.setTrainingType((byte) 3); - raise.setLikedAreas((short) 272); - raise.setDislikedAreas((short) 640); - raise.setGains(600, 1000, 60, 40, 110, 50); - - // Evo Requirements - List requirements = new ArrayList<>(); - requirements.add(new Requirement(SuperGroup.QUOTA, (byte) 0, Operator.QUOTA, Comperator.QUOTA, Type.QUOTA, 2)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.HIGHEST, Type.DEFENSE, 0)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 2, Operator.AND, Comperator.LESS_THAN, Type.WEIGHT, 12)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 3, Operator.AND, Comperator.EQUALS, Type.DIGIMON, DigimonList.GIGIMON)); - - keep.getEvoRequirements().get(ownId - 1).setRequirements(requirements); - - // Evo Paths - setEvolveFrom(keep, ownId, DigimonList.GIGIMON); - setEvolveTo(keep, ownId, DigimonList.ICEDEVIMON, DigimonList.IKKAKUMON, DigimonList.GURURUMON, DigimonList.EXVEEMON, DigimonList.CENTARUMON); - - setDescriptionString(context, ownId, "Focus on Defense and low weight.\nEvolves from Gigimon."); - } - - private void addSolarmon(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Adding Solarmon..."); - - GlobalKeepData keep = context.getGlobalKeepData(); - final short baseId = DigimonList.HAGURUMON; - final short ownId = DigimonList.SOLARMON; - - // Digimon Data - applyBaseData(context, ownId, baseId, (short) 105); - - // Raise Data - DigimonRaising raise = keep.getRaiseData().get(ownId - 1); - raise.setSleepSchedule(4); - raise.setFavoriteFood(50); - raise.setTrainingType((byte) 5); - raise.setLikedAreas((short) 1056); - raise.setDislikedAreas((short) 24); - raise.setGains(400, 1000, 120, 50, 55, 55); - - // Evo Requirements - List requirements = new ArrayList<>(); - requirements.add(new Requirement(SuperGroup.QUOTA, (byte) 0, Operator.QUOTA, Comperator.QUOTA, Type.QUOTA, 2)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.HIGHEST, Type.OFFENSE, 0)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 2, Operator.AND, Comperator.GREATER_THAN, Type.WEIGHT, 15)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 3, Operator.AND, Comperator.EQUALS, Type.DIGIMON, DigimonList.MOTIMON)); - - keep.getEvoRequirements().get(ownId - 1).setRequirements(requirements); - - // Evo Paths - setEvolveFrom(keep, ownId, DigimonList.MOTIMON); - setEvolveTo(keep, ownId, DigimonList.GUARDROMON, DigimonList.GROWLMON_ORANGE, DigimonList.BIRDRAMON, DigimonList.VEGIEMON, DigimonList.GEREMON); - - setDescriptionString(context, ownId, "Focus on Offense and high weight.\nEvolves from Motimon."); - } - - private void addBlackGarurumon(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Adding BlackGarurumon..."); - - GlobalKeepData keep = context.getGlobalKeepData(); - final short ownId = DigimonList.BLACKGARURUMON; - final short baseId = DigimonList.GARURUMON; - - // Digimon Data - applyBaseData(context, ownId, baseId, (short) 100); - - // Raise Data - DigimonRaising raise = keep.getRaiseData().get(ownId - 1); - raise.setSleepSchedule(5); - raise.setFavoriteFood(40); - raise.setTrainingType((byte) 1); - raise.setLikedAreas((short) 320); - raise.setDislikedAreas((short) 40); - raise.setGains(2100, 1200, 140, 200, 220, 160); - - // Evo Requirements - List requirements = new ArrayList<>(); - requirements.add(new Requirement(SuperGroup.QUOTA, (byte) 0, Operator.QUOTA, Comperator.QUOTA, Type.QUOTA, 3)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.HP, 1000)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.SPEED, 85)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.DEFENSE, 60)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 2, Operator.AND, Comperator.LESS_THAN, Type.WEIGHT, 25)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 3, Operator.AND, Comperator.LESS_THAN, Type.CARE, 4)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 4, Operator.AND, Comperator.GREATER_THAN, Type.HAPPINESS, 70)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 5, Operator.AND, Comperator.GREATER_THAN, Type.TECHS, 25)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 6, Operator.AND, Comperator.GREATER_THAN, Type.DECODE_LEVEL, 10)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 7, Operator.AND, Comperator.EQUALS, Type.DIGIMON, DigimonList.BLACKGABUMON)); - - keep.getEvoRequirements().get(ownId - 1).setRequirements(requirements); - - // Evo Paths - setEvolveFrom(keep, ownId, DigimonList.BLACKGABUMON, DigimonList.GABUMON, DigimonList.SALAMON, DigimonList.RENAMON); - setEvolveTo(keep, ownId, DigimonList.BLACKWEREGARURUMON, DigimonList.BLUEMERAMON, DigimonList.WARUMONZAEMON); - - setDescriptionString(context, ownId, "Requires HP, DEF and SPD.\nDon't get too heavy. Being happy helps.\nEvolves easier from BlackGabumon."); - } - - private void addGururumon(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Adding Gururumon..."); - - GlobalKeepData keep = context.getGlobalKeepData(); - final short ownId = DigimonList.GURURUMON; - final short baseId = DigimonList.GARURUMON; - - // Digimon Data - applyBaseData(context, ownId, baseId, (short) 101); - - // Raise Data - DigimonRaising raise = keep.getRaiseData().get(ownId - 1); - raise.setSleepSchedule(6); - raise.setFavoriteFood(42); - raise.setTrainingType((byte) 5); - raise.setLikedAreas((short) 320); - raise.setDislikedAreas((short) 40); - raise.setGains(2400, 1200, 140, 210, 130, 210); - - // Evo Requirements - List requirements = new ArrayList<>(); - requirements.add(new Requirement(SuperGroup.QUOTA, (byte) 0, Operator.QUOTA, Comperator.QUOTA, Type.QUOTA, 3)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.HP, 900)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.OFFENSE, 65)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.DEFENSE, 110)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.SPEED, 65)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 2, Operator.AND, Comperator.LESS_THAN, Type.WEIGHT, 25)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 3, Operator.AND, Comperator.GREATER_THAN, Type.CARE, 2)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 4, Operator.AND, Comperator.LESS_THAN, Type.DISCIPLINE, 60)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 5, Operator.AND, Comperator.GREATER_THAN, Type.TECHS, 20)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 6, Operator.AND, Comperator.GREATER_THAN, Type.DECODE_LEVEL, 9)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 7, Operator.AND, Comperator.EQUALS, Type.DIGIMON, DigimonList.PSYCHEMON)); - - keep.getEvoRequirements().get(ownId - 1).setRequirements(requirements); - - // Evo Paths - setEvolveFrom(keep, ownId, DigimonList.PSYCHEMON, DigimonList.SNOWAGUMON, DigimonList.VEEMON, DigimonList.GAOMON); - setEvolveTo(keep, ownId, DigimonList.WEREGARURUMON, DigimonList.ICELEOMON, DigimonList.TAOMON); - - setDescriptionString(context, ownId, "Requires high Defense. Don't get too heavy.\nDoesn't respect authority.\nEvolves easier from Psychemon."); - } - - private void addOrangeGrowlmon(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Adding OrangeGrowlmon..."); - - GlobalKeepData keep = context.getGlobalKeepData(); - final short ownId = DigimonList.GROWLMON_ORANGE; - final short baseId = DigimonList.GROWLMON; - - // Digimon Data - applyBaseData(context, ownId, baseId, (short) 102); - - // Raise Data - DigimonRaising raise = keep.getRaiseData().get(ownId - 1); - raise.setSleepSchedule(5); - raise.setFavoriteFood(40); - raise.setTrainingType((byte) 4); - raise.setLikedAreas((short) 4224); - raise.setDislikedAreas((short) 272); - raise.setGains(1800, 2000, 160, 150, 220, 140); - - // Evo Requirements - List requirements = new ArrayList<>(); - requirements.add(new Requirement(SuperGroup.QUOTA, (byte) 0, Operator.QUOTA, Comperator.QUOTA, Type.QUOTA, 3)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.DEFENSE, 110)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.SPEED, 150)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 2, Operator.AND, Comperator.GREATER_THAN, Type.WEIGHT, 28)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 3, Operator.AND, Comperator.LESS_THAN, Type.CARE, 4)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 4, Operator.AND, Comperator.GREATER_THAN, Type.BATTLES, 10)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 5, Operator.AND, Comperator.GREATER_THAN, Type.TECHS, 18)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 6, Operator.AND, Comperator.GREATER_THAN, Type.DECODE_LEVEL, 12)); - - keep.getEvoRequirements().get(ownId - 1).setRequirements(requirements); - - // Evo Paths - setEvolveFrom(keep, ownId, DigimonList.SOLARMON, DigimonList.GOBURIMON, DigimonList.LALAMON, DigimonList.PATAMON); - setEvolveTo(keep, ownId, DigimonList.WARGROWLMON_ORANGE, DigimonList.RIZEGREYMON, DigimonList.METALGREYMON); - - setDescriptionString(context, ownId, "Requires DEF and SPD. Likes to fight."); - } - - private void addBlackGrowlmon(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Adding BlackGrowlmon..."); - - GlobalKeepData keep = context.getGlobalKeepData(); - final short ownId = DigimonList.BLACKGROWLMON; - final short baseId = DigimonList.GROWLMON; - - // Digimon Data - applyBaseData(context, ownId, baseId, (short) 103); - - // Raise Data - DigimonRaising raise = keep.getRaiseData().get(ownId - 1); - raise.setSleepSchedule(5); - raise.setFavoriteFood(40); - raise.setTrainingType((byte) 5); - raise.setLikedAreas((short) 4224); - raise.setDislikedAreas((short) 272); - raise.setGains(2000, 1900, 210, 180, 140, 130); - - // Evo Requirements - List requirements = new ArrayList<>(); - requirements.add(new Requirement(SuperGroup.QUOTA, (byte) 0, Operator.QUOTA, Comperator.QUOTA, Type.QUOTA, 3)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.HP, 800)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.OFFENSE, 110)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.DEFENSE, 110)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 2, Operator.AND, Comperator.GREATER_THAN, Type.WEIGHT, 28)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 3, Operator.AND, Comperator.LESS_THAN, Type.CARE, 5)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 4, Operator.AND, Comperator.GREATER_THAN, Type.BATTLES, 15)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 5, Operator.AND, Comperator.GREATER_THAN, Type.TECHS, 19)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 6, Operator.AND, Comperator.GREATER_THAN, Type.DECODE_LEVEL, 13)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 7, Operator.AND, Comperator.EQUALS, Type.DIGIMON, DigimonList.BLACKAGUMON)); - - keep.getEvoRequirements().get(ownId - 1).setRequirements(requirements); - - // Evo Paths - setEvolveFrom(keep, ownId, DigimonList.BLACKAGUMON, DigimonList.AGUMON, DigimonList.BETAMON, DigimonList.GUILMON); - setEvolveTo(keep, ownId, DigimonList.BLACK_WARGROWLMON, DigimonList.METALGREYMON_VIRUS, DigimonList.MEGADRAMON); - - setDescriptionString(context, ownId, "Requires HP, Offense and Defense.\nLikes to fight.\nEvolves easier from BlackAgumon."); - } - - private void addIceDevimon(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Adding IceDevimon..."); - - GlobalKeepData keep = context.getGlobalKeepData(); - final short ownId = DigimonList.ICEDEVIMON; - final short baseId = DigimonList.DEVIMON; - - // Digimon Data - applyBaseData(context, ownId, baseId, (short) 104); - - // Raise Data - DigimonRaising raise = keep.getRaiseData().get(ownId - 1); - raise.setSleepSchedule(4); - raise.setFavoriteFood(49); - raise.setTrainingType((byte) 4); - raise.setLikedAreas((short) 272); - raise.setDislikedAreas((short) 640); - raise.setGains(2200, 1200, 150, 200, 2200, 140); - - // Evo Requirements - List requirements = new ArrayList<>(); - requirements.add(new Requirement(SuperGroup.QUOTA, (byte) 0, Operator.QUOTA, Comperator.QUOTA, Type.QUOTA, 3)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.MP, 1150)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.SPEED, 85)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.BRAINS, 85)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 2, Operator.AND, Comperator.LESS_THAN, Type.WEIGHT, 30)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 3, Operator.AND, Comperator.GREATER_THAN, Type.CARE, 2)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 4, Operator.AND, Comperator.GREATER_THAN, Type.DISCIPLINE, 70)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 5, Operator.AND, Comperator.GREATER_THAN, Type.TECHS, 25)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 6, Operator.AND, Comperator.GREATER_THAN, Type.DECODE_LEVEL, 12)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 7, Operator.AND, Comperator.EQUALS, Type.DIGIMON, DigimonList.SNOWAGUMON)); - - keep.getEvoRequirements().get(ownId - 1).setRequirements(requirements); - - // Evo Paths - setEvolveFrom(keep, ownId, DigimonList.SNOWAGUMON, DigimonList.DEMIDEVIMON, DigimonList.GOMAMON, DigimonList.KAMEMON); - setEvolveTo(keep, ownId, DigimonList.ZUDOMON, DigimonList.LADYDEVIMON, DigimonList.DIGITAMAMON); - - setDescriptionString(context, ownId, "Requires MP, Speed and Brains.\nDon't get too heavy. Being disciplined helps.\nEvolves easier from SnowAgumon."); - } - - private void addGeremon(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Adding Geremon..."); - - GlobalKeepData keep = context.getGlobalKeepData(); - final short ownId = DigimonList.GEREMON; - final short baseId = DigimonList.NUMEMON; - - // Digimon Data - applyBaseData(context, ownId, baseId, (short) 105); - - // Raise Data - DigimonRaising raise = keep.getRaiseData().get(ownId - 1); - raise.setSleepSchedule(7); - raise.setFavoriteFood(47); - raise.setTrainingType((byte) 1); - raise.setLikedAreas((short) 96); - raise.setDislikedAreas((short) 2304); - raise.setGains(1300, 1600, 180, 200, 150, 130); - - // Evo Requirements - List requirements = new ArrayList<>(); - requirements.add(new Requirement(SuperGroup.QUOTA, (byte) 0, Operator.QUOTA, Comperator.QUOTA, Type.QUOTA, 3)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.HP, 900)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.OFFENSE, 65)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.DEFENSE, 110)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.SPEED, 65)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 2, Operator.AND, Comperator.LESS_THAN, Type.WEIGHT, 25)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 3, Operator.AND, Comperator.GREATER_THAN, Type.CARE, 2)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 4, Operator.AND, Comperator.LESS_THAN, Type.DISCIPLINE, 80)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 5, Operator.AND, Comperator.GREATER_THAN, Type.TECHS, 20)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 6, Operator.AND, Comperator.GREATER_THAN, Type.DECODE_LEVEL, 9)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 7, Operator.AND, Comperator.EQUALS, Type.DIGIMON, DigimonList.PSYCHEMON)); - - keep.getEvoRequirements().get(ownId - 1).setRequirements(requirements); - - // Evo Paths - setEvolveFrom(keep, ownId, DigimonList.SOLARMON, DigimonList.CHUUMON); - setEvolveTo(keep, ownId, DigimonList.MONZAEMON, DigimonList.ETEMON); - - setDescriptionString(context, ownId, "Requires high Defense. Don't get too heavy.\nYou probably want to avoid this one.\nEvolves easier from Psychemon."); - } - - private void addMetalGreymonVirus(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Adding MetalGreymon (Virus)..."); - - GlobalKeepData keep = context.getGlobalKeepData(); - final short ownId = DigimonList.METALGREYMON_VIRUS; - final short baseId = DigimonList.METALGREYMON; - - // Digimon Data - applyBaseData(context, ownId, baseId, (short) 100); - - // Raise Data - DigimonRaising raise = keep.getRaiseData().get(ownId - 1); - raise.setSleepSchedule(6); - raise.setFavoriteFood(41); - raise.setTrainingType((byte) 5); - raise.setLikedAreas((short) 4224); - raise.setDislikedAreas((short) 2064); - raise.setGains(3000, 4200, 380, 340, 310, 350); - - // Evo Requirements - List requirements = new ArrayList<>(); - requirements.add(new Requirement(SuperGroup.QUOTA, (byte) 0, Operator.QUOTA, Comperator.QUOTA, Type.QUOTA, 5)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.HP, 2000)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.MP, 3000)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 2, Operator.AND, Comperator.GREATER_THAN, Type.OFFENSE, 350)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 2, Operator.AND, Comperator.GREATER_THAN, Type.DEFENSE, 200)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 3, Operator.AND, Comperator.GREATER_THAN, Type.BRAINS, 270)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 4, Operator.AND, Comperator.GREATER_THAN, Type.WEIGHT, 45)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 5, Operator.AND, Comperator.GREATER_THAN, Type.CARE, 3)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 6, Operator.AND, Comperator.GREATER_THAN, Type.DISCIPLINE, 75)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 6, Operator.AND, Comperator.GREATER_THAN, Type.BATTLES, 25)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 7, Operator.AND, Comperator.GREATER_THAN, Type.TECHS, 32)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 8, Operator.AND, Comperator.GREATER_THAN, Type.DECODE_LEVEL, 15)); - - keep.getEvoRequirements().get(ownId - 1).setRequirements(requirements); - - // Evo Paths - setEvolveFrom(keep, ownId, DigimonList.BLACKGROWLMON, DigimonList.GREYMON); - setEvolveTo(keep, ownId, DigimonList.BLACKWARGREYMON, DigimonList.MACHINEDRAMON); - - setDescriptionString(context, ownId, "Requires high overall stats.\nDon't save on food.\nBeing disciplined helps."); - } - - private void addWarGrowlmonBlack(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Adding BlackWarGrowlmon..."); - - GlobalKeepData keep = context.getGlobalKeepData(); - final short ownId = DigimonList.BLACK_WARGROWLMON; - final short baseId = DigimonList.WARGROWLMON; - - // Digimon Data - applyBaseData(context, ownId, baseId, (short) 101); - - // Raise Data - DigimonRaising raise = keep.getRaiseData().get(ownId - 1); - raise.setSleepSchedule(5); - raise.setFavoriteFood(41); - raise.setTrainingType((byte) 4); - raise.setLikedAreas((short) 4224); - raise.setDislikedAreas((short) 272); - raise.setGains(3000, 2800, 340, 400, 460, 320); - - // Evo Requirements - List requirements = new ArrayList<>(); - requirements.add(new Requirement(SuperGroup.QUOTA, (byte) 0, Operator.QUOTA, Comperator.QUOTA, Type.QUOTA, 5)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.HP, 3000)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 2, Operator.AND, Comperator.GREATER_THAN, Type.DEFENSE, 360)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 3, Operator.AND, Comperator.GREATER_THAN, Type.SPEED, 230)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 3, Operator.AND, Comperator.GREATER_THAN, Type.BRAINS, 290)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 4, Operator.AND, Comperator.GREATER_THAN, Type.WEIGHT, 50)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 5, Operator.AND, Comperator.LESS_THAN, Type.CARE, 10)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 6, Operator.AND, Comperator.GREATER_THAN, Type.BATTLES, 30)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 7, Operator.AND, Comperator.GREATER_THAN, Type.TECHS, 28)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 8, Operator.AND, Comperator.GREATER_THAN, Type.DECODE_LEVEL, 13)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 9, Operator.AND, Comperator.EQUALS, Type.DIGIMON, DigimonList.BLACKGROWLMON)); - - keep.getEvoRequirements().get(ownId - 1).setRequirements(requirements); - - // Evo Paths - setEvolveFrom(keep, ownId, DigimonList.BLACKGROWLMON, DigimonList.GROWLMON); - setEvolveTo(keep, ownId, DigimonList.CHAOSGALLANTMON, DigimonList.DARKDRAMON); - - setDescriptionString(context, ownId, "Requires HP, Defense and Brains.\nKeep some food around. Likes to fight.\nEvolves easier from BlackGrowlmon."); - } - - private void addWarGrowlmonOrange(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Adding OrangeWarGrowlmon..."); - - GlobalKeepData keep = context.getGlobalKeepData(); - final short ownId = DigimonList.WARGROWLMON_ORANGE; - final short baseId = DigimonList.WARGROWLMON; - - // Digimon Data - applyBaseData(context, ownId, baseId, (short) 102); - - // Raise Data - DigimonRaising raise = keep.getRaiseData().get(ownId - 1); - raise.setSleepSchedule(5); - raise.setFavoriteFood(41); - raise.setTrainingType((byte) 1); - raise.setLikedAreas((short) 4224); - raise.setDislikedAreas((short) 272); - raise.setGains(4000, 2500, 250, 410, 310, 480); - - // Evo Requirements - List requirements = new ArrayList<>(); - requirements.add(new Requirement(SuperGroup.QUOTA, (byte) 0, Operator.QUOTA, Comperator.QUOTA, Type.QUOTA, 5)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.HP, 2700)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 2, Operator.AND, Comperator.GREATER_THAN, Type.OFFENSE, 210)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 2, Operator.AND, Comperator.GREATER_THAN, Type.DEFENSE, 360)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 3, Operator.AND, Comperator.GREATER_THAN, Type.BRAINS, 370)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 4, Operator.AND, Comperator.GREATER_THAN, Type.WEIGHT, 45)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 5, Operator.AND, Comperator.LESS_THAN, Type.CARE, 10)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 6, Operator.AND, Comperator.GREATER_THAN, Type.BATTLES, 30)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 7, Operator.AND, Comperator.GREATER_THAN, Type.TECHS, 30)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 8, Operator.AND, Comperator.GREATER_THAN, Type.DECODE_LEVEL, 13)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 9, Operator.AND, Comperator.EQUALS, Type.DIGIMON, DigimonList.GROWLMON_ORANGE)); - - keep.getEvoRequirements().get(ownId - 1).setRequirements(requirements); - - // Evo Paths - setEvolveFrom(keep, ownId, DigimonList.GROWLMON_ORANGE, DigimonList.TYRANNOMON); - setEvolveTo(keep, ownId, DigimonList.RUSTTYRANNOMON, DigimonList.PRINCEMAMEMON); - - setDescriptionString(context, ownId, "Requires HP, Defense and Brains.\nKeep some food around. Likes to fight.\nEvolves easier from OrangeGrowlmon."); - } - - private void addBlackWereGarurumon(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Adding BlackWereGarurumon..."); - - GlobalKeepData keep = context.getGlobalKeepData(); - final short ownId = DigimonList.BLACKWEREGARURUMON; - final short baseId = DigimonList.WEREGARURUMON; - - // Digimon Data - applyBaseData(context, ownId, baseId, (short) 103); - - // Raise Data - DigimonRaising raise = keep.getRaiseData().get(ownId - 1); - raise.setSleepSchedule(5); - raise.setFavoriteFood(53); - raise.setTrainingType((byte) 1); - raise.setLikedAreas((short) 576); - raise.setDislikedAreas((short) 4112); - raise.setGains(3200, 2600, 400, 330, 440, 350); - - // Evo Requirements - List requirements = new ArrayList<>(); - requirements.add(new Requirement(SuperGroup.QUOTA, (byte) 0, Operator.QUOTA, Comperator.QUOTA, Type.QUOTA, 5)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.HP, 2000)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.MP, 2000)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 2, Operator.AND, Comperator.GREATER_THAN, Type.OFFENSE, 310)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 3, Operator.AND, Comperator.GREATER_THAN, Type.SPEED, 350)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 4, Operator.AND, Comperator.LESS_THAN, Type.WEIGHT, 40)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 5, Operator.AND, Comperator.LESS_THAN, Type.CARE, 15)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 6, Operator.AND, Comperator.GREATER_THAN, Type.HAPPINESS, 80)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 6, Operator.AND, Comperator.GREATER_THAN, Type.BATTLES, 25)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 7, Operator.AND, Comperator.GREATER_THAN, Type.TECHS, 35)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 8, Operator.AND, Comperator.GREATER_THAN, Type.DECODE_LEVEL, 14)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 9, Operator.AND, Comperator.EQUALS, Type.DIGIMON, DigimonList.BLACKGARURUMON)); - - keep.getEvoRequirements().get(ownId - 1).setRequirements(requirements); - - // Evo Paths - setEvolveFrom(keep, ownId, DigimonList.BLACKGARURUMON, DigimonList.GARURUMON, DigimonList.BLACKGATOMON); - setEvolveTo(keep, ownId, DigimonList.BLACKMETALGARURUMON, DigimonList.PIEDMON); - - setDescriptionString(context, ownId, "Strong, fast and nimble fighter.\nEvolves easier from BlackGarurumon."); - } - - private void addBlackWarGreymon(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Adding BlackWarGreymon..."); - - GlobalKeepData keep = context.getGlobalKeepData(); - final short ownId = DigimonList.BLACKWARGREYMON; - final short baseId = DigimonList.WARGREYMON; - - // Digimon Data - applyBaseData(context, ownId, baseId, (short) 100); - - // Raise Data - DigimonRaising raise = keep.getRaiseData().get(ownId - 1); - raise.setSleepSchedule(5); - raise.setFavoriteFood(57); - raise.setTrainingType((byte) 4); - raise.setLikedAreas((short) 40); - raise.setDislikedAreas((short) 1152); - raise.setGains(5800, 6700, 770, 460, 660, 870); - - // Evo Requirements - List requirements = new ArrayList<>(); - requirements.add(new Requirement(SuperGroup.QUOTA, (byte) 0, Operator.QUOTA, Comperator.QUOTA, Type.QUOTA, 6)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.HP, 5500)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 2, Operator.AND, Comperator.GREATER_THAN, Type.OFFENSE, 650)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 3, Operator.AND, Comperator.GREATER_THAN, Type.DEFENSE, 550)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 4, Operator.AND, Comperator.GREATER_THAN, Type.BRAINS, 420)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 5, Operator.AND, Comperator.GREATER_THAN, Type.WEIGHT, 55)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 6, Operator.AND, Comperator.LESS_THAN, Type.CARE, 10)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 7, Operator.AND, Comperator.GREATER_THAN, Type.DISCIPLINE, 80)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 8, Operator.AND, Comperator.GREATER_THAN, Type.TECHS, 40)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 9, Operator.AND, Comperator.GREATER_THAN, Type.DECODE_LEVEL, 16)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 10, Operator.AND, Comperator.EQUALS, Type.DIGIMON, DigimonList.METALGREYMON_VIRUS)); - - keep.getEvoRequirements().get(ownId - 1).setRequirements(requirements); - - // Evo Paths - setEvolveFrom(keep, ownId, DigimonList.METALGREYMON_VIRUS, DigimonList.METALGREYMON); - - setDescriptionString(context, ownId, "A perfect balance of offensive.\nand defense capabilities.\nRequires disciplined training and good food.\nEvolves from MetalGreymon."); - } - - private void addChaosDukemon(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Adding ChaosDukemon..."); - - GlobalKeepData keep = context.getGlobalKeepData(); - final short ownId = DigimonList.CHAOSGALLANTMON; - final short baseId = DigimonList.GALLANTMON; - - // Digimon Data - applyBaseData(context, ownId, baseId, (short) 101); - - // Raise Data - DigimonRaising raise = keep.getRaiseData().get(ownId - 1); - raise.setSleepSchedule(4); - raise.setFavoriteFood(60); - raise.setTrainingType((byte) 0); - raise.setLikedAreas((short) 2056); - raise.setDislikedAreas((short) 1056); - raise.setGains(6300, 6500, 750, 600, 600, 620); - - // Evo Requirements - List requirements = new ArrayList<>(); - requirements.add(new Requirement(SuperGroup.QUOTA, (byte) 0, Operator.QUOTA, Comperator.QUOTA, Type.QUOTA, 8)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.HP, 4000)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 2, Operator.AND, Comperator.GREATER_THAN, Type.MP, 3000)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 3, Operator.AND, Comperator.GREATER_THAN, Type.OFFENSE, 600)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 4, Operator.AND, Comperator.GREATER_THAN, Type.DEFENSE, 600)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 5, Operator.AND, Comperator.GREATER_THAN, Type.SPEED, 700)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 6, Operator.AND, Comperator.GREATER_THAN, Type.BRAINS, 500)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 7, Operator.AND, Comperator.GREATER_THAN, Type.WEIGHT, 60)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 8, Operator.AND, Comperator.LESS_THAN, Type.CARE, 10)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 9, Operator.AND, Comperator.GREATER_THAN, Type.HAPPINESS, 80)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 10, Operator.AND, Comperator.GREATER_THAN, Type.TECHS, 42)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 11, Operator.AND, Comperator.GREATER_THAN, Type.DECODE_LEVEL, 17)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 12, Operator.AND, Comperator.EQUALS, Type.DIGIMON, DigimonList.BLACK_WARGROWLMON)); - - keep.getEvoRequirements().get(ownId - 1).setRequirements(requirements); - - // Evo Paths - setEvolveFrom(keep, ownId, DigimonList.BLACK_WARGROWLMON, DigimonList.WARGROWLMON); - - setDescriptionString(context, ownId, "Requires high overall stats. Likes good food.\nEvolves easier from BlackWarGrowlmon."); - } - - private void addBlackMetalGarurumon(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Adding BlackMetalGarurumon..."); - - GlobalKeepData keep = context.getGlobalKeepData(); - final short ownId = DigimonList.BLACKMETALGARURUMON; - final short baseId = DigimonList.METALGARURUMON; - - // Digimon Data - applyBaseData(context, ownId, baseId, (short) 102); - - // Raise Data - DigimonRaising raise = keep.getRaiseData().get(ownId - 1); - raise.setSleepSchedule(4); - raise.setFavoriteFood(59); - raise.setTrainingType((byte) 0); - raise.setLikedAreas((short) 320); - raise.setDislikedAreas((short) 136); - raise.setGains(9300, 4700, 520, 690, 750, 450); - - // Evo Requirements - List requirements = new ArrayList<>(); - requirements.add(new Requirement(SuperGroup.QUOTA, (byte) 0, Operator.QUOTA, Comperator.QUOTA, Type.QUOTA, 7)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 1, Operator.AND, Comperator.GREATER_THAN, Type.MP, 4500)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 2, Operator.AND, Comperator.GREATER_THAN, Type.OFFENSE, 500)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 3, Operator.AND, Comperator.GREATER_THAN, Type.DEFENSE, 700)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 4, Operator.AND, Comperator.GREATER_THAN, Type.SPEED, 700)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 5, Operator.AND, Comperator.GREATER_THAN, Type.BRAINS, 400)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 6, Operator.AND, Comperator.LESS_THAN, Type.WEIGHT, 50)); - requirements.add(new Requirement(SuperGroup.NORMAL, (byte) 7, Operator.AND, Comperator.LESS_THAN, Type.CARE, 15)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 8, Operator.AND, Comperator.GREATER_THAN, Type.HAPPINESS, 80)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 9, Operator.AND, Comperator.GREATER_THAN, Type.DISCIPLINE, 80)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 10, Operator.AND, Comperator.GREATER_THAN, Type.TECHS, 44)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 11, Operator.AND, Comperator.GREATER_THAN, Type.DECODE_LEVEL, 17)); - requirements.add(new Requirement(SuperGroup.BONUS, (byte) 12, Operator.AND, Comperator.EQUALS, Type.DIGIMON, DigimonList.BLACKWEREGARURUMON)); - - keep.getEvoRequirements().get(ownId - 1).setRequirements(requirements); - - // Evo Paths - setEvolveFrom(keep, ownId, DigimonList.BLACKWEREGARURUMON, DigimonList.WEREGARURUMON); - - setDescriptionString(context, ownId, "Very fast and defensive.\nKeep a disciplined diet, but don't get depressed.\nEvolves easier from BlackWereGarurumon."); - } - - private void setDescriptionString(RandomizationContext context, short ownId, String string) { - context.getLanguageKeep().getDigimonDescription().getEntryById(ownId).ifPresent(a -> a.setString(string)); - } - - @SuppressWarnings("unused") - private static void registerSprite(RandomizationContext context, short id, BufferedImage image) { - Optional images = context.getFile("part0/arcv/Keep/GlobalKeepRes.res").map(AbstractKCAP.class::cast).map(a -> (GMIPKCAP) a.get(8)); - - if(images.isEmpty()) - return; - - GMIOPayload gmio = new GMIOPayload(null); - gmio.setImage(image); - gmio.setFormat(PixelFormat.RGB5551); - gmio.setMinFilter(TextureFiltering.LINEAR); - gmio.setMagFilter(TextureFiltering.LINEAR); - gmio.setUnknown(UnknownEnum.NORMAL); - gmio.setUVHeightAbsolute(16); - gmio.setUVWidthAbsolute(68); - gmio.setWrapS(TextureWrap.CLAMP_TO_EDGE); - gmio.setWrapT(TextureWrap.CLAMP_TO_EDGE); - - images.get().add(gmio); - - for(int offset : SPRITE_TABLES) { - context.addASM(String.format(".org 0x%X", offset + id * 2)); - context.addASM(String.format(".halfword %d", 0x145 + images.get().getEntryCount() - 1)); - } - } - - private static final int[] SPRITE_TABLES = { 0x4A4330, 0x4A4E00, 0x4A527C, 0x4A6E00, 0x4A9AB0, 0x4AA564, 0x4AAFBC, 0x4AB678, 0x4ABD40, 0x4AC510, 0x4ACA90, - 0x4AE12C, 0x4AE828, 0x4AF108, 0x4AFE08 }; - - private static void applyBaseData(RandomizationContext context, short self, short base, short evoListPos) { - Digimon baseData = context.getGlobalKeepData().getDigimonData().get(base - 1); - Digimon data = context.getGlobalKeepData().getDigimonData().get(self - 1); - - data.setEvoListPos(evoListPos); - data.setInitialY(baseData.getInitialY()); - data.setInitialZ(baseData.getInitialZ()); - data.setMinY(baseData.getMinY()); - data.setMinZ(baseData.getMinZ()); - data.setMaxY(baseData.getMaxY()); - data.setMaxZ(baseData.getMaxZ()); - data.setInitialRotation(baseData.getInitialRotation()); - data.setDigiviceScale(baseData.getDigiviceScale()); - data.setUnk7(baseData.getUnk7()); - data.setUnk8(baseData.getUnk8()); - data.setUnk11(baseData.getUnk11()); - data.setUnk38((short) (data.getUnk38() | 65)); - - Optional baseDigi = context.getDigimon(base, true); - Optional modDigi = context.getDigimon(self); - - if(baseDigi.isEmpty() || modDigi.isEmpty()) - return; - - if(modDigi.get().getAnim5().isEmpty()) - modDigi.ifPresent(b -> b.setAnim5(baseDigi.map(a -> a.getAnim5().orElse(null)))); - - if(modDigi.get().getAccessoryData().isEmpty()) - modDigi.ifPresent(b -> b.setAccessoryData(baseDigi.map(PartnerDigimon::getAccessoryData).orElse(Collections.emptyList()))); - } - - private static void setEvolveFrom(GlobalKeepData keep, short self, short... sources) { - DigimonRaising data = keep.getRaiseData().get(self - 1); - - for (short source : sources) { - data.addEvolveFrom(source); - keep.getRaiseData().get(source - 1).addEvolveTo(self); - } - } - - private static void setEvolveTo(GlobalKeepData keep, short self, short... targets) { - DigimonRaising data = keep.getRaiseData().get(self - 1); - - for (short target : targets) { - data.addEvolveTo(target); - keep.getRaiseData().get(target - 1).addEvolveFrom(self); - } - } - - private void patchMovementSpeed(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Patching running speed..."); - - float newRunSpeed = 50f * 1.5f; - float newWalkSpeed = 21f; - float newEnemySpeed = 57.5f * 1.5f; - - context.addASM(".org 0x44B8B8"); - context.addASM(String.format(Locale.US, ".float %5.3f", newRunSpeed)); - context.addASM(String.format(Locale.US, ".float %5.3f", newWalkSpeed)); - - context.addASM(".org 0x2FDCE8"); - context.addASM(String.format(Locale.US, ".float %5.3f", newEnemySpeed)); - } - - private void disable90FBattles(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Patching out 90F battle..."); - - context.getFile("part0/arcv/map/are90.res").ifPresent(a -> { - byte[] data = ((GenericPayload) ((AbstractKCAP) a).get(0)).getData(); - data[0x30D8] = 0x7D; // JZ -> J - data[0x30D9] = 0x60; // 101 -> 96 - }); - } - - private void patchStartMPDisc(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Patching starting MP Disc..."); - - context.addASM(".org 0x27AD7C"); - context.addASM("MOV R0, #5"); - } - - private void patchBrainsChance(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Patching Brains learning chance..."); - - context.addASM(".org 0x14B820"); - context.addASM(String.format(Locale.US, ".float %5.3f", 0.002 * Math.max(1D, patchBrainsChanceFactor.get()))); - } - - private void patchViewDistance(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Patching view distance..."); - - context.addASM(".org 0x4E5118"); - context.addASM(".float 1000.0"); - context.addASM(".float 1000.0"); - context.addASM(".org 0x44CC48"); - context.addASM(".float 1000.0"); - context.addASM(".float 1000.0"); - context.addASM(".org 0x1F9F74"); - context.addASM(".float 1000.0"); - context.addASM(".float 1000.0"); - context.addASM(".org 0x2C56B8"); - context.addASM("NOP"); - context.addASM(".org 0x2C56C4"); - context.addASM("NOP"); - } - - @Override - public Map serialize() { - Map map = new HashMap<>(); - - map.put("patchViewDistance", patchViewDistance.get()); - map.put("patchBrainsChance", patchBrainsChance.get()); - map.put("patchBrainsChanceFactor", patchBrainsChanceFactor.get()); - map.put("patchStartMPDisc", patchStartMPDisc.get()); - map.put("patchDisable90FBattles", patchDisable90FBattles.get()); - map.put("patchMovementSpeed", patchMovementSpeed.get()); - map.put("patchAddRecolorDigimon", patchAddRecolorDigimon.get()); - map.put("patchListOrder", patchListOrder.get()); - - return map; - } - - @Override - public void load(YamlMapping map) { - if (map == null) - return; - - this.patchViewDistance.set(Boolean.parseBoolean(map.string("patchViewDistance"))); - this.patchBrainsChance.set(Boolean.parseBoolean(map.string("patchBrainsChance"))); - this.patchBrainsChanceFactor.set(map.doubleNumber("patchBrainsChanceFactor")); - this.patchStartMPDisc.set(Boolean.parseBoolean(map.string("patchStartMPDisc"))); - this.patchDisable90FBattles.set(Boolean.parseBoolean(map.string("patchDisable90FBattles"))); - this.patchMovementSpeed.set(Boolean.parseBoolean(map.string("patchMovementSpeed"))); - this.patchAddRecolorDigimon.set(Boolean.parseBoolean(map.string("patchAddRecolorDigimon"))); - this.patchListOrder.set(Boolean.parseBoolean(map.string("patchListOrder"))); - } - -} diff --git a/src/main/java/net/digimonworld/decode/randomizer/settings/PlayerSettings.java b/src/main/java/net/digimonworld/decode/randomizer/settings/PlayerSettings.java deleted file mode 100644 index 9bd8982..0000000 --- a/src/main/java/net/digimonworld/decode/randomizer/settings/PlayerSettings.java +++ /dev/null @@ -1,151 +0,0 @@ -package net.digimonworld.decode.randomizer.settings; - -import java.util.Arrays; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Random; -import java.util.stream.Collectors; - -import org.controlsfx.control.CheckListView; - -import com.amihaiemil.eoyaml.YamlMapping; - -import net.digimonworld.decodetools.data.keepdata.GlobalKeepData; -import net.digimonworld.decodetools.data.keepdata.LanguageKeep; -import javafx.beans.property.BooleanProperty; -import javafx.beans.property.SimpleBooleanProperty; -import javafx.collections.FXCollections; -import javafx.geometry.Pos; -import javafx.scene.control.TitledPane; -import javafx.scene.control.cell.CheckBoxListCell; -import javafx.scene.layout.VBox; -import net.digimonworld.decode.randomizer.RandomizationContext; -import net.digimonworld.decode.randomizer.RandoLogger.LogLevel; -import net.digimonworld.decode.randomizer.utils.JavaFXUtils; - -public class PlayerSettings implements Setting { - // TODO pronouns, requires translation patch 1.1 - // TODO cutins, see 0x4D8624 and 0x4D8628 | requires target value to have _01 to _10, otherwise the game will crash when trying to load those - // TODO voice? - - - private BooleanProperty enabled = new SimpleBooleanProperty(); - private Map checkedMap = new EnumMap<>(Character.class); - - @Override - public TitledPane create(GlobalKeepData inputData, LanguageKeep languageKeep) { - VBox vbox = new VBox(8); - TitledPane pane = new TitledPane("Player", vbox); - vbox.setAlignment(Pos.TOP_LEFT); - pane.setCollapsible(false); - pane.setPrefHeight(400); - - Arrays.stream(Character.values()).forEach(a -> checkedMap.put(a, new SimpleBooleanProperty())); - CheckListView list = new CheckListView<>(FXCollections.observableArrayList(Character.values())); - list.disableProperty().bind(enabled.not()); - list.setCellFactory(listView -> new CheckBoxListCell<>(checkedMap::get) { - @Override - public void updateItem(Character a, boolean b) { - super.updateItem(a, b); - setText(a == null ? "" : languageKeep.getCharacterNames().getStringById(a.getStringId())); - } - }); - - vbox.getChildren().addAll(JavaFXUtils.buildToggleSwitch("Enabled", Optional.empty(), Optional.of(enabled)), list); - return pane; - } - - @Override - public void randomize(RandomizationContext context) { - if (enabled.get()) - randomizePlayer(context); - } - - private void randomizePlayer(RandomizationContext context) { - List list = checkedMap.entrySet().stream().filter(a -> a.getValue().get()).map(Map.Entry::getKey).collect(Collectors.toList()); - - if (list.isEmpty()) - return; - - context.logLine(LogLevel.ALWAYS, "Randomizing player character..."); - Random rand = new Random(context.getInitialSeed() * "Player".hashCode()); - - Character starterRina = list.get(rand.nextInt(list.size())); - Character starterTaiga = list.get(rand.nextInt(list.size())); - - context.addASM(".org 0x4A1CDE"); - context.addASM(String.format(".ascii \"%s\"", starterTaiga.getFileName())); - context.addASM(".org 0x4A1D4E"); - context.addASM(String.format(".ascii \"%s\"", starterRina.getFileName())); - - context.logLine(LogLevel.CASUAL, - String.format("Randomized Rina's Character to %s.", - context.getLanguageKeep().getCharacterNames().getStringById(starterRina.getStringId()))); - context.logLine(LogLevel.CASUAL, - String.format("Randomized Taiga's Character to %s.", - context.getLanguageKeep().getCharacterNames().getStringById(starterTaiga.getStringId()))); - } - - @Override - public Map serialize() { - Map map = new HashMap<>(); - - map.put("enabled", enabled.get()); - map.put("checked", checkedMap.entrySet().stream().collect(Collectors.toMap(a -> a.getKey().toString(), a -> a.getValue().get()))); - - return map; - } - - @Override - public void load(YamlMapping map) { - if (map == null) - return; - - YamlMapping list = map.yamlMapping("checked"); - Arrays.asList(Character.values()) - .forEach(a -> checkedMap.computeIfAbsent(a, b -> new SimpleBooleanProperty()).setValue(Boolean.parseBoolean(list.string(a.toString())))); - enabled.set(Boolean.parseBoolean(map.string("enabled"))); - } - - public enum Character { - TAIGA("pc01.res", 1062, Pronoun.HE), - RINA("pc02.res", 1063, Pronoun.SHE), - AKIHO("Npc01.res", 1002, Pronoun.SHE), - NIKO("Npc02.res", 1003, Pronoun.HE), - YUUYA("Npc03.res", 1004, Pronoun.HE), - MIREI("Npc04.res", 1005, Pronoun.SHE), - PETROV("Npc05.res", 1006, Pronoun.HE), - LILY("Npc10.res", 1007, Pronoun.SHE); - - private final String fileName; - private final int stringId; - private final Pronoun pronoun; - - private Character(String fileName, int stringId, Pronoun pronoun) { - this.fileName = fileName; - this.stringId = stringId; - this.pronoun = pronoun; - } - - public String getFileName() { - return fileName; - } - - public int getStringId() { - return stringId; - } - - public Pronoun getPronoun() { - return pronoun; - } - } - - public enum Pronoun { - HE, - SHE, - THEY; - } -} diff --git a/src/main/java/net/digimonworld/decode/randomizer/settings/RandomizerSettings.java b/src/main/java/net/digimonworld/decode/randomizer/settings/RandomizerSettings.java deleted file mode 100644 index 49b3ced..0000000 --- a/src/main/java/net/digimonworld/decode/randomizer/settings/RandomizerSettings.java +++ /dev/null @@ -1,111 +0,0 @@ -package net.digimonworld.decode.randomizer.settings; - -import java.io.IOException; -import java.io.StringWriter; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import com.amihaiemil.eoyaml.Yaml; -import com.amihaiemil.eoyaml.YamlMapping; - -import net.digimonworld.decodetools.core.Tuple; -import net.digimonworld.decodetools.data.keepdata.GlobalKeepData; -import net.digimonworld.decodetools.data.keepdata.LanguageKeep; -import javafx.geometry.Insets; -import javafx.geometry.Orientation; -import javafx.scene.control.Tab; -import javafx.scene.layout.FlowPane; -import net.digimonworld.decode.randomizer.RandoLogger.LogLevel; -import net.digimonworld.decode.randomizer.RandomizationContext; - -public class RandomizerSettings { - private SkillsSettings skillSettings = new SkillsSettings(); - private DigimonSettings digimonSettings = new DigimonSettings(); - private EvolutionSettings evolutionSettings = new EvolutionSettings(); - private StarterSettings starterSettings = new StarterSettings(); - private WorldSettings worldSettings = new WorldSettings(); - private PatchSettings patchSettings = new PatchSettings(); - private PlayerSettings playerSettings = new PlayerSettings(); - - public void randomize(RandomizationContext context) { - logSettings(context); - - patchSettings.randomize(context); - skillSettings.randomize(context); - digimonSettings.randomize(context); - evolutionSettings.randomize(context); - starterSettings.randomize(context); - worldSettings.randomize(context); - playerSettings.randomize(context); - } - - private void logSettings(RandomizationContext context) { - context.logLine(LogLevel.ALWAYS, "Randomizer Settings: "); - - Map configMap = new HashMap<>(); - configMap.put("seed", context.getInitialSeed()); - configMap.put("settings", serialize()); - configMap.put("raceLogging", context.isRaceLogging()); - - try (StringWriter writer = new StringWriter()) { - Yaml.createYamlPrinter(writer).print(Yaml.createYamlDump(configMap).dump()); - context.logLine(LogLevel.ALWAYS, writer.toString()); - } - catch (IOException e) { - // should never happen - e.printStackTrace(); - } - - context.logLine(LogLevel.ALWAYS, ""); - } - - public List create(GlobalKeepData inputData, LanguageKeep languageKeep) { - return getSettingsMap().stream().map(a -> { - FlowPane generalPane = new FlowPane(); - generalPane.setVgap(10); - generalPane.setHgap(10); - generalPane.setPadding(new Insets(10)); - generalPane.setOrientation(Orientation.VERTICAL); - generalPane.setPrefWrapLength(400); - - for (Setting setting : a.getValue()) - generalPane.getChildren().add(setting.create(inputData, languageKeep)); - - return new Tab(a.getKey(), generalPane); - }).collect(Collectors.toList()); - } - - private List>> getSettingsMap() { - return List.of(Tuple.of("General", Arrays.asList(digimonSettings, evolutionSettings, skillSettings, worldSettings, patchSettings)), - Tuple.of("New Game", Arrays.asList(starterSettings, playerSettings))); - } - - public Map serialize() { - Map map = new HashMap<>(); - map.put("skillSettings", skillSettings.serialize()); - map.put("digimonSettings", digimonSettings.serialize()); - map.put("evolutionSettings", evolutionSettings.serialize()); - map.put("starterSettings", starterSettings.serialize()); - map.put("worldSettings", worldSettings.serialize()); - map.put("patchSettings", patchSettings.serialize()); - map.put("playerSettings", playerSettings.serialize()); - - return map; - } - - public void load(YamlMapping map) { - if (map == null) - return; - - skillSettings.load(map.yamlMapping("skillSettings")); - digimonSettings.load(map.yamlMapping("digimonSettings")); - evolutionSettings.load(map.yamlMapping("evolutionSettings")); - starterSettings.load(map.yamlMapping("starterSettings")); - worldSettings.load(map.yamlMapping("worldSettings")); - patchSettings.load(map.yamlMapping("patchSettings")); - playerSettings.load(map.yamlMapping("playerSettings")); - } -} diff --git a/src/main/java/net/digimonworld/decode/randomizer/settings/SkillsSettings.java b/src/main/java/net/digimonworld/decode/randomizer/settings/SkillsSettings.java deleted file mode 100644 index 4c035ec..0000000 --- a/src/main/java/net/digimonworld/decode/randomizer/settings/SkillsSettings.java +++ /dev/null @@ -1,293 +0,0 @@ -package net.digimonworld.decode.randomizer.settings; - -import java.util.HashMap; -import java.util.ListIterator; -import java.util.Map; -import java.util.Optional; -import java.util.Random; - -import com.amihaiemil.eoyaml.YamlMapping; - -import net.digimonworld.decodetools.data.keepdata.Finisher; -import net.digimonworld.decodetools.data.keepdata.GlobalKeepData; -import net.digimonworld.decodetools.data.keepdata.LanguageKeep; -import net.digimonworld.decodetools.data.keepdata.Skill; -import net.digimonworld.decodetools.data.keepdata.enums.MoveKind; -import net.digimonworld.decodetools.data.keepdata.enums.Status; -import javafx.beans.property.BooleanProperty; -import javafx.beans.property.SimpleBooleanProperty; -import javafx.geometry.Pos; -import javafx.scene.control.TitledPane; -import javafx.scene.layout.VBox; -import net.digimonworld.decode.randomizer.RandoLogger.LogLevel; -import net.digimonworld.decode.randomizer.RandomizationContext; -import net.digimonworld.decode.randomizer.utils.JavaFXUtils; - -public class SkillsSettings implements Setting { - /*- - * MP Cost - * enable - * Cooldown - * enable - * Learn Rate - * enable - * Damage - * enable - * Status - * enable - * Status chance - * enable - */ - // TODO Tooltips - - private BooleanProperty randomizeMPCost = new SimpleBooleanProperty(); - private BooleanProperty randomizeCooldown = new SimpleBooleanProperty(); - private BooleanProperty randomizeLearnRate = new SimpleBooleanProperty(); - private BooleanProperty randomizeDamage = new SimpleBooleanProperty(); - private BooleanProperty randomizeStatus = new SimpleBooleanProperty(); - private BooleanProperty randomizeStatusChance = new SimpleBooleanProperty(); - private BooleanProperty randomizeFinisher = new SimpleBooleanProperty(); - - @Override - public TitledPane create(GlobalKeepData data, LanguageKeep language) { - VBox vbox = new VBox(4); - TitledPane pane = new TitledPane("Skills", vbox); - vbox.setAlignment(Pos.TOP_RIGHT); - pane.setCollapsible(false); - - vbox.getChildren().addAll(JavaFXUtils.buildToggleSwitch("MP Cost", Optional.empty(), Optional.of(randomizeMPCost)), - JavaFXUtils.buildToggleSwitch("Cooldown", Optional.empty(), Optional.of(randomizeCooldown)), - JavaFXUtils.buildToggleSwitch("Learn Rate", Optional.empty(), Optional.of(randomizeLearnRate)), - JavaFXUtils.buildToggleSwitch("Power", Optional.empty(), Optional.of(randomizeDamage)), - JavaFXUtils.buildToggleSwitch("Status", Optional.empty(), Optional.of(randomizeStatus)), - JavaFXUtils.buildToggleSwitch("Status Chance", Optional.empty(), Optional.of(randomizeStatusChance)), - JavaFXUtils.buildToggleSwitch("Finisher", Optional.empty(), Optional.of(randomizeFinisher))); - return pane; - } - - public void setRandomizeMPCost(boolean set) { - randomizeMPCost.set(set); - } - - @Override - public void randomize(RandomizationContext context) { - if (randomizeMPCost.get()) - randomizeMPCost(context); - if (randomizeCooldown.get()) - randomizeCooldown(context); - if (randomizeLearnRate.get()) - randomizeLearnRate(context); - if (randomizeDamage.get()) - randomizeDamage(context); - if (randomizeStatus.get()) - randomizeStatus(context); - if (randomizeStatusChance.get()) - randomizeStatusChance(context); - if (randomizeFinisher.get()) - randomizeFinisher(context); - } - - private void randomizeLearnRate(RandomizationContext context) { - Random rand = new Random(context.getInitialSeed() * "LearnChance".hashCode()); - - context.logLine(LogLevel.ALWAYS, "Randomizing Learn Rates..."); - - for (ListIterator itr = context.getGlobalKeepData().getSkills().listIterator(); itr.hasNext();) { - int i = itr.nextIndex(); - Skill a = itr.next(); - - if (a.getTier() == 0) - continue; - - float newLearnRate = 0.1f + 0.9f * rand.nextFloat(); - context.logLine(LogLevel.CASUAL, - String.format(FORMAT_FLOAT, - context.getLanguageKeep().getSkillNames().getStringById(i + 1), - "Learn Rate", - a.getLearning(), - newLearnRate)); - a.setLearning(newLearnRate); - } - - context.logLine(LogLevel.ALWAYS, ""); - } - - private void randomizeFinisher(RandomizationContext context) { - Random randDamage = new Random(context.getInitialSeed() * "FinisherDamage".hashCode()); - Random randStatus = new Random(context.getInitialSeed() * "FinisherStatus".hashCode()); - - context.logLine(LogLevel.ALWAYS, "Randomizing Finisher..."); - - for (ListIterator itr = context.getGlobalKeepData().getFinisher().listIterator(); itr.hasNext();) { - int i = itr.nextIndex(); - Finisher a = itr.next(); - - if (randomizeDamage.get()) { - int power = 250 + randDamage.nextInt(750); - context.logLine(LogLevel.CASUAL, - String.format(FORMAT_INT, context.getLanguageKeep().getFinisherNames().getStringById(i + 1), "Power", a.getPower(), power)); - a.setPower(power); - } - - if (randomizeStatus.get()) { - Status status = randStatus.nextDouble() > 0.75 ? Status.NONE : Status.values()[randStatus.nextInt(6) + 1]; - context.logLine(LogLevel.CASUAL, - String.format(FORMAT_STRING, - context.getLanguageKeep().getFinisherNames().getStringById(i + 1), - "Status", - a.getEffect(), - status)); - a.setEffect(status); - a.setChance((short) (status == Status.NONE ? 0 : 100)); - } - } - - context.logLine(LogLevel.ALWAYS, ""); - } - - private void randomizeCooldown(RandomizationContext context) { - Random rand = new Random(context.getInitialSeed() * "Cooldown".hashCode()); - - context.logLine(LogLevel.ALWAYS, "Randomizing Cooldowns..."); - - for (ListIterator itr = context.getGlobalKeepData().getSkills().listIterator(); itr.hasNext();) { - int i = itr.nextIndex(); - Skill a = itr.next(); - - if (a.getKind() != MoveKind.ATTACK || a.getTier() == 0) - continue; - - short newCooldown = (short) (500 + rand.nextInt(6500)); - context.logLine(LogLevel.CASUAL, - String.format(FORMAT_INT, - context.getLanguageKeep().getSkillNames().getStringById(i + 1), - "Cooldown", - a.getCooldown(), - newCooldown)); - a.setCooldown(newCooldown); - } - - context.logLine(LogLevel.ALWAYS, ""); - } - - private void randomizeDamage(RandomizationContext context) { - Random rand = new Random(context.getInitialSeed() * "Power".hashCode()); - - context.logLine(LogLevel.ALWAYS, "Randomizing Power..."); - - for (ListIterator itr = context.getGlobalKeepData().getSkills().listIterator(); itr.hasNext();) { - int i = itr.nextIndex(); - Skill a = itr.next(); - - if (a.getKind() != MoveKind.ATTACK) - continue; - - int newDamage = 50 + rand.nextInt(200) + (rand.nextInt(1024) * rand.nextInt(1 + rand.nextInt(749))) / 1024; - context.logLine(LogLevel.CASUAL, - String.format(FORMAT_INT, context.getLanguageKeep().getSkillNames().getStringById(i + 1), "Power", a.getDamage(), newDamage)); - a.setDamage(newDamage); - } - - context.logLine(LogLevel.ALWAYS, ""); - } - - private void randomizeStatus(RandomizationContext context) { - Random rand = new Random(context.getInitialSeed() * "Status".hashCode()); - - context.logLine(LogLevel.ALWAYS, "Randomizing Status Effects..."); - - for (ListIterator itr = context.getGlobalKeepData().getSkills().listIterator(); itr.hasNext();) { - int i = itr.nextIndex(); - Skill a = itr.next(); - - if (a.getKind() != MoveKind.ATTACK || a.getTier() == 0) - continue; - - Status newStatus = rand.nextBoolean() ? Status.NONE : Status.values()[rand.nextInt(6) + 1]; - context.logLine(LogLevel.CASUAL, - String.format(FORMAT_STRING, context.getLanguageKeep().getSkillNames().getStringById(i + 1), "Status", a.getStatus(), newStatus)); - a.setStatus(newStatus); - } - - context.logLine(LogLevel.ALWAYS, ""); - } - - private void randomizeStatusChance(RandomizationContext context) { - Random rand = new Random(context.getInitialSeed() * "StatusChance".hashCode()); - - context.logLine(LogLevel.ALWAYS, "Randomizing Status Chances..."); - - for (ListIterator itr = context.getGlobalKeepData().getSkills().listIterator(); itr.hasNext();) { - int i = itr.nextIndex(); - Skill a = itr.next(); - - if (a.getStatus() == Status.NONE || a.getKind() != MoveKind.ATTACK || a.getTier() == 0) - continue; - - short newStatusChance = (short) (1 + rand.nextInt(99)); - - context.logLine(LogLevel.CASUAL, - String.format(FORMAT_INT, - context.getLanguageKeep().getSkillNames().getStringById(i + 1), - "StatusChance", - a.getStatusChance(), - newStatusChance)); - a.setStatusChance(newStatusChance); - } - - context.logLine(LogLevel.ALWAYS, ""); - } - - private void randomizeMPCost(RandomizationContext context) { - Random rand = new Random(context.getInitialSeed() * "MPCost".hashCode()); - - context.logLine(LogLevel.ALWAYS, "Randomizing MP Cost..."); - - final int mean = 250; - final int stdDev = 150; - - for (ListIterator itr = context.getGlobalKeepData().getSkills().listIterator(); itr.hasNext();) { - int i = itr.nextIndex(); - Skill a = itr.next(); - - int val = (int) (mean + (rand.nextGaussian() * stdDev)); - if (val < 5 || val > 995 || rand.nextDouble() < (500 - val) / 3000D) - val = 5 + rand.nextInt(994); - - context.logLine(LogLevel.CASUAL, - String.format(FORMAT_INT, context.getLanguageKeep().getSkillNames().getStringById(i + 1), "MP Cost", a.getMpCost(), val)); - a.setMpCost((short) val); - } - - context.logLine(LogLevel.ALWAYS, ""); - } - - @Override - public Map serialize() { - Map map = new HashMap<>(); - - map.put("randomizeMPCosts", randomizeMPCost.get()); - map.put("randomizeCooldown", randomizeCooldown.get()); - map.put("randomizeLearnRate", randomizeLearnRate.get()); - map.put("randomizeDamage", randomizeDamage.get()); - map.put("randomizeStatus", randomizeStatus.get()); - map.put("randomizeStatusChance", randomizeStatusChance.get()); - map.put("randomizeFinisher", randomizeFinisher.get()); - - return map; - } - - @Override - public void load(YamlMapping map) { - if(map == null) - return; - - this.randomizeMPCost.set(Boolean.parseBoolean(map.string("randomizeMPCosts"))); - this.randomizeCooldown.set(Boolean.parseBoolean(map.string("randomizeCooldown"))); - this.randomizeLearnRate.set(Boolean.parseBoolean(map.string("randomizeLearnRate"))); - this.randomizeDamage.set(Boolean.parseBoolean(map.string("randomizeDamage"))); - this.randomizeStatus.set(Boolean.parseBoolean(map.string("randomizeStatus"))); - this.randomizeStatusChance.set(Boolean.parseBoolean(map.string("randomizeStatusChance"))); - this.randomizeFinisher.set(Boolean.parseBoolean(map.string("randomizeFinisher"))); - } -} diff --git a/src/main/java/net/digimonworld/decode/randomizer/settings/StarterSettings.java b/src/main/java/net/digimonworld/decode/randomizer/settings/StarterSettings.java deleted file mode 100644 index 780ac55..0000000 --- a/src/main/java/net/digimonworld/decode/randomizer/settings/StarterSettings.java +++ /dev/null @@ -1,145 +0,0 @@ -package net.digimonworld.decode.randomizer.settings; - -import java.util.ArrayList; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.Optional; -import java.util.Random; -import java.util.stream.Collectors; - -import org.controlsfx.control.CheckTreeView; - -import com.amihaiemil.eoyaml.YamlMapping; -import com.amihaiemil.eoyaml.YamlSequence; - -import net.digimonworld.decodetools.data.keepdata.Digimon; -import net.digimonworld.decodetools.data.keepdata.GlobalKeepData; -import net.digimonworld.decodetools.data.keepdata.LanguageKeep; -import net.digimonworld.decodetools.data.keepdata.enums.Level; -import javafx.beans.property.BooleanProperty; -import javafx.beans.property.SimpleBooleanProperty; -import javafx.geometry.Pos; -import javafx.scene.control.CheckBoxTreeItem; -import javafx.scene.control.TitledPane; -import javafx.scene.layout.VBox; -import net.digimonworld.decode.randomizer.RandoLogger.LogLevel; -import net.digimonworld.decode.randomizer.RandomizationContext; -import net.digimonworld.decode.randomizer.utils.JavaFXUtils; - -public class StarterSettings implements Setting { - - // TODO adjust lifespan - - private class DigimonEntry { - int id; - String name; - - public DigimonEntry(int id, String name) { - this.id = id; - this.name = name; - } - - @Override - public String toString() { - return name; - } - } - - private BooleanProperty enabled = new SimpleBooleanProperty(); - private Map propertyMap = new HashMap<>(); - - @Override - public TitledPane create(GlobalKeepData data, LanguageKeep language) { - VBox vbox = new VBox(8); - TitledPane pane = new TitledPane("Starter", vbox); - vbox.setAlignment(Pos.TOP_LEFT); - pane.setCollapsible(false); - pane.setPrefHeight(400); - - CheckBoxTreeItem root = new CheckBoxTreeItem<>(new DigimonEntry(-10, "Root")); - Map> map = new EnumMap<>(Level.class); - - for (ListIterator itr = data.getDigimonData().listIterator(); itr.hasNext();) { - int id = itr.nextIndex() + 1; - Digimon digi = itr.next(); - - if ((digi.getUnk38() & 1) == 1) - map.computeIfAbsent(digi.getLevel(), a -> new ArrayList()) - .add(new DigimonEntry(id, language.getDigimonNames().getStringById(id))); - } - - map.entrySet().forEach(a -> { - CheckBoxTreeItem item = new CheckBoxTreeItem<>(new DigimonEntry(-a.getKey().ordinal(), a.getKey().getDisplayName())); - item.getChildren().addAll(a.getValue().stream().map(b -> { - CheckBoxTreeItem i = new CheckBoxTreeItem<>(b); - BooleanProperty prop = new SimpleBooleanProperty(); - i.selectedProperty().bindBidirectional(prop); - propertyMap.put(b.id, prop); - return i; - }).collect(Collectors.toList())); - root.getChildren().add(item); - }); - - CheckTreeView tree = new CheckTreeView<>(root); - tree.setShowRoot(false); - tree.disableProperty().bind(enabled.not()); - - vbox.getChildren().addAll(JavaFXUtils.buildToggleSwitch("Enabled", Optional.empty(), Optional.of(enabled)), tree); - return pane; - } - - @Override - public void randomize(RandomizationContext context) { - List list = propertyMap.entrySet().stream().filter(a -> a.getValue().get()).map(Map.Entry::getKey).collect(Collectors.toList()); - - if (!enabled.get() || list.isEmpty()) - return; - - context.logLine(LogLevel.ALWAYS, "Randomizing starter Digimon..."); - Random rand = new Random(context.getInitialSeed() * "Starter".hashCode()); - - int starterRina = list.get(rand.nextInt(list.size())); - int starterTaiga = list.get(rand.nextInt(list.size())); - int starterTaigaNGP = list.get(rand.nextInt(list.size())); - - context.addASM(".org 0x12CCC4"); - context.addASM(String.format(".byte 0x%02X", starterRina)); - - context.addASM(".org 0x12D6A0"); - context.addASM(String.format(".byte 0x%02X", starterTaigaNGP)); - - context.addASM(".org 0x27AA18"); - context.addASM(String.format(".byte 0x%02X", starterTaiga)); - - context.logLine(LogLevel.CASUAL, - String.format("Randomized Rina's Starter to %s.", context.getLanguageKeep().getDigimonNames().getStringById(starterRina + 1))); - context.logLine(LogLevel.CASUAL, - String.format("Randomized Taiga's Starter to %s.", context.getLanguageKeep().getDigimonNames().getStringById(starterTaiga + 1))); - context.logLine(LogLevel.CASUAL, - String.format("Randomized Taiga's BG+ Starter to %s.", context.getLanguageKeep().getDigimonNames().getStringById(starterTaigaNGP + 1))); - - } - - @Override - public Map serialize() { - Map map = new HashMap<>(); - map.put("enabled", enabled.get()); - map.put("checked", propertyMap.entrySet().stream().filter(a -> a.getValue().get()).map(Map.Entry::getKey).collect(Collectors.toList())); - return map; - } - - @Override - public void load(YamlMapping map) { - if (map == null) - return; - - YamlSequence list = map.yamlSequence("checked"); - List activeList = list == null ? new ArrayList<>() - : list.values().stream().map(a -> Integer.parseInt(a.asScalar().value())).collect(Collectors.toList()); - propertyMap.forEach((a, b) -> b.set(activeList.contains(a))); - enabled.set(Boolean.parseBoolean(map.string("enabled"))); - } -} diff --git a/src/main/java/net/digimonworld/decode/randomizer/settings/WorldSettings.java b/src/main/java/net/digimonworld/decode/randomizer/settings/WorldSettings.java deleted file mode 100644 index 6b254b7..0000000 --- a/src/main/java/net/digimonworld/decode/randomizer/settings/WorldSettings.java +++ /dev/null @@ -1,372 +0,0 @@ -package net.digimonworld.decode.randomizer.settings; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Random; - -import org.controlsfx.control.ToggleSwitch; - -import com.amihaiemil.eoyaml.YamlMapping; - -import javafx.beans.property.BooleanProperty; -import javafx.beans.property.SimpleBooleanProperty; -import javafx.geometry.Pos; -import javafx.scene.control.TitledPane; -import javafx.scene.layout.VBox; -import net.digimonworld.decode.randomizer.RandoLogger.LogLevel; -import net.digimonworld.decode.randomizer.RandomizationContext; -import net.digimonworld.decode.randomizer.utils.JavaFXUtils; -import net.digimonworld.decode.randomizer.utils.RandomizerUtils; -import net.digimonworld.decodetools.core.MappedSet; -import net.digimonworld.decodetools.core.StreamAccess; -import net.digimonworld.decodetools.data.keepdata.Digimon; -import net.digimonworld.decodetools.data.keepdata.EnemyData; -import net.digimonworld.decodetools.data.keepdata.EnemyData.ItemDrop; -import net.digimonworld.decodetools.data.keepdata.GlobalKeepData; -import net.digimonworld.decodetools.data.keepdata.LanguageKeep; -import net.digimonworld.decodetools.data.keepdata.MapEnemyData; -import net.digimonworld.decodetools.data.keepdata.MapEnemyData.MapEnemyEntry; -import net.digimonworld.decodetools.data.keepdata.TreasureLoot; -import net.digimonworld.decodetools.data.keepdata.TypeAlignmentChart; -import net.digimonworld.decodetools.data.keepdata.enums.DropType; -import net.digimonworld.decodetools.data.keepdata.enums.Special; -import net.digimonworld.decodetools.data.map.MapItemSpawns; -import net.digimonworld.decodetools.data.map.MapItemSpawns.ItemSpawn; -import net.digimonworld.decodetools.data.map.MapItemSpawns.MapItemSpawn; -import net.digimonworld.decodetools.res.kcap.AbstractKCAP; -import net.digimonworld.decodetools.res.payload.GenericPayload; - -public class WorldSettings implements Setting { - - private BooleanProperty randomizeTypeEffectiveness = new SimpleBooleanProperty(); - private BooleanProperty randomizeTreasureHunt = new SimpleBooleanProperty(); - private BooleanProperty randomizeItemSpawns = new SimpleBooleanProperty(); - - private BooleanProperty randomizeEnemies = new SimpleBooleanProperty(); - private BooleanProperty randomizeEnemyStats = new SimpleBooleanProperty(); - private BooleanProperty randomizeEnemyDigimon = new SimpleBooleanProperty(); - private BooleanProperty randomizeEnemyMoves = new SimpleBooleanProperty(); - private BooleanProperty randomizeEnemyLoot = new SimpleBooleanProperty(); - - @Override - public TitledPane create(GlobalKeepData inputData, LanguageKeep languageKeep) { - VBox vbox = new VBox(4); - TitledPane pane = new TitledPane("World", vbox); - vbox.setAlignment(Pos.TOP_RIGHT); - pane.setCollapsible(false); - - ToggleSwitch enemies = JavaFXUtils.buildToggleSwitch("Enemies", Optional.empty(), Optional.of(randomizeEnemies)); - ToggleSwitch stats = JavaFXUtils.buildToggleSwitch("Enemy Stats", Optional.empty(), Optional.of(randomizeEnemyStats)); - ToggleSwitch digimon = JavaFXUtils.buildToggleSwitch("Enemy Digimon", Optional.empty(), Optional.of(randomizeEnemyDigimon)); - ToggleSwitch moves = JavaFXUtils.buildToggleSwitch("Enemy Moves", Optional.empty(), Optional.of(randomizeEnemyMoves)); - ToggleSwitch loot = JavaFXUtils.buildToggleSwitch("Enemy Loot", Optional.empty(), Optional.of(randomizeEnemyLoot)); - - stats.disableProperty().bind(randomizeEnemies.not()); - digimon.disableProperty().bind(randomizeEnemies.not()); - moves.disableProperty().bind(randomizeEnemies.not()); - loot.disableProperty().bind(randomizeEnemies.not()); - - vbox.getChildren().addAll(JavaFXUtils.buildToggleSwitch("Type Effectiveness", Optional.empty(), Optional.of(randomizeTypeEffectiveness)), - JavaFXUtils.buildToggleSwitch("Treasure Hunt", Optional.empty(), Optional.of(randomizeTreasureHunt)), - JavaFXUtils.buildToggleSwitch("Item Spawns", Optional.empty(), Optional.of(randomizeItemSpawns)), - enemies, - stats, - digimon, - moves, - loot); - return pane; - } - - @Override - public void randomize(RandomizationContext context) { - if (randomizeTypeEffectiveness.get()) - randomizeTypeEffectiveness(context); - if (randomizeTreasureHunt.get()) - randomizeTreasureHunt(context); - if (randomizeEnemies.get()) - randomizeEnemies(context); - if (randomizeItemSpawns.get()) - randomizeItemSpawns(context); - } - - private void randomizeItemSpawns(RandomizationContext context) { - Random rand = new Random(context.getInitialSeed() * "ItemSpawns".hashCode()); - - context.logLine(LogLevel.ALWAYS, "Randomizing Item Spawns..."); - context.logLine(LogLevel.CASUAL, ""); - - List items = RandomizerUtils.getUseableItems(context.getGlobalKeepData()); - Map mapMap = readItemSpawnMapping(); - - mapMap.forEach((a, b) -> { - String filePath = String.format("part0/arcv/map/%s.res", a); - context.getFile(filePath).ifPresent(m -> { - AbstractKCAP root = (AbstractKCAP) m; - AbstractKCAP map = (AbstractKCAP) root.get(1); - GenericPayload payload = (GenericPayload) map.get(b); - - @SuppressWarnings("resource") - MapItemSpawns mapSpawns = new MapItemSpawns(new StreamAccess(payload.getData())); - - context.logLine(LogLevel.CASUAL, String.format("=== %s old spawns: ===", a)); - logItemSpawns(mapSpawns, context); - - for (MapItemSpawn spawns : mapSpawns.getSpawns()) { - int numItems = 1 + rand.nextInt(8); - float chancePerItem = (0.1f + rand.nextFloat() * 0.9f) / numItems; - - for (int i = 0; i < 8; i++) { - ItemSpawn spawn = spawns.getSpawns()[i]; - - // don't randomize firewood - if(spawn.getItemId() == 367) - continue; - - spawn.setChance(i < numItems ? chancePerItem : 0f); - spawn.setItemId(i < numItems ? items.get(rand.nextInt(items.size())) : 0); - } - } - - context.logLine(LogLevel.CASUAL, String.format("=== %s new spawns: ===", a)); - logItemSpawns(mapSpawns, context); - - payload.setData(mapSpawns.toByteArray()); - context.logLine(LogLevel.CASUAL, ""); - }); - }); - } - - private void logItemSpawns(MapItemSpawns mapSpawns, RandomizationContext context) { - for (MapItemSpawn spawns : mapSpawns.getSpawns()) - for (ItemSpawn spawn : spawns.getSpawns()) - context.logLine(LogLevel.CASUAL, - String.format("%30s | %5.4f", - context.getLanguageKeep().getItemNames().getStringById(spawn.getItemId()), - spawn.getChance())); - } - - private Map readItemSpawnMapping() { - Map map = new HashMap<>(); - try (BufferedReader reader = new BufferedReader(new InputStreamReader(WorldSettings.class.getResourceAsStream("itemSpawnMapping.csv")))) { - String str; - while ((str = reader.readLine()) != null) { - String[] arr = str.split(","); - map.put(arr[0], Integer.parseInt(arr[1])); - } - } - catch (IOException e) { - e.printStackTrace(); - } - - return map; - } - - private void randomizeEnemies(RandomizationContext context) { - Random rand = new Random(context.getInitialSeed() * "Enemies".hashCode()); - - context.logLine(LogLevel.ALWAYS, "Randomizing Map Encounters..."); - context.logLine(LogLevel.CASUAL, ""); - - GlobalKeepData keep = context.getGlobalKeepData(); - MappedSet enemyData = keep.getEnemyData(); - List digimonList = RandomizerUtils.getEnemyDigimonList(keep); - - int i = 7000; - for (MapEnemyData a : keep.getEnemyMapData()) { - for (MapEnemyEntry entry : a.getEntries()) { - if (entry.getEnemyId() == 0) - continue; - - EnemyData oldData = enemyData.get(entry.getEnemyId()); - EnemyData newData = new EnemyData(oldData); - - entry.setEnemyId((short) i); - newData.setEnemyId((short) i++); - - // Digimon ID - if (randomizeEnemyDigimon.get()) - newData.setDigimonId(digimonList.get(rand.nextInt(digimonList.size())).shortValue()); - - Digimon digi = keep.getDigimonData().get(newData.getDigimonId() - 1); - - // Stats - if (randomizeEnemyStats.get()) - randomizeEnemyStats(rand, newData); - - // Moves - List moves = RandomizerUtils.getMoveList(digi); - Collections.shuffle(moves, rand); - - if (randomizeEnemyMoves.get() || !moves.contains(newData.getMove1())) - newData.setMove1(moves.isEmpty() ? 0 : moves.get(0)); - if (randomizeEnemyMoves.get() || !moves.contains(newData.getMove2())) - newData.setMove2(moves.size() < 2 ? 0 : moves.get(1)); - if (randomizeEnemyMoves.get() || !moves.contains(newData.getMove3())) - newData.setMove3(moves.size() < 3 ? 0 : moves.get(2)); - - // Loot - if (randomizeEnemyLoot.get()) - randomizeLoot(rand, newData, keep); - - enemyData.add(newData); - - context.logLine(LogLevel.CASUAL, String.format("=== Map %s | Spawn %d", a.getMap(), a.getSpawnPoint())); - context.logLine(LogLevel.CASUAL, ""); - RandomizerUtils.logEnemyData(context, oldData); - context.logLine(LogLevel.CASUAL, ""); - RandomizerUtils.logEnemyData(context, newData); - context.logLine(LogLevel.CASUAL, ""); - context.logLine(LogLevel.CASUAL, ""); - } - } - } - - private void randomizeLoot(Random rand, EnemyData newData, GlobalKeepData keep) { - List itemList = RandomizerUtils.getUseableItems(keep); - - short bits = newData.getBits(); - short decodeXP = newData.getDecodeXP(); - - bits *= 1 + (rand.nextBoolean() ? -rand.nextFloat() / 2 : rand.nextFloat()); - decodeXP *= 1 + (rand.nextBoolean() ? -rand.nextFloat() / 2 : rand.nextFloat()); - - newData.setBits(bits); - newData.setDecodeXP(decodeXP); - - for (int j = 0; j < 3; j++) { - int r1 = rand.nextInt(10); - ItemDrop drop = newData.getDrop(j); - - if (r1 < 5) { - drop.setType(DropType.ITEM); - drop.setId(itemList.get(rand.nextInt(itemList.size())).shortValue()); - drop.setChance(Math.min(1.0f, 0.05f + rand.nextFloat())); - } - else if (r1 < 7) { - drop.setType(DropType.CARD); - drop.setId((short) (1 + rand.nextInt(588))); - drop.setChance(Math.min(1.0f, 0.05f + rand.nextFloat())); - } - else { - drop.setType(DropType.ITEM); - drop.setId((short) 0); - drop.setChance(0f); - } - } - } - - private void randomizeEnemyStats(Random rand, EnemyData newData) { - int hp = newData.getHp(); - int mp = newData.getMp(); - short off = newData.getOffense(); - short def = newData.getDefense(); - short speed = newData.getSpeed(); - short brains = newData.getBrains(); - - hp *= 1 + (rand.nextBoolean() ? -rand.nextFloat() / 2 : rand.nextFloat()); - mp *= 1 + (rand.nextBoolean() ? -rand.nextFloat() / 2 : rand.nextFloat()); - off *= 1 + (rand.nextBoolean() ? -rand.nextFloat() / 2 : rand.nextFloat()); - def *= 1 + (rand.nextBoolean() ? -rand.nextFloat() / 2 : rand.nextFloat()); - speed *= 1 + (rand.nextBoolean() ? -rand.nextFloat() / 2 : rand.nextFloat()); - brains *= 1 + (rand.nextBoolean() ? -rand.nextFloat() / 2 : rand.nextFloat()); - - newData.setHp(hp); - newData.setMp(mp); - newData.setOffense(off); - newData.setDefense(def); - newData.setSpeed(speed); - newData.setBrains(brains); - } - - private void randomizeTreasureHunt(RandomizationContext context) { - Random rand = new Random(context.getInitialSeed() * "TreasureLoot".hashCode()); - List itemList = RandomizerUtils.getUseableItems(context.getGlobalKeepData()); - - context.logLine(LogLevel.ALWAYS, "Randomizing Treasure Hunt Loot..."); - context.logLine(LogLevel.CASUAL, "Old Table: "); - - for (int i = 0; i < 120; i++) { - if (i % 20 == 0) - Collections.shuffle(itemList, rand); - - TreasureLoot loot = context.getGlobalKeepData().getTreasureLoot().get(i); - context.logLine(LogLevel.CASUAL, - String.format("%s - %3.2f", context.getLanguageKeep().getItemNames().getStringById(loot.getItem()), loot.getChance())); - - loot.setItem(itemList.get(i % 20)); - loot.setChance(0.05f); - } - - context.logLine(LogLevel.CASUAL, ""); - context.logLine(LogLevel.CASUAL, "New Table: "); - - for (TreasureLoot loot : context.getGlobalKeepData().getTreasureLoot()) - context.logLine(LogLevel.CASUAL, - String.format("%s - %3.2f", context.getLanguageKeep().getItemNames().getStringById(loot.getItem()), loot.getChance())); - } - - private void randomizeTypeEffectiveness(RandomizationContext context) { - Random rand = new Random(context.getInitialSeed() * "TypeAlignment".hashCode()); - - TypeAlignmentChart chart = context.getGlobalKeepData().getTypeAlignmentChart(); - - StringBuilder sbOld = new StringBuilder(); - StringBuilder sbNew = new StringBuilder(); - - for (Special attacker : TypeAlignmentChart.VALUES) { - for (Special victim : TypeAlignmentChart.VALUES) { - int val = rand.nextInt(101); - int value = 50 + (Math.min(val, 50) + Math.max(2 * (val - 50), 0)); - sbOld.append(Byte.toUnsignedInt(chart.get(attacker, victim))).append(" "); - sbNew.append(value).append(" "); - chart.set(attacker, victim, value); - } - sbOld.append("\n"); - sbNew.append("\n"); - } - - context.logLine(LogLevel.ALWAYS, "Randomizing type alignments..."); - context.logLine(LogLevel.CASUAL, "Old Alignments: "); - context.logLine(LogLevel.CASUAL, sbOld.toString()); - context.logLine(LogLevel.CASUAL, "New Alignments: "); - context.logLine(LogLevel.CASUAL, sbNew.toString()); - } - - @Override - public Map serialize() { - Map map = new HashMap<>(); - - map.put("randomizeTypeEffectiveness", randomizeTypeEffectiveness.get()); - map.put("randomizeTreasureHunt", randomizeTreasureHunt.get()); - map.put("randomizeEnemies", randomizeEnemies.get()); - map.put("randomizeEnemyStats", randomizeEnemyStats.get()); - map.put("randomizeEnemyDigimon", randomizeEnemyDigimon.get()); - map.put("randomizeEnemyMoves", randomizeEnemyMoves.get()); - map.put("randomizeEnemyLoot", randomizeEnemyLoot.get()); - map.put("randomizeItemSpawns", randomizeItemSpawns.get()); - - return map; - } - - @Override - public void load(YamlMapping map) { - if (map == null) - return; - - this.randomizeTypeEffectiveness.set(Boolean.parseBoolean(map.string("randomizeTypeEffectiveness"))); - this.randomizeTreasureHunt.set(Boolean.parseBoolean(map.string("randomizeTreasureHunt"))); - this.randomizeEnemies.set(Boolean.parseBoolean(map.string("randomizeEnemies"))); - this.randomizeEnemyStats.set(Boolean.parseBoolean(map.string("randomizeEnemyStats"))); - this.randomizeEnemyDigimon.set(Boolean.parseBoolean(map.string("randomizeEnemyDigimon"))); - this.randomizeEnemyMoves.set(Boolean.parseBoolean(map.string("randomizeEnemyMoves"))); - this.randomizeEnemyLoot.set(Boolean.parseBoolean(map.string("randomizeEnemyLoot"))); - this.randomizeItemSpawns.set(Boolean.parseBoolean(map.string("randomizeItemSpawns"))); - } - -} diff --git a/src/main/java/net/digimonworld/decode/randomizer/settings/package-info.java b/src/main/java/net/digimonworld/decode/randomizer/settings/package-info.java deleted file mode 100644 index d90b430..0000000 --- a/src/main/java/net/digimonworld/decode/randomizer/settings/package-info.java +++ /dev/null @@ -1 +0,0 @@ -package net.digimonworld.decode.randomizer.settings; diff --git a/src/main/java/net/digimonworld/decode/randomizer/utils/RandomizerUtils.java b/src/main/java/net/digimonworld/decode/randomizer/utils/RandomizerUtils.java deleted file mode 100644 index d2d056f..0000000 --- a/src/main/java/net/digimonworld/decode/randomizer/utils/RandomizerUtils.java +++ /dev/null @@ -1,86 +0,0 @@ -package net.digimonworld.decode.randomizer.utils; - -import java.util.ArrayList; -import java.util.List; -import java.util.ListIterator; - -import net.digimonworld.decodetools.data.keepdata.Digimon; -import net.digimonworld.decodetools.data.keepdata.EnemyData; -import net.digimonworld.decodetools.data.keepdata.EnemyData.ItemDrop; -import net.digimonworld.decodetools.data.keepdata.GlobalKeepData; -import net.digimonworld.decodetools.data.keepdata.Item; -import net.digimonworld.decodetools.data.keepdata.Item.ItemType; -import net.digimonworld.decodetools.data.keepdata.enums.DropType; -import net.digimonworld.decode.randomizer.RandoLogger.LogLevel; -import net.digimonworld.decode.randomizer.RandomizationContext; - -public class RandomizerUtils { - private RandomizerUtils() { - } - - public static List getUseableItems(GlobalKeepData data) { - List itemList = new ArrayList<>(); - for (ListIterator itr = data.getItems().listIterator(); itr.hasNext();) { - int i = itr.nextIndex(); - Item a = itr.next(); - - // filter technical, unused and Mt. Infinity items - if (a.getType() == ItemType.BASE || a.getUnk30() == 0 || (a.getUnk30() & 64) != 0 || (a.getUnk31() & 1) != 0) - continue; - - itemList.add(i + 1); - } - return itemList; - } - - public static List getMoveList(Digimon digi) { - List moves = new ArrayList<>(); - for (byte b : digi.getSkills()) - if (b != 0) - moves.add(b); - - return moves; - } - - public static List getEnemyDigimonList(GlobalKeepData keep) { - List itemList = new ArrayList<>(); - for (ListIterator itr = keep.getDigimonData().listIterator(); itr.hasNext();) { - int i = itr.nextIndex(); - Digimon a = itr.next(); - - if (a.getSkills()[0] == 0) - continue; - - itemList.add(i + 1); - } - return itemList; - } - - public static void logEnemyData(RandomizationContext context, EnemyData oldData) { - context.logLine(LogLevel.CASUAL, - String.format("ID %d | %s | Stats: %d %d %d %d %d %d", - oldData.getEnemyId(), - context.getLanguageKeep().getDigimonNames().getStringById(oldData.getDigimonId()), - oldData.getHp(), - oldData.getMp(), - oldData.getOffense(), - oldData.getDefense(), - oldData.getSpeed(), - oldData.getBrains())); - - context.logLine(LogLevel.CASUAL, - String.format("Moves: %s | %s | %s", - context.getLanguageKeep().getSkillNames().getStringById(oldData.getMove1()), - context.getLanguageKeep().getSkillNames().getStringById(oldData.getMove2()), - context.getLanguageKeep().getSkillNames().getStringById(oldData.getMove3()))); - - for (int i = 0; i < 3; i++) { - ItemDrop drop = oldData.getDrop(i); - String name = drop.getType() == DropType.CARD ? context.getLanguageKeep().getCardNames1().getStringById(drop.getId()) - : context.getLanguageKeep().getItemNames().getStringById(drop.getId()); - - context.logLine(LogLevel.CASUAL, String.format("Drop %d: %s | %s | %1.3f", i, drop.getType().name(), name, drop.getChance())); - } - - } -} diff --git a/src/main/java/net/digimonworld/decode/randomizer/AboutWindowController.java b/src/main/java/net/digimonworld/decode/textmod/AboutWindowController.java similarity index 55% rename from src/main/java/net/digimonworld/decode/randomizer/AboutWindowController.java rename to src/main/java/net/digimonworld/decode/textmod/AboutWindowController.java index f8de6be..4205b16 100644 --- a/src/main/java/net/digimonworld/decode/randomizer/AboutWindowController.java +++ b/src/main/java/net/digimonworld/decode/textmod/AboutWindowController.java @@ -1,37 +1,37 @@ -package net.digimonworld.decode.randomizer; +package net.digimonworld.decode.textmod; import javafx.event.ActionEvent; public class AboutWindowController { - private static final String LICENSE_URL = "https://github.com/SydMontague/DecodeRandomizer/LICENSE"; - private static final String GITHUB_URL = "https://github.com/SydMontague/DecodeRandomizer"; + private static final String LICENSE_URL = "https://github.com/Thertzlor/DecodeTextMod/blob/master/LICENSE"; + private static final String GITHUB_URL = "https://github.com/Thertzlor/DecodeTextMod"; private static final String DISCORD_URL = "https://discord.gg/AeRYeGJF2P"; - private static final String THIRD_PARTY_LICENSE_URL = "https://github.com/SydMontague/DecodeRandomizer/THIRD-PARTY-NOTICE"; + private static final String THIRD_PARTY_LICENSE_URL = "https://github.com/Thertzlor/DecodeTextMod/blob/master/THIRD-PARTY-NOTICE"; private static final String PATREON_URL = "https://patreon.com/sydmontague"; private static final String PAYPAL_URL = "https://paypal.me/sydmontague"; public void clickLicense(ActionEvent e) { - DecodeRandomizer.getInstance().getHostServices().showDocument(LICENSE_URL); + DecodeTextMod.getInstance().getHostServices().showDocument(LICENSE_URL); } public void clickThirdPartyLicense(ActionEvent e) { - DecodeRandomizer.getInstance().getHostServices().showDocument(THIRD_PARTY_LICENSE_URL); + DecodeTextMod.getInstance().getHostServices().showDocument(THIRD_PARTY_LICENSE_URL); } public void clickGitHub(ActionEvent e) { - DecodeRandomizer.getInstance().getHostServices().showDocument(GITHUB_URL); + DecodeTextMod.getInstance().getHostServices().showDocument(GITHUB_URL); } public void clickDiscord(ActionEvent e) { - DecodeRandomizer.getInstance().getHostServices().showDocument(DISCORD_URL); + DecodeTextMod.getInstance().getHostServices().showDocument(DISCORD_URL); } public void clickPatreon(ActionEvent e) { - DecodeRandomizer.getInstance().getHostServices().showDocument(PATREON_URL); + DecodeTextMod.getInstance().getHostServices().showDocument(PATREON_URL); } public void clickPayPal(ActionEvent e) { - DecodeRandomizer.getInstance().getHostServices().showDocument(PAYPAL_URL); + DecodeTextMod.getInstance().getHostServices().showDocument(PAYPAL_URL); } } diff --git a/src/main/java/net/digimonworld/decode/randomizer/DecodeRandomizer.java b/src/main/java/net/digimonworld/decode/textmod/DecodeTextMod.java similarity index 54% rename from src/main/java/net/digimonworld/decode/randomizer/DecodeRandomizer.java rename to src/main/java/net/digimonworld/decode/textmod/DecodeTextMod.java index dc14551..5d9cedf 100644 --- a/src/main/java/net/digimonworld/decode/randomizer/DecodeRandomizer.java +++ b/src/main/java/net/digimonworld/decode/textmod/DecodeTextMod.java @@ -1,4 +1,4 @@ -package net.digimonworld.decode.randomizer; +package net.digimonworld.decode.textmod; import java.io.IOException; @@ -16,34 +16,25 @@ * - xdelta | Apache 2.0, bundle | https://github.com/jmacd/xdelta */ -/* TODO features - * - * patches - * - camera distance - * - priority randomization (rookies) - */ - -public class DecodeRandomizer extends Application { - private static DecodeRandomizer instance; +public class DecodeTextMod extends Application { + private static DecodeTextMod instance; - public DecodeRandomizer() { - synchronized (DecodeRandomizer.class) { - if (instance == null) - instance = this; - else - throw new UnsupportedOperationException("Tried to instantiate the App's main class more than once."); + public DecodeTextMod() { + synchronized (DecodeTextMod.class) { + if (instance == null) instance = this; + else throw new UnsupportedOperationException("Tried to instantiate the App's main class more than once."); } } - public static DecodeRandomizer getInstance() { + public static DecodeTextMod getInstance() { return instance; } @Override public void start(Stage stage) throws IOException { - FXMLLoader loader = new FXMLLoader(DecodeRandomizer.class.getResource("MainWindow.fxml")); + FXMLLoader loader = new FXMLLoader(DecodeTextMod.class.getResource("MainWindow.fxml")); stage.setScene(loader.load()); - stage.setTitle("Digimon World Re:Digitize Decode Randomizer"); + stage.setTitle("Digimon World Re:Digitize Decode TextMod Tool"); stage.show(); } diff --git a/src/main/java/net/digimonworld/decode/textmod/Launcher.java b/src/main/java/net/digimonworld/decode/textmod/Launcher.java new file mode 100644 index 0000000..fd05f97 --- /dev/null +++ b/src/main/java/net/digimonworld/decode/textmod/Launcher.java @@ -0,0 +1,7 @@ +package net.digimonworld.decode.textmod; + +public class Launcher { + public static void main(String[] args) { + DecodeTextMod.main(args); + } +} diff --git a/src/main/java/net/digimonworld/decode/randomizer/MainWindowController.java b/src/main/java/net/digimonworld/decode/textmod/MainWindowController.java similarity index 80% rename from src/main/java/net/digimonworld/decode/randomizer/MainWindowController.java rename to src/main/java/net/digimonworld/decode/textmod/MainWindowController.java index 3d43815..c6bbb15 100644 --- a/src/main/java/net/digimonworld/decode/randomizer/MainWindowController.java +++ b/src/main/java/net/digimonworld/decode/textmod/MainWindowController.java @@ -1,24 +1,18 @@ -package net.digimonworld.decode.randomizer; +package net.digimonworld.decode.textmod; -import java.io.BufferedWriter; import java.io.File; import java.io.IOException; -import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; -import java.util.HashMap; + import java.util.List; -import java.util.Map; import java.util.Random; import java.util.concurrent.CompletableFuture; import java.util.function.Supplier; import org.controlsfx.control.ToggleSwitch; -import com.amihaiemil.eoyaml.Yaml; -import com.amihaiemil.eoyaml.YamlMapping; import javafx.application.Platform; import javafx.event.ActionEvent; @@ -36,8 +30,8 @@ import javafx.stage.FileChooser; import javafx.stage.FileChooser.ExtensionFilter; import javafx.stage.Stage; -import net.digimonworld.decode.randomizer.settings.RandomizerSettings; -import net.digimonworld.decode.randomizer.utils.JavaFXUtils; +import net.digimonworld.decode.textmod.settings.RandomizerSettings; +import net.digimonworld.decode.textmod.utils.JavaFXUtils; import net.digimonworld.decodetools.core.Access; import net.digimonworld.decodetools.core.DeleteDirectoryFileVisitor; import net.digimonworld.decodetools.core.FileAccess; @@ -131,7 +125,7 @@ public void setupBaseROM(ActionEvent e) { Alert alert = new Alert(AlertType.NONE); alert.setTitle("Extracting ROM..."); alert.setHeaderText(null); - alert.setContentText("Extracting ROM. This might take a minute."); + alert.setContentText("Extracting ROM. This might take a few minutes."); alert.show(); CompletableFuture.supplyAsync(provideExtractionSupplier(chooser.getSelectedExtensionFilter(), WORKING_PATH, selected.toPath())).thenAccept(a -> Platform.runLater(() -> { @@ -185,7 +179,7 @@ public void onRandomize() throws IOException { Alert alert = new Alert(AlertType.NONE); alert.setTitle("Rebuilding ROM..."); alert.setHeaderText(null); - alert.setContentText("Rebuilding ROM. This might take a minute."); + alert.setContentText("Rebuilding ROM. This might take a few minutes."); alert.show(); CompletableFuture.runAsync(() -> { @@ -221,47 +215,7 @@ private long parseSeed(String input) { return Utils.parseLongOrDefault(input, input.isBlank() ? new Random().nextLong() : input.hashCode()); } - @FXML - public void onSaveSettings() throws IOException { - FileChooser chooser = new FileChooser(); - chooser.setTitle("Where to save the settings?"); - chooser.setInitialDirectory(new File(".")); - chooser.getExtensionFilters().add(new ExtensionFilter("YAML", "*.yml")); - - File selected = chooser.showSaveDialog(root.getWindow()); - - if (selected == null) - return; - - Map configMap = new HashMap<>(); - - configMap.put("seed", seedField.getText()); - configMap.put("settings", settings.serialize()); - configMap.put("raceLogging", raceLogging.isSelected()); - - try (BufferedWriter writer = Files.newBufferedWriter(selected.toPath(), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) { - Yaml.createYamlPrinter(writer).print(Yaml.createYamlDump(configMap).dump()); - } - } - @FXML - public void onLoadSettings() throws IOException { - FileChooser chooser = new FileChooser(); - chooser.setTitle("Select the settings to load"); - chooser.setInitialDirectory(new File(".")); - chooser.getExtensionFilters().add(new ExtensionFilter("YAML", "*.yml")); - File selected = chooser.showOpenDialog(root.getWindow()); - - if (selected == null) - return; - - try (InputStream is = Files.newInputStream(selected.toPath(), StandardOpenOption.READ)) { - YamlMapping mapping = Yaml.createYamlInput(is).readYamlMapping(); - seedField.setText(mapping.string("seed")); - raceLogging.setSelected(Boolean.parseBoolean(mapping.string("raceLogging"))); - settings.load(mapping.yamlMapping("settings")); - } - } private void updatedRomStatus() { boolean exists = Files.exists(WORKING_PATH); diff --git a/src/main/java/net/digimonworld/decode/randomizer/RandoLogger.java b/src/main/java/net/digimonworld/decode/textmod/RandoLogger.java similarity index 97% rename from src/main/java/net/digimonworld/decode/randomizer/RandoLogger.java rename to src/main/java/net/digimonworld/decode/textmod/RandoLogger.java index 8f739cc..5cc9f15 100644 --- a/src/main/java/net/digimonworld/decode/randomizer/RandoLogger.java +++ b/src/main/java/net/digimonworld/decode/textmod/RandoLogger.java @@ -1,4 +1,4 @@ -package net.digimonworld.decode.randomizer; +package net.digimonworld.decode.textmod; import java.io.IOException; import java.io.PrintStream; diff --git a/src/main/java/net/digimonworld/decode/randomizer/RandomizationContext.java b/src/main/java/net/digimonworld/decode/textmod/RandomizationContext.java similarity index 97% rename from src/main/java/net/digimonworld/decode/randomizer/RandomizationContext.java rename to src/main/java/net/digimonworld/decode/textmod/RandomizationContext.java index 54e0325..03e1b16 100644 --- a/src/main/java/net/digimonworld/decode/randomizer/RandomizationContext.java +++ b/src/main/java/net/digimonworld/decode/textmod/RandomizationContext.java @@ -1,4 +1,4 @@ -package net.digimonworld.decode.randomizer; +package net.digimonworld.decode.textmod; import java.io.IOException; import java.nio.file.Files; @@ -9,7 +9,7 @@ import java.util.Map; import java.util.Optional; -import net.digimonworld.decode.randomizer.RandoLogger.LogLevel; +import net.digimonworld.decode.textmod.RandoLogger.LogLevel; import net.digimonworld.decodetools.core.Access; import net.digimonworld.decodetools.core.FileAccess; import net.digimonworld.decodetools.data.digimon.PartnerDigimon; diff --git a/src/main/java/net/digimonworld/decode/textmod/settings/NamingSettings.java b/src/main/java/net/digimonworld/decode/textmod/settings/NamingSettings.java new file mode 100644 index 0000000..daa16ee --- /dev/null +++ b/src/main/java/net/digimonworld/decode/textmod/settings/NamingSettings.java @@ -0,0 +1,784 @@ +package net.digimonworld.decode.textmod.settings; + +import java.io.BufferedReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; +import java.io.BufferedWriter; +import java.nio.file.StandardCopyOption; +import java.nio.file.Path; +import java.nio.file.Files; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.nio.charset.StandardCharsets; +import java.text.ParseException; +import java.util.NoSuchElementException; +import java.util.Comparator; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.controlsfx.control.ToggleSwitch; + +import com.amihaiemil.eoyaml.YamlMapping; + +import net.digimonworld.decodetools.data.keepdata.GlobalKeepData; +import net.digimonworld.decodetools.data.keepdata.LanguageKeep; +import net.digimonworld.decodetools.res.kcap.NormalKCAP; +import net.digimonworld.decodetools.res.payload.BTXPayload; +import net.digimonworld.decodetools.core.DeleteDirectoryFileVisitor; +import net.digimonworld.decodetools.core.Tuple; +import net.digimonworld.decodetools.core.Utils; +import net.digimonworld.decodetools.res.payload.BTXPayload.BTXEntry; +import net.digimonworld.decodetools.res.ResPayload; +import net.digimonworld.decodetools.res.ResPayload.Payload; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.geometry.Pos; +import javafx.beans.binding.BooleanBinding; +import javafx.beans.binding.When; +import javafx.scene.control.Button; +import javafx.scene.control.TitledPane; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.layout.VBox; + +import net.digimonworld.decode.textmod.RandomizationContext; +import net.digimonworld.decode.textmod.utils.JavaFXUtils; +import net.digimonworld.decode.textmod.DecodeTextMod; + +public class NamingSettings implements Setting { + + private final List skippable = List.of("", "None", "Unused Item", "???", "NO DATA", "n"); + private final BooleanProperty renameEnabled = new SimpleBooleanProperty(true); + private final BooleanProperty camelCase = new SimpleBooleanProperty(true); + private final BooleanProperty manualCsv = new SimpleBooleanProperty(); + private final BooleanProperty replaceAll = new SimpleBooleanProperty(true); + private final BooleanProperty pickle = new SimpleBooleanProperty(false); + private final BooleanProperty ogre = new SimpleBooleanProperty(false); + private final BooleanProperty blackPrefix = new SimpleBooleanProperty(false); + private final List priorities = List.of("_general.csv", "_general_digimon.csv", "DigimonNames.csv", "CardNames1.csv", "FinisherNames.csv"); + private final Map repMap = new HashMap<>(); + + /** + * Visualization of a replacement map: + * + * { "part0\arcv\Keep\LanguageKeep_jp.res\11:12" : [ [0,4,2] , [8,13,-1] ] } + * + * Path schema works like this: + * + * [string path to the actual file]/[index of BTX file]:[BTX line] + * + * Replacement info pattern: + * + * [match start, match end, offset of result] + * + * Replacements are saved to prevent replacing terms that have already been + * processed by a prior replacement. The offsets are used to map a position + * of a match to its position in the unmodified line, making it possible to + * exclude replacing matches at specific indices in a line based on the + * unmodified contents. + */ + public Map> replacementMap = new HashMap<>(); + + /** + * DIGIMONMULTI designates names like WarGreymon or MetalGarurumon. + * + * All other DIGIMON names are simply other terms contained in a file + * designated as Digimon name file. + * + * Everything else is classified as "GENERAL" + * + */ + protected enum TermType { + GENERAL, + DIGIMON, + DIGIMONMULTI + } + + private static TermType classifyTerm(String term, String path) { + //These files contain digimon names + List digiNamePaths = List.of(11, 27, 28).stream().map(n -> "part0\\arcv\\Keep\\LanguageKeep_jp.res\\" + n).collect(Collectors.toList()); + digiNamePaths.add("_general_digimon.csv"); + return digiNamePaths.contains(path) ? (term.matches(".*[a-z][A-Z].*") ? TermType.DIGIMONMULTI : TermType.DIGIMON) : TermType.GENERAL; + } + + /** + * This class does everything that has to do with directly replacing + * strings. + */ + private final class Replacement { + + public String original; + public String replacement; + private final List excludedTerms; + private final ArrayList disabledPaths = new ArrayList(); + private final ArrayList enabledPaths = new ArrayList(); + private final int matchLength; + private int index = -1; + /** + * Does this replacement need to check for apostrophe correction? + */ + private final boolean diffS; + /** + * Does this replacement need to check for indefinite article + * correction? + */ + private final boolean diffArt; + private final int baseOffset; + public boolean global = true; + private final List vow = List.of("A", "E", "I", "O", "U", "Ü", "Ö", "Ä"); + + /** + * Utility class used to compare references to text positions supporting + * wildcards for lines and columns. + */ + private final class PathPosition { + + public int line = -1; + public int col = -1; + public boolean wildcard = false; + public String path = ""; + + public PathPosition(String pathDescriptor) { + String[] splitter = pathDescriptor.trim().split(":", -1); + this.path = splitter[0]; + if (this.path.startsWith("*")) { + this.wildcard = true; + this.path = this.path.substring(1); + } + if (splitter.length == 1) return; + + this.line = Integer.parseInt(splitter[1]); + if (splitter.length == 2) this.col = -1; + else this.col = Integer.parseInt(splitter[2]); + } + + /** + * Check if two paths match. If wildcards are used, the second path + * has to be the shorter one which currently is always the case + * since generated paths are always full length. + */ + public boolean matches(PathPosition p2) { + return (this.wildcard ? p2.path.endsWith(path) : p2.path.equals(path)) + && (line == -1 || p2.line == line) + && (col == -1 || p2.col == col); + } + } + + public Replacement(String index, String original, String replacement, String rawExcludedTerms, String rawDisabledPaths, String origin) { + this.index = Integer.parseInt(index); + this.original = original; + this.global = true; + + TermType tType = classifyTerm(replacement, origin); + //Special modifications only apply to Digimon names + if (!manualCsv.get() && tType != TermType.GENERAL) { + if (ogre.get() && replacement.equals("Orgemon")) this.replacement = "Ogremon"; + if (pickle.get() && replacement.equals("Piccolomon")) this.replacement = "Picklemon"; + else if (blackPrefix.get() && replacement.endsWith("mon (Black)")) this.replacement = "Black" + replacement.substring(0, replacement.length() - 8); + else this.replacement = replacement; + } else this.replacement = replacement; + + //Separating multipart Digimon names Wikimon style + if (tType == TermType.DIGIMONMULTI && !camelCase.get()) this.replacement = this.replacement.replaceAll("([a-z])([A-Z])", "$1 $2"); + this.replacement = this.replacement.replaceAll("\\n", "\n"); + + this.diffS = replacement.endsWith("s") != original.endsWith("s"); + + this.diffArt = (original.length() != 0 && replacement.length() != 0) + ? vow.contains(this.replacement.substring(0, 1)) != vow.contains(this.original.substring(0, 1)) + : false; + + this.matchLength = original.length(); + + this.baseOffset = replacement.length() - original.length(); + + this.excludedTerms = List.of(rawExcludedTerms.split(",")).stream().map(p -> p.replaceAll("\\$", original)).collect(Collectors.toList()); + String[] pathos = rawDisabledPaths.split(","); + for (String p : pathos) { + String tp = p.trim(); + if (tp.toLowerCase().equals("all")) this.global = false; + else if (tp.startsWith("!")) this.enabledPaths.add(new PathPosition(tp.substring(1))); + else if (!tp.equals("")) this.disabledPaths.add(new PathPosition(tp)); + } + } + + /** + * Fixing mistakes like Davis' -> Daisuke' etc, returning the + * modification to the offset value. + */ + private int correctApostrophe(BTXEntry btx, int end) { + if (!diffS) return 0; + String text = btx.getString(); + int max = text.length(); + if (max == end) return 0; + if (replacement.endsWith("s")) { + // remove s after apostrophe + if (text.substring(Math.min(end, max), Math.min(end + 2, max)).equals("'s")) { + btx.setString(text.substring(0, end + 1) + text.substring(end + 2)); + return -1; + } else return 0; + } else { + // add s after apostrophe + if (text.substring(Math.min(end, max), Math.min(end + 1, max)).equals("'")) { + btx.setString(text.substring(0, end + 1) + "s" + text.substring(end + 1)); + return 1; + } + return 0; + } + } + + /** + * Fixing mistakes like "a Champion" -> "a Adult", returns the + * modification to the offset value. + * + * Cannot be 100% accurate because of arbitrary "consonantal properties" + * of vowels in some words. + */ + private int correctArticle(BTXEntry btx, int start) { + if (!diffArt || start == 0) return 0; + + String text = btx.getString(); + if (vow.contains(replacement.substring(0, 1))) { + //Adding the missing n + if (text.substring(Math.max(0, start - 3), start).matches(".*\\b[aA]\\b.*")) { + btx.setString(text.substring(0, start - 1) + "n" + text.substring(start - 1)); + return 1; + } + return 0; + } else { + //Removing the n + if (text.substring(Math.max(0, start - 4), start).matches(".*\\b[aA]n\\b.*")) { + btx.setString(text.substring(0, start - 2) + text.substring(start - 1)); + return -1; + } + return 0; + } + } + + /** + * Replace an entire line for a specific index of a BTX. + * This method does not check what the line currently contains. + */ + public void replaceExact(BTXPayload btx, String path) { + BTXEntry entry = btx.getEntryById(index).get(); + if (!original.equals(replacement)) { + entry.setString(replacement); + System.out.println(original + " -> " + replacement); + } + // Exact replacements block any future replacements on this particular line. + insertRepData(path + ":" + index, -1, Integer.MAX_VALUE, 0); + } + + public void replaceDynamic(BTXEntry btx, String path) { + String origText = btx.getString(); + Tuple match = findInText(origText, path); + int matchStart = match.getKey(); + if (matchStart == -1) return; + + String rep = match.getValue(); + + int matchEnd = matchStart + matchLength; + btx.setString(origText.substring(0, matchStart) + rep + origText.substring(matchEnd)); + + int artOff = correctArticle(btx, matchStart); + int apOff = correctApostrophe(btx, matchEnd); + + int finalOffset = baseOffset + artOff + apOff; + System.out.println(path + " | " + origText.substring(matchStart, matchEnd).replaceAll("\n", "\\\\n") + " -> " + btx.getString().substring(matchStart, matchEnd + finalOffset).replaceAll("\n", "\\\\n")); + + insertRepData(path, matchStart, matchEnd, finalOffset); + } + + /** + * Checks where the position of the current match would have been in the + * unmodified text + */ + private int realPosition(String path, int index) { + ArrayList repls = replacementMap.get(path); + if (repls == null) return index; + + int finalOffset = 0; + for (int[] current : repls) { + int start = current[0]; + int offset = current[2]; + if (start > index) break; + + finalOffset += offset; + } + return index + finalOffset; + } + + /** + * Checks if the current match overlaps a text range that has already + * been replaced. + */ + private boolean isOverlapping(String path, int index) { + ArrayList repls = replacementMap.get(path); + if (repls == null) return false; + + + int pos = realPosition(path, index); + for (int[] current : repls) { + int start = current[0]; + int end = current[1]; + // If the start position is bigger than the end of our match we don't need to check the rest + if (start >= pos + (matchLength - 1)) break; + + // Oh no, an overlap! + if (end >= pos && start < pos) return true; + } + return false; + } + + private void insertRepData(String path, int start, int end, int offset) { + int[] entry = new int[]{start, end, offset}; + if (!replacementMap.containsKey(path)) { + ArrayList newList = new ArrayList<>(); + newList.add(entry); + replacementMap.put(path, newList); + return; + } + ArrayList repls = replacementMap.get(path); + //Keeping the list of replacements of each BTX well ordered by inserting it before the first bigger start value + for (int i = 0; i < repls.size(); i++) { + int current = repls.get(i)[0]; + if (current > start) { + repls.add(i, entry); + return; + } + } + repls.add(entry); + } + + private boolean termExclusion(String text, int index) { + for (String term : excludedTerms) { + if (term.equals("[]")) { + //Checking for word boundaries + if (!text.substring(Math.max(0, index - 2), Math.min(text.length(), index + 2)).matches(".*\b" + original + "\b.*")) return true; + continue; + } + int exDex = text.indexOf(term); + if (exDex == -1) { + if (text.contains("\n")) { + Matcher mt = Pattern.compile(term.replaceAll(" ", "(\\\\s)")).matcher(text); + if (mt.find()) exDex = mt.start(); + else continue; + } else continue; + } + int subDex = term.replaceAll("\n", " ").indexOf(original); + if (exDex + subDex == index) return true; + } + return false; + } + + private boolean pathExclusion(String path, int index) { + PathPosition currentPath = new PathPosition(path + ':' + realPosition(path, index)); + for (PathPosition p : disabledPaths) { + if (p.matches(currentPath)) { + System.out.println("skipping " + path + " for " + original); + return true; + } + } + return !enabledPaths.isEmpty() && !enabledPaths.stream().anyMatch(p -> p.matches(currentPath)); + } + + /** + * If a multipart term was broken up by a newline, we match its + * components and attempt to reinsert a space at a comparable position + * in the replacing string + */ + private Tuple adjustForNewlines(String text) { + Matcher spaceMatch = Pattern.compile(original.replaceAll(" ", "(\\\\s)")).matcher(text); + if (!spaceMatch.find()) return new Tuple(-1, replacement); + else { + int first = spaceMatch.start(); + if (!replacement.contains(" ")) return new Tuple(first, replacement + "\n"); + + String[] repSplit = replacement.split(" "); + if (repSplit.length == 2) return new Tuple(first, repSplit[0] + "\n" + repSplit[1]); + + int spaceLoc = 0; + int spaceDex = 0; + for (int i = 1; i < spaceMatch.groupCount(); i++) { + if (spaceMatch.group(i).equals("\n")) { + spaceLoc = i; + break; + } + } + String[] splits = original.split(" "); + for (int i = 0; i < splits.length; i++) { + String s = splits[i]; + spaceDex += s.length() + 1; + if (i == spaceLoc) break; + } + if (spaceDex >= replacement.length()) return new Tuple(first, replacement + "\n"); + + int firstBefore = replacement.substring(0, spaceDex).lastIndexOf(" "); + int firstAfter = replacement.substring(spaceDex).indexOf(" "); + if (firstAfter == -1 && firstBefore == -1) return new Tuple(first, replacement + "\n"); + + int finalSpace = firstAfter == -1 ? firstBefore : firstBefore == -1 ? firstAfter : Math.min(firstAfter, firstBefore) == firstBefore ? firstBefore : firstAfter; + return new Tuple(first, replacement.substring(0, finalSpace) + "\n" + replacement.substring(finalSpace + 1)); + } + + } + + public Tuple findInText(String text, String path) { + int idx = text.indexOf(original); + if (idx == -1 && original.contains(" ") && text.contains("\n")) return adjustForNewlines(text); + //If any of the exclusions match, we return -1 + return new Tuple((idx == -1 || termExclusion(text, idx) || (path != null && (pathExclusion(path, idx) || isOverlapping(path, idx)))) ? -1 : idx, replacement); + } + + } + + /** + * Exports all methods for name lists from the LanguageKeep + */ + private ArrayList getNameListMethods(LanguageKeep lang) { + ArrayList methodList = new ArrayList<>(); + Method[] methods = lang.getClass().getMethods(); + for (Method method : methods) { + String methodName = method.getName(); + if (methodName.contains("Names")) methodList.add(methodName); + } + return methodList; + } + + private static void clearExportDir(File dir) { + try { if (dir.exists()) Files.walkFileTree(dir.toPath(), new DeleteDirectoryFileVisitor());} + catch (IOException exc) { + exc.printStackTrace(); + return; + } + dir.mkdir(); + } + + private static EventHandler buildHandler(File targetDir) { + return (ActionEvent e) -> { + e.consume(); + clearExportDir(targetDir); + try { + BufferedReader reader = new BufferedReader(new InputStreamReader(DecodeTextMod.class.getResourceAsStream("settings/builtinRenamingPreset.csv"))); + String pName; + while ((pName = reader.readLine()) != null) Files.copy(DecodeTextMod.class.getResourceAsStream(pName), Path.of(pName), StandardCopyOption.REPLACE_EXISTING); + } catch (IOException exc) {exc.printStackTrace();} + }; + } + + @Override + public TitledPane create(GlobalKeepData data, LanguageKeep language) { + + + VBox restoreBox = new VBox(8); + + restoreBox.setAlignment(Pos.TOP_LEFT); + + TitledPane pane = new TitledPane("Undub/Editing Settings", restoreBox); + + + pane.setCollapsible(false); + File csvDir = new File(".\\renamingPresets\\"); + manualCsv.set(csvDir.exists() && csvDir.isDirectory() && csvDir.listFiles().length != 0); + + ToggleSwitch camel = JavaFXUtils.buildToggleSwitch("camelCase names", Optional.empty(), Optional.of(camelCase)); + ToggleSwitch manCs = JavaFXUtils.buildToggleSwitch("use Manual CSV", Optional.empty(), Optional.of(manualCsv)); + ToggleSwitch orgeCheck = JavaFXUtils.buildToggleSwitch("'Ogremon' spelling", Optional.empty(), Optional.of(ogre)); + ToggleSwitch pickleCheck = JavaFXUtils.buildToggleSwitch("'Picklemon' spelling", Optional.empty(), Optional.of(pickle)); + ToggleSwitch blackCheck = JavaFXUtils.buildToggleSwitch("Always use 'Black' as prefix", Optional.empty(), Optional.of(blackPrefix)); + ToggleSwitch repAll = JavaFXUtils.buildToggleSwitch("Replace terms in ALL text", Optional.empty(), Optional.of(replaceAll)); + + BooleanBinding manLink = new When(renameEnabled).then(manualCsv).otherwise(renameEnabled.not()); + + manualCsv.addListener(b -> { + if (manualCsv.get() == true && !(csvDir.exists() && csvDir.isDirectory() && csvDir.listFiles().length != 0)) { + JavaFXUtils.showAndWaitAlert(AlertType.ERROR, "No custom CSVs found", null, "No custom data found.\nCustom CSV mode requires a 'renamingPresets' directory\n containing CSV renaming lists."); + manualCsv.set(false); + manCs.fire(); + } + }); + + manCs.disableProperty().bind(renameEnabled.not()); + repAll.disableProperty().bind(renameEnabled.not()); + camel.disableProperty().bind(manLink); + blackCheck.disableProperty().bind(manLink); + + EventHandler rawExportHandler = (ActionEvent event) -> { + event.consume(); + ArrayList methodList = getNameListMethods(language); + + System.out.println(methodList); + clearExportDir(csvDir); + methodList.forEach(s -> { + ArrayList> myList = new ArrayList<>(); + try { + BTXPayload btx = (BTXPayload) language.getClass().getMethod(s).invoke(language); + btx.getEntries().stream().forEach(e -> myList.add(new Tuple(e.getKey(), e.getValue().getString()))); + } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {e.printStackTrace();} + + File destFile = new File(".\\renamingPresets\\" + s.substring(3) + ".csv"); + try (BufferedWriter writer = new BufferedWriter(new FileWriter(destFile, StandardCharsets.UTF_8))) { + writer.write("index;original;replace;excludeTerms;excludePaths\n"); + String string = myList.stream() + .filter(str -> !skippable.contains(str.getValue())) + .map(str -> str.getKey().toString() + ';' + str.getValue() + ";" + str.getValue()) + .collect(Collectors.joining(";;\n")) + + ";;"; + writer.write(string); + } catch (IOException e) {e.printStackTrace();} + }); + manualCsv.set(true); + }; + + Button camelExp = new Button("Export CSVs for built-in preset"); + Button curExp = new Button("Export CSVs for current names"); + curExp.setOnAction(rawExportHandler); + camelExp.setOnAction(buildHandler(csvDir)); + + restoreBox.getChildren().addAll( + JavaFXUtils.buildToggleSwitch("Enabled", Optional.empty(), Optional.of(renameEnabled)), + repAll, + manCs, + camel, + blackCheck, + orgeCheck, + pickleCheck, + curExp, + camelExp); + + return pane; + } + + private class PathResolver { + + private final RandomizationContext context; + private final Map shortcuts = new HashMap<>(); + public final Map keepMap = new HashMap<>(); + + public PathResolver(RandomizationContext context) { + this.context = context; + this.shortcuts.put("keep", "Keep\\LanguageKeep_jp.res"); + this.shortcuts.put("map", "map\\text"); + this.keepMap.put("DigimonNames", "11"); + this.keepMap.put("ItemNames", "0"); + this.keepMap.put("KeyItemNames", "3"); + this.keepMap.put("AccessoryNames", "5"); + this.keepMap.put("SkillNames", "7"); + this.keepMap.put("FinisherNames", "9"); + this.keepMap.put("CharacterNames", "13"); + this.keepMap.put("NatureNames", "16"); + this.keepMap.put("MedalNames", "17"); + this.keepMap.put("GlossaryNames", "25"); + this.keepMap.put("CardNames1", "27"); + this.keepMap.put("CardNames2", "28"); + this.keepMap.put("CardSetNames", "30"); + } + + /** + * Returns a file directly from the RandomizationContext + */ + public ResPayload resolveRaw(String finalPath) throws IOException { + try {return context.getFile(finalPath).get();} + catch (NoSuchElementException exc) {throw new IOException("Path " + finalPath + " does not exist.");} + } + + /** + * Resolves a path directly into BTX payloads while applying shortcuts + */ + public Tuple resolve(String path) throws ParseException { + ArrayList frag = new ArrayList<>( + List.of((keepMap.containsKey(path) ? ("keep-" + keepMap.get(path)) : path).split("-"))); + int btxIndex = Integer.parseInt(frag.remove(frag.size() - 1)); + String finalPath = "part0\\arcv\\" + frag.stream() + .map(s -> shortcuts.containsKey(s) ? shortcuts.get(s) : s) + .collect(Collectors.joining("\\")); + try { + NormalKCAP pk = (NormalKCAP) context.getFile(finalPath).get(); + if (frag.get(frag.size() - 1).equals("keep")) pk = (NormalKCAP) pk.get(0); + return new Tuple<>(finalPath + "\\" + btxIndex, (BTXPayload) pk.get(btxIndex)); + } catch (NoSuchElementException exc) {throw new ParseException("csv not correctly mapped", 0);} + } + } + + /** + * Replacing the contents of a BTX file based on a CSV that contains direct + * mappings to the BTX entry IDs + */ + private void targetedBtxReplacement(BTXPayload btx, List f, String fileName, String path) { + System.out.println(fileName + " -> " + path); + parseReplacements(f, path, false).forEach(r -> r.replaceExact(btx, path)); + } + + /** + * Replacing the contents of a BTX file based on a CSV that contains direct + * mappings to the BTX entry IDs + */ + private void targetedBtxReplacement(BTXPayload btx, File f, String path) { + System.out.println(f.getName() + " -> " + path); + parseReplacements(f, path, false).forEach(r -> r.replaceExact(btx, path)); + } + + private ArrayList instantiateReplacements(List lines, String path, boolean addAll) { + ArrayList rList = new ArrayList<>(); + for (int i = 0; i < lines.size(); i++) { + if (i == 0) continue; + String[] entries = lines.get(i).split(";", -1); + // Even if we don't replace a term, if it's a multipart Digimon name it will be changed if the camelCase option is not set. + if (entries[1].equals(entries[2]) && (camelCase.get() || classifyTerm(entries[2], path) != TermType.DIGIMONMULTI)) continue; + Replacement rep = new Replacement(entries[0], entries[1], entries[2], entries[3], entries[4], path); + rList.add(rep); + //By adding only the first replacement of a word to the global replacement list, we only need to define the global rules once. + if (replaceAll.get() && rep.global && (addAll || !repMap.containsKey(rep.original))) repMap.put(rep.original, rep); + + } + return rList; + } + + private ArrayList parseReplacements(List f, String path, boolean addAll) { + return instantiateReplacements(f, path, addAll); + } + + private ArrayList parseReplacements(File f, String path, boolean addAll) { + try { + List lines = Files.readAllLines(f.toPath(), StandardCharsets.UTF_8); + return instantiateReplacements(lines, path, addAll); + } catch (IOException e) { + e.printStackTrace(); + return new ArrayList<>(); + } + } + + @Override + public void randomize(RandomizationContext context) { + + + PathResolver res = new PathResolver(context); + + // Main logic for dub -> sub conversion + try { + File manualCsvDir = new File(".\\renamingPresets\\"); + if (manualCsv.get() && manualCsvDir.exists()) { + List csvs = List.of(manualCsvDir.listFiles()); + csvs.stream().sorted(Comparator.comparing(f -> priorities.indexOf(f.getName()))).sorted(Comparator.comparing(f -> priorities.contains(f.getName()) ? -1 : 1)).forEach(p -> { + String pName = p.getName(); + if (pName.equals("_general.csv") || pName.equals("_general_digimon.csv")) { + if (replaceAll.get()) { + System.out.println("Parsing general " + (pName.contains("digimon") ? "Digimon " : "") + "replacements"); + parseReplacements(p, pName, true); + } + return; + } + try { + Tuple foundBtx = res.resolve(pName.substring(0, pName.length() - 4)); + targetedBtxReplacement(foundBtx.getValue(), p, foundBtx.getKey()); + } catch (ParseException e) {e.printStackTrace();} + }); + } else { + BufferedReader reader = new BufferedReader(new InputStreamReader(DecodeTextMod.class.getResourceAsStream("settings/builtinRenamingPreset.csv"))); + String pName; + while ((pName = reader.readLine()) != null) { + + BufferedReader reader2 = new BufferedReader(new InputStreamReader(DecodeTextMod.class.getResourceAsStream(pName))); + String str2; + ArrayList foundReps = new ArrayList<>(); + while ((str2 = reader2.readLine()) != null) foundReps.add(str2); + if (pName.endsWith("_general.csv") || pName.endsWith("_general_digimon.csv")) { + if (replaceAll.get()) { + System.out.println("Parsing general " + (pName.contains("digimon") ? "Digimon " : "") + "replacements"); + parseReplacements(foundReps, pName, true); + } + continue; + } + try { + Tuple foundBtx = res.resolve(pName.substring(16, pName.length() - 4)); + targetedBtxReplacement(foundBtx.getValue(), foundReps, pName, foundBtx.getKey()); + } catch (ParseException e) {e.printStackTrace();} + } + + } + + } catch (IOException exc) {exc.printStackTrace();} + + if (!replaceAll.get()) {return;} + + File startDir = new File(".\\working\\part0\\arcv\\"); + + //Sorting our replacements by length to avoid longer replacements getting overriding by prior partial matches. + List sortedReps = repMap.values().stream().sorted(Comparator.comparing(v -> v.original.length() * -1)).collect(Collectors.toList()); + ArrayList> fileEntries = new ArrayList>(); + Utils.listFiles(startDir).stream() + //Everything that could contain BTX + .filter(s -> s.getName().endsWith("_jp.res") + || s.getName().endsWith(".pack") + ).forEach(fA -> { + try { + Path longPath = fA.toPath(); + Path normalPath = longPath.subpath(2, longPath.getNameCount()); + boolean applies; + try (BufferedReader reader = new BufferedReader(new InputStreamReader(Files.newInputStream(longPath), StandardCharsets.UTF_16LE))) { + String str; + applies = false; + while ((str = reader.readLine()) != null) { + String strx = str; + if (sortedReps.stream().anyMatch(r -> r.findInText(strx, null).getKey() != -1)) { + applies = true; + break; + } + } + } + + if (!applies) { + System.out.println("Skipping " + fA.toPath()); + return; + } + var elements = res.resolveRaw(normalPath.toString()).getElementsWithType(Payload.BTX); + + for (int i = 0; i < elements.size(); i++) { + var payload = (BTXPayload) elements.get(i); + String partialPath = normalPath.toString() + "\\" + (i); + payload.getEntries().forEach(bt -> fileEntries.add(new Tuple(partialPath + ":" + bt.getKey(), bt.getValue()))); + } + } catch (IOException e) {e.printStackTrace();} + }); + sortedReps.forEach(rep -> fileEntries.forEach(t -> rep.replaceDynamic(t.getValue(), t.getKey()))); + + repMap.clear(); + replacementMap.clear(); + } + + + @Override + public Map serialize() { + Map map = new HashMap<>(); + map.put("renameEnabled", renameEnabled.get()); + map.put("camelCase", camelCase.get()); + map.put("manualCsv", manualCsv.get()); + map.put("replaceAll", replaceAll.get()); + map.put("pickle", pickle.get()); + map.put("ogre", ogre.get()); + map.put("blackPrefix", blackPrefix.get()); + return map; + } + + @Override + public void load(YamlMapping map) { + if (map == null) return; + renameEnabled.set(Boolean.parseBoolean(map.string("renameEnabled"))); + camelCase.set(Boolean.parseBoolean(map.string("camelCase"))); + manualCsv.set(Boolean.parseBoolean(map.string("manualCsv"))); + replaceAll.set(Boolean.parseBoolean(map.string("replaceAll"))); + pickle.set(Boolean.parseBoolean(map.string("pickle"))); + ogre.set(Boolean.parseBoolean(map.string("ogre"))); + blackPrefix.set(Boolean.parseBoolean(map.string("blackPrefix"))); + } +} diff --git a/src/main/java/net/digimonworld/decode/textmod/settings/RandomizerSettings.java b/src/main/java/net/digimonworld/decode/textmod/settings/RandomizerSettings.java new file mode 100644 index 0000000..e484d31 --- /dev/null +++ b/src/main/java/net/digimonworld/decode/textmod/settings/RandomizerSettings.java @@ -0,0 +1,86 @@ +package net.digimonworld.decode.textmod.settings; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import com.amihaiemil.eoyaml.Yaml; +import com.amihaiemil.eoyaml.YamlMapping; + +import net.digimonworld.decodetools.core.Tuple; +import net.digimonworld.decodetools.data.keepdata.GlobalKeepData; +import net.digimonworld.decodetools.data.keepdata.LanguageKeep; +import javafx.geometry.Insets; +import javafx.geometry.Orientation; +import javafx.scene.control.Tab; +import javafx.scene.layout.FlowPane; +import net.digimonworld.decode.textmod.RandoLogger.LogLevel; +import net.digimonworld.decode.textmod.RandomizationContext; + +public class RandomizerSettings { + + private NamingSettings namingSettings = new NamingSettings(); + private StringRandomizeSettings stringRandoSettings = new StringRandomizeSettings(); + + public void randomize(RandomizationContext context) { + logSettings(context); + namingSettings.randomize(context); + stringRandoSettings.randomize(context); + } + + private void logSettings(RandomizationContext context) { + context.logLine(LogLevel.ALWAYS, "Randomizer Settings: "); + + Map configMap = new HashMap<>(); + configMap.put("seed", context.getInitialSeed()); + configMap.put("settings", serialize()); + configMap.put("raceLogging", context.isRaceLogging()); + + try (StringWriter writer = new StringWriter()) { + Yaml.createYamlPrinter(writer).print(Yaml.createYamlDump(configMap).dump()); + context.logLine(LogLevel.ALWAYS, writer.toString()); + } catch (IOException e) { + // should never happen + e.printStackTrace(); + } + + context.logLine(LogLevel.ALWAYS, ""); + } + + public List create(GlobalKeepData inputData, LanguageKeep languageKeep) { + return getSettingsMap().stream().map(a -> { + FlowPane generalPane = new FlowPane(); + generalPane.setVgap(10); + generalPane.setHgap(10); + generalPane.setPadding(new Insets(10)); + generalPane.setOrientation(Orientation.VERTICAL); + generalPane.setPrefWrapLength(400); + + for (Setting setting : a.getValue()) + generalPane.getChildren().add(setting.create(inputData, languageKeep)); + + return new Tab(a.getKey(), generalPane); + }).collect(Collectors.toList()); + } + + private List>> getSettingsMap() { + return List.of( + Tuple.of("Patch Names", Arrays.asList(namingSettings)), + Tuple.of("Randomize Names", Arrays.asList(stringRandoSettings)) + ); + } + + public Map serialize() { + Map map = new HashMap<>(); + map.put("namingSettings", namingSettings.serialize()); + map.put("stringRandomSettings", stringRandoSettings.serialize()); + return map; + } + + public void load(YamlMapping map) { + } +} diff --git a/src/main/java/net/digimonworld/decode/randomizer/settings/Setting.java b/src/main/java/net/digimonworld/decode/textmod/settings/Setting.java similarity index 85% rename from src/main/java/net/digimonworld/decode/randomizer/settings/Setting.java rename to src/main/java/net/digimonworld/decode/textmod/settings/Setting.java index 38d2806..b219368 100644 --- a/src/main/java/net/digimonworld/decode/randomizer/settings/Setting.java +++ b/src/main/java/net/digimonworld/decode/textmod/settings/Setting.java @@ -1,4 +1,4 @@ -package net.digimonworld.decode.randomizer.settings; +package net.digimonworld.decode.textmod.settings; import java.util.Map; @@ -7,7 +7,7 @@ import net.digimonworld.decodetools.data.keepdata.GlobalKeepData; import net.digimonworld.decodetools.data.keepdata.LanguageKeep; import javafx.scene.control.TitledPane; -import net.digimonworld.decode.randomizer.RandomizationContext; +import net.digimonworld.decode.textmod.RandomizationContext; public interface Setting { diff --git a/src/main/java/net/digimonworld/decode/textmod/settings/StringRandomizeSettings.java b/src/main/java/net/digimonworld/decode/textmod/settings/StringRandomizeSettings.java new file mode 100644 index 0000000..b3d12f7 --- /dev/null +++ b/src/main/java/net/digimonworld/decode/textmod/settings/StringRandomizeSettings.java @@ -0,0 +1,210 @@ +package net.digimonworld.decode.textmod.settings; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Random; +import java.util.stream.Collectors; + +import java.text.ParseException; +import java.util.NoSuchElementException; + +import org.controlsfx.control.ToggleSwitch; + +import com.amihaiemil.eoyaml.YamlMapping; +import com.amihaiemil.eoyaml.YamlSequence; + +import net.digimonworld.decodetools.data.keepdata.GlobalKeepData; +import net.digimonworld.decodetools.data.keepdata.LanguageKeep; +import net.digimonworld.decodetools.res.kcap.NormalKCAP; +import net.digimonworld.decodetools.res.payload.BTXPayload; +import net.digimonworld.decodetools.core.Tuple; +import net.digimonworld.decodetools.res.payload.BTXPayload.BTXEntry; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.SimpleBooleanProperty; + +import javafx.geometry.Pos; + +import javafx.scene.control.TitledPane; +import javafx.scene.layout.VBox; + +import net.digimonworld.decode.textmod.RandomizationContext; +import net.digimonworld.decode.textmod.utils.JavaFXUtils; + +public class StringRandomizeSettings implements Setting { + + private final List skippable = List.of("", "None", "Unused Item", "???", "NO DATA", "n"); + private final BooleanProperty randomizeEnabled = new SimpleBooleanProperty(); + private final Map randoMap = new HashMap<>(); + private final List randoTypes = List.of("Digimon Names", "Finisher Names", "Skill Names", "Character Names", "Item Names", "Medal Names"); + + /** + * Visualization of a replacement map: + * + * { "part0\arcv\Keep\LanguageKeep_jp.res\11:12" : [ [0,4,2] , [8,13,-1] ] } + * + * Path schema works like this: + * + * [string path to the actual file]/[index of BTX file]:[BTX line] + * + * Replacement info pattern: + * + * [match start, match end, offset of result] + * + * Replacements are saved to prevent replacing terms that have already been + * processed by a prior replacement. The offsets are used to map a position + * of a match to its position in the unmodified line, making it possible to + * exclude replacing matches at specific indices in a line based on the + * unmodified contents. + */ + public Map> replacementMap = new HashMap<>(); + + /** + * DIGIMONMULTI designates names like WarGreymon or MetalGarurumon. + * + * All other DIGIMON names are simply other terms contained in a file + * designated as Digijmon name file. + * + * Everything else is classified as "GENERAL" + * + */ + protected enum TermType { + GENERAL, + DIGIMON, + DIGIMONMULTI + } + + private static void btxSwitch(BTXEntry btxA, BTXEntry btxB) { + String a = btxA.getString(); + String b = btxB.getString(); + btxA.setString(b); + btxB.setString(a); + } + + + @Override + public TitledPane create(GlobalKeepData data, LanguageKeep language) { + + + VBox randoBox = new VBox(8); + + randoBox.setAlignment(Pos.TOP_LEFT); + + TitledPane pane = new TitledPane("Randomizer Settings", randoBox); + + + pane.setCollapsible(false); + + + randoBox.getChildren().addAll( + JavaFXUtils.buildToggleSwitch("Enabled", Optional.empty(), Optional.of(randomizeEnabled))); + + for (String r : randoTypes) { + randoMap.put(r, new SimpleBooleanProperty(false)); + ToggleSwitch swit = JavaFXUtils.buildToggleSwitch(r, Optional.empty(), Optional.of(randoMap.get(r))); + swit.disableProperty().bind(randomizeEnabled.not()); + randoBox.getChildren().add(swit); + } + + return pane; + } + + private class PathResolver { + + private final RandomizationContext context; + private final Map shortcuts = new HashMap<>(); + public final Map keepMap = new HashMap<>(); + + public PathResolver(RandomizationContext context) { + this.context = context; + this.shortcuts.put("keep", "Keep\\LanguageKeep_jp.res"); + this.shortcuts.put("map", "map\\text"); + this.keepMap.put("DigimonNames", "11"); + this.keepMap.put("ItemNames", "0"); + this.keepMap.put("KeyItemNames", "3"); + this.keepMap.put("AccessoryNames", "5"); + this.keepMap.put("SkillNames", "7"); + this.keepMap.put("FinisherNames", "9"); + this.keepMap.put("CharacterNames", "13"); + this.keepMap.put("NatureNames", "16"); + this.keepMap.put("MedalNames", "17"); + this.keepMap.put("GlossaryNames", "25"); + this.keepMap.put("CardNames1", "27"); + this.keepMap.put("CardNames2", "28"); + this.keepMap.put("CardSetNames", "30"); + } + + + + /** + * Resolves a path directly into BTX payloads while applying shortcuts + */ + public Tuple resolve(String path) throws ParseException { + ArrayList frag = new ArrayList<>( + List.of((keepMap.containsKey(path) ? ("keep-" + keepMap.get(path)) : path).split("-"))); + int btxIndex = Integer.parseInt(frag.remove(frag.size() - 1)); + String finalPath = "part0\\arcv\\" + frag.stream() + .map(s -> shortcuts.containsKey(s) ? shortcuts.get(s) : s) + .collect(Collectors.joining("\\")); + try { + NormalKCAP pk = (NormalKCAP) context.getFile(finalPath).get(); + if (frag.get(frag.size() - 1).equals("keep")) pk = (NormalKCAP) pk.get(0); + return new Tuple<>(finalPath + "\\" + btxIndex, (BTXPayload) pk.get(btxIndex)); + } catch (NoSuchElementException exc) {throw new ParseException("csv not correctly mapped", 0);} + } + } + + + + + @Override + public void randomize(RandomizationContext context) { + + + PathResolver res = new PathResolver(context); + + //Randomizing different lists of strings + Random rand = new Random(context.getInitialSeed() * "ShuffleTerms".hashCode()); + randoTypes.stream().filter(k -> randoMap.get(k).get()).map(s -> s.replaceAll(" ", "")).forEach(name -> { + try { + //creating a list of all btx entries in the payload without empty/filler fields + ArrayList entries = new ArrayList<>(res.resolve(name).getValue().getEntries().stream().map(e -> e.getValue()).filter(v -> !skippable.contains(v.getString())).collect(Collectors.toList())); + + BTXEntry firstEntry = null; + //Switching the value of a random pair of BTX entries and removing them from the list. + while (entries.size() > 1) { + int i = rand.nextInt(entries.size()); + BTXEntry btxA = entries.remove(i); + if (firstEntry == null) firstEntry = btxA; + int n = rand.nextInt(entries.size()); + BTXEntry btxB = entries.remove(n); + btxSwitch(btxA, btxB); + } + //In case there's an uneven number of entries we switch the leftover entry with the first entry we processed previously + if (entries.size() == 1) btxSwitch(firstEntry, entries.get(0)); + } catch (ParseException e) {e.printStackTrace();} + }); + + } + + @Override + public Map serialize() { + Map map = new HashMap<>(); + map.put("randomizeEnabled", randomizeEnabled.get()); + map.put("randomChecked", randoMap.entrySet().stream().filter(a -> a.getValue().get()).map(Map.Entry::getKey).collect(Collectors.toList())); + return map; + } + + @Override + public void load(YamlMapping map) { + if (map == null) return; + + YamlSequence list = map.yamlSequence("randomChecked"); + List activeList = list == null ? new ArrayList<>() : list.values().stream().map(a -> a.toString()).collect(Collectors.toList()); + randoMap.forEach((a, b) -> b.set(activeList.contains(a))); + randomizeEnabled.set(Boolean.parseBoolean(map.string("randomizeEnabled"))); + } +} diff --git a/src/main/java/net/digimonworld/decode/textmod/settings/package-info.java b/src/main/java/net/digimonworld/decode/textmod/settings/package-info.java new file mode 100644 index 0000000..b4e8f18 --- /dev/null +++ b/src/main/java/net/digimonworld/decode/textmod/settings/package-info.java @@ -0,0 +1 @@ +package net.digimonworld.decode.textmod.settings; diff --git a/src/main/java/net/digimonworld/decode/randomizer/utils/JavaFXUtils.java b/src/main/java/net/digimonworld/decode/textmod/utils/JavaFXUtils.java similarity index 95% rename from src/main/java/net/digimonworld/decode/randomizer/utils/JavaFXUtils.java rename to src/main/java/net/digimonworld/decode/textmod/utils/JavaFXUtils.java index 620969c..1b9e4c5 100644 --- a/src/main/java/net/digimonworld/decode/randomizer/utils/JavaFXUtils.java +++ b/src/main/java/net/digimonworld/decode/textmod/utils/JavaFXUtils.java @@ -1,4 +1,4 @@ -package net.digimonworld.decode.randomizer.utils; +package net.digimonworld.decode.textmod.utils; import java.util.Optional; diff --git a/src/main/resources/net/digimonworld/decode/randomizer/settings/BlackAgumon.png b/src/main/resources/net/digimonworld/decode/randomizer/settings/BlackAgumon.png deleted file mode 100644 index c3cb545..0000000 Binary files a/src/main/resources/net/digimonworld/decode/randomizer/settings/BlackAgumon.png and /dev/null differ diff --git a/src/main/resources/net/digimonworld/decode/randomizer/settings/BlackGabumon.png b/src/main/resources/net/digimonworld/decode/randomizer/settings/BlackGabumon.png deleted file mode 100644 index 3df5cbc..0000000 Binary files a/src/main/resources/net/digimonworld/decode/randomizer/settings/BlackGabumon.png and /dev/null differ diff --git a/src/main/resources/net/digimonworld/decode/randomizer/settings/BlackGarurumon.png b/src/main/resources/net/digimonworld/decode/randomizer/settings/BlackGarurumon.png deleted file mode 100644 index 40041e4..0000000 Binary files a/src/main/resources/net/digimonworld/decode/randomizer/settings/BlackGarurumon.png and /dev/null differ diff --git a/src/main/resources/net/digimonworld/decode/randomizer/settings/BlackMetalGarurumon.png b/src/main/resources/net/digimonworld/decode/randomizer/settings/BlackMetalGarurumon.png deleted file mode 100644 index 0b047a2..0000000 Binary files a/src/main/resources/net/digimonworld/decode/randomizer/settings/BlackMetalGarurumon.png and /dev/null differ diff --git a/src/main/resources/net/digimonworld/decode/randomizer/settings/BlackWarGreymon.png b/src/main/resources/net/digimonworld/decode/randomizer/settings/BlackWarGreymon.png deleted file mode 100644 index cb8d020..0000000 Binary files a/src/main/resources/net/digimonworld/decode/randomizer/settings/BlackWarGreymon.png and /dev/null differ diff --git a/src/main/resources/net/digimonworld/decode/randomizer/settings/BlackWereGarurumon.png b/src/main/resources/net/digimonworld/decode/randomizer/settings/BlackWereGarurumon.png deleted file mode 100644 index e71238f..0000000 Binary files a/src/main/resources/net/digimonworld/decode/randomizer/settings/BlackWereGarurumon.png and /dev/null differ diff --git a/src/main/resources/net/digimonworld/decode/randomizer/settings/itemSpawnMapping.csv b/src/main/resources/net/digimonworld/decode/randomizer/settings/itemSpawnMapping.csv deleted file mode 100644 index d56052a..0000000 --- a/src/main/resources/net/digimonworld/decode/randomizer/settings/itemSpawnMapping.csv +++ /dev/null @@ -1,50 +0,0 @@ -can01,12 -can02,12 -can03,12 -can04,12 -des01,12 -des02,12 -des03,12 -des04,12 -des05,12 -fie01,12 -fie02,12 -fie03,12 -fie04,12 -fie05,12 -for01,12 -for02,6 -for03,6 -for04,12 -for05,12 -gro01,6 -gro02,6 -gro03,6 -gro04,6 -gro05,6 -gro06,6 -mar01,12 -mar02,13 -mar03,12 -mar04,13 -mar05,12 -mar06,12 -sea01,12 -sea02,12 -sea03,12 -sea04,12 -sno01,12 -sno02,12 -sno03,6 -sno04,6 -tem01,6 -tem02,6 -tem03,6 -vol01,6 -vol03,6 -vol04,12 -vol05,6 -wat01,6 -wat02,6 -wat03,6 -wat04,6 \ No newline at end of file diff --git a/src/main/resources/net/digimonworld/decode/randomizer/AboutScene.fxml b/src/main/resources/net/digimonworld/decode/textmod/AboutScene.fxml similarity index 71% rename from src/main/resources/net/digimonworld/decode/randomizer/AboutScene.fxml rename to src/main/resources/net/digimonworld/decode/textmod/AboutScene.fxml index a894d00..ac31f40 100644 --- a/src/main/resources/net/digimonworld/decode/randomizer/AboutScene.fxml +++ b/src/main/resources/net/digimonworld/decode/textmod/AboutScene.fxml @@ -9,14 +9,16 @@ - + - + @@ -29,6 +31,11 @@ + + + + + diff --git a/src/main/resources/net/digimonworld/decode/randomizer/MainWindow.fxml b/src/main/resources/net/digimonworld/decode/textmod/MainWindow.fxml similarity index 78% rename from src/main/resources/net/digimonworld/decode/randomizer/MainWindow.fxml rename to src/main/resources/net/digimonworld/decode/textmod/MainWindow.fxml index 46b95e4..f522280 100644 --- a/src/main/resources/net/digimonworld/decode/randomizer/MainWindow.fxml +++ b/src/main/resources/net/digimonworld/decode/textmod/MainWindow.fxml @@ -17,12 +17,14 @@ - +
- + @@ -38,9 +40,7 @@
- - - - - - - - - - - - + + + + + + + + + + + +
diff --git a/src/main/resources/net/digimonworld/decode/randomizer/main.css b/src/main/resources/net/digimonworld/decode/textmod/main.css similarity index 100% rename from src/main/resources/net/digimonworld/decode/randomizer/main.css rename to src/main/resources/net/digimonworld/decode/textmod/main.css diff --git a/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/AccessoryNames.csv b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/AccessoryNames.csv new file mode 100644 index 0000000..99295f9 --- /dev/null +++ b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/AccessoryNames.csv @@ -0,0 +1,9 @@ +index;original;replace;excludeTerms;excludePaths +35;Antyla Ears;Andira Ears;; +55;Tai's Goggles;Taichi's Goggles;; +56;Davis' Goggles;Daisuke's Goggles;; +92;Tai's Digivice;Taichi's Digivice;; +104;Myotis Mask;Vam Mask;; +110;T.K.'s Cap;Takeru's Cap;; +112;Puppet Cap;Pinocchi Cap;; +169;Dera Bush;Delu Bush;; \ No newline at end of file diff --git a/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/CardNames1.csv b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/CardNames1.csv new file mode 100644 index 0000000..fba0a04 --- /dev/null +++ b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/CardNames1.csv @@ -0,0 +1,195 @@ +index;original;replace;excludeTerms;excludePaths +13;Biyomon;Piyomon;; +16;Candlemon;Candmon;; +17;Chuumon;Tyumon;; +18;Tsukaimon;Tukaimon;; +25;DemiDevimon;PicoDevimon;; +29;SnowAgumon;YukiAgumon;; +36;Dorumon;DORUmon;; +41;ExVeemon;XV-mon;; +46;BlackGatomon;BlackTailmon;; +51;Growlmon;Growmon;; +53;Growlmon (Orange);Growmon (Orange);; +54;Gatomon;Tailmon;; +56;BlackGrowlmon;BlackGrowmon;; +58;BlackGarurumon;Garurumon (Black);; +62;Sukamon;Scumon;; +72;MagnaAngemon;HolyAngemon;; +77;Myotismon;Vamdemon;; +79;WarGrowlmon;MegaloGrowmon;; +80;BlackWarGrowlmon;BlackMegaloGrowmon;; +84;BlackWereGarurumon;WereGarurumon (Black);; +86;MegaKabuterimon;AtlurKabuterimon;; +90;MetalTyrannomon;MetalTyranomon;; +96;Phoenixmon;Hououmon;; +100;MarineAngemon;MarinAngemon;; +107;BlackMetalGarurumon;MetalGarurumon (Black);; +108;ZeedGarurumon;Z'dGarurumon;; +109;HerculesKabuterimon;HerakleKabuterimon;; +112;ChaosGallantmon;ChaosDukemon;; +113;MaloMyotismon;BelialVamdemon;; +115;Ghoulmon;Deathmon;; +120;Antylamon;Andiramon;; +129;Machinedramon;Mugendramon;; +132;NeoMyotismon;NeoVamdemon;; +141;Ophanimon;Ofanimon;; +145;Beelzemon;Beelzebumon;; +149;Daemon;Demon;; +150;Goldramon;Goddramon;; +151;Magnadramon;Holydramon;; +153;Azulongmon;Qinglongmon;; +156;Ebonwumon;Xuanwumon;; +159;AncientBeetlemon;AncientBeatmon;; +160;AncientKazemon;AncientIrismon;; +161;AncientMegatheriummon;AncientMegatheriumon;; +162;AncientMermaidmon;AncientMermaimon;; +163;AncientTroymon;AncientTroiamon;; +173;Gallantmon;Dukemon;; +176;Crusadermon;Dukemon;; +177;UlforceVeedramon;UlforceV-dramon;; +178;Craniamon;Craniummon;; +179;Kentaurosmon;Sleipmon;; +180;Leopardmon;Duftmon;; +185;Merukimon;Mercurymon;; +200;SkullScorpiomon X;Anomalocarimon X;; +201;UlforceVeedramon X;UlforceV-dramon X;; +203;Ebemon X;EBEmon X;; +206;Samudramon;Gaioumon;; +209;Crabmon X;Ganimon X;; +214;Growlmon X;Growmon X;; +215;GranDracmon;GrandDracumon;; +218;Cerberusmon X;Cerberumon X;; +220;Goldramon X;Goddramon X;; +221;Gotsumon X;Gottsumon X;; +224;Thundermon X;Thunderballmon X;; +227;SkullMammothmon X;SkullMammon X;; +233;DexDorugamon;Death-X-DORUgamon;; +234;DexDoruGreymon;Death-X-DORUguremon;; +235;Dexmon;Death-X-mon;; +236;Gallantmon X;Dukemon X;; +238;Leopardmon X;Duftmon X;; +240;Dracmon;Dracumon;; +245;IceLeomon X;Panjyamon X;; +248;Salamon X;Plotmon X;; +251;Beelzemon X;Beelzebumon X;; +252;Magnadramon X;Holydramon X;; +254;Matadormon;Matadrmon;; +257;Mammothmon X;Mammon X;; +259;WarGrowlmon X;MegaloGrowmon X;; +263;MetalTyrannomon X;MetalTyranomon X;; +265;MedievalGallantmon;MedievalDukemon;; +267;Lillymon X;Lilimon X;; +271;Tyrannomon;Tyranomon;; +272;DarkTyrannomon;DarkTyranomon;; +273;ExTyrannomon;Ex-Tyranomon;; +274;MasterTyrannomon;MasterTyranomon;; +276;RustTyrannomon;RustTyranomon;; +283;Kimeramon;Chimairamon;; +284;Dorugamon;DORUgamon;; +285;DoruGreymon;DORUguremon;; +286;Dorugoramon;DORUgoramon;; +287;DexDorugoramon;Death-X-DORUgoramon;; +311;Ravemon BM;Ravmon BM;; +312;Aurumon;Owlmon;; +316;Pteramon;Pteranomon;; +317;Halsemon;Holsmon;; +318;Elephantmon;Elephamon;; +327;Pegasusmon;Pegasmon;; +334;Yasyamon;Yaksamon;; +343;Butterflymon;Butterflamon;; +348;Quetzalmon;Coatlmon;; +361;Salamandermon;Salamandamon;; +364;FlameWizardmon;FlaWizardmon;; +365;Flamedramon;Fladramon;; +369;Thunderbirdmon;Thunderbirmon;; +374;Raidramon;Lighdramon;; +375;Linkmon;Rinkmon;; +376;GoldVeedramon;GoldV-dramon;; +378;Agunimon;Agnimon;; +380;BurningGreymon;Vritramon;; +381;EmperorGreymon;KaiserGreymon;; +382;Flamemon;Flamon;; +386;Kumamon;Chackmon;; +387;Korikakumon;Blizzarmon;; +389;Zephyrmon;Shutumon;; +390;Kazemon;Fairimon;; +391;Beetlemon;Blitzmon;; +392;MetalKabuterimon;Bolgmon;; +397;Grumblemon;Grottemon;; +398;Sakkakumon;Sephirothmon;; +399;Mercurymon;Mercuremon;; +400;Lobomon;Wolfmon;; +401;KendoGarurumon;Garummon;; +402;BeoWolfmon;Beowolfmon;; +405;JagerLoweemon;KaiserLeomon;; +407;Velgemon;Velgrmon;; +408;Rhihimon;Raihimon;; +409;Loweemon;Löwemon;; +411;Wizardmon;Wizarmon;; +412;Garbagemon;Gerbemon;; +414;Centarumon;Centalmon;; +416;Cherrymon;Jyureimon;; +418;Deramon;Delumon;; +419;ShogunGekomon;TonosamaGekomon;; +424;Frigimon;Yukidarumon;; +425;Lillymon;Lilimon;; +426;Salamon;Plotmon;; +433;Diaboromon;Diablomon;; +446;ProfessorAgumon;Agumon Hakase;; +450;Armadillomon;Armadiomon;; +451;Wendigomon;Wendimon;; +452;Gwappamon;Gawappamon;; +454;Shawjamon;Shawujinmon;; +458;Chirinmon;Tyilinmon;; +459;Gallantmon Crimson Mode;Dukemon Crimson Mode;; +463;Crowmon;Yatagaramon;; +464;Ravemon;Ravmon;; +470;Gargomon;Galgomon;; +474;MegaGargomon;SaintGalgomon;; +479;Beelzemon Blast Mode;Beelzebumon Blast Mode;; +483;Ogremon;Orgemon;; +484;Veedramon;V-dramon;; +485;AeroVeedramon;AeroV-dramon;; +486;Piedmon;Piemon;; +487;Vegiemon;Vegimon;; +489;Puppetmon;Pinochimon;; +491;Piximon;Piccolomon;; +494;Hi-Andromon;HiAndromon;; +497;SkullMeramon;DeathMeramon;; +498;GrapLeomon;GrappuLeomon;; +500;IceLeomon;Panjyamon;; +501;Pabumon;Bubbmon;; +502;Motimon;Mochimon;; +508;Fake ProfessorAgumon;NiseAgumon Hakase;; +510;Alphamon Ouryuken;Alphamon: Ouryuken;; +511;Millenniummon;Millenniumon;; +512;ZeedMillenniummon;ZeedMillenniumon;; +513;MoonMillenniummon;MoonMillenniumon;; +516;ShogunMamemon;TonosamaMamemon;; +520;Shamanmon;Shamamon;; +523;SkullScorpiomon;Scorpiomon;; +524;Ebemon;EBEmon;; +527;Cerberusmon;Cerberumon;; +528;Gotsumon;Gottsumon;; +529;Thundermon;Thunderballmon;; +530;SkullMammothmon;SkullMammon;; +535;Mammothmon;Mammon;; +536;UltimateBrachiomon;UltimateBrachimon;; +537;Fanbeemon;Funbeemon;; +538;TobuCatmon;Tobucatmon;; +543;Pteramon X;Pteranomon X;; +546;Syakomon X;Shakomon X;; +550;Syakomon;Shakomon;; +553;Penguinmon;Penmon;; +555;Tsunomon;Tunomon;; +558;Kokatorimon;Cockatrimon;; +560;Ninjamon;Igamon;; +565;Pichimon;Pitchmon;; +569;Chibomon;Chicomon;; +570;DemiVeemon;Chibimon;; +581;Conomon;Cocomon;; +582;Kokomon;Chocomon;; +583;MetalKoromon;Choromon;; +586;DemiMeramon;PetitMeramon;; +587;Calumon;Culumon;; +588;Kapurimon;Caprimon;; \ No newline at end of file diff --git a/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/CardNames2.csv b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/CardNames2.csv new file mode 100644 index 0000000..fba0a04 --- /dev/null +++ b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/CardNames2.csv @@ -0,0 +1,195 @@ +index;original;replace;excludeTerms;excludePaths +13;Biyomon;Piyomon;; +16;Candlemon;Candmon;; +17;Chuumon;Tyumon;; +18;Tsukaimon;Tukaimon;; +25;DemiDevimon;PicoDevimon;; +29;SnowAgumon;YukiAgumon;; +36;Dorumon;DORUmon;; +41;ExVeemon;XV-mon;; +46;BlackGatomon;BlackTailmon;; +51;Growlmon;Growmon;; +53;Growlmon (Orange);Growmon (Orange);; +54;Gatomon;Tailmon;; +56;BlackGrowlmon;BlackGrowmon;; +58;BlackGarurumon;Garurumon (Black);; +62;Sukamon;Scumon;; +72;MagnaAngemon;HolyAngemon;; +77;Myotismon;Vamdemon;; +79;WarGrowlmon;MegaloGrowmon;; +80;BlackWarGrowlmon;BlackMegaloGrowmon;; +84;BlackWereGarurumon;WereGarurumon (Black);; +86;MegaKabuterimon;AtlurKabuterimon;; +90;MetalTyrannomon;MetalTyranomon;; +96;Phoenixmon;Hououmon;; +100;MarineAngemon;MarinAngemon;; +107;BlackMetalGarurumon;MetalGarurumon (Black);; +108;ZeedGarurumon;Z'dGarurumon;; +109;HerculesKabuterimon;HerakleKabuterimon;; +112;ChaosGallantmon;ChaosDukemon;; +113;MaloMyotismon;BelialVamdemon;; +115;Ghoulmon;Deathmon;; +120;Antylamon;Andiramon;; +129;Machinedramon;Mugendramon;; +132;NeoMyotismon;NeoVamdemon;; +141;Ophanimon;Ofanimon;; +145;Beelzemon;Beelzebumon;; +149;Daemon;Demon;; +150;Goldramon;Goddramon;; +151;Magnadramon;Holydramon;; +153;Azulongmon;Qinglongmon;; +156;Ebonwumon;Xuanwumon;; +159;AncientBeetlemon;AncientBeatmon;; +160;AncientKazemon;AncientIrismon;; +161;AncientMegatheriummon;AncientMegatheriumon;; +162;AncientMermaidmon;AncientMermaimon;; +163;AncientTroymon;AncientTroiamon;; +173;Gallantmon;Dukemon;; +176;Crusadermon;Dukemon;; +177;UlforceVeedramon;UlforceV-dramon;; +178;Craniamon;Craniummon;; +179;Kentaurosmon;Sleipmon;; +180;Leopardmon;Duftmon;; +185;Merukimon;Mercurymon;; +200;SkullScorpiomon X;Anomalocarimon X;; +201;UlforceVeedramon X;UlforceV-dramon X;; +203;Ebemon X;EBEmon X;; +206;Samudramon;Gaioumon;; +209;Crabmon X;Ganimon X;; +214;Growlmon X;Growmon X;; +215;GranDracmon;GrandDracumon;; +218;Cerberusmon X;Cerberumon X;; +220;Goldramon X;Goddramon X;; +221;Gotsumon X;Gottsumon X;; +224;Thundermon X;Thunderballmon X;; +227;SkullMammothmon X;SkullMammon X;; +233;DexDorugamon;Death-X-DORUgamon;; +234;DexDoruGreymon;Death-X-DORUguremon;; +235;Dexmon;Death-X-mon;; +236;Gallantmon X;Dukemon X;; +238;Leopardmon X;Duftmon X;; +240;Dracmon;Dracumon;; +245;IceLeomon X;Panjyamon X;; +248;Salamon X;Plotmon X;; +251;Beelzemon X;Beelzebumon X;; +252;Magnadramon X;Holydramon X;; +254;Matadormon;Matadrmon;; +257;Mammothmon X;Mammon X;; +259;WarGrowlmon X;MegaloGrowmon X;; +263;MetalTyrannomon X;MetalTyranomon X;; +265;MedievalGallantmon;MedievalDukemon;; +267;Lillymon X;Lilimon X;; +271;Tyrannomon;Tyranomon;; +272;DarkTyrannomon;DarkTyranomon;; +273;ExTyrannomon;Ex-Tyranomon;; +274;MasterTyrannomon;MasterTyranomon;; +276;RustTyrannomon;RustTyranomon;; +283;Kimeramon;Chimairamon;; +284;Dorugamon;DORUgamon;; +285;DoruGreymon;DORUguremon;; +286;Dorugoramon;DORUgoramon;; +287;DexDorugoramon;Death-X-DORUgoramon;; +311;Ravemon BM;Ravmon BM;; +312;Aurumon;Owlmon;; +316;Pteramon;Pteranomon;; +317;Halsemon;Holsmon;; +318;Elephantmon;Elephamon;; +327;Pegasusmon;Pegasmon;; +334;Yasyamon;Yaksamon;; +343;Butterflymon;Butterflamon;; +348;Quetzalmon;Coatlmon;; +361;Salamandermon;Salamandamon;; +364;FlameWizardmon;FlaWizardmon;; +365;Flamedramon;Fladramon;; +369;Thunderbirdmon;Thunderbirmon;; +374;Raidramon;Lighdramon;; +375;Linkmon;Rinkmon;; +376;GoldVeedramon;GoldV-dramon;; +378;Agunimon;Agnimon;; +380;BurningGreymon;Vritramon;; +381;EmperorGreymon;KaiserGreymon;; +382;Flamemon;Flamon;; +386;Kumamon;Chackmon;; +387;Korikakumon;Blizzarmon;; +389;Zephyrmon;Shutumon;; +390;Kazemon;Fairimon;; +391;Beetlemon;Blitzmon;; +392;MetalKabuterimon;Bolgmon;; +397;Grumblemon;Grottemon;; +398;Sakkakumon;Sephirothmon;; +399;Mercurymon;Mercuremon;; +400;Lobomon;Wolfmon;; +401;KendoGarurumon;Garummon;; +402;BeoWolfmon;Beowolfmon;; +405;JagerLoweemon;KaiserLeomon;; +407;Velgemon;Velgrmon;; +408;Rhihimon;Raihimon;; +409;Loweemon;Löwemon;; +411;Wizardmon;Wizarmon;; +412;Garbagemon;Gerbemon;; +414;Centarumon;Centalmon;; +416;Cherrymon;Jyureimon;; +418;Deramon;Delumon;; +419;ShogunGekomon;TonosamaGekomon;; +424;Frigimon;Yukidarumon;; +425;Lillymon;Lilimon;; +426;Salamon;Plotmon;; +433;Diaboromon;Diablomon;; +446;ProfessorAgumon;Agumon Hakase;; +450;Armadillomon;Armadiomon;; +451;Wendigomon;Wendimon;; +452;Gwappamon;Gawappamon;; +454;Shawjamon;Shawujinmon;; +458;Chirinmon;Tyilinmon;; +459;Gallantmon Crimson Mode;Dukemon Crimson Mode;; +463;Crowmon;Yatagaramon;; +464;Ravemon;Ravmon;; +470;Gargomon;Galgomon;; +474;MegaGargomon;SaintGalgomon;; +479;Beelzemon Blast Mode;Beelzebumon Blast Mode;; +483;Ogremon;Orgemon;; +484;Veedramon;V-dramon;; +485;AeroVeedramon;AeroV-dramon;; +486;Piedmon;Piemon;; +487;Vegiemon;Vegimon;; +489;Puppetmon;Pinochimon;; +491;Piximon;Piccolomon;; +494;Hi-Andromon;HiAndromon;; +497;SkullMeramon;DeathMeramon;; +498;GrapLeomon;GrappuLeomon;; +500;IceLeomon;Panjyamon;; +501;Pabumon;Bubbmon;; +502;Motimon;Mochimon;; +508;Fake ProfessorAgumon;NiseAgumon Hakase;; +510;Alphamon Ouryuken;Alphamon: Ouryuken;; +511;Millenniummon;Millenniumon;; +512;ZeedMillenniummon;ZeedMillenniumon;; +513;MoonMillenniummon;MoonMillenniumon;; +516;ShogunMamemon;TonosamaMamemon;; +520;Shamanmon;Shamamon;; +523;SkullScorpiomon;Scorpiomon;; +524;Ebemon;EBEmon;; +527;Cerberusmon;Cerberumon;; +528;Gotsumon;Gottsumon;; +529;Thundermon;Thunderballmon;; +530;SkullMammothmon;SkullMammon;; +535;Mammothmon;Mammon;; +536;UltimateBrachiomon;UltimateBrachimon;; +537;Fanbeemon;Funbeemon;; +538;TobuCatmon;Tobucatmon;; +543;Pteramon X;Pteranomon X;; +546;Syakomon X;Shakomon X;; +550;Syakomon;Shakomon;; +553;Penguinmon;Penmon;; +555;Tsunomon;Tunomon;; +558;Kokatorimon;Cockatrimon;; +560;Ninjamon;Igamon;; +565;Pichimon;Pitchmon;; +569;Chibomon;Chicomon;; +570;DemiVeemon;Chibimon;; +581;Conomon;Cocomon;; +582;Kokomon;Chocomon;; +583;MetalKoromon;Choromon;; +586;DemiMeramon;PetitMeramon;; +587;Calumon;Culumon;; +588;Kapurimon;Caprimon;; \ No newline at end of file diff --git a/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/CardSetNames.csv b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/CardSetNames.csv new file mode 100644 index 0000000..e93108e --- /dev/null +++ b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/CardSetNames.csv @@ -0,0 +1,30 @@ +index;original;replace;excludeTerms;excludePaths +3;Digimon Sovereigns;Holy Beasts;; +10;Ebonwumon's Followers;Xuanwumon's Followers;; +11;Azulongmon's Followers;Qinglongmon's Followers;; +16;Biyomon Line;Piyomon Line;; +21;Gatomon Line;Tailmon Line;; +22;Veemon Line;V-mon Line;; +23;Armadillomon Line;Armadimon Line;; +26;Digi-Egg of Courage;Digimental of Courage;; +27;Digi-Egg of Friendship;Digimental of Friendship;; +28;Digi-Egg of Love;Digimental of Love;; +29;Digi-Egg of Knowledge;Digimental of Knowledge;; +30;Digi-Egg of Purity;Digimental of Purity;; +31;Digi-Egg of Sincerity;Digimental of Sincerity;; +32;Digi-Egg of Hope;Digimental of Hope;; +33;Digi-Egg of Light;Digimental of Light;; +34;Digi-Egg of Kindness;Digimental of Kindness;; +35;Digi-Egg of Miracles;Digimental of Miracles;; +36;Digi-Egg of Fate;Digimental of Fate;; +41;BeoWolfmon Line;Beowolfmon Line;; +54;Veedramon Line;V-dramon Line;; +63;DNA Digivolutions 1;Jogress Evolutions 1;; +64;DNA Digivolutions 2;Jogress Evolutions 2;; +65;DNA Digivolutions 3;Jogress Evolutions 3;; +66;DNA Digivolutions 4;Jogress Evolutions 4;; +67;DNA Digivolutions 5;Jogress Evolutions 5;; +68;Kimera Data;Chimera Data;; +73;Tyranno Brothers;Tyrano Brothers;; +91;Tricolour Growlmon;Tricolour Growmon;; +92;Tricolour WarGrowlmon;Tricolour MegaloGrowmon;; \ No newline at end of file diff --git a/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/CharacterNames.csv b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/CharacterNames.csv new file mode 100644 index 0000000..6a53588 --- /dev/null +++ b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/CharacterNames.csv @@ -0,0 +1,10 @@ +index;original;replace;excludeTerms;excludePaths +1024;Tai;Taichi;[]; +1025;Matt;Yamato;[]; +1027;Davis;Daisuke;; +1032;Izzy Izumi;Koushiro Izumi;; +1036;Kari Kamiya;Hikari Yagami;; +1037;Marcus Damon;Masaru Daimon;; +1055;Izzy Izumi;Kosuhiro Izumi;; +1059;Kari Kamiya;Hikari Yagami;; +1060;Marcus Damon;Masaru Daimon;; \ No newline at end of file diff --git a/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/DigimonNames.csv b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/DigimonNames.csv new file mode 100644 index 0000000..c0cfe0f --- /dev/null +++ b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/DigimonNames.csv @@ -0,0 +1,73 @@ +index;original;replace;excludeTerms;excludePaths +3;Jarimon;Jyarimon;; +12;Candlemon;Candmon;; +13;Chuumon;Tyumon;; +14;Tsukaimon;Tukaimon;; +15;Agumon;Agumon;; +23;DemiDevimon;PicoDevimon;; +24;BlackGabumon;Gabumon (Black);; +27;Dorumon;DORUmon;; +28;Veemon;V-mon;; +29;SnowAgumon;YukiAgumon;; +30;BlackAgumon;Agumon (Black);; +36;Biyomon;Piyomon;; +45;BlackGatomon;BlackTailmon;; +53;Growlmon;Growmon;; +55;Growlmon (Orange);Growmon (Orange);; +56;Gatomon;Tailmon;; +58;BlackGrowlmon;BlackGrowmon;; +61;BlackGarurumon;Garurumon (Black);; +67;Birdramon;Birdramon;; +68;Sukamon;Scumon;; +69;Vegiemon;Vegimon;; +81;Myotismon;Vamdemon;; +83;MagnaAngemon;HolyAngemon;; +88;B-WarGrowlmon;MegaloGrowmon (Black);; +92;B-WereGarurumon;WereGarurumon (Black);; +95;WarGrowlmon (Orange);MegaloGrowmon (Orange);; +99;MegaKabuterimon;AtlurKabuterimon;; +102;MarineAngemon;MarinAngemon;; +105;Beelzemon;Beelzebumon;; +108;Daemon;Demon;; +121;Gallantmon;Dukemon;; +123;ChaosGallantmon;ChaosDukemon;; +131;ZeedGarurumon;Z'dGarurumon;; +138;HerculesKabuterimon;HerakleKabuterimon;; +139;Phoenixmon;Hououmon;; +167;Gallantmon X;Dukemon X;; +168;Lillymon;Lilimon;; +170;Salamon;Plotmon;; +171;Salamon X;Plotmon X;; +172;Tyrannomon;Tyranomon;; +173;MetalTyrannomon;MetalTyranomon;; +174;ExVeemon;XV-mon;; +175;Dexmon;Death-X-mon;; +179;Frigimon;Yukidarumon;; +181;Centarumon;Centalmon;; +185;ShogunGekomon;TonosamaGekomon;; +186;Wizardmon;Wizarmon;; +187;Deramon;Delumon;; +188;Cherrymon;Jyureimon;; +189;Garbagemon;Gerbemon;; +192;RustTyrannomon;RustTyranomon;; +194;Machinedramon;Mugendramon;; +196;Motimon;Mochimon;; +202;Ogremon;Orgemon;; +204;Dorugamon;DORUgamon;; +205;Veedramon;V-dramon;; +208;AeroVeedramon;AeroV-dramon;; +211;GrapLeomon;GrappuLeomon;; +214;SkullMeramon;DeathMeramon;; +215;DoruGreymon;DORUguremon;; +217;IceLeomon;Panjyamon;; +218;Piximon;Piccolomon;; +223;MasterTyrannomon;MasterTyranomon;; +225;UlforceVeedramon;UlforceV-dramon;; +226;UlforceVeedramon X;UlforceV-dramon X;; +229;Ophanimon;Ofanimon;; +231;GrandKuwagamon;GranKuwagamon;; +234;Hi-Andromon;HiAndromon;; +235;Piedmon;Piemon;; +236;Puppetmon;Pinochimon;; +238;Beelzemon X;Beelzebumon X;; +245;Tsunomon;Tunomon;; \ No newline at end of file diff --git a/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/FinisherNames.csv b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/FinisherNames.csv new file mode 100644 index 0000000..5e92d94 --- /dev/null +++ b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/FinisherNames.csv @@ -0,0 +1,96 @@ +index;original;replace;excludeTerms;excludePaths +1;Cog Crusher;Darkness Gear;; +2;Flame Bomber;Bonfire;; +5;Pepper Breath;Baby Flame;; +6;Armored Arrow;Pointer Arrow;; +7;Horn Blaster;Holy Shot;; +9;Seed Blast;Nuts Shoot;; +10;Bada Boom;Night of Fire;; +11;Fireball;Fire Ball;; +12;Boom Bubble;Air Shot;; +13;Demi Darts;Pico Darts;; +14;Blue Blaster;Petit Fire;; +18;Vee Headbutt;V-mon Head;; +19;Frozen Wind;Little Blizzard;; +20;Pepper Breath;Baby Flame;; +21;Blue Blaster;Petit Fire;; +25;Super Shocker;Petit Thunder;; +26;Spiral Twister;Magical Fire;; +29;Howling Blaster;Fox Fire;; +30;Evil Charm;Death Charm;; +35;Lightning Paw;Neko Punch;; +37;Nova Blast;Mega Flame;; +40;Nume-Sludge;Poop Throw;; +43;Pyro Blaster;Exhaust Flame;; +44;Hand of Fate;Heaven's Knuckle;; +45;Pyro Blaster;Exhaust Flame;; +46;Lightning Paw;Neko Punch;; +47;Touch of Evil;Death Claw;; +48;Pyro Blaster;Exhaust Flame;; +49;Frozen Claw;Frost Claw;; +51;Howling Blaster;Fox Fire;; +56;Electro Shocker;Mega Blaster;; +58;Party Time;Poop Throw;; +59;Party Time;Poop Throw;; +60;Nova Blast;Mega Flame;; +62;Ultimate Sacrifice;Dead or Alive;; +64;Hearts Attack;Lovely Attack;; +71;Grisly Wing;Night Raid;; +72;Spiking Strike;Spiking Finish;; +73;Gate of Destiny;Heaven's Gate;; +75;Lightning Javelin;Thunder Javelin;; +79;Wolf Claw;Kaiser Nail;; +80;Celestial Arrow;Holy Arrow;; +82;Wolf Claw;Kaiser Nail;; +87;Dark Side Attack;Genocide Attack;; +88;Giga Blaster;Giga Destroyer;; +90;Wing Blade;Shadow Wing;; +91;Concert Crush;Love Serenade;; +92;Kahuna Waves;Ocean Love;; +93;Terra Force;Gaia Force;; +102;Lion Slash;Shishiraouzan;; +104;Excrement;Platinum Excrement;; +106;Supreme Cannon;Garuru Cannon;; +111;Lightning Joust;Royal Saber;; +112;Metal Wolf Claw;Cocytus Breath;; +113;Demon's Disaster;Demons Disaster;; +114;Terra Destroyer;Dark Gaia Force;; +115;Metal Wolf Claw;Cocytus Breath;; +121;Full Metal Breath;Full Metal Blaze;; +131;Strike of the Seven Stars;Seven Heavens;; +132;Giga Blaster;Giga Destroyer;; +139;Pepper Breath;Baby Flame;; +141;Thunder Blast;Spiral Sword;; +143;Harpoon Torpedo;Harpoon Vulcan;; +144;Vulcan's Hammer;Hammer Spark;; +146;Ice Blast;Ice Arrow;; +148;Needle Spray;Prickly Bang Bang;; +150;Hearts Attack;Lovely Attack;; +183;Pepper Breath;Baby Flame;; +184;Infinity Cannon;Mugen Cannon;; +187;Diamond Storm;Koyōsetsu;; +188;Sticky Net;Nebaneba Net;; +191;Dragon Wheel;Koenryū;; +193;V-Nova Blast;V-Breath Arrow;; +195;Crash Symphony;Crush Symphony;; +197;Double Scissor Claw;Scissor Arms Ω;; +199;Cyclone Turbine;Senpū Turbine Geri;; +200;Dark Shot;Ground Zero;; +201;Talisman of Light;Bonhitsusen;; +202;Metal Fireball;Heavy Metal Fire;; +203;Galactic Flare;Cosmo Flash;; +205;Frozen Fury;Hyoujūken;; +206;Pit Bomb;Bit Bomb;; +207;Abduction Beam;Abduction Kousen;; +208;Smirk Bomb;Big Smiley Bomber;; +209;Metal Smirk Bomb;Energy Bomb;; +210;Mjoelnir Thunder;Mjölnir Thunder;; +212;Ultimate Ouryuken;Kyūkyoku Senjin Ouryūken;; +213;Ray of Victory;Shining V Force;; +214;Ray of Victory;Shining V Force;; +215;Giga Crusher;Giga Death;; +218;Hyper Infinity Cannon;Hyper Mugen Cannon;; +221;Amethyst Mandala;Kongoukai Mandara;; +224;Puppet Pummel;Bullet Hammer;; +230;River of Power;Ultimate Stream;; +233;Soul Core Attack;Konpaku Shingeki;; \ No newline at end of file diff --git a/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/GlossaryNames.csv b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/GlossaryNames.csv new file mode 100644 index 0000000..63d590c --- /dev/null +++ b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/GlossaryNames.csv @@ -0,0 +1,2 @@ +index;original;replace;excludeTerms;excludePaths +87;Machinedramon;Mugendramon;; \ No newline at end of file diff --git a/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/ItemNames.csv b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/ItemNames.csv new file mode 100644 index 0000000..9746fe4 --- /dev/null +++ b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/ItemNames.csv @@ -0,0 +1,4 @@ +index;original;replace;excludeTerms;excludePaths +344;Emperial Dragon's Old Cannon;Imperial Dragon's Old Cannon;; +372;Chip of Sincerity;Chip of Purity;; +373;Chip of Reliability;Chip of Sincerity;; diff --git a/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/KeyItemNames.csv b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/KeyItemNames.csv new file mode 100644 index 0000000..29559ca --- /dev/null +++ b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/KeyItemNames.csv @@ -0,0 +1,4 @@ +index;original;replace;excludeTerms;excludePaths +61;Crest of Reliability;Crest of Sincerity;; +62;Crest of Sincerity;Crest of Purity;; +65;Golden Digi-Egg;Golden Digimental;; \ No newline at end of file diff --git a/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/MedalNames.csv b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/MedalNames.csv new file mode 100644 index 0000000..6f2d82c --- /dev/null +++ b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/MedalNames.csv @@ -0,0 +1,2 @@ +index;original;replace;excludeTerms;excludePaths +63;Tyranno-Mania;Tyrano-Mania;; \ No newline at end of file diff --git a/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/_general.csv b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/_general.csv new file mode 100644 index 0000000..747108c --- /dev/null +++ b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/_general.csv @@ -0,0 +1,15 @@ +index;original;replace;excludeTerms;excludePaths +0;Fresh;Baby I;$ly;*\LanguageKeep_jp.res\14:4227 +0;Champion;Adult;Digimon $,Colosseum $,Tenkaichi $,You're the $,Limit $s; +0;Ultimate;Perfect;$ Piece,$ X Antibody,$Brachiomon,$Brachimon,$ Stream,$ body,$ victory,$ Sacrifice,$ Ouryuken,$ Poop Hell,$ Weapon,$ Herbal,$ Slicer,$ Enemy,$ Thunder,$ Blast,$ Quake,$ly;*\LanguageKeep_jp.res\39:175 +0;Mega;Ultimate;$ Meat,$ Blaster,$seadramon,$dramon,$Seadramon,$ Burst,$battle,$Kabuterimon,$Gargomon,$ Electro,Ancient$,$lo,$ton,$ Barrage;*\LanguageKeep_jp.res\31:73,*\LanguageKeep_jp.res\35:188,*\LanguageKeep_jp.res\36:188 +0;Rookie;Child Digimon;;!*\LanguageKeep_jp.res\12:198,!*\LanguageKeep_jp.res\42:224 +0;Rookie;Child;$ Collector;*\mgm01_text.pack\55:600,*\mgm01_text.pack\55:700,*\LanguageKeep_jp.res\15:812 +0;Rookies;Child Digimon;; +0;Champions;Adult Digimon;; +0;DigiArmor Energize;Digimental Up;; +0;Digi-Egg of;Digimental of;; +0;Digivol;Evol;; +0;digivol;evol;; +0;DNA Digivol;Jogress Evol;; +0;Digimon Fusion;Digimon Xros Wars;; \ No newline at end of file diff --git a/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/_general_digimon.csv b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/_general_digimon.csv new file mode 100644 index 0000000..3031880 --- /dev/null +++ b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/_general_digimon.csv @@ -0,0 +1,4 @@ +index;original;replace;excludeTerms;excludePaths +0;VenomMyotismon;VenomVamdemon;; +0;Warumonzaemon;WaruMonzaemon;; +0;Megaseadramon;MegaSeadramon;; \ No newline at end of file diff --git a/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/keep-15.csv b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/keep-15.csv new file mode 100644 index 0000000..f2c2aba --- /dev/null +++ b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/keep-15.csv @@ -0,0 +1,20 @@ +index;original;replace;excludeTerms;excludePaths +12;Fresh;Baby I;; +13;In-Training;Baby II;; +14;Rookie;Child;; +15;Champion;Adult;; +16;Ultimate;Perfect;; +17;Mega;Ultimate;; +131;Displays Digivolutions your Partner Digimon went through and its Digivolution History.;Displays Evolutions your Partner Digimon went through and its Evolution History.;; +302;Digivolutions;Evolutions;; +5304;Digivolution Completion Rate;Evolution Completion Rate;; +5309;Total Bit gained from the sale of cards;Total Bits gained from the sale of cards;; +5407;Most digivolved Rookie;Most evolved Child;; +5408;Most digivolved Champion;Most evolved Adult;; +5409;Most digivolved Ultimate;Most evolved Perfect;; +5410;Most digivolved Mega;Most evolved Ultimate;; +5708;Number of Digivolutions;Number of Evolutions;; +6516;Digivolutions Completed;Evolutions Completed;; +7700;Digivolutions;Evolutions;; +7710;Look at the Digimon your Partner digivolved into during your Adventures.;Look at the Digimon your Partner evolved into during your Adventures.;; +7711;Check out the Digivolution history of your current Partner Digimon.;Check out the Evolution history of your current Partner Digimon.;; diff --git a/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/keep-39.csv b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/keep-39.csv new file mode 100644 index 0000000..39da81f --- /dev/null +++ b/src/main/resources/net/digimonworld/decode/textmod/renamingPresets/keep-39.csv @@ -0,0 +1,2 @@ +index;original;replace;excludeTerms;excludePaths +24;x;Even among Child Digimon, depending on how they're\ntrained, there can be a huge difference in strength!;;all diff --git a/src/main/resources/net/digimonworld/decode/textmod/settings/builtinRenamingPreset.csv b/src/main/resources/net/digimonworld/decode/textmod/settings/builtinRenamingPreset.csv new file mode 100644 index 0000000..e4b5f11 --- /dev/null +++ b/src/main/resources/net/digimonworld/decode/textmod/settings/builtinRenamingPreset.csv @@ -0,0 +1,15 @@ +renamingPresets/_general_digimon.csv +renamingPresets/_general.csv +renamingPresets/AccessoryNames.csv +renamingPresets/CardNames1.csv +renamingPresets/CardNames2.csv +renamingPresets/CardSetNames.csv +renamingPresets/CharacterNames.csv +renamingPresets/DigimonNames.csv +renamingPresets/FinisherNames.csv +renamingPresets/GlossaryNames.csv +renamingPresets/ItemNames.csv +renamingPresets/keep-15.csv +renamingPresets/keep-39.csv +renamingPresets/KeyItemNames.csv +renamingPresets/MedalNames.csv \ No newline at end of file