From fd2da22d3a6cd8a76a5dfa4547f8f2a263371774 Mon Sep 17 00:00:00 2001 From: Kurt Date: Thu, 7 Sep 2017 23:18:04 -0700 Subject: [PATCH] Update PKMConverter internals [insert lenny face here] --- .../Encounters/EncounterSuggestion.cs | 2 +- PKHeX.Core/PKM/PKMConverter.cs | 257 ++++++++++-------- 2 files changed, 147 insertions(+), 112 deletions(-) diff --git a/PKHeX.Core/Legality/Encounters/EncounterSuggestion.cs b/PKHeX.Core/Legality/Encounters/EncounterSuggestion.cs index 2ae3747af..1c16f9ee6 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterSuggestion.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterSuggestion.cs @@ -65,7 +65,7 @@ private static EncounterStatic GetSuggestedEncounterStatic(EncounterStatic s, in /// /// Gets a valid Egg hatch location for the origin game. /// - private static int GetSuggestedEggMetLocation(PKM pkm) + public static int GetSuggestedEggMetLocation(PKM pkm) { // Return one of legal hatch locations for game switch ((GameVersion)pkm.Version) diff --git a/PKHeX.Core/PKM/PKMConverter.cs b/PKHeX.Core/PKM/PKMConverter.cs index a4cf2b300..73431ac4e 100644 --- a/PKHeX.Core/PKM/PKMConverter.cs +++ b/PKHeX.Core/PKM/PKMConverter.cs @@ -130,9 +130,9 @@ public static PKM GetPKMfromBytes(byte[] data, string ident = null, int prefer = /// Checks if the input PK6 file is really a PK7. /// /// PK6 to check - /// Prefer a certain generation over another + /// Prefer a certain generation over another /// Boolean is a PK7 - private static bool IsPK6FormatReallyPK7(PK6 pk, int prefer) + private static bool IsPK6FormatReallyPK7(PK6 pk, int preferredFormat) { if (pk.Version > Legal.MaxGameID_6) return true; @@ -170,7 +170,7 @@ private static bool IsPK6FormatReallyPK7(PK6 pk, int prefer) if ((mb >> (i << 1) & 3) == 3) // markings are 10 or 01 (or 00), never 11 return false; - return prefer > 6; + return preferredFormat > 6; } /// @@ -187,139 +187,174 @@ public static bool IsConvertibleToFormat(PKM pk, int format) return false; // pk1/2->upward has to be 7 or greater return true; } + + /// + /// Converts a PKM from one Generation 3 format to another. If it matches the destination format, the conversion will automatically return. + /// + /// PKM to convert + /// Format/Type to convert to + /// Comments regarding the transfer's success/failure + /// Converted PKM public static PKM ConvertToType(PKM pk, Type PKMType, out string comment) { if (pk == null || pk.Species == 0) { - comment = "Null input. Aborting."; + comment = $"Bad {nameof(pk)} input. Aborting."; return null; } Type fromType = pk.GetType(); - int fromFormat = int.Parse(fromType.Name.Last().ToString()); - int toFormat = int.Parse(PKMType.Name.Last().ToString()); - Debug.WriteLine($"Trying to convert {fromType.Name} to {PKMType.Name}."); - - PKM pkm = null; - if (fromType == PKMType) { comment = "No need to convert, current format matches requested format."; return pk; } - if (fromFormat <= toFormat || fromFormat == 2) - { - pkm = pk.Clone(); - if (pkm.IsEgg) // force hatch - { - pkm.IsEgg = false; - if (pkm.AO) - pkm.Met_Location = 318; // Battle Resort - else if (pkm.XY) - pkm.Met_Location = 38; // Route 7 - else if (pkm.Gen5) - pkm.Met_Location = 16; // Route 16 - else - pkm.Met_Location = 30001; // Pokétransfer - pkm.IsNicknamed = false; - pkm.Nickname = PKX.GetSpeciesNameGeneration(pkm.Species, pkm.Language, fromFormat); - } - switch (fromType.Name) - { - case nameof(PK1): - if (toFormat == 2) - { - pkm = PKMType == typeof (PK2) ? ((PK1) pk).ConvertToPK2() : null; - break; - } - if (toFormat == 7) - pkm = ((PK1) pk).ConvertToPK7(); - break; - case nameof(PK2): - if (PKMType == typeof (PK1)) - { - if (pk.Species > 151) - { - comment = $"Cannot convert a {PKX.GetSpeciesName(pkm.Species, ((PK2)pkm).Japanese ? 1 : 2)} to {PKMType.Name}"; - return null; - } - pkm = ((PK2) pk).ConvertToPK1(); - pkm.ClearInvalidMoves(); - } - else - pkm = null; - break; - case nameof(CK3): - case nameof(XK3): - // interconverting C/XD needs to visit main series format - // ends up stripping purification/shadow etc stats - pkm = pkm.ConvertToPK3(); - goto case nameof(PK3); // fall through - case nameof(PK3): - if (toFormat == 3) // Gen3 Inter-trading - { - switch (PKMType.Name) - { - case nameof(CK3): pkm = pkm.ConvertToCK3(); break; - case nameof(XK3): pkm = pkm.ConvertToXK3(); break; - case nameof(PK3): pkm = pkm.ConvertToPK3(); break; // already converted, instantly returns - default: throw new FormatException(); - } - break; - } - if (fromType.Name != nameof(PK3)) - pkm = pkm.ConvertToPK3(); - pkm = ((PK3)pkm).ConvertToPK4(); - if (toFormat == 4) - break; - goto case nameof(PK4); - case nameof(BK4): - pkm = ((BK4)pkm).ConvertToPK4(); - if (toFormat == 4) - break; - goto case nameof(PK4); - case nameof(PK4): - if (PKMType == typeof(BK4)) + Debug.WriteLine($"Trying to convert {fromType.Name} to {PKMType.Name}."); + + int fromFormat = int.Parse(fromType.Name.Last().ToString()); + int toFormat = int.Parse(PKMType.Name.Last().ToString()); + if (fromFormat > toFormat && fromFormat != 2) + { + comment = $"Cannot convert a {fromType.Name} to a {PKMType.Name}."; + return null; + } + + PKM pkm = pk.Clone(); + if (pkm.IsEgg) + ForceHatchPKM(pkm); + + switch (fromType.Name) + { + case nameof(PK1): + if (toFormat == 7) // VC->Bank + pkm = ((PK1)pk).ConvertToPK7(); + else if (toFormat == 2) // GB<->GB + pkm = ((PK1)pk).ConvertToPK2(); + break; + case nameof(PK2): + if (toFormat == 7) // VC->Bank + pkm = ((PK2)pk).ConvertToPK7(); + else if (toFormat == 1) // GB<->GB + { + if (pk.Species > 151) { - pkm = ((PK4)pkm).ConvertToBK4(); - break; - } - if (pkm.Species == 172 && pkm.AltForm != 0) - { - comment = "Cannot transfer Spiky-Eared Pichu forward."; + comment = $"Cannot convert a {PKX.GetSpeciesName(pkm.Species, ((PK2)pkm).Japanese ? 1 : 2)} to {PKMType.Name}"; return null; } - pkm = ((PK4)pkm).ConvertToPK5(); - if (toFormat == 5) - break; - goto case nameof(PK5); - case nameof(PK5): - pkm = ((PK5)pkm).ConvertToPK6(); - if (toFormat == 6) - break; - goto case nameof(PK6); - case nameof(PK6): - if (pkm.Species == 25 && pkm.AltForm != 0) // cosplay pikachu - { - comment = "Cannot transfer Cosplay Pikachu forward."; - return null; - } - pkm = ((PK6)pkm).ConvertToPK7(); - if (toFormat == 7) - break; - goto case nameof(PK7); - case nameof(PK7): + pkm = ((PK2)pk).ConvertToPK1(); + pkm.ClearInvalidMoves(); + } + break; + case nameof(CK3): + case nameof(XK3): + // interconverting C/XD needs to visit main series format + // ends up stripping purification/shadow etc stats + pkm = pkm.ConvertToPK3(); + goto case nameof(PK3); // fall through + case nameof(PK3): + if (toFormat == 3) // Gen3 Inter-trading + { + pkm = InterConvertPK3(pkm, PKMType); break; - } + } + if (fromType.Name != nameof(PK3)) + pkm = pkm.ConvertToPK3(); + + pkm = ((PK3) pkm).ConvertToPK4(); + if (toFormat == 4) + break; + goto case nameof(PK4); + case nameof(BK4): + pkm = ((BK4) pkm).ConvertToPK4(); + if (toFormat == 4) + break; + goto case nameof(PK4); + case nameof(PK4): + if (PKMType == typeof(BK4)) + { + pkm = ((PK4) pkm).ConvertToBK4(); + break; + } + if (pkm.Species == 172 && pkm.AltForm != 0) + { + comment = "Cannot transfer Spiky-Eared Pichu forward."; + return null; + } + pkm = ((PK4) pkm).ConvertToPK5(); + if (toFormat == 5) + break; + goto case nameof(PK5); + case nameof(PK5): + pkm = ((PK5) pkm).ConvertToPK6(); + if (toFormat == 6) + break; + goto case nameof(PK6); + case nameof(PK6): + if (pkm.Species == 25 && pkm.AltForm != 0) // cosplay pikachu + { + comment = "Cannot transfer Cosplay Pikachu forward."; + return null; + } + pkm = ((PK6) pkm).ConvertToPK7(); + if (toFormat == 7) + break; + goto case nameof(PK7); + case nameof(PK7): + break; } comment = pkm == null - ? $"Cannot convert a {fromType.Name} to a {PKMType.Name}." + ? $"Cannot convert a {fromType.Name} to a {PKMType.Name}." : $"Converted from {fromType.Name} to {PKMType.Name}."; return pkm; } + + /// + /// Converts a PKM from one Generation 3 format to another. If it matches the destination format, the conversion will automatically return. + /// + /// PKM to convert + /// Format/Type to convert to + /// , , and are supported. + /// Converted PKM + private static PKM InterConvertPK3(PKM pk, Type desiredFormatType) + { + // if already converted it instantly returns + switch (desiredFormatType.Name) + { + case nameof(CK3): + return pk.ConvertToCK3(); + case nameof(XK3): + return pk.ConvertToXK3(); + case nameof(PK3): + return pk.ConvertToPK3(); + default: throw new FormatException(); + } + } + + /// + /// Force hatches a PKM by applying the current species name and a valid Met Location from the origin game. + /// + /// PKM to apply hatch details to + /// + /// is not checked; can be abused to re-hatch already hatched inputs. + /// is not modified; must be updated manually if desired. + /// + private static void ForceHatchPKM(PKM pkm) + { + pkm.IsEgg = false; + pkm.Nickname = PKX.GetSpeciesNameGeneration(pkm.Species, pkm.Language, pkm.Format); + var loc = EncounterSuggestion.GetSuggestedEggMetLocation(pkm); + if (loc >= 0) + pkm.Met_Location = loc; + } + + /// + /// Checks if a PKM is encrypted; if encrypted, decrypts the PKM. + /// + /// The input PKM object is decrypted; no new object is returned. + /// PKM to check encryption for (and decrypt if appropriate). public static void CheckEncrypted(ref byte[] pkm) { int format = GetPKMDataFormat(pkm);