From e9f4017ce7018e177fd9b5881dbb87baa019b23b Mon Sep 17 00:00:00 2001 From: Nifyr Date: Sun, 29 Oct 2023 22:50:53 +0100 Subject: [PATCH] Added randomizer support for starters via external jsons patch --- DataParser.cs | 32 ++++++++++++++++- FileManager.cs | 35 +++++++++++++++++++ GlobalData.cs | 7 ++-- Randomizer.cs | 63 ++++++++++++++++++++-------------- Structs/ExternalJsonStructs.cs | 13 +++++++ 5 files changed, 121 insertions(+), 29 deletions(-) create mode 100644 Structs/ExternalJsonStructs.cs diff --git a/DataParser.cs b/DataParser.cs index b453a99..577b268 100644 --- a/DataParser.cs +++ b/DataParser.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using static ImpostersOrdeal.GlobalData; using static ImpostersOrdeal.GameDataTypes; +using static ImpostersOrdeal.ExternalJsonStructs; using static ImpostersOrdeal.Wwise; using AssetsTools.NET.Extra; using SmartPoint.AssetAssistant; @@ -56,7 +57,8 @@ public static void PrepareAnalysis() Task.Run(() => ParseMasterDatas()), Task.Run(() => ParsePersonalMasterDatas()), Task.Run(() => ParseUIMasterDatas()), - Task.Run(() => ParseContestMasterDatas()) + Task.Run(() => ParseContestMasterDatas()), + Task.Run(() => TryParseExternalStarters()) }; ParseDamagaCategories(); ParseGlobalMetadata(); @@ -68,6 +70,19 @@ public static void PrepareAnalysis() GC.Collect(); } + private static void TryParseExternalStarters() + { + List starters = new(); + for (int i = 0; i < 3; i++) + { + Starter starter = fileManager.TryGetExternalJson($"Encounters\\Starter\\starter_{i}.json"); + if (starter == null) + return; + starters.Add(starter); + } + gameData.starters = starters; + } + private static async Task ParseContestMasterDatas() { gameData.contestResultMotion = new(); @@ -1319,6 +1334,13 @@ private static async Task ParseMoves() AssetTypeValueField[] moveFields = monoBehaviour.children[4].children[0].children; AssetTypeValueField[] animationFields = animationData.children[8].children[0].children; AssetTypeValueField[] textFields = textData.children[8].children[0].children; + + if (animationFields.Length < moveFields.Length) + MainForm.ShowParserError("Oh my, this BattleDataTable is missing some stuff...\n" + + "I don't feel so good...\n" + + "WazaTable entries: " + moveFields.Length + "\n" + + "BattleDataTable entries: " + animationFields.Length + "??"); + for (int moveID = 0; moveID < moveFields.Length; moveID++) { Move move = new(); @@ -1955,6 +1977,14 @@ public static void CommitChanges() CommitContestMasterDatas(); if (gameData.IsModified(GameDataSet.DataField.DprBin)) CommitDprBin(); + if (gameData.IsModified(GameDataSet.DataField.ExternalStarters)) + CommitExternalStarters(); + } + + private static void CommitExternalStarters() + { + for (int i = 0; i < gameData.starters.Count; i++) + fileManager.CommitExternalJson($"Encounters\\Starter\\starter_{i}.json"); } private static void CommitContestMasterDatas() diff --git a/FileManager.cs b/FileManager.cs index 585ecce..51adb04 100644 --- a/FileManager.cs +++ b/FileManager.cs @@ -9,6 +9,7 @@ using SmartPoint.AssetAssistant; using System.Configuration; using System.Text; +using Newtonsoft.Json; namespace ImpostersOrdeal { @@ -44,10 +45,12 @@ public class FileManager private static readonly string delphisMainPath = "romfs\\Data\\StreamingAssets\\Audio\\GeneratedSoundBanks\\Switch\\Delphis_Main.bnk"; private static readonly string globalMetadataPath = "romfs\\Data\\Managed\\Metadata\\global-metadata.dat"; private static readonly string dprBinPath = "romfs\\Data\\StreamingAssets\\AssetAssistant\\Dpr.bin"; + private static readonly string externalJsonGamePath = "romfs\\Data\\ExtraData"; private string assetAssistantPath; private string audioPath; private string metadataPath; + private string externalJsonPath; private Dictionary fileArchive; private AssetsManager am = new(); private int fileIndex = 0; @@ -108,6 +111,7 @@ public bool InitializeFromInput() } audioPath = Directory.GetParent(assetAssistantPath).FullName + "\\Audio\\GeneratedSoundBanks\\Switch"; metadataPath = GetDataPath(fbd.SelectedPath) + "\\Managed\\Metadata"; + externalJsonPath = GetDataPath(fbd.SelectedPath) + "\\ExtraData"; //Setup fileArchive @@ -159,6 +163,7 @@ public bool InitializeFromConfig() return false; audioPath = Directory.GetParent(assetAssistantPath).FullName + "\\Audio\\GeneratedSoundBanks\\Switch"; metadataPath = GetDataPath(dumpPath) + "\\Managed\\Metadata"; + externalJsonPath = GetDataPath(dumpPath) + "\\ExtraData"; //Setup fileArchive @@ -564,6 +569,19 @@ public StringBuilder GetAudioSourceLog() return new(File.ReadAllText(fileArchive[logPath].fileLocation)); } + public T TryGetExternalJson(string externalJsonPath) + { + string gamePath = externalJsonGamePath + "\\" + externalJsonPath; + if (!fileArchive.ContainsKey(gamePath)) + return default; + return JsonConvert.DeserializeObject(File.ReadAllText(fileArchive[gamePath].fileLocation)); + } + + public void CommitExternalJson(string externalJsonPath) + { + fileArchive[externalJsonGamePath + "\\" + externalJsonPath].fileSource = FileSource.App; + } + public void DuplicateIconBundle(string srcPath, string dstPath) { FileData fd = new(); @@ -588,6 +606,8 @@ private static void ExportFile(FileData fd, string modRoot) if (fd.fileSource == FileSource.App) { + if (ExportExternalJson(fd, modRoot)) + return; byte[] buffer = null; switch (Path.GetFileName(fd.gamePath)) { @@ -630,6 +650,21 @@ private static void ExportFile(FileData fd, string modRoot) File.Delete(fd.fileLocation); } + private static bool ExportExternalJson(FileData fd, string modRoot) + { + if (!fd.gamePath.StartsWith(externalJsonGamePath)) return false; + if (!fd.gamePath.EndsWith(".json")) return false; + string externalJsonPath = fd.gamePath[(externalJsonGamePath.Length + 1)..]; + if (externalJsonPath.StartsWith("Encounters\\Starter")) + { + string fileName = Path.GetFileNameWithoutExtension(externalJsonPath); + int starterIndex = int.Parse(fileName.Split('_')[1]); + File.WriteAllText(modRoot + "\\" + fd.gamePath, JsonConvert.SerializeObject(gameData.starters[starterIndex], Formatting.Indented)); + return true; + } + return false; + } + public void DeleteTemporaryFiles() { foreach (FileData fd in fileArchive.Values) diff --git a/GlobalData.cs b/GlobalData.cs index c1ec10d..693401f 100644 --- a/GlobalData.cs +++ b/GlobalData.cs @@ -3,8 +3,8 @@ using System.Data; using System.Linq; using System.Text; -using System.Threading.Tasks; using static ImpostersOrdeal.GameDataTypes; +using static ImpostersOrdeal.ExternalJsonStructs; using SmartPoint.AssetAssistant; namespace ImpostersOrdeal @@ -57,6 +57,8 @@ public class GameDataSet public List contestResultMotion; public AssetBundleDownloadManifest dprBin; + public List starters; + public Dictionary trainerNames; public StringBuilder audioSourceLog; @@ -95,7 +97,8 @@ public enum DataField MotionTimingData, PokemonInfo, ContestResultMotion, - DprBin + DprBin, + ExternalStarters } public bool IsModified(DataField d) diff --git a/Randomizer.cs b/Randomizer.cs index 0bd4d6c..faef17c 100644 --- a/Randomizer.cs +++ b/Randomizer.cs @@ -4,6 +4,7 @@ using System.Text; using System.Threading.Tasks; using static ImpostersOrdeal.Distributions; +using static ImpostersOrdeal.ExternalJsonStructs; using static ImpostersOrdeal.GameDataTypes; using static ImpostersOrdeal.GlobalData; @@ -28,8 +29,6 @@ public Randomizer(MainForm m) /// public void Randomize() { - //FixTPEVIVs(); - if (m.checkBox57.Checked) ScaleEvolutionLevels((double)m.numericUpDown8.Value); if (m.checkBox58.Checked) @@ -125,30 +124,6 @@ public void Randomize() RandomizeMusic(); } - // Fix in case an older version of Imposter's Ordeal broke someone's iv and ev spreads. - private static void FixTPEVIVs() - { - foreach (Trainer t in gameData.trainers) - { - foreach (TrainerPokemon tp in t.trainerPokemon) - { - byte spAtkIV = tp.spDefIV; - byte spDefIV = tp.spdIV; - byte spdIV = tp.spAtkIV; - byte spAtkEV = tp.spDefEV; - byte spDefEV = tp.spdEV; - byte spdEV = tp.spAtkEV; - - tp.spAtkIV = spAtkIV; - tp.spDefIV = spDefIV; - tp.spdIV = spdIV; - tp.spAtkEV = spAtkEV; - tp.spDefEV = spDefEV; - tp.spdEV = spdEV; - } - } - } - private void RandomizeTypeMatchups(IDistribution distribution) { int typeCount = 18; @@ -657,6 +632,7 @@ private void RandomizeWildEncounters(bool randomizeSpecies, IDistribution specie bool ugVersionsUnbounded = gameData.UgVersionsUnbounded(); bool uint16UgTables = gameData.Uint16UgTables(); bool randomizeUgEncounterTableFormIDs = ugVersionsUnbounded || uint16UgTables; + List legendaryDexIDs = gameData.dexEntries.Where(d => d.forms[0].legendary).Select(d => d.dexID).ToList(); foreach (EncounterTableFile encounterTableFile in gameData.encounterTableFiles) { foreach (EncounterTable encounterTable in encounterTableFile.encounterTables) @@ -726,6 +702,41 @@ private void RandomizeWildEncounters(bool randomizeSpecies, IDistribution specie gameData.SetModified(GameDataSet.DataField.UgEncounterFiles); gameData.SetModified(GameDataSet.DataField.UgEncounterLevelSets); gameData.SetModified(GameDataSet.DataField.UgSpecialEncounters); + + if (gameData.starters != null) + { + foreach (Starter starter in gameData.starters) + { + if (randomizeLevels && IsWithin(AbsoluteBoundary.Level, starter.level)) + { + starter.level = Conform(AbsoluteBoundary.Level, levelDistribution.Next(starter.level)); + + if (evolveLogic) + { + Pokemon p = FindStage(gameData.GetPokemon(starter.monsNo, starter.formNo), starter.level, true); + starter.monsNo = p.dexID; + starter.formNo = p.formID; + } + } + + if (randomizeSpecies) + { + bool acceptLegendary = !legendLogic || P(starter.level); + Func resolveStage = evolveLogic ? p => FindStage(p, starter.level, true) : p => p; + + do + { + starter.monsNo = speciesDistribution.Next(starter.monsNo); + starter.formNo = rng.Next(gameData.dexEntries[starter.monsNo].forms.Count); + Pokemon p = resolveStage(gameData.GetPokemon(starter.monsNo, starter.formNo)); + starter.monsNo = p.dexID; + starter.formNo = p.formID; + } while (!gameData.GetPokemon(starter.monsNo, starter.formNo).IsValid() || + !acceptLegendary && legendaryDexIDs.Contains(starter.monsNo)); + } + } + gameData.SetModified(GameDataSet.DataField.ExternalStarters); + } } /// diff --git a/Structs/ExternalJsonStructs.cs b/Structs/ExternalJsonStructs.cs new file mode 100644 index 0000000..8a0753b --- /dev/null +++ b/Structs/ExternalJsonStructs.cs @@ -0,0 +1,13 @@ +namespace ImpostersOrdeal +{ + public static class ExternalJsonStructs + { + public class Starter + { + public int monsNo; + public int formNo; + public int level; + public int itemNo; + } + } +}