From 37cb15749e9fcf19f23ea2d916011f87cd01a7f1 Mon Sep 17 00:00:00 2001 From: Kurt Date: Mon, 8 Feb 2021 20:26:53 -0800 Subject: [PATCH] Update FormArgument handling for gen6/7 Disassociate pk4/pk6 backing byte[] when converting to pk5|pk7, as we no longer make a copy of the byte[] in the pkm's constructor. Change UpdatePKM to include isParty, as we want it optional to update FormArgument too. Change FormArgument saving to be handled by FormConverter; kinda not really good to have it there, but nothing else is handling FormArgument values. Expand IFormArgument to have all FormArgument values exposed. "Maximum" is furfrou only. PK6: Max is in the "FormArgument" u32, and the remain/elapsed is in party stats (hence the reverting when boxed) PK7: u8 remain, u8 elapsed, u8 max, u8 unused. PK8: assumedly the same as PK7, given the disassembly hints that it's the same as past games (even though Furfrou and Hoopa are not in SWSH). --- PKHeX.Core/Legality/Verifiers/FormVerifier.cs | 51 ++++++++++++++----- PKHeX.Core/PKM/PB7.cs | 4 ++ PKHeX.Core/PKM/PK4.cs | 2 +- PKHeX.Core/PKM/PK6.cs | 13 ++++- PKHeX.Core/PKM/PK7.cs | 8 +++ PKHeX.Core/PKM/PK8.cs | 3 ++ PKHeX.Core/PKM/Shared/IFormArgument.cs | 15 ++++++ PKHeX.Core/PKM/Util/FormConverter.cs | 39 +++++++------- PKHeX.Core/Saves/SAV3Colosseum.cs | 2 +- PKHeX.Core/Saves/SAV3XD.cs | 2 +- PKHeX.Core/Saves/SAV4.cs | 2 +- PKHeX.Core/Saves/SAV4BR.cs | 2 +- PKHeX.Core/Saves/SAV5.cs | 2 +- PKHeX.Core/Saves/SAV6.cs | 29 ++++++++--- PKHeX.Core/Saves/SAV7.cs | 12 ++--- PKHeX.Core/Saves/SAV7b.cs | 2 +- PKHeX.Core/Saves/SAV8.cs | 21 +++++++- PKHeX.Core/Saves/SaveFile.cs | 19 +++---- PKHeX.WinForms/Controls/PKM Editor/EditPK6.cs | 2 +- .../Controls/PKM Editor/FormArgument.cs | 12 +++-- .../Controls/PKM Editor/LoadSave.cs | 2 +- .../Controls/PKM Editor/PKMEditor.Designer.cs | 1 - .../Controls/PKM Editor/PKMEditor.cs | 5 +- 23 files changed, 176 insertions(+), 74 deletions(-) diff --git a/PKHeX.Core/Legality/Verifiers/FormVerifier.cs b/PKHeX.Core/Legality/Verifiers/FormVerifier.cs index e50684649..683eb7b98 100644 --- a/PKHeX.Core/Legality/Verifiers/FormVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/FormVerifier.cs @@ -20,7 +20,7 @@ public override void Verify(LegalityAnalysis data) data.AddLine(result); if (pkm is IFormArgument f) - data.AddLine(VerifyFormArgument(data, f.FormArgument)); + data.AddLine(VerifyFormArgument(data, f)); } private CheckResult VALID => GetValid(LFormValid); @@ -247,15 +247,20 @@ private void VerifyFormFriendSafari(LegalityAnalysis data) } } - private CheckResult VerifyFormArgument(LegalityAnalysis data, in uint arg) + private CheckResult VerifyFormArgument(LegalityAnalysis data, IFormArgument f) { var pkm = data.pkm; var enc = data.EncounterMatch; + var arg = f.FormArgument; + + var unusedMask = pkm.Format == 6 ? 0xFFFF_FF00 : 0xFF00_0000; + if ((arg & unusedMask) != 0) + return GetInvalid(LFormArgumentHigh); return (Species)pkm.Species switch { - Furfrou when pkm.Form != 0 => !IsFormArgumentDayCounterValid(arg, 5) ? GetInvalid(LFormArgumentInvalid) :GetValid(LFormArgumentValid), - Hoopa when pkm.Form == 1 => !IsFormArgumentDayCounterValid(arg, 3) ? GetInvalid(LFormArgumentInvalid) : GetValid(LFormArgumentValid), + Furfrou when pkm.Form != 0 => !IsFormArgumentDayCounterValid(f, 5) ? GetInvalid(LFormArgumentInvalid) :GetValid(LFormArgumentValid), + Hoopa when pkm.Form == 1 => !IsFormArgumentDayCounterValid(f, 3) ? GetInvalid(LFormArgumentInvalid) : GetValid(LFormArgumentValid), Yamask when pkm.Form == 1 => arg switch { not 0 when pkm.IsEgg => GetInvalid(LFormArgumentNotAllowed), @@ -283,27 +288,45 @@ private CheckResult VerifyFormArgument(LegalityAnalysis data, in uint arg) > (uint) AlcremieDecoration.Ribbon => GetInvalid(LFormArgumentHigh), _ => GetValid(LFormArgumentValid) }, - _ => arg switch - { - not 0 => GetInvalid(LFormArgumentNotAllowed), - _ => GetValid(LFormArgumentValid) - }, + _ => VerifyFormArgumentNone(pkm, f), }; } - private static bool IsFormArgumentDayCounterValid(uint value, uint maxSeed, bool canRefresh = false) + private CheckResult VerifyFormArgumentNone(PKM pkm, IFormArgument f) { - // lowest byte is days remaining - // second lowest is days elapsed (lol) - var remain = value & 0xFF; - var elapsed = (value >> 8) & 0xFF; + if (f.FormArgument != 0) + return GetInvalid(LFormArgumentNotAllowed); + + if (pkm is not PK6 pk6) + return GetValid(LFormArgumentValid); + + // Stored separately from main form argument value + if (pk6.FormArgumentRemain != 0) + return GetInvalid(LFormArgumentNotAllowed); + if (pk6.FormArgumentElapsed != 0) + return GetInvalid(LFormArgumentNotAllowed); + + return GetValid(LFormArgumentValid); + } + + private static bool IsFormArgumentDayCounterValid(IFormArgument f, uint maxSeed, bool canRefresh = false) + { + var remain = f.FormArgumentRemain; + var elapsed = f.FormArgumentElapsed; + var maxElapsed = f.FormArgumentMaximum; if (canRefresh) { + if (maxElapsed < elapsed) + return false; + if (remain + elapsed < maxSeed) return false; } else { + if (maxElapsed != 0) + return false; + if (remain + elapsed != maxSeed) return false; } diff --git a/PKHeX.Core/PKM/PB7.cs b/PKHeX.Core/PKM/PB7.cs index adfced0fb..a215968e3 100644 --- a/PKHeX.Core/PKM/PB7.cs +++ b/PKHeX.Core/PKM/PB7.cs @@ -131,6 +131,10 @@ public override uint PID public int HeightScalar { get => Data[0x3A]; set => Data[0x3A] = (byte)value; } public int WeightScalar { get => Data[0x3B]; set => Data[0x3B] = (byte)value; } public uint FormArgument { get => BitConverter.ToUInt32(Data, 0x3C); set => BitConverter.GetBytes(value).CopyTo(Data, 0x3C); } + public byte FormArgumentRemain { get => (byte)FormArgument; set => FormArgument = (FormArgument & ~0xFFu) | value; } + public byte FormArgumentElapsed { get => (byte)(FormArgument >> 8); set => FormArgument = (FormArgument & ~0xFF00u) | (uint)(value << 8); } + public byte FormArgumentMaximum { get => (byte)(FormArgument >> 16); set => FormArgument = (FormArgument & ~0xFF0000u) | (uint)(value << 16); } + #endregion #region Block B public override string Nickname diff --git a/PKHeX.Core/PKM/PK4.cs b/PKHeX.Core/PKM/PK4.cs index 082e45f65..9c671abc3 100644 --- a/PKHeX.Core/PKM/PK4.cs +++ b/PKHeX.Core/PKM/PK4.cs @@ -371,7 +371,7 @@ public PK5 ConvertToPK5() DateTime moment = DateTime.Now; - PK5 pk5 = new(Data) // Convert away! + PK5 pk5 = new((byte[])Data.Clone()) // Convert away! { OT_Friendship = 70, // Apply new met date diff --git a/PKHeX.Core/PKM/PK6.cs b/PKHeX.Core/PKM/PK6.cs index d6265ec3f..3b176ca30 100644 --- a/PKHeX.Core/PKM/PK6.cs +++ b/PKHeX.Core/PKM/PK6.cs @@ -216,6 +216,7 @@ public override uint PID public bool Dist7 { get => (DistByte & (1 << 6)) == 1 << 6; set => DistByte = (byte)((DistByte & ~(1 << 6)) | (value ? 1 << 6 : 0)); } public bool Dist8 { get => (DistByte & (1 << 7)) == 1 << 7; set => DistByte = (byte)((DistByte & ~(1 << 7)) | (value ? 1 << 7 : 0)); } public uint FormArgument { get => BitConverter.ToUInt32(Data, 0x3C); set => BitConverter.GetBytes(value).CopyTo(Data, 0x3C); } + public byte FormArgumentMaximum { get => (byte)FormArgument; set => FormArgument = value & 0xFFu; } #endregion #region Block B public override string Nickname { get => GetString(0x40, 24); set => SetString(value, 12).CopyTo(Data, 0x40); } @@ -352,6 +353,8 @@ public override int RelearnMove4 #region Battle Stats public override int Status_Condition { get => BitConverter.ToInt32(Data, 0xE8); set => BitConverter.GetBytes(value).CopyTo(Data, 0xE8); } public override int Stat_Level { get => Data[0xEC]; set => Data[0xEC] = (byte)value; } + public byte FormArgumentRemain { get => Data[0xED]; set => Data[0xED] = value; } + public byte FormArgumentElapsed { get => Data[0xEE]; set => Data[0xEE] = value; } public override int Stat_HPCurrent { get => BitConverter.ToUInt16(Data, 0xF0); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xF0); } public override int Stat_HPMax { get => BitConverter.ToUInt16(Data, 0xF2); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xF2); } public override int Stat_ATK { get => BitConverter.ToUInt16(Data, 0xF4); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xF4); } @@ -453,10 +456,13 @@ protected override void TradeHT(ITrainerInfo tr) public PK7 ConvertToPK7() { - PK7 pk7 = new(Data) + PK7 pk7 = new((byte[])Data.Clone()) { Markings = Markings, // Clears old Super Training Bag & Hits Remaining Data = { [0x2A] = 0 }, // Clears old Marking Value + FormArgument = 0, // Clears old style Form Argument + DirtType = 0, // Clears old Form Argument byte + DirtLocation = 0, // Clears old Form Argument byte }; var an = AbilityNumber; @@ -479,6 +485,11 @@ public PK7 ConvertToPK7() pk7.Data[0x72] &= 0xFC; /* Clear lower two bits of Super training flags. */ pk7.Data[0xDE] = 0; /* Gen IV encounter type. */ + // Copy Form Argument data for Furfrou and Hoopa, since we're nice. + pk7.FormArgumentRemain = FormArgumentRemain; + pk7.FormArgumentElapsed = FormArgumentElapsed; + pk7.FormArgumentMaximum = FormArgumentMaximum; + pk7.HealPP(); // Fix Checksum pk7.RefreshChecksum(); diff --git a/PKHeX.Core/PKM/PK7.cs b/PKHeX.Core/PKM/PK7.cs index baeae623a..909977ddf 100644 --- a/PKHeX.Core/PKM/PK7.cs +++ b/PKHeX.Core/PKM/PK7.cs @@ -226,6 +226,9 @@ public override uint PID public bool Dist7 { get => (DistByte & (1 << 6)) == 1 << 6; set => DistByte = (byte)((DistByte & ~(1 << 6)) | (value ? 1 << 6 : 0)); } public bool Dist8 { get => (DistByte & (1 << 7)) == 1 << 7; set => DistByte = (byte)((DistByte & ~(1 << 7)) | (value ? 1 << 7 : 0)); } public uint FormArgument { get => BitConverter.ToUInt32(Data, 0x3C); set => BitConverter.GetBytes(value).CopyTo(Data, 0x3C); } + public byte FormArgumentRemain { get => (byte)FormArgument; set => FormArgument = (FormArgument & ~0xFFu) | value; } + public byte FormArgumentElapsed { get => (byte)(FormArgument >> 8); set => FormArgument = (FormArgument & ~0xFF00u) | (uint)(value << 8); } + public byte FormArgumentMaximum { get => (byte)(FormArgument >> 16); set => FormArgument = (FormArgument & ~0xFF0000u) | (uint)(value << 16); } #endregion #region Block B public override string Nickname @@ -633,6 +636,11 @@ public PK8 ConvertToPK8() StatNature = Nature, // HeightScalar = 0, // WeightScalar = 0, + + // Copy Form Argument data for Furfrou and Hoopa, since we're nice. + FormArgumentRemain = FormArgumentRemain, + FormArgumentElapsed = FormArgumentElapsed, + FormArgumentMaximum = FormArgumentMaximum, }; // Wipe Totem Forms diff --git a/PKHeX.Core/PKM/PK8.cs b/PKHeX.Core/PKM/PK8.cs index 8dacf581a..afe56fc38 100644 --- a/PKHeX.Core/PKM/PK8.cs +++ b/PKHeX.Core/PKM/PK8.cs @@ -441,6 +441,9 @@ public override string Nickname public override int Language { get => Data[0xE2]; set => Data[0xE2] = (byte)value; } public int UnkE3 { get => Data[0xE3]; set => Data[0xE3] = (byte)value; } public uint FormArgument { get => BitConverter.ToUInt32(Data, 0xE4); set => BitConverter.GetBytes(value).CopyTo(Data, 0xE4); } + public byte FormArgumentRemain { get => (byte)FormArgument; set => FormArgument = (FormArgument & ~0xFFu) | value; } + public byte FormArgumentElapsed { get => (byte)(FormArgument >> 8); set => FormArgument = (FormArgument & ~0xFF00u) | (uint)(value << 8); } + public byte FormArgumentMaximum { get => (byte)(FormArgument >> 16); set => FormArgument = (FormArgument & ~0xFF0000u) | (uint)(value << 16); } public sbyte AffixedRibbon { get => (sbyte)Data[0xE8]; set => Data[0xE8] = (byte)value; } // selected ribbon // remainder unused diff --git a/PKHeX.Core/PKM/Shared/IFormArgument.cs b/PKHeX.Core/PKM/Shared/IFormArgument.cs index a4297135f..6eebb5ff2 100644 --- a/PKHeX.Core/PKM/Shared/IFormArgument.cs +++ b/PKHeX.Core/PKM/Shared/IFormArgument.cs @@ -16,5 +16,20 @@ public interface IFormArgument /// Argument for the associated /// uint FormArgument { get; set; } + + /// + /// Amount of days the timed will remain active for. + /// + byte FormArgumentRemain { get; set; } + + /// + /// Amount of days the timed has been active for. + /// + byte FormArgumentElapsed { get; set; } + + /// + /// Maximum amount of days the has maintained a without reverting to its base form. + /// + byte FormArgumentMaximum { get; set; } } } \ No newline at end of file diff --git a/PKHeX.Core/PKM/Util/FormConverter.cs b/PKHeX.Core/PKM/Util/FormConverter.cs index 2b6986bc5..3539b7fde 100644 --- a/PKHeX.Core/PKM/Util/FormConverter.cs +++ b/PKHeX.Core/PKM/Util/FormConverter.cs @@ -758,23 +758,6 @@ public static bool IsFormArgumentTypeDatePair(int species, int form) }; } - public static uint GetFormArgument(int species, int form, int generation, uint current) - { - var max = GetFormArgumentMax(species, form, generation); - var pair = IsFormArgumentTypeDatePair(species, form); - if (!pair) - return Math.Min(current, max); - return GetFormArgumentDatePairCombined(current, max); - } - - public static uint GetFormArgumentDatePairCombined(uint current, uint max) - { - if (current > max) - current = max; - var elapsed = max - current; - return (uint)(((byte)elapsed << 8) | (byte)current); - } - public static bool GetFormArgumentIsNamedIndex(int species) => species == (int)Alcremie; public static string[] GetFormArgumentStrings(int species) => species switch @@ -782,5 +765,27 @@ public static uint GetFormArgumentDatePairCombined(uint current, uint max) (int)Alcremie => Enum.GetNames(typeof(AlcremieDecoration)), _ => EMPTY }; + + public static void ChangeFormArgument(IFormArgument f, int species, int form, int generation, uint value) + { + if (!IsFormArgumentTypeDatePair(species, form)) + { + f.FormArgument = value; + return; + } + + var max = GetFormArgumentMax(species, form, generation); + f.FormArgumentRemain = (byte)value; + if (value == max) + { + f.FormArgumentElapsed = f.FormArgumentMaximum = 0; + return; + } + + byte elapsed = max < value ? 0 : (byte)(max - value); + f.FormArgumentElapsed = elapsed; + if (species == (int)Furfrou) + f.FormArgumentMaximum = Math.Max(f.FormArgumentMaximum, elapsed); + } } } diff --git a/PKHeX.Core/Saves/SAV3Colosseum.cs b/PKHeX.Core/Saves/SAV3Colosseum.cs index 055d8e64a..b6f24c6a3 100644 --- a/PKHeX.Core/Saves/SAV3Colosseum.cs +++ b/PKHeX.Core/Saves/SAV3Colosseum.cs @@ -302,7 +302,7 @@ protected override byte[] DecryptPKM(byte[] data) return data; } - protected override void SetPKM(PKM pkm) + protected override void SetPKM(PKM pkm, bool isParty = false) { if (pkm is not CK3 pk) return; diff --git a/PKHeX.Core/Saves/SAV3XD.cs b/PKHeX.Core/Saves/SAV3XD.cs index 9fa2a989b..bba536d72 100644 --- a/PKHeX.Core/Saves/SAV3XD.cs +++ b/PKHeX.Core/Saves/SAV3XD.cs @@ -285,7 +285,7 @@ public override PKM GetStoredSlot(byte[] data, int offset) return pk; } - protected override void SetPKM(PKM pkm) + protected override void SetPKM(PKM pkm, bool isParty = false) { if (pkm is not XK3 pk) return; // shouldn't ever hit diff --git a/PKHeX.Core/Saves/SAV4.cs b/PKHeX.Core/Saves/SAV4.cs index bfa90e8a1..032b44308 100644 --- a/PKHeX.Core/Saves/SAV4.cs +++ b/PKHeX.Core/Saves/SAV4.cs @@ -401,7 +401,7 @@ public int Z protected override PKM GetPKM(byte[] data) => new PK4(data); protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray45(data); - protected override void SetPKM(PKM pkm) + protected override void SetPKM(PKM pkm, bool isParty = false) { var pk4 = (PK4)pkm; // Apply to this Save File diff --git a/PKHeX.Core/Saves/SAV4BR.cs b/PKHeX.Core/Saves/SAV4BR.cs index 05eed42af..9795b39c8 100644 --- a/PKHeX.Core/Saves/SAV4BR.cs +++ b/PKHeX.Core/Saves/SAV4BR.cs @@ -230,7 +230,7 @@ protected override PKM GetPKM(byte[] data) protected override void SetDex(PKM pkm) { /* There's no PokéDex */ } - protected override void SetPKM(PKM pkm) + protected override void SetPKM(PKM pkm, bool isParty = false) { var pk4 = (BK4)pkm; // Apply to this Save File diff --git a/PKHeX.Core/Saves/SAV5.cs b/PKHeX.Core/Saves/SAV5.cs index 8d02f316e..0e7d26a98 100644 --- a/PKHeX.Core/Saves/SAV5.cs +++ b/PKHeX.Core/Saves/SAV5.cs @@ -104,7 +104,7 @@ public bool BattleBoxLocked set => Data[BattleBoxOffset + 0x358] = value ? 1 : 0; } - protected override void SetPKM(PKM pkm) + protected override void SetPKM(PKM pkm, bool isParty = false) { var pk5 = (PK5)pkm; // Apply to this Save File diff --git a/PKHeX.Core/Saves/SAV6.cs b/PKHeX.Core/Saves/SAV6.cs index ffbed48d7..a14fb30f1 100644 --- a/PKHeX.Core/Saves/SAV6.cs +++ b/PKHeX.Core/Saves/SAV6.cs @@ -101,7 +101,7 @@ public override void SetBoxName(int box, string value) SetData(data, PCLayout + (LongStringLength * box)); } - protected override void SetPKM(PKM pkm) + protected override void SetPKM(PKM pkm, bool isParty = false) { PK6 pk6 = (PK6)pkm; // Apply to this Save File @@ -116,6 +116,27 @@ protected override void SetPKM(PKM pkm) else if (pk6.HasMove(218)) // Frustration pkm.CurrentFriendship = pk6.OppositeFriendship; } + + pk6.FormArgumentElapsed = pk6.FormArgumentMaximum = 0; + pk6.FormArgumentRemain = (byte)GetFormArgument(pkm, isParty); + if (!isParty && pkm.Form != 0) + { + switch (pkm.Species) + { + case (int) Species.Furfrou: + pkm.Form = 0; + break; + case (int) Species.Hoopa: + { + pkm.Form = 0; + var hsf = Array.IndexOf(pkm.Moves, (int) Move.HyperspaceFury); + if (hsf != -1) + pkm.SetMove(hsf, (int) Move.HyperspaceHole); + break; + } + } + } + pkm.RefreshChecksum(); AddCountAcquired(pkm); } @@ -129,12 +150,6 @@ private void AddCountAcquired(PKM pkm) Records.AddRecord(005); // wild encounters } - protected override void SetPartyValues(PKM pkm, bool isParty) - { - base.SetPartyValues(pkm, isParty); - ((PK6)pkm).FormArgument = GetFormArgument(pkm, isParty); - } - private static uint GetFormArgument(PKM pkm, bool isParty) { if (!isParty || pkm.Form == 0) diff --git a/PKHeX.Core/Saves/SAV7.cs b/PKHeX.Core/Saves/SAV7.cs index 093180d51..4ef05617c 100644 --- a/PKHeX.Core/Saves/SAV7.cs +++ b/PKHeX.Core/Saves/SAV7.cs @@ -170,7 +170,7 @@ public override byte[] SetString(string value, int maxLength, int PadToSize = 0, public override int BoxesUnlocked { get => BoxLayout.BoxesUnlocked; set => BoxLayout.BoxesUnlocked = value; } public override byte[] BoxFlags { get => BoxLayout.BoxFlags; set => BoxLayout.BoxFlags = value; } - protected override void SetPKM(PKM pkm) + protected override void SetPKM(PKM pkm, bool isParty = false) { PK7 pk7 = (PK7)pkm; // Apply to this Save File @@ -185,6 +185,10 @@ protected override void SetPKM(PKM pkm) else if (pk7.HasMove(218)) // Frustration pkm.CurrentFriendship = pk7.OppositeFriendship; } + + pk7.FormArgumentElapsed = pk7.FormArgumentMaximum = 0; + pk7.FormArgumentRemain = (byte)GetFormArgument(pkm); + pkm.RefreshChecksum(); AddCountAcquired(pkm); } @@ -198,12 +202,6 @@ private void AddCountAcquired(PKM pkm) Records.AddRecord(004); // wild encounters } - protected override void SetPartyValues(PKM pkm, bool isParty) - { - base.SetPartyValues(pkm, isParty); - ((PK7)pkm).FormArgument = GetFormArgument(pkm); - } - private static uint GetFormArgument(PKM pkm) { if (pkm.Form == 0) diff --git a/PKHeX.Core/Saves/SAV7b.cs b/PKHeX.Core/Saves/SAV7b.cs index 823d82f8f..168bcaafb 100644 --- a/PKHeX.Core/Saves/SAV7b.cs +++ b/PKHeX.Core/Saves/SAV7b.cs @@ -82,7 +82,7 @@ private void Initialize() public bool FixPreWrite() => Blocks.Storage.CompressStorage(); - protected override void SetPKM(PKM pkm) + protected override void SetPKM(PKM pkm, bool isParty = false) { var pk = (PB7)pkm; // Apply to this Save File diff --git a/PKHeX.Core/Saves/SAV8.cs b/PKHeX.Core/Saves/SAV8.cs index 947036c8f..13c4f3081 100644 --- a/PKHeX.Core/Saves/SAV8.cs +++ b/PKHeX.Core/Saves/SAV8.cs @@ -100,16 +100,35 @@ public override byte[] SetString(string value, int maxLength, int PadToSize = 0, public override void SetBoxName(int box, string value) => BoxLayout[box] = value; public override byte[] GetDataForBox(PKM pkm) => pkm.EncryptedPartyData; - protected override void SetPKM(PKM pkm) + protected override void SetPKM(PKM pkm, bool isParty = false) { PK8 pk = (PK8)pkm; // Apply to this Save File DateTime Date = DateTime.Now; pk.Trade(this, Date.Day, Date.Month, Date.Year); + + if (FormConverter.IsFormArgumentTypeDatePair(pk.Species, pk.Form)) + { + pk.FormArgumentElapsed = pk.FormArgumentMaximum = 0; + pk.FormArgumentRemain = (byte)GetFormArgument(pkm); + } + pkm.RefreshChecksum(); AddCountAcquired(pkm); } + private static uint GetFormArgument(PKM pkm) + { + if (pkm.Form == 0) + return 0; + return pkm.Species switch + { + (int)Species.Furfrou => 5u, // Furfrou + (int)Species.Hoopa => 3u, // Hoopa + _ => 0u + }; + } + private void AddCountAcquired(PKM pkm) { if (pkm.WasEgg) diff --git a/PKHeX.Core/Saves/SaveFile.cs b/PKHeX.Core/Saves/SaveFile.cs index 9e47c590b..aeca54eb6 100644 --- a/PKHeX.Core/Saves/SaveFile.cs +++ b/PKHeX.Core/Saves/SaveFile.cs @@ -357,7 +357,7 @@ public void SetSlotFormatParty(PKM pkm, byte[] data, int offset, PKMImportSettin if (pkm.GetType() != PKMType) throw new ArgumentException($"PKM Format needs to be {PKMType} when setting to this Save File."); - UpdatePKM(pkm, trade, dex); + UpdatePKM(pkm, isParty: true, trade, dex); SetPartyValues(pkm, isParty: true); WritePartySlot(pkm, data, offset); } @@ -367,7 +367,7 @@ public void SetPartySlot(PKM pkm, byte[] data, int offset, PKMImportSetting trad if (pkm.GetType() != PKMType) throw new ArgumentException($"PKM Format needs to be {PKMType} when setting to this Save File."); - UpdatePKM(pkm, trade, dex); + UpdatePKM(pkm, isParty: true, trade, dex); SetPartyValues(pkm, isParty: true); WritePartySlot(pkm, data, offset); } @@ -377,7 +377,7 @@ public void SetSlotFormatStored(PKM pkm, byte[] data, int offset, PKMImportSetti if (pkm.GetType() != PKMType) throw new ArgumentException($"PKM Format needs to be {PKMType} when setting to this Save File."); - UpdatePKM(pkm, trade, dex); + UpdatePKM(pkm, isParty: false, trade, dex); SetPartyValues(pkm, isParty: false); WriteSlotFormatStored(pkm, data, offset); } @@ -387,7 +387,7 @@ public void SetBoxSlot(PKM pkm, byte[] data, int offset, PKMImportSetting trade if (pkm.GetType() != PKMType) throw new ArgumentException($"PKM Format needs to be {PKMType} when setting to this Save File."); - UpdatePKM(pkm, trade, dex); + UpdatePKM(pkm, isParty: false, trade, dex); SetPartyValues(pkm, isParty: false); WriteBoxSlot(pkm, data, offset); } @@ -453,16 +453,17 @@ protected virtual void SetPartyValues(PKM pkm, bool isParty) /// Conditions a for this save file as if it was traded to it. /// /// Entity to adapt + /// Entity exists in party format /// Setting on whether or not to adapt - public void AdaptPKM(PKM pkm, PKMImportSetting trade = PKMImportSetting.UseDefault) + public void AdaptPKM(PKM pkm, bool party = true, PKMImportSetting trade = PKMImportSetting.UseDefault) { if (GetTradeUpdateSetting(trade)) - SetPKM(pkm); + SetPKM(pkm, party); } - protected void UpdatePKM(PKM pkm, PKMImportSetting trade, PKMImportSetting dex) + protected void UpdatePKM(PKM pkm, bool isParty, PKMImportSetting trade, PKMImportSetting dex) { - AdaptPKM(pkm, trade); + AdaptPKM(pkm, isParty, trade); if (GetDexUpdateSetting(dex)) SetDex(pkm); } @@ -481,7 +482,7 @@ private static bool GetDexUpdateSetting(PKMImportSetting trade = PKMImportSettin return trade == PKMImportSetting.Update; } - protected virtual void SetPKM(PKM pkm) { } + protected virtual void SetPKM(PKM pkm, bool isParty = false) { } protected virtual void SetDex(PKM pkm) { } #endregion diff --git a/PKHeX.WinForms/Controls/PKM Editor/EditPK6.cs b/PKHeX.WinForms/Controls/PKM Editor/EditPK6.cs index 694e05fb3..4e97d8683 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/EditPK6.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/EditPK6.cs @@ -42,7 +42,7 @@ private PK6 PreparePK6() // Unneeded Party Stats (Status, Flags, Unused) pk6.Data[0xE8] = pk6.Data[0xE9] = pk6.Data[0xEA] = pk6.Data[0xEB] = - pk6.Data[0xED] = pk6.Data[0xEE] = pk6.Data[0xEF] = + pk6.Data[0xEF] = pk6.Data[0xFE] = pk6.Data[0xFF] = pk6.Data[0x100] = pk6.Data[0x101] = pk6.Data[0x102] = pk6.Data[0x103] = 0; diff --git a/PKHeX.WinForms/Controls/PKM Editor/FormArgument.cs b/PKHeX.WinForms/Controls/PKM Editor/FormArgument.cs index 4f8357e2a..4d1298b6e 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/FormArgument.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/FormArgument.cs @@ -61,16 +61,21 @@ public void LoadArgument(IFormArgument f, int species, int form, int generation) CurrentGeneration = generation; if (FormConverter.IsFormArgumentTypeDatePair(species, form)) - CurrentValue = f.FormArgument & 0xFF; + CurrentValue = f.FormArgumentRemain; else CurrentValue = f.FormArgument; FieldsLoaded = true; } - public uint CurrentValue + public void SaveArgument(IFormArgument f) { - get => IsRawMode ? FormConverter.GetFormArgument(CurrentSpecies, CurrentForm, CurrentGeneration, (uint) NUD_FormArg.Value) : (uint) CB_FormArg.SelectedIndex; + FormConverter.ChangeFormArgument(f, CurrentSpecies, CurrentForm, CurrentGeneration, CurrentValue); + } + + private uint CurrentValue + { + get => IsRawMode ? (uint) NUD_FormArg.Value : (uint) CB_FormArg.SelectedIndex; set { if (IsRawMode) @@ -80,7 +85,6 @@ public uint CurrentValue } } - public void SaveArgument(IFormArgument f) => f.FormArgument = CurrentValue; public event EventHandler? ValueChanged; private void CB_FormArg_SelectedIndexChanged(object sender, EventArgs e) diff --git a/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs b/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs index 3f64cd304..fdeb27e29 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs @@ -187,7 +187,7 @@ private void SaveMisc2(PKM pk) pk.HeldItem = WinFormsUtil.GetIndex(CB_HeldItem); pk.Form = (MT_Form.Enabled ? Convert.ToInt32(MT_Form.Text) : CB_Form.Enabled ? CB_Form.SelectedIndex : 0) & 0x1F; if (Entity is IFormArgument f) - f.FormArgument = FA_Form.CurrentValue; + FA_Form.SaveArgument(f); pk.CurrentFriendship = Util.ToInt32(TB_Friendship.Text); } diff --git a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.Designer.cs b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.Designer.cs index 6554f12c8..aed394580 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.Designer.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.Designer.cs @@ -819,7 +819,6 @@ private void InitializeComponent() // // FA_Form // - this.FA_Form.CurrentValue = ((uint)(4294967295u)); this.FA_Form.Location = new System.Drawing.Point(90, 0); this.FA_Form.Margin = new System.Windows.Forms.Padding(0); this.FA_Form.Name = "FA_Form"; diff --git a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs index 64f971f08..0c466107a 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs @@ -1016,11 +1016,8 @@ private void RefreshFormArguments() if (Entity is not IFormArgument f) return; - var index = FA_Form.CurrentValue; + FA_Form.SaveArgument(f); FA_Form.LoadArgument(f, Entity.Species, Entity.Form, Entity.Format); - if (ChangingFields) - return; - FA_Form.CurrentValue = index; } private void UpdateHaXForm(object sender, EventArgs e)