From 8950613422f9631c7d0699ebee8859ab3bb30b37 Mon Sep 17 00:00:00 2001 From: Kurt Date: Sun, 15 Mar 2026 18:25:13 -0500 Subject: [PATCH] Add party import for hall of fame 3 Closes #4754 --- .../Saves/Substructures/Gen3/HallFame3.cs | 41 +++++++++++-- PKHeX.WinForms/Resources/text/lang_de.txt | 1 + PKHeX.WinForms/Resources/text/lang_en.txt | 1 + PKHeX.WinForms/Resources/text/lang_es-419.txt | 1 + PKHeX.WinForms/Resources/text/lang_es.txt | 1 + PKHeX.WinForms/Resources/text/lang_fr.txt | 1 + PKHeX.WinForms/Resources/text/lang_it.txt | 1 + PKHeX.WinForms/Resources/text/lang_ja.txt | 1 + PKHeX.WinForms/Resources/text/lang_ko.txt | 1 + .../Resources/text/lang_zh-Hans.txt | 1 + .../Resources/text/lang_zh-Hant.txt | 1 + .../Gen3/SAV_HallOfFame3.Designer.cs | 58 ++++++++++++------- .../Save Editors/Gen3/SAV_HallOfFame3.cs | 29 ++++++++++ 13 files changed, 112 insertions(+), 26 deletions(-) diff --git a/PKHeX.Core/Saves/Substructures/Gen3/HallFame3.cs b/PKHeX.Core/Saves/Substructures/Gen3/HallFame3.cs index 469a102d4..c29e22135 100644 --- a/PKHeX.Core/Saves/Substructures/Gen3/HallFame3.cs +++ b/PKHeX.Core/Saves/Substructures/Gen3/HallFame3.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using static System.Buffers.Binary.BinaryPrimitives; @@ -19,13 +20,14 @@ private static int GetMemberOffset(int index) private Memory GetMemberSlice(int index) => Raw.Slice(GetMemberOffset(index), HallFame3PKM.SIZE); - private HallFame3PKM GetMember(int index) => new(GetMemberSlice(index), Japanese); + + public HallFame3PKM GetMember(int index) => new(GetMemberSlice(index), Japanese); public HallFame3PKM[] Team { get { - var team = new HallFame3PKM[6]; + var team = new HallFame3PKM[Count]; for (int i = 0; i < Count; i++) team[i] = GetMember(i); return team; @@ -49,13 +51,26 @@ public static HallFame3Entry[] GetEntries(SAV3 sav) public static void SetEntries(SAV3 sav, HallFame3Entry[] entries) { - byte[] data = sav.GetHallOfFameData(); + Span data = sav.GetHallOfFameData(); Debug.Assert(data.Length >= MaxLength); for (int i = 0; i < entries.Length; i++) - entries[i].Data.CopyTo(data.AsSpan(i * SIZE)); + entries[i].Data.CopyTo(data[(i * SIZE)..]); sav.SetHallOfFameData(data); } + + public void CopyFrom(IReadOnlyList party) + { + var length = Math.Min(Count, party.Count); + for (int i = 0; i < length; i++) + GetMember(i).CopyFrom(party[i]); + } + + public void CopyFrom(HallFame3Entry entry) + { + for (int i = 0; i < Count; i++) + GetMember(i).CopyFrom(entry.GetMember(i)); + } } public sealed class HallFame3PKM(Memory Raw, bool Japanese) : ISpeciesForm @@ -104,4 +119,22 @@ public ushort Species }; public bool IsShiny => ShinyUtil.GetIsShiny3(ID32, PID); + + public void CopyFrom(PKM pk) + { + Species = pk.Species; + Level = pk.CurrentLevel; + PID = pk.EncryptionConstant; + ID32 = pk.ID32; + pk.NicknameTrash.CopyTo(NicknameTrash); + } + + public void CopyFrom(HallFame3PKM pk) + { + Species = pk.Species; + Level = pk.Level; + PID = pk.PID; + ID32 = pk.ID32; + pk.NicknameTrash.CopyTo(NicknameTrash); + } } diff --git a/PKHeX.WinForms/Resources/text/lang_de.txt b/PKHeX.WinForms/Resources/text/lang_de.txt index 5a4c3da39..9a2a44d7f 100644 --- a/PKHeX.WinForms/Resources/text/lang_de.txt +++ b/PKHeX.WinForms/Resources/text/lang_de.txt @@ -1302,6 +1302,7 @@ SAV_HallOfFame1.L_PartyNum=Party Index: SAV_HallOfFame1.Label_Species=Species: SAV_HallOfFame3.B_Cancel=Cancel SAV_HallOfFame3.B_Clear=Clear +SAV_HallOfFame3.B_ImportParty=Alle aus Team importieren SAV_HallOfFame3.B_Save=Save SAV_HallOfFame3.CHK_Shiny=Shiny SAV_HallOfFame3.L_Level=Level: diff --git a/PKHeX.WinForms/Resources/text/lang_en.txt b/PKHeX.WinForms/Resources/text/lang_en.txt index 7b0cd18f2..59762c045 100644 --- a/PKHeX.WinForms/Resources/text/lang_en.txt +++ b/PKHeX.WinForms/Resources/text/lang_en.txt @@ -1302,6 +1302,7 @@ SAV_HallOfFame1.L_PartyNum=Party Index: SAV_HallOfFame1.Label_Species=Species: SAV_HallOfFame3.B_Cancel=Cancel SAV_HallOfFame3.B_Clear=Clear +SAV_HallOfFame3.B_ImportParty=Import All From Party SAV_HallOfFame3.B_Save=Save SAV_HallOfFame3.CHK_Shiny=Shiny SAV_HallOfFame3.L_Level=Level: diff --git a/PKHeX.WinForms/Resources/text/lang_es-419.txt b/PKHeX.WinForms/Resources/text/lang_es-419.txt index ab54589db..6146f04de 100644 --- a/PKHeX.WinForms/Resources/text/lang_es-419.txt +++ b/PKHeX.WinForms/Resources/text/lang_es-419.txt @@ -1302,6 +1302,7 @@ SAV_HallOfFame1.L_PartyNum=Party Index: SAV_HallOfFame1.Label_Species=Species: SAV_HallOfFame3.B_Cancel=Cancel SAV_HallOfFame3.B_Clear=Clear +SAV_HallOfFame3.B_ImportParty=Importar todo desde el equipo SAV_HallOfFame3.B_Save=Save SAV_HallOfFame3.CHK_Shiny=Shiny SAV_HallOfFame3.L_Level=Level: diff --git a/PKHeX.WinForms/Resources/text/lang_es.txt b/PKHeX.WinForms/Resources/text/lang_es.txt index 55935c5bb..d148189a3 100644 --- a/PKHeX.WinForms/Resources/text/lang_es.txt +++ b/PKHeX.WinForms/Resources/text/lang_es.txt @@ -1302,6 +1302,7 @@ SAV_HallOfFame1.L_PartyNum=Party Index: SAV_HallOfFame1.Label_Species=Especie: SAV_HallOfFame3.B_Cancel=Cancelar SAV_HallOfFame3.B_Clear=Limpiar +SAV_HallOfFame3.B_ImportParty=Importar todo desde el equipo SAV_HallOfFame3.B_Save=Guardar SAV_HallOfFame3.CHK_Shiny=Shiny SAV_HallOfFame3.L_Level=Nivel: diff --git a/PKHeX.WinForms/Resources/text/lang_fr.txt b/PKHeX.WinForms/Resources/text/lang_fr.txt index fa17590c5..0b165136a 100644 --- a/PKHeX.WinForms/Resources/text/lang_fr.txt +++ b/PKHeX.WinForms/Resources/text/lang_fr.txt @@ -1302,6 +1302,7 @@ SAV_HallOfFame1.L_PartyNum=Index équipe : SAV_HallOfFame1.Label_Species=Espèce : SAV_HallOfFame3.B_Cancel=Annuler SAV_HallOfFame3.B_Clear=Effacer +SAV_HallOfFame3.B_ImportParty=Tout importer depuis l'équipe SAV_HallOfFame3.B_Save=Sauvegarder SAV_HallOfFame3.CHK_Shiny=Chromatique SAV_HallOfFame3.L_Level=Niveau : diff --git a/PKHeX.WinForms/Resources/text/lang_it.txt b/PKHeX.WinForms/Resources/text/lang_it.txt index ea59cb4b1..e857ea38a 100644 --- a/PKHeX.WinForms/Resources/text/lang_it.txt +++ b/PKHeX.WinForms/Resources/text/lang_it.txt @@ -1302,6 +1302,7 @@ SAV_HallOfFame1.L_PartyNum=Party Index: SAV_HallOfFame1.Label_Species=Species: SAV_HallOfFame3.B_Cancel=Cancel SAV_HallOfFame3.B_Clear=Clear +SAV_HallOfFame3.B_ImportParty=Importa tutto dalla squadra SAV_HallOfFame3.B_Save=Save SAV_HallOfFame3.CHK_Shiny=Shiny SAV_HallOfFame3.L_Level=Level: diff --git a/PKHeX.WinForms/Resources/text/lang_ja.txt b/PKHeX.WinForms/Resources/text/lang_ja.txt index 5b5306704..dd0768855 100644 --- a/PKHeX.WinForms/Resources/text/lang_ja.txt +++ b/PKHeX.WinForms/Resources/text/lang_ja.txt @@ -1302,6 +1302,7 @@ SAV_HallOfFame1.L_PartyNum=パーティ: SAV_HallOfFame1.Label_Species=ポケモン: SAV_HallOfFame3.B_Cancel=キャンセル SAV_HallOfFame3.B_Clear=クリア +SAV_HallOfFame3.B_ImportParty=手持ちから全員を取り込む SAV_HallOfFame3.B_Save=保存 SAV_HallOfFame3.CHK_Shiny=色違い SAV_HallOfFame3.L_Level=レベル: diff --git a/PKHeX.WinForms/Resources/text/lang_ko.txt b/PKHeX.WinForms/Resources/text/lang_ko.txt index 9e7bdaa36..ce72d119a 100644 --- a/PKHeX.WinForms/Resources/text/lang_ko.txt +++ b/PKHeX.WinForms/Resources/text/lang_ko.txt @@ -1302,6 +1302,7 @@ SAV_HallOfFame1.L_PartyNum=Party Index: SAV_HallOfFame1.Label_Species=Species: SAV_HallOfFame3.B_Cancel=Cancel SAV_HallOfFame3.B_Clear=Clear +SAV_HallOfFame3.B_ImportParty=파티 전체 가져오기 SAV_HallOfFame3.B_Save=Save SAV_HallOfFame3.CHK_Shiny=Shiny SAV_HallOfFame3.L_Level=Level: diff --git a/PKHeX.WinForms/Resources/text/lang_zh-Hans.txt b/PKHeX.WinForms/Resources/text/lang_zh-Hans.txt index f9d8fbb56..7ae4872fd 100644 --- a/PKHeX.WinForms/Resources/text/lang_zh-Hans.txt +++ b/PKHeX.WinForms/Resources/text/lang_zh-Hans.txt @@ -1302,6 +1302,7 @@ SAV_HallOfFame1.L_PartyNum=队伍索引: SAV_HallOfFame1.Label_Species=种类: SAV_HallOfFame3.B_Cancel=取消 SAV_HallOfFame3.B_Clear=清空 +SAV_HallOfFame3.B_ImportParty=从队伍导入全部 SAV_HallOfFame3.B_Save=保存 SAV_HallOfFame3.CHK_Shiny=异色 SAV_HallOfFame3.L_Level=等级: diff --git a/PKHeX.WinForms/Resources/text/lang_zh-Hant.txt b/PKHeX.WinForms/Resources/text/lang_zh-Hant.txt index 98b76dd9e..6c7a07305 100644 --- a/PKHeX.WinForms/Resources/text/lang_zh-Hant.txt +++ b/PKHeX.WinForms/Resources/text/lang_zh-Hant.txt @@ -1302,6 +1302,7 @@ SAV_HallOfFame1.L_PartyNum=Party Index: SAV_HallOfFame1.Label_Species=Species: SAV_HallOfFame3.B_Cancel=Cancel SAV_HallOfFame3.B_Clear=Clear +SAV_HallOfFame3.B_ImportParty=從隊伍匯入全部 SAV_HallOfFame3.B_Save=Save SAV_HallOfFame3.CHK_Shiny=Shiny SAV_HallOfFame3.L_Level=Level: diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_HallOfFame3.Designer.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_HallOfFame3.Designer.cs index 386c6a1e8..06b323dc5 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_HallOfFame3.Designer.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_HallOfFame3.Designer.cs @@ -46,6 +46,7 @@ private void InitializeComponent() CHK_Shiny = new System.Windows.Forms.CheckBox(); B_Clear = new System.Windows.Forms.Button(); PB_Sprite = new System.Windows.Forms.PictureBox(); + B_ImportParty = new System.Windows.Forms.Button(); ((System.ComponentModel.ISupportInitialize)NUD_Members).BeginInit(); ((System.ComponentModel.ISupportInitialize)NUD_Level).BeginInit(); ((System.ComponentModel.ISupportInitialize)PB_Sprite).BeginInit(); @@ -57,20 +58,20 @@ private void InitializeComponent() LB_Entries.FormattingEnabled = true; LB_Entries.Location = new System.Drawing.Point(12, 14); LB_Entries.Name = "LB_Entries"; - LB_Entries.Size = new System.Drawing.Size(120, 191); + LB_Entries.Size = new System.Drawing.Size(120, 242); LB_Entries.TabIndex = 0; // // CB_Species // CB_Species.FormattingEnabled = true; - CB_Species.Location = new System.Drawing.Point(169, 14); + CB_Species.Location = new System.Drawing.Point(223, 87); CB_Species.Name = "CB_Species"; CB_Species.Size = new System.Drawing.Size(119, 25); CB_Species.TabIndex = 2; // // NUD_Members // - NUD_Members.Location = new System.Drawing.Point(344, 14); + NUD_Members.Location = new System.Drawing.Point(181, 14); NUD_Members.Maximum = new decimal(new int[] { 5, 0, 0, 0 }); NUD_Members.Name = "NUD_Members"; NUD_Members.Size = new System.Drawing.Size(35, 25); @@ -80,7 +81,7 @@ private void InitializeComponent() // TB_PID.CharacterCasing = System.Windows.Forms.CharacterCasing.Upper; TB_PID.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 0); - TB_PID.Location = new System.Drawing.Point(224, 101); + TB_PID.Location = new System.Drawing.Point(223, 175); TB_PID.MaxLength = 8; TB_PID.Name = "TB_PID"; TB_PID.Size = new System.Drawing.Size(68, 20); @@ -90,16 +91,16 @@ private void InitializeComponent() // // TB_Nickname // - TB_Nickname.Location = new System.Drawing.Point(224, 43); + TB_Nickname.Location = new System.Drawing.Point(223, 117); TB_Nickname.MaxLength = 10; TB_Nickname.Name = "TB_Nickname"; TB_Nickname.Size = new System.Drawing.Size(120, 25); TB_Nickname.TabIndex = 6; - TB_Nickname.Text = "WWWWWWWWWW"; + TB_Nickname.Text = "WWWWWWWW"; // // L_TID // - L_TID.Location = new System.Drawing.Point(138, 122); + L_TID.Location = new System.Drawing.Point(137, 196); L_TID.Name = "L_TID"; L_TID.Size = new System.Drawing.Size(80, 24); L_TID.TabIndex = 7; @@ -108,7 +109,7 @@ private void InitializeComponent() // // L_SID // - L_SID.Location = new System.Drawing.Point(138, 146); + L_SID.Location = new System.Drawing.Point(137, 220); L_SID.Name = "L_SID"; L_SID.Size = new System.Drawing.Size(80, 24); L_SID.TabIndex = 8; @@ -117,7 +118,7 @@ private void InitializeComponent() // // L_PID // - L_PID.Location = new System.Drawing.Point(138, 98); + L_PID.Location = new System.Drawing.Point(137, 172); L_PID.Name = "L_PID"; L_PID.Size = new System.Drawing.Size(80, 24); L_PID.TabIndex = 9; @@ -126,7 +127,7 @@ private void InitializeComponent() // // L_Nickname // - L_Nickname.Location = new System.Drawing.Point(138, 41); + L_Nickname.Location = new System.Drawing.Point(137, 115); L_Nickname.Name = "L_Nickname"; L_Nickname.Size = new System.Drawing.Size(80, 24); L_Nickname.TabIndex = 10; @@ -135,7 +136,7 @@ private void InitializeComponent() // // L_Level // - L_Level.Location = new System.Drawing.Point(138, 71); + L_Level.Location = new System.Drawing.Point(137, 145); L_Level.Name = "L_Level"; L_Level.Size = new System.Drawing.Size(80, 24); L_Level.TabIndex = 11; @@ -144,7 +145,7 @@ private void InitializeComponent() // // NUD_Level // - NUD_Level.Location = new System.Drawing.Point(224, 72); + NUD_Level.Location = new System.Drawing.Point(223, 146); NUD_Level.Maximum = new decimal(new int[] { 255, 0, 0, 0 }); NUD_Level.Name = "NUD_Level"; NUD_Level.Size = new System.Drawing.Size(40, 25); @@ -154,7 +155,7 @@ private void InitializeComponent() // B_Save // B_Save.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right; - B_Save.Location = new System.Drawing.Point(389, 185); + B_Save.Location = new System.Drawing.Point(389, 191); B_Save.Name = "B_Save"; B_Save.Size = new System.Drawing.Size(89, 27); B_Save.TabIndex = 13; @@ -165,7 +166,7 @@ private void InitializeComponent() // B_Cancel // B_Cancel.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right; - B_Cancel.Location = new System.Drawing.Point(294, 185); + B_Cancel.Location = new System.Drawing.Point(389, 224); B_Cancel.Name = "B_Cancel"; B_Cancel.Size = new System.Drawing.Size(89, 27); B_Cancel.TabIndex = 14; @@ -175,20 +176,20 @@ private void InitializeComponent() // // TB_TID // - TB_TID.Location = new System.Drawing.Point(224, 124); + TB_TID.Location = new System.Drawing.Point(223, 198); TB_TID.Mask = "00000"; TB_TID.Name = "TB_TID"; - TB_TID.Size = new System.Drawing.Size(40, 25); + TB_TID.Size = new System.Drawing.Size(44, 25); TB_TID.TabIndex = 15; TB_TID.Text = "00000"; TB_TID.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; // // TB_SID // - TB_SID.Location = new System.Drawing.Point(224, 148); + TB_SID.Location = new System.Drawing.Point(223, 222); TB_SID.Mask = "00000"; TB_SID.Name = "TB_SID"; - TB_SID.Size = new System.Drawing.Size(40, 25); + TB_SID.Size = new System.Drawing.Size(44, 25); TB_SID.TabIndex = 16; TB_SID.Text = "00000"; TB_SID.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; @@ -197,7 +198,7 @@ private void InitializeComponent() // CHK_Shiny.AutoSize = true; CHK_Shiny.Enabled = false; - CHK_Shiny.Location = new System.Drawing.Point(298, 101); + CHK_Shiny.Location = new System.Drawing.Point(297, 175); CHK_Shiny.Name = "CHK_Shiny"; CHK_Shiny.Size = new System.Drawing.Size(57, 21); CHK_Shiny.TabIndex = 17; @@ -207,7 +208,7 @@ private void InitializeComponent() // B_Clear // B_Clear.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right; - B_Clear.Location = new System.Drawing.Point(385, 11); + B_Clear.Location = new System.Drawing.Point(389, 14); B_Clear.Name = "B_Clear"; B_Clear.Size = new System.Drawing.Size(89, 27); B_Clear.TabIndex = 18; @@ -218,7 +219,7 @@ private void InitializeComponent() // PB_Sprite // PB_Sprite.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - PB_Sprite.Location = new System.Drawing.Point(389, 53); + PB_Sprite.Location = new System.Drawing.Point(223, 14); PB_Sprite.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); PB_Sprite.Name = "PB_Sprite"; PB_Sprite.Size = new System.Drawing.Size(81, 67); @@ -226,10 +227,22 @@ private void InitializeComponent() PB_Sprite.TabIndex = 32; PB_Sprite.TabStop = false; // + // B_ImportParty + // + B_ImportParty.Anchor = System.Windows.Forms.AnchorStyles.Right; + B_ImportParty.Location = new System.Drawing.Point(389, 65); + B_ImportParty.Name = "B_ImportParty"; + B_ImportParty.Size = new System.Drawing.Size(89, 100); + B_ImportParty.TabIndex = 33; + B_ImportParty.Text = "Import All From Party"; + B_ImportParty.UseVisualStyleBackColor = true; + B_ImportParty.Click += B_ImportParty_Click; + // // SAV_HallOfFame3 // AutoScaleMode = System.Windows.Forms.AutoScaleMode.Inherit; - ClientSize = new System.Drawing.Size(490, 224); + ClientSize = new System.Drawing.Size(490, 263); + Controls.Add(B_ImportParty); Controls.Add(PB_Sprite); Controls.Add(B_Clear); Controls.Add(CHK_Shiny); @@ -282,5 +295,6 @@ private void InitializeComponent() private System.Windows.Forms.CheckBox CHK_Shiny; private System.Windows.Forms.Button B_Clear; private System.Windows.Forms.PictureBox PB_Sprite; + private System.Windows.Forms.Button B_ImportParty; } } diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_HallOfFame3.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_HallOfFame3.cs index c397c3902..8e71d35f6 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_HallOfFame3.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_HallOfFame3.cs @@ -154,4 +154,33 @@ private void ClickNickname(object? sender, EventArgs e) TrashEditor.Show(tb, SAV, pk.NicknameTrash); } + + private void B_ImportParty_Click(object sender, EventArgs e) + { + // assemble party + var party = new PK3[6]; + var partyCount = SAV.PartyCount; + for (int i = 0; i < partyCount; i++) + party[i] = (PK3)SAV.GetPartySlotAtIndex(i); + for (int i = partyCount; i < party.Length; i++) + party[i] = new PK3(); // ensure data is clean + + var current = Fame[prevEntry]; + current.CopyFrom(party); + var pkm = current.GetMember(prevMember); + LoadEntry(pkm); // reload from updated data + + if (ModifierKeys == Keys.Shift) + { + // Apply to all other entries + for (int i = 0; i < Fame.Length; i++) + { + if (i != prevEntry) + Fame[i].CopyFrom(party); + } + } + + UpdateSprite(); + System.Media.SystemSounds.Asterisk.Play(); + } }