diff --git a/PKHeX.Core/Editing/CommonEdits.cs b/PKHeX.Core/Editing/CommonEdits.cs index 41b3d930a..27ded6590 100644 --- a/PKHeX.Core/Editing/CommonEdits.cs +++ b/PKHeX.Core/Editing/CommonEdits.cs @@ -344,7 +344,7 @@ public static void ForceHatchPKM(this PKM pk, ITrainerInfo? tr = null, bool reHa return; pk.IsEgg = false; pk.ClearNickname(); - pk.CurrentFriendship = pk.PersonalInfo.BaseFriendship; + pk.OriginalTrainerFriendship = Math.Min(pk.OriginalTrainerFriendship, EggStateLegality.GetEggHatchFriendship(pk.Context)); if (pk.IsTradedEgg) pk.EggLocation = pk.MetLocation; if (pk.Version == 0) diff --git a/PKHeX.Core/Editing/Saves/Editors/FakeSaveFile.cs b/PKHeX.Core/Editing/Saves/Editors/FakeSaveFile.cs index 0144cfc66..c8e667bb5 100644 --- a/PKHeX.Core/Editing/Saves/Editors/FakeSaveFile.cs +++ b/PKHeX.Core/Editing/Saves/Editors/FakeSaveFile.cs @@ -30,7 +30,7 @@ public sealed class FakeSaveFile : SaveFile public override int BoxCount => 1; public override int GetPartyOffset(int slot) => -1; protected override void SetChecksums() { } - + public override GameVersion Version { get => GameVersion.R; set { } } public override Type PKMType => typeof(PK3); protected override PK3 GetPKM(byte[] data) => BlankPKM; protected override byte[] DecryptPKM(byte[] data) => data; diff --git a/PKHeX.Core/Legality/Encounters/Templates/Shared/EncounterEgg.cs b/PKHeX.Core/Legality/Encounters/Templates/Shared/EncounterEgg.cs index 1df89673c..fa4ecd5b3 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Shared/EncounterEgg.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Shared/EncounterEgg.cs @@ -42,7 +42,7 @@ public PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) var ball = FixedBall; pk.Ball = ball is Ball.None ? (byte)Ball.Poke : (byte)ball; - pk.OriginalTrainerFriendship = pk.PersonalInfo.BaseFriendship; + pk.OriginalTrainerFriendship = EggStateLegality.GetEggHatchFriendship(Context); SetEncounterMoves(pk, version); pk.HealPP(); @@ -51,17 +51,22 @@ public PKM ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) if (gen <= 2) { - if (version != GameVersion.C) + var pk2 = (PK2)pk; + if (version == GameVersion.C) { - pk.OriginalTrainerGender = 0; + // Set met data for Crystal hatch. + pk2.MetLocation = Locations.HatchLocationC; + pk2.MetLevel = 1; + pk2.MetTimeOfDay = rnd.Next(1, 4); // Morning | Day | Night } - else + else // G/S { - pk.MetLocation = Locations.HatchLocationC; - pk.MetLevel = 1; - ((PK2)pk).MetTimeOfDay = rnd.Next(1, 4); // Morning | Day | Night + // G/S can't set any data for Trainer Gender. + pk2.OriginalTrainerGender = 0; } - return pk; + + // No other revisions needed. + return pk2; } SetMetData(pk); diff --git a/PKHeX.Core/Legality/Verifiers/Egg/EggStateLegality.cs b/PKHeX.Core/Legality/Verifiers/Egg/EggStateLegality.cs index d142357d5..2bc287c27 100644 --- a/PKHeX.Core/Legality/Verifiers/Egg/EggStateLegality.cs +++ b/PKHeX.Core/Legality/Verifiers/Egg/EggStateLegality.cs @@ -153,4 +153,29 @@ public static int GetMaximumEggHatchCycles(PKM pk, IEncounterTemplate enc) SL or VL => Locations.HatchLocation9, _ => 0, }; + + /// + /// Gets the initial friendship value for an egg when it is hatched. + /// + public static byte GetEggHatchFriendship(EntityContext context) => context switch + { + // From Gen2->Gen7, the value was 120. + EntityContext.Gen2 => 120, + EntityContext.Gen3 => 120, + EntityContext.Gen4 => 120, + EntityContext.Gen5 => 120, + EntityContext.Gen6 => 120, + EntityContext.Gen7 => 120, + // No eggs in LGP/E. + + // Starting in SW/SH, Friendship was rescaled away from 255 (to 160-ish), so the value is lower than prior. + _ => 100, + }; + + /// + /// Reasonable value for the friendship of an egg when it is hatched. + /// + /// Only use if you're trying to generalize a value for hatched eggs without checking context. + + public const byte EggHatchFriendshipGeneral = 100; } diff --git a/PKHeX.Core/PKM/Interfaces/IHandlerUpdate.cs b/PKHeX.Core/PKM/Interfaces/IHandlerUpdate.cs new file mode 100644 index 000000000..2beac48a6 --- /dev/null +++ b/PKHeX.Core/PKM/Interfaces/IHandlerUpdate.cs @@ -0,0 +1,19 @@ +namespace PKHeX.Core; + +/// +/// Interface exposing a method to adapt the entity to the Handling Trainer. +/// +public interface IHandlerUpdate +{ + /// + /// Indicates if the entity belongs to the . + /// + /// Trainer to check if it originally possessed the entity. + bool BelongsTo(ITrainerInfo tr); + + /// + /// Updates the entity to match the . + /// + /// Trainer that is now in possession of the entity. + void UpdateHandler(ITrainerInfo tr); +} diff --git a/PKHeX.Core/PKM/PA8.cs b/PKHeX.Core/PKM/PA8.cs index 890c4c22f..a0766cbd9 100644 --- a/PKHeX.Core/PKM/PA8.cs +++ b/PKHeX.Core/PKM/PA8.cs @@ -8,7 +8,8 @@ namespace PKHeX.Core; /// Generation 8 format. public sealed class PA8 : PKM, ISanityChecksum, IGanbaru, IAlpha, INoble, ITechRecord, ISociability, IMoveShop8Mastery, IContestStats, IHyperTrain, IScaledSizeValue, IScaledSize3, IGigantamax, IFavorite, IDynamaxLevel, IHandlerLanguage, IFormArgument, IHomeTrack, IBattleVersion, ITrainerMemories, IPokerusStatus, - IRibbonIndex, IRibbonSetAffixed, IRibbonSetRibbons, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetMarks, IRibbonSetMark8, IRibbonSetCommon9, IRibbonSetMark9 + IRibbonIndex, IRibbonSetAffixed, IRibbonSetRibbons, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetMarks, IRibbonSetMark8, IRibbonSetCommon9, IRibbonSetMark9, + IHandlerUpdate { public override ReadOnlySpan ExtraBytes => [ @@ -570,7 +571,19 @@ public int GetRibbonByte(int index) return 0x40 + (index >> 3); } - public void Trade(ITrainerInfo tr) + public bool BelongsTo(ITrainerInfo tr) + { + if (tr.Version != Version) + return false; + if (tr.ID32 != ID32) + return false; + if (tr.Gender != OriginalTrainerGender) + return false; + return tr.OT == OriginalTrainerName; + } + + + public void UpdateHandler(ITrainerInfo tr) { // Process to the HT if the OT of the Pokémon does not match the SAV's OT info. if (!TradeOT(tr)) @@ -581,38 +594,27 @@ public void FixMemories() { if (LA) { - OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = 0; - HandlingTrainerMemoryVariable = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = 0; // future inter-format conversion? - } - - if (IsEgg) // No memories if is egg. - { - HandlingTrainerMemoryVariable = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = 0; - OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = 0; - - // Clear Handler - if (!IsTradedEgg) - { - HandlingTrainerFriendship = HandlingTrainerGender = HandlingTrainerLanguage = 0; - HandlingTrainerTrash.Clear(); - } - return; + this.ClearMemoriesOT(); + this.ClearMemoriesHT(); } if (IsUntraded) - HandlingTrainerMemoryVariable = HandlingTrainerGender = HandlingTrainerFriendship = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = HandlingTrainerLanguage = 0; - - var gen = Generation; - if (gen < 6) - OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = 0; - // if (gen != 8) // must be transferred via HOME, and must have memories - // this.SetTradeMemoryHT8(); // not faking HOME tracker. + { + HandlingTrainerGender = HandlingTrainerFriendship = HandlingTrainerLanguage = 0; + HandlingTrainerTrash.Clear(); + } + else + { + var gen = Generation; + if (gen < 6) + this.ClearMemoriesOT(); + } } private bool TradeOT(ITrainerInfo tr) { // Check to see if the OT matches the SAV's OT info. - if (!(tr.ID32 == ID32 && tr.Gender == OriginalTrainerGender && tr.OT == OriginalTrainerName)) + if (!BelongsTo(tr)) return false; CurrentHandler = 0; diff --git a/PKHeX.Core/PKM/PB7.cs b/PKHeX.Core/PKM/PB7.cs index 341367fbe..a8d1eee74 100644 --- a/PKHeX.Core/PKM/PB7.cs +++ b/PKHeX.Core/PKM/PB7.cs @@ -5,7 +5,8 @@ namespace PKHeX.Core; /// Generation 7 format used for . -public sealed class PB7 : G6PKM, IHyperTrain, IAwakened, IScaledSizeValue, ICombatPower, IFavorite, IFormArgument, IAppliedMarkings7 +public sealed class PB7 : G6PKM, IHyperTrain, IAwakened, IScaledSizeValue, ICombatPower, IFavorite, + IFormArgument, IAppliedMarkings7, IHandlerUpdate { public override ReadOnlySpan ExtraBytes => [ @@ -336,7 +337,7 @@ public void SetMarking(int index, MarkingColor value) protected override bool TradeOT(ITrainerInfo tr) { // Check to see if the OT matches the SAV's OT info. - if (!(tr.ID32 == ID32 && tr.Gender == OriginalTrainerGender && tr.OT == OriginalTrainerName)) + if (!BelongsTo(tr)) return false; CurrentHandler = 0; @@ -357,7 +358,10 @@ protected override void TradeHT(ITrainerInfo tr) public void FixMemories() { if (IsUntraded) - HT_TextVar = HandlingTrainerFriendship = HT_Memory = HT_Intensity = HT_Feeling = 0; + { + HandlingTrainerTrash.Clear(); + HandlingTrainerGender = HandlingTrainerFriendship = 0; + } } // Maximums diff --git a/PKHeX.Core/PKM/PB8.cs b/PKHeX.Core/PKM/PB8.cs index c286b5afa..ece5561cc 100644 --- a/PKHeX.Core/PKM/PB8.cs +++ b/PKHeX.Core/PKM/PB8.cs @@ -45,13 +45,28 @@ public bool IsDprIllegal set => Data[0x52] = (byte)((Data[0x52] & 0xFE) | (value ? 1 : 0)); } - public void Trade(ITrainerInfo tr, int Day = 1, int Month = 1, int Year = 2015) + public bool BelongsTo(ITrainerInfo tr) + { + if (tr.Version != Version) + return false; + if (tr.ID32 != ID32) + return false; + if (tr.Gender != OriginalTrainerGender) + return false; + return tr.OT == OriginalTrainerName; + } + + public void UpdateHandler(ITrainerInfo tr) { if (IsEgg) { // Apply link trade data, only if it left the OT (ignore if dumped & imported, or cloned, etc.) - if ((tr.TID16 != TID16) || (tr.SID16 != SID16) || (tr.Gender != OriginalTrainerGender) || (tr.OT != OriginalTrainerName)) - SetLinkTradeEgg(Day, Month, Year, Locations.LinkTrade6NPC); + const ushort location = Locations.LinkTrade6NPC; + if (MetLocation != location && !BelongsTo(tr)) + { + var date = EncounterDate.GetDate3DS(); + SetLinkTradeEgg(date.Day, date.Month, date.Year, location); + } // Unfortunately, BD/SP doesn't return if it's an egg, and can update the HT details & handler. // Continue to the rest of the method. @@ -67,15 +82,13 @@ public void FixMemories() { if (BDSP) { - OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = 0; - HandlingTrainerMemoryVariable = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = 0; // future inter-format conversion? + this.ClearMemoriesOT(); + this.ClearMemoriesHT(); } if (IsEgg) // No memories if is egg. { - HandlingTrainerMemoryVariable = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = 0; - OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = 0; - + // Memories already cleared above. // Clear Handler if (!IsTradedEgg) { @@ -86,19 +99,23 @@ public void FixMemories() } if (IsUntraded) - HandlingTrainerMemoryVariable = HandlingTrainerGender = HandlingTrainerFriendship = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = HandlingTrainerLanguage = 0; - - var gen = Generation; - if (gen < 6) - OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = 0; - // if (gen != 8) // must be transferred via HOME, and must have memories - // this.SetTradeMemoryHT8(); // not faking HOME tracker. + { + // Memories already cleared above. + HandlingTrainerFriendship = HandlingTrainerGender = HandlingTrainerLanguage = 0; + HandlingTrainerTrash.Clear(); + } + else + { + var gen = Generation; + if (gen < 6) + this.ClearMemoriesOT(); + } } private bool TradeOT(ITrainerInfo tr) { // Check to see if the OT matches the SAV's OT info. - if (!(tr.ID32 == ID32 && tr.Gender == OriginalTrainerGender && tr.OT == OriginalTrainerName)) + if (!BelongsTo(tr)) return false; CurrentHandler = 0; diff --git a/PKHeX.Core/PKM/PK5.cs b/PKHeX.Core/PKM/PK5.cs index da5abb937..96689cefa 100644 --- a/PKHeX.Core/PKM/PK5.cs +++ b/PKHeX.Core/PKM/PK5.cs @@ -7,7 +7,7 @@ namespace PKHeX.Core; /// Generation 5 format. public sealed class PK5 : PKM, ISanityChecksum, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetUnique3, IRibbonSetUnique4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetRibbons, - IContestStats, IGroundTile, IAppliedMarkings4 + IContestStats, IGroundTile, IAppliedMarkings4, IHandlerUpdate { public override ReadOnlySpan ExtraBytes => [ @@ -297,14 +297,29 @@ protected override byte[] Encrypt() } // Synthetic Trading Logic - public bool Trade(string SAV_Trainer, uint savID32, int SAV_GENDER, int Day = 1, int Month = 1, int Year = 2013) + public bool BelongsTo(ITrainerInfo tr) { - if (IsEgg && !(SAV_Trainer == OriginalTrainerName && savID32 == ID32 && SAV_GENDER == OriginalTrainerGender)) + if (tr.Version != Version) + return false; + if (tr.ID32 != ID32) + return false; + if (tr.Gender != OriginalTrainerGender) + return false; + return tr.OT == OriginalTrainerName; + } + + public void UpdateHandler(ITrainerInfo tr) + { + if (IsEgg) { - SetLinkTradeEgg(Day, Month, Year, Locations.LinkTrade5); - return true; + // Don't bother updating eggs that were already traded. + const ushort location = Locations.LinkTrade5; + if (MetLocation != location && !BelongsTo(tr)) + { + var date = EncounterDate.GetDateNDS(); + SetLinkTradeEgg(date.Day, date.Month, date.Year, location); + } } - return false; } public int MarkingCount => 6; diff --git a/PKHeX.Core/PKM/PK6.cs b/PKHeX.Core/PKM/PK6.cs index 0b3089ed5..68c406e98 100644 --- a/PKHeX.Core/PKM/PK6.cs +++ b/PKHeX.Core/PKM/PK6.cs @@ -413,7 +413,7 @@ public void FixMemories() protected override bool TradeOT(ITrainerInfo tr) { // Check to see if the OT matches the SAV's OT info. - if (!(tr.ID32 == ID32 && tr.Gender == OriginalTrainerGender && tr.OT == OriginalTrainerName)) + if (!BelongsTo(tr)) return false; CurrentHandler = 0; diff --git a/PKHeX.Core/PKM/PK7.cs b/PKHeX.Core/PKM/PK7.cs index 7f88022ea..d792afd97 100644 --- a/PKHeX.Core/PKM/PK7.cs +++ b/PKHeX.Core/PKM/PK7.cs @@ -477,7 +477,7 @@ public void FixMemories() protected override bool TradeOT(ITrainerInfo tr) { // Check to see if the OT matches the SAV's OT info. - if (!(tr.ID32 == ID32 && tr.Gender == OriginalTrainerGender && tr.OT == OriginalTrainerName)) + if (!BelongsTo(tr)) return false; CurrentHandler = 0; diff --git a/PKHeX.Core/PKM/PK8.cs b/PKHeX.Core/PKM/PK8.cs index edaa11581..e58e4b189 100644 --- a/PKHeX.Core/PKM/PK8.cs +++ b/PKHeX.Core/PKM/PK8.cs @@ -4,7 +4,7 @@ namespace PKHeX.Core; /// Generation 8 format. -public sealed class PK8 : G8PKM +public sealed class PK8 : G8PKM, IHandlerUpdate { public override ReadOnlySpan ExtraBytes => [ @@ -35,14 +35,30 @@ public PK8() => AffixedRibbon = -1; // 00 would make it show Kalos Champion :) public PK8(byte[] data) : base(data) { } public override PK8 Clone() => new((byte[])Data.Clone()); - public void Trade(ITrainerInfo tr, int Day = 1, int Month = 1, int Year = 2015) + // Synthetic Trading Logic + public bool BelongsTo(ITrainerInfo tr) + { + if (tr.Version != Version) + return false; + if (tr.ID32 != ID32) + return false; + if (tr.Gender != OriginalTrainerGender) + return false; + return tr.OT == OriginalTrainerName; + } + + public void UpdateHandler(ITrainerInfo tr) { if (IsEgg) { // Eggs do not have any modifications done if they are traded // Apply link trade data, only if it left the OT (ignore if dumped & imported, or cloned, etc.) - if ((tr.TID16 != TID16) || (tr.SID16 != SID16) || (tr.Gender != OriginalTrainerGender) || (tr.OT != OriginalTrainerName)) - SetLinkTradeEgg(Day, Month, Year, Locations.LinkTrade6); + const ushort location = Locations.LinkTrade6; + if (MetLocation != location && !BelongsTo(tr)) + { + var date = EncounterDate.GetDateSwitch(); + SetLinkTradeEgg(date.Day, date.Month, date.Year, location); + } return; } @@ -57,28 +73,31 @@ public void FixMemories() { if (IsEgg) // No memories if is egg. { - HandlingTrainerMemoryVariable = HandlingTrainerFriendship = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = HandlingTrainerLanguage = 0; - /* OriginalTrainerFriendship */ OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = 0; - - // Clear Handler + this.ClearMemoriesOT(); + this.ClearMemoriesHT(); + HandlingTrainerGender = HandlingTrainerFriendship = HandlingTrainerLanguage = 0; HandlingTrainerTrash.Clear(); return; } if (IsUntraded) - HandlingTrainerMemoryVariable = HandlingTrainerFriendship = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = HandlingTrainerLanguage = 0; - - var gen = Generation; - if (gen < 6) - OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = 0; - if (gen != 8) // must be transferred via HOME, and must have memories - this.SetTradeMemoryHT8(); // not faking HOME tracker. + { + this.ClearMemoriesHT(); + HandlingTrainerGender = HandlingTrainerFriendship = HandlingTrainerLanguage = 0; + HandlingTrainerTrash.Clear(); + } + else + { + var gen = Generation; + if (gen < 6) + this.ClearMemoriesOT(); + } } private bool TradeOT(ITrainerInfo tr) { // Check to see if the OT matches the SAV's OT info. - if (!(tr.ID32 == ID32 && tr.Gender == OriginalTrainerGender && tr.OT == OriginalTrainerName)) + if (!BelongsTo(tr)) return false; CurrentHandler = 0; diff --git a/PKHeX.Core/PKM/PK9.cs b/PKHeX.Core/PKM/PK9.cs index c7699449e..6f5107b75 100644 --- a/PKHeX.Core/PKM/PK9.cs +++ b/PKHeX.Core/PKM/PK9.cs @@ -5,7 +5,7 @@ namespace PKHeX.Core; /// Generation 9 format. -public sealed class PK9 : PKM, ISanityChecksum, ITeraType, ITechRecord, IObedienceLevel, +public sealed class PK9 : PKM, ISanityChecksum, ITeraType, ITechRecord, IObedienceLevel, IHandlerUpdate, IContestStats, IHyperTrain, IScaledSize, IScaledSize3, IFavorite, IHandlerLanguage, IFormArgument, IHomeTrack, IBattleVersion, ITrainerMemories, IAppliedMarkings7, IRibbonIndex, IRibbonSetAffixed, IRibbonSetRibbons, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetCommon9, IRibbonSetMarks, IRibbonSetMark8, IRibbonSetMark9 { @@ -549,34 +549,30 @@ public int GetRibbonByte(int index) return 0x40 + (index >> 3); } - public void Trade(ITrainerInfo tr, int Day = 1, int Month = 1, int Year = 2015) + // Synthetic Trading Logic + public bool BelongsTo(ITrainerInfo tr) + { + if (tr.Version != Version) + return false; + return BelongsToSkipVersion(tr); + } + + public bool BelongsToSkipVersion(ITrainerInfo tr) + { + if (tr.ID32 != ID32) + return false; + if (tr.Gender != OriginalTrainerGender) + return false; + if (tr.Language != Language) + return false; + return tr.OT == OriginalTrainerName; + } + + public void UpdateHandler(ITrainerInfo tr) { if (IsEgg) { - if (EggLocation == 60005 && tr.Gender == OriginalTrainerGender && tr.Language == Language && tr.OT == OriginalTrainerName) - return; // Jacq gift, don't change. - - // Apply link trade data, only if it left the OT (ignore if dumped & imported, or cloned, etc.) - // If not matching the trainer details, mark as a traded egg. - if (!IsTradedEgg && tr.Gender == OriginalTrainerGender && tr.Language == Language && tr.OT == OriginalTrainerName) - { - OriginalTrainerTrash.Clear(); - NicknameTrash.Clear(); - HandlingTrainerTrash.Clear(); - CurrentHandler = 0; - Language = tr.Language; - Nickname = SpeciesName.GetEggName(tr.Language, 9); - OriginalTrainerName = tr.OT; - HandlingTrainerLanguage = 0; - } - else - { - HandlingTrainerName = tr.OT; - HandlingTrainerGender = tr.Gender; - HandlingTrainerLanguage = (byte)tr.Language; - SetLinkTradeEgg(Day, Month, Year, Locations.LinkTrade6); - CurrentHandler = 1; - } + UpdateHandlerEgg(tr); return; } @@ -585,33 +581,79 @@ public void Trade(ITrainerInfo tr, int Day = 1, int Month = 1, int Year = 2015) TradeHT(tr); } + private void UpdateHandlerEgg(ITrainerInfo tr) + { + bool belongs = BelongsToSkipVersion(tr); + if (EggLocation == 60005 && belongs) + return; // Jacq gift, don't change. + + // Apply link trade data, only if it left the OT (ignore if dumped & imported, or cloned, etc.) + // If not matching the trainer details, mark as a traded egg. + // If it's the OT's, be nice and reset the data. + if (belongs) + SetHandlerEggOT(tr); + else + SetHandlerEggTraded(tr); + } + + private void SetHandlerEggOT(ITrainerInfo tr) + { + // Reset back to the OT. + OriginalTrainerTrash.Clear(); + NicknameTrash.Clear(); + HandlingTrainerTrash.Clear(); + HandlingTrainerGender = 0; + HandlingTrainerLanguage = 0; + + Nickname = SpeciesName.GetEggName(tr.Language, 9); + OriginalTrainerName = tr.OT; + CurrentHandler = 0; + } + + private void SetHandlerEggTraded(ITrainerInfo tr) + { + HandlingTrainerName = tr.OT; + HandlingTrainerGender = tr.Gender; + HandlingTrainerLanguage = (byte)tr.Language; + + var date = EncounterDate.GetDateSwitch(); + SetLinkTradeEgg(date.Day, date.Month, date.Year, Locations.LinkTrade6); + CurrentHandler = 1; + } + public void FixMemories() { if (IsEgg) // No memories if is egg. { // HT_Language is set for eggs - HandlingTrainerMemoryVariable = HandlingTrainerFriendship = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = 0; - /* OriginalTrainerFriendship */ - OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = 0; + this.ClearMemoriesOT(); + this.ClearMemoriesHT(); + HandlingTrainerGender = 0; + HandlingTrainerFriendship = 0; + HandlingTrainerTrash.Clear(); return; } if (IsUntraded) { - // HT_Language is set for gifts - // Skip clearing that. - HandlingTrainerMemoryVariable = HandlingTrainerFriendship = HandlingTrainerMemory = HandlingTrainerMemoryIntensity = HandlingTrainerMemoryFeeling = 0; + // HT_Language is set for gifts -- skip clearing that. + this.ClearMemoriesHT(); + HandlingTrainerGender = 0; + HandlingTrainerFriendship = 0; + HandlingTrainerTrash.Clear(); + } + else + { + var gen = Generation; + if (gen < 6) + this.ClearMemoriesOT(); } - - var gen = Generation; - if (gen < 6) - OriginalTrainerMemoryVariable = OriginalTrainerMemory = OriginalTrainerMemoryIntensity = OriginalTrainerMemoryFeeling = 0; } private bool TradeOT(ITrainerInfo tr) { // Check to see if the OT matches the SAV's OT info. - if (!(tr.ID32 == ID32 && tr.Gender == OriginalTrainerGender && tr.OT == OriginalTrainerName)) + if (!BelongsTo(tr)) return false; CurrentHandler = 0; diff --git a/PKHeX.Core/PKM/PKM.cs b/PKHeX.Core/PKM/PKM.cs index e8f8601f4..89bc45fc2 100644 --- a/PKHeX.Core/PKM/PKM.cs +++ b/PKHeX.Core/PKM/PKM.cs @@ -797,13 +797,13 @@ public bool ForcePartyData() /// /// Day the was traded. /// Month the was traded. - /// Day the was traded. + /// Day the was traded. /// Link Trade location value. - protected void SetLinkTradeEgg(int day, int month, int y, ushort location) + protected void SetLinkTradeEgg(int day, int month, int year, ushort location) { MetDay = (byte)day; MetMonth = (byte)month; - MetYear = (byte)(y - 2000); + MetYear = (byte)(year - 2000); MetLocation = location; } diff --git a/PKHeX.Core/PKM/Shared/G4PKM.cs b/PKHeX.Core/PKM/Shared/G4PKM.cs index 1b2e2da76..114add24b 100644 --- a/PKHeX.Core/PKM/Shared/G4PKM.cs +++ b/PKHeX.Core/PKM/Shared/G4PKM.cs @@ -5,7 +5,7 @@ namespace PKHeX.Core; /// Generation 4 format. -public abstract class G4PKM : PKM, +public abstract class G4PKM : PKM, IHandlerUpdate, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetUnique3, IRibbonSetUnique4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetRibbons, IContestStats, IGroundTile, IAppliedMarkings4 { protected G4PKM(byte[] data) : base(data) { } @@ -279,15 +279,29 @@ public sealed override byte Ball } // Synthetic Trading Logic - public bool Trade(string SAV_Trainer, uint savID32, int SAV_GENDER, int Day = 1, int Month = 1, int Year = 2009) + public bool BelongsTo(ITrainerInfo tr) { - // Eggs do not have any modifications done if they are traded - if (IsEgg && !(SAV_Trainer == OriginalTrainerName && savID32 == ID32 && SAV_GENDER == OriginalTrainerGender)) + if (tr.Version != Version) + return false; + if (tr.ID32 != ID32) + return false; + if (tr.Gender != OriginalTrainerGender) + return false; + return tr.OT == OriginalTrainerName; + } + + public void UpdateHandler(ITrainerInfo tr) + { + if (IsEgg) { - SetLinkTradeEgg(Day, Month, Year, Locations.LinkTrade4); - return true; + // Don't bother updating eggs that were already traded. + const ushort location = Locations.LinkTrade4; + if (MetLocation != location && !BelongsTo(tr)) + { + var date = EncounterDate.GetDateNDS(); + SetLinkTradeEgg(date.Day, date.Month, date.Year, location); + } } - return false; } // Enforce D/P content only (no Pt or HG/SS) diff --git a/PKHeX.Core/PKM/Shared/G6PKM.cs b/PKHeX.Core/PKM/Shared/G6PKM.cs index fe8f7bce8..3fc26cedc 100644 --- a/PKHeX.Core/PKM/Shared/G6PKM.cs +++ b/PKHeX.Core/PKM/Shared/G6PKM.cs @@ -4,7 +4,7 @@ namespace PKHeX.Core; /// Generation 6 format. -public abstract class G6PKM : PKM, ISanityChecksum +public abstract class G6PKM : PKM, ISanityChecksum, IHandlerUpdate { public override int SIZE_PARTY => PokeCrypto.SIZE_6PARTY; public override int SIZE_STORED => PokeCrypto.SIZE_6STORED; @@ -79,20 +79,41 @@ public void FixRelearn() } // Synthetic Trading Logic - public void Trade(ITrainerInfo tr, int Day = 1, int Month = 1, int Year = 2015) + public bool BelongsTo(ITrainerInfo tr) + { + if (tr.Version != Version) + return false; + if (tr.ID32 != ID32) + return false; + if (tr.Gender != OriginalTrainerGender) + return false; + return tr.OT == OriginalTrainerName; + } + + public void UpdateHandler(ITrainerInfo tr) { if (IsEgg) { // Eggs do not have any modifications done if they are traded // Apply link trade data, only if it left the OT (ignore if dumped & imported, or cloned, etc.) - if ((tr.TID16 != TID16) || (tr.SID16 != SID16) || (tr.Gender != OriginalTrainerGender) || (tr.OT != OriginalTrainerName)) - SetLinkTradeEgg(Day, Month, Year, Locations.LinkTrade6); + const ushort location = Locations.LinkTrade6; + if (MetLocation != location && !BelongsTo(tr)) + { + var date = EncounterDate.GetDate3DS(); + SetLinkTradeEgg(date.Day, date.Month, date.Year, location); + } return; } // Process to the HT if the OT of the Pokémon does not match the SAV's OT info. + var handler = CurrentHandler; if (!TradeOT(tr)) TradeHT(tr); + if (handler == CurrentHandler) + return; // Logic updated Friendship + // Copy over the Friendship Value only under certain circumstances + if (HasMove((int)Move.Return) || HasMove((int)Move.Frustration)) + CurrentFriendship = OppositeFriendship; } protected abstract bool TradeOT(ITrainerInfo tr); diff --git a/PKHeX.Core/PKM/Util/EntitySorting.cs b/PKHeX.Core/PKM/Util/EntitySorting.cs index a7df26b06..1fb361e13 100644 --- a/PKHeX.Core/PKM/Util/EntitySorting.cs +++ b/PKHeX.Core/PKM/Util/EntitySorting.cs @@ -251,7 +251,16 @@ private static int GetFriendshipDelta(PKM pk) var currentFriendship = pk.CurrentFriendship; if (currentFriendship == 255) return 255; - var baseFriendship = pk.PersonalInfo.BaseFriendship; + + var baseFriendship = GetInitialFriendship(pk); return currentFriendship - baseFriendship; } + + private static byte GetInitialFriendship(PKM pk) + { + // Don't get too intricate with this, we generally want to know if it's been raised. + if (pk.WasEgg) + return EggStateLegality.EggHatchFriendshipGeneral; + return pk.PersonalInfo.BaseFriendship; + } } diff --git a/PKHeX.Core/Saves/Abstractions/ITrainerInfo.cs b/PKHeX.Core/Saves/Abstractions/ITrainerInfo.cs index 3f5e11203..b957606f0 100644 --- a/PKHeX.Core/Saves/Abstractions/ITrainerInfo.cs +++ b/PKHeX.Core/Saves/Abstractions/ITrainerInfo.cs @@ -41,36 +41,6 @@ public static void ApplyTo(this ITrainerInfo info, PKM pk) o.CopyRegionOrigin(tr); } - /// - /// Copies the data to the object's Handling Trainer data. - /// - /// Trainer Information - /// Pokémon to copy to - /// If true, will overwrite the Handling Trainer Data even if it has not been traded. - public static void ApplyHandlingTrainerInfo(this ITrainerInfo sav, PKM pk, bool force = false) - { - if (pk.Format == sav.Generation && !force) - return; - - pk.HandlingTrainerName = sav.OT; - pk.HandlingTrainerGender = sav.Gender; - pk.HandlingTrainerFriendship = pk.OriginalTrainerFriendship; - pk.CurrentHandler = 1; - if (pk is IHandlerLanguage h) - h.HandlingTrainerLanguage = (byte)sav.Language; - - if (pk is PK6 pk6 && sav is IRegionOrigin o) - { - pk6.Geo1_Country = o.Country; - pk6.Geo1_Region = o.Region; - pk6.SetTradeMemoryHT6(true); - } - else if (pk is PK8 pk8 && PersonalTable.SWSH.IsPresentInGame(pk.Species, pk.Form)) - { - pk8.SetTradeMemoryHT8(); - } - } - /// /// Checks if the data matches the object's Original Trainer data. /// @@ -82,9 +52,6 @@ public static bool IsFromTrainer(this ITrainerInfo tr, PKM pk) if (pk.IsEgg) return tr.IsFromTrainerEgg(pk); - if (tr.Version == GameVersion.Any) - return true; - if (!IsFromTrainerNoVersion(tr, pk)) return false; diff --git a/PKHeX.Core/Saves/SAV4.cs b/PKHeX.Core/Saves/SAV4.cs index ae44fcd48..b5ac05ceb 100644 --- a/PKHeX.Core/Saves/SAV4.cs +++ b/PKHeX.Core/Saves/SAV4.cs @@ -347,9 +347,8 @@ protected sealed override void SetPKM(PKM pk, bool isParty = false) { var pk4 = (PK4)pk; // Apply to this Save File - var now = EncounterDate.GetDateNDS(); - if (pk4.Trade(OT, ID32, Gender, now.Day, now.Month, now.Year)) - pk.RefreshChecksum(); + pk4.UpdateHandler(this); + pk.RefreshChecksum(); } // Daycare diff --git a/PKHeX.Core/Saves/SAV4BR.cs b/PKHeX.Core/Saves/SAV4BR.cs index bd99cfab5..74fd6369f 100644 --- a/PKHeX.Core/Saves/SAV4BR.cs +++ b/PKHeX.Core/Saves/SAV4BR.cs @@ -244,9 +244,8 @@ protected override void SetPKM(PKM pk, bool isParty = false) { var pk4 = (BK4)pk; // Apply to this Save File - var now = EncounterDate.GetDateNDS(); - if (pk4.Trade(OT, ID32, Gender, now.Day, now.Month, now.Year)) - pk.RefreshChecksum(); + pk4.UpdateHandler(this); + pk.RefreshChecksum(); } protected override void SetPartyValues(PKM pk, bool isParty) diff --git a/PKHeX.Core/Saves/SAV4DP.cs b/PKHeX.Core/Saves/SAV4DP.cs index 0f74bf516..4a6164157 100644 --- a/PKHeX.Core/Saves/SAV4DP.cs +++ b/PKHeX.Core/Saves/SAV4DP.cs @@ -24,6 +24,7 @@ public SAV4DP(byte[] data) : base(data, GeneralSize, StorageSize, GeneralSize) public override Zukan4 Dex { get; } protected override SAV4 CloneInternal4() => State.Exportable ? new SAV4DP((byte[])Data.Clone()) : new SAV4DP(); + public override GameVersion Version { get => GameVersion.DP; set { } } public override PersonalTable4 Personal => PersonalTable.DP; public override ReadOnlySpan HeldItems => Legal.HeldItems_DP; public override int MaxItemID => Legal.MaxItemID_4_DP; diff --git a/PKHeX.Core/Saves/SAV4HGSS.cs b/PKHeX.Core/Saves/SAV4HGSS.cs index 76dbec195..23d8450c1 100644 --- a/PKHeX.Core/Saves/SAV4HGSS.cs +++ b/PKHeX.Core/Saves/SAV4HGSS.cs @@ -25,6 +25,7 @@ public SAV4HGSS(byte[] data) : base(data, GeneralSize, StorageSize, GeneralSize public override Zukan4 Dex { get; } protected override SAV4 CloneInternal4() => State.Exportable ? new SAV4HGSS((byte[])Data.Clone()) : new SAV4HGSS(); + public override GameVersion Version { get => GameVersion.HGSS; set { } } public override PersonalTable4 Personal => PersonalTable.HGSS; public override ReadOnlySpan HeldItems => Legal.HeldItems_HGSS; public override int MaxItemID => Legal.MaxItemID_4_HGSS; diff --git a/PKHeX.Core/Saves/SAV4Pt.cs b/PKHeX.Core/Saves/SAV4Pt.cs index 94deb3883..02ea01367 100644 --- a/PKHeX.Core/Saves/SAV4Pt.cs +++ b/PKHeX.Core/Saves/SAV4Pt.cs @@ -23,6 +23,7 @@ public SAV4Pt(byte[] data) : base(data, GeneralSize, StorageSize, GeneralSize) public override Zukan4 Dex { get; } protected override SAV4 CloneInternal4() => State.Exportable ? new SAV4Pt((byte[])Data.Clone()) : new SAV4Pt(); + public override GameVersion Version { get => GameVersion.Pt; set { } } public override PersonalTable4 Personal => PersonalTable.Pt; public override ReadOnlySpan HeldItems => Legal.HeldItems_Pt; public override int MaxItemID => Legal.MaxItemID_4_Pt; diff --git a/PKHeX.Core/Saves/SAV5.cs b/PKHeX.Core/Saves/SAV5.cs index 8b00573e6..db11c3d48 100644 --- a/PKHeX.Core/Saves/SAV5.cs +++ b/PKHeX.Core/Saves/SAV5.cs @@ -109,9 +109,8 @@ protected override void SetPKM(PKM pk, bool isParty = false) { var pk5 = (PK5)pk; // Apply to this Save File - var now = EncounterDate.GetDateNDS(); - if (pk5.Trade(OT, ID32, Gender, now.Day, now.Month, now.Year)) - pk.RefreshChecksum(); + pk5.UpdateHandler(this); + pk5.RefreshChecksum(); } // Player Data diff --git a/PKHeX.Core/Saves/SAV6.cs b/PKHeX.Core/Saves/SAV6.cs index 06b9a1270..b5fee4815 100644 --- a/PKHeX.Core/Saves/SAV6.cs +++ b/PKHeX.Core/Saves/SAV6.cs @@ -111,15 +111,7 @@ protected override void SetPKM(PKM pk, bool isParty = false) { PK6 pk6 = (PK6)pk; // Apply to this Save File - int CT = pk6.CurrentHandler; - var now = EncounterDate.GetDate3DS(); - pk6.Trade(this, now.Day, now.Month, now.Year); - if (CT != pk6.CurrentHandler) // Logic updated Friendship - { - // Copy over the Friendship Value only under certain circumstances - if (pk6.HasMove((int)Move.Return) || pk6.HasMove((int)Move.Frustration)) - pk6.CurrentFriendship = pk6.OppositeFriendship; - } + pk6.UpdateHandler(this); pk6.FormArgumentElapsed = pk6.FormArgumentMaximum = 0; pk6.FormArgumentRemain = (byte)GetFormArgument(pk, isParty); diff --git a/PKHeX.Core/Saves/SAV7.cs b/PKHeX.Core/Saves/SAV7.cs index c8f4a0d94..2a46c5dbc 100644 --- a/PKHeX.Core/Saves/SAV7.cs +++ b/PKHeX.Core/Saves/SAV7.cs @@ -169,15 +169,7 @@ protected override void SetPKM(PKM pk, bool isParty = false) { PK7 pk7 = (PK7)pk; // Apply to this Save File - int CT = pk7.CurrentHandler; - var now = EncounterDate.GetDate3DS(); - pk7.Trade(this, now.Day, now.Month, now.Year); - if (CT != pk7.CurrentHandler) // Logic updated Friendship - { - // Copy over the Friendship Value only under certain circumstances - if (pk7.HasMove((int)Move.Return) || pk7.HasMove((int)Move.Frustration)) - pk7.CurrentFriendship = pk7.OppositeFriendship; - } + pk7.UpdateHandler(this); pk7.FormArgumentElapsed = pk7.FormArgumentMaximum = 0; pk7.FormArgumentRemain = (byte)GetFormArgument(pk); diff --git a/PKHeX.Core/Saves/SAV7b.cs b/PKHeX.Core/Saves/SAV7b.cs index 00a92f405..2382430c5 100644 --- a/PKHeX.Core/Saves/SAV7b.cs +++ b/PKHeX.Core/Saves/SAV7b.cs @@ -96,8 +96,7 @@ protected override void SetPKM(PKM pk, bool isParty = false) { var pb7 = (PB7)pk; // Apply to this Save File - var now = EncounterDate.GetDateSwitch(); - pb7.Trade(this, now.Day, now.Month, now.Year); + pb7.UpdateHandler(this); pb7.RefreshChecksum(); } diff --git a/PKHeX.Core/Saves/SAV8BS.cs b/PKHeX.Core/Saves/SAV8BS.cs index 346b9002c..1b833aff1 100644 --- a/PKHeX.Core/Saves/SAV8BS.cs +++ b/PKHeX.Core/Saves/SAV8BS.cs @@ -304,8 +304,7 @@ protected override void SetPKM(PKM pk, bool isParty = false) { var pb8 = (PB8)pk; // Apply to this Save File - var now = EncounterDate.GetDateSwitch(); - pb8.Trade(this, now.Day, now.Month, now.Year); + pb8.UpdateHandler(this); pb8.RefreshChecksum(); if (SetUpdateRecords != PKMImportSetting.Skip) diff --git a/PKHeX.Core/Saves/SAV8LA.cs b/PKHeX.Core/Saves/SAV8LA.cs index 473cf9b2e..8115ccaf4 100644 --- a/PKHeX.Core/Saves/SAV8LA.cs +++ b/PKHeX.Core/Saves/SAV8LA.cs @@ -148,7 +148,7 @@ protected override void SetPKM(PKM pk, bool isParty = false) { var pa8 = (PA8)pk; // Apply to this Save File - pa8.Trade(this); + pa8.UpdateHandler(this); pa8.RefreshChecksum(); } diff --git a/PKHeX.Core/Saves/SAV8SWSH.cs b/PKHeX.Core/Saves/SAV8SWSH.cs index 53ec75eda..4752ce9a1 100644 --- a/PKHeX.Core/Saves/SAV8SWSH.cs +++ b/PKHeX.Core/Saves/SAV8SWSH.cs @@ -191,8 +191,7 @@ protected override void SetPKM(PKM pk, bool isParty = false) { PK8 pk8 = (PK8)pk; // Apply to this Save File - var now = EncounterDate.GetDateSwitch(); - pk8.Trade(this, now.Day, now.Month, now.Year); + pk8.UpdateHandler(this); if (FormArgumentUtil.IsFormArgumentTypeDatePair(pk8.Species, pk8.Form)) { diff --git a/PKHeX.Core/Saves/SAV9SV.cs b/PKHeX.Core/Saves/SAV9SV.cs index 890ae86d8..2b0380e8a 100644 --- a/PKHeX.Core/Saves/SAV9SV.cs +++ b/PKHeX.Core/Saves/SAV9SV.cs @@ -197,8 +197,7 @@ protected override void SetPKM(PKM pk, bool isParty = false) { PK9 pk9 = (PK9)pk; // Apply to this Save File - var now = EncounterDate.GetDateSwitch(); - pk9.Trade(this, now.Day, now.Month, now.Year); + pk9.UpdateHandler(this); if (FormArgumentUtil.IsFormArgumentTypeDatePair(pk9.Species, pk9.Form)) { diff --git a/PKHeX.Core/Saves/SaveFile.cs b/PKHeX.Core/Saves/SaveFile.cs index 54bd49b81..d76451dac 100644 --- a/PKHeX.Core/Saves/SaveFile.cs +++ b/PKHeX.Core/Saves/SaveFile.cs @@ -61,7 +61,7 @@ protected virtual byte[] GetFinalData() #region Metadata & Limits public virtual string MiscSaveInfo() => string.Empty; public virtual bool IsVersionValid() => true; - public virtual GameVersion Version { get => default; set { } } + public abstract GameVersion Version { get; set; } public abstract bool ChecksumsValid { get; } public abstract string ChecksumInfo { get; } public abstract byte Generation { get; } diff --git a/PKHeX.Core/Saves/Storage/Bank3.cs b/PKHeX.Core/Saves/Storage/Bank3.cs index e97de240b..da8bf35f2 100644 --- a/PKHeX.Core/Saves/Storage/Bank3.cs +++ b/PKHeX.Core/Saves/Storage/Bank3.cs @@ -9,6 +9,7 @@ public sealed class Bank3 : BulkStorage { public Bank3(byte[] data) : base(data, typeof(PK3), 0) => Version = GameVersion.RS; + public override GameVersion Version { get => GameVersion.RS; set { } } public override PersonalTable3 Personal => PersonalTable.RS; public override ReadOnlySpan HeldItems => Legal.HeldItems_RS; protected override Bank3 CloneInternal() => new((byte[])Data.Clone()); diff --git a/PKHeX.Core/Saves/Storage/Bank4.cs b/PKHeX.Core/Saves/Storage/Bank4.cs index 195f961e3..8b1e10ae9 100644 --- a/PKHeX.Core/Saves/Storage/Bank4.cs +++ b/PKHeX.Core/Saves/Storage/Bank4.cs @@ -9,6 +9,7 @@ public sealed class Bank4 : BulkStorage { public Bank4(byte[] data) : base(data, typeof(PK4), 0) => Version = GameVersion.HGSS; + public override GameVersion Version { get => GameVersion.HGSS; set { } } public override PersonalTable4 Personal => PersonalTable.HGSS; public override ReadOnlySpan HeldItems => Legal.HeldItems_HGSS; protected override Bank4 CloneInternal() => new((byte[])Data.Clone()); diff --git a/PKHeX.Core/Saves/Storage/Bank7.cs b/PKHeX.Core/Saves/Storage/Bank7.cs index 808573d32..8eac84a85 100644 --- a/PKHeX.Core/Saves/Storage/Bank7.cs +++ b/PKHeX.Core/Saves/Storage/Bank7.cs @@ -11,6 +11,7 @@ public sealed class Bank7 : BulkStorage { public Bank7(byte[] data, Type t, [ConstantExpected] int start, int slotsPerBox = 30) : base(data, t, start, slotsPerBox) => Version = GameVersion.USUM; + public override GameVersion Version { get => GameVersion.USUM; set { } } public override PersonalTable7 Personal => PersonalTable.USUM; public override ReadOnlySpan HeldItems => Legal.HeldItems_SM; protected override Bank7 CloneInternal() => new((byte[])Data.Clone(), PKMType, BoxStart, SlotsPerBox); diff --git a/PKHeX.Core/Saves/Storage/SAV4Ranch.cs b/PKHeX.Core/Saves/Storage/SAV4Ranch.cs index 561b8f394..2d66c7165 100644 --- a/PKHeX.Core/Saves/Storage/SAV4Ranch.cs +++ b/PKHeX.Core/Saves/Storage/SAV4Ranch.cs @@ -13,7 +13,6 @@ public sealed class SAV4Ranch : BulkStorage, ISaveFileRevision protected override int SIZE_STORED => PokeCrypto.SIZE_4RSTORED; protected override int SIZE_PARTY => PokeCrypto.SIZE_4RSTORED; public int MaxToyID => (int) ((SaveRevision == 0) ? RanchToyType.Poke_Ball : RanchToyType.Water); - public int SaveRevision => Version == GameVersion.DP ? 0 : 1; public string SaveRevisionString => Version == GameVersion.DP ? "-DP" : "-Pt"; @@ -46,9 +45,12 @@ public sealed class SAV4Ranch : BulkStorage, ISaveFileRevision protected override bool IsSlotSwapProtected(int box, int slot) => IsSlotOverwriteProtected(box, slot); public override bool IsPKMPresent(ReadOnlySpan data) => EntityDetection.IsPresentSAV4Ranch(data); + + private readonly GameVersion _version; + public override GameVersion Version { get => _version; set { } } public SAV4Ranch(byte[] data) : base(data, typeof(RK4), 0) { - Version = Data.Length == SaveUtil.SIZE_G4RANCH_PLAT ? GameVersion.Pt : GameVersion.DP; + _version = Data.Length == SaveUtil.SIZE_G4RANCH_PLAT ? GameVersion.Pt : GameVersion.DP; OT = GetString(Data.AsSpan(0x770, 0x12));