diff --git a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonStrings.cs b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonStrings.cs
index ffb46a0d5..66e156b77 100644
--- a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonStrings.cs
+++ b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonStrings.cs
@@ -7,7 +7,7 @@ namespace PKHeX.Core;
///
/// String Translation Utility
///
-public class RibbonStrings
+public sealed class RibbonStrings
{
private readonly Dictionary RibbonNames = [];
diff --git a/PKHeX.Core/Saves/Pokeathlon4.cs b/PKHeX.Core/Saves/Pokeathlon4.cs
index e59ce3114..bd3e347b8 100644
--- a/PKHeX.Core/Saves/Pokeathlon4.cs
+++ b/PKHeX.Core/Saves/Pokeathlon4.cs
@@ -7,7 +7,7 @@ namespace PKHeX.Core;
///
/// Manages the Pokeathlon Data for
///
-public class Pokeathlon4(Memory Raw) // 0xD9D4 within SAV4HGSS
+public sealed class Pokeathlon4(Memory Raw) // 0xD9D4 within SAV4HGSS
{
public const int SIZE = 0xB80;
diff --git a/PKHeX.Core/Saves/SAV4.cs b/PKHeX.Core/Saves/SAV4.cs
index 8619ad110..591efd790 100644
--- a/PKHeX.Core/Saves/SAV4.cs
+++ b/PKHeX.Core/Saves/SAV4.cs
@@ -237,7 +237,7 @@ private int GetActiveExtraBlock(BlockInfo4 block)
private int OFS_Backdrop => FashionCase + 0x28;
protected int OFS_Chatter = int.MinValue;
- public Chatter4 Chatter => new(this, GeneralBuffer[OFS_Chatter..]);
+ public Chatter4 Chatter => new(GeneralBuffer.Slice(OFS_Chatter, Chatter4.SIZE));
protected int OFS_Record = int.MinValue;
public Record4 Records => new(this, GeneralBuffer.Slice(OFS_Record, Record4.GetSize(this)));
diff --git a/PKHeX.Core/Saves/Substructures/Gen3/Roamer3.cs b/PKHeX.Core/Saves/Substructures/Gen3/Roamer3.cs
index f9c245390..4d0a43cb6 100644
--- a/PKHeX.Core/Saves/Substructures/Gen3/Roamer3.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen3/Roamer3.cs
@@ -50,7 +50,7 @@ public byte CurrentLevel
public byte ContestSmart { get => Data[0x11]; set => Data[0x11] = value; }
public byte ContestTough { get => Data[0x12]; set => Data[0x12] = value; }
public byte ContestSheen { get => 0; set { } }
- public bool Active { get => Data[0x13] == 1; set => Data[0x13] = value ? (byte)1 : (byte)0; }
+ public bool IsActive { get => Data[0x13] == 1; set => Data[0x13] = value ? (byte)1 : (byte)0; }
// Derived Properties
public int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | (uint)((value > 31 ? 31 : value) << 00); }
diff --git a/PKHeX.Core/Saves/Substructures/Gen4/Chatter4.cs b/PKHeX.Core/Saves/Substructures/Gen4/Chatter4.cs
index b12ff1bd4..444935cc4 100644
--- a/PKHeX.Core/Saves/Substructures/Gen4/Chatter4.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen4/Chatter4.cs
@@ -6,8 +6,12 @@ namespace PKHeX.Core;
///
/// Generation 4 Chatter Recording
///
-public sealed class Chatter4(SAV4 SAV, Memory raw) : SaveBlock(SAV, raw), IChatter
+public sealed class Chatter4(Memory Raw) : IChatter
{
+ public const int SIZE = sizeof(uint) + IChatter.SIZE_PCM;
+
+ private Span Data => Raw.Span;
+
public bool Initialized
{
get => ReadUInt32LittleEndian(Data) == 1u;
diff --git a/PKHeX.Core/Saves/Substructures/Gen4/PBR/BattlePass.cs b/PKHeX.Core/Saves/Substructures/Gen4/PBR/BattlePass.cs
index ea11bafcc..96abc73c0 100644
--- a/PKHeX.Core/Saves/Substructures/Gen4/PBR/BattlePass.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen4/PBR/BattlePass.cs
@@ -7,7 +7,7 @@ namespace PKHeX.Core;
///
/// Pokémon Battle Revolution Battle Pass Structure
///
-public class BattlePass(Memory raw)
+public sealed class BattlePass(Memory raw)
{
public const int Size = 0x6EC;
public const int PokeSize = PokeCrypto.SIZE_4STORED + 4;
diff --git a/PKHeX.Core/Saves/Substructures/Gen4/Record4.cs b/PKHeX.Core/Saves/Substructures/Gen4/Record4.cs
index 9c48627d2..bd75bfc5e 100644
--- a/PKHeX.Core/Saves/Substructures/Gen4/Record4.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen4/Record4.cs
@@ -240,10 +240,65 @@ public enum Record4PtIndex
public enum Record4HGSSIndex
{
// u32
- ApricornGet = 1,
+ StepsWalked = 0,
+ StepsBiked = 1,
Score = 2,
- BadgeGet = 22,
- BattlePoints = 69,
+
+ BerriesPlanted = 5,
+
+ WildEncounters = 8,
+ TrainerBattles = 9,
+ Caught = 10,
+ Fished = 11,
+ EggsHatched = 12,
+ PokedexProgress = 13,
+
+ LocalLinkTrades = 20,
+ LocalLinkBattles = 21,
+ LocalLinkBattleWins = 22,
+ LocalLinkBattleLosses = 23,
+ LocalLinkBattleDraws = 24, // and forfeits
+ WifiTrades = 25,
+ WifiBattles = 26,
+ WifiBattleWins = 27,
+ WifiBattleLosses = 28,
+ WifiBattleDraws = 29, // and forfeits
+
+ BattleTowerWins = 30,
+
+ CurrencySpent = 36,
+ DepositedDaycare = 41,
+ OpponentsFainted = 42,
+
+ MailWritten = 46,
+
+ PremierBallsEarned = 51,
+
+ FrontierParticipations = 59,
+
+ BattlePointsReceived = 69,
+ BattlePointsSpent = 70,
+
+ LeagueWins = 74,
+ SplashUsed = 77,
+
+ SelfDestructUsed = 79,
+ ExplosionUsed = 80,
+
+ LocalContestEntries = 91,
+ CommContestEntries = 92,
+ LocalContestWins = 93,
+ CommContestWins = 94,
+ RibbonsEarned = 95,
+ IneffectiveMovesUsed = 96,
+ PlayerMonFainted = 97,
+ AlliesDamaged = 98,
+ RunFailures = 99,
+ WildPokemonFled = 100,
+ FishGotAway = 101,
+ TrainerCardsSigned = 115,
+ FossilsRevived = 116,
+ EggsSpun = 120,
// u16
FirstU16 = Record32HGSS,
diff --git a/PKHeX.Core/Saves/Substructures/Gen4/Roamer4.cs b/PKHeX.Core/Saves/Substructures/Gen4/Roamer4.cs
index 6aa228ffd..1bac05919 100644
--- a/PKHeX.Core/Saves/Substructures/Gen4/Roamer4.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen4/Roamer4.cs
@@ -23,7 +23,7 @@ public sealed class Roamer4(Memory Raw)
public ushort Stat_HPCurrent { get => ReadUInt16LittleEndian(Data[0xE..]); set => WriteUInt16LittleEndian(Data[0xE..], value); }
public byte Level { get => Data[0x10]; set => Data[0x10] = value; }
public byte Status { get => Data[0x11]; set => Data[0x11] = value; }
- public bool Active { get => Data[0x12] != 0; set => Data[0x12] = (byte)(value ? 1 : 0); }
+ public bool IsActive { get => Data[0x12] != 0; set => Data[0x12] = (byte)(value ? 1 : 0); }
// 0x13 alignment, unused
// Derived Properties
diff --git a/PKHeX.Core/Saves/Substructures/Gen5/Roamer5.cs b/PKHeX.Core/Saves/Substructures/Gen5/Roamer5.cs
index 356be0669..dafeff671 100644
--- a/PKHeX.Core/Saves/Substructures/Gen5/Roamer5.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen5/Roamer5.cs
@@ -23,7 +23,7 @@ public sealed class Roamer5(Memory raw)
public ushort Stat_HPCurrent { get => ReadUInt16LittleEndian(Data[0x0E..]); set => WriteUInt16LittleEndian(Data[0x0E..], value); }
public byte Level { get => Data[0x10]; set => Data[0x10] = value; }
public byte Status { get => Data[0x11]; set => Data[0x11] = value; }
- public bool Active { get => Data[0x12] != 0; set => Data[0x12] = (byte)(value ? 1 : 0); }
+ public bool IsActive { get => Data[0x12] != 0; set => Data[0x12] = (byte)(value ? 1 : 0); }
public byte Unk13 { get => Data[0x13]; set => Data[0x13] = value; } // likely just alignment
// Derived Properties
diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/FieldObjectSave8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/FieldObjectSave8b.cs
index 8265e62e2..1a2918c8c 100644
--- a/PKHeX.Core/Saves/Substructures/Gen8/BS/FieldObjectSave8b.cs
+++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/FieldObjectSave8b.cs
@@ -43,7 +43,7 @@ public sealed class FieldObject8b
private readonly Memory Raw = new byte[SIZE];
private Span Data => Raw.Span;
- public override string ToString() => $"{NameHash:X8} @ ({GridX:000},{GridY:000}) - {(Active ? "✓" : "✕")}";
+ public override string ToString() => $"{NameHash:X8} @ ({GridX:000},{GridY:000}) - {(IsActive ? "✓" : "✕")}";
public FieldObject8b(ReadOnlySpan data) => data[..SIZE].CopyTo(Data);
@@ -58,7 +58,7 @@ public sealed class FieldObject8b
public int GridY { get => ReadInt32LittleEndian(Data[0x0C..]); set => WriteInt32LittleEndian(Data[0x0C..], value); }
public int Height { get => ReadInt32LittleEndian(Data[0x10..]); set => WriteInt32LittleEndian(Data[0x10..], value); }
public int Angle { get => ReadInt32LittleEndian(Data[0x14..]); set => WriteInt32LittleEndian(Data[0x14..], value); }
- public bool Active { get => ReadInt32LittleEndian(Data[0x18..]) == 1; set => WriteUInt32LittleEndian(Data[0x18..], value ? 1u : 0u); }
+ public bool IsActive{ get => ReadInt32LittleEndian(Data[0x18..]) == 1; set => WriteUInt32LittleEndian(Data[0x18..], value ? 1u : 0u); }
public int MoveCode { get => ReadInt32LittleEndian(Data[0x1C..]); set => WriteInt32LittleEndian(Data[0x1C..], value); }
public int DirHead { get => ReadInt32LittleEndian(Data[0x20..]); set => WriteInt32LittleEndian(Data[0x20..], value); }
public int MvParam0 { get => ReadInt32LittleEndian(Data[0x24..]); set => WriteInt32LittleEndian(Data[0x24..], value); }
diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Roamer3.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Roamer3.cs
index e19dce3cb..7a7b01e2d 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Roamer3.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/Gen3/SAV_Roamer3.cs
@@ -36,7 +36,7 @@ private void LoadData()
TB_SPAIV.Text = Reader.IV_SPA.ToString();
TB_SPDIV.Text = Reader.IV_SPD.ToString();
- CHK_Active.Checked = Reader.Active;
+ CHK_Active.Checked = Reader.IsActive;
NUD_Level.Value = Math.Min(Reader.CurrentLevel, NUD_Level.Maximum);
NUD_HP.Value = Math.Min(Reader.HP_Current, NUD_HP.Maximum);
}
@@ -54,7 +54,7 @@ private void SaveData()
Util.ToInt32(TB_SPAIV.Text),
Util.ToInt32(TB_SPDIV.Text),
]);
- Reader.Active = CHK_Active.Checked;
+ Reader.IsActive = CHK_Active.Checked;
Reader.CurrentLevel = (byte)NUD_Level.Value;
Reader.HP_Current = (ushort)NUD_HP.Value;
}
diff --git a/PKHeX.WinForms/Subforms/Save Editors/SAV_Inventory.cs b/PKHeX.WinForms/Subforms/Save Editors/SAV_Inventory.cs
index 91479e8fa..c2482ec9d 100644
--- a/PKHeX.WinForms/Subforms/Save Editors/SAV_Inventory.cs
+++ b/PKHeX.WinForms/Subforms/Save Editors/SAV_Inventory.cs
@@ -298,7 +298,8 @@ private static void Dgv_EditingControlShowing(object? sender, DataGridViewEditin
if (dgv.CurrentCell?.OwningColumn is not DataGridViewComboBoxColumn)
return;
- cb.DroppedDown = true;
+ // let the row reference update, invoke via DataGrid rather than directly call
+ dgv.BeginInvoke((MethodInvoker)(() => cb.DroppedDown = true));
}
private void SetBag(DataGridView dgv, InventoryPouch pouch)