diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..f640b535 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,45 @@ +root = true + +# All Files +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true + +# Solution Files +[*.sln] +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true + +# XML Project Files +[*.csproj] +indent_style = space +indent_size = 2 + +# Code Files +[*.cs] +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 4 +tab_width = 4 +end_of_line = crlf +csharp_prefer_braces = when_multiline:warning +dotnet_diagnostic.IDE0047.severity = none +dotnet_diagnostic.IDE0048.severity = none +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:suggest +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:suggest +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:suggest +dotnet_style_parentheses_in_other_operators = always_for_clarity:suggest + +[*.{cs,vb}] +#### Naming styles #### + +# Naming styles + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.capitalization = pascal_case diff --git a/pkNX.WinForms/Controls/EncounterList.cs b/pkNX.WinForms/Controls/EncounterList.cs index 8fdf6c9a..581a2c5a 100644 --- a/pkNX.WinForms/Controls/EncounterList.cs +++ b/pkNX.WinForms/Controls/EncounterList.cs @@ -1,150 +1,152 @@ -using System; +using System; using System.Windows.Forms; using pkNX.Sprites; using pkNX.Structures.FlatBuffers; -namespace pkNX.WinForms +namespace pkNX.WinForms; + +public partial class EncounterList : UserControl { - public partial class EncounterList : UserControl + public EncounterList() { - public EncounterList() + InitializeComponent(); + } + + public bool OverworldSpawn + { + set => NUD_Count.Visible = L_Count.Visible = value; + } + + public bool ShowForm + { + set => dgv.Columns[FormColumn].Visible = value; + } + + private const string FormColumn = nameof(FormColumn); + + public void Initialize() + { + var dgvPicture = new DataGridViewImageColumn { - InitializeComponent(); - } - - public bool OverworldSpawn + HeaderText = "Sprite", + DisplayIndex = 0, + Width = SpriteUtil.Spriter.Width + 2, + DefaultCellStyle = { Alignment = DataGridViewContentAlignment.MiddleCenter }, + ReadOnly = true, + }; + var padding = SpriteUtil.Spriter.Height > 40 + ? new Padding(0, (SpriteUtil.Spriter.Height / 2) - 8, 0, 0) + : new Padding(0); + var dgvSpecies = new DataGridViewComboBoxColumn { - set => NUD_Count.Visible = L_Count.Visible = value; - } - - public bool ShowForm + HeaderText = "Species", + DisplayIndex = 1, + Width = 135, + DefaultCellStyle = { Alignment = DataGridViewContentAlignment.MiddleCenter, Padding = padding }, + FlatStyle = FlatStyle.Flat + }; + var dgvForm = new DataGridViewTextBoxColumn { - set => dgv.Columns[FormColumn].Visible = value; - } - - private const string FormColumn = nameof(FormColumn); - - public void Initialize() + Name = FormColumn, + HeaderText = "Form", + DisplayIndex = 2, + Width = 45, + DefaultCellStyle = { Alignment = DataGridViewContentAlignment.MiddleCenter } + }; + var dgvPercent = new DataGridViewTextBoxColumn { - var dgvPicture = new DataGridViewImageColumn - { - HeaderText = "Sprite", - DisplayIndex = 0, - Width = SpriteUtil.Spriter.Width + 2, - DefaultCellStyle = { Alignment = DataGridViewContentAlignment.MiddleCenter }, - ReadOnly = true, - }; - var padding = SpriteUtil.Spriter.Height > 40 - ? new Padding(0, (SpriteUtil.Spriter.Height / 2) - 8, 0, 0) - : new Padding(0); - var dgvSpecies = new DataGridViewComboBoxColumn - { - HeaderText = "Species", - DisplayIndex = 1, - Width = 135, - DefaultCellStyle = { Alignment = DataGridViewContentAlignment.MiddleCenter, Padding = padding }, - FlatStyle = FlatStyle.Flat - }; - var dgvForm = new DataGridViewTextBoxColumn - { - Name = FormColumn, - HeaderText = "Form", - DisplayIndex = 2, - Width = 45, - DefaultCellStyle = { Alignment = DataGridViewContentAlignment.MiddleCenter } - }; - var dgvPercent = new DataGridViewTextBoxColumn - { - HeaderText = "Chance", - DisplayIndex = 3, - Width = 52, - DefaultCellStyle = { Alignment = DataGridViewContentAlignment.MiddleCenter } - }; + HeaderText = "Chance", + DisplayIndex = 3, + Width = 52, + DefaultCellStyle = { Alignment = DataGridViewContentAlignment.MiddleCenter } + }; - dgvSpecies.Items.AddRange(species); + dgvSpecies.Items.AddRange(SpeciesNames); - dgv.Columns.Add(dgvPicture); - dgv.Columns.Add(dgvSpecies); - dgv.Columns.Add(dgvForm); - dgv.Columns.Add(dgvPercent); + dgv.Columns.Add(dgvPicture); + dgv.Columns.Add(dgvSpecies); + dgv.Columns.Add(dgvForm); + dgv.Columns.Add(dgvPercent); - dgv.CellValueChanged += (s, e) => - { - if (e.ColumnIndex == 0) - return; - UpdateRowImage(e.RowIndex); - }; - dgv.Columns[0].DefaultCellStyle.SelectionBackColor = dgv.DefaultCellStyle.BackColor; - } - - private void UpdateRowImage(int row) + dgv.CellValueChanged += (s, e) => { - int sp = Array.IndexOf(species, dgv.Rows[row].Cells[1].Value); - string formstr = (dgv.Rows[row].Cells[2].Value ?? 0).ToString(); - if (!int.TryParse(formstr, out var form) || (uint) form > 100) - dgv.Rows[row].Cells[2].Value = 0; - if (!int.TryParse(dgv.Rows[row].Cells[2].Value?.ToString(), out var rate) || (uint)rate > 100) - dgv.Rows[row].Cells[3].Value = 0; - - dgv.Rows[row].Cells[0].Value = SpriteUtil.GetSprite(sp, form, 0, 0, false, false, false); - } - - private EncounterSlot7b[]? Slots; - public static string[] species = Array.Empty(); - - public void LoadSlots(EncounterSlot7b[] slots) - { - Slots = slots; - - dgv.Rows.Clear(); - dgv.Rows.Add(slots.Length); - // Fill Entries - for (int i = 0; i < slots.Length; i++) - { - var row = dgv.Rows[i]; - row.Cells[1].Value = species[slots[i].Species]; - row.Cells[2].Value = slots[i].Form; - row.Cells[3].Value = slots[i].Probability; - row.Height = SpriteUtil.Spriter.Height + 2; - } - - dgv.CancelEdit(); - } - - public void SaveCurrent() - { - if (Slots == null) + if (e.ColumnIndex == 0) return; - for (int i = 0; i < Slots.Length; i++) - { - SaveRow(i, Slots[i]); - } + UpdateRowImage(e.RowIndex); + }; + dgv.Columns[0].DefaultCellStyle.SelectionBackColor = dgv.DefaultCellStyle.BackColor; + } + + private void UpdateRowImage(int row) + { + var r = dgv.Rows[row]; + var cells = r.Cells; + int sp = Array.IndexOf(SpeciesNames, cells[1].Value); + var formstr = cells[2].Value?.ToString() ?? "0"; + if (!int.TryParse(formstr, out var form) || (uint) form > 100) + cells[2].Value = 0; + if (!int.TryParse(cells[2].Value?.ToString(), out var rate) || (uint)rate > 100) + cells[3].Value = 0; + + cells[0].Value = SpriteUtil.GetSprite(sp, form, 0, 0, false, false, false); + } + + private EncounterSlot7b[]? Slots; + public static string[] SpeciesNames { private get; set; }= Array.Empty(); + + public void LoadSlots(EncounterSlot7b[] slots) + { + Slots = slots; + + dgv.Rows.Clear(); + dgv.Rows.Add(slots.Length); + // Fill Entries + for (int i = 0; i < slots.Length; i++) + { + var row = dgv.Rows[i]; + row.Cells[1].Value = SpeciesNames[slots[i].Species]; + row.Cells[2].Value = slots[i].Form; + row.Cells[3].Value = slots[i].Probability; + row.Height = SpriteUtil.Spriter.Height + 2; } - private void SaveRow(int row, EncounterSlot7b s) + dgv.CancelEdit(); + } + + public void SaveCurrent() + { + if (Slots == null) + return; + for (int i = 0; i < Slots.Length; i++) { - int sp = Array.IndexOf(species, dgv.Rows[row].Cells[1].Value ?? species[0]); - string formstr = (dgv.Rows[row].Cells[2].Value ?? 0).ToString(); - short.TryParse(formstr, out var form); - string probstr = (dgv.Rows[row].Cells[3].Value ?? 0).ToString(); - int.TryParse(probstr, out var prob); - - if (sp == 0) - { - s.Species = s.Probability = 0; - s.Form = 0; - return; - } - - s.Species = sp; - s.Form = form; - s.Probability = prob; - } - - private void CurrentCellDirtyStateChanged(object sender, EventArgs e) - { - if (dgv.IsCurrentCellDirty) - dgv.CommitEdit(DataGridViewDataErrorContexts.Commit); + SaveRow(i, Slots[i]); } } + + private void SaveRow(int row, EncounterSlot7b s) + { + var cells = dgv.Rows[row].Cells; + int sp = Array.IndexOf(SpeciesNames, cells[1].Value ?? SpeciesNames[0]); + string formstr = cells[2].Value?.ToString() ?? "0"; + _ = short.TryParse(formstr, out var form); + string probstr = cells[3].Value?.ToString() ?? "0"; + _ = int.TryParse(probstr, out var prob); + + if (sp == 0) + { + s.Species = s.Probability = 0; + s.Form = 0; + return; + } + + s.Species = sp; + s.Form = form; + s.Probability = prob; + } + + private void CurrentCellDirtyStateChanged(object sender, EventArgs e) + { + if (dgv.IsCurrentCellDirty) + dgv.CommitEdit(DataGridViewDataErrorContexts.Commit); + } } diff --git a/pkNX.WinForms/Controls/EncounterList8.cs b/pkNX.WinForms/Controls/EncounterList8.cs index b9dda144..cd66c8fc 100644 --- a/pkNX.WinForms/Controls/EncounterList8.cs +++ b/pkNX.WinForms/Controls/EncounterList8.cs @@ -1,139 +1,138 @@ -using System; +using System; using System.Windows.Forms; using pkNX.Sprites; using pkNX.Structures.FlatBuffers; -namespace pkNX.WinForms +namespace pkNX.WinForms; + +public partial class EncounterList8 : UserControl { - public partial class EncounterList8 : UserControl + private EncounterSlot8[]? Slots; + public static string[] SpeciesNames { private get; set; } = Array.Empty(); + private const string FormColumn = nameof(FormColumn); + + public EncounterList8() => InitializeComponent(); + + public void Initialize() { - public EncounterList8() + var dgvPicture = new DataGridViewImageColumn { - InitializeComponent(); - } - - private const string FormColumn = nameof(FormColumn); - - public void Initialize() + HeaderText = "Sprite", + DisplayIndex = 0, + Width = SpriteUtil.Spriter.Width + 2, + DefaultCellStyle = { Alignment = DataGridViewContentAlignment.MiddleCenter }, + ReadOnly = true, + }; + var padding = SpriteUtil.Spriter.Height > 40 + ? new Padding(0, (SpriteUtil.Spriter.Height / 2) - 8, 0, 0) + : new Padding(0); + var dgvSpecies = new DataGridViewComboBoxColumn { - var dgvPicture = new DataGridViewImageColumn - { - HeaderText = "Sprite", - DisplayIndex = 0, - Width = SpriteUtil.Spriter.Width + 2, - DefaultCellStyle = { Alignment = DataGridViewContentAlignment.MiddleCenter }, - ReadOnly = true, - }; - var padding = SpriteUtil.Spriter.Height > 40 - ? new Padding(0, (SpriteUtil.Spriter.Height / 2) - 8, 0, 0) - : new Padding(0); - var dgvSpecies = new DataGridViewComboBoxColumn - { - HeaderText = "Species", - DisplayIndex = 1, - Width = 135, - DefaultCellStyle = { Alignment = DataGridViewContentAlignment.MiddleCenter, Padding = padding}, - FlatStyle = FlatStyle.Flat - }; - var dgvForm = new DataGridViewTextBoxColumn - { - Name = FormColumn, - HeaderText = "Form", - DisplayIndex = 2, - Width = 45, - DefaultCellStyle = { Alignment = DataGridViewContentAlignment.MiddleCenter } - }; - var dgvPercent = new DataGridViewTextBoxColumn - { - HeaderText = "Chance", - DisplayIndex = 3, - Width = 52, - DefaultCellStyle = { Alignment = DataGridViewContentAlignment.MiddleCenter } - }; - - dgvSpecies.Items.AddRange(species); - - dgv.Columns.Add(dgvPicture); - dgv.Columns.Add(dgvSpecies); - dgv.Columns.Add(dgvForm); - dgv.Columns.Add(dgvPercent); - - dgv.CellValueChanged += (s, e) => - { - if (e.ColumnIndex == 0) - return; - UpdateRowImage(e.RowIndex); - }; - dgv.Columns[0].DefaultCellStyle.SelectionBackColor = dgv.DefaultCellStyle.BackColor; - } - - private void UpdateRowImage(int row) + HeaderText = "Species", + DisplayIndex = 1, + Width = 135, + DefaultCellStyle = { Alignment = DataGridViewContentAlignment.MiddleCenter, Padding = padding}, + FlatStyle = FlatStyle.Flat + }; + var dgvForm = new DataGridViewTextBoxColumn { - int sp = Array.IndexOf(species, dgv.Rows[row].Cells[1].Value); - string formstr = (dgv.Rows[row].Cells[2].Value ?? 0).ToString(); - if (!int.TryParse(formstr, out var form) || (uint) form > 100) - dgv.Rows[row].Cells[2].Value = 0; - if (!int.TryParse(dgv.Rows[row].Cells[2].Value?.ToString(), out var rate) || (uint)rate > 100) - dgv.Rows[row].Cells[3].Value = 0; - - dgv.Rows[row].Cells[0].Value = SpriteUtil.GetSprite(sp, form, 0, 0, false, false, false); - } - - private EncounterSlot8[]? Slots; - public static string[] species = Array.Empty(); - - public void LoadSlots(EncounterSlot8[] slots) + Name = FormColumn, + HeaderText = "Form", + DisplayIndex = 2, + Width = 45, + DefaultCellStyle = { Alignment = DataGridViewContentAlignment.MiddleCenter } + }; + var dgvPercent = new DataGridViewTextBoxColumn { - Slots = slots; + HeaderText = "Chance", + DisplayIndex = 3, + Width = 52, + DefaultCellStyle = { Alignment = DataGridViewContentAlignment.MiddleCenter } + }; - dgv.Rows.Clear(); - dgv.Rows.Add(slots.Length); - // Fill Entries - for (int i = 0; i < slots.Length; i++) - { - var row = dgv.Rows[i]; - row.Cells[1].Value = species[slots[i].Species]; - row.Cells[2].Value = slots[i].Form; - row.Cells[3].Value = slots[i].Probability; - row.Height = SpriteUtil.Spriter.Height + 2; - } + dgvSpecies.Items.AddRange(SpeciesNames); - dgv.CancelEdit(); - } + dgv.Columns.Add(dgvPicture); + dgv.Columns.Add(dgvSpecies); + dgv.Columns.Add(dgvForm); + dgv.Columns.Add(dgvPercent); - public void SaveCurrent() + dgv.CellValueChanged += (s, e) => { - if (Slots == null) + if (e.ColumnIndex == 0) return; - for (int i = 0; i < Slots.Length; i++) - { - SaveRow(i, Slots[i]); - } + UpdateRowImage(e.RowIndex); + }; + dgv.Columns[0].DefaultCellStyle.SelectionBackColor = dgv.DefaultCellStyle.BackColor; + } + + private void UpdateRowImage(int row) + { + var cells = dgv.Rows[row].Cells; + int sp = Array.IndexOf(SpeciesNames, cells[1].Value); + string formstr = cells[2].Value?.ToString() ?? "0"; + if (!int.TryParse(formstr, out var form) || (uint) form > 100) + cells[2].Value = 0; + if (!int.TryParse(dgv.Rows[row].Cells[2].Value?.ToString(), out var rate) || (uint)rate > 100) + cells[3].Value = 0; + + cells[0].Value = SpriteUtil.GetSprite(sp, form, 0, 0, false, false, false); + } + + public void LoadSlots(EncounterSlot8[] slots) + { + Slots = slots; + + dgv.Rows.Clear(); + dgv.Rows.Add(slots.Length); + // Fill Entries + for (int i = 0; i < slots.Length; i++) + { + var row = dgv.Rows[i]; + var cells = row.Cells; + cells[1].Value = SpeciesNames[slots[i].Species]; + cells[2].Value = slots[i].Form; + cells[3].Value = slots[i].Probability; + + row.Height = SpriteUtil.Spriter.Height + 2; } - private void SaveRow(int row, EncounterSlot8 s) + dgv.CancelEdit(); + } + + public void SaveCurrent() + { + if (Slots == null) + return; + for (int i = 0; i < Slots.Length; i++) { - int sp = Array.IndexOf(species, dgv.Rows[row].Cells[1].Value ?? species[0]); - string formstr = (dgv.Rows[row].Cells[2].Value ?? 0).ToString(); - byte.TryParse(formstr, out var form); - string probstr = (dgv.Rows[row].Cells[3].Value ?? 0).ToString(); - byte.TryParse(probstr, out var prob); - - if (sp == 0) - { - s.Species = s.Form = s.Probability = 0; - return; - } - - s.Species = sp; - s.Form = form; - s.Probability = prob; - } - - private void CurrentCellDirtyStateChanged(object sender, EventArgs e) - { - if (dgv.IsCurrentCellDirty) - dgv.CommitEdit(DataGridViewDataErrorContexts.Commit); + SaveRow(i, Slots[i]); } } + + private void SaveRow(int row, EncounterSlot8 s) + { + var cells = dgv.Rows[row].Cells; + int sp = Array.IndexOf(SpeciesNames, cells[1].Value ?? SpeciesNames[0]); + string formstr = cells[2].Value?.ToString() ?? "0"; + _ = byte.TryParse(formstr, out var form); + string probstr = cells[3].Value?.ToString() ?? "0"; + _ = byte.TryParse(probstr, out var prob); + + if (sp == 0) + { + s.Species = s.Form = s.Probability = 0; + return; + } + + s.Species = sp; + s.Form = form; + s.Probability = prob; + } + + private void CurrentCellDirtyStateChanged(object sender, EventArgs e) + { + if (dgv.IsCurrentCellDirty) + dgv.CommitEdit(DataGridViewDataErrorContexts.Commit); + } } diff --git a/pkNX.WinForms/Controls/EncounterTableEditor8a.cs b/pkNX.WinForms/Controls/EncounterTableEditor8a.cs index 22cf5b6f..5bbd1b1a 100644 --- a/pkNX.WinForms/Controls/EncounterTableEditor8a.cs +++ b/pkNX.WinForms/Controls/EncounterTableEditor8a.cs @@ -1,8 +1,6 @@ -using System; -using System.Diagnostics; +using System; using System.Linq; using System.Windows.Forms; -using pkNX.Structures; using pkNX.Structures.FlatBuffers; namespace pkNX.WinForms.Controls; @@ -70,7 +68,7 @@ private void B_NoShinyLocks_Click(object sender, EventArgs e) private void PG_Encounters_SelectedGridItemChanged(object sender, SelectedGridItemChangedEventArgs e) { - object obj = e.NewSelection.Value; + var obj = e.NewSelection.Value; bool enable = obj is EncounterSlot8a; B_CloneTableEntry.Enabled = enable; B_ConfigureAsAlpha.Enabled = enable; @@ -79,7 +77,7 @@ private void PG_Encounters_SelectedGridItemChanged(object sender, SelectedGridIt private void B_CloneTableEntry_Click(object sender, EventArgs e) { - object obj = PG_Encounters.SelectedGridItem.Value; + var obj = PG_Encounters.SelectedGridItem.Value; if (obj is EncounterSlot8a slotToClone) { var encounterTable = (EncounterTable8a)PG_Encounters.SelectedObject; @@ -90,7 +88,7 @@ private void B_CloneTableEntry_Click(object sender, EventArgs e) private void B_ConfigureAsAlpha_Click(object sender, EventArgs e) { - object obj = PG_Encounters.SelectedGridItem.Value; + var obj = PG_Encounters.SelectedGridItem.Value; if (obj is EncounterSlot8a slotToEdit) { slotToEdit.BaseProbability = 1; @@ -107,7 +105,7 @@ private void B_ConfigureAsAlpha_Click(object sender, EventArgs e) private void B_RemoveCondition_Click(object sender, EventArgs e) { - object obj = PG_Encounters.SelectedGridItem.Value; + var obj = PG_Encounters.SelectedGridItem.Value; if (obj is EncounterSlot8a slotToEdit) { slotToEdit.Eligibility.ConditionID = Condition8a.None; diff --git a/pkNX.WinForms/Controls/EvolutionRow.cs b/pkNX.WinForms/Controls/EvolutionRow.cs index 4fe5bfc5..fc445ccb 100644 --- a/pkNX.WinForms/Controls/EvolutionRow.cs +++ b/pkNX.WinForms/Controls/EvolutionRow.cs @@ -1,96 +1,95 @@ -using System; +using System; using System.Linq; using System.Windows.Forms; using pkNX.Sprites; using pkNX.Structures; -namespace pkNX.WinForms +namespace pkNX.WinForms; + +public partial class EvolutionRow : UserControl { - public partial class EvolutionRow : UserControl + public EvolutionRow() { - public EvolutionRow() + InitializeComponent(); + + CB_Method.Items.AddRange(EvoMethods); + CB_Species.Items.AddRange(species); + + CB_Species.SelectedIndexChanged += (_, __) => ChangeSpecies(CB_Species.SelectedIndex, (int)NUD_Form.Value); + NUD_Form.ValueChanged += (_, __) => ChangeSpecies(CB_Species.SelectedIndex, (int)NUD_Form.Value); + + CB_Arg.Items.AddRange(None); + CB_Method.SelectedIndexChanged += (s, e) => { - InitializeComponent(); - - CB_Method.Items.AddRange(EvoMethods); - CB_Species.Items.AddRange(species); - - CB_Species.SelectedIndexChanged += (_, __) => ChangeSpecies(CB_Species.SelectedIndex, (int)NUD_Form.Value); - NUD_Form.ValueChanged += (_, __) => ChangeSpecies(CB_Species.SelectedIndex, (int)NUD_Form.Value); - - CB_Arg.Items.AddRange(None); - CB_Method.SelectedIndexChanged += (s, e) => - { - var index = (EvolutionType)CB_Method.SelectedIndex; - var type = index.GetArgType(); - L_Method.Visible = L_Species.Visible = L_Arg.Visible = L_Form.Visible = L_Level.Visible = index > 0; - L_Arg.Visible = CB_Arg.Visible = type >= EvolutionTypeArgumentType.Items; - if (type == oldMethod) - return; - - if (type < EvolutionTypeArgumentType.Items) - return; - - CB_Arg.Visible = true; - oldMethod = type; - CB_Arg.Items.Clear(); - var vals = GetArgs(type); - CB_Arg.Items.AddRange(vals); - CB_Arg.SelectedIndex = 0; - }; - } - - private void ChangeSpecies(int spec, int form) => PB_Preview.Image = SpriteUtil.GetSprite(spec, form, 0, 0, false, false, false); - - private EvolutionMethod? current; - private EvolutionTypeArgumentType oldMethod; - - public void LoadEvolution(EvolutionMethod s) - { - var evo = current = s; - CB_Species.SelectedIndex = evo.Species; - NUD_Form.Value = evo.Form; - NUD_Level.Value = evo.Level; - CB_Method.SelectedIndex = (int)evo.Method; - CB_Arg.SelectedIndex = evo.Argument; - } - - public void SaveEvolution() - { - var evo = current; - if (evo == null) + var index = (EvolutionType)CB_Method.SelectedIndex; + var type = index.GetArgType(); + L_Method.Visible = L_Species.Visible = L_Arg.Visible = L_Form.Visible = L_Level.Visible = index > 0; + L_Arg.Visible = CB_Arg.Visible = type >= EvolutionTypeArgumentType.Items; + if (type == oldMethod) return; - evo.Species = (ushort)CB_Species.SelectedIndex; - evo.Form = (byte)NUD_Form.Value; - evo.Level = (byte)NUD_Level.Value; - evo.Method = (EvolutionType)CB_Method.SelectedIndex; - evo.Argument = (ushort)CB_Arg.SelectedIndex; - } - public static string[] items = Array.Empty(); - public static string[] movelist = Array.Empty(); - public static string[] species = Array.Empty(); - public static string[] types = Array.Empty(); + if (type < EvolutionTypeArgumentType.Items) + return; - private static readonly string[] EvoMethods = Enum.GetNames(typeof(EvolutionType)); - private static readonly string[] Levels = Enumerable.Range(0, 100 + 1).Select(z => z.ToString()).ToArray(); - private static readonly string[] Stats = Enumerable.Range(0, 255 + 1).Select(z => z.ToString()).ToArray(); - private static readonly string[] None = { "" }; + CB_Arg.Visible = true; + oldMethod = type; + CB_Arg.Items.Clear(); + var vals = GetArgs(type); + CB_Arg.Items.AddRange(vals); + CB_Arg.SelectedIndex = 0; + }; + } - private static string[] GetArgs(EvolutionTypeArgumentType type) + private void ChangeSpecies(int spec, int form) => PB_Preview.Image = SpriteUtil.GetSprite(spec, form, 0, 0, false, false, false); + + private EvolutionMethod? current; + private EvolutionTypeArgumentType oldMethod; + + public void LoadEvolution(EvolutionMethod s) + { + var evo = current = s; + CB_Species.SelectedIndex = evo.Species; + NUD_Form.Value = evo.Form; + NUD_Level.Value = evo.Level; + CB_Method.SelectedIndex = (int)evo.Method; + CB_Arg.SelectedIndex = evo.Argument; + } + + public void SaveEvolution() + { + var evo = current; + if (evo == null) + return; + evo.Species = (ushort)CB_Species.SelectedIndex; + evo.Form = (byte)NUD_Form.Value; + evo.Level = (byte)NUD_Level.Value; + evo.Method = (EvolutionType)CB_Method.SelectedIndex; + evo.Argument = (ushort)CB_Arg.SelectedIndex; + } + + public static string[] items = Array.Empty(); + public static string[] movelist = Array.Empty(); + public static string[] species = Array.Empty(); + public static string[] types = Array.Empty(); + + private static readonly string[] EvoMethods = Enum.GetNames(typeof(EvolutionType)); + private static readonly string[] Levels = Enumerable.Range(0, 100 + 1).Select(z => z.ToString()).ToArray(); + private static readonly string[] Stats = Enumerable.Range(0, 255 + 1).Select(z => z.ToString()).ToArray(); + private static readonly string[] None = { "" }; + + private static string[] GetArgs(EvolutionTypeArgumentType type) + { + return type switch { - return type switch - { - EvolutionTypeArgumentType.NoArg => None, - EvolutionTypeArgumentType.Level => Levels, - EvolutionTypeArgumentType.Items => items, - EvolutionTypeArgumentType.Moves => movelist, - EvolutionTypeArgumentType.Species => species, - EvolutionTypeArgumentType.Stat => Stats, - EvolutionTypeArgumentType.Type => types, - EvolutionTypeArgumentType.Version => Stats, - _ => throw new ArgumentOutOfRangeException(nameof(type), type, null) - }; - } + EvolutionTypeArgumentType.NoArg => None, + EvolutionTypeArgumentType.Level => Levels, + EvolutionTypeArgumentType.Items => items, + EvolutionTypeArgumentType.Moves => movelist, + EvolutionTypeArgumentType.Species => species, + EvolutionTypeArgumentType.Stat => Stats, + EvolutionTypeArgumentType.Type => types, + EvolutionTypeArgumentType.Version => Stats, + _ => throw new ArgumentOutOfRangeException(nameof(type), type, null) + }; } } diff --git a/pkNX.WinForms/Controls/EvolutionRow8a.cs b/pkNX.WinForms/Controls/EvolutionRow8a.cs index 4460e175..715f0628 100644 --- a/pkNX.WinForms/Controls/EvolutionRow8a.cs +++ b/pkNX.WinForms/Controls/EvolutionRow8a.cs @@ -1,97 +1,96 @@ -using System; +using System; using System.Linq; using System.Windows.Forms; using pkNX.Sprites; using pkNX.Structures; using pkNX.Structures.FlatBuffers; -namespace pkNX.WinForms +namespace pkNX.WinForms; + +public partial class EvolutionRow8a : UserControl { - public partial class EvolutionRow8a : UserControl + public static string[] items = Array.Empty(); + public static string[] movelist = Array.Empty(); + public static string[] species = Array.Empty(); + public static string[] types = Array.Empty(); + + private static readonly string[] EvoMethods = Enum.GetNames(typeof(EvolutionType)); + private static readonly string[] Levels = Enumerable.Range(0, 100 + 1).Select(z => z.ToString()).ToArray(); + private static readonly string[] Stats = Enumerable.Range(0, 255 + 1).Select(z => z.ToString()).ToArray(); + private static readonly string[] None = { "" }; + + private EvolutionEntry8a? current; + private EvolutionTypeArgumentType oldMethod; + + public EvolutionRow8a() { - public static string[] items = Array.Empty(); - public static string[] movelist = Array.Empty(); - public static string[] species = Array.Empty(); - public static string[] types = Array.Empty(); + InitializeComponent(); - private static readonly string[] EvoMethods = Enum.GetNames(typeof(EvolutionType)); - private static readonly string[] Levels = Enumerable.Range(0, 100 + 1).Select(z => z.ToString()).ToArray(); - private static readonly string[] Stats = Enumerable.Range(0, 255 + 1).Select(z => z.ToString()).ToArray(); - private static readonly string[] None = { "" }; + CB_Method.Items.AddRange(EvoMethods); + CB_Species.Items.AddRange(species); - private EvolutionEntry8a? current; - private EvolutionTypeArgumentType oldMethod; + CB_Species.SelectedIndexChanged += (_, __) => ChangeSpecies(CB_Species.SelectedIndex, (int)NUD_Form.Value); + NUD_Form.ValueChanged += (_, __) => ChangeSpecies(CB_Species.SelectedIndex, (int)NUD_Form.Value); - public EvolutionRow8a() + CB_Arg.Items.AddRange(None); + CB_Method.SelectedIndexChanged += (s, e) => { - InitializeComponent(); - - CB_Method.Items.AddRange(EvoMethods); - CB_Species.Items.AddRange(species); - - CB_Species.SelectedIndexChanged += (_, __) => ChangeSpecies(CB_Species.SelectedIndex, (int)NUD_Form.Value); - NUD_Form.ValueChanged += (_, __) => ChangeSpecies(CB_Species.SelectedIndex, (int)NUD_Form.Value); - - CB_Arg.Items.AddRange(None); - CB_Method.SelectedIndexChanged += (s, e) => - { - var index = (EvolutionType)CB_Method.SelectedIndex; - var type = index.GetArgType(); - L_Method.Visible = L_Species.Visible = L_Arg.Visible = L_Form.Visible = L_Level.Visible = index > 0; - L_Arg.Visible = CB_Arg.Visible = type >= EvolutionTypeArgumentType.Items; - if (type == oldMethod) - return; - - if (type < EvolutionTypeArgumentType.Items) - return; - - CB_Arg.Visible = true; - oldMethod = type; - CB_Arg.Items.Clear(); - var vals = GetArgs(type); - CB_Arg.Items.AddRange(vals); - CB_Arg.SelectedIndex = 0; - }; - } - - private void ChangeSpecies(int spec, int form) => PB_Preview.Image = SpriteUtil.GetSprite(spec, form, 0, 0, false, false, false); - - public void LoadEvolution(EvolutionEntry8a s) - { - var evo = current = s; - CB_Species.SelectedIndex = evo.Species; - NUD_Form.Value = evo.Form; - NUD_Level.Value = evo.Level; - CB_Method.SelectedIndex = evo.Method; - CB_Arg.SelectedIndex = evo.Argument; - } - - public void SaveEvolution() - { - var evo = current; - if (evo == null) + var index = (EvolutionType)CB_Method.SelectedIndex; + var type = index.GetArgType(); + L_Method.Visible = L_Species.Visible = L_Arg.Visible = L_Form.Visible = L_Level.Visible = index > 0; + L_Arg.Visible = CB_Arg.Visible = type >= EvolutionTypeArgumentType.Items; + if (type == oldMethod) return; - evo.Species = (ushort)CB_Species.SelectedIndex; - evo.Form = (ushort)NUD_Form.Value; - evo.Level = (ushort)NUD_Level.Value; - evo.Method = (ushort)CB_Method.SelectedIndex; - evo.Argument = (ushort)CB_Arg.SelectedIndex; - } - private static string[] GetArgs(EvolutionTypeArgumentType type) + if (type < EvolutionTypeArgumentType.Items) + return; + + CB_Arg.Visible = true; + oldMethod = type; + CB_Arg.Items.Clear(); + var vals = GetArgs(type); + CB_Arg.Items.AddRange(vals); + CB_Arg.SelectedIndex = 0; + }; + } + + private void ChangeSpecies(int spec, int form) => PB_Preview.Image = SpriteUtil.GetSprite(spec, form, 0, 0, false, false, false); + + public void LoadEvolution(EvolutionEntry8a s) + { + var evo = current = s; + CB_Species.SelectedIndex = evo.Species; + NUD_Form.Value = evo.Form; + NUD_Level.Value = evo.Level; + CB_Method.SelectedIndex = evo.Method; + CB_Arg.SelectedIndex = evo.Argument; + } + + public void SaveEvolution() + { + var evo = current; + if (evo == null) + return; + evo.Species = (ushort)CB_Species.SelectedIndex; + evo.Form = (ushort)NUD_Form.Value; + evo.Level = (ushort)NUD_Level.Value; + evo.Method = (ushort)CB_Method.SelectedIndex; + evo.Argument = (ushort)CB_Arg.SelectedIndex; + } + + private static string[] GetArgs(EvolutionTypeArgumentType type) + { + return type switch { - return type switch - { - EvolutionTypeArgumentType.NoArg => None, - EvolutionTypeArgumentType.Level => Levels, - EvolutionTypeArgumentType.Items => items, - EvolutionTypeArgumentType.Moves => movelist, - EvolutionTypeArgumentType.Species => species, - EvolutionTypeArgumentType.Stat => Stats, - EvolutionTypeArgumentType.Type => types, - EvolutionTypeArgumentType.Version => Stats, - _ => throw new ArgumentOutOfRangeException(nameof(type), type, null) - }; - } + EvolutionTypeArgumentType.NoArg => None, + EvolutionTypeArgumentType.Level => Levels, + EvolutionTypeArgumentType.Items => items, + EvolutionTypeArgumentType.Moves => movelist, + EvolutionTypeArgumentType.Species => species, + EvolutionTypeArgumentType.Stat => Stats, + EvolutionTypeArgumentType.Type => types, + EvolutionTypeArgumentType.Version => Stats, + _ => throw new ArgumentOutOfRangeException(nameof(type), type, null) + }; } } diff --git a/pkNX.WinForms/Controls/MegaEvoEntry.cs b/pkNX.WinForms/Controls/MegaEvoEntry.cs index 72c11345..c0c2cf82 100644 --- a/pkNX.WinForms/Controls/MegaEvoEntry.cs +++ b/pkNX.WinForms/Controls/MegaEvoEntry.cs @@ -1,65 +1,64 @@ -using System; +using System; using System.Windows.Forms; using pkNX.Sprites; using pkNX.Structures; -namespace pkNX.WinForms +namespace pkNX.WinForms; + +public partial class MegaEvoEntry : UserControl { - public partial class MegaEvoEntry : UserControl + public static string[] items = Array.Empty(); + + private static readonly string[] EvoMethods = Enum.GetNames(typeof(MegaEvolutionMethod)); + + public MegaEvoEntry() { - public static string[] items = Array.Empty(); + InitializeComponent(); - private static readonly string[] EvoMethods = Enum.GetNames(typeof(MegaEvolutionMethod)); + CB_Method.Items.AddRange(EvoMethods); + CB_Arg.Items.AddRange(items); - public MegaEvoEntry() + NUD_Form.ValueChanged += (_, __) => ChangeSpecies((int)NUD_Form.Value); + CB_Method.SelectedIndexChanged += (s, e) => { - InitializeComponent(); - - CB_Method.Items.AddRange(EvoMethods); - CB_Arg.Items.AddRange(items); - - NUD_Form.ValueChanged += (_, __) => ChangeSpecies((int)NUD_Form.Value); - CB_Method.SelectedIndexChanged += (s, e) => - { - PB_Preview.Visible = PB_Base.Visible = L_Into.Visible = CB_Method.SelectedIndex > 0; - CB_Arg.Visible = CB_Method.SelectedIndex == (int)MegaEvolutionMethod.Item; - }; - } - - public int Species { private get; set; } - private MegaEvolutionSet? current; - - private void ChangeSpecies(int form) - { - PB_Base.Image = SpriteUtil.GetSprite(Species, 0, 0, 0, false, false, false, 7); - PB_Preview.Image = SpriteUtil.GetSprite(Species, form, 0, 0, false, false, false, 7); PB_Preview.Visible = PB_Base.Visible = L_Into.Visible = CB_Method.SelectedIndex > 0; - } + CB_Arg.Visible = CB_Method.SelectedIndex == (int)MegaEvolutionMethod.Item; + }; + } - public void LoadEvolution(MegaEvolutionSet s, int species) + public int Species { private get; set; } + private MegaEvolutionSet? current; + + private void ChangeSpecies(int form) + { + PB_Base.Image = SpriteUtil.GetSprite(Species, 0, 0, 0, false, false, false, 7); + PB_Preview.Image = SpriteUtil.GetSprite(Species, form, 0, 0, false, false, false, 7); + PB_Preview.Visible = PB_Base.Visible = L_Into.Visible = CB_Method.SelectedIndex > 0; + } + + public void LoadEvolution(MegaEvolutionSet s, int species) + { + Species = species; + current = s; + + CB_Method.SelectedIndex = s.Method; + NUD_Form.Value = s.ToForm; + } + + public void SaveEvolution() + { + if (current == null) + return; + + if (CB_Method.SelectedIndex <= 0) { - Species = species; - current = s; - - CB_Method.SelectedIndex = s.Method; - NUD_Form.Value = s.ToForm; - } - - public void SaveEvolution() - { - if (current == null) - return; - - if (CB_Method.SelectedIndex <= 0) - { - current.ToForm = 0; - current.Method = 0; - current.Argument = 0; - return; - } - current.Method = CB_Method.SelectedIndex; - current.Argument = CB_Arg.SelectedIndex; - current.ToForm = (int) NUD_Form.Value; + current.ToForm = 0; + current.Method = 0; + current.Argument = 0; + return; } + current.Method = CB_Method.SelectedIndex; + current.Argument = CB_Arg.SelectedIndex; + current.ToForm = (int) NUD_Form.Value; } } diff --git a/pkNX.WinForms/Controls/StatEditor.cs b/pkNX.WinForms/Controls/StatEditor.cs index 0e2e1c2d..7b31c504 100644 --- a/pkNX.WinForms/Controls/StatEditor.cs +++ b/pkNX.WinForms/Controls/StatEditor.cs @@ -1,171 +1,170 @@ -using System; +using System; using System.Drawing; using System.Linq; using System.Windows.Forms; using pkNX.Structures; using Util = pkNX.Randomization.Util; -namespace pkNX.WinForms.Controls +namespace pkNX.WinForms.Controls; + +public partial class StatEditor : UserControl { - public partial class StatEditor : UserControl + public StatEditor() { - public StatEditor() + InitializeComponent(); + tb_iv = new[] { TB_HPIV, TB_ATKIV, TB_DEFIV, TB_SPEIV, TB_SPAIV, TB_SPDIV }; + tb_ev = new[] { TB_HPEV, TB_ATKEV, TB_DEFEV, TB_SPEEV, TB_SPAEV, TB_SPDEV }; + tb_av = new[] { TB_HPAV, TB_ATKAV, TB_DEFAV, TB_SPEAV, TB_SPAAV, TB_SPDAV }; + labarray = new[] { Label_ATK, Label_DEF, Label_SPE, Label_SPA, Label_SPD }; + } + + public void Initialize(string[] types) + { + UpdatingFields = true; + foreach (var t in types.Skip(1)) + CB_HPType.Items.Add(t); + UpdatingFields = false; + } + + public IPersonalTable? Personal { private get; set; } + public bool UpdatingFields; + public StatPKM PKM { get; set; } = new TrainerPoke7b(); + + private readonly MaskedTextBox[] tb_iv; + private readonly MaskedTextBox[] tb_ev; + private readonly MaskedTextBox[] tb_av; + private readonly Label[] labarray; + + public void UpdateStats() + { + if (UpdatingFields) + return; + + UpdatingFields = true; + for (int i = 0; i < 6; i++) { - InitializeComponent(); - tb_iv = new[] { TB_HPIV, TB_ATKIV, TB_DEFIV, TB_SPEIV, TB_SPAIV, TB_SPDIV }; - tb_ev = new[] { TB_HPEV, TB_ATKEV, TB_DEFEV, TB_SPEEV, TB_SPAEV, TB_SPDEV }; - tb_av = new[] { TB_HPAV, TB_ATKAV, TB_DEFAV, TB_SPEAV, TB_SPAAV, TB_SPDAV }; - labarray = new[] { Label_ATK, Label_DEF, Label_SPE, Label_SPA, Label_SPD }; + if (Util.ToInt32(tb_iv[i].Text) > 31) + tb_iv[i].Text = "31"; + if (Util.ToInt32(tb_ev[i].Text) > 255) + tb_ev[i].Text = "255"; + if (Util.ToInt32(tb_av[i].Text) > 200) + tb_av[i].Text = "200"; } + UpdatingFields = false; - public void Initialize(string[] types) + var pt = Personal; + if (pt == null) + throw new NullReferenceException("Personal table hasn't been initialized."); + + var pi = pt.GetFormEntry((ushort)PKM.Species, (byte)PKM.Form); + var stats = PKM.GetStats(pi); + + Stat_HP.Text = stats[0].ToString(); + Stat_ATK.Text = stats[1].ToString(); + Stat_DEF.Text = stats[2].ToString(); + Stat_SPA.Text = stats[4].ToString(); + Stat_SPD.Text = stats[5].ToString(); + Stat_SPE.Text = stats[3].ToString(); + + TB_IVTotal.Text = tb_iv.Select(z => Util.ToInt32(z.Text)).Sum().ToString(); + TB_EVTotal.Text = tb_ev.Select(z => Util.ToInt32(z.Text)).Sum().ToString(); + if (PKM is IAwakened s) + TB_AVTotal.Text = s.AwakeningSum().ToString(); + + var showAV = PKM is IAwakened; + Label_AVs.Visible = TB_AVTotal.Visible = FLP_HPType.Visible = showAV; + foreach (var mtb in tb_av) + mtb.Visible = showAV; + Label_EVs.Visible = TB_EVTotal.Visible = FLP_Dynamax.Visible = !showAV; + foreach (var mtb in tb_ev) + mtb.Visible = !showAV; + + // Recolor the Stat Labels based on boosted stats. + RecolorStatLabels(); + UpdatingFields = true; + CB_HPType.SelectedIndex = PKM.HiddenPowerType; + UpdatingFields = false; + } + + private void RecolorStatLabels() + { + int incr = (PKM.Nature / 5); + int decr = (PKM.Nature % 5); + // Reset Label Colors + foreach (Label label in labarray) + label.ResetForeColor(); + + // Set Colored StatLabels only if Nature isn't Neutral + if (incr != decr) { - UpdatingFields = true; - foreach (var t in types.Skip(1)) - CB_HPType.Items.Add(t); - UpdatingFields = false; - } - - public IPersonalTable? Personal { private get; set; } - public bool UpdatingFields; - public StatPKM PKM { get; set; } = new TrainerPoke7b(); - - private readonly MaskedTextBox[] tb_iv; - private readonly MaskedTextBox[] tb_ev; - private readonly MaskedTextBox[] tb_av; - private readonly Label[] labarray; - - public void UpdateStats() - { - if (UpdatingFields) - return; - - UpdatingFields = true; - for (int i = 0; i < 6; i++) - { - if (Util.ToInt32(tb_iv[i].Text) > 31) - tb_iv[i].Text = "31"; - if (Util.ToInt32(tb_ev[i].Text) > 255) - tb_ev[i].Text = "255"; - if (Util.ToInt32(tb_av[i].Text) > 200) - tb_av[i].Text = "200"; - } - UpdatingFields = false; - - var pt = Personal; - if (pt == null) - throw new NullReferenceException("Personal table hasn't been initialized."); - - var pi = pt.GetFormEntry((ushort)PKM.Species, (byte)PKM.Form); - var stats = PKM.GetStats(pi); - - Stat_HP.Text = stats[0].ToString(); - Stat_ATK.Text = stats[1].ToString(); - Stat_DEF.Text = stats[2].ToString(); - Stat_SPA.Text = stats[4].ToString(); - Stat_SPD.Text = stats[5].ToString(); - Stat_SPE.Text = stats[3].ToString(); - - TB_IVTotal.Text = tb_iv.Select(z => Util.ToInt32(z.Text)).Sum().ToString(); - TB_EVTotal.Text = tb_ev.Select(z => Util.ToInt32(z.Text)).Sum().ToString(); - if (PKM is IAwakened s) - TB_AVTotal.Text = s.AwakeningSum().ToString(); - - var showAV = PKM is IAwakened; - Label_AVs.Visible = TB_AVTotal.Visible = FLP_HPType.Visible = showAV; - foreach (var mtb in tb_av) - mtb.Visible = showAV; - Label_EVs.Visible = TB_EVTotal.Visible = FLP_Dynamax.Visible = !showAV; - foreach (var mtb in tb_ev) - mtb.Visible = !showAV; - - // Recolor the Stat Labels based on boosted stats. - RecolorStatLabels(); - UpdatingFields = true; - CB_HPType.SelectedIndex = PKM.HiddenPowerType; - UpdatingFields = false; - } - - private void RecolorStatLabels() - { - int incr = (PKM.Nature / 5); - int decr = (PKM.Nature % 5); - // Reset Label Colors - foreach (Label label in labarray) - label.ResetForeColor(); - - // Set Colored StatLabels only if Nature isn't Neutral - if (incr != decr) - { - labarray[incr].ForeColor = Color.Red; - labarray[decr].ForeColor = Color.Blue; - } - } - - public void LoadStats(StatPKM pkm) - { - PKM = pkm; - - UpdatingFields = true; - for (int i = 0; i < 6; i++) - tb_iv[i].Text = pkm.GetIV(i).ToString("00"); - for (int i = 0; i < 6; i++) - tb_ev[i].Text = pkm.GetEV(i).ToString("00"); - if (PKM is IAwakened a) - { - for (int i = 0; i < 6; i++) - tb_av[i].Text = a.GetAV(i).ToString("00"); - } - CB_HPType.SelectedIndex = PKM.HiddenPowerType; - UpdatingFields = false; - UpdateStats(); - } - - private void UpdateIV(object sender, EventArgs e) - { - if (UpdatingFields || sender is not MaskedTextBox t) - return; - var index = Array.IndexOf(tb_iv, t); - if (index < 0) - return; - int value = Math.Min(31, Util.ToInt32(t.Text)); - PKM.SetIV(index, value); - UpdatingFields = true; - CB_HPType.SelectedIndex = PKM.HiddenPowerType; - UpdatingFields = false; - UpdateStats(); - } - - private void UpdateEV(object sender, EventArgs e) - { - if (UpdatingFields || sender is not MaskedTextBox t) - return; - var index = Array.IndexOf(tb_ev, t); - if (index < 0) - return; - int value = Math.Min(252, Util.ToInt32(t.Text)); - PKM.SetEV(index, value); - UpdateStats(); - } - - private void UpdateAV(object sender, EventArgs e) - { - if (UpdatingFields || sender is not MaskedTextBox t || PKM is not IAwakened a) - return; - var index = Array.IndexOf(tb_av, t); - if (index < 0) - return; - int value = Math.Min(200, Util.ToInt32(t.Text)); - a.SetAV(index, value); - UpdateStats(); - } - - private void ChangeHPType(object sender, EventArgs e) - { - if (UpdatingFields) - return; - PKM.SetHPIVs(CB_HPType.SelectedIndex); - UpdateStats(); + labarray[incr].ForeColor = Color.Red; + labarray[decr].ForeColor = Color.Blue; } } + + public void LoadStats(StatPKM pkm) + { + PKM = pkm; + + UpdatingFields = true; + for (int i = 0; i < 6; i++) + tb_iv[i].Text = pkm.GetIV(i).ToString("00"); + for (int i = 0; i < 6; i++) + tb_ev[i].Text = pkm.GetEV(i).ToString("00"); + if (PKM is IAwakened a) + { + for (int i = 0; i < 6; i++) + tb_av[i].Text = a.GetAV(i).ToString("00"); + } + CB_HPType.SelectedIndex = PKM.HiddenPowerType; + UpdatingFields = false; + UpdateStats(); + } + + private void UpdateIV(object sender, EventArgs e) + { + if (UpdatingFields || sender is not MaskedTextBox t) + return; + var index = Array.IndexOf(tb_iv, t); + if (index < 0) + return; + int value = Math.Min(31, Util.ToInt32(t.Text)); + PKM.SetIV(index, value); + UpdatingFields = true; + CB_HPType.SelectedIndex = PKM.HiddenPowerType; + UpdatingFields = false; + UpdateStats(); + } + + private void UpdateEV(object sender, EventArgs e) + { + if (UpdatingFields || sender is not MaskedTextBox t) + return; + var index = Array.IndexOf(tb_ev, t); + if (index < 0) + return; + int value = Math.Min(252, Util.ToInt32(t.Text)); + PKM.SetEV(index, value); + UpdateStats(); + } + + private void UpdateAV(object sender, EventArgs e) + { + if (UpdatingFields || sender is not MaskedTextBox t || PKM is not IAwakened a) + return; + var index = Array.IndexOf(tb_av, t); + if (index < 0) + return; + int value = Math.Min(200, Util.ToInt32(t.Text)); + a.SetAV(index, value); + UpdateStats(); + } + + private void ChangeHPType(object sender, EventArgs e) + { + if (UpdatingFields) + return; + PKM.SetHPIVs(CB_HPType.SelectedIndex); + UpdateStats(); + } } diff --git a/pkNX.WinForms/Dumping/DumperPLA.cs b/pkNX.WinForms/Dumping/DumperPLA.cs index 99e731d9..e41b3f38 100644 --- a/pkNX.WinForms/Dumping/DumperPLA.cs +++ b/pkNX.WinForms/Dumping/DumperPLA.cs @@ -1,145 +1,144 @@ -using System; +using System; using System.Diagnostics; using System.Windows.Forms; using pkNX.Game; -namespace pkNX.WinForms +namespace pkNX.WinForms; + +public partial class DumperPLA : Form { - public partial class DumperPLA : Form + private readonly GameDumperPLA Dumper; + + public DumperPLA(GameManagerPLA rom) { - private readonly GameDumperPLA Dumper; - - public DumperPLA(GameManagerPLA rom) - { - InitializeComponent(); - Dumper = new GameDumperPLA(rom); - } - - private void B_OpenFolder_Click(object sender, EventArgs e) => Process.Start("explorer.exe", Dumper.DumpFolder); - - #region Tab 1 - private void B_ParsePersonal_Click(object sender, EventArgs e) - { - Dumper.DumpPersonal(); - System.Media.SystemSounds.Asterisk.Play(); - } - private void B_ParsePKMDetails_Click(object sender, EventArgs e) - { - Dumper.DumpPokeInfo(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_Wild_Click(object sender, EventArgs e) - { - Dumper.DumpWilds(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_Static_Click(object sender, EventArgs e) - { - Dumper.DumpStatic(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_Gift_Click(object sender, EventArgs e) - { - Dumper.DumpGifts(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_PokeDrops_Click(object sender, EventArgs e) - { - Dumper.DumpDrops(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_ItemInfo_Click(object sender, EventArgs e) - { - Dumper.DumpItems(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_Moves_Click(object sender, EventArgs e) - { - Dumper.DumpMoves(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_Placement_Click(object sender, EventArgs e) - { - Dumper.DumpPlacement(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_Resident_Click(object sender, EventArgs e) - { - Dumper.DumpResident(); - System.Media.SystemSounds.Asterisk.Play(); - } - #endregion - - #region Tab 2 - private void B_PKText_Click(object sender, EventArgs e) - { - Dumper.DumpStrings(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_PKLearn_Click(object sender, EventArgs e) - { - Dumper.DumpLearnsetBinary(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_PKEvo_Click(object sender, EventArgs e) - { - Dumper.DumpEvolutionBinary(); - System.Media.SystemSounds.Asterisk.Play(); - } - #endregion - - #region Tab 3 - private void B_GetOutbreak_Click(object sender, EventArgs e) - { - Dumper.DumpOutbreak(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_DumpScriptCommands(object sender, EventArgs e) - { - Dumper.DumpScriptID(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_EventTriggers_Click(object sender, EventArgs e) - { - Dumper.DumpEventTriggers(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_GetDex_Click(object sender, EventArgs e) - { - Dumper.DumpDex(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_MoveShop_Click(object sender, EventArgs e) - { - Dumper.DumpMoveShop(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_DumpHash_Click(object sender, EventArgs e) - { - Dumper.DumpAHTB(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_FlavorText_Click(object sender, EventArgs e) - { - Dumper.DumpFlavorText(); - System.Media.SystemSounds.Asterisk.Play(); - } - #endregion + InitializeComponent(); + Dumper = new GameDumperPLA(rom); } + + private void B_OpenFolder_Click(object sender, EventArgs e) => Process.Start("explorer.exe", Dumper.DumpFolder); + + #region Tab 1 + private void B_ParsePersonal_Click(object sender, EventArgs e) + { + Dumper.DumpPersonal(); + System.Media.SystemSounds.Asterisk.Play(); + } + private void B_ParsePKMDetails_Click(object sender, EventArgs e) + { + Dumper.DumpPokeInfo(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_Wild_Click(object sender, EventArgs e) + { + Dumper.DumpWilds(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_Static_Click(object sender, EventArgs e) + { + Dumper.DumpStatic(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_Gift_Click(object sender, EventArgs e) + { + Dumper.DumpGifts(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_PokeDrops_Click(object sender, EventArgs e) + { + Dumper.DumpDrops(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_ItemInfo_Click(object sender, EventArgs e) + { + Dumper.DumpItems(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_Moves_Click(object sender, EventArgs e) + { + Dumper.DumpMoves(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_Placement_Click(object sender, EventArgs e) + { + Dumper.DumpPlacement(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_Resident_Click(object sender, EventArgs e) + { + Dumper.DumpResident(); + System.Media.SystemSounds.Asterisk.Play(); + } + #endregion + + #region Tab 2 + private void B_PKText_Click(object sender, EventArgs e) + { + Dumper.DumpStrings(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_PKLearn_Click(object sender, EventArgs e) + { + Dumper.DumpLearnsetBinary(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_PKEvo_Click(object sender, EventArgs e) + { + Dumper.DumpEvolutionBinary(); + System.Media.SystemSounds.Asterisk.Play(); + } + #endregion + + #region Tab 3 + private void B_GetOutbreak_Click(object sender, EventArgs e) + { + Dumper.DumpOutbreak(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_DumpScriptCommands(object sender, EventArgs e) + { + Dumper.DumpScriptID(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_EventTriggers_Click(object sender, EventArgs e) + { + Dumper.DumpEventTriggers(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_GetDex_Click(object sender, EventArgs e) + { + Dumper.DumpDex(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_MoveShop_Click(object sender, EventArgs e) + { + Dumper.DumpMoveShop(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_DumpHash_Click(object sender, EventArgs e) + { + Dumper.DumpAHTB(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_FlavorText_Click(object sender, EventArgs e) + { + Dumper.DumpFlavorText(); + System.Media.SystemSounds.Asterisk.Play(); + } + #endregion } diff --git a/pkNX.WinForms/Dumping/DumperSWSH.cs b/pkNX.WinForms/Dumping/DumperSWSH.cs index 37ef1e36..b649f948 100644 --- a/pkNX.WinForms/Dumping/DumperSWSH.cs +++ b/pkNX.WinForms/Dumping/DumperSWSH.cs @@ -1,180 +1,179 @@ -using System; +using System; using System.Diagnostics; using System.Windows.Forms; using pkNX.Game; -namespace pkNX.WinForms +namespace pkNX.WinForms; + +public partial class DumperSWSH : Form { - public partial class DumperSWSH : Form + private readonly GameDumperSWSH Dumper; + + public DumperSWSH(GameManagerSWSH rom) { - private readonly GameDumperSWSH Dumper; - - public DumperSWSH(GameManagerSWSH rom) - { - InitializeComponent(); - Dumper = new GameDumperSWSH(rom); - } - - private void B_OpenFolder_Click(object sender, EventArgs e) => Process.Start("explorer.exe", Dumper.DumpFolder); - - #region Tab 1 - private void B_ParsePKMDetails_Click(object sender, EventArgs e) - { - Dumper.DumpPokeInfo(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_DumpTrainers_Click(object sender, EventArgs e) - { - Dumper.DumpTrainers(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_Wild_Click(object sender, EventArgs e) - { - Dumper.DumpWilds(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_Static_Click(object sender, EventArgs e) - { - Dumper.DumpStatic(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_Placement_Click(object sender, EventArgs e) - { - Dumper.DumpPlacement(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_Gift_Click(object sender, EventArgs e) - { - Dumper.DumpGifts(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_Nest_Click(object sender, EventArgs e) - { - Dumper.DumpNestEntries(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_Trade_Click(object sender, EventArgs e) - { - Dumper.DumpTrades(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_ItemInfo_Click(object sender, EventArgs e) - { - Dumper.DumpItems(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_Moves_Click(object sender, EventArgs e) - { - Dumper.DumpMoves(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_BattleTower_Click(object sender, EventArgs e) - { - Dumper.DumpBattleTower(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_Distribution_Nests_Click(object sender, EventArgs e) - { - using var fbd = new FolderBrowserDialog(); - if (fbd.ShowDialog() != DialogResult.OK) - return; - var path = fbd.SelectedPath; - Dumper.DumpDistributionNestEntries(path); - System.Media.SystemSounds.Asterisk.Play(); - } - #endregion - - #region Tab 2 - private void B_PKText_Click(object sender, EventArgs e) - { - Dumper.DumpStrings(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_PKLearn_Click(object sender, EventArgs e) - { - Dumper.DumpLearnsetBinary(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_PKEggMove_Click(object sender, EventArgs e) - { - Dumper.DumpEggBinary(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_PKEvo_Click(object sender, EventArgs e) - { - Dumper.DumpEvolutionBinary(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_PKForms_Click(object sender, EventArgs e) - { - Dumper.DumpFormNames(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_PKRibbon_Click(object sender, EventArgs e) - { - Dumper.DumpRibbonNames(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_Memories_Click(object sender, EventArgs e) - { - Dumper.DumpMemoryStrings(); - System.Media.SystemSounds.Asterisk.Play(); - } - #endregion - - #region Tab 3 - private void B_GetDummiedMoveInfo_Click(object sender, EventArgs e) - { - Dumper.DumpDummiedMoves(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_DumpHash_Click(object sender, EventArgs e) - { - Dumper.DumpAHTB(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_GalarDex_Click(object sender, EventArgs e) - { - Dumper.DumpGalarDex(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_FlavorText_Click(object sender, EventArgs e) - { - Dumper.DumpFlavorText(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_EggMove_Click(object sender, EventArgs e) - { - Dumper.DumpEggEntries(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void B_MaxDens_Click(object sender, EventArgs e) - { - Dumper.DumpMaxDens(); - System.Media.SystemSounds.Asterisk.Play(); - } - #endregion + InitializeComponent(); + Dumper = new GameDumperSWSH(rom); } + + private void B_OpenFolder_Click(object sender, EventArgs e) => Process.Start("explorer.exe", Dumper.DumpFolder); + + #region Tab 1 + private void B_ParsePKMDetails_Click(object sender, EventArgs e) + { + Dumper.DumpPokeInfo(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_DumpTrainers_Click(object sender, EventArgs e) + { + Dumper.DumpTrainers(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_Wild_Click(object sender, EventArgs e) + { + Dumper.DumpWilds(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_Static_Click(object sender, EventArgs e) + { + Dumper.DumpStatic(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_Placement_Click(object sender, EventArgs e) + { + Dumper.DumpPlacement(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_Gift_Click(object sender, EventArgs e) + { + Dumper.DumpGifts(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_Nest_Click(object sender, EventArgs e) + { + Dumper.DumpNestEntries(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_Trade_Click(object sender, EventArgs e) + { + Dumper.DumpTrades(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_ItemInfo_Click(object sender, EventArgs e) + { + Dumper.DumpItems(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_Moves_Click(object sender, EventArgs e) + { + Dumper.DumpMoves(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_BattleTower_Click(object sender, EventArgs e) + { + Dumper.DumpBattleTower(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_Distribution_Nests_Click(object sender, EventArgs e) + { + using var fbd = new FolderBrowserDialog(); + if (fbd.ShowDialog() != DialogResult.OK) + return; + var path = fbd.SelectedPath; + Dumper.DumpDistributionNestEntries(path); + System.Media.SystemSounds.Asterisk.Play(); + } + #endregion + + #region Tab 2 + private void B_PKText_Click(object sender, EventArgs e) + { + Dumper.DumpStrings(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_PKLearn_Click(object sender, EventArgs e) + { + Dumper.DumpLearnsetBinary(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_PKEggMove_Click(object sender, EventArgs e) + { + Dumper.DumpEggBinary(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_PKEvo_Click(object sender, EventArgs e) + { + Dumper.DumpEvolutionBinary(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_PKForms_Click(object sender, EventArgs e) + { + Dumper.DumpFormNames(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_PKRibbon_Click(object sender, EventArgs e) + { + Dumper.DumpRibbonNames(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_Memories_Click(object sender, EventArgs e) + { + Dumper.DumpMemoryStrings(); + System.Media.SystemSounds.Asterisk.Play(); + } + #endregion + + #region Tab 3 + private void B_GetDummiedMoveInfo_Click(object sender, EventArgs e) + { + Dumper.DumpDummiedMoves(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_DumpHash_Click(object sender, EventArgs e) + { + Dumper.DumpAHTB(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_GalarDex_Click(object sender, EventArgs e) + { + Dumper.DumpGalarDex(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_FlavorText_Click(object sender, EventArgs e) + { + Dumper.DumpFlavorText(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_EggMove_Click(object sender, EventArgs e) + { + Dumper.DumpEggEntries(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void B_MaxDens_Click(object sender, EventArgs e) + { + Dumper.DumpMaxDens(); + System.Media.SystemSounds.Asterisk.Play(); + } + #endregion } diff --git a/pkNX.WinForms/Dumping/GameDumperPLA.cs b/pkNX.WinForms/Dumping/GameDumperPLA.cs index f45976b6..13e4b88d 100644 --- a/pkNX.WinForms/Dumping/GameDumperPLA.cs +++ b/pkNX.WinForms/Dumping/GameDumperPLA.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -7,1071 +7,1093 @@ using pkNX.Structures; using pkNX.Structures.FlatBuffers; -namespace pkNX.WinForms +namespace pkNX.WinForms; + +public class GameDumperPLA { - public class GameDumperPLA + private readonly GameManagerPLA ROM; + public GameDumperPLA(GameManagerPLA rom) => ROM = rom; + public string DumpFolder { - private readonly GameManagerPLA ROM; - public GameDumperPLA(GameManagerPLA rom) => ROM = rom; - public string DumpFolder => Path.Combine(Directory.GetParent(ROM.PathRomFS).FullName, "Dump"); - - private string GetPath(string path) + get { - Directory.CreateDirectory(DumpFolder); - var result = Path.Combine(DumpFolder, path); - Directory.CreateDirectory(Directory.GetParent(result).FullName); // double check :( - return result; - } - - private string GetPath(string parent, string path) - { - Directory.CreateDirectory(DumpFolder); - var result = Path.Combine(DumpFolder, parent, path); - Directory.CreateDirectory(Directory.GetParent(result).FullName); // double check :( - return result; - } - - public void DumpPersonal() - { - var data = ROM.GetFile(GameFile.PersonalStats)[0]; - /*var obj = FlatBufferConverter.DeserializeFrom(data); - var test = PersonalConverter.GetBin(obj); - var path = GetPath("personal_la"); - File.WriteAllBytes(path, test);*/ - - var csv = GetPath("personal.csv"); - File.WriteAllText(csv, FlatDumper.GetTable(data)); - } - - public void DumpPokeInfo() - { - var s = ROM.GetStrings(TextName.SpeciesNames); - - var lrd = ROM.GetFile(GameFile.Learnsets)[0]; - var lr = FlatBufferConverter.DeserializeFrom(lrd); - var evd = ROM.GetFile(GameFile.Evolutions)[0]; - var ev = FlatBufferConverter.DeserializeFrom(evd); - var pt = new PersonalTable8LA(ROM.GetFile(GameFile.PersonalStats)); - var altForms = pt.GetFormList(s); - var entryNames = pt.GetPersonalEntryList(altForms, s, out _, out _); - var moveNames = ROM.GetStrings(TextName.MoveNames); - - var pd = new PersonalDumperPLA - { - Colors = Enum.GetNames(typeof(PokeColor)), - EggGroups = Enum.GetNames(typeof(EggGroup)), - EntryEggMoves = Array.Empty(), - EntryLearnsets = lr.Table, - EntryNames = entryNames, - ExpGroups = Enum.GetNames(typeof(EXPGroup)), - Evos = ev.Table, - - Abilities = ROM.GetStrings(TextName.AbilityNames), - Items = ROM.GetStrings(TextName.ItemNames), - Moves = moveNames, - Types = ROM.GetStrings(TextName.Types), - Species = ROM.GetStrings(TextName.SpeciesNames), - ZukanA = ROM.GetStrings(TextName.PokedexEntry1), - ZukanB = ROM.GetStrings(TextName.PokedexEntry2), - TMIndexes = Legal.TMHM_SWSH, - }; - - var result = pd.Dump(pt); - - var outname = GetPath("Pokemon.txt"); - File.WriteAllLines(outname, result); - - var learnTable = pd.MoveSpeciesLearn; - var outLearn = GetPath("MovePerPokemon.txt"); - var moveLines = learnTable.Select((z, i) => $"{i:000}\t{moveNames[i]}\t{string.Join(", ", z.Distinct())}"); - File.WriteAllLines(outLearn, moveLines); - - DumpMoveUsers(pt, lr); - } - - private void DumpMoveUsers(IPersonalTable pt, Learnset8a lr) - { - List Users = new(); - var moves = ROM.GetStrings(TextName.MoveNames); - var spec = ROM.GetStrings(TextName.SpeciesNames); - var shop = Legal.MoveShop8_LA; - for (int i = 0; i < moves.Length; i++) - { - var move = i; - var shopIndex = Array.IndexOf(shop, move); - bool isShop = shopIndex != -1; - var learn = lr.Table.Where(z => z.Arceus.Any(x => x.Move == move)); - var filtered = learn.Where(z => ((IPersonalInfoPLA)pt.GetFormEntry(z.Species, (byte)z.Form)).IsPresentInGame); - var result = filtered.Select(x => $"{spec[x.Species]}{(x.Form == 0 ? "" : $"-{x.Form}")} @ {Array.Find(x.Arceus, w => w.Move == move).Level}").ToArray(); - - List r = new() { $"{moves[move]}:" }; - if (isShop) - { - var species = pt.Table.OfType().Where(z => z.SpecialTutors[0][shopIndex] && z.IsPresentInGame); - var names = species.Select(z => $"{spec[z.ModelID]}{(z.Form == 0 ? "" : $"-{z.Form}")}"); - r.Add($"\tTutors: {string.Join(", ", names)}"); - } - - var lv = result.Length == 0 ? "None." : string.Join(", ", result); - r.Add($"\tLevel Up: {lv}"); - Users.AddRange(r); - } - - var outname = GetPath("MoveUsers.txt"); - File.WriteAllLines(outname, Users); - } - - private static readonly string[] ahtbext = { ".tbl", ".hsh" }; - - public void DumpAHTB() - { - var files = Directory.EnumerateFiles(ROM.PathRomFS, "*", SearchOption.AllDirectories) - .Where(z => ahtbext.Contains(Path.GetExtension(z))); - - var result = new HashSet(); - var list = new List(); - var gf = new List(); - foreach (var f in files) - { - var bytes = File.ReadAllBytes(f); - if (AHTB.IsAHTB(bytes)) - { - var tbl = new AHTB(bytes); - var summaries = tbl.Summary; - foreach (var t in tbl.ShortSummary) - result.Add(t); - list.Add(Path.GetFileName(f)); - list.AddRange(summaries); - } - else if (DatTable.IsDatTable(bytes)) - { - var tbl = new DatTable(bytes); - var summaries = tbl.Summary; - foreach (var t in tbl.ShortSummary) - result.Add(t); - list.Add(Path.GetFileName(f)); - list.AddRange(summaries); - } - } - - var paks = Directory.EnumerateFiles(ROM.PathRomFS, "*", SearchOption.AllDirectories) - .Where(z => Path.GetExtension(z) == ".gfpak"); - foreach (var f in paks) - { - var pak = new GFPack(f); - foreach (var bytes in pak.DecompressedFiles) - { - if (!AHTB.IsAHTB(bytes)) - continue; - - var tbl = new AHTB(bytes); - var summaries = tbl.Summary; - foreach (var t in tbl.ShortSummary) - result.Add(t); - list.Add(Path.GetFileName(f)); - list.AddRange(summaries); - } - - for (var i = 0; i < pak.HashAbsolute.Length; i++) - { - var x = pak.HashAbsolute[i]; - gf.Add($"{x.HashFnv1aPathFull:X16}\t{f}.Absolute[{i}]"); - } - - for (var i = 0; i < pak.HashInFolder.Length; i++) - { - var x = pak.HashInFolder[i]; - var folder = x.Folder; - gf.Add($"{folder.HashFnv1aPathFolderName:X16}\t{f}.Folder[{i}] ({folder.FileCount})"); - for (int j = 0; j < x.Files.Length; j++) - { - var y = x.Files[j]; - gf.Add($"{y.HashFnv1aPathFileName:X16}\t{f}.Folder[{i}][{j}] ({y.Index})"); - } - } - } - - var outname = GetPath("ahtb.txt"); - var outname2 = GetPath("ahtblist.txt"); - var outname3 = GetPath("gfpakhash.txt"); - File.WriteAllLines(outname, result); - File.WriteAllLines(outname2, list); - File.WriteAllLines(outname3, gf); - } - - public void DumpDrops() - { - var names = ROM.GetStrings(TextName.ItemNames); - var field = Path.Combine(ROM.PathRomFS, "bin", "pokemon", "data", "poke_drop_item.bin"); - var fieldItems = FlatBufferConverter.DeserializeFrom(field).Table.Select(z => z.Dump(names)); - File.WriteAllLines(GetPath("DropItems.txt"), fieldItems); - - var battle = Path.Combine(ROM.PathRomFS, "bin", "pokemon", "data", "poke_drop_item_battle.bin"); - var battleItems = FlatBufferConverter.DeserializeFrom(battle).Table.Select(z => z.Dump(names)); - File.WriteAllLines(GetPath("BattleDropItems.txt"), battleItems); - } - - public void DumpItems() - { - var items = ROM.GetFile(GameFile.ItemStats); - var file = items[0]; - var array = Item8a.GetArray(file); - var groups = array.GroupBy(z => z.Pouch); - foreach (var g in groups) - { - var key = g.Key; - var IDs = g.Where(z => z.ItemSprite >= 0).Select(z => z.ItemID); - var path = GetPath($"{key}.txt"); - File.WriteAllText(path, string.Join(", ", IDs.Select(z => $"{z:000}"))); - } - - var names = ROM.GetStrings(TextName.ItemNames); - var lines = TableUtil.GetNamedTypeTable(array, names, "Items"); - var table = GetPath("ItemData.txt"); - var bin = GetPath("ItemData.bin"); - File.WriteAllText(table, lines); - File.WriteAllBytes(bin, array.SelectMany(z => z.Data).ToArray()); - } - - public void DumpMoves() - { - var dir = Path.Combine(ROM.PathRomFS, "bin", "pml", "waza"); - var files = Directory.GetFiles(dir); - var moves = FlatBufferConverter.DeserializeFrom(files); - var names = ROM.GetStrings(TextName.MoveNames); - var lines = TableUtil.GetNamedTypeTable(moves, names, "Moves"); - var table = GetPath("MoveData.txt"); - File.WriteAllText(table, lines); - - var pp = moves.Select(z => z.FPP); - var str = string.Join(", ", pp.Select(z => $"{z:00}")); - var pppath = GetPath("MovePP.txt"); - File.WriteAllText(pppath, str); - - // get dummied moves - var moveNames = ROM.GetStrings(TextName.MoveNames); - var moveDesc = ROM.GetStrings(TextName.MoveFlavor); - - var tuple = moveNames - .Select((z, i) => new { Name = z, Desc = moveDesc[i], Index = i }) - .Where(z => !moves[z.Index].CanUseMove) - .Select(z => $"{z.Index:000}\t{z.Name}"); - - var path = GetPath("snappedMoves.txt"); - File.WriteAllLines(path, tuple); // rest in peace - - var snap2 = GetPath("snappedID.txt"); - var snapMove = string.Join(", ", moves.Where(z => !z.CanUseMove).Select(z => $"{z.MoveID:000}")); - File.WriteAllText(snap2, snapMove); - } - - public void DumpLearnsetBinary() - { - var data = ROM.GetFile(GameFile.Learnsets)[0]; - var obj = FlatBufferConverter.DeserializeFrom(data); - var pt = new PersonalTable8LA(ROM.GetFile(GameFile.PersonalStats)); - var result = new byte[pt.Table.Length][]; - var mastery = new byte[pt.Table.Length][]; - for (int i = 0; i < result.Length; i++) - result[i] = mastery[i] = Array.Empty(); - - var Dupes = new List<(int Species, int Form)>(); - foreach (var e in obj.Table) - { - if (e.Arceus.Length == 0) - continue; - var index = pt.GetFormIndex(e.Species, (byte)e.Form); - var entry = (IPersonalInfoPLA)pt[index]; - if (!entry.IsPresentInGame) - continue; - result[index] = e.WriteLearnsetAsLearn6(); - mastery[index] = e.WriteMasteryAsLearn6(); - - if (e.Arceus.Select(z => z.Level).Distinct().Count() != e.Arceus.Length) - Dupes.Add(new(e.Species, e.Form)); - } - - // Learnset - { - var mini = MiniUtil.PackMini(result, "la"); - var bin = GetPath(Path.Combine("bin", "lvlmove_la.pkl")); - File.WriteAllBytes(bin, mini); - } - // Mastery - { - var mini = MiniUtil.PackMini(mastery, "la"); - var bin = GetPath(Path.Combine("bin", "mastery_la.pkl")); - File.WriteAllBytes(bin, mini); - } - // Dupes - { - var txt = GetPath(Path.Combine("bin", "lvlmove_dupes.txt")); - File.WriteAllLines(txt, Dupes.Select(z => $"{(Species)z.Species}{(z.Form == 0 ? "" : $"{z.Form}")}")); - } - } - - public void DumpEvolutionBinary() - { - // format matches past gen and PKHeX's expected format - var data = ROM.GetFilteredFolder(GameFile.Evolutions)[0]; - var obj = FlatBufferConverter.DeserializeFrom(data); - var pt = new PersonalTable8LA(ROM.GetFile(GameFile.PersonalStats)); - var result = new byte[pt.Table.Length][]; - for (int i = 0; i < result.Length; i++) - result[i] = Array.Empty(); - - for (var i = 0; i < obj.Table.Length; i++) - { - var e = obj.Table[i]; - if (e.Table?.Length is not > 0) - continue; - var index = pt.GetFormIndex(e.Species, (byte)e.Form); - var entry = (IPersonalInfoPLA)pt[index]; - if (!entry.IsPresentInGame) - continue; - result[index] = e.Write(); - } - - var mini = MiniUtil.PackMini(result, "la"); - var bin = GetPath(Path.Combine("bin", "evos_la.pkl")); - File.WriteAllBytes(bin, mini); - } - - public void DumpGifts() - { - var speciesNames = ROM.GetStrings(TextName.SpeciesNames); - var data = ROM.GetFile(GameFile.EncounterGift)[0]; - var gifts = FlatBufferConverter.DeserializeFrom(data); - var table = TableUtil.GetTable(gifts.Table); - var fn = GetPath("Gifts.txt"); - File.WriteAllText(fn, table); - - var f2 = GetPath("GiftsPKHeX.txt"); - File.WriteAllLines(f2, gifts.Table.Select(z => z.Dump(speciesNames))); - } - - public void DumpStatic() - { - var speciesNames = ROM.GetStrings(TextName.SpeciesNames); - var data = ROM.GetFile(GameFile.EncounterStatic)[0]; - var statics = FlatBufferConverter.DeserializeFrom(data); - - var lines = new List(); - - foreach (var set in statics.Table) - { - lines.Add($"{set.EncounterName}:"); - - var table = TableUtil.GetTable(set.Table); - - foreach (var line in table.Split(new[] { Environment.NewLine }, StringSplitOptions.None)) - lines.Add($"\t{line}"); - } - - var fn = GetPath("StaticEncounters.txt"); - File.WriteAllLines(fn, lines); - - var f2 = GetPath("StaticEncountersPKHeX.txt"); - File.WriteAllLines(f2, statics.Table.SelectMany(z => z.Table.Select(x => x.Dump(speciesNames, z.EncounterName))).OrderBy(z => z)); - } - - public void DumpWilds() - { - var speciesName = ROM.GetStrings(TextName.SpeciesNames); - - Dictionary map = GetPlaceNameMap(); - var multdata = ROM.GetFile(GameFile.EncounterRateTable)[0]; - var multipliers = FlatBufferConverter.DeserializeFrom(multdata); - var miscdata = ROM.GetFile(GameFile.PokeMisc)[0]; - var misc = FlatBufferConverter.DeserializeFrom(miscdata); - - var nhoGroup_b = ROM.GetFile(GameFile.NewHugeGroup)[0]; - var nhoGroup = FlatBufferConverter.DeserializeFrom(nhoGroup_b); - var nhoGroupL_b = ROM.GetFile(GameFile.NewHugeGroupLottery)[0]; - var nhoGroupL = FlatBufferConverter.DeserializeFrom(nhoGroupL_b); - - var resident = (GFPack)ROM.GetFile(GameFile.Resident); - var bin_settings = resident.GetDataFullPath("bin/field/resident/AreaSettings.bin"); - var settings = FlatBufferConverter.DeserializeFrom(bin_settings); - - const string wild = "wild"; - Directory.CreateDirectory(GetPath(wild)); - - var all = new List(); - var allUnownLines = new List(); - var allUnownLinesBias = new List(); - const float bias = 20; - - var hexBin = new List(); - var allSlots = new List(); - var allSpawners = new List(); - var allWormholes = new List(); - var allLocations = new List(); - var allLandItems = new List(); - var allLandMarks = new List(); - var allUnown = new List(); - var allMkrg = new List(); - var allSearchItem = new List(); - foreach (var areaNameList in ResidentAreaSet.AreaNames) - { - var instance = AreaInstance8a.Create(resident, areaNameList, settings); - var lines = EncounterTable8aUtil.GetLines(multipliers, misc, speciesName, instance, nhoGroup, nhoGroupL, map).ToList(); - File.WriteAllLines(GetPath(wild, $"Encounters_{instance.AreaName}.txt"), lines); - - var unown = EncounterTable8aUtil.GetUnownLines(instance, map).Distinct().ToList(); - File.WriteAllLines(GetPath(wild, $"unown_0_{instance.AreaName}.txt"), unown); - var unownBias = EncounterTable8aUtil.GetUnownLinesBias(instance, map, bias).Distinct().ToList(); - File.WriteAllLines(GetPath(wild, $"unown_{bias:0}_{instance.AreaName}.txt"), unownBias); - allUnownLines.AddRange(unown); - allUnownLinesBias.AddRange(unownBias); - - var slices = EncounterTable8aUtil.GetEncounterDump(instance, map, misc, nhoGroup, nhoGroupL); - foreach (var s in slices) - { - if (!hexBin.Any(z => z.SequenceEqual(s))) - hexBin.Add(s); - else - continue; - } - - all.AddRange(lines); - all.Add(string.Empty); - - allSlots.AddRange(instance.Encounters.SelectMany(z => z.Table)); - allSpawners.AddRange(instance.Spawners); - allWormholes.AddRange(instance.Wormholes); - allLocations.AddRange(instance.Locations); - allLandItems.AddRange(instance.LandItems); - allLandMarks.AddRange(instance.LandMarks); - allUnown.AddRange(instance.Unown); - allMkrg.AddRange(instance.Mikaruge); - allSearchItem.AddRange(instance.SearchItem); - - foreach (var subArea in instance.SubAreas) - { - allSlots.AddRange(subArea.Encounters.SelectMany(z => z.Table)); - allSpawners.AddRange(subArea.Spawners); - allWormholes.AddRange(subArea.Wormholes); - allLocations.AddRange(subArea.Locations); - allLandItems.AddRange(subArea.LandItems); - allLandMarks.AddRange(subArea.LandMarks); - allUnown.AddRange(subArea.Unown); - allMkrg.AddRange(subArea.Mikaruge); - allSearchItem.AddRange(subArea.SearchItem); - } - } - - var mini = MiniUtil.PackMini(hexBin.ToArray(), "la"); - File.WriteAllBytes(GetPath(wild, "encounter_la.pkl"), mini); - File.WriteAllLines(GetPath(wild, "Encounters_All.txt"), all); - File.WriteAllLines(GetPath(wild, "Unown_All.txt"), allUnownLines); - File.WriteAllLines(GetPath(wild, $"Unown_All_Bias_{bias}.txt"), allUnownLinesBias); - - File.WriteAllText(GetPath(wild, "allMultipliers.csv"), TableUtil.GetTable(multipliers.Table)); - File.WriteAllText(GetPath(wild, "PokeMisc.csv"), TableUtil.GetTable(misc.Table)); - File.WriteAllText(GetPath(wild, "allSlotTable.csv"), TableUtil.GetTable(allSlots)); - File.WriteAllText(GetPath(wild, "allSpawnerTable.csv"), TableUtil.GetTable(allSpawners)); - File.WriteAllText(GetPath(wild, "allWormholeTable.csv"), TableUtil.GetTable(allWormholes)); - File.WriteAllText(GetPath(wild, "allLocationTable.csv"), TableUtil.GetTable(allLocations)); - File.WriteAllText(GetPath(wild, "allLandMarks.csv"), TableUtil.GetTable(allLandMarks)); - File.WriteAllText(GetPath(wild, "allLandMarkSpawns.csv"), TableUtil.GetTable(allLandItems)); - File.WriteAllText(GetPath(wild, "allUnown.csv"), TableUtil.GetTable(allUnown)); - File.WriteAllText(GetPath(wild, "allMkrg.csv"), TableUtil.GetTable(allMkrg)); - File.WriteAllText(GetPath(wild, "allSearchItem.csv"), TableUtil.GetTable(allSearchItem)); - } - - public void DumpResident() - { - var resident = (GFPack)ROM.GetFile(GameFile.Resident); - var bin_settings = resident.GetDataFullPath("bin/field/resident/AreaSettings.bin"); - var settings = FlatBufferConverter.DeserializeFrom(bin_settings); - var dir = GetPath("Resident"); - var props = typeof(AreaSettings8a).GetProperties(); - foreach (var x in settings.Table) - { - foreach (var p in props) - { - var value = p.GetValue(x); - if (value is not string { Length: not 0 } s) - continue; - if (!s.Contains('/')) - continue; - if (File.Exists(Path.Combine(ROM.PathRomFS, s))) - continue; - - try - { - int index = resident.GetIndexFull(FnvHash.HashFnv1a_64(s)); - if (index == -1) - continue; - var data = resident.GetDataFullPath(s); - var file = s.Replace('/', '\\'); - var dest = Path.Combine(dir, file); - var folder = Path.GetDirectoryName(dest); - Directory.CreateDirectory(folder); - File.WriteAllBytes(dest, data); - } - catch - { - } - } - } - } - - public void DumpPlacement() - { - var resident = (GFPack)ROM.GetFile(GameFile.Resident); - var bin_settings = resident.GetDataFullPath("bin/field/resident/AreaSettings.bin"); - var settings = FlatBufferConverter.DeserializeFrom(bin_settings); - - Dictionary map = GetPlaceNameMap(); - - var location_all = new List(); - var spawner_all = new List(); - var wh_spawner_all = new List(); - var mkrg_all = new List(); - const string placement = "placement"; - Directory.CreateDirectory(GetPath(placement)); - - foreach (var areaNameList in ResidentAreaSet.AreaNames) - { - var area = AreaInstance8a.Create(resident, areaNameList, settings); - foreach (var subArea in new[] { area }.Concat(area.SubAreas)) - { - var areaName = subArea.AreaName; - if (subArea.Locations.Length != 0) - { - var loc_lines = GetLocationBoundLines(areaName, map, subArea.Locations); - - location_all.AddRange(loc_lines); - location_all.Add(string.Empty); - File.WriteAllLines(GetPath(placement, $"Location_{areaName}.txt"), loc_lines); - } - if (subArea.Spawners.Length != 0) - { - var spwn_lines = GetSpawnLines(areaName, map, subArea.Spawners, subArea.Locations); - - spawner_all.AddRange(spwn_lines); - spawner_all.Add(string.Empty); - File.WriteAllLines(GetPath(placement, $"Spawner_{areaName}.txt"), spwn_lines); - } - if (subArea.Wormholes.Length != 0) - { - var spwn_lines = GetSpawnLines(areaName, map, subArea.Wormholes, subArea.Locations); - - wh_spawner_all.AddRange(spwn_lines); - wh_spawner_all.Add(string.Empty); - File.WriteAllLines(GetPath(placement, $"WhSpawner_{areaName}.txt"), spwn_lines); - } - if (subArea.Mikaruge.Length != 0) - { - var mkrg_lines = GetMikarugeLines(areaName, map, subArea.Mikaruge, subArea.Locations); - - mkrg_all.AddRange(mkrg_lines); - mkrg_all.Add(string.Empty); - File.WriteAllLines(GetPath(placement, $"Mikaruge_{areaName}.txt"), mkrg_lines); - } - if (subArea.SearchItem.Length != 0) - { - var mkrg_lines = GetSearchItemLines(areaName, map, subArea.SearchItem, subArea.Locations); - - mkrg_all.AddRange(mkrg_lines); - mkrg_all.Add(string.Empty); - File.WriteAllLines(GetPath(placement, $"SearchItem_{areaName}.txt"), mkrg_lines); - } - - // Debug for Visualization - if (new[] { "ha_area01", "ha_area02", "ha_area03", "ha_area04", "ha_area05" }.Contains(areaName)) - DumpVisualizationData(area); - } - } - - File.WriteAllLines(GetPath(placement, "Location_all.txt"), location_all); - File.WriteAllLines(GetPath(placement, "Spawner_all.txt"), spawner_all); - File.WriteAllLines(GetPath(placement, "WhSpawner_all.txt"), wh_spawner_all); - File.WriteAllLines(GetPath(placement, "Mikaruge_all.txt"), mkrg_all); - } - - private Dictionary GetPlaceNameMap() - { - var map = new Dictionary(); - var place_names = ROM.GetStrings(TextName.metlist_00000); - - var scriptFolder = new FolderContainer(((FolderContainer)ROM.GetFile(GameFile.StoryText)).FilePath!); - scriptFolder.Initialize(); - - var locationNames = scriptFolder.GetFileData("place_name.tbl")!; - var ahtb = new AHTB(locationNames); - for (var i = 0; i < place_names.Length; i++) - map[ahtb.Entries[i].Name] = (place_names[i], i); - return map; - } - - private static IReadOnlyList GetLocationBoundLines(string areaName, - IReadOnlyDictionary map, - IEnumerable locations) - { - var result = new List { $"Area: {areaName}" }; - foreach (var location in locations) - { - string line = $"\t{location}"; - if (location.IsNamedPlace) - { - var (name, index) = map[location.PlaceName]; - line += $" // {index}, \"{name}\""; - } - result.Add(line); - } - return result; - } - - private static IReadOnlyList GetSpawnLines(string areaName, - IReadOnlyDictionary map, - IEnumerable spawners, - IReadOnlyList locations) - { - var result = new List { $"Area: {areaName}" }; - foreach (var spawner in spawners) - { - var contained = GetNearbyLocationNames(spawner, locations, map); - result.Add($"\t{spawner} // Containing Locations: {contained}"); - } - return result; - } - - private static IReadOnlyList GetMikarugeLines(string areaName, - IReadOnlyDictionary map, - IEnumerable mkrgs, - IReadOnlyList locations) - { - var result = new List { $"Area: {areaName}" }; - foreach (var mkrg in mkrgs) - { - var contained = GetNearbyLocationNames(mkrg, locations, map); - result.Add($"\t{mkrg} // Containing Locations: {contained}"); - } - return result; - } - - private static IReadOnlyList GetSearchItemLines(string areaName, - IReadOnlyDictionary map, - IEnumerable mkrgs, - IReadOnlyList locations) - { - var result = new List { $"Area: {areaName}" }; - foreach (var psi in mkrgs) - { - var contained = GetNearbyLocationNames(psi, locations, map); - result.Add($"\t{psi} // Containing Locations: {contained}"); - } - return result; - } - - private static string GetNearbyLocationNames(PlacementSpawner8a spawner, - IReadOnlyList locations, - IReadOnlyDictionary map) - { - var containedBy = spawner.GetContainingLocations(locations); - var placeNames = containedBy.Select(z => z.PlaceName).Distinct(); - var localized = placeNames.Select(pn => map[pn].Name); - return string.Join(", ", localized); - } - - private static string GetNearbyLocationNames(PlacementSearchItem mkrg, - IReadOnlyList locations, - IReadOnlyDictionary map) - { - var containedBy = mkrg.GetContainingLocations(locations); - var placeNames = containedBy.Select(z => z.PlaceName).Distinct(); - var localized = placeNames.Select(pn => map[pn].Name); - return string.Join(", ", localized); - } - - private static string GetNearbyLocationNames(PlacementMkrgEntry mkrg, - IReadOnlyList locations, - IReadOnlyDictionary map) - { - var containedBy = mkrg.GetContainingLocations(locations); - var placeNames = containedBy.Select(z => z.PlaceName).Distinct(); - var localized = placeNames.Select(pn => map[pn].Name); - return string.Join(", ", localized); - } - - private void DumpVisualizationData(AreaInstance8a area) - { - var vis_lines = new List { "LOCS = [" }; - - const string folder = "placementVis"; - Directory.CreateDirectory(GetPath(folder)); - - foreach (var loc in area.Locations) - { - if (!loc.IsNamedPlace) - continue; - vis_lines.Add($"({loc.Parameters.Coordinates.ToTriple()}, {loc.Parameters.Rotation.ToTriple()}, {loc.ShapeSummary.Replace("/* Shape = */ ", "")}, {loc.SizeX}, {loc.SizeY}, {loc.SizeZ}, \"{loc.PlaceName}\"), "); - } - - vis_lines.Add("]"); - vis_lines.Add(string.Empty); - - vis_lines.Add("SPAWNERS = ["); - foreach (var spwn in area.Spawners) - vis_lines.Add($"({spwn.Parameters.Coordinates.ToTriple()}, {spwn.Scalar}),"); - vis_lines.Add("]"); - vis_lines.Add(string.Empty); - - vis_lines.Add("WH_SPAWNERS = ["); - foreach (var spwn in area.Wormholes) - vis_lines.Add($"({spwn.Parameters.Coordinates.ToTriple()}, {spwn.Scalar}),"); - - vis_lines.Add("LANDMARKS = ["); - foreach (var spwn in area.LandMarks) - vis_lines.Add($"({spwn.Parameters.Coordinates.ToTriple()}, {spwn.Scalar}),"); - - vis_lines.Add("]"); - vis_lines.Add(string.Empty); - - File.WriteAllLines(GetPath(folder, $"Vis_{area.AreaName}.txt"), vis_lines); - } - - public void DumpOutbreak() - { - var file = ROM.GetFile(GameFile.Outbreak).FilePath; - var result = FlatDumper.GetTable(file!); - File.WriteAllText(GetPath("massOutbreak.txt"), result); - - var arr = FlatBufferConverter.DeserializeFrom(file!).Table; - var cache = new DataCache(arr); - var names = Enumerable.Range(0, cache.Length).Select(z => $"{z}").ToArray(); - var form = new GenericEditor(cache, names, "Outbreak"); - form.ShowDialog(); - } - - public void DumpDex() - { - DumpDexSummarySpecies(); - - var dexResearchPath = Path.Combine(ROM.PathRomFS, "bin", "appli", "pokedex", "res_table", "pokedex_research_task_table.bin"); - var dexResearchBin = File.ReadAllBytes(dexResearchPath); - var dexResearch = FlatBufferConverter.DeserializeFrom(dexResearchBin); - - var csv = GetPath("pokedex_research.csv"); - File.WriteAllText(csv, TableUtil.GetTable(dexResearch.Table)); - - // Pokedex Research for PKHeX - DumpResearchTasks(dexResearch); - } - - private void DumpResearchTasks(PokedexResearchTable dexResearch) - { - var pt = new PersonalTable8LA(ROM.GetFile(GameFile.PersonalStats)); - var result = new byte[pt.Table.Max(p => p.DexIndexRegional)][]; - for (int i = 0; i < result.Length; i++) - result[i] = Array.Empty(); - - ushort GetDexIndex(ushort species) - { - var formCount = pt.GetFormEntry(species, 0).FormCount; - for (byte form = 0; form < formCount; form++) - { - var p = (IPersonalInfoPLA)pt.GetFormEntry(species, form); - - if (p.DexIndexRegional != 0) - return p.DexIndexRegional; - } - - return 0; - } - - for (ushort species = 0; species <= 980; species++) - { - var entries = Array.FindAll(dexResearch.Table, z => z.Species == species); - if (entries.Length == 0) - continue; - - var dexInd = GetDexIndex(species); - if (dexInd == 0) - throw new ArgumentException($"Research tasks exist for species {species} not in dex?"); - - if (result[dexInd - 1].Length != 0) - throw new ArgumentException($"Two species share dex index {dexInd}?"); - - using var ms = new MemoryStream(); - using var br = new BinaryWriter(ms); - - var moveTaskIndex = 0; - var defeatTypeTaskIndex = 0; - - foreach (var task in entries) - { - var type = task.MoveType; - var timeOfDay = task.TimeOfDay; - - var curMultiIndex = 0xFF; - - if (task.TaskType == ResearchTaskType.MoveTask) - { - curMultiIndex = moveTaskIndex; - moveTaskIndex++; - } - - if (task.TaskType == ResearchTaskType.DefeatTask) - { - curMultiIndex = defeatTypeTaskIndex; - defeatTypeTaskIndex++; - } - else - { - type = 18; - } - - if (task.TaskType != ResearchTaskType.Unknown_10) - { - timeOfDay = 5; - } - - var thresholds = - new[] { task.Threshold1, task.Threshold2, task.Threshold3, task.Threshold4, task.Threshold5 } - .Where(e => e != 0).ToArray(); - - // 00: u8 task - // 01: u8 points_single - // 02: u8 points_bonus - // 03: u8 threshold - // 04: u16 move - // 06: u8 type - // 07: u8 time of day - // 08: u64 hash_06 - // 10: u64 hash_07 - // 18: u64 hash_08 - // 20: u8 num_thresholds - // 21: u8 thresholds[5] - // 26: u8 required - // 27: u8 multi_index - - br.Write((byte)task.TaskType); - br.Write((byte)task.PointsSingle); - br.Write((byte)task.PointsBonus); - br.Write((byte)task.Threshold); - br.Write((ushort)task.Move); - br.Write((byte)type); - br.Write((byte)timeOfDay); - br.Write(task.Hash_06); - br.Write(task.Hash_07); - br.Write(task.Hash_08); - - br.Write((byte)thresholds.Length); - for (var i = 0; i < 5; i++) - { - if (i < thresholds.Length) - br.Write((byte)thresholds[i]); - else - br.Write((byte)0); - } - - br.Write((byte)(task.RequiredForCompletion ? 1 : 0)); - br.Write((byte)curMultiIndex); - } - - result[dexInd - 1] = ms.ToArray(); - } - - var mini = MiniUtil.PackMini(result, "la"); - var bin = GetPath(Path.Combine("bin", "researchtask_la.pkl")); - File.WriteAllBytes(bin, mini); - } - - private void DumpDexSummarySpecies() - { - var pt = new PersonalTable8LA(ROM.GetFile(GameFile.PersonalStats)); - var s = ROM.GetStrings(TextName.SpeciesNames); - - var dex = new List(); - var dexit = new List(); - var foreign = new List(); - for (int i = 1; i < pt.Table.Length; i++) - { - var p = (IPersonalInfoPLA)pt[i]; - bool any = false; - var specForm = $"{p.ModelID:000}\t{p.Form}\t{s[p.ModelID]}{(p.Form == 0 ? "" : $"-{p.Form:00}")}"; - if (p.DexIndexRegional != 0) - { - dex.Add($"{p.DexIndexRegional:000}\t{specForm}"); - any = true; - } - - if (!p.IsPresentInGame) - dexit.Add(specForm); - else if (!any) - foreign.Add(specForm); - } - - var path = GetPath("Dex.txt"); - File.WriteAllLines(path, dex.OrderBy(z => z)); - - var path4 = GetPath("Dexit.txt"); - File.WriteAllLines(path4, dexit); - - var path5 = GetPath("Foreign.txt"); - File.WriteAllLines(path5, foreign); - } - - public void DumpFlavorText() - { - IEnumerable Zip(TextName name, TextName flavor) - { - var n = ROM.GetStrings(name); - var f = ROM.GetStrings(flavor); - return n.Select((z, i) => $"{z}\t{f[i].Replace("\\n", " ")}"); - } - - var p1 = GetPath("ItemFlavor.txt"); - var p2 = GetPath("MoveFlavor.txt"); - var p3 = GetPath("AbilityFlavor.txt"); - - var l1 = Zip(TextName.ItemNames, TextName.ItemFlavor); - var l2 = Zip(TextName.MoveNames, TextName.MoveFlavor); - var l3 = Zip(TextName.AbilityNames, TextName.AbilityFlavor); - - File.WriteAllLines(p1, l1); - File.WriteAllLines(p2, l2); - File.WriteAllLines(p3, l3); - } - - private static readonly string[] LanguageCodes = { "ja", "en", "fr", "it", "de", "es", "ko", "zh", "zh2" }; - - private static readonly string[] LanguageNames = - { - "カタカナ", - "漢字", - "English", - "Français", - "Italiano", - "Deutsch", - "Español", - "한국", - "汉字简化方案", - "漢字簡化方案", - }; - - private void ChangeLanguage(int index) - { - ROM.Language = index; - ROM.ResetText(); - } - - public void DumpStrings() - { - int lang = ROM.Language; - var indexes = new[] { 0, 2, 3, 4, 5, 6, 7, 8, 9 }; - for (int i = 0; i < indexes.Length; i++) - { - var code = LanguageCodes[i]; - var name = LanguageNames[i]; - var index = indexes[i]; - - DumpStrings(code, name, index); - } - ChangeLanguage(lang); - } - - private void DumpStrings(string code, string name, int index) - { - Console.WriteLine($"Dumping strings for {name}."); - ChangeLanguage(index); - - DumpStringSet(TextName.MoveNames, "Moves"); - DumpStringSet(TextName.ItemNames, "Items"); - DumpStringSet(TextName.SpeciesNames, "Species"); - DumpStringSet(TextName.AbilityNames, "Abilities"); - DumpStringSet(TextName.metlist_00000, "la_00000"); - DumpStringSet(TextName.metlist_30000, "la_30000"); - DumpStringSet(TextName.metlist_40000, "la_40000"); - DumpStringSet(TextName.metlist_60000, "la_60000"); - DumpStringSet(TextName.Forms, "forms"); - - void DumpStringSet(TextName t, string file) - { - var strings = ROM.GetStrings(t); - var fn = $"text_{file}_{code}.txt"; - - var folder = Path.Combine(code, fn); - - var path = GetPath(folder); - File.WriteAllLines(path, strings); - } - } - - public void DumpScriptID() - { - var file = Path.Combine(ROM.PathRomFS, "bin", "event", "script_id_record_release.bin"); - var text = FlatDumper.GetTable(file); - var path = GetPath("scriptCommands.txt"); - File.WriteAllText(path, text); - } - - public void DumpEventTriggers() - { - var eventTriggerDir = Path.Combine(ROM.PathRomFS, "bin", "event", "event_progress", "trigger"); - var eventTriggerFiles = Directory.EnumerateFiles(eventTriggerDir, "*", SearchOption.AllDirectories).Where(p => Path.GetExtension(p) == ".bin"); - - const string outFolder = "event_trigger"; - Directory.CreateDirectory(GetPath(outFolder)); - - var unknownTriggers = new List(); - var unknownConditions = new List(); - var unknownCommands = new List(); - - var allLines = new List(); - - foreach (var f in eventTriggerFiles) - { - if (Path.GetFileName(f) == "trigger_preset.bin") - continue; - - var table = FlatBufferConverter.DeserializeFrom(f); - - var curLines = new List { $"File: {Path.GetFileName(f)}" }; - - foreach (var line in Trigger8aUtil.GetTriggerTableSummary(table)) - curLines.Add($"\t{line}"); - - File.WriteAllLines(GetPath(outFolder, $"trigger_{Path.GetFileNameWithoutExtension(f).Replace("trigger_", string.Empty)}.txt"), curLines); - - allLines.AddRange(curLines); - allLines.Add(string.Empty); - - foreach (var trg in table.Table) - { - if (!Enum.IsDefined(typeof(TriggerType8a), trg.Meta.TriggerTypeID) && !unknownTriggers.Contains((ulong)trg.Meta.TriggerTypeID)) - unknownTriggers.Add((ulong)trg.Meta.TriggerTypeID); - - foreach (var cond in trg.Conditions) - { - if (!Enum.IsDefined(typeof(ConditionType8a), cond.ConditionTypeID) && !unknownConditions.Contains((ulong)cond.ConditionTypeID)) - unknownConditions.Add((ulong)cond.ConditionTypeID); - } - - foreach (var cmd in trg.Commands) - { - if (!Enum.IsDefined(typeof(TriggerCommandType8a), cmd.CommandTypeID) && !unknownCommands.Contains((ulong)cmd.CommandTypeID)) - unknownCommands.Add((ulong)cmd.CommandTypeID); - } - } - } - - File.WriteAllLines(GetPath(outFolder, "triggerAll.txt"), allLines); - - File.WriteAllLines(GetPath(outFolder, "triggerUnknownTypes.txt"), unknownTriggers.OrderBy(x => x).Select(x => $"0x{x:X16},")); - File.WriteAllLines(GetPath(outFolder, "triggerUnknownConditions.txt"), unknownConditions.OrderBy(x => x).Select(x => $"0x{x:X16},")); - File.WriteAllLines(GetPath(outFolder, "triggerUnknownCommands.txt"), unknownCommands.OrderBy(x => x).Select(x => $"0x{x:X16},")); - } - - public void DumpMoveShop() - { - var file = ROM.GetFile(GameFile.MoveShop).FilePath; - var result = FlatDumper.GetTable(file!); - File.WriteAllText(GetPath("MoveShop.csv"), result); + var parent = Directory.GetParent(ROM.PathRomFS); + if (parent is null) + throw new DirectoryNotFoundException($"Unable to find parent directory of {ROM.PathRomFS}"); + return Path.Combine(parent.FullName, "Dump"); } } + + private string GetPath(string path) + { + Directory.CreateDirectory(DumpFolder); + var result = Path.Combine(DumpFolder, path); + var parent = Directory.GetParent(result); + if (parent is null) + throw new DirectoryNotFoundException($"Unable to get parent directory of {result}"); + Directory.CreateDirectory(parent.FullName); // double check :( + return result; + } + + private string GetPath(string parent, string path) + { + Directory.CreateDirectory(DumpFolder); + var result = Path.Combine(DumpFolder, parent, path); + var parent2 = Directory.GetParent(result); + if (parent2 is null) + throw new DirectoryNotFoundException($"Unable to get parent directory of {result}"); + Directory.CreateDirectory(parent2.FullName); // double check :( + return result; + } + + public void DumpPersonal() + { + var data = ROM.GetFile(GameFile.PersonalStats)[0]; + /*var obj = FlatBufferConverter.DeserializeFrom(data); + var test = PersonalConverter.GetBin(obj); + var path = GetPath("personal_la"); + File.WriteAllBytes(path, test);*/ + + var csv = GetPath("personal.csv"); + File.WriteAllText(csv, FlatDumper.GetTable(data)); + } + + public void DumpPokeInfo() + { + var s = ROM.GetStrings(TextName.SpeciesNames); + + var lrd = ROM.GetFile(GameFile.Learnsets)[0]; + var lr = FlatBufferConverter.DeserializeFrom(lrd); + var evd = ROM.GetFile(GameFile.Evolutions)[0]; + var ev = FlatBufferConverter.DeserializeFrom(evd); + var pt = new PersonalTable8LA(ROM.GetFile(GameFile.PersonalStats)); + var altForms = pt.GetFormList(s); + var entryNames = pt.GetPersonalEntryList(altForms, s, out _, out _); + var moveNames = ROM.GetStrings(TextName.MoveNames); + + var pd = new PersonalDumperPLA + { + Colors = Enum.GetNames(typeof(PokeColor)), + EggGroups = Enum.GetNames(typeof(EggGroup)), + EntryEggMoves = Array.Empty(), + EntryLearnsets = lr.Table, + EntryNames = entryNames, + ExpGroups = Enum.GetNames(typeof(EXPGroup)), + Evos = ev.Table, + + Abilities = ROM.GetStrings(TextName.AbilityNames), + Items = ROM.GetStrings(TextName.ItemNames), + Moves = moveNames, + Types = ROM.GetStrings(TextName.Types), + Species = ROM.GetStrings(TextName.SpeciesNames), + ZukanA = ROM.GetStrings(TextName.PokedexEntry1), + ZukanB = ROM.GetStrings(TextName.PokedexEntry2), + TMIndexes = Legal.TMHM_SWSH, + }; + + var result = pd.Dump(pt); + + var outname = GetPath("Pokemon.txt"); + File.WriteAllLines(outname, result); + + var learnTable = pd.MoveSpeciesLearn; + var outLearn = GetPath("MovePerPokemon.txt"); + var moveLines = learnTable.Select((z, i) => $"{i:000}\t{moveNames[i]}\t{string.Join(", ", z.Distinct())}"); + File.WriteAllLines(outLearn, moveLines); + + DumpMoveUsers(pt, lr); + } + + private void DumpMoveUsers(IPersonalTable pt, Learnset8a lr) + { + List Users = new(); + var moves = ROM.GetStrings(TextName.MoveNames); + var spec = ROM.GetStrings(TextName.SpeciesNames); + var shop = Legal.MoveShop8_LA; + for (int i = 0; i < moves.Length; i++) + { + var move = i; + var shopIndex = Array.IndexOf(shop, move); + bool isShop = shopIndex != -1; + var learn = lr.Table.Where(z => z.Arceus.Any(x => x.Move == move)); + var filtered = learn.Where(z => ((IPersonalInfoPLA)pt.GetFormEntry(z.Species, (byte)z.Form)).IsPresentInGame); + var result = filtered.Select(x => GetSpeciesMove(spec, x, move)).ToArray(); + + List r = new() { $"{moves[move]}:" }; + if (isShop) + { + var species = pt.Table.OfType().Where(z => z.SpecialTutors[0][shopIndex] && z.IsPresentInGame); + var names = species.Select(z => $"{spec[z.ModelID]}{(z.Form == 0 ? "" : $"-{z.Form}")}"); + r.Add($"\tTutors: {string.Join(", ", names)}"); + } + + var lv = result.Length == 0 ? "None." : string.Join(", ", result); + r.Add($"\tLevel Up: {lv}"); + Users.AddRange(r); + } + + var outname = GetPath("MoveUsers.txt"); + File.WriteAllLines(outname, Users); + } + + private static string GetSpeciesMove(string[] spec, Learnset8aMeta x, int move) + { + var learnset = Array.Find(x.Arceus, w => w.Move == move); + var level = learnset is null ? "INVALID" : learnset.Level.ToString(); + return $"{spec[x.Species]}{(x.Form == 0 ? "" : $"-{x.Form}")} @ {level}"; + } + + private static readonly string[] ahtbext = { ".tbl", ".hsh" }; + + public void DumpAHTB() + { + var files = Directory.EnumerateFiles(ROM.PathRomFS, "*", SearchOption.AllDirectories) + .Where(z => ahtbext.Contains(Path.GetExtension(z))); + + var result = new HashSet(); + var list = new List(); + var gf = new List(); + foreach (var f in files) + { + var bytes = File.ReadAllBytes(f); + if (AHTB.IsAHTB(bytes)) + { + var tbl = new AHTB(bytes); + var summaries = tbl.Summary; + foreach (var t in tbl.ShortSummary) + result.Add(t); + list.Add(Path.GetFileName(f)); + list.AddRange(summaries); + } + else if (DatTable.IsDatTable(bytes)) + { + var tbl = new DatTable(bytes); + var summaries = tbl.Summary; + foreach (var t in tbl.ShortSummary) + result.Add(t); + list.Add(Path.GetFileName(f)); + list.AddRange(summaries); + } + } + + var paks = Directory.EnumerateFiles(ROM.PathRomFS, "*", SearchOption.AllDirectories) + .Where(z => Path.GetExtension(z) == ".gfpak"); + foreach (var f in paks) + { + var pak = new GFPack(f); + foreach (var bytes in pak.DecompressedFiles) + { + if (!AHTB.IsAHTB(bytes)) + continue; + + var tbl = new AHTB(bytes); + var summaries = tbl.Summary; + foreach (var t in tbl.ShortSummary) + result.Add(t); + list.Add(Path.GetFileName(f)); + list.AddRange(summaries); + } + + for (var i = 0; i < pak.HashAbsolute.Length; i++) + { + var x = pak.HashAbsolute[i]; + gf.Add($"{x.HashFnv1aPathFull:X16}\t{f}.Absolute[{i}]"); + } + + for (var i = 0; i < pak.HashInFolder.Length; i++) + { + var x = pak.HashInFolder[i]; + var folder = x.Folder; + gf.Add($"{folder.HashFnv1aPathFolderName:X16}\t{f}.Folder[{i}] ({folder.FileCount})"); + for (int j = 0; j < x.Files.Length; j++) + { + var y = x.Files[j]; + gf.Add($"{y.HashFnv1aPathFileName:X16}\t{f}.Folder[{i}][{j}] ({y.Index})"); + } + } + } + + var outname = GetPath("ahtb.txt"); + var outname2 = GetPath("ahtblist.txt"); + var outname3 = GetPath("gfpakhash.txt"); + File.WriteAllLines(outname, result); + File.WriteAllLines(outname2, list); + File.WriteAllLines(outname3, gf); + } + + public void DumpDrops() + { + var names = ROM.GetStrings(TextName.ItemNames); + var field = Path.Combine(ROM.PathRomFS, "bin", "pokemon", "data", "poke_drop_item.bin"); + var fieldItems = FlatBufferConverter.DeserializeFrom(field).Table.Select(z => z.Dump(names)); + File.WriteAllLines(GetPath("DropItems.txt"), fieldItems); + + var battle = Path.Combine(ROM.PathRomFS, "bin", "pokemon", "data", "poke_drop_item_battle.bin"); + var battleItems = FlatBufferConverter.DeserializeFrom(battle).Table.Select(z => z.Dump(names)); + File.WriteAllLines(GetPath("BattleDropItems.txt"), battleItems); + } + + public void DumpItems() + { + var items = ROM.GetFile(GameFile.ItemStats); + var file = items[0]; + var array = Item8a.GetArray(file); + var groups = array.GroupBy(z => z.Pouch); + foreach (var g in groups) + { + var key = g.Key; + var IDs = g.Where(z => z.ItemSprite >= 0).Select(z => z.ItemID); + var path = GetPath($"{key}.txt"); + File.WriteAllText(path, string.Join(", ", IDs.Select(z => $"{z:000}"))); + } + + var names = ROM.GetStrings(TextName.ItemNames); + var lines = TableUtil.GetNamedTypeTable(array, names, "Items"); + var table = GetPath("ItemData.txt"); + var bin = GetPath("ItemData.bin"); + File.WriteAllText(table, lines); + File.WriteAllBytes(bin, array.SelectMany(z => z.Data).ToArray()); + } + + public void DumpMoves() + { + var dir = Path.Combine(ROM.PathRomFS, "bin", "pml", "waza"); + var files = Directory.GetFiles(dir); + var moves = FlatBufferConverter.DeserializeFrom(files); + var names = ROM.GetStrings(TextName.MoveNames); + var lines = TableUtil.GetNamedTypeTable(moves, names, "Moves"); + var table = GetPath("MoveData.txt"); + File.WriteAllText(table, lines); + + var pp = moves.Select(z => z.FPP); + var str = string.Join(", ", pp.Select(z => $"{z:00}")); + var pppath = GetPath("MovePP.txt"); + File.WriteAllText(pppath, str); + + // get dummied moves + var moveNames = ROM.GetStrings(TextName.MoveNames); + var moveDesc = ROM.GetStrings(TextName.MoveFlavor); + + var tuple = moveNames + .Select((z, i) => new { Name = z, Desc = moveDesc[i], Index = i }) + .Where(z => !moves[z.Index].CanUseMove) + .Select(z => $"{z.Index:000}\t{z.Name}"); + + var path = GetPath("snappedMoves.txt"); + File.WriteAllLines(path, tuple); // rest in peace + + var snap2 = GetPath("snappedID.txt"); + var snapMove = string.Join(", ", moves.Where(z => !z.CanUseMove).Select(z => $"{z.MoveID:000}")); + File.WriteAllText(snap2, snapMove); + } + + public void DumpLearnsetBinary() + { + var data = ROM.GetFile(GameFile.Learnsets)[0]; + var obj = FlatBufferConverter.DeserializeFrom(data); + var pt = new PersonalTable8LA(ROM.GetFile(GameFile.PersonalStats)); + var result = new byte[pt.Table.Length][]; + var mastery = new byte[pt.Table.Length][]; + for (int i = 0; i < result.Length; i++) + result[i] = mastery[i] = Array.Empty(); + + var Dupes = new List<(int Species, int Form)>(); + foreach (var e in obj.Table) + { + if (e.Arceus.Length == 0) + continue; + var index = pt.GetFormIndex(e.Species, (byte)e.Form); + var entry = (IPersonalInfoPLA)pt[index]; + if (!entry.IsPresentInGame) + continue; + result[index] = e.WriteLearnsetAsLearn6(); + mastery[index] = e.WriteMasteryAsLearn6(); + + if (e.Arceus.Select(z => z.Level).Distinct().Count() != e.Arceus.Length) + Dupes.Add(new(e.Species, e.Form)); + } + + // Learnset + { + var mini = MiniUtil.PackMini(result, "la"); + var bin = GetPath(Path.Combine("bin", "lvlmove_la.pkl")); + File.WriteAllBytes(bin, mini); + } + // Mastery + { + var mini = MiniUtil.PackMini(mastery, "la"); + var bin = GetPath(Path.Combine("bin", "mastery_la.pkl")); + File.WriteAllBytes(bin, mini); + } + // Dupes + { + var txt = GetPath(Path.Combine("bin", "lvlmove_dupes.txt")); + File.WriteAllLines(txt, Dupes.Select(z => $"{(Species)z.Species}{(z.Form == 0 ? "" : $"{z.Form}")}")); + } + } + + public void DumpEvolutionBinary() + { + // format matches past gen and PKHeX's expected format + var data = ROM.GetFilteredFolder(GameFile.Evolutions)[0]; + var obj = FlatBufferConverter.DeserializeFrom(data); + var pt = new PersonalTable8LA(ROM.GetFile(GameFile.PersonalStats)); + var result = new byte[pt.Table.Length][]; + for (int i = 0; i < result.Length; i++) + result[i] = Array.Empty(); + + for (var i = 0; i < obj.Table.Length; i++) + { + var e = obj.Table[i]; + if (e.Table?.Length is not > 0) + continue; + var index = pt.GetFormIndex(e.Species, (byte)e.Form); + var entry = (IPersonalInfoPLA)pt[index]; + if (!entry.IsPresentInGame) + continue; + result[index] = e.Write(); + } + + var mini = MiniUtil.PackMini(result, "la"); + var bin = GetPath(Path.Combine("bin", "evos_la.pkl")); + File.WriteAllBytes(bin, mini); + } + + public void DumpGifts() + { + var speciesNames = ROM.GetStrings(TextName.SpeciesNames); + var data = ROM.GetFile(GameFile.EncounterGift)[0]; + var gifts = FlatBufferConverter.DeserializeFrom(data); + var table = TableUtil.GetTable(gifts.Table); + var fn = GetPath("Gifts.txt"); + File.WriteAllText(fn, table); + + var f2 = GetPath("GiftsPKHeX.txt"); + File.WriteAllLines(f2, gifts.Table.Select(z => z.Dump(speciesNames))); + } + + public void DumpStatic() + { + var speciesNames = ROM.GetStrings(TextName.SpeciesNames); + var data = ROM.GetFile(GameFile.EncounterStatic)[0]; + var statics = FlatBufferConverter.DeserializeFrom(data); + + var lines = new List(); + + foreach (var set in statics.Table) + { + lines.Add($"{set.EncounterName}:"); + + var table = TableUtil.GetTable(set.Table); + + foreach (var line in table.Split(new[] { Environment.NewLine }, StringSplitOptions.None)) + lines.Add($"\t{line}"); + } + + var fn = GetPath("StaticEncounters.txt"); + File.WriteAllLines(fn, lines); + + var f2 = GetPath("StaticEncountersPKHeX.txt"); + File.WriteAllLines(f2, statics.Table.SelectMany(z => z.Table.Select(x => x.Dump(speciesNames, z.EncounterName))).OrderBy(z => z)); + } + + public void DumpWilds() + { + var speciesName = ROM.GetStrings(TextName.SpeciesNames); + + Dictionary map = GetPlaceNameMap(); + var multdata = ROM.GetFile(GameFile.EncounterRateTable)[0]; + var multipliers = FlatBufferConverter.DeserializeFrom(multdata); + var miscdata = ROM.GetFile(GameFile.PokeMisc)[0]; + var misc = FlatBufferConverter.DeserializeFrom(miscdata); + + var nhoGroup_b = ROM.GetFile(GameFile.NewHugeGroup)[0]; + var nhoGroup = FlatBufferConverter.DeserializeFrom(nhoGroup_b); + var nhoGroupL_b = ROM.GetFile(GameFile.NewHugeGroupLottery)[0]; + var nhoGroupL = FlatBufferConverter.DeserializeFrom(nhoGroupL_b); + + var resident = (GFPack)ROM.GetFile(GameFile.Resident); + var bin_settings = resident.GetDataFullPath("bin/field/resident/AreaSettings.bin"); + var settings = FlatBufferConverter.DeserializeFrom(bin_settings); + + const string wild = "wild"; + Directory.CreateDirectory(GetPath(wild)); + + var all = new List(); + var allUnownLines = new List(); + var allUnownLinesBias = new List(); + const float bias = 20; + + var hexBin = new List(); + var allSlots = new List(); + var allSpawners = new List(); + var allWormholes = new List(); + var allLocations = new List(); + var allLandItems = new List(); + var allLandMarks = new List(); + var allUnown = new List(); + var allMkrg = new List(); + var allSearchItem = new List(); + foreach (var areaNameList in ResidentAreaSet.AreaNames) + { + var instance = AreaInstance8a.Create(resident, areaNameList, settings); + var lines = EncounterTable8aUtil.GetLines(multipliers, misc, speciesName, instance, nhoGroup, nhoGroupL, map).ToList(); + File.WriteAllLines(GetPath(wild, $"Encounters_{instance.AreaName}.txt"), lines); + + var unown = EncounterTable8aUtil.GetUnownLines(instance, map).Distinct().ToList(); + File.WriteAllLines(GetPath(wild, $"unown_0_{instance.AreaName}.txt"), unown); + var unownBias = EncounterTable8aUtil.GetUnownLinesBias(instance, map, bias).Distinct().ToList(); + File.WriteAllLines(GetPath(wild, $"unown_{bias:0}_{instance.AreaName}.txt"), unownBias); + allUnownLines.AddRange(unown); + allUnownLinesBias.AddRange(unownBias); + + var slices = EncounterTable8aUtil.GetEncounterDump(instance, map, misc, nhoGroup, nhoGroupL); + foreach (var s in slices) + { + if (!hexBin.Any(z => z.SequenceEqual(s))) + hexBin.Add(s); + } + + all.AddRange(lines); + all.Add(string.Empty); + + allSlots.AddRange(instance.Encounters.SelectMany(z => z.Table)); + allSpawners.AddRange(instance.Spawners); + allWormholes.AddRange(instance.Wormholes); + allLocations.AddRange(instance.Locations); + allLandItems.AddRange(instance.LandItems); + allLandMarks.AddRange(instance.LandMarks); + allUnown.AddRange(instance.Unown); + allMkrg.AddRange(instance.Mikaruge); + allSearchItem.AddRange(instance.SearchItem); + + foreach (var subArea in instance.SubAreas) + { + allSlots.AddRange(subArea.Encounters.SelectMany(z => z.Table)); + allSpawners.AddRange(subArea.Spawners); + allWormholes.AddRange(subArea.Wormholes); + allLocations.AddRange(subArea.Locations); + allLandItems.AddRange(subArea.LandItems); + allLandMarks.AddRange(subArea.LandMarks); + allUnown.AddRange(subArea.Unown); + allMkrg.AddRange(subArea.Mikaruge); + allSearchItem.AddRange(subArea.SearchItem); + } + } + + var mini = MiniUtil.PackMini(hexBin.ToArray(), "la"); + File.WriteAllBytes(GetPath(wild, "encounter_la.pkl"), mini); + File.WriteAllLines(GetPath(wild, "Encounters_All.txt"), all); + File.WriteAllLines(GetPath(wild, "Unown_All.txt"), allUnownLines); + File.WriteAllLines(GetPath(wild, $"Unown_All_Bias_{bias}.txt"), allUnownLinesBias); + + File.WriteAllText(GetPath(wild, "allMultipliers.csv"), TableUtil.GetTable(multipliers.Table)); + File.WriteAllText(GetPath(wild, "PokeMisc.csv"), TableUtil.GetTable(misc.Table)); + File.WriteAllText(GetPath(wild, "allSlotTable.csv"), TableUtil.GetTable(allSlots)); + File.WriteAllText(GetPath(wild, "allSpawnerTable.csv"), TableUtil.GetTable(allSpawners)); + File.WriteAllText(GetPath(wild, "allWormholeTable.csv"), TableUtil.GetTable(allWormholes)); + File.WriteAllText(GetPath(wild, "allLocationTable.csv"), TableUtil.GetTable(allLocations)); + File.WriteAllText(GetPath(wild, "allLandMarks.csv"), TableUtil.GetTable(allLandMarks)); + File.WriteAllText(GetPath(wild, "allLandMarkSpawns.csv"), TableUtil.GetTable(allLandItems)); + File.WriteAllText(GetPath(wild, "allUnown.csv"), TableUtil.GetTable(allUnown)); + File.WriteAllText(GetPath(wild, "allMkrg.csv"), TableUtil.GetTable(allMkrg)); + File.WriteAllText(GetPath(wild, "allSearchItem.csv"), TableUtil.GetTable(allSearchItem)); + } + + public void DumpResident() + { + var resident = (GFPack)ROM.GetFile(GameFile.Resident); + var bin_settings = resident.GetDataFullPath("bin/field/resident/AreaSettings.bin"); + var settings = FlatBufferConverter.DeserializeFrom(bin_settings); + var dir = GetPath("Resident"); + var props = typeof(AreaSettings8a).GetProperties(); + foreach (var x in settings.Table) + { + foreach (var p in props) + { + var value = p.GetValue(x); + if (value is not string { Length: not 0 } s) + continue; + if (!s.Contains('/')) + continue; + if (File.Exists(Path.Combine(ROM.PathRomFS, s))) + continue; + + try + { + int index = resident.GetIndexFull(FnvHash.HashFnv1a_64(s)); + if (index == -1) + continue; + var data = resident.GetDataFullPath(s); + var file = s.Replace('/', '\\'); + var dest = Path.Combine(dir, file); + var folder = Path.GetDirectoryName(dest); + if (folder is null) + throw new Exception($"Unable to get directory name of {dest}"); + + Directory.CreateDirectory(folder); + File.WriteAllBytes(dest, data); + } + catch + { + } + } + } + } + + public void DumpPlacement() + { + var resident = (GFPack)ROM.GetFile(GameFile.Resident); + var bin_settings = resident.GetDataFullPath("bin/field/resident/AreaSettings.bin"); + var settings = FlatBufferConverter.DeserializeFrom(bin_settings); + + Dictionary map = GetPlaceNameMap(); + + var location_all = new List(); + var spawner_all = new List(); + var wh_spawner_all = new List(); + var mkrg_all = new List(); + const string placement = "placement"; + Directory.CreateDirectory(GetPath(placement)); + + foreach (var areaNameList in ResidentAreaSet.AreaNames) + { + var area = AreaInstance8a.Create(resident, areaNameList, settings); + foreach (var subArea in new[] { area }.Concat(area.SubAreas)) + { + var areaName = subArea.AreaName; + if (subArea.Locations.Length != 0) + { + var loc_lines = GetLocationBoundLines(areaName, map, subArea.Locations); + + location_all.AddRange(loc_lines); + location_all.Add(string.Empty); + File.WriteAllLines(GetPath(placement, $"Location_{areaName}.txt"), loc_lines); + } + if (subArea.Spawners.Length != 0) + { + var spwn_lines = GetSpawnLines(areaName, map, subArea.Spawners, subArea.Locations); + + spawner_all.AddRange(spwn_lines); + spawner_all.Add(string.Empty); + File.WriteAllLines(GetPath(placement, $"Spawner_{areaName}.txt"), spwn_lines); + } + if (subArea.Wormholes.Length != 0) + { + var spwn_lines = GetSpawnLines(areaName, map, subArea.Wormholes, subArea.Locations); + + wh_spawner_all.AddRange(spwn_lines); + wh_spawner_all.Add(string.Empty); + File.WriteAllLines(GetPath(placement, $"WhSpawner_{areaName}.txt"), spwn_lines); + } + if (subArea.Mikaruge.Length != 0) + { + var mkrg_lines = GetMikarugeLines(areaName, map, subArea.Mikaruge, subArea.Locations); + + mkrg_all.AddRange(mkrg_lines); + mkrg_all.Add(string.Empty); + File.WriteAllLines(GetPath(placement, $"Mikaruge_{areaName}.txt"), mkrg_lines); + } + if (subArea.SearchItem.Length != 0) + { + var mkrg_lines = GetSearchItemLines(areaName, map, subArea.SearchItem, subArea.Locations); + + mkrg_all.AddRange(mkrg_lines); + mkrg_all.Add(string.Empty); + File.WriteAllLines(GetPath(placement, $"SearchItem_{areaName}.txt"), mkrg_lines); + } + + // Debug for Visualization + if (new[] { "ha_area01", "ha_area02", "ha_area03", "ha_area04", "ha_area05" }.Contains(areaName)) + DumpVisualizationData(area); + } + } + + File.WriteAllLines(GetPath(placement, "Location_all.txt"), location_all); + File.WriteAllLines(GetPath(placement, "Spawner_all.txt"), spawner_all); + File.WriteAllLines(GetPath(placement, "WhSpawner_all.txt"), wh_spawner_all); + File.WriteAllLines(GetPath(placement, "Mikaruge_all.txt"), mkrg_all); + } + + private Dictionary GetPlaceNameMap() + { + var map = new Dictionary(); + var place_names = ROM.GetStrings(TextName.metlist_00000); + + var scriptFolder = new FolderContainer(((FolderContainer)ROM.GetFile(GameFile.StoryText)).FilePath!); + scriptFolder.Initialize(); + + var locationNames = scriptFolder.GetFileData("place_name.tbl")!; + var ahtb = new AHTB(locationNames); + for (var i = 0; i < place_names.Length; i++) + map[ahtb.Entries[i].Name] = (place_names[i], i); + return map; + } + + private static IReadOnlyList GetLocationBoundLines(string areaName, + IReadOnlyDictionary map, + IEnumerable locations) + { + var result = new List { $"Area: {areaName}" }; + foreach (var location in locations) + { + string line = $"\t{location}"; + if (location.IsNamedPlace) + { + var (name, index) = map[location.PlaceName]; + line += $" // {index}, \"{name}\""; + } + result.Add(line); + } + return result; + } + + private static IReadOnlyList GetSpawnLines(string areaName, + IReadOnlyDictionary map, + IEnumerable spawners, + IReadOnlyList locations) + { + var result = new List { $"Area: {areaName}" }; + foreach (var spawner in spawners) + { + var contained = GetNearbyLocationNames(spawner, locations, map); + result.Add($"\t{spawner} // Containing Locations: {contained}"); + } + return result; + } + + private static IReadOnlyList GetMikarugeLines(string areaName, + IReadOnlyDictionary map, + IEnumerable mkrgs, + IReadOnlyList locations) + { + var result = new List { $"Area: {areaName}" }; + foreach (var mkrg in mkrgs) + { + var contained = GetNearbyLocationNames(mkrg, locations, map); + result.Add($"\t{mkrg} // Containing Locations: {contained}"); + } + return result; + } + + private static IReadOnlyList GetSearchItemLines(string areaName, + IReadOnlyDictionary map, + IEnumerable mkrgs, + IReadOnlyList locations) + { + var result = new List { $"Area: {areaName}" }; + foreach (var psi in mkrgs) + { + var contained = GetNearbyLocationNames(psi, locations, map); + result.Add($"\t{psi} // Containing Locations: {contained}"); + } + return result; + } + + private static string GetNearbyLocationNames(PlacementSpawner8a spawner, + IReadOnlyList locations, + IReadOnlyDictionary map) + { + var containedBy = spawner.GetContainingLocations(locations); + var placeNames = containedBy.Select(z => z.PlaceName).Distinct(); + var localized = placeNames.Select(pn => map[pn].Name); + return string.Join(", ", localized); + } + + private static string GetNearbyLocationNames(PlacementSearchItem mkrg, + IReadOnlyList locations, + IReadOnlyDictionary map) + { + var containedBy = mkrg.GetContainingLocations(locations); + var placeNames = containedBy.Select(z => z.PlaceName).Distinct(); + var localized = placeNames.Select(pn => map[pn].Name); + return string.Join(", ", localized); + } + + private static string GetNearbyLocationNames(PlacementMkrgEntry mkrg, + IReadOnlyList locations, + IReadOnlyDictionary map) + { + var containedBy = mkrg.GetContainingLocations(locations); + var placeNames = containedBy.Select(z => z.PlaceName).Distinct(); + var localized = placeNames.Select(pn => map[pn].Name); + return string.Join(", ", localized); + } + + private void DumpVisualizationData(AreaInstance8a area) + { + var vis_lines = new List { "LOCS = [" }; + + const string folder = "placementVis"; + Directory.CreateDirectory(GetPath(folder)); + + foreach (var loc in area.Locations) + { + if (!loc.IsNamedPlace) + continue; + vis_lines.Add($"({loc.Parameters.Coordinates.ToTriple()}, {loc.Parameters.Rotation.ToTriple()}, {loc.ShapeSummary.Replace("/* Shape = */ ", "")}, {loc.SizeX}, {loc.SizeY}, {loc.SizeZ}, \"{loc.PlaceName}\"), "); + } + + vis_lines.Add("]"); + vis_lines.Add(string.Empty); + + vis_lines.Add("SPAWNERS = ["); + foreach (var spwn in area.Spawners) + vis_lines.Add($"({spwn.Parameters.Coordinates.ToTriple()}, {spwn.Scalar}),"); + vis_lines.Add("]"); + vis_lines.Add(string.Empty); + + vis_lines.Add("WH_SPAWNERS = ["); + foreach (var spwn in area.Wormholes) + vis_lines.Add($"({spwn.Parameters.Coordinates.ToTriple()}, {spwn.Scalar}),"); + + vis_lines.Add("LANDMARKS = ["); + foreach (var spwn in area.LandMarks) + vis_lines.Add($"({spwn.Parameters.Coordinates.ToTriple()}, {spwn.Scalar}),"); + + vis_lines.Add("]"); + vis_lines.Add(string.Empty); + + File.WriteAllLines(GetPath(folder, $"Vis_{area.AreaName}.txt"), vis_lines); + } + + public void DumpOutbreak() + { + var file = ROM.GetFile(GameFile.Outbreak).FilePath; + var result = FlatDumper.GetTable(file!); + File.WriteAllText(GetPath("massOutbreak.txt"), result); + + var arr = FlatBufferConverter.DeserializeFrom(file!).Table; + var cache = new DataCache(arr); + var names = Enumerable.Range(0, cache.Length).Select(z => $"{z}").ToArray(); + var form = new GenericEditor(cache, names, "Outbreak"); + form.ShowDialog(); + } + + public void DumpDex() + { + DumpDexSummarySpecies(); + + var dexResearchPath = Path.Combine(ROM.PathRomFS, "bin", "appli", "pokedex", "res_table", "pokedex_research_task_table.bin"); + var dexResearchBin = File.ReadAllBytes(dexResearchPath); + var dexResearch = FlatBufferConverter.DeserializeFrom(dexResearchBin); + + var csv = GetPath("pokedex_research.csv"); + File.WriteAllText(csv, TableUtil.GetTable(dexResearch.Table)); + + // Pokedex Research for PKHeX + DumpResearchTasks(dexResearch); + } + + private void DumpResearchTasks(PokedexResearchTable dexResearch) + { + var pt = new PersonalTable8LA(ROM.GetFile(GameFile.PersonalStats)); + var result = new byte[pt.Table.Max(p => p.DexIndexRegional)][]; + for (int i = 0; i < result.Length; i++) + result[i] = Array.Empty(); + + ushort GetDexIndex(ushort species) + { + var formCount = pt.GetFormEntry(species, 0).FormCount; + for (byte form = 0; form < formCount; form++) + { + var p = (IPersonalInfoPLA)pt.GetFormEntry(species, form); + + if (p.DexIndexRegional != 0) + return p.DexIndexRegional; + } + + return 0; + } + + for (ushort species = 0; species <= 980; species++) + { + var entries = Array.FindAll(dexResearch.Table, z => z.Species == species); + if (entries.Length == 0) + continue; + + var dexInd = GetDexIndex(species); + if (dexInd == 0) + throw new ArgumentException($"Research tasks exist for species {species} not in dex?"); + + if (result[dexInd - 1].Length != 0) + throw new ArgumentException($"Two species share dex index {dexInd}?"); + + using var ms = new MemoryStream(); + using var br = new BinaryWriter(ms); + + var moveTaskIndex = 0; + var defeatTypeTaskIndex = 0; + + foreach (var task in entries) + { + var type = task.MoveType; + var timeOfDay = task.TimeOfDay; + + var curMultiIndex = 0xFF; + + if (task.TaskType == ResearchTaskType.MoveTask) + { + curMultiIndex = moveTaskIndex; + moveTaskIndex++; + } + + if (task.TaskType == ResearchTaskType.DefeatTask) + { + curMultiIndex = defeatTypeTaskIndex; + defeatTypeTaskIndex++; + } + else + { + type = 18; + } + + if (task.TaskType != ResearchTaskType.Unknown_10) + { + timeOfDay = 5; + } + + var thresholds = + new[] { task.Threshold1, task.Threshold2, task.Threshold3, task.Threshold4, task.Threshold5 } + .Where(e => e != 0).ToArray(); + + // 00: u8 task + // 01: u8 points_single + // 02: u8 points_bonus + // 03: u8 threshold + // 04: u16 move + // 06: u8 type + // 07: u8 time of day + // 08: u64 hash_06 + // 10: u64 hash_07 + // 18: u64 hash_08 + // 20: u8 num_thresholds + // 21: u8 thresholds[5] + // 26: u8 required + // 27: u8 multi_index + + br.Write((byte)task.TaskType); + br.Write((byte)task.PointsSingle); + br.Write((byte)task.PointsBonus); + br.Write((byte)task.Threshold); + br.Write((ushort)task.Move); + br.Write((byte)type); + br.Write((byte)timeOfDay); + br.Write(task.Hash_06); + br.Write(task.Hash_07); + br.Write(task.Hash_08); + + br.Write((byte)thresholds.Length); + for (var i = 0; i < 5; i++) + { + if (i < thresholds.Length) + br.Write((byte)thresholds[i]); + else + br.Write((byte)0); + } + + br.Write((byte)(task.RequiredForCompletion ? 1 : 0)); + br.Write((byte)curMultiIndex); + } + + result[dexInd - 1] = ms.ToArray(); + } + + var mini = MiniUtil.PackMini(result, "la"); + var bin = GetPath(Path.Combine("bin", "researchtask_la.pkl")); + File.WriteAllBytes(bin, mini); + } + + private void DumpDexSummarySpecies() + { + var pt = new PersonalTable8LA(ROM.GetFile(GameFile.PersonalStats)); + var s = ROM.GetStrings(TextName.SpeciesNames); + + var dex = new List(); + var dexit = new List(); + var foreign = new List(); + for (int i = 1; i < pt.Table.Length; i++) + { + var p = (IPersonalInfoPLA)pt[i]; + bool any = false; + var specForm = $"{p.ModelID:000}\t{p.Form}\t{s[p.ModelID]}{(p.Form == 0 ? "" : $"-{p.Form:00}")}"; + if (p.DexIndexRegional != 0) + { + dex.Add($"{p.DexIndexRegional:000}\t{specForm}"); + any = true; + } + + if (!p.IsPresentInGame) + dexit.Add(specForm); + else if (!any) + foreign.Add(specForm); + } + + var path = GetPath("Dex.txt"); + File.WriteAllLines(path, dex.OrderBy(z => z)); + + var path4 = GetPath("Dexit.txt"); + File.WriteAllLines(path4, dexit); + + var path5 = GetPath("Foreign.txt"); + File.WriteAllLines(path5, foreign); + } + + public void DumpFlavorText() + { + IEnumerable Zip(TextName name, TextName flavor) + { + var n = ROM.GetStrings(name); + var f = ROM.GetStrings(flavor); + return n.Select((z, i) => $"{z}\t{f[i].Replace("\\n", " ")}"); + } + + var p1 = GetPath("ItemFlavor.txt"); + var p2 = GetPath("MoveFlavor.txt"); + var p3 = GetPath("AbilityFlavor.txt"); + + var l1 = Zip(TextName.ItemNames, TextName.ItemFlavor); + var l2 = Zip(TextName.MoveNames, TextName.MoveFlavor); + var l3 = Zip(TextName.AbilityNames, TextName.AbilityFlavor); + + File.WriteAllLines(p1, l1); + File.WriteAllLines(p2, l2); + File.WriteAllLines(p3, l3); + } + + private static readonly string[] LanguageCodes = { "ja", "en", "fr", "it", "de", "es", "ko", "zh", "zh2" }; + + private static readonly string[] LanguageNames = + { + "カタカナ", + "漢字", + "English", + "Français", + "Italiano", + "Deutsch", + "Español", + "한국", + "汉字简化方案", + "漢字簡化方案", + }; + + private void ChangeLanguage(int index) + { + ROM.Language = index; + ROM.ResetText(); + } + + public void DumpStrings() + { + int lang = ROM.Language; + var indexes = new[] { 0, 2, 3, 4, 5, 6, 7, 8, 9 }; + for (int i = 0; i < indexes.Length; i++) + { + var code = LanguageCodes[i]; + var name = LanguageNames[i]; + var index = indexes[i]; + + DumpStrings(code, name, index); + } + ChangeLanguage(lang); + } + + private void DumpStrings(string code, string name, int index) + { + Console.WriteLine($"Dumping strings for {name}."); + ChangeLanguage(index); + + DumpStringSet(TextName.MoveNames, "Moves"); + DumpStringSet(TextName.ItemNames, "Items"); + DumpStringSet(TextName.SpeciesNames, "Species"); + DumpStringSet(TextName.AbilityNames, "Abilities"); + DumpStringSet(TextName.metlist_00000, "la_00000"); + DumpStringSet(TextName.metlist_30000, "la_30000"); + DumpStringSet(TextName.metlist_40000, "la_40000"); + DumpStringSet(TextName.metlist_60000, "la_60000"); + DumpStringSet(TextName.Forms, "forms"); + + void DumpStringSet(TextName t, string file) + { + var strings = ROM.GetStrings(t); + var fn = $"text_{file}_{code}.txt"; + + var folder = Path.Combine(code, fn); + + var path = GetPath(folder); + File.WriteAllLines(path, strings); + } + } + + public void DumpScriptID() + { + var file = Path.Combine(ROM.PathRomFS, "bin", "event", "script_id_record_release.bin"); + var text = FlatDumper.GetTable(file); + var path = GetPath("scriptCommands.txt"); + File.WriteAllText(path, text); + } + + public void DumpEventTriggers() + { + var eventTriggerDir = Path.Combine(ROM.PathRomFS, "bin", "event", "event_progress", "trigger"); + var eventTriggerFiles = Directory.EnumerateFiles(eventTriggerDir, "*", SearchOption.AllDirectories).Where(p => Path.GetExtension(p) == ".bin"); + + const string outFolder = "event_trigger"; + Directory.CreateDirectory(GetPath(outFolder)); + + var unknownTriggers = new List(); + var unknownConditions = new List(); + var unknownCommands = new List(); + + var allLines = new List(); + + foreach (var f in eventTriggerFiles) + { + if (Path.GetFileName(f) == "trigger_preset.bin") + continue; + + var table = FlatBufferConverter.DeserializeFrom(f); + + var curLines = new List { $"File: {Path.GetFileName(f)}" }; + + foreach (var line in Trigger8aUtil.GetTriggerTableSummary(table)) + curLines.Add($"\t{line}"); + + File.WriteAllLines(GetPath(outFolder, $"trigger_{Path.GetFileNameWithoutExtension(f).Replace("trigger_", string.Empty)}.txt"), curLines); + + allLines.AddRange(curLines); + allLines.Add(string.Empty); + + foreach (var trg in table.Table) + { + if (!Enum.IsDefined(typeof(TriggerType8a), trg.Meta.TriggerTypeID) && !unknownTriggers.Contains((ulong)trg.Meta.TriggerTypeID)) + unknownTriggers.Add((ulong)trg.Meta.TriggerTypeID); + + foreach (var cond in trg.Conditions) + { + if (!Enum.IsDefined(typeof(ConditionType8a), cond.ConditionTypeID) && !unknownConditions.Contains((ulong)cond.ConditionTypeID)) + unknownConditions.Add((ulong)cond.ConditionTypeID); + } + + foreach (var cmd in trg.Commands) + { + if (!Enum.IsDefined(typeof(TriggerCommandType8a), cmd.CommandTypeID) && !unknownCommands.Contains((ulong)cmd.CommandTypeID)) + unknownCommands.Add((ulong)cmd.CommandTypeID); + } + } + } + + File.WriteAllLines(GetPath(outFolder, "triggerAll.txt"), allLines); + + File.WriteAllLines(GetPath(outFolder, "triggerUnknownTypes.txt"), unknownTriggers.OrderBy(x => x).Select(x => $"0x{x:X16},")); + File.WriteAllLines(GetPath(outFolder, "triggerUnknownConditions.txt"), unknownConditions.OrderBy(x => x).Select(x => $"0x{x:X16},")); + File.WriteAllLines(GetPath(outFolder, "triggerUnknownCommands.txt"), unknownCommands.OrderBy(x => x).Select(x => $"0x{x:X16},")); + } + + public void DumpMoveShop() + { + var file = ROM.GetFile(GameFile.MoveShop).FilePath; + var result = FlatDumper.GetTable(file!); + File.WriteAllText(GetPath("MoveShop.csv"), result); + } } diff --git a/pkNX.WinForms/Dumping/GameDumperSWSH.cs b/pkNX.WinForms/Dumping/GameDumperSWSH.cs index 9e696ca4..85ef5616 100644 --- a/pkNX.WinForms/Dumping/GameDumperSWSH.cs +++ b/pkNX.WinForms/Dumping/GameDumperSWSH.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -9,102 +9,144 @@ // ReSharper disable StringLiteralTypo -namespace pkNX.WinForms +namespace pkNX.WinForms; + +public class GameDumperSWSH { - public class GameDumperSWSH + private readonly GameManagerSWSH ROM; + public GameDumperSWSH(GameManagerSWSH rom) => ROM = rom; + public string DumpFolder { - private readonly GameManagerSWSH ROM; - public GameDumperSWSH(GameManagerSWSH rom) => ROM = rom; - public string DumpFolder => Path.Combine(Directory.GetParent(ROM.PathRomFS).FullName, "Dump"); - - private string GetPath(string path) + get { - Directory.CreateDirectory(DumpFolder); - var result = Path.Combine(DumpFolder, path); - Directory.CreateDirectory(Directory.GetParent(result).FullName); // double check :( - return result; + var parent = Directory.GetParent(ROM.PathRomFS); + if (parent is null) + throw new DirectoryNotFoundException($"Unable to find parent directory of {ROM.PathRomFS}"); + return Path.Combine(parent.FullName, "Dump"); } + } - private string GetPath(string parent, string path) + private string GetPath(string path) + { + Directory.CreateDirectory(DumpFolder); + var result = Path.Combine(DumpFolder, path); + var parent = Directory.GetParent(result); + if (parent is null) + throw new DirectoryNotFoundException($"Unable to get parent directory of {result}"); + Directory.CreateDirectory(parent.FullName); // double check :( + return result; + } + + private string GetPath(string parent, string path) + { + Directory.CreateDirectory(DumpFolder); + var result = Path.Combine(DumpFolder, parent, path); + var parent2 = Directory.GetParent(result); + if (parent2 is null) + throw new DirectoryNotFoundException($"Unable to get parent directory of {result}"); + Directory.CreateDirectory(parent2.FullName); // double check :( + return result; + } + + public void DumpDummiedMoves() + { + // get dummied moves + var moveNames = ROM.GetStrings(TextName.MoveNames); + var moveDesc = ROM.GetStrings(TextName.MoveFlavor); + + var dummy = moveDesc[237]; // hidden power is kill + var tuple = moveNames + .Select((z, i) => new { Name = z, Desc = moveDesc[i], Index = i }) + .Where(z => z.Desc == dummy) + .Select(z => $"{z.Index:000}\t{z.Name}"); + + var path = GetPath("snappedMoves.txt"); + File.WriteAllLines(path, tuple); // rest in peace + } + + public void DumpPokeInfo() + { + var s = ROM.GetStrings(TextName.SpeciesNames); + + var eggdata = ROM.GetFilteredFolder(GameFile.EggMoves); + var egg = EggMoves7.GetArray(eggdata.GetFiles().Result); + + var pt = ROM.Data.PersonalData; + var altForms = pt.GetFormList(s); + var entryNames = pt.GetPersonalEntryList(altForms, s, out _, out _); + var moveNames = ROM.GetStrings(TextName.MoveNames); + + var pd = new PersonalDumperSWSH { - Directory.CreateDirectory(DumpFolder); - var result = Path.Combine(DumpFolder, parent, path); - Directory.CreateDirectory(Directory.GetParent(result).FullName); // double check :( - return result; - } + Colors = Enum.GetNames(typeof(PokeColor)), + EggGroups = Enum.GetNames(typeof(EggGroup)), + EntryEggMoves = egg, + EntryLearnsets = ROM.Data.LevelUpData.LoadAll(), + EntryNames = entryNames, + ExpGroups = Enum.GetNames(typeof(EXPGroup)), + Evos = ROM.Data.EvolutionData.LoadAll(), - public void DumpDummiedMoves() + Abilities = ROM.GetStrings(TextName.AbilityNames), + Items = ROM.GetStrings(TextName.ItemNames), + Moves = moveNames, + Types = ROM.GetStrings(TextName.Types), + Species = ROM.GetStrings(TextName.SpeciesNames), + ZukanA = ROM.GetStrings(TextName.PokedexEntry1), + ZukanB = ROM.GetStrings(TextName.PokedexEntry2), + TMIndexes = Legal.TMHM_SWSH, + }; + + var result = pd.Dump(pt); + + var outname = GetPath("Pokemon.txt"); + File.WriteAllLines(outname, result); + + var learnTable = pd.MoveSpeciesLearn; + var outLearn = GetPath("MovePerPokemon.txt"); + var moveLines = learnTable.Select((z, i) => $"{i:000}\t{moveNames[i]}\t{string.Join(", ", z.Distinct())}"); + File.WriteAllLines(outLearn, moveLines); + } + + private static readonly string[] ahtbext = { ".tbl", ".hsh" }; + + public void DumpAHTB() + { + var files = Directory.EnumerateFiles(ROM.PathRomFS, "*", SearchOption.AllDirectories) + .Where(z => ahtbext.Contains(Path.GetExtension(z))); + + var result = new HashSet(); + var list = new List(); + var gf = new List(); + foreach (var f in files) { - // get dummied moves - var moveNames = ROM.GetStrings(TextName.MoveNames); - var moveDesc = ROM.GetStrings(TextName.MoveFlavor); - - var dummy = moveDesc[237]; // hidden power is kill - var tuple = moveNames - .Select((z, i) => new { Name = z, Desc = moveDesc[i], Index = i }) - .Where(z => z.Desc == dummy) - .Select(z => $"{z.Index:000}\t{z.Name}"); - - var path = GetPath("snappedMoves.txt"); - File.WriteAllLines(path, tuple); // rest in peace - } - - public void DumpPokeInfo() - { - var s = ROM.GetStrings(TextName.SpeciesNames); - - var eggdata = ROM.GetFilteredFolder(GameFile.EggMoves); - var egg = EggMoves7.GetArray(eggdata.GetFiles().Result); - - var pt = ROM.Data.PersonalData; - var altForms = pt.GetFormList(s); - var entryNames = pt.GetPersonalEntryList(altForms, s, out _, out _); - var moveNames = ROM.GetStrings(TextName.MoveNames); - - var pd = new PersonalDumperSWSH + var bytes = File.ReadAllBytes(f); + if (AHTB.IsAHTB(bytes)) { - Colors = Enum.GetNames(typeof(PokeColor)), - EggGroups = Enum.GetNames(typeof(EggGroup)), - EntryEggMoves = egg, - EntryLearnsets = ROM.Data.LevelUpData.LoadAll(), - EntryNames = entryNames, - ExpGroups = Enum.GetNames(typeof(EXPGroup)), - Evos = ROM.Data.EvolutionData.LoadAll(), - - Abilities = ROM.GetStrings(TextName.AbilityNames), - Items = ROM.GetStrings(TextName.ItemNames), - Moves = moveNames, - Types = ROM.GetStrings(TextName.Types), - Species = ROM.GetStrings(TextName.SpeciesNames), - ZukanA = ROM.GetStrings(TextName.PokedexEntry1), - ZukanB = ROM.GetStrings(TextName.PokedexEntry2), - TMIndexes = Legal.TMHM_SWSH, - }; - - var result = pd.Dump(pt); - - var outname = GetPath("Pokemon.txt"); - File.WriteAllLines(outname, result); - - var learnTable = pd.MoveSpeciesLearn; - var outLearn = GetPath("MovePerPokemon.txt"); - var moveLines = learnTable.Select((z, i) => $"{i:000}\t{moveNames[i]}\t{string.Join(", ", z.Distinct())}"); - File.WriteAllLines(outLearn, moveLines); + var tbl = new AHTB(bytes); + var summaries = tbl.Summary; + foreach (var t in tbl.ShortSummary) + result.Add(t); + list.Add(Path.GetFileName(f)); + list.AddRange(summaries); + } + else if (DatTable.IsDatTable(bytes)) + { + var tbl = new DatTable(bytes); + var summaries = tbl.Summary; + foreach (var t in tbl.ShortSummary) + result.Add(t); + list.Add(Path.GetFileName(f)); + list.AddRange(summaries); + } } - private static readonly string[] ahtbext = { ".tbl", ".hsh" }; - - public void DumpAHTB() + var paks = Directory.EnumerateFiles(ROM.PathRomFS, "*", SearchOption.AllDirectories) + .Where(z => Path.GetExtension(z) == ".gfpak"); + foreach (var f in paks) { - var files = Directory.EnumerateFiles(ROM.PathRomFS, "*", SearchOption.AllDirectories) - .Where(z => ahtbext.Contains(Path.GetExtension(z))); - - var result = new HashSet(); - var list = new List(); - var gf = new List(); - foreach (var f in files) + var pak = new GFPack(f); + foreach (var bytes in pak.DecompressedFiles) { - var bytes = File.ReadAllBytes(f); if (AHTB.IsAHTB(bytes)) { var tbl = new AHTB(bytes); @@ -114,554 +156,486 @@ public void DumpAHTB() list.Add(Path.GetFileName(f)); list.AddRange(summaries); } - else if (DatTable.IsDatTable(bytes)) - { - var tbl = new DatTable(bytes); - var summaries = tbl.Summary; - foreach (var t in tbl.ShortSummary) - result.Add(t); - list.Add(Path.GetFileName(f)); - list.AddRange(summaries); - } } - var paks = Directory.EnumerateFiles(ROM.PathRomFS, "*", SearchOption.AllDirectories) - .Where(z => Path.GetExtension(z) == ".gfpak"); - foreach (var f in paks) + for (var i = 0; i < pak.HashAbsolute.Length; i++) { - var pak = new GFPack(f); - foreach (var bytes in pak.DecompressedFiles) - { - if (AHTB.IsAHTB(bytes)) - { - var tbl = new AHTB(bytes); - var summaries = tbl.Summary; - foreach (var t in tbl.ShortSummary) - result.Add(t); - list.Add(Path.GetFileName(f)); - list.AddRange(summaries); - } - } - - for (var i = 0; i < pak.HashAbsolute.Length; i++) - { - var x = pak.HashAbsolute[i]; - gf.Add($"{x.HashFnv1aPathFull:X16}\t{f}.Absolute[{i}]"); - } - - for (var i = 0; i < pak.HashInFolder.Length; i++) - { - var x = pak.HashInFolder[i]; - var folder = x.Folder; - gf.Add($"{folder.HashFnv1aPathFolderName:X16}\t{f}.Folder[{i}] ({folder.FileCount})"); - for (int j = 0; j < x.Files.Length; j++) - { - var y = x.Files[j]; - gf.Add($"{y.HashFnv1aPathFileName:X16}\t{f}.Folder[{i}][{j}] ({y.Index})"); - } - } + var x = pak.HashAbsolute[i]; + gf.Add($"{x.HashFnv1aPathFull:X16}\t{f}.Absolute[{i}]"); } - var outname = GetPath("ahtb.txt"); - var outname2 = GetPath("ahtblist.txt"); - var outname3 = GetPath("gfpakhash.txt"); - File.WriteAllLines(outname, result); - File.WriteAllLines(outname2, list); - File.WriteAllLines(outname3, gf); - } - - public static Dictionary ReadAHTB(byte[] bytes) - { - if (!AHTB.IsAHTB(bytes)) - throw new ArgumentException(); - - var tbl = new AHTB(bytes); - return tbl.ToDictionary(); - } - - private TrainerEditor GetTrainerEditor() - { - var editor = new TrainerEditor + for (var i = 0; i < pak.HashInFolder.Length; i++) { - ReadClass = data => new TrainerClass8(data), - ReadPoke = data => new TrainerPoke8(data), - ReadTrainer = data => new TrainerData8(data), - ReadTeam = TrainerPoke8.ReadTeam, - WriteTeam = TrainerPoke8.WriteTeam, - TrainerData = ROM.GetFilteredFolder(GameFile.TrainerData), - TrainerPoke = ROM.GetFilteredFolder(GameFile.TrainerPoke), - TrainerClass = ROM.GetFilteredFolder(GameFile.TrainerClass), - }; - editor.Initialize(); - return editor; - } - - public void DumpTrainers() - { - var trc = ROM.GetStrings(TextName.TrainerClasses); - var trn = ROM.GetStrings(TextName.TrainerNames); - var m = ROM.GetStrings(TextName.MoveNames); - var s = ROM.GetStrings(TextName.SpeciesNames); - - var tr = GetTrainerEditor(); - var result = new List(); - for (int i = 0; i < tr.Length; i++) - { - var t = tr[i]; - - // some battles with Avery and Klara have out of bounds trclasses -- set back to "Pokémon Trainer" - if (t.Self.Class > trc.Length) - t.Self.Class = 1; - - result.Add($"{i:000} - {trc[t.Self.Class]}: {trn[i]}"); - const int MoneyScalar = 80; - result.Add($"AI: {t.Self.AI} | Mode: {t.Self.Mode} | Money: {t.Self.Money * MoneyScalar}"); - result.Add($"Pokémon Count: {t.Self.NumPokemon}"); - - result.Add("---"); - for (int j = 0; j < t.Team.Count; j++) + var x = pak.HashInFolder[i]; + var folder = x.Folder; + gf.Add($"{folder.HashFnv1aPathFolderName:X16}\t{f}.Folder[{i}] ({folder.FileCount})"); + for (int j = 0; j < x.Files.Length; j++) { - IEnumerable moves = t.Team[j].Moves.Where(z => z != 0).Select(z => m[z]).ToArray(); - if (!moves.Any()) moves = new[] { "Default Level Up" }; - int form = t.Team[j].Form; - var formstr = form != 0 ? $"-{form}" : ""; - var str = $"{j + 1}: Lv{t.Team[j].Level:00} {s[t.Team[j].Species]}{formstr} : {string.Join(" / ", moves)}"; - result.Add(str); + var y = x.Files[j]; + gf.Add($"{y.HashFnv1aPathFileName:X16}\t{f}.Folder[{i}][{j}] ({y.Index})"); } - result.Add("---"); - - result.Add("========="); - result.Add(""); } - - var outname = GetPath("trparse.txt"); - File.WriteAllLines(outname, result); } - public void DumpBattleTower() + var outname = GetPath("ahtb.txt"); + var outname2 = GetPath("ahtblist.txt"); + var outname3 = GetPath("gfpakhash.txt"); + File.WriteAllLines(outname, result); + File.WriteAllLines(outname2, list); + File.WriteAllLines(outname3, gf); + } + + public static Dictionary ReadAHTB(byte[] data) + { + if (!AHTB.IsAHTB(data)) + throw new ArgumentException("Provided data is not an AHTB file", nameof(data)); + + var tbl = new AHTB(data); + return tbl.ToDictionary(); + } + + private TrainerEditor GetTrainerEditor() + { + var editor = new TrainerEditor { - var pk_table_path = ROM.GetFile(GameFile.FacilityPokeNormal)[0]; - var tr_table_path = ROM.GetFile(GameFile.FacilityTrainerNormal)[0]; - var pokes = FlatBufferConverter.DeserializeFrom(pk_table_path); - var trainers = FlatBufferConverter.DeserializeFrom(tr_table_path); + ReadClass = data => new TrainerClass8(data), + ReadPoke = data => new TrainerPoke8(data), + ReadTrainer = data => new TrainerData8(data), + ReadTeam = TrainerPoke8.ReadTeam, + WriteTeam = TrainerPoke8.WriteTeam, + TrainerData = ROM.GetFilteredFolder(GameFile.TrainerData), + TrainerPoke = ROM.GetFilteredFolder(GameFile.TrainerPoke), + TrainerClass = ROM.GetFilteredFolder(GameFile.TrainerClass), + }; + editor.Initialize(); + return editor; + } - var pk = TableUtil.GetTable(pokes.Table); - var tr = TableUtil.GetTable(trainers.Entries); + public void DumpTrainers() + { + var trc = ROM.GetStrings(TextName.TrainerClasses); + var trn = ROM.GetStrings(TextName.TrainerNames); + var m = ROM.GetStrings(TextName.MoveNames); + var s = ROM.GetStrings(TextName.SpeciesNames); - File.WriteAllText(GetPath("towerPoke.txt"), pk); - File.WriteAllText(GetPath("towerTrainer.txt"), tr); - } - - public void DumpItems() + var tr = GetTrainerEditor(); + var result = new List(); + for (int i = 0; i < tr.Length; i++) { - var items = ROM.GetFile(GameFile.ItemStats); - var file = items[0]; - var array = Item8.GetArray(file); - var groups = array.GroupBy(z => z.Pouch); - foreach (var g in groups) + var t = tr[i]; + + // some battles with Avery and Klara have out of bounds trclasses -- set back to "Pokémon Trainer" + if (t.Self.Class > trc.Length) + t.Self.Class = 1; + + result.Add($"{i:000} - {trc[t.Self.Class]}: {trn[i]}"); + const int MoneyScalar = 80; + result.Add($"AI: {t.Self.AI} | Mode: {t.Self.Mode} | Money: {t.Self.Money * MoneyScalar}"); + result.Add($"Pokémon Count: {t.Self.NumPokemon}"); + + result.Add("---"); + for (int j = 0; j < t.Team.Count; j++) { - var key = g.Key; - var IDs = g.Where(z => z.ItemSprite >= 0).Select(z => z.ItemID); - var path = GetPath($"{key}.txt"); - File.WriteAllText(path, string.Join(", ", IDs.Select(z => $"{z:000}"))); + IEnumerable moves = t.Team[j].Moves.Where(z => z != 0).Select(z => m[z]).ToArray(); + if (!moves.Any()) moves = new[] { "Default Level Up" }; + int form = t.Team[j].Form; + var formstr = form != 0 ? $"-{form}" : ""; + var str = $"{j + 1}: Lv{t.Team[j].Level:00} {s[t.Team[j].Species]}{formstr} : {string.Join(" / ", moves)}"; + result.Add(str); } + result.Add("---"); - var names = ROM.GetStrings(TextName.ItemNames); - var lines = TableUtil.GetNamedTypeTable(array, names, "Items"); - var table = GetPath("ItemData.txt"); - var bin = GetPath("ItemData.bin"); - File.WriteAllText(table, lines); - File.WriteAllBytes(bin, array.SelectMany(z => z.Data).ToArray()); + result.Add("========="); + result.Add(""); } - public void DumpMoves() + var outname = GetPath("trparse.txt"); + File.WriteAllLines(outname, result); + } + + public void DumpBattleTower() + { + var pk_table_path = ROM.GetFile(GameFile.FacilityPokeNormal)[0]; + var tr_table_path = ROM.GetFile(GameFile.FacilityTrainerNormal)[0]; + var pokes = FlatBufferConverter.DeserializeFrom(pk_table_path); + var trainers = FlatBufferConverter.DeserializeFrom(tr_table_path); + + var pk = TableUtil.GetTable(pokes.Table); + var tr = TableUtil.GetTable(trainers.Entries); + + File.WriteAllText(GetPath("towerPoke.txt"), pk); + File.WriteAllText(GetPath("towerTrainer.txt"), tr); + } + + public void DumpItems() + { + var items = ROM.GetFile(GameFile.ItemStats); + var file = items[0]; + var array = Item8.GetArray(file); + var groups = array.GroupBy(z => z.Pouch); + foreach (var g in groups) { - var dir = Path.Combine(ROM.PathRomFS, "bin", "pml", "waza"); - var files = Directory.GetFiles(dir); - var moves = FlatBufferConverter.DeserializeFrom(files); - var names = ROM.GetStrings(TextName.MoveNames); - var lines = TableUtil.GetNamedTypeTable(moves, names, "Moves"); - var table = GetPath("MoveData.txt"); - File.WriteAllText(table, lines); + var key = g.Key; + var IDs = g.Where(z => z.ItemSprite >= 0).Select(z => z.ItemID); + var path = GetPath($"{key}.txt"); + File.WriteAllText(path, string.Join(", ", IDs.Select(z => $"{z:000}"))); } - public void DumpLearnsetBinary() + var names = ROM.GetStrings(TextName.ItemNames); + var lines = TableUtil.GetNamedTypeTable(array, names, "Items"); + var table = GetPath("ItemData.txt"); + var bin = GetPath("ItemData.bin"); + File.WriteAllText(table, lines); + File.WriteAllBytes(bin, array.SelectMany(z => z.Data).ToArray()); + } + + public void DumpMoves() + { + var dir = Path.Combine(ROM.PathRomFS, "bin", "pml", "waza"); + var files = Directory.GetFiles(dir); + var moves = FlatBufferConverter.DeserializeFrom(files); + var names = ROM.GetStrings(TextName.MoveNames); + var lines = TableUtil.GetNamedTypeTable(moves, names, "Moves"); + var table = GetPath("MoveData.txt"); + File.WriteAllText(table, lines); + } + + public void DumpLearnsetBinary() + { + var data = ROM.Data.LevelUpData.LoadAll() + .Cast().Select(z => z.WriteAsLearn6()).ToArray(); + var mini = MiniUtil.PackMini(data, "ss"); + var bin = GetPath(Path.Combine("bin", "lvlmove_swsh.pkl")); + File.WriteAllBytes(bin, mini); + } + + public void DumpEggBinary() + { + // format matches past gen and PKHeX's expected format + var data = ROM.GetFilteredFolder(GameFile.EggMoves).GetFiles().Result; + var mini = MiniUtil.PackMini(data, "ss"); + var bin = GetPath(Path.Combine("bin", "eggmove_swsh.pkl")); + File.WriteAllBytes(bin, mini); + } + + public void DumpEvolutionBinary() + { + // format matches past gen and PKHeX's expected format + var data = ROM.GetFilteredFolder(GameFile.Evolutions).GetFiles().Result; + var mini = MiniUtil.PackMini(data, "ss"); + var bin = GetPath(Path.Combine("bin", "evos_ss.pkl")); + File.WriteAllBytes(bin, mini); + } + + public void DumpGifts() + { + var speciesNames = ROM.GetStrings(TextName.SpeciesNames); + var data = ROM.GetFile(GameFile.EncounterGift)[0]; + var gifts = FlatBufferConverter.DeserializeFrom(data); + var table = TableUtil.GetTable(gifts.Table); + var fn = GetPath("Gifts.txt"); + File.WriteAllText(fn, table); + + var f2 = GetPath("GiftsPKHeX.txt"); + File.WriteAllLines(f2, gifts.Table.Select(z => z.GetSummary(speciesNames))); + } + + public void DumpStatic() + { + var speciesNames = ROM.GetStrings(TextName.SpeciesNames); + var data = ROM.GetFile(GameFile.EncounterStatic)[0]; + var statics = FlatBufferConverter.DeserializeFrom(data); + var table = TableUtil.GetTable(statics.Table); + var fn = GetPath("StaticEncounters.txt"); + File.WriteAllText(fn, table); + + var f2 = GetPath("StaticEncountersPKHeX.txt"); + File.WriteAllLines(f2, statics.Table.Select(z => z.GetSummary(speciesNames))); + } + + public void DumpWilds() + { + var wildpak = ROM.GetFile(GameFile.NestData)[0]; + var data_table = new GFPack(wildpak); + var encount_sw = FlatBufferConverter.DeserializeFrom(data_table.GetDataFileName("encount_k.bin")); + var encount_symbol_sw = FlatBufferConverter.DeserializeFrom(data_table.GetDataFileName("encount_symbol_k.bin")); + var encount_sh = FlatBufferConverter.DeserializeFrom(data_table.GetDataFileName("encount_t.bin")); + var encount_symbol_sh = FlatBufferConverter.DeserializeFrom(data_table.GetDataFileName("encount_symbol_t.bin")); + + var species = ROM.GetStrings(TextName.SpeciesNames); + var zones = SWSHInfo.Zones; + var subtables = Enum.GetNames(typeof(SWSHEncounterType)).Select(z => z.Replace("_", " ")).ToArray(); + + File.WriteAllLines(GetPath("Encounters_Sword.txt"), EncounterTable8Util.GetLines(encount_sw, zones, subtables, species)); + File.WriteAllLines(GetPath("Encounters_Symbol_Sword.txt"), EncounterTable8Util.GetLines(encount_symbol_sw, zones, subtables, species)); + File.WriteAllLines(GetPath("Encounters_Shield.txt"), EncounterTable8Util.GetLines(encount_sh, zones, subtables, species)); + File.WriteAllLines(GetPath("Encounters_Symbol_Shield.txt"), EncounterTable8Util.GetLines(encount_symbol_sh, zones, subtables, species)); + + File.WriteAllBytes(GetPath("encounter_sw_hidden.pkl"), MiniUtil.PackMini(EncounterTable8Util.GetBytes(SWSHInfo.ZoneLocations, SWSHInfo.ZoneType, encount_sw, true), "sw")); + File.WriteAllBytes(GetPath("encounter_sh_hidden.pkl"), MiniUtil.PackMini(EncounterTable8Util.GetBytes(SWSHInfo.ZoneLocations, SWSHInfo.ZoneType, encount_sh, true), "sh")); + File.WriteAllBytes(GetPath("encounter_sw_symbol.pkl"), MiniUtil.PackMini(EncounterTable8Util.GetBytes(SWSHInfo.ZoneLocations, SWSHInfo.ZoneType, encount_symbol_sw), "sw")); + File.WriteAllBytes(GetPath("encounter_sh_symbol.pkl"), MiniUtil.PackMini(EncounterTable8Util.GetBytes(SWSHInfo.ZoneLocations, SWSHInfo.ZoneType, encount_symbol_sh), "sh")); + } + + public void DumpPlacement() + { + var statics = FlatBufferConverter.DeserializeFrom(ROM.GetFile(GameFile.EncounterStatic)[0]); + var placement = new GFPack(ROM.GetFile(GameFile.Placement)[0]); + var species_names = ROM.GetStrings(TextName.SpeciesNames); + var weathers = Enum.GetNames(typeof(SWSHEncounterType)).Select(z => z.Replace("_", " ")).ToArray(); + var area_names = new AHTB(placement.GetDataFileName("AreaNameHashTable.tbl")).ToDictionary(); + var zone_names = new AHTB(placement.GetDataFileName("ZoneNameHashTable.tbl")).ToDictionary(); + var zone_descs = SWSHInfo.Zones; + var obj_names = new AHTB(placement.GetDataFileName("ObjectNameHashTable.tbl")).ToDictionary(); + //var vanish_flags = new AHTB(placement.GetDataFileName("VanishFlagAutoTable.tbl")).ToDictionary(); + //var x = placement.GetDataFileName("template_data.bin"); // flatbuffer skybox + var wild_area = FlatBufferConverter.DeserializeFrom(placement.GetDataFileName("a_wr0101.bin")); + var isle_of_armor = FlatBufferConverter.DeserializeFrom(placement.GetDataFileName("a_wr0201.bin")); + var crown_tundra = FlatBufferConverter.DeserializeFrom(placement.GetDataFileName("a_wr0301.bin")); + + File.WriteAllLines(GetPath("Placement_WildArea.txt"), wild_area.Table.SelectMany(z => z.GetSummary(statics.Table, species_names, zone_names, zone_descs, obj_names, weathers))); + File.WriteAllLines(GetPath("Placement_IsleOfArmor.txt"), isle_of_armor.Table.SelectMany(z => z.GetSummary(statics.Table, species_names, zone_names, zone_descs, obj_names, weathers))); + File.WriteAllLines(GetPath("Placement_CrownTundra.txt"), crown_tundra.Table.SelectMany(z => z.GetSummary(statics.Table, species_names, zone_names, zone_descs, obj_names, weathers))); + + var placement_all = new List(); + foreach (var area in area_names) { - var data = ROM.Data.LevelUpData.LoadAll() - .Cast().Select(z => z.WriteAsLearn6()).ToArray(); - var mini = MiniUtil.PackMini(data, "ss"); - var bin = GetPath(Path.Combine("bin", "lvlmove_swsh.pkl")); - File.WriteAllBytes(bin, mini); + var areaName = area.Value; + var fileName = $"{areaName}.bin"; + if (placement.GetIndexFileName(fileName) < 0) + continue; + + placement_all.Add("=================================="); + placement_all.Add(areaName); + placement_all.Add("=================================="); + placement_all.Add(string.Empty); + + var bin = placement.GetDataFileName(fileName); + var data = FlatBufferConverter.DeserializeFrom(bin); + placement_all.AddRange(data.Table.SelectMany(z => z.GetSummary(statics.Table, species_names, zone_names, zone_descs, obj_names, weathers))); + placement_all.Add(string.Empty); + + File.WriteAllBytes(GetPath("areas", fileName), bin); } - public void DumpEggBinary() + File.WriteAllLines(GetPath("Placement_all.txt"), placement_all); + } + + public void DumpNestEntries() + { + var speciesNames = ROM.GetStrings(TextName.SpeciesNames); + var itemNames = ROM.GetStrings(TextName.ItemNames); + var moveNames = ROM.GetStrings(TextName.MoveNames); + var wildpak = ROM.GetFile(GameFile.NestData)[0]; + var data_table = new GFPack(wildpak); + var nest_encounts = FlatBufferConverter.DeserializeFrom(data_table.GetDataFileName("nest_hole_encount.bin")); + // var nest_levels = FlatBufferConverter.DeserializeFrom(data_table.GetDataFileName("nest_hole_level.bin")); + var nest_drops = FlatBufferConverter.DeserializeFrom(data_table.GetDataFileName("nest_hole_drop_rewards.bin")); + var nest_bonus = FlatBufferConverter.DeserializeFrom(data_table.GetDataFileName("nest_hole_bonus_rewards.bin")); + + string[][] nestHex = new string[2][]; + foreach (var game in new[] { 1, 2 }) { - // format matches past gen and PKHeX's expected format - var data = ROM.GetFilteredFolder(GameFile.EggMoves).GetFiles().Result; - var mini = MiniUtil.PackMini(data, "ss"); - var bin = GetPath(Path.Combine("bin", "eggmove_swsh.pkl")); - File.WriteAllBytes(bin, mini); + var tables = nest_encounts.Table.Where(z => z.GameVersion == game).ToList(); + var entries = tables.Select((_, x) => $"private const int Nest{x:000} = {x + 100_000};"); + var encounters = tables.SelectMany((z, x) => z.GetSummary(speciesNames, x)).ToArray(); + + var path1 = GetPath($"nestHex{game}.txt"); + File.WriteAllLines(path1, entries.Concat(encounters)); + nestHex[game - 1] = encounters; + + var result = tables.Select(z => z.GetSummarySimple()); + var path2 = GetPath($"nest{game}.txt"); + File.WriteAllLines(path2, result); } - public void DumpEvolutionBinary() + var common = nestHex[0].Intersect(nestHex[1]).Where(z => z.StartsWith(" ")).Distinct(); + var sword = nestHex[0].Where(z => !nestHex[1].Contains(z)).Distinct(); + var shield = nestHex[1].Where(z => !nestHex[0].Contains(z)).Distinct(); + + File.WriteAllLines(GetPath("nestCommon.txt"), common); + File.WriteAllLines(GetPath("nestSword.txt"), sword); + File.WriteAllLines(GetPath("nestShield.txt"), shield); + + var nest_pretty_sw = nest_encounts.Table.Where(z => z.GameVersion == 1).SelectMany((z, x) => + z.GetPrettySummary(speciesNames, itemNames, moveNames, Legal.TMHM_SWSH, nest_drops.Table, nest_bonus.Table, x)); + var nest_pretty_sh = nest_encounts.Table.Where(z => z.GameVersion == 2).SelectMany((z, x) => + z.GetPrettySummary(speciesNames, itemNames, moveNames, Legal.TMHM_SWSH, nest_drops.Table, nest_bonus.Table, x)); + File.WriteAllLines(GetPath("nestPrettySword.txt"), nest_pretty_sw); + File.WriteAllLines(GetPath("nestPrettyShield.txt"), nest_pretty_sh); + } + + public void DumpGalarDex() + { + var pt = ROM.Data.PersonalData; + var s = ROM.GetStrings(TextName.SpeciesNames); + + var galar = new List(); + var armor = new List(); + var crown = new List(); + var dexit = new List(); + var foreign = new List(); + for (int i = 1; i <= ROM.Info.MaxSpeciesID; i++) { - // format matches past gen and PKHeX's expected format - var data = ROM.GetFilteredFolder(GameFile.Evolutions).GetFiles().Result; - var mini = MiniUtil.PackMini(data, "ss"); - var bin = GetPath(Path.Combine("bin", "evos_ss.pkl")); - File.WriteAllBytes(bin, mini); - } - - public void DumpGifts() - { - var speciesNames = ROM.GetStrings(TextName.SpeciesNames); - var data = ROM.GetFile(GameFile.EncounterGift)[0]; - var gifts = FlatBufferConverter.DeserializeFrom(data); - var table = TableUtil.GetTable(gifts.Table); - var fn = GetPath("Gifts.txt"); - File.WriteAllText(fn, table); - - var f2 = GetPath("GiftsPKHeX.txt"); - File.WriteAllLines(f2, gifts.Table.Select(z => z.GetSummary(speciesNames))); - } - - public void DumpStatic() - { - var speciesNames = ROM.GetStrings(TextName.SpeciesNames); - var data = ROM.GetFile(GameFile.EncounterStatic)[0]; - var statics = FlatBufferConverter.DeserializeFrom(data); - var table = TableUtil.GetTable(statics.Table); - var fn = GetPath("StaticEncounters.txt"); - File.WriteAllText(fn, table); - - var f2 = GetPath("StaticEncountersPKHeX.txt"); - File.WriteAllLines(f2, statics.Table.Select(z => z.GetSummary(speciesNames))); - } - - public void DumpWilds() - { - var wildpak = ROM.GetFile(GameFile.NestData)[0]; - var data_table = new GFPack(wildpak); - var encount_sw = FlatBufferConverter.DeserializeFrom(data_table.GetDataFileName("encount_k.bin")); - var encount_symbol_sw = FlatBufferConverter.DeserializeFrom(data_table.GetDataFileName("encount_symbol_k.bin")); - var encount_sh = FlatBufferConverter.DeserializeFrom(data_table.GetDataFileName("encount_t.bin")); - var encount_symbol_sh = FlatBufferConverter.DeserializeFrom(data_table.GetDataFileName("encount_symbol_t.bin")); - - var species = ROM.GetStrings(TextName.SpeciesNames); - var zones = SWSHInfo.Zones; - var subtables = Enum.GetNames(typeof(SWSHEncounterType)).Select(z => z.Replace("_", " ")).ToArray(); - - File.WriteAllLines(GetPath("Encounters_Sword.txt"), EncounterTable8Util.GetLines(encount_sw, zones, subtables, species)); - File.WriteAllLines(GetPath("Encounters_Symbol_Sword.txt"), EncounterTable8Util.GetLines(encount_symbol_sw, zones, subtables, species)); - File.WriteAllLines(GetPath("Encounters_Shield.txt"), EncounterTable8Util.GetLines(encount_sh, zones, subtables, species)); - File.WriteAllLines(GetPath("Encounters_Symbol_Shield.txt"), EncounterTable8Util.GetLines(encount_symbol_sh, zones, subtables, species)); - - File.WriteAllBytes(GetPath("encounter_sw_hidden.pkl"), MiniUtil.PackMini(EncounterTable8Util.GetBytes(SWSHInfo.ZoneLocations, SWSHInfo.ZoneType, encount_sw, true), "sw")); - File.WriteAllBytes(GetPath("encounter_sh_hidden.pkl"), MiniUtil.PackMini(EncounterTable8Util.GetBytes(SWSHInfo.ZoneLocations, SWSHInfo.ZoneType, encount_sh, true), "sh")); - File.WriteAllBytes(GetPath("encounter_sw_symbol.pkl"), MiniUtil.PackMini(EncounterTable8Util.GetBytes(SWSHInfo.ZoneLocations, SWSHInfo.ZoneType, encount_symbol_sw), "sw")); - File.WriteAllBytes(GetPath("encounter_sh_symbol.pkl"), MiniUtil.PackMini(EncounterTable8Util.GetBytes(SWSHInfo.ZoneLocations, SWSHInfo.ZoneType, encount_symbol_sh), "sh")); - } - - public void DumpPlacement() - { - var statics = FlatBufferConverter.DeserializeFrom(ROM.GetFile(GameFile.EncounterStatic)[0]); - var placement = new GFPack(ROM.GetFile(GameFile.Placement)[0]); - var species_names = ROM.GetStrings(TextName.SpeciesNames); - var weathers = Enum.GetNames(typeof(SWSHEncounterType)).Select(z => z.Replace("_", " ")).ToArray(); - var area_names = new AHTB(placement.GetDataFileName("AreaNameHashTable.tbl")).ToDictionary(); - var zone_names = new AHTB(placement.GetDataFileName("ZoneNameHashTable.tbl")).ToDictionary(); - var zone_descs = SWSHInfo.Zones; - var obj_names = new AHTB(placement.GetDataFileName("ObjectNameHashTable.tbl")).ToDictionary(); - //var vanish_flags = new AHTB(placement.GetDataFileName("VanishFlagAutoTable.tbl")).ToDictionary(); - //var x = placement.GetDataFileName("template_data.bin"); // flatbuffer skybox - var wild_area = FlatBufferConverter.DeserializeFrom(placement.GetDataFileName("a_wr0101.bin")); - var isle_of_armor = FlatBufferConverter.DeserializeFrom(placement.GetDataFileName("a_wr0201.bin")); - var crown_tundra = FlatBufferConverter.DeserializeFrom(placement.GetDataFileName("a_wr0301.bin")); - - File.WriteAllLines(GetPath("Placement_WildArea.txt"), wild_area.Table.SelectMany(z => z.GetSummary(statics.Table, species_names, zone_names, zone_descs, obj_names, weathers))); - File.WriteAllLines(GetPath("Placement_IsleOfArmor.txt"), isle_of_armor.Table.SelectMany(z => z.GetSummary(statics.Table, species_names, zone_names, zone_descs, obj_names, weathers))); - File.WriteAllLines(GetPath("Placement_CrownTundra.txt"), crown_tundra.Table.SelectMany(z => z.GetSummary(statics.Table, species_names, zone_names, zone_descs, obj_names, weathers))); - - var placement_all = new List(); - foreach (var area in area_names) + var p = (IPersonalInfoSWSH)pt[i]; + bool any = false; + if (p.DexIndexRegional != 0) { - var areaName = area.Value; - var fileName = $"{areaName}.bin"; - if (placement.GetIndexFileName(fileName) < 0) - continue; - - placement_all.Add("=================================="); - placement_all.Add(areaName); - placement_all.Add("=================================="); - placement_all.Add(string.Empty); - - var bin = placement.GetDataFileName(fileName); - var data = FlatBufferConverter.DeserializeFrom(bin); - placement_all.AddRange(data.Table.SelectMany(z => z.GetSummary(statics.Table, species_names, zone_names, zone_descs, obj_names, weathers))); - placement_all.Add(string.Empty); - - File.WriteAllBytes(GetPath("areas", fileName), bin); + galar.Add($"{p.DexIndexRegional:000} - [{i:000]} - {s[i]}"); + any = true; + } + if (p.ArmorDexIndex != 0) + { + armor.Add($"{p.ArmorDexIndex:000} - [{i:000]} - {s[i]}"); + any = true; + } + if (p.CrownDexIndex != 0) + { + crown.Add($"{p.CrownDexIndex:000} - [{i:000]} - {s[i]}"); + any = true; } - File.WriteAllLines(GetPath("Placement_all.txt"), placement_all); + if (!p.IsPresentInGame) + dexit.Add($"[{i:000]} - {s[i]}"); + else if (!any) + foreign.Add($"[{i:000]} - {s[i]}"); } - public void DumpNestEntries() + var path = GetPath("GalarDex.txt"); + File.WriteAllLines(path, galar.OrderBy(z => z)); + + var path2 = GetPath("ArmorDex.txt"); + File.WriteAllLines(path2, armor.OrderBy(z => z)); + + var path3 = GetPath("CrownDex.txt"); + File.WriteAllLines(path3, crown.OrderBy(z => z)); + + var path4 = GetPath("Dexit.txt"); + File.WriteAllLines(path4, dexit); + + var path5 = GetPath("Foreign.txt"); + File.WriteAllLines(path5, foreign); + } + + public void DumpFlavorText() + { + IEnumerable Zip(TextName name, TextName flavor) { - var speciesNames = ROM.GetStrings(TextName.SpeciesNames); - var itemNames = ROM.GetStrings(TextName.ItemNames); - var moveNames = ROM.GetStrings(TextName.MoveNames); - var wildpak = ROM.GetFile(GameFile.NestData)[0]; - var data_table = new GFPack(wildpak); - var nest_encounts = FlatBufferConverter.DeserializeFrom(data_table.GetDataFileName("nest_hole_encount.bin")); - // var nest_levels = FlatBufferConverter.DeserializeFrom(data_table.GetDataFileName("nest_hole_level.bin")); - var nest_drops = FlatBufferConverter.DeserializeFrom(data_table.GetDataFileName("nest_hole_drop_rewards.bin")); - var nest_bonus = FlatBufferConverter.DeserializeFrom(data_table.GetDataFileName("nest_hole_bonus_rewards.bin")); + var n = ROM.GetStrings(name); + var f = ROM.GetStrings(flavor); + return n.Select((z, i) => $"{z}\t{f[i].Replace("\\n", " ")}"); + } + + var p1 = GetPath("ItemFlavor.txt"); + var p2 = GetPath("MoveFlavor.txt"); + var p3 = GetPath("AbilityFlavor.txt"); + + var l1 = Zip(TextName.ItemNames, TextName.ItemFlavor); + var l2 = Zip(TextName.MoveNames, TextName.MoveFlavor); + var l3 = Zip(TextName.AbilityNames, TextName.AbilityFlavor); + + File.WriteAllLines(p1, l1); + File.WriteAllLines(p2, l2); + File.WriteAllLines(p3, l3); + } + + public void DumpEggEntries() + { + var eggdata = ROM.GetFilteredFolder(GameFile.EggMoves).GetFiles().Result; + var egg = EggMoves7.GetArray(eggdata); + var moves = ROM.GetStrings(TextName.MoveNames); + var lines = egg.Select((z, i) => $"{i:000}\t{z.FormTableIndex:0000}\t{string.Join(", ", z.Moves.Select(m => moves[m]))}"); + var bin = GetPath(Path.Combine("eggEntries.txt")); + File.WriteAllLines(bin, lines); + } + + public void DumpMaxDens() + { + var file = ROM.GetFile(GameFile.DynamaxDens)[0]; + var encounters = FlatBufferConverter.DeserializeFrom(file); + var lines = TableUtil.GetTable(encounters.Table); + var table = GetPath("MaxDens.txt"); + File.WriteAllText(table, lines); + + var names = ROM.GetStrings(TextName.SpeciesNames); + var pkhex = encounters.Table.Select(z => z.GetSummary(names)); + File.WriteAllText(GetPath("MaxDens_hex.txt"), string.Join(Environment.NewLine, pkhex)); + } + + public static byte[] GetDistributionContents(string path, out int index) + { + var archive = File.ReadAllBytes(path); + + // Validate Header + if (archive.Length < 0x20 || archive.Length != 4 + BitConverter.ToInt32(archive, 0x10) || BitConverter.ToInt32(archive, 0x8) != 0x20) + throw new ArgumentException("The file at the provided path does not contain a valid header.", nameof(path)); + + index = archive[0]; + + // TODO: Eventually validate CRC16 over Data[:-4], CRC stored at Data[-4:] + + var data = new byte[archive.Length - 0x24]; + Array.Copy(archive, 0x20, data, 0, data.Length); + return data; + } + + public void DumpDistributionNestEntries(string path) + { + var speciesNames = ROM.GetStrings(TextName.SpeciesNames); + var itemNames = ROM.GetStrings(TextName.ItemNames); + var moveNames = ROM.GetStrings(TextName.MoveNames); + var wildpak = ROM.GetFile(GameFile.NestData)[0]; + var data_table = new GFPack(wildpak); + var nest_drops = FlatBufferConverter.DeserializeFrom(data_table.GetDataFileName("nest_hole_drop_rewards.bin")); + var nest_bonus = FlatBufferConverter.DeserializeFrom(data_table.GetDataFileName("nest_hole_bonus_rewards.bin")); + + var dai_data = GetDistributionContents(Path.Combine(path, "dai_encount"), out int dai_index); + var drop_data = GetDistributionContents(Path.Combine(path, "drop_rewards"), out int drop_index); + var bonus_data = GetDistributionContents(Path.Combine(path, "bonus_rewards"), out int bonus_index); + var dist_drops = FlatBufferConverter.DeserializeFrom(drop_data); + var dist_bonus = FlatBufferConverter.DeserializeFrom(bonus_data); + var dai_encounts = FlatBufferConverter.DeserializeFrom(dai_data); + + System.Diagnostics.Debug.Assert(dai_index == drop_index && drop_index == bonus_index, "BCAT Index should be the same for all files!"); + + DumpDistIfExists("normal_encount", ""); + DumpDistIfExists("normal_encount_rigel1", "Armor"); + DumpDistIfExists("normal_encount_rigel2", "Crown"); + + void DumpDistIfExists(string filePath, string dest) + { + var p = Path.Combine(path, filePath); + if (!File.Exists(p)) + return; + + var data = GetDistributionContents(p, out int index); + var encounts = FlatBufferConverter.DeserializeFrom(data); + var pretty_sw = encounts.Table.Where(z => z.GameVersion == 1).SelectMany((z, x) => + z.GetPrettySummary(speciesNames, itemNames, moveNames, Legal.TMHM_SWSH, nest_drops.Table, nest_bonus.Table, dist_drops.Table, dist_bonus.Table, x)); + var pretty_sh = encounts.Table.Where(z => z.GameVersion == 2).SelectMany((z, x) => + z.GetPrettySummary(speciesNames, itemNames, moveNames, Legal.TMHM_SWSH, nest_drops.Table, nest_bonus.Table, dist_drops.Table, dist_bonus.Table, x)); + + File.WriteAllLines(GetPath($"nestDist{dest}PrettySword.txt"), pretty_sw); + File.WriteAllLines(GetPath($"nestDist{dest}PrettyShield.txt"), pretty_sh); + + var dist_sw = TableUtil.GetTable(encounts.Table.Where(z => z.GameVersion == 1).SelectMany(z => z.Entries)); + var dist_sh = TableUtil.GetTable(encounts.Table.Where(z => z.GameVersion == 2).SelectMany(z => z.Entries)); + + File.WriteAllText(GetPath($"nestDist{dest}_sw.txt"), dist_sw); + File.WriteAllText(GetPath($"nestDist{dest}_sh.txt"), dist_sh); string[][] nestHex = new string[2][]; foreach (var game in new[] { 1, 2 }) { - var tables = nest_encounts.Table.Where(z => z.GameVersion == game).ToList(); - var entries = tables.Select((_, x) => $"private const int Nest{x:000} = {x + 100_000};"); - var encounters = tables.SelectMany((z, x) => z.GetSummary(speciesNames, x)).ToArray(); + var tables = encounts.Table.Where(z => z.GameVersion == game).ToList(); + var encounters = tables.SelectMany(z => z.GetSummary(speciesNames, index)).ToArray(); - var path1 = GetPath($"nestHex{game}.txt"); - File.WriteAllLines(path1, entries.Concat(encounters)); - nestHex[game - 1] = encounters; - - var result = tables.Select(z => z.GetSummarySimple()); - var path2 = GetPath($"nest{game}.txt"); - File.WriteAllLines(path2, result); - } - - var common = nestHex[0].Intersect(nestHex[1]).Where(z => z.StartsWith(" ")).Distinct(); - var sword = nestHex[0].Where(z => !nestHex[1].Contains(z)).Distinct(); - var shield = nestHex[1].Where(z => !nestHex[0].Contains(z)).Distinct(); - - File.WriteAllLines(GetPath("nestCommon.txt"), common); - File.WriteAllLines(GetPath("nestSword.txt"), sword); - File.WriteAllLines(GetPath("nestShield.txt"), shield); - - var nest_pretty_sw = nest_encounts.Table.Where(z => z.GameVersion == 1).SelectMany((z, x) => - z.GetPrettySummary(speciesNames, itemNames, moveNames, Legal.TMHM_SWSH, nest_drops.Table, nest_bonus.Table, x)); - var nest_pretty_sh = nest_encounts.Table.Where(z => z.GameVersion == 2).SelectMany((z, x) => - z.GetPrettySummary(speciesNames, itemNames, moveNames, Legal.TMHM_SWSH, nest_drops.Table, nest_bonus.Table, x)); - File.WriteAllLines(GetPath("nestPrettySword.txt"), nest_pretty_sw); - File.WriteAllLines(GetPath("nestPrettyShield.txt"), nest_pretty_sh); - } - - public void DumpGalarDex() - { - var pt = ROM.Data.PersonalData; - var s = ROM.GetStrings(TextName.SpeciesNames); - - var galar = new List(); - var armor = new List(); - var crown = new List(); - var dexit = new List(); - var foreign = new List(); - for (int i = 1; i <= ROM.Info.MaxSpeciesID; i++) - { - var p = (IPersonalInfoSWSH)pt[i]; - bool any = false; - if (p.DexIndexRegional != 0) - { - galar.Add($"{p.DexIndexRegional:000} - [{i:000]} - {s[i]}"); - any = true; - } - if (p.ArmorDexIndex != 0) - { - armor.Add($"{p.ArmorDexIndex:000} - [{i:000]} - {s[i]}"); - any = true; - } - if (p.CrownDexIndex != 0) - { - crown.Add($"{p.CrownDexIndex:000} - [{i:000]} - {s[i]}"); - any = true; - } - - if (!p.IsPresentInGame) - dexit.Add($"[{i:000]} - {s[i]}"); - else if (!any) - foreign.Add($"[{i:000]} - {s[i]}"); - } - - var path = GetPath("GalarDex.txt"); - File.WriteAllLines(path, galar.OrderBy(z => z)); - - var path2 = GetPath("ArmorDex.txt"); - File.WriteAllLines(path2, armor.OrderBy(z => z)); - - var path3 = GetPath("CrownDex.txt"); - File.WriteAllLines(path3, crown.OrderBy(z => z)); - - var path4 = GetPath("Dexit.txt"); - File.WriteAllLines(path4, dexit); - - var path5 = GetPath("Foreign.txt"); - File.WriteAllLines(path5, foreign); - } - - public void DumpFlavorText() - { - IEnumerable Zip(TextName name, TextName flavor) - { - var n = ROM.GetStrings(name); - var f = ROM.GetStrings(flavor); - return n.Select((z, i) => $"{z}\t{f[i].Replace("\\n", " ")}"); - } - - var p1 = GetPath("ItemFlavor.txt"); - var p2 = GetPath("MoveFlavor.txt"); - var p3 = GetPath("AbilityFlavor.txt"); - - var l1 = Zip(TextName.ItemNames, TextName.ItemFlavor); - var l2 = Zip(TextName.MoveNames, TextName.MoveFlavor); - var l3 = Zip(TextName.AbilityNames, TextName.AbilityFlavor); - - File.WriteAllLines(p1, l1); - File.WriteAllLines(p2, l2); - File.WriteAllLines(p3, l3); - } - - public void DumpEggEntries() - { - var eggdata = ROM.GetFilteredFolder(GameFile.EggMoves).GetFiles().Result; - var egg = EggMoves7.GetArray(eggdata); - var moves = ROM.GetStrings(TextName.MoveNames); - var lines = egg.Select((z, i) => $"{i:000}\t{z.FormTableIndex:0000}\t{string.Join(", ", z.Moves.Select(m => moves[m]))}"); - var bin = GetPath(Path.Combine("eggEntries.txt")); - File.WriteAllLines(bin, lines); - } - - public void DumpMaxDens() - { - var file = ROM.GetFile(GameFile.DynamaxDens)[0]; - var encounters = FlatBufferConverter.DeserializeFrom(file); - var lines = TableUtil.GetTable(encounters.Table); - var table = GetPath("MaxDens.txt"); - File.WriteAllText(table, lines); - - var names = ROM.GetStrings(TextName.SpeciesNames); - var pkhex = encounters.Table.Select(z => z.GetSummary(names)); - File.WriteAllText(GetPath("MaxDens_hex.txt"), string.Join(Environment.NewLine, pkhex)); - } - - public static byte[] GetDistributionContents(string path, out int index) - { - var archive = File.ReadAllBytes(path); - - // Validate Header - if (archive.Length < 0x20 || archive.Length != 4 + BitConverter.ToInt32(archive, 0x10) || BitConverter.ToInt32(archive, 0x8) != 0x20) - throw new ArgumentException(); - - index = archive[0]; - - // TODO: Eventually validate CRC16 over Data[:-4], CRC stored at Data[-4:] - - var data = new byte[archive.Length - 0x24]; - Array.Copy(archive, 0x20, data, 0, data.Length); - return data; - } - - public void DumpDistributionNestEntries(string path) - { - var speciesNames = ROM.GetStrings(TextName.SpeciesNames); - var itemNames = ROM.GetStrings(TextName.ItemNames); - var moveNames = ROM.GetStrings(TextName.MoveNames); - var wildpak = ROM.GetFile(GameFile.NestData)[0]; - var data_table = new GFPack(wildpak); - var nest_drops = FlatBufferConverter.DeserializeFrom(data_table.GetDataFileName("nest_hole_drop_rewards.bin")); - var nest_bonus = FlatBufferConverter.DeserializeFrom(data_table.GetDataFileName("nest_hole_bonus_rewards.bin")); - - var dai_data = GetDistributionContents(Path.Combine(path, "dai_encount"), out int dai_index); - var drop_data = GetDistributionContents(Path.Combine(path, "drop_rewards"), out int drop_index); - var bonus_data = GetDistributionContents(Path.Combine(path, "bonus_rewards"), out int bonus_index); - var dist_drops = FlatBufferConverter.DeserializeFrom(drop_data); - var dist_bonus = FlatBufferConverter.DeserializeFrom(bonus_data); - var dai_encounts = FlatBufferConverter.DeserializeFrom(dai_data); - - System.Diagnostics.Debug.Assert(dai_index == drop_index && drop_index == bonus_index, "BCAT Index should be the same for all files!"); - - DumpDistIfExists("normal_encount", ""); - DumpDistIfExists("normal_encount_rigel1", "Armor"); - DumpDistIfExists("normal_encount_rigel2", "Crown"); - - void DumpDistIfExists(string filePath, string dest) - { - var p = Path.Combine(path, filePath); - if (!File.Exists(p)) - return; - - var data = GetDistributionContents(p, out int index); - var encounts = FlatBufferConverter.DeserializeFrom(data); - var pretty_sw = encounts.Table.Where(z => z.GameVersion == 1).SelectMany((z, x) => - z.GetPrettySummary(speciesNames, itemNames, moveNames, Legal.TMHM_SWSH, nest_drops.Table, nest_bonus.Table, dist_drops.Table, dist_bonus.Table, x)); - var pretty_sh = encounts.Table.Where(z => z.GameVersion == 2).SelectMany((z, x) => - z.GetPrettySummary(speciesNames, itemNames, moveNames, Legal.TMHM_SWSH, nest_drops.Table, nest_bonus.Table, dist_drops.Table, dist_bonus.Table, x)); - - File.WriteAllLines(GetPath($"nestDist{dest}PrettySword.txt"), pretty_sw); - File.WriteAllLines(GetPath($"nestDist{dest}PrettyShield.txt"), pretty_sh); - - var dist_sw = TableUtil.GetTable(encounts.Table.Where(z => z.GameVersion == 1).SelectMany(z => z.Entries)); - var dist_sh = TableUtil.GetTable(encounts.Table.Where(z => z.GameVersion == 2).SelectMany(z => z.Entries)); - - File.WriteAllText(GetPath($"nestDist{dest}_sw.txt"), dist_sw); - File.WriteAllText(GetPath($"nestDist{dest}_sh.txt"), dist_sh); - - string[][] nestHex = new string[2][]; - foreach (var game in new[] { 1, 2 }) - { - var tables = encounts.Table.Where(z => z.GameVersion == game).ToList(); - var encounters = tables.SelectMany(z => z.GetSummary(speciesNames, index)).ToArray(); - - var path1 = GetPath($"nestDistHex{game}.txt"); - File.WriteAllLines(path1, encounters); - nestHex[game - 1] = encounters; - - var result = tables.Select(z => z.GetSummarySimple()); - var path2 = GetPath($"nestDistFormat_{game}.txt"); - File.WriteAllLines(path2, result); - } - - var common = nestHex[0].Intersect(nestHex[1]).Where(z => z.StartsWith(" ")).Distinct(); - var sword = nestHex[0].Where(z => !nestHex[1].Contains(z)).Distinct(); - var shield = nestHex[1].Where(z => !nestHex[0].Contains(z)).Distinct(); - - File.WriteAllLines(GetPath($"hex_nestDist{dest}Common.txt"), common); - File.WriteAllLines(GetPath($"hex_nestDist{dest}Sword.txt"), sword); - File.WriteAllLines(GetPath($"hex_nestDist{dest}Shield.txt"), shield); - } - - var dai_pretty_sw = dai_encounts.Table.Where(z => z.GameVersion == 1).SelectMany((z, x) => - z.GetPrettySummary(speciesNames, itemNames, moveNames, Legal.TMHM_SWSH, nest_drops.Table, nest_bonus.Table, dist_drops.Table, dist_bonus.Table, x)); - var dai_pretty_sh = dai_encounts.Table.Where(z => z.GameVersion == 2).SelectMany((z, x) => - z.GetPrettySummary(speciesNames, itemNames, moveNames, Legal.TMHM_SWSH, nest_drops.Table, nest_bonus.Table, dist_drops.Table, dist_bonus.Table, x)); - File.WriteAllLines(GetPath("nestCrystalPrettySword.txt"), dai_pretty_sw); - File.WriteAllLines(GetPath("nestCrystalPrettyShield.txt"), dai_pretty_sh); - - var dai_sw = TableUtil.GetTable(dai_encounts.Table.Where(z => z.GameVersion == 1).SelectMany(z => z.Entries)); - var dai_sh = TableUtil.GetTable(dai_encounts.Table.Where(z => z.GameVersion == 2).SelectMany(z => z.Entries)); - File.WriteAllText(GetPath("nestCrystal_sw.txt"), dai_sw); - File.WriteAllText(GetPath("nestCrystal_sh.txt"), dai_sh); - - DumpHexCrystal(dai_encounts, speciesNames, itemNames); - } - - private void DumpHexCrystal(NestHoleCrystalEncounter8Archive dai_encounts, string[] speciesNames, string[] itemNames) - { - string[][] nestHex = new string[2][]; - foreach (var game in new[] { 1, 2 }) - { - var tables = dai_encounts.Table.Where(z => z.GameVersion == game).ToList(); - var encounters = tables.SelectMany(z => z.GetSummary(speciesNames, itemNames)).ToArray(); - - var path1 = GetPath($"nestCrystalHex{game}.txt"); + var path1 = GetPath($"nestDistHex{game}.txt"); File.WriteAllLines(path1, encounters); nestHex[game - 1] = encounters; var result = tables.Select(z => z.GetSummarySimple()); - var path2 = GetPath($"nestCrystalFormat_{game}.txt"); + var path2 = GetPath($"nestDistFormat_{game}.txt"); File.WriteAllLines(path2, result); } @@ -669,299 +643,341 @@ private void DumpHexCrystal(NestHoleCrystalEncounter8Archive dai_encounts, strin var sword = nestHex[0].Where(z => !nestHex[1].Contains(z)).Distinct(); var shield = nestHex[1].Where(z => !nestHex[0].Contains(z)).Distinct(); - File.WriteAllLines(GetPath("hex_nestCrystalCommon.txt"), common); - File.WriteAllLines(GetPath("hex_nestCrystalSword.txt"), sword); - File.WriteAllLines(GetPath("hex_nestCrystalShield.txt"), shield); + File.WriteAllLines(GetPath($"hex_nestDist{dest}Common.txt"), common); + File.WriteAllLines(GetPath($"hex_nestDist{dest}Sword.txt"), sword); + File.WriteAllLines(GetPath($"hex_nestDist{dest}Shield.txt"), shield); } - private static readonly int[] LanguageIndexes = { 0, 2, 3, 4, 5, 6, 7, 8, 9 }; - private static readonly string[] LanguageCodes = { "ja", "en", "fr", "it", "de", "es", "ko", "zh", "zh2" }; + var dai_pretty_sw = dai_encounts.Table.Where(z => z.GameVersion == 1).SelectMany((z, x) => + z.GetPrettySummary(speciesNames, itemNames, moveNames, Legal.TMHM_SWSH, nest_drops.Table, nest_bonus.Table, dist_drops.Table, dist_bonus.Table, x)); + var dai_pretty_sh = dai_encounts.Table.Where(z => z.GameVersion == 2).SelectMany((z, x) => + z.GetPrettySummary(speciesNames, itemNames, moveNames, Legal.TMHM_SWSH, nest_drops.Table, nest_bonus.Table, dist_drops.Table, dist_bonus.Table, x)); + File.WriteAllLines(GetPath("nestCrystalPrettySword.txt"), dai_pretty_sw); + File.WriteAllLines(GetPath("nestCrystalPrettyShield.txt"), dai_pretty_sh); - private static readonly string[] LanguageNames = - { - "カタカナ", - "漢字", - "English", - "Français", - "Italiano", - "Deutsch", - "Español", - "한국", - "汉字简化方案", - "漢字簡化方案", - }; + var dai_sw = TableUtil.GetTable(dai_encounts.Table.Where(z => z.GameVersion == 1).SelectMany(z => z.Entries)); + var dai_sh = TableUtil.GetTable(dai_encounts.Table.Where(z => z.GameVersion == 2).SelectMany(z => z.Entries)); + File.WriteAllText(GetPath("nestCrystal_sw.txt"), dai_sw); + File.WriteAllText(GetPath("nestCrystal_sh.txt"), dai_sh); - private string[] GetStoryLines(string str) + DumpHexCrystal(dai_encounts, speciesNames, itemNames); + } + + private void DumpHexCrystal(NestHoleCrystalEncounter8Archive dai_encounts, string[] speciesNames, string[] itemNames) + { + string[][] nestHex = new string[2][]; + foreach (var game in new[] { 1, 2 }) { - var strpath = ((FolderContainer)ROM[GameFile.StoryText]).FilePath; - var file = Path.Combine(strpath, str); - var txt = new TextFile(File.ReadAllBytes(file)); - return txt.Lines; + var tables = dai_encounts.Table.Where(z => z.GameVersion == game).ToList(); + var encounters = tables.SelectMany(z => z.GetSummary(speciesNames, itemNames)).ToArray(); + + var path1 = GetPath($"nestCrystalHex{game}.txt"); + File.WriteAllLines(path1, encounters); + nestHex[game - 1] = encounters; + + var result = tables.Select(z => z.GetSummarySimple()); + var path2 = GetPath($"nestCrystalFormat_{game}.txt"); + File.WriteAllLines(path2, result); } - private void ChangeLanguage(int index) + var common = nestHex[0].Intersect(nestHex[1]).Where(z => z.StartsWith(" ")).Distinct(); + var sword = nestHex[0].Where(z => !nestHex[1].Contains(z)).Distinct(); + var shield = nestHex[1].Where(z => !nestHex[0].Contains(z)).Distinct(); + + File.WriteAllLines(GetPath("hex_nestCrystalCommon.txt"), common); + File.WriteAllLines(GetPath("hex_nestCrystalSword.txt"), sword); + File.WriteAllLines(GetPath("hex_nestCrystalShield.txt"), shield); + } + + private static readonly int[] LanguageIndexes = { 0, 2, 3, 4, 5, 6, 7, 8, 9 }; + private static readonly string[] LanguageCodes = { "ja", "en", "fr", "it", "de", "es", "ko", "zh", "zh2" }; + + private static readonly string[] LanguageNames = + { + "カタカナ", + "漢字", + "English", + "Français", + "Italiano", + "Deutsch", + "Español", + "한국", + "汉字简化方案", + "漢字簡化方案", + }; + + private string[] GetStoryLines(string str) + { + var strpath = ((FolderContainer)ROM[GameFile.StoryText]).FilePath; + if (strpath is null) + throw new ArgumentException("StoryText not found in ROM"); + var file = Path.Combine(strpath, str); + var txt = new TextFile(File.ReadAllBytes(file)); + return txt.Lines; + } + + private void ChangeLanguage(int index) + { + ROM.Language = index; + ROM.ResetText(); + } + + public void DumpStrings() + { + int lang = ROM.Language; + var indexes = new[] { 0, 2, 3, 4, 5, 6, 7, 8, 9 }; + for (int i = 0; i < indexes.Length; i++) { - ROM.Language = index; - ROM.ResetText(); + var code = LanguageCodes[i]; + var name = LanguageNames[i]; + var index = indexes[i]; + + DumpStrings(code, name, index); } + ChangeLanguage(lang); + } - public void DumpStrings() + private void DumpStrings(string code, string name, int index) + { + Console.WriteLine($"Dumping strings for {name}."); + ChangeLanguage(index); + + DumpStringSet(TextName.MoveNames, "Moves"); + DumpStringSet(TextName.ItemNames, "Items"); + DumpStringSet(TextName.SpeciesNames, "Species"); + DumpStringSet(TextName.AbilityNames, "Abilities"); + DumpStringSet(TextName.metlist_00000, "swsh_00000"); + DumpStringSet(TextName.metlist_30000, "swsh_30000"); + DumpStringSet(TextName.metlist_40000, "swsh_40000"); + DumpStringSet(TextName.metlist_60000, "swsh_60000"); + DumpStringSet(TextName.Forms, "forms"); + + void DumpStringSet(TextName t, string file) { - int lang = ROM.Language; - var indexes = new[] { 0, 2, 3, 4, 5, 6, 7, 8, 9 }; - for (int i = 0; i < indexes.Length; i++) - { - var code = LanguageCodes[i]; - var name = LanguageNames[i]; - var index = indexes[i]; - - DumpStrings(code, name, index); - } - ChangeLanguage(lang); - } - - private void DumpStrings(string code, string name, int index) - { - Console.WriteLine($"Dumping strings for {name}."); - ChangeLanguage(index); - - DumpStringSet(TextName.MoveNames, "Moves"); - DumpStringSet(TextName.ItemNames, "Items"); - DumpStringSet(TextName.SpeciesNames, "Species"); - DumpStringSet(TextName.AbilityNames, "Abilities"); - DumpStringSet(TextName.metlist_00000, "swsh_00000"); - DumpStringSet(TextName.metlist_30000, "swsh_30000"); - DumpStringSet(TextName.metlist_40000, "swsh_40000"); - DumpStringSet(TextName.metlist_60000, "swsh_60000"); - DumpStringSet(TextName.Forms, "forms"); - - void DumpStringSet(TextName t, string file) - { - var strings = ROM.GetStrings(t); - var fn = $"text_{file}_{code}.txt"; - - var folder = Path.Combine(code, fn); - - var path = GetPath(folder); - File.WriteAllLines(path, strings); - } - } - - public void DumpFormNames() - { - int lang = ROM.Language; - for (int i = 0; i < LanguageIndexes.Length; i++) - { - var code = LanguageCodes[i]; - var name = LanguageNames[i]; - var index = LanguageIndexes[i]; - - DumpForms(code, name, index); - } - ChangeLanguage(lang); - } - - private void DumpForms(string code, string name, int index) - { - Console.WriteLine($"Dumping strings for {name}."); - ChangeLanguage(index); - - var strings = ROM.GetStrings(TextName.Forms); - - var indexes = new[] - { - 0930, // Galarian - 0931, // Gigantamax - 1258, // Gulping - 1259, // Gorging - 1260, // Low Key - - 1267, // Ruby Cream - 1268, // Matcha Cream - 1269, // Mint Cream - 1270, // Lemon Cream - 1271, // Salted Cream - 1272, // Ruby Swirl - 1273, // Caramel Swirl - 1274, // Rainbow Swirl - - 1276, // Noice Face (iceman) - 1278, // Hangry Mode - - 1281, // Crowned (skip sword/shield) - 1284, // Eternamax - - // DLC - 0892, // Single Strike Style - 0920, // World Cap - 1285, // Rapid Strike Style - 1288, // Dada - 1289, // Ice Rider - 1290, // Shadow Rider - }; - - var fn = $"NewFormNames_{code}.txt"; + var strings = ROM.GetStrings(t); + var fn = $"text_{file}_{code}.txt"; var folder = Path.Combine(code, fn); var path = GetPath(folder); - var newNames = strings.Select((z, i) => new { Index = i, Name = z }) - .Where(z => indexes.Contains(z.Index)) - .Select(z => z.Name); - File.WriteAllLines(path, newNames); - } - - public void DumpRibbonNames() - { - int lang = ROM.Language; - var indexes = new[] { 0, 2, 3, 4, 5, 6, 7, 8, 9 }; - for (int i = 0; i < indexes.Length; i++) - { - var code = LanguageCodes[i]; - var name = LanguageNames[i]; - var index = indexes[i]; - - DumpRibbonNames(code, name, index); - } - ChangeLanguage(lang); - } - - private void DumpRibbonNames(string code, string name, int index) - { - Console.WriteLine($"Dumping strings for {name}."); - ChangeLanguage(index); - - var strings = ROM.GetStrings(TextName.RibbonMark); - var lines = strings.Skip(148).Take(48).ToArray(); - - var fn = $"NewRibbonMarks_{code}.txt"; - var folder = Path.Combine(code, fn); - var path = GetPath(folder); - - File.WriteAllLines(path, lines); - } - - public void DumpTrades() - { - var speciesNames = ROM.GetStrings(TextName.SpeciesNames); - var data = ROM.GetFile(GameFile.EncounterTrade)[0]; - var trades = FlatBufferConverter.DeserializeFrom(data); - var table = TableUtil.GetTable(trades.Table); - var fn = GetPath("Trades.txt"); - File.WriteAllText(fn, table); - - var f2 = GetPath("TradesPKHeX.txt"); - File.WriteAllLines(f2, trades.Table.Select(z => z.GetSummary(speciesNames))); - - int lang = ROM.Language; - var indexes = new[] { 0, 2, 3, 4, 5, 6, 7, 8, 9 }; - for (int i = 0; i < indexes.Length; i++) - { - var code = LanguageCodes[i]; - var name = LanguageNames[i]; - var index = indexes[i]; - - DumpTradeNames(code, name, index); - } - ChangeLanguage(lang); - } - - private void DumpTradeNames(string code, string name, int index) - { - Console.WriteLine($"Dumping Trade strings for {name}."); - ChangeLanguage(index); - - var strings = GetStoryLines("field_trade.dat"); - - const int count = 11; - string[] result = new string[count * 2]; - for (int i = 0; i < count; i++) - { - var nickIndex = 6 + (8 * i); - var otIndex = 7 + (8 * i); - - result[i] = strings[nickIndex]; - result[i + count] = strings[otIndex]; - } - - var fn = $"text_tradeswsh_{code}.txt"; - var folder = Path.Combine(code, fn); - var path = GetPath(folder); - - File.WriteAllLines(path, result); - } - - public void DumpMemoryStrings() - { - int lang = ROM.Language; - var indexes = new[] { 0, 2, 3, 4, 5, 6, 7, 8, 9 }; - for (int i = 0; i < indexes.Length; i++) - { - var code = LanguageCodes[i]; - var name = LanguageNames[i]; - var index = indexes[i]; - - DumpMemories(code, name, index); - } - ChangeLanguage(lang); - } - - private void DumpMemories(string code, string name, int index) - { - Console.WriteLine($"Dumping Trade strings for {name}."); - ChangeLanguage(index); - - var places = GetStoryLines("poke_memory_place.dat"); - File.WriteAllLines(GetPath(Path.Combine(code, $"text_GenLoc_{code}.txt")), places); - - var strings = GetStoryLines("sub_event_129.dat").Skip(90).ToArray(); - for (int i = 0; i < strings.Length; i++) - { - strings[i] = strings[i].Replace("[VAR 0100(0001)]", "{1}"); - strings[i] = strings[i].Replace("[VAR 0101(0004)]", "{2}"); - strings[i] = strings[i].Replace("[VAR 0102(0000)]", "{0}"); - strings[i] = strings[i].Replace("[VAR 0107(0005)]", "{2}"); - strings[i] = strings[i].Replace("[VAR 0108(0005)]", "{2}"); - strings[i] = strings[i].Replace("[VAR 0109(0003)]", "{2}"); - strings[i] = strings[i].Replace("[VAR 010A(0003)]", "{2}"); - strings[i] = strings[i].Replace("[VAR 01D6(0002)]", "{2}"); - strings[i] = strings[i].Replace("[VAR 01D7(0006)]", "{3}"); - strings[i] = strings[i].Replace("[VAR 01D8(0007)]", "{4}"); - strings[i] = strings[i].Replace("[VAR 1001]", ""); - strings[i] = strings[i].Replace("[VAR 1002]", ""); - strings[i] = strings[i].Replace("[VAR 1003]", ""); - strings[i] = strings[i].Replace("[VAR 1100(0001,0101)]", ""); - strings[i] = strings[i].Replace("[VAR 1100(00FF,0101)]", ""); - strings[i] = strings[i].Replace("[VAR 1101(0003,0100)]", ""); - strings[i] = strings[i].Replace("[VAR 1101(0003,0200)]", ""); - strings[i] = strings[i].Replace("[VAR 1302(0003,0000)]", ""); - strings[i] = strings[i].Replace("[VAR 1302(0004,0000)]", ""); - strings[i] = strings[i].Replace("[VAR 1400(0001,0001)]", ""); - strings[i] = strings[i].Replace("[VAR 1400(0003,0000)]", ""); - strings[i] = strings[i].Replace("[VAR 1402(0003,0000)]", ""); - strings[i] = strings[i].Replace("[VAR 1408(0001,0000)]", ""); - strings[i] = strings[i].Replace("[VAR 1408(0001,0001)]", ""); - strings[i] = strings[i].Replace("[VAR 140A(0001,0001)]", ""); - strings[i] = strings[i].Replace("[VAR 1500(0003,0000)]", ""); - strings[i] = strings[i].Replace("[VAR 1502(0003,0000)]", ""); - strings[i] = strings[i].Replace("[VAR 1502(0003,0001)]", ""); - strings[i] = strings[i].Replace("[VAR 1502(0004,0000)]", ""); - strings[i] = strings[i].Replace("[VAR 1502(0004,0001)]", ""); - strings[i] = strings[i].Replace("[VAR 1602(0003,0000)]", ""); - strings[i] = strings[i].Replace("[VAR 1606(0003,0000)]", ""); - strings[i] = strings[i].Replace("[VAR 1700(0003,0000)]", ""); - strings[i] = strings[i].Replace("[VAR 1702(0002,0000)]", ""); - strings[i] = strings[i].Replace("[VAR 1702(0003,0000)]", ""); - strings[i] = strings[i].Replace("[VAR 1900(0001)]", ""); - strings[i] = strings[i].Replace("[VAR 1900(0002)]", ""); - strings[i] = strings[i].Replace("[VAR 1900(0003)]", ""); - strings[i] = strings[i].Replace("[VAR 1900(0004)]", ""); - strings[i] = strings[i].Replace("[VAR 1900(0005)]", ""); - strings[i] = strings[i].Replace("\\c", ""); - strings[i] = strings[i].Replace("\\n", " "); - strings[i] = strings[i].Replace("\\r", ""); - } - File.WriteAllLines(GetPath(Path.Combine(code, $"text_NewMemories_{code}.txt")), strings); + File.WriteAllLines(path, strings); } } -} \ No newline at end of file + + public void DumpFormNames() + { + int lang = ROM.Language; + for (int i = 0; i < LanguageIndexes.Length; i++) + { + var code = LanguageCodes[i]; + var name = LanguageNames[i]; + var index = LanguageIndexes[i]; + + DumpForms(code, name, index); + } + ChangeLanguage(lang); + } + + private void DumpForms(string code, string name, int index) + { + Console.WriteLine($"Dumping strings for {name}."); + ChangeLanguage(index); + + var strings = ROM.GetStrings(TextName.Forms); + + var indexes = new[] + { + 0930, // Galarian + 0931, // Gigantamax + 1258, // Gulping + 1259, // Gorging + 1260, // Low Key + + 1267, // Ruby Cream + 1268, // Matcha Cream + 1269, // Mint Cream + 1270, // Lemon Cream + 1271, // Salted Cream + 1272, // Ruby Swirl + 1273, // Caramel Swirl + 1274, // Rainbow Swirl + + 1276, // Noice Face (iceman) + 1278, // Hangry Mode + + 1281, // Crowned (skip sword/shield) + 1284, // Eternamax + + // DLC + 0892, // Single Strike Style + 0920, // World Cap + 1285, // Rapid Strike Style + 1288, // Dada + 1289, // Ice Rider + 1290, // Shadow Rider + }; + + var fn = $"NewFormNames_{code}.txt"; + + var folder = Path.Combine(code, fn); + + var path = GetPath(folder); + var newNames = strings.Select((z, i) => new { Index = i, Name = z }) + .Where(z => indexes.Contains(z.Index)) + .Select(z => z.Name); + File.WriteAllLines(path, newNames); + } + + public void DumpRibbonNames() + { + int lang = ROM.Language; + var indexes = new[] { 0, 2, 3, 4, 5, 6, 7, 8, 9 }; + for (int i = 0; i < indexes.Length; i++) + { + var code = LanguageCodes[i]; + var name = LanguageNames[i]; + var index = indexes[i]; + + DumpRibbonNames(code, name, index); + } + ChangeLanguage(lang); + } + + private void DumpRibbonNames(string code, string name, int index) + { + Console.WriteLine($"Dumping strings for {name}."); + ChangeLanguage(index); + + var strings = ROM.GetStrings(TextName.RibbonMark); + var lines = strings.Skip(148).Take(48).ToArray(); + + var fn = $"NewRibbonMarks_{code}.txt"; + var folder = Path.Combine(code, fn); + var path = GetPath(folder); + + File.WriteAllLines(path, lines); + } + + public void DumpTrades() + { + var speciesNames = ROM.GetStrings(TextName.SpeciesNames); + var data = ROM.GetFile(GameFile.EncounterTrade)[0]; + var trades = FlatBufferConverter.DeserializeFrom(data); + var table = TableUtil.GetTable(trades.Table); + var fn = GetPath("Trades.txt"); + File.WriteAllText(fn, table); + + var f2 = GetPath("TradesPKHeX.txt"); + File.WriteAllLines(f2, trades.Table.Select(z => z.GetSummary(speciesNames))); + + int lang = ROM.Language; + var indexes = new[] { 0, 2, 3, 4, 5, 6, 7, 8, 9 }; + for (int i = 0; i < indexes.Length; i++) + { + var code = LanguageCodes[i]; + var name = LanguageNames[i]; + var index = indexes[i]; + + DumpTradeNames(code, name, index); + } + ChangeLanguage(lang); + } + + private void DumpTradeNames(string code, string name, int index) + { + Console.WriteLine($"Dumping Trade strings for {name}."); + ChangeLanguage(index); + + var strings = GetStoryLines("field_trade.dat"); + + const int count = 11; + string[] result = new string[count * 2]; + for (int i = 0; i < count; i++) + { + var nickIndex = 6 + (8 * i); + var otIndex = 7 + (8 * i); + + result[i] = strings[nickIndex]; + result[i + count] = strings[otIndex]; + } + + var fn = $"text_tradeswsh_{code}.txt"; + var folder = Path.Combine(code, fn); + var path = GetPath(folder); + + File.WriteAllLines(path, result); + } + + public void DumpMemoryStrings() + { + int lang = ROM.Language; + var indexes = new[] { 0, 2, 3, 4, 5, 6, 7, 8, 9 }; + for (int i = 0; i < indexes.Length; i++) + { + var code = LanguageCodes[i]; + var name = LanguageNames[i]; + var index = indexes[i]; + + DumpMemories(code, name, index); + } + ChangeLanguage(lang); + } + + private void DumpMemories(string code, string name, int index) + { + Console.WriteLine($"Dumping Trade strings for {name}."); + ChangeLanguage(index); + + var places = GetStoryLines("poke_memory_place.dat"); + File.WriteAllLines(GetPath(Path.Combine(code, $"text_GenLoc_{code}.txt")), places); + + var strings = GetStoryLines("sub_event_129.dat").Skip(90).ToArray(); + for (int i = 0; i < strings.Length; i++) + { + strings[i] = strings[i].Replace("[VAR 0100(0001)]", "{1}"); + strings[i] = strings[i].Replace("[VAR 0101(0004)]", "{2}"); + strings[i] = strings[i].Replace("[VAR 0102(0000)]", "{0}"); + strings[i] = strings[i].Replace("[VAR 0107(0005)]", "{2}"); + strings[i] = strings[i].Replace("[VAR 0108(0005)]", "{2}"); + strings[i] = strings[i].Replace("[VAR 0109(0003)]", "{2}"); + strings[i] = strings[i].Replace("[VAR 010A(0003)]", "{2}"); + strings[i] = strings[i].Replace("[VAR 01D6(0002)]", "{2}"); + strings[i] = strings[i].Replace("[VAR 01D7(0006)]", "{3}"); + strings[i] = strings[i].Replace("[VAR 01D8(0007)]", "{4}"); + strings[i] = strings[i].Replace("[VAR 1001]", ""); + strings[i] = strings[i].Replace("[VAR 1002]", ""); + strings[i] = strings[i].Replace("[VAR 1003]", ""); + strings[i] = strings[i].Replace("[VAR 1100(0001,0101)]", ""); + strings[i] = strings[i].Replace("[VAR 1100(00FF,0101)]", ""); + strings[i] = strings[i].Replace("[VAR 1101(0003,0100)]", ""); + strings[i] = strings[i].Replace("[VAR 1101(0003,0200)]", ""); + strings[i] = strings[i].Replace("[VAR 1302(0003,0000)]", ""); + strings[i] = strings[i].Replace("[VAR 1302(0004,0000)]", ""); + strings[i] = strings[i].Replace("[VAR 1400(0001,0001)]", ""); + strings[i] = strings[i].Replace("[VAR 1400(0003,0000)]", ""); + strings[i] = strings[i].Replace("[VAR 1402(0003,0000)]", ""); + strings[i] = strings[i].Replace("[VAR 1408(0001,0000)]", ""); + strings[i] = strings[i].Replace("[VAR 1408(0001,0001)]", ""); + strings[i] = strings[i].Replace("[VAR 140A(0001,0001)]", ""); + strings[i] = strings[i].Replace("[VAR 1500(0003,0000)]", ""); + strings[i] = strings[i].Replace("[VAR 1502(0003,0000)]", ""); + strings[i] = strings[i].Replace("[VAR 1502(0003,0001)]", ""); + strings[i] = strings[i].Replace("[VAR 1502(0004,0000)]", ""); + strings[i] = strings[i].Replace("[VAR 1502(0004,0001)]", ""); + strings[i] = strings[i].Replace("[VAR 1602(0003,0000)]", ""); + strings[i] = strings[i].Replace("[VAR 1606(0003,0000)]", ""); + strings[i] = strings[i].Replace("[VAR 1700(0003,0000)]", ""); + strings[i] = strings[i].Replace("[VAR 1702(0002,0000)]", ""); + strings[i] = strings[i].Replace("[VAR 1702(0003,0000)]", ""); + strings[i] = strings[i].Replace("[VAR 1900(0001)]", ""); + strings[i] = strings[i].Replace("[VAR 1900(0002)]", ""); + strings[i] = strings[i].Replace("[VAR 1900(0003)]", ""); + strings[i] = strings[i].Replace("[VAR 1900(0004)]", ""); + strings[i] = strings[i].Replace("[VAR 1900(0005)]", ""); + strings[i] = strings[i].Replace("\\c", ""); + strings[i] = strings[i].Replace("\\n", " "); + strings[i] = strings[i].Replace("\\r", ""); + } + File.WriteAllLines(GetPath(Path.Combine(code, $"text_NewMemories_{code}.txt")), strings); + } +} diff --git a/pkNX.WinForms/Dumping/PersonalDumperPLA.cs b/pkNX.WinForms/Dumping/PersonalDumperPLA.cs index 984111d2..db2407c9 100644 --- a/pkNX.WinForms/Dumping/PersonalDumperPLA.cs +++ b/pkNX.WinForms/Dumping/PersonalDumperPLA.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -6,239 +6,238 @@ using pkNX.Structures.FlatBuffers; #nullable disable // meh -namespace pkNX.WinForms +namespace pkNX.WinForms; + +public class PersonalDumperPLA { - public class PersonalDumperPLA + private void AddTRs(List lines, IMovesInfo_1 pi, string specCode) { - private void AddTRs(List lines, IMovesInfo_1 pi, string specCode) + if (!(TMIndexes?.Count > 0)) + return; + var tmhm = pi.TMHM; + int count = 0; + lines.Add("Legacy TRs:"); + for (int i = 0; i < 100; i++) { - if (!(TMIndexes?.Count > 0)) - return; - var tmhm = pi.TMHM; - int count = 0; - lines.Add("Legacy TRs:"); - for (int i = 0; i < 100; i++) - { - if (!tmhm[100 + i]) - continue; - var move = TMIndexes[100 + i]; - lines.Add($"- [TR{i:00}] {Moves[move]}"); - count++; + if (!tmhm[100 + i]) + continue; + var move = TMIndexes[100 + i]; + lines.Add($"- [TR{i:00}] {Moves[move]}"); + count++; - MoveSpeciesLearn[move].Add(specCode); - } - if (count == 0) - lines.Add("None!"); + MoveSpeciesLearn[move].Add(specCode); } + if (count == 0) + lines.Add("None!"); + } - public bool HasAbilities { get; set; } = true; - public bool HasItems { get; set; } = true; + public bool HasAbilities { get; set; } = true; + public bool HasItems { get; set; } = true; - public IReadOnlyList Abilities { private get; set; } - public IReadOnlyList Types { private get; set; } - public IReadOnlyList Items { private get; set; } - public IReadOnlyList Colors { private get; set; } - public IReadOnlyList EggGroups { private get; set; } - public IReadOnlyList ExpGroups { private get; set; } - public IReadOnlyList EntryNames { private get; set; } - public IReadOnlyList Moves { protected get; set; } - public IReadOnlyList Species { private get; set; } - public IReadOnlyList ZukanA { private get; set; } - public IReadOnlyList ZukanB { private get; set; } + public IReadOnlyList Abilities { private get; set; } + public IReadOnlyList Types { private get; set; } + public IReadOnlyList Items { private get; set; } + public IReadOnlyList Colors { private get; set; } + public IReadOnlyList EggGroups { private get; set; } + public IReadOnlyList ExpGroups { private get; set; } + public IReadOnlyList EntryNames { private get; set; } + public IReadOnlyList Moves { protected get; set; } + public IReadOnlyList Species { private get; set; } + public IReadOnlyList ZukanA { private get; set; } + public IReadOnlyList ZukanB { private get; set; } - public Learnset8aMeta[] EntryLearnsets { private get; set; } - public IReadOnlyList EntryEggMoves { private get; set; } - public EvolutionSet8a[] Evos { private get; set; } - public IReadOnlyList TMIndexes { protected get; set; } + public Learnset8aMeta[] EntryLearnsets { private get; set; } + public IReadOnlyList EntryEggMoves { private get; set; } + public EvolutionSet8a[] Evos { private get; set; } + public IReadOnlyList TMIndexes { protected get; set; } - private static readonly string[] AbilitySuffix = { " (1)", " (2)", " (H)" }; - private static readonly string[] ItemPrefix = { "Item 1 (50%)", "Item 2 (5%)", "Item 3 (1%)" }; + private static readonly string[] AbilitySuffix = { " (1)", " (2)", " (H)" }; + private static readonly string[] ItemPrefix = { "Item 1 (50%)", "Item 2 (5%)", "Item 3 (1%)" }; - public IReadOnlyList> MoveSpeciesLearn { get; private set; } + public IReadOnlyList> MoveSpeciesLearn { get; private set; } - public PersonalDumperSettings Settings = new(); + public PersonalDumperSettings Settings = new(); - public List Dump(IPersonalTable table) + public List Dump(IPersonalTable table) + { + var lines = new List(); + var ml = new List[Moves.Count]; + for (int i = 0; i < ml.Length; i++) + ml[i] = new List(); + MoveSpeciesLearn = ml; + + for (ushort species = 0; species <= table.MaxSpeciesID; species++) { - var lines = new List(); - var ml = new List[Moves.Count]; - for (int i = 0; i < ml.Length; i++) - ml[i] = new List(); - MoveSpeciesLearn = ml; - - for (ushort species = 0; species <= table.MaxSpeciesID; species++) - { - var spec = table[species]; - for (byte form = 0; form < spec.FormCount; form++) - AddDump(lines, table, species, form); - } - return lines; + var spec = table[species]; + for (byte form = 0; form < spec.FormCount; form++) + AddDump(lines, table, species, form); } + return lines; + } - public void AddDump(List lines, IPersonalTable table, ushort species, byte form) + public void AddDump(List lines, IPersonalTable table, ushort species, byte form) + { + var index = table.GetFormIndex(species, form); + var entry = table[index]; + string name = EntryNames[index]; + AddDump(lines, entry, index, name, species, form); + lines.Add(""); + } + + private void AddDump(List lines, IPersonalInfo pi, int entry, string name, int species, int form) + { + if (pi is IPersonalMisc_1 { IsPresentInGame: false }) + return; + + var specCode = pi.FormCount > 1 ? $"{Species[species]}-{form}" : $"{Species[species]}"; + + if (Settings.Stats) + AddPersonalLines(lines, pi, entry, name, specCode); + if (Settings.Learn) { - var index = table.GetFormIndex(species, form); - var entry = table[index]; - string name = EntryNames[index]; - AddDump(lines, entry, index, name, species, form); - lines.Add(""); + AddLearnsets(lines, specCode, species, form); + AddLearnsetsLegacy(lines, specCode, species, form); } + if (Settings.Evo) + AddEvolutions(lines, species, form); + if (Settings.Dex) + AddZukan(lines, entry); + } - private void AddDump(List lines, IPersonalInfo pi, int entry, string name, int species, int form) + private void AddZukan(List lines, int entry) + { + if (entry >= Species.Count) + return; + lines.Add(ZukanA[entry].Replace("\\n", " ")); + lines.Add(ZukanB[entry].Replace("\\n", " ")); + } + + protected virtual void AddTMs(List lines, IMovesInfo_1 pi, string SpecCode) + { + var tmhm = pi.TMHM; + int count = 0; + lines.Add("Legacy TMs:"); + for (int i = 0; i < 100; i++) { - if (pi is IPersonalMisc_1 { IsPresentInGame: false }) - return; + if (!tmhm[i]) + continue; + var move = TMIndexes[i]; + lines.Add($"- [TM{i:00}] {Moves[move]}"); + count++; - var specCode = pi.FormCount > 1 ? $"{Species[species]}-{form}" : $"{Species[species]}"; - - if (Settings.Stats) - AddPersonalLines(lines, pi, entry, name, specCode); - if (Settings.Learn) - { - AddLearnsets(lines, specCode, species, form); - AddLearnsetsLegacy(lines, specCode, species, form); - } - if (Settings.Evo) - AddEvolutions(lines, species, form); - if (Settings.Dex) - AddZukan(lines, entry); + MoveSpeciesLearn[move].Add(SpecCode); } + if (count == 0) + lines.Add("None!"); - private void AddZukan(List lines, int entry) + AddTRs(lines, pi, SpecCode); + } + + protected virtual void AddArmorTutors(List lines, IMovesInfo_2 pi, string SpecCode) + { + var shop = pi.SpecialTutors[0]; + int count = 0; + lines.Add("Move Shop:"); + for (int i = 0; i < Math.Min(shop.Length, Legal.MoveShop8_LA.Length); i++) { - if (entry >= Species.Count) - return; - lines.Add(ZukanA[entry].Replace("\\n", " ")); - lines.Add(ZukanB[entry].Replace("\\n", " ")); + if (!shop[i]) + continue; + var move = Legal.MoveShop8_LA[i]; + lines.Add($"- {Moves[move]}"); + count++; + + MoveSpeciesLearn[move].Add(SpecCode); } + if (count == 0) + lines.Add("None!"); + } - protected virtual void AddTMs(List lines, IMovesInfo_1 pi, string SpecCode) + private void AddLearnsetsLegacy(List lines, string specCode, int species, int form) + { + var learn = Array.Find(EntryLearnsets, z => z.Species == species && z.Form == form); + if (learn is null) + return; + + + lines.Add("Legacy Level Up Moves:"); + foreach (var x in learn.Mainline) { - var tmhm = pi.TMHM; - int count = 0; - lines.Add("Legacy TMs:"); - for (int i = 0; i < 100; i++) - { - if (!tmhm[i]) - continue; - var move = TMIndexes[i]; - lines.Add($"- [TM{i:00}] {Moves[move]}"); - count++; - - MoveSpeciesLearn[move].Add(SpecCode); - } - if (count == 0) - lines.Add("None!"); - - AddTRs(lines, pi, SpecCode); - } - - protected virtual void AddArmorTutors(List lines, IMovesInfo_2 pi, string SpecCode) - { - var shop = pi.SpecialTutors[0]; - int count = 0; - lines.Add("Move Shop:"); - for (int i = 0; i < Math.Min(shop.Length, Legal.MoveShop8_LA.Length); i++) - { - if (!shop[i]) - continue; - var move = Legal.MoveShop8_LA[i]; - lines.Add($"- {Moves[move]}"); - count++; - - MoveSpeciesLearn[move].Add(SpecCode); - } - if (count == 0) - lines.Add("None!"); - } - - private void AddLearnsetsLegacy(List lines, string specCode, int species, int form) - { - var learn = Array.Find(EntryLearnsets, z => z.Species == species && z.Form == form); - if (learn is null) - return; - - - lines.Add("Legacy Level Up Moves:"); - foreach (var x in learn.Mainline) - { - var move = x.Move; - var level = x.Level; - lines.Add($"- [{level:00}] {Moves[move]}"); - MoveSpeciesLearn[move].Add(specCode); - } - } - - private void AddLearnsets(List lines, string specCode, int species, int form) - { - var learn = Array.Find(EntryLearnsets, z => z.Species == species && z.Form == form); - if (learn is null) - return; - - lines.Add("Level Up Moves:"); - foreach (var x in learn.Arceus) - { - var move = x.Move; - var level = x.Level; - var master = x.LevelMaster; - lines.Add($"- [{level:00}] [{master:00}] {Moves[move]}"); - MoveSpeciesLearn[move].Add(specCode); - } - } - - private void AddEvolutions(List lines, int species, int form) - { - var evo = Array.Find(Evos, z => z.Species == species && z.Form == form); - if (evo?.Table is null) - return; - var evo2 = evo.Table.Where(z => z.Species != 0).ToArray(); - if (evo2.Length == 0) - return; - - var msg = evo2.Select(z => $"Evolves into {Species[z.Species]}-{z.Form} @ {z.Level} ({z.Method}) [{z.Argument}]"); - lines.AddRange(msg); - } - - private void AddPersonalLines(List lines, IPersonalInfo pi, int entry, string name, string specCode) - { - Debug.WriteLine($"Dumping {specCode}"); - lines.Add("======"); - lines.Add($"{entry:000} - {name} (Stage: {pi.EvoStage})"); - lines.Add("======"); - if (pi is IPersonalMisc_1 { IsPresentInGame: false }) - lines.Add("Present: No"); - lines.Add($"Base Stats: {pi.HP}.{pi.ATK}.{pi.DEF}.{pi.SPA}.{pi.SPD}.{pi.SPE} (BST: {pi.GetBaseStatTotal()})"); - lines.Add($"EV Yield: {pi.EV_HP}.{pi.EV_ATK}.{pi.EV_DEF}.{pi.EV_SPA}.{pi.EV_SPD}.{pi.EV_SPE}"); - lines.Add($"Gender Ratio: {pi.Gender}"); - lines.Add($"Catch Rate: {pi.CatchRate}"); - - if (HasAbilities) - { - var abils = new int[pi.GetNumAbilities()]; - pi.GetAbilities(abils); - var msg = string.Join(" | ", abils.Select((z, j) => Abilities[z] + AbilitySuffix[j])); - lines.Add($"Abilities: {msg}"); - } - - lines.Add(string.Format(pi.Type1 != pi.Type2 - ? "Type: {0} / {1}" - : "Type: {0}", Types[(int)pi.Type1], Types[(int)pi.Type2])); - - if (HasItems) - { - var items = new int[pi.GetNumItems()]; - pi.GetItems(items); - if (items.Distinct().Count() == 1) - lines.Add($"Items: {Items[pi.Item1]}"); - else - lines.AddRange(items.Select((z, j) => $"{ItemPrefix[j]}: {Items[z]}")); - } - - lines.Add($"EXP Group: {ExpGroups[pi.EXPGrowth]}"); - lines.Add(string.Format(pi.EggGroup1 != pi.EggGroup2 - ? "Egg Group: {0} / {1}" - : "Egg Group: {0}", EggGroups[pi.EggGroup1], EggGroups[pi.EggGroup2])); - lines.Add($"Height: {(decimal)pi.Height / 100:00.00}m, Weight: {(decimal)pi.Weight / 10:000.0}kg, Color: {Colors[pi.Color]}"); + var move = x.Move; + var level = x.Level; + lines.Add($"- [{level:00}] {Moves[move]}"); + MoveSpeciesLearn[move].Add(specCode); } } -} \ No newline at end of file + + private void AddLearnsets(List lines, string specCode, int species, int form) + { + var learn = Array.Find(EntryLearnsets, z => z.Species == species && z.Form == form); + if (learn is null) + return; + + lines.Add("Level Up Moves:"); + foreach (var x in learn.Arceus) + { + var move = x.Move; + var level = x.Level; + var master = x.LevelMaster; + lines.Add($"- [{level:00}] [{master:00}] {Moves[move]}"); + MoveSpeciesLearn[move].Add(specCode); + } + } + + private void AddEvolutions(List lines, int species, int form) + { + var evo = Array.Find(Evos, z => z.Species == species && z.Form == form); + if (evo?.Table is null) + return; + var evo2 = evo.Table.Where(z => z.Species != 0).ToArray(); + if (evo2.Length == 0) + return; + + var msg = evo2.Select(z => $"Evolves into {Species[z.Species]}-{z.Form} @ {z.Level} ({z.Method}) [{z.Argument}]"); + lines.AddRange(msg); + } + + private void AddPersonalLines(List lines, IPersonalInfo pi, int entry, string name, string specCode) + { + Debug.WriteLine($"Dumping {specCode}"); + lines.Add("======"); + lines.Add($"{entry:000} - {name} (Stage: {pi.EvoStage})"); + lines.Add("======"); + if (pi is IPersonalMisc_1 { IsPresentInGame: false }) + lines.Add("Present: No"); + lines.Add($"Base Stats: {pi.HP}.{pi.ATK}.{pi.DEF}.{pi.SPA}.{pi.SPD}.{pi.SPE} (BST: {pi.GetBaseStatTotal()})"); + lines.Add($"EV Yield: {pi.EV_HP}.{pi.EV_ATK}.{pi.EV_DEF}.{pi.EV_SPA}.{pi.EV_SPD}.{pi.EV_SPE}"); + lines.Add($"Gender Ratio: {pi.Gender}"); + lines.Add($"Catch Rate: {pi.CatchRate}"); + + if (HasAbilities) + { + var abils = new int[pi.GetNumAbilities()]; + pi.GetAbilities(abils); + var msg = string.Join(" | ", abils.Select((z, j) => Abilities[z] + AbilitySuffix[j])); + lines.Add($"Abilities: {msg}"); + } + + lines.Add(string.Format(pi.Type1 != pi.Type2 + ? "Type: {0} / {1}" + : "Type: {0}", Types[(int)pi.Type1], Types[(int)pi.Type2])); + + if (HasItems) + { + var items = new int[pi.GetNumItems()]; + pi.GetItems(items); + if (items.Distinct().Count() == 1) + lines.Add($"Items: {Items[pi.Item1]}"); + else + lines.AddRange(items.Select((z, j) => $"{ItemPrefix[j]}: {Items[z]}")); + } + + lines.Add($"EXP Group: {ExpGroups[pi.EXPGrowth]}"); + lines.Add(string.Format(pi.EggGroup1 != pi.EggGroup2 + ? "Egg Group: {0} / {1}" + : "Egg Group: {0}", EggGroups[pi.EggGroup1], EggGroups[pi.EggGroup2])); + lines.Add($"Height: {(decimal)pi.Height / 100:00.00}m, Weight: {(decimal)pi.Weight / 10:000.0}kg, Color: {Colors[pi.Color]}"); + } +} diff --git a/pkNX.WinForms/Main.cs b/pkNX.WinForms/Main.cs index d2580cbe..f240daf7 100644 --- a/pkNX.WinForms/Main.cs +++ b/pkNX.WinForms/Main.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Diagnostics; using System.Globalization; using System.IO; @@ -7,183 +7,197 @@ using System.Windows.Forms; using pkNX.Sprites; using pkNX.Structures; -using pkNX.WinForms.Properties; using EditorBase = pkNX.WinForms.Controls.EditorBase; -namespace pkNX.WinForms +namespace pkNX.WinForms; + +public class ProgramSettings { - public partial class Main : Form + public int Language { get; set; } = 2; + public string GamePath { get; set; } = string.Empty; +} + +public partial class Main : Form +{ + public static readonly string ProgramSettingsPath = Path.Combine(Application.StartupPath, "settings.json"); + public ProgramSettings Settings { get; } + + private int Language { - private int Language + get => CB_Lang.SelectedIndex; + set => CB_Lang.SelectedIndex = value; + } + + private EditorBase? Editor; + + public Main() + { + InitializeComponent(); + + // Fix number values displaying incorrectly for certain cultures. + Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; + Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture; + + Settings = SettingsSerializer.GetSettings(ProgramSettingsPath).Result; + CB_Lang.SelectedIndex = Settings.Language; + if (!string.IsNullOrWhiteSpace(Settings.GamePath)) + OpenPath(Settings.GamePath); + + DragDrop += (s, e) => { - get => CB_Lang.SelectedIndex; - set => CB_Lang.SelectedIndex = value; - } - - private EditorBase? Editor; - - public Main() - { - InitializeComponent(); - - // Fix number values displaying incorrectly for certain cultures. - Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; - Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture; - - CB_Lang.SelectedIndex = Settings.Default.Language; - if (!string.IsNullOrWhiteSpace(Settings.Default.GamePath)) - OpenPath(Settings.Default.GamePath); - - DragDrop += (s, e) => - { - var files = (string[])e.Data.GetData(DataFormats.FileDrop); - foreach (var f in files) - OpenPath(f); - }; - DragEnter += (s, e) => - { - if (e.Data.GetDataPresent(DataFormats.FileDrop)) - e.Effect = DragDropEffects.Copy; - }; - } - - private void ChangeLanguage(object sender, EventArgs e) - { - Menu_Options.DropDown.Close(); - if (Editor == null) + var files = (string[]?)e.Data?.GetData(DataFormats.FileDrop); + if (files is null) return; + foreach (var f in files) + OpenPath(f); + }; + DragEnter += (s, e) => + { + if (e.Data?.GetDataPresent(DataFormats.FileDrop) ?? false) + e.Effect = DragDropEffects.Copy; + }; + } - if (Editor.Game.GetGeneration() < 7 && Language > 7) - { - WinFormsUtil.Alert("Selected Language is not available for this game", "Defaulting to English."); - CB_Lang.SelectedIndex = 2; + private void ChangeLanguage(object sender, EventArgs e) + { + Menu_Options.DropDown.Close(); + if (Editor == null) + return; + + if (Editor.Game.GetGeneration() < 7 && Language > 7) + { + WinFormsUtil.Alert("Selected Language is not available for this game", "Defaulting to English."); + CB_Lang.SelectedIndex = 2; + return; + } + Editor.Language = Language; + } + + private void Menu_Open_Click(object sender, EventArgs e) + { + using var fbd = new FolderBrowserDialog(); + if (fbd.ShowDialog() == DialogResult.OK) + OpenPath(fbd.SelectedPath); + } + + private async void Main_FormClosing(object sender, FormClosingEventArgs e) + { + if (Editor == null) + return; + + Editor.Close(); + EditUtil.SaveSettings(Editor.Game); + Settings.Language = CB_Lang.SelectedIndex; + Settings.GamePath = TB_Path.Text; + await SettingsSerializer.SaveSettings(Settings, ProgramSettingsPath); + } + + private void Menu_Exit_Click(object sender, EventArgs e) + { + if (ModifierKeys == Keys.Control) // triggered via hotkey + { + if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, $"Quit {nameof(pkNX)}?")) return; - } - Editor.Language = Language; } + Close(); + } - private void Menu_Open_Click(object sender, EventArgs e) + private void Menu_SetRNGSeed_Click(object sender, EventArgs e) + { + var result = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Reseed RNG?", + "If yes, copy the 32 bit (not hex) integer seed to the clipboard before hitting Yes."); + if (DialogResult.Yes != result) + return; + + string val = string.Empty; + try { val = Clipboard.GetText(); } + catch { } + if (int.TryParse(val, out int seed)) { - using var fbd = new FolderBrowserDialog(); - if (fbd.ShowDialog() == DialogResult.OK) - OpenPath(fbd.SelectedPath); + Util.Rand = new Random(seed); + WinFormsUtil.Alert($"Reseeded RNG to seed: {seed}"); + return; } + WinFormsUtil.Alert("Unable to set seed."); + } - private void Main_FormClosing(object sender, FormClosingEventArgs e) + private void OpenPath(string path) + { + try { - if (Editor == null) - return; - - Editor.Close(); - EditUtil.SaveSettings(Editor.Game); - Settings.Default.Language = CB_Lang.SelectedIndex; - Settings.Default.GamePath = TB_Path.Text; - Settings.Default.Save(); + if (Directory.Exists(path)) + OpenFolder(path); + else + OpenFile(path); } - - private void Menu_Exit_Click(object sender, EventArgs e) + catch (Exception ex) { - if (ModifierKeys == Keys.Control) // triggered via hotkey - { - if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, $"Quit {nameof(pkNX)}?")) - return; - } - Close(); - } - - private void Menu_SetRNGSeed_Click(object sender, EventArgs e) - { - var result = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Reseed RNG?", - "If yes, copy the 32 bit (not hex) integer seed to the clipboard before hitting Yes."); - if (DialogResult.Yes != result) - return; - - string val = string.Empty; - try { val = Clipboard.GetText(); } - catch { } - if (int.TryParse(val, out int seed)) - { - Util.Rand = new Random(seed); - WinFormsUtil.Alert($"Reseeded RNG to seed: {seed}"); - return; - } - WinFormsUtil.Alert("Unable to set seed."); - } - - private void OpenPath(string path) - { - try - { - if (Directory.Exists(path)) - OpenFolder(path); - else - OpenFile(path); - } - catch (Exception ex) - { - WinFormsUtil.Error($"Failed to open -- {path}", ex.Message); - } - } - - private static void OpenFile(string path) - { - var result = FileRipper.TryOpenFile(path); - if (result.Code != RipResultCode.Success) - { - WinFormsUtil.Alert("Invalid file loaded." + Environment.NewLine + $"Unable to recognize data: {result.Code}.", path); - return; - } - - System.Media.SystemSounds.Asterisk.Play(); - Process.Start("explorer.exe", result.ResultPath); - } - - private void OpenFolder(string path) - { - var editor = EditorBase.GetEditor(path, Language); - if (editor == null) - { - WinFormsUtil.Alert("Invalid folder loaded." + Environment.NewLine + "Unable to recognize game data.", path); - return; - } - - try - { - editor.Initialize(); - LoadROM(editor); - } - catch (Exception ex) - { - WinFormsUtil.Error("Failed to initialize ROM data." + Environment.NewLine + "Please ensure your dump is correctly set up, with updated patches merged in (if applicable).", ex.Message, ex.StackTrace); - } - } - - private void LoadROM(EditorBase editor) - { - Editor = editor; - var ctrl = Editor.GetControls(120, 35).OrderBy(x => x.Text); - FLP_Controls.Controls.Clear(); - foreach (var c in ctrl) - FLP_Controls.Controls.Add(c); - - Text = $"{nameof(pkNX)} - {Editor.Game}"; - TB_Path.Text = Editor.Location; - Menu_Current.Enabled = true; - EditUtil.LoadSettings(Editor.Game); - EditUtil.SaveSettings(Editor.Game); - SpriteUtil.Initialize(); - System.Media.SystemSounds.Asterisk.Play(); - } - - private void Menu_Current_Click(object sender, EventArgs e) - { - if (Directory.Exists(TB_Path.Text)) - Process.Start("explorer.exe", TB_Path.Text); - } - - private void Menu_Save_Click(object sender, EventArgs e) - { - Editor?.Save(); + WinFormsUtil.Error($"Failed to open -- {path}", ex.Message); } } + + private static void OpenFile(string path) + { + var result = FileRipper.TryOpenFile(path); + if (result.Code != RipResultCode.Success || result.ResultPath is not { } resultPath) + { + WinFormsUtil.Alert("Invalid file loaded." + Environment.NewLine + $"Unable to recognize data: {result.Code}.", path); + return; + } + + System.Media.SystemSounds.Asterisk.Play(); + Process.Start("explorer.exe", resultPath); + } + + private void OpenFolder(string path) + { + var editor = EditorBase.GetEditor(path, Language); + if (editor == null) + { + var msg = "Invalid folder loaded." + Environment.NewLine + "Unable to recognize game data."; + WinFormsUtil.Alert(msg, path); + return; + } + + try + { + editor.Initialize(); + LoadROM(editor); + } + catch (Exception ex) + { + var msg = "Failed to initialize ROM data." + Environment.NewLine + + "Please ensure your dump is correctly set up, with updated patches merged in (if applicable)."; + var stack = ex.StackTrace ?? string.Empty; + WinFormsUtil.Error(msg, ex.Message, stack); + } + } + + private void LoadROM(EditorBase editor) + { + Editor = editor; + var ctrl = Editor.GetControls(120, 35).OrderBy(x => x.Text); + FLP_Controls.Controls.Clear(); + foreach (var c in ctrl) + FLP_Controls.Controls.Add(c); + + Text = $"{nameof(pkNX)} - {Editor.Game}"; + TB_Path.Text = Editor.Location; + Menu_Current.Enabled = true; + EditUtil.LoadSettings(Editor.Game); + EditUtil.SaveSettings(Editor.Game); + SpriteUtil.Initialize(); + System.Media.SystemSounds.Asterisk.Play(); + } + + private void Menu_Current_Click(object sender, EventArgs e) + { + if (Directory.Exists(TB_Path.Text)) + Process.Start("explorer.exe", TB_Path.Text); + } + + private void Menu_Save_Click(object sender, EventArgs e) + { + Editor?.Save(); + } } diff --git a/pkNX.WinForms/MainEditor/EditUtil.cs b/pkNX.WinForms/MainEditor/EditUtil.cs index 337b959f..b4616aee 100644 --- a/pkNX.WinForms/MainEditor/EditUtil.cs +++ b/pkNX.WinForms/MainEditor/EditUtil.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Diagnostics; using System.IO; using System.Windows.Forms; @@ -6,66 +6,67 @@ using pkNX.Randomization; using pkNX.Structures; -namespace pkNX.WinForms +namespace pkNX.WinForms; + +[Serializable] +public class SharedSettings { - [Serializable] - public class SharedSettings + public PersonalRandSettings Personal { get; set; } = new(); + public SpeciesSettings Species { get; set; } = new(); + public TrainerRandSettings Trainer { get; set; } = new(); + public MovesetRandSettings Move { get; set; } = new(); + public LearnSettings Learn { get; set; } = new(); +} + +public static class EditUtil +{ + public static SharedSettings Settings { get; set; } = new(); + + public static void LoadSettings(GameVersion game) { - public PersonalRandSettings Personal { get; set; } = new(); - public SpeciesSettings Species { get; set; } = new(); - public TrainerRandSettings Trainer { get; set; } = new(); - public MovesetRandSettings Move { get; set; } = new(); - public LearnSettings Learn { get; set; } = new(); + string path = GetSettingsFileName(game); + if (!File.Exists(path)) + { + Settings = new SharedSettings(); + return; + } + + using var file = File.OpenRead(path); + var reader = new XmlSerializer(typeof(SharedSettings)); + try + { + Settings = (SharedSettings?) reader.Deserialize(file) ?? new SharedSettings(); + } + catch (Exception e) + { + Debug.WriteLine(e.Message); + } } - public static class EditUtil + public static void SaveSettings(GameVersion game) { - public static SharedSettings Settings { get; set; } = new(); - - public static void LoadSettings(GameVersion game) + string path = GetSettingsFileName(game); + using var file = File.Create(path); + var writer = new XmlSerializer(typeof(SharedSettings)); + try { - string path = GetSettingsFileName(game); + writer.Serialize(file, Settings); + } + catch (Exception e) + { + Debug.WriteLine(e.Message); if (!File.Exists(path)) - { - Settings = new SharedSettings(); return; - } - - using var file = File.OpenRead(path); - var reader = new XmlSerializer(typeof(SharedSettings)); - try - { - Settings = (SharedSettings?) reader.Deserialize(file) ?? new SharedSettings(); - } - catch (Exception e) - { - Debug.WriteLine(e.Message); - } + file.Close(); + File.Delete(path); } + } - public static void SaveSettings(GameVersion game) - { - string path = GetSettingsFileName(game); - using var file = File.Create(path); - var writer = new XmlSerializer(typeof(SharedSettings)); - try - { - writer.Serialize(file, Settings); - } - catch (Exception e) - { - Debug.WriteLine(e.Message); - if (!File.Exists(path)) - return; - file.Close(); - File.Delete(path); - } - } - - private static string GetSettingsFileName(GameVersion game) - { - var path = Path.GetDirectoryName(Application.ExecutablePath); - return Path.Combine(path, $"randsetting{game}.xml"); - } + private static string GetSettingsFileName(GameVersion game) + { + var path = Path.GetDirectoryName(Application.StartupPath); + if (path is null) + throw new ArgumentNullException(nameof(path)); + return Path.Combine(path, $"randsetting{game}.xml"); } } diff --git a/pkNX.WinForms/MainEditor/EditorGG.cs b/pkNX.WinForms/MainEditor/EditorGG.cs index 0dd35761..72d10bb3 100644 --- a/pkNX.WinForms/MainEditor/EditorGG.cs +++ b/pkNX.WinForms/MainEditor/EditorGG.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Linq; using System.Windows.Forms; @@ -8,379 +8,378 @@ using pkNX.Structures; using pkNX.Structures.FlatBuffers; -namespace pkNX.WinForms.Controls +namespace pkNX.WinForms.Controls; + +internal class EditorGG : EditorBase { - internal class EditorGG : EditorBase + private GameData Data => ((GameManagerGG)ROM).Data; + protected internal EditorGG(GameManagerGG rom) : base(rom) { } + + public void EditCommon() { - private GameData Data => ((GameManagerGG)ROM).Data; - protected internal EditorGG(GameManagerGG rom) : base(rom) { } + 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 EditCommon() + 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 { - 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(); - } + 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.TrainerData), + TrainerPoke = ROM.GetFilteredFolder(GameFile.TrainerPoke), + TrainerClass = ROM.GetFilteredFolder(GameFile.TrainerClass), + }; + editor.Initialize(); + using var form = new BTTE(Data, editor, ROM); + form.ShowDialog(); + if (!form.Modified) + editor.CancelEdits(); + else + editor.Save(); + } - public void EditScript() + public void EditPokémon() + { + var editor = new PokeEditor { - 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(); - } + 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 EditTrainers() + public void EditItems() + { + var obj = ROM.GetFilteredFolder(GameFile.ItemStats, z => new FileInfo(z).Length == 36); + var cache = new DataCache(obj) { - 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.TrainerData), - TrainerPoke = ROM.GetFilteredFolder(GameFile.TrainerPoke), - TrainerClass = ROM.GetFilteredFolder(GameFile.TrainerClass), - }; - 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; - } - + 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(); - Data.MoveData.ClearAll(); // force reload if used again + } + + 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; } - public void EditGift() + cache.Save(); + Data.MoveData.ClearAll(); // force reload if used again + } + + public void EditGift() + { + var file = ROM[GameFile.EncounterGift]; + 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 file = ROM[GameFile.EncounterGift]; - 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); + 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.GetRandomForme((int)t.Species, false, false, true, false, Data.PersonalData.Table); + t.Nature = Nature.Random25; + t.Gender = FixedGender.Random; + t.Shiny = Shiny.Random; + t.RelearnMoves = new[] { 0, 0, 0, 0 }; + if (t.IV_HP != -4) + t.IVs = new[] { -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.EncounterTrade]; + 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.GetRandomForme((int)t.Species, false, false, true, false, 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 = new[] { 0, 0, 0, 0 }; + if (t.IV_HP != -4) + t.IVs = new[] { -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.EncounterStatic]; + 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.GetRandomForme((int)t.Species, false, false, true, false, Data.PersonalData.Table); + t.Nature = Nature.Random25; + t.Gender = FixedGender.Random; + t.Shiny = Shiny.Random; + t.RelearnMoves = new[] { 0, 0, 0, 0 }; + if (t.IV_HP != -4) + t.IVs = new[] { -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((GameManagerGG)ROM, obj); + if (form.ShowDialog() != DialogResult.OK) + return; + + data = FlatBufferConverter.SerializeFrom(obj); + 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.Types); + 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.Shop1; + var names = table.Select((z, _) => $"{(z.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(Shop1)} Editor", Randomize); + form.ShowDialog(); + if (!form.Modified) + { + arc.CancelEdits(); + return; + } 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) + for (int s = 1; s < table.Length; s++) // skip first table with TMs (unobtainable otherwise) { - t.Species = (Species)srand.GetRandomSpecies((int)t.Species); - t.Form = frand.GetRandomForme((int)t.Species, false, false, true, false, Data.PersonalData.Table); - t.Nature = Nature.Random25; - t.Gender = FixedGender.Random; - t.Shiny = Shiny.Random; - t.RelearnMoves = new[] { 0, 0, 0, 0 }; - if (t.IV_HP != -4) - t.IVs = new[] { -1, -1, -1, -1, -1, -1 }; + var shopDefinition = table[s]; + var items = shopDefinition.Inventory.Items; + for (int i = 0; i < items.Length; i++) + items[i] = PossibleHeldItems[Randomization.Util.Random.Next(PossibleHeldItems.Length)]; } } - - using var form = new GenericEditor(cache, names, "Gift Editor", Randomize); + } + else + { + var table = shop.Shop2; + var names = table.Select((z, _) => $"{(z.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(Shop2)} 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.EncounterTrade]; - 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); + { + arc.CancelEdits(); + return; + } 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) + foreach (var shopDefinition in table) { - t.Species = (Species)srand.GetRandomSpecies((int)t.Species); - t.RequiredSpecies = (Species)srand.GetRandomSpecies((int)t.Species); - t.Form = frand.GetRandomForme((int)t.Species, false, false, true, false, 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 = new[] { 0, 0, 0, 0 }; - if (t.IV_HP != -4) - t.IVs = new[] { -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.EncounterStatic]; - 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.GetRandomForme((int)t.Species, false, false, true, false, Data.PersonalData.Table); - t.Nature = Nature.Random25; - t.Gender = FixedGender.Random; - t.Shiny = Shiny.Random; - t.RelearnMoves = new[] { 0, 0, 0, 0 }; - if (t.IV_HP != -4) - t.IVs = new[] { -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((GameManagerGG)ROM, obj); - if (form.ShowDialog() != DialogResult.OK) - return; - - data = FlatBufferConverter.SerializeFrom(obj); - 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.Types); - 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.Shop1; - var names = table.Select((z, _) => $"{(z.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(Shop1)} Editor", Randomize); - form.ShowDialog(); - if (!form.Modified) - { - arc.CancelEdits(); - return; - } - - void Randomize() - { - for (int s = 1; s < table.Length; s++) // skip first table with TMs (unobtainable otherwise) + foreach (var inv in shopDefinition.Inventories) { - var shopDefinition = table[s]; - var items = shopDefinition.Inventory.Items; + var items = inv.Items; for (int i = 0; i < items.Length; i++) items[i] = PossibleHeldItems[Randomization.Util.Random.Next(PossibleHeldItems.Length)]; } } } - else - { - var table = shop.Shop2; - var names = table.Select((z, _) => $"{(z.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(Shop2)} 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.Length; i++) - items[i] = PossibleHeldItems[Randomization.Util.Random.Next(PossibleHeldItems.Length)]; - } - } - } - } - arc[0] = FlatBufferConverter.SerializeFrom(shop); } + arc[0] = FlatBufferConverter.SerializeFrom(shop); } } diff --git a/pkNX.WinForms/MainEditor/EditorPLA.cs b/pkNX.WinForms/MainEditor/EditorPLA.cs index e52e1aff..dc1dcbeb 100644 --- a/pkNX.WinForms/MainEditor/EditorPLA.cs +++ b/pkNX.WinForms/MainEditor/EditorPLA.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -57,7 +57,7 @@ public void EditTrainers() Create = FlatBufferConverter.DeserializeFrom, Write = FlatBufferConverter.SerializeFrom, }; - var names = folder.GetPaths().Select(Path.GetFileNameWithoutExtension).ToArray(); + var names = folder.GetPaths().Select(s => Path.GetFileNameWithoutExtension(s)!).ToArray(); using var form = new GenericEditor(cache, names, "Trainers", Randomize, canSave: true); form.ShowDialog(); diff --git a/pkNX.WinForms/MainEditor/EditorProvider.cs b/pkNX.WinForms/MainEditor/EditorProvider.cs index 6b78c360..dee1cbd4 100644 --- a/pkNX.WinForms/MainEditor/EditorProvider.cs +++ b/pkNX.WinForms/MainEditor/EditorProvider.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Reflection; using System.Text; @@ -6,117 +6,116 @@ using pkNX.Game; using pkNX.Structures; -namespace pkNX.WinForms.Controls +namespace pkNX.WinForms.Controls; + +public abstract class EditorBase { - public abstract class EditorBase + protected readonly GameManager ROM; + + public GameVersion Game => ROM.Game; + public int Language { get => ROM.Language; set => ROM.Language = value; } + + protected EditorBase(GameManager rom) => ROM = rom; + public string? Location { get; internal set; } + + public void Initialize() => ROM.Initialize(); + + private static string GetEditorName(string name) { - protected readonly GameManager ROM; + var newName = name.Replace('_', ' ').ToCharArray(); + var builder = new StringBuilder(); - public GameVersion Game => ROM.Game; - public int Language { get => ROM.Language; set => ROM.Language = value; } + // Force first char to upper + newName[0] = char.ToUpper(newName[0]); - protected EditorBase(GameManager rom) => ROM = rom; - public string? Location { get; internal set; } - - public void Initialize() => ROM.Initialize(); - - private static string GetEditorName(string name) + for (int i = 0; i < newName.Length; ++i) { - var newName = name.Replace('_', ' ').ToCharArray(); - var builder = new StringBuilder(); + char c = newName[i]; + builder.Append(c); - // Force first char to upper - newName[0] = char.ToUpper(newName[0]); + // Check the next char + if (i + 1 >= newName.Length) + continue; + char nextC = newName[i + 1]; - for (int i = 0; i < newName.Length; ++i) + // If current is space, replace next with upper char + if (c == ' ') { - char c = newName[i]; - builder.Append(c); - - // Check the next char - if (i + 1 >= newName.Length) - continue; - char nextC = newName[i + 1]; - - // If current is space, replace next with upper char - if (c == ' ') - { - newName[i + 1] = char.ToUpper(nextC); - } - // If current is lower and next is upper, add a space in between - else if (char.IsLower(c) && char.IsUpper(nextC)) - { - builder.Append(' '); - } - // If previous is upper, current is upper and next is lower, add a space in between - else if (i + 2 < newName.Length && char.IsUpper(c) && char.IsUpper(nextC) && char.IsLower(newName[i + 2])) - { - builder.Append(' '); - } + newName[i + 1] = char.ToUpper(nextC); } - return builder.ToString(); - } - - public IEnumerable