From 5a3ebec12b58dee09cd06ea42ee3c34533ef0e69 Mon Sep 17 00:00:00 2001 From: Kurt Date: Sat, 17 May 2025 15:03:42 -0500 Subject: [PATCH] Fix characteristic of all-0 IV mons when EC%6!=0 They'll always be HP. ty Anubis for testing and SirToastyToes for reporting Changing characteristic is a 1 in (5/6)*(32^6) chance, when no IVs are forced; aka ~1:900million or just get a colo e-reader mon with 5/6 chance :) Gen4/HOME(mobile): correct, unaffected Gen5-Gen9/HOME(switch): bugged --- PKHeX.Core/PKM/PA8.cs | 2 +- PKHeX.Core/PKM/PK5.cs | 2 +- PKHeX.Core/PKM/PK9.cs | 2 +- PKHeX.Core/PKM/Shared/G6PKM.cs | 2 +- PKHeX.Core/PKM/Shared/G8PKM.cs | 2 +- PKHeX.Core/PKM/Util/EntityCharacteristic.cs | 9 +++++++++ 6 files changed, 14 insertions(+), 5 deletions(-) diff --git a/PKHeX.Core/PKM/PA8.cs b/PKHeX.Core/PKM/PA8.cs index 56215339e..87635a920 100644 --- a/PKHeX.Core/PKM/PA8.cs +++ b/PKHeX.Core/PKM/PA8.cs @@ -79,7 +79,7 @@ public override byte CurrentFriendship public override bool IsUntraded => Data[0xB8] == 0 && Data[0xB8 + 1] == 0 && Format == Generation; // immediately terminated HandlingTrainerName data (\0) // Complex Generated Attributes - public override int Characteristic => EntityCharacteristic.GetCharacteristic(EncryptionConstant, IV32); + public override int Characteristic => EntityCharacteristic.GetCharacteristicInit0(EncryptionConstant, IV32); // Methods protected override byte[] Encrypt() diff --git a/PKHeX.Core/PKM/PK5.cs b/PKHeX.Core/PKM/PK5.cs index dc15a63f4..d880a1966 100644 --- a/PKHeX.Core/PKM/PK5.cs +++ b/PKHeX.Core/PKM/PK5.cs @@ -289,7 +289,7 @@ public override string Nickname // Generated Attributes public override uint PSV => ((PID >> 16) ^ (PID & 0xFFFF)) >> 3; public override uint TSV => (uint)(TID16 ^ SID16) >> 3; - public override int Characteristic => EntityCharacteristic.GetCharacteristic(PID, IV32); + public override int Characteristic => EntityCharacteristic.GetCharacteristicInit0(PID, IV32); // Maximums public override ushort MaxMoveID => Legal.MaxMoveID_5; diff --git a/PKHeX.Core/PKM/PK9.cs b/PKHeX.Core/PKM/PK9.cs index fc9396a53..89134acf6 100644 --- a/PKHeX.Core/PKM/PK9.cs +++ b/PKHeX.Core/PKM/PK9.cs @@ -74,7 +74,7 @@ public override byte CurrentFriendship public bool IsUnhatchedEgg => Version == 0 && IsEgg; // Complex Generated Attributes - public override int Characteristic => EntityCharacteristic.GetCharacteristic(EncryptionConstant, IV32); + public override int Characteristic => EntityCharacteristic.GetCharacteristicInit0(EncryptionConstant, IV32); // Methods protected override byte[] Encrypt() diff --git a/PKHeX.Core/PKM/Shared/G6PKM.cs b/PKHeX.Core/PKM/Shared/G6PKM.cs index f5dbafac1..0a8478a0c 100644 --- a/PKHeX.Core/PKM/Shared/G6PKM.cs +++ b/PKHeX.Core/PKM/Shared/G6PKM.cs @@ -45,7 +45,7 @@ public byte OppositeFriendship // Complex Generated Attributes public abstract uint IV32 { get; set; } - public override int Characteristic => EntityCharacteristic.GetCharacteristic(EncryptionConstant, IV32); + public override int Characteristic => EntityCharacteristic.GetCharacteristicInit0(EncryptionConstant, IV32); // Methods protected sealed override byte[] Encrypt() diff --git a/PKHeX.Core/PKM/Shared/G8PKM.cs b/PKHeX.Core/PKM/Shared/G8PKM.cs index 15f05e9b8..14f18d0a9 100644 --- a/PKHeX.Core/PKM/Shared/G8PKM.cs +++ b/PKHeX.Core/PKM/Shared/G8PKM.cs @@ -55,7 +55,7 @@ public override byte CurrentFriendship public override bool IsUntraded => Data[0xA8] == 0 && Data[0xA8 + 1] == 0 && Format == Generation; // immediately terminated HandlingTrainerName data (\0) // Complex Generated Attributes - public override int Characteristic => EntityCharacteristic.GetCharacteristic(EncryptionConstant, IV32); + public override int Characteristic => EntityCharacteristic.GetCharacteristicInit0(EncryptionConstant, IV32); // Methods protected override byte[] Encrypt() diff --git a/PKHeX.Core/PKM/Util/EntityCharacteristic.cs b/PKHeX.Core/PKM/Util/EntityCharacteristic.cs index 45ee88ab7..4d367486f 100644 --- a/PKHeX.Core/PKM/Util/EntityCharacteristic.cs +++ b/PKHeX.Core/PKM/Util/EntityCharacteristic.cs @@ -28,6 +28,15 @@ public static int GetCharacteristic(uint ec, uint iv32) return GetCharacteristic(maxStatIndex, maxStatValue); } + /// + /// + /// Generations 5-9(+?) initialize the "best" characteristic index to 0 (HP). + /// In the event that all IVs are 0, the characteristic index is also 0, regardless of EC % 6. + /// The original implementation in Gen4 has the "correct" behavior, being based on EC % 6; as does HOME on mobile. + /// Only formats that display the all-zero-IV characteristic as always-"HP" reference this method. + /// + public static int GetCharacteristicInit0(uint ec, uint iv32) => iv32 == 0 ? 0 : GetCharacteristic(ec, iv32); + /// /// Gets the characteristic index of the given unpacked IVs. ///