using System; using System.IO; using System.Linq; using System.Windows.Forms; using pkNX.Containers; using pkNX.Game; using pkNX.Randomization; using pkNX.Structures; using pkNX.Structures.FlatBuffers; using pkNX.Structures.FlatBuffers.LGPE; namespace pkNX.WinForms.Controls; internal class EditorGG : EditorBase { protected override GameManagerGG ROM { get; } private GameData Data => ROM.Data; protected internal EditorGG(GameManagerGG rom) => ROM = rom; public void EditCommon() { var text = ROM.GetFilteredFolder(GameFile.GameText, z => Path.GetExtension(z) == ".dat"); var config = new TextConfig(ROM.Game); var tc = new TextContainer(text, config); using var form = new TextEditor(tc, TextEditor.TextEditorMode.Common); form.ShowDialog(); if (!form.Modified) text.CancelEdits(); } public void EditScript() { var text = ROM.GetFilteredFolder(GameFile.StoryText, z => Path.GetExtension(z) == ".dat"); var config = new TextConfig(ROM.Game); var tc = new TextContainer(text, config); using var form = new TextEditor(tc, TextEditor.TextEditorMode.Script); form.ShowDialog(); if (!form.Modified) text.CancelEdits(); } public void EditTrainers() { var editor = new TrainerEditor { ReadClass = data => new TrainerClass7b(data), ReadPoke = data => new TrainerPoke7b(data), ReadTrainer = data => new TrainerData7b(data), ReadTeam = TrainerPoke7b.ReadTeam, WriteTeam = TrainerPoke7b.WriteTeam, TrainerData = ROM.GetFilteredFolder(GameFile.TrainerSpecData), TrainerPoke = ROM.GetFilteredFolder(GameFile.TrainerSpecPoke), TrainerClass = ROM.GetFilteredFolder(GameFile.TrainerSpecClass), }; editor.Initialize(); using var form = new BTTE(Data, editor, ROM); form.ShowDialog(); if (!form.Modified) editor.CancelEdits(); else editor.Save(); } public void EditPokémon() { var editor = new PokeEditor { Evolve = Data.EvolutionData, Learn = Data.LevelUpData, Mega = Data.MegaEvolutionData, Personal = Data.PersonalData, TMHM = Legal.TMHM_GG, }; using var form = new PokeDataUI(editor, ROM, Data); form.ShowDialog(); if (!form.Modified) editor.CancelEdits(); else editor.Save(); } public void EditItems() { var obj = ROM.GetFilteredFolder(GameFile.ItemStats, z => new FileInfo(z).Length == 36); var cache = new DataCache(obj) { Create = Item.FromBytes, Write = item => item.Write(), }; using var form = new GenericEditor(cache, ROM.GetStrings(TextName.ItemNames), "Item Editor"); form.ShowDialog(); if (!form.Modified) cache.CancelEdits(); else cache.Save(); } public void EditMoves() { var obj = ROM[GameFile.MoveStats]; // mini var cache = new DataCache(obj) { Create = data => new Move7(data), Write = move => move.Write(), }; using var form = new GenericEditor(cache, ROM.GetStrings(TextName.MoveNames), "Move Editor"); form.ShowDialog(); if (!form.Modified) { cache.CancelEdits(); return; } cache.Save(); Data.MoveData.ClearAll(); // force reload if used again } public void EditGift() { var file = ROM[GameFile.EncounterTableGift]; var data = file[0]; var objs = data.GetArray(z => new EncounterGift7b(z), EncounterGift7b.SIZE); // binary var names = Enumerable.Range(0, objs.Length).Select(z => $"{z:000}").ToArray(); var cache = new DirectCache(objs); void Randomize() { var spec = EditUtil.Settings.Species; spec.Gen2 = spec.Gen3 = spec.Gen4 = spec.Gen5 = spec.Gen6 = spec.Gen7 = false; var srand = new SpeciesRandomizer(ROM.Info, Data.PersonalData); var frand = new FormRandomizer(Data.PersonalData); srand.Initialize(spec); foreach (var t in objs) { t.Species = (Species)srand.GetRandomSpecies((int)t.Species); t.Form = frand.GetRandomForm((int)t.Species, spec.AllowRandomMegaForms, false, ROM.Info.Generation, Data.PersonalData.Table); t.Nature = Nature.Random25; t.Gender = FixedGender.Random; t.Shiny = Shiny.Random; t.RelearnMoves = [0, 0, 0, 0]; if (t.IV_HP != -4) t.IVs = [-1, -1, -1, -1, -1, -1]; } } using var form = new GenericEditor(cache, names, "Gift Editor", Randomize); form.ShowDialog(); if (!form.Modified) file.CancelEdits(); else file[0] = objs.SelectMany(z => z.Write()).ToArray(); } public void EditTrade() { var file = ROM[GameFile.EncounterTableTrade]; var data = file[0]; var objs = data.GetArray(z => new EncounterTrade7b(z), EncounterTrade7b.SIZE); // binary var names = Enumerable.Range(0, objs.Length).Select(z => $"{z:000}").ToArray(); var cache = new DirectCache(objs); void Randomize() { var spec = EditUtil.Settings.Species; spec.Gen2 = spec.Gen3 = spec.Gen4 = spec.Gen5 = spec.Gen6 = spec.Gen7 = false; var srand = new SpeciesRandomizer(ROM.Info, Data.PersonalData); var frand = new FormRandomizer(Data.PersonalData); srand.Initialize(spec, 808, 809); // can only catch 1-151 in wild foreach (var t in objs) { t.Species = (Species)srand.GetRandomSpecies((int)t.Species); t.RequiredSpecies = (Species)srand.GetRandomSpecies((int)t.Species); t.Form = frand.GetRandomForm((int)t.Species, spec.AllowRandomMegaForms, false, ROM.Info.Generation, Data.PersonalData.Table); t.RequiredForm = 0; // can't catch wild alolan forms t.Nature = Nature.Random - 1; t.Gender = FixedGender.Random; t.Shiny = Shiny.Random; t.RelearnMoves = [0, 0, 0, 0]; if (t.IV_HP != -4) t.IVs = [-1, -1, -1, -1, -1, -1]; } } using var form = new GenericEditor(cache, names, "Trade Editor", Randomize); form.ShowDialog(); if (!form.Modified) file.CancelEdits(); else file[0] = objs.SelectMany(z => z.Write()).ToArray(); } public void EditStatic() { var file = ROM[GameFile.EncounterTableStatic]; var data = file[0]; var objs = data.GetArray(z => new EncounterStatic7b(z), EncounterStatic7b.SIZE); // binary var names = Enumerable.Range(0, objs.Length).Select(z => $"{z:000}").ToArray(); var cache = new DirectCache(objs); void Randomize() { var spec = EditUtil.Settings.Species; spec.Gen2 = spec.Gen3 = spec.Gen4 = spec.Gen5 = spec.Gen6 = spec.Gen7 = false; var srand = new SpeciesRandomizer(ROM.Info, Data.PersonalData); var frand = new FormRandomizer(Data.PersonalData); srand.Initialize(spec); for (int i = 2; i < objs.Length; i++) // skip starters { var t = objs[i]; t.Species = (Species)srand.GetRandomSpecies((int)t.Species); t.Form = frand.GetRandomForm((int)t.Species, spec.AllowRandomMegaForms, false, ROM.Info.Generation, Data.PersonalData.Table); t.Nature = Nature.Random25; t.Gender = FixedGender.Random; t.Shiny = Shiny.Random; t.RelearnMoves = [0, 0, 0, 0]; if (t.IV_HP != -4) t.IVs = [-1, -1, -1, -1, -1, -1]; } } using var form = new GenericEditor(cache, names, "Static Encounter Editor", Randomize); form.ShowDialog(); if (!form.Modified) file.CancelEdits(); else file[0] = objs.SelectMany(z => z.Write()).ToArray(); } public void EditWild() => PopWildEdit(ROM.Game == GameVersion.GP ? GameFile.WildData1 : GameFile.WildData2); private void PopWildEdit(GameFile type) { var file = ROM.GetFile(type); var data = file[0]; var obj = FlatBufferConverter.DeserializeFrom(data); using var form = new GGWE(ROM, obj); if (form.ShowDialog() != DialogResult.OK) return; data = obj.SerializeFrom(); file[0] = data; } public void EditShinyRate() { var path = Path.Combine(ROM.PathExeFS, "main"); var data = FileMitm.ReadAllBytes(path); var nso = new NSO(data); var shiny = new ShinyRateGG(nso.DecompressedText); if (!shiny.IsEditable) { WinFormsUtil.Alert("Not able to find shiny rate logic in ExeFS."); return; } using var editor = new ShinyRate(shiny); editor.ShowDialog(); if (!editor.Modified) return; nso.DecompressedText = shiny.Data; FileMitm.WriteAllBytes(path, nso.Write()); } public void EditTM() { var path = Path.Combine(ROM.PathExeFS, "main"); var data = FileMitm.ReadAllBytes(path); var list = new TMEditorGG(data); if (!list.Valid) { WinFormsUtil.Alert("Not able to find tm data in ExeFS."); return; } var moves = list.GetMoves(); var allowed = Legal.GetAllowedMoves(ROM.Game, Data.MoveData.Length); var names = ROM.GetStrings(TextName.MoveNames); using var editor = new TMList(moves, allowed, names); editor.ShowDialog(); if (!editor.Modified) return; list.SetMoves(editor.FinalMoves); data = list.Write(); FileMitm.WriteAllBytes(path, data); } public void EditTypeChart() { var path = Path.Combine(ROM.PathExeFS, "main"); var data = FileMitm.ReadAllBytes(path); var nso = new NSO(data); byte[] pattern = // N2nn3pia9transport18UnreliableProtocolE [ 0x4E, 0x32, 0x6E, 0x6E, 0x33, 0x70, 0x69, 0x61, 0x39, 0x74, 0x72, 0x61, 0x6E, 0x73, 0x70, 0x6F, 0x72, 0x74, 0x31, 0x38, 0x55, 0x6E, 0x72, 0x65, 0x6C, 0x69, 0x61, 0x62, 0x6C, 0x65, 0x50, 0x72, 0x6F, 0x74, 0x6F, 0x63, 0x6F, 0x6C, 0x45, 0x00, ]; int ofs = CodePattern.IndexOfBytes(nso.DecompressedRO, pattern); if (ofs < 0) { WinFormsUtil.Alert("Not able to find type chart data in ExeFS."); return; } ofs += pattern.Length + 0x24; // 0x5B4C0C in lgpe 1.0 RO var cdata = new byte[18 * 18]; var types = ROM.GetStrings(TextName.TypeNames); Array.Copy(nso.DecompressedRO, ofs, cdata, 0, cdata.Length); var chart = new TypeChartEditor(cdata); using var editor = new TypeChart(chart, types); editor.ShowDialog(); if (!editor.Modified) return; chart.Data.CopyTo(nso.DecompressedRO, ofs); data = nso.Write(); FileMitm.WriteAllBytes(path, data); } public void EditShop1() => EditShop(false); public void EditShop2() => EditShop(true); private void EditShop(bool shop2) { var arc = ROM.GetFile(GameFile.Shops); var data = arc[0]; int[] PossibleHeldItems = Legal.GetRandomItemList(ROM.Game); var shop = FlatBufferConverter.DeserializeFrom(data); if (!shop2) { var table = shop.Single; var names = table.Select((z, _) => $"{(SingleShop.LGPE.TryGetValue(z.Hash, out var shopName) ? shopName : z.Hash.ToString("X"))}").ToArray(); var cache = new DirectCache(table); using var form = new GenericEditor(cache, names, $"{nameof(SingleShop)} Editor", Randomize); form.ShowDialog(); if (!form.Modified) { arc.CancelEdits(); return; } void Randomize() { for (int s = 1; s < table.Count; s++) // skip first table with TMs (unobtainable otherwise) { var shopDefinition = table[s]; var items = shopDefinition.Inventories.Items; for (int i = 0; i < items.Count; i++) items[i] = PossibleHeldItems[Randomization.Util.Random.Next(PossibleHeldItems.Length)]; } } } else { var table = shop.Multi; var names = table.Select((z, _) => $"{(MultiShop.LGPE.TryGetValue(z.Hash, out var shopName) ? shopName : z.Hash.ToString("X"))}").ToArray(); var cache = new DirectCache(table); using var form = new GenericEditor(cache, names, $"{nameof(MultiShop)} Editor", Randomize); form.ShowDialog(); if (!form.Modified) { arc.CancelEdits(); return; } void Randomize() { foreach (var shopDefinition in table) { foreach (var inv in shopDefinition.Inventories) { var items = inv.Items; for (int i = 0; i < items.Count; i++) items[i] = PossibleHeldItems[Randomization.Util.Random.Next(PossibleHeldItems.Length)]; } } } } arc[0] = shop.SerializeFrom(); } }