/// <summary> /// Checks if the input <see cref="PKM"/> is compatible with the target <see cref="PKM"/>. /// </summary> /// <param name="pk">Input to check -> update/sanitize</param> /// <param name="target">Target type PKM with misc properties accessible for checking.</param> /// <param name="c">Comment output</param> /// <param name="pkm">Output compatible PKM</param> /// <returns>Indication if the input is (now) compatible with the target.</returns> public static bool TryMakePKMCompatible(PKM pk, PKM target, out string c, out PKM pkm) { if (!IsConvertibleToFormat(pk, target.Format)) { pkm = null; c = $"Can't load {pk.GetType().Name}s to Gen{target.Format} saves."; if (!AllowIncompatibleConversion) { return(false); } } if (target.Format < 3 && pk.Japanese != target.Japanese) { pkm = null; var strs = new[] { "International", "Japanese" }; var val = target.Japanese ? 0 : 1; c = $"Cannot load {strs[val]} {pk.GetType().Name}s to {strs[val ^ 1]} saves."; if (!AllowIncompatibleConversion) { return(false); } } pkm = ConvertToType(pk, target.GetType(), out c); Debug.WriteLine(c); return(pkm != null); }
public static List <PKM> GetLivingDex(this ITrainerInfo tr, IEnumerable <int> speciesToGenerate, PKM blank) { var result = new List <PKM>(); var destType = blank.GetType(); foreach (var s in speciesToGenerate) { var pk = blank.Clone(); pk.Species = s; pk.Gender = pk.GetSaneGender(); var pi = pk.PersonalInfo; for (int f = 0; f < pi.FormCount; f++) { var entry = tr.GetLivingEntry(pk, s, f, destType); if (entry == null) { continue; } result.Add(entry); } } return(result); }
public void setPartySlot(PKM pkm, int offset, bool?trade = null, bool?dex = null) { if (pkm == null) { return; } if (pkm.GetType() != PKMType) { throw new InvalidCastException($"PKM Format needs to be {PKMType} when setting to a Gen{Generation} Save File."); } if (trade ?? SetUpdatePKM) { setPKM(pkm); } if (dex ?? SetUpdateDex) { setDex(pkm); } for (int i = 0; i < 6; i++) { if (getPartyOffset(i) == offset) { if (PartyCount <= i) { PartyCount = i + 1; } } } setData(pkm.EncryptedPartyData, offset); Edited = true; }
/// <summary> /// Converts a PKM from one Generation 3 format to another. If it matches the destination format, the conversion will automatically return. /// </summary> /// <param name="pk">PKM to convert</param> /// <param name="PKMType">Format/Type to convert to</param> /// <param name="comment">Comments regarding the transfer's success/failure</param> /// <returns>Converted PKM</returns> public static PKM ConvertToType(PKM pk, Type PKMType, out string comment) { if (pk == null) { comment = $"Bad {nameof(pk)} input. Aborting."; return(null); } Type fromType = pk.GetType(); if (fromType == PKMType) { comment = "No need to convert, current format matches requested format."; return(pk); } var pkm = ConvertPKM(pk, PKMType, fromType, out comment); if (!AllowIncompatibleConversion || pkm != null) { return(pkm); } // Try Incompatible Conversion pkm = GetBlank(PKMType); pk.TransferPropertiesWithReflection(pkm); if (!IsPKMCompatibleWithModifications(pkm)) { return(null); } comment = "Converted via reflection."; return(pkm); }
public override void setStoredSlot(PKM pkm, int offset, bool?trade = null, bool?dex = null) { if (pkm == null) { return; } if (pkm.GetType() != PKMType) { throw new InvalidCastException($"PKM Format needs to be {PKMType} when setting to a Gen{Generation} Save File."); } if (trade ?? SetUpdatePKM) { setPKM(pkm); } if (dex ?? SetUpdateDex) { setDex(pkm); } byte[] data = pkm.EncryptedBoxData; setData(data, offset); BitConverter.GetBytes((ushort)pkm.TID).CopyTo(Data, offset + data.Length + 0); BitConverter.GetBytes((ushort)pkm.SID).CopyTo(Data, offset + data.Length + 2); Edited = true; }
public static string GetIncompatibleGBMessage(PKM pk, bool destJP) { var src = destJP ? MsgPKMConvertInternational : MsgPKMConvertJapanese; var dest = !destJP ? MsgPKMConvertInternational : MsgPKMConvertJapanese; return(string.Format(MsgPKMConvertIncompatible, src, pk.GetType().Name, dest)); }
internal static bool GetIncorrectRibbonsEgg(PKM pkm, object encounterContent) { var event3 = encounterContent as IRibbonSetEvent3; var event4 = encounterContent as IRibbonSetEvent4; var RibbonNames = ReflectUtil.GetPropertiesStartWithPrefix(pkm.GetType(), "Ribbon"); if (event3 != null) { RibbonNames = RibbonNames.Except(event3.RibbonNames()); } if (event4 != null) { RibbonNames = RibbonNames.Except(event4.RibbonNames()); } foreach (object RibbonValue in RibbonNames.Select(RibbonName => ReflectUtil.GetValue(pkm, RibbonName))) { if (HasFlag(RibbonValue) || HasCount(RibbonValue)) { return(true); } bool HasFlag(object o) => o is bool z && z; bool HasCount(object o) => o is int z && z > 0; } return(false); }
/// <summary> /// Tries to modify the <see cref="PKMInfo"/>. /// </summary> /// <param name="pk">Command Filter</param> /// <param name="filters">Filters which must be satisfied prior to any modifications being made.</param> /// <param name="modifications">Modifications to perform on the <see cref="pk"/>.</param> /// <returns>Result of the attempted modification.</returns> internal static ModifyResult TryModifyPKM(PKM pk, IEnumerable <StringInstruction> filters, IEnumerable <StringInstruction> modifications) { if (!pk.ChecksumValid || pk.Species == 0) { return(ModifyResult.Invalid); } PKMInfo info = new PKMInfo(pk); var pi = Props[Array.IndexOf(Types, pk.GetType())]; foreach (var cmd in filters) { try { if (!IsFilterMatch(cmd, info, pi)) { return(ModifyResult.Filtered); } } #pragma warning disable CA1031 // Do not catch general exception types // Swallow any error because this can be malformed user input. catch (Exception ex) #pragma warning restore CA1031 // Do not catch general exception types { Debug.WriteLine(MsgBEModifyFailCompare + " " + ex.Message, cmd.PropertyName, cmd.PropertyValue); return(ModifyResult.Error); } } ModifyResult result = ModifyResult.Modified; foreach (var cmd in modifications) { try { var tmp = SetPKMProperty(cmd, info, pi); if (tmp != ModifyResult.Modified) { result = tmp; } } #pragma warning disable CA1031 // Do not catch general exception types // Swallow any error because this can be malformed user input. catch (Exception ex) #pragma warning restore CA1031 // Do not catch general exception types { Debug.WriteLine(MsgBEModifyFail + " " + ex.Message, cmd.PropertyName, cmd.PropertyValue); } } return(result); }
/// <summary> /// Checks a <see cref="PKM"/> file for compatibility to the <see cref="SaveFile"/>. /// </summary> /// <param name="sav"><see cref="SaveFile"/> that is being checked.</param> /// <param name="pk"><see cref="PKM"/> that is being tested for compatibility.</param> public static bool IsCompatiblePKM(this SaveFile sav, PKM pk) { if (sav.PKMType != pk.GetType()) { return(false); } if (sav is ILangDeviantSave il && PKMConverter.IsIncompatibleGB(pk, il.Japanese, pk.Japanese)) { return(false); } return(true); }
/// <summary> /// Applies all shared properties from <see cref="Source"/> to <see cref="Destination"/>. /// </summary> /// <param name="Source"><see cref="PKM"/> that supplies property values.</param> /// <param name="Destination"><see cref="PKM"/> that receives property values.</param> protected void TransferPropertiesWithReflection(PKM Source, PKM Destination) { var SourceProperties = ReflectUtil.getPropertiesCanWritePublic(Source.GetType()); var DestinationProperties = ReflectUtil.getPropertiesCanWritePublic(Destination.GetType()); // Skip Data property when applying all individual properties. Let the setters do the updates for Data. foreach (string property in SourceProperties.Intersect(DestinationProperties).Where(prop => prop != nameof(Data))) { var prop = ReflectUtil.GetValue(this, property); if (prop != null) { ReflectUtil.SetValue(Destination, property, prop); } } }
protected void TransferPropertiesWithReflection(PKM Source, PKM Destination) { var SourceProperties = ReflectUtil.getPropertiesCanWritePublic(Source.GetType()); var DestinationProperties = ReflectUtil.getPropertiesCanWritePublic(Destination.GetType()); foreach (string property in SourceProperties.Intersect(DestinationProperties).Where(prop => prop != nameof(Data))) { var prop = ReflectUtil.GetValue(this, property); if (prop == null) { continue; } ReflectUtil.SetValue(Destination, property, prop); } }
private static bool GetIncorrectRibbonsEgg(PKM pkm, object encounterContent) { var RibbonNames = ReflectUtil.GetPropertiesStartWithPrefix(pkm.GetType(), "Ribbon"); if (encounterContent is IRibbonSetEvent3 event3) { RibbonNames = RibbonNames.Except(event3.RibbonNames()); } if (encounterContent is IRibbonSetEvent4 event4) { RibbonNames = RibbonNames.Except(event4.RibbonNames()); } foreach (object RibbonValue in RibbonNames.Select(RibbonName => ReflectUtil.GetValue(pkm, RibbonName))) { if (HasFlag(RibbonValue) || HasCount(RibbonValue)) { return(true); }
/// <summary> /// Tries to modify the <see cref="PKMInfo"/>. /// </summary> /// <param name="pkm">Command Filter</param> /// <param name="filters">Filters which must be satisfied prior to any modifications being made.</param> /// <param name="modifications">Modifications to perform on the <see cref="pkm"/>.</param> /// <returns>Result of the attempted modification.</returns> internal static ModifyResult TryModifyPKM(PKM pkm, IEnumerable <StringInstruction> filters, IEnumerable <StringInstruction> modifications) { if (!pkm.ChecksumValid || pkm.Species == 0) { return(ModifyResult.Invalid); } PKMInfo info = new PKMInfo(pkm); var pi = Props[Array.IndexOf(Types, pkm.GetType())]; foreach (var cmd in filters) { try { if (!IsFilterMatch(cmd, info, pi)) { return(ModifyResult.Filtered); } } catch (Exception ex) { Debug.WriteLine(MsgBEModifyFailCompare + " " + ex.Message, cmd.PropertyName, cmd.PropertyValue); return(ModifyResult.Error); } } ModifyResult result = ModifyResult.Modified; foreach (var cmd in modifications) { try { var tmp = SetPKMProperty(cmd, info, pi); if (result != ModifyResult.Modified) { result = tmp; } } catch (Exception ex) { Debug.WriteLine(MsgBEModifyFail + " " + ex.Message, cmd.PropertyName, cmd.PropertyValue); } } return(result); }
public static List <PKM> GetLivingDex(ITrainerInfo tr, IEnumerable <int> speciesToGenerate, PKM blank) { var result = new List <PKM>(); var destType = blank.GetType(); foreach (var s in speciesToGenerate) { var pk = blank.Clone(); pk.Species = s; pk.Gender = pk.GetSaneGender(); var pi = pk.PersonalInfo; for (int i = 0; i < pi.FormeCount; i++) { pk.AltForm = i; if (s == (int)Species.Indeedee || s == (int)Species.Meowstic) { pk.Gender = i; } var f = EncounterMovesetGenerator.GeneratePKMs(pk, tr).FirstOrDefault(); if (f == null) { continue; } var converted = PKMConverter.ConvertToType(f, destType, out _); if (converted == null) { continue; } converted.CurrentLevel = 100; converted.Species = s; converted.AltForm = i; result.Add(converted); } } return(result); }
public static IReadOnlyList <RibbonInfo> GetRibbonInfo(PKM pkm) { // Get a list of all Ribbon Attributes in the PKM var riblist = new List <RibbonInfo>(); var names = ReflectUtil.GetPropertiesStartWithPrefix(pkm.GetType(), "Ribbon"); foreach (var name in names) { object RibbonValue = ReflectUtil.GetValue(pkm, name); if (RibbonValue is int x) { riblist.Add(new RibbonInfo(name, x)); } if (RibbonValue is bool b) { riblist.Add(new RibbonInfo(name, b)); } } return(riblist); }
/// <summary> /// Checks if the input <see cref="PKM"/> is compatible with the target <see cref="PKM"/>. /// </summary> /// <param name="pk">Input to check -> update/sanitize</param> /// <param name="target">Target type PKM with misc properties accessible for checking.</param> /// <param name="c">Comment output</param> /// <param name="pkm">Output compatible PKM</param> /// <returns>Indication if the input is (now) compatible with the target.</returns> public static bool TryMakePKMCompatible(PKM pk, PKM target, out string c, out PKM pkm) { if (!IsConvertibleToFormat(pk, target.Format)) { pkm = null; c = string.Format(MsgPKMConvertFailBackwards, pk.GetType().Name, target.Format); if (!AllowIncompatibleConversion) { return(false); } } if (IsIncompatibleGB(target.Format, target.Japanese, pk.Japanese)) { pkm = null; c = GetIncompatibleGBMessage(pk, target.Japanese); return(false); } pkm = ConvertToType(pk, target.GetType(), out c); Debug.WriteLine(c); return(pkm != null); }
private static PKM ConvertPKM(PKM pk, Type PKMType, int toFormat, ref string comment) { PKM pkm = pk.Clone(); if (pkm.IsEgg) { pkm.ForceHatchPKM(); } while (true) { pkm = IntermediaryConvert(pkm, PKMType, toFormat, ref comment); if (pkm == null) // fail convert { return(null); } if (pkm.GetType() == PKMType) // finish convert { return(pkm); } } }
public virtual void setStoredSlot(PKM pkm, int offset, bool?trade = null, bool?dex = null) { if (pkm == null) { return; } if (pkm.GetType() != PKMType) { throw new InvalidCastException($"PKM Format needs to be {PKMType} when setting to a {GetType().Name.Last()} Save File."); } if (trade ?? SetUpdatePKM) { setPKM(pkm); } if (dex ?? SetUpdateDex) { setDex(pkm); } setData(pkm.EncryptedBoxData, offset); Edited = true; }
private static bool GetIncorrectRibbonsEgg(PKM pkm, IEncounterTemplate enc) { var names = ReflectUtil.GetPropertiesStartWithPrefix(pkm.GetType(), RibbonInfo.PropertyPrefix); if (enc is IRibbonSetEvent3 event3) { names = names.Except(event3.RibbonNames()); } if (enc is IRibbonSetEvent4 event4) { names = names.Except(event4.RibbonNames()); } foreach (var value in names.Select(name => ReflectUtil.GetValue(pkm, name))) { if (value is null) { continue; } if (HasFlag(value) || HasCount(value)) { return(true); }
public void setPartySlot(PKM pkm, int offset, bool? trade = null, bool? dex = null) { if (pkm == null) return; if (pkm.GetType() != PKMType) throw new InvalidCastException($"PKM Format needs to be {PKMType} when setting to a Gen{Generation} Save File."); if (trade ?? SetUpdatePKM) setPKM(pkm); if (dex ?? SetUpdateDex) setDex(pkm); for (int i = 0; i < 6; i++) if (getPartyOffset(i) == offset) if (PartyCount <= i) PartyCount = i + 1; setData(pkm.EncryptedPartyData, offset); Edited = true; }
private static ModifyResult ProcessPKM(PKM PKM, IEnumerable<StringInstruction> Filters, IEnumerable<StringInstruction> Instructions) { if (!PKM.ChecksumValid || PKM.Species == 0) return ModifyResult.Invalid; Type pkm = PKM.GetType(); foreach (var cmd in Filters) { try { if (!pkm.HasProperty(cmd.PropertyName)) return ModifyResult.Filtered; if (ReflectUtil.GetValueEquals(PKM, cmd.PropertyName, cmd.PropertyValue) != cmd.Evaluator) return ModifyResult.Filtered; } catch { Console.WriteLine($"Unable to compare {cmd.PropertyName} to {cmd.PropertyValue}."); return ModifyResult.Filtered; } } ModifyResult result = ModifyResult.Error; foreach (var cmd in Instructions) { try { if (cmd.PropertyName == nameof(PKM.MetDate)) PKM.MetDate = DateTime.ParseExact(cmd.PropertyValue, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None); else if (cmd.PropertyName == nameof(PKM.EggMetDate)) PKM.EggMetDate = DateTime.ParseExact(cmd.PropertyValue, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None); else if (cmd.PropertyName == nameof(PKM.EncryptionConstant) && cmd.PropertyValue == CONST_RAND) ReflectUtil.SetValue(PKM, cmd.PropertyName, Util.rnd32().ToString()); else if(cmd.PropertyName == nameof(PKM.PID) && cmd.PropertyValue == CONST_RAND) PKM.setPIDGender(PKM.Gender); else if (cmd.PropertyName == nameof(PKM.EncryptionConstant) && cmd.PropertyValue == nameof(PKM.PID)) PKM.EncryptionConstant = PKM.PID; else if (cmd.PropertyName == nameof(PKM.PID) && cmd.PropertyValue == CONST_SHINY) PKM.setShinyPID(); else if (cmd.PropertyName == nameof(PKM.Species) && cmd.PropertyValue == "0") PKM.Data = new byte[PKM.Data.Length]; else if (cmd.PropertyName.StartsWith("IV") && cmd.PropertyValue == CONST_RAND) setRandomIVs(PKM, cmd); else if (cmd.Random) ReflectUtil.SetValue(PKM, cmd.PropertyName, cmd.RandomValue); else ReflectUtil.SetValue(PKM, cmd.PropertyName, cmd.PropertyValue); result = ModifyResult.Modified; } catch { Console.WriteLine($"Unable to set {cmd.PropertyName} to {cmd.PropertyValue}."); } } return result; }
public override void setStoredSlot(PKM pkm, int offset, bool? trade = null, bool? dex = null) { if (pkm == null) return; if (pkm.GetType() != PKMType) throw new InvalidCastException($"PKM Format needs to be {PKMType} when setting to a Gen{Generation} Save File."); if (trade ?? SetUpdatePKM) setPKM(pkm); if (dex ?? SetUpdateDex) setDex(pkm); byte[] data = pkm.EncryptedBoxData; setData(data, offset); BitConverter.GetBytes((ushort)pkm.TID).CopyTo(Data, offset + data.Length + 0); BitConverter.GetBytes((ushort)pkm.SID).CopyTo(Data, offset + data.Length + 2); Edited = true; }
/// <summary> /// Tries to fetch the <see cref="PKM"/> property from the cache of available properties. /// </summary> /// <param name="pk">Pokémon to check</param> /// <param name="name">Property Name to check</param> /// <param name="pi">Property Info retrieved (if any).</param> /// <returns>True if has property, false if does not.</returns> public static bool TryGetHasProperty(PKM pk, string name, [NotNullWhen(true)] out PropertyInfo?pi) { var type = pk.GetType(); return(TryGetHasProperty(type, name, out pi)); }
/// <summary> /// Tries to fetch the <see cref="PKM"/> property from the cache of available properties. /// </summary> /// <param name="pkm">Pokémon to check</param> /// <param name="name">Property Name to check</param> /// <param name="pi">Property Info retrieved (if any).</param> /// <returns>True if has property, false if does not.</returns> public static bool TryGetHasProperty(PKM pkm, string name, out PropertyInfo pi) { var props = Props[Array.IndexOf(Types, pkm.GetType())]; return(props.TryGetValue(name, out pi)); }
public static PKM ConvertToType(PKM pk, Type PKMType, out string comment) { if (pk == null || pk.Species == 0) { comment = "Null 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)) { 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}." : $"Converted from {fromType.Name} to {PKMType.Name}."; return(pkm); }
public static PKM convertToFormat(PKM pk, Type PKMType, out string comment) { if (pk == null || pk.Species == 0) { comment = "Null input. Aborting."; return null; } Type fromType = pk.GetType(); int fromFormat = int.Parse(fromType.Name.Last().ToString()); int toFormat = int.Parse(PKMType.Name.Last().ToString()); Console.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 } switch (fromType.Name) { case nameof(PK1): if (toFormat == 2) { pkm = PKMType == typeof (PK2) ? ((PK1) pk).convertToPK2() : null; break; } if (toFormat == 7) pkm = null; // pkm.convertPK1toPK7(); 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(); } 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)) { pkm = ((PK4)pkm).convertToBK4(); break; } 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): pkm = new PK7(pkm.Data, pkm.Identifier); if (toFormat == 7) break; goto case nameof(PK7); case nameof(PK7): break; } } comment = pkm == null ? $"Cannot convert a {fromType.Name} to a {PKMType.Name}." : $"Converted from {fromType.Name} to {PKMType.Name}."; return pkm; }
/// <summary> /// Checks if the object is filtered by the provided <see cref="filters"/>. /// </summary> /// <param name="filters">Filters which must be satisfied.</param> /// <param name="pkm">Object to check.</param> /// <returns>True if <see cref="pkm"/> matches all filters.</returns> public static bool IsFilterMatch(IEnumerable <StringInstruction> filters, PKM pkm) => filters.All(z => IsFilterMatch(z, pkm, Props[Array.IndexOf(Types, pkm.GetType())]));
/// <summary> /// Converts a PKM from one Generation 3 format to another. If it matches the destination format, the conversion will automatically return. /// </summary> /// <param name="pk">PKM to convert</param> /// <param name="PKMType">Format/Type to convert to</param> /// <param name="comment">Comments regarding the transfer's success/failure</param> /// <returns>Converted PKM</returns> public static PKM ConvertToType(PKM pk, Type PKMType, out string comment) { if (pk == null) { comment = $"Bad {nameof(pk)} input. Aborting."; return(null); } Type fromType = pk.GetType(); if (fromType == PKMType) { comment = "No need to convert, current format matches requested format."; return(pk); } if (IsNotTransferrable(pk, out comment)) { return(null); } 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) { comment = $"Cannot convert a {PKX.GetSpeciesName(pkm.Species, pkm.Japanese ? 1 : 2)} to {PKMType.Name}"; return(null); } 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; } 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}." : $"Converted from {fromType.Name} to {PKMType.Name}."; return(pkm); }
public static PKM convertToFormat(PKM pk, Type PKMType, out string comment) { bool timeMachine = true; if (pk == null || pk.Species == 0) { comment = "Null input. Aborting."; return(null); } Type fromType = pk.GetType(); int fromFormat = int.Parse(fromType.Name.Last().ToString()); int toFormat = int.Parse(PKMType.Name.Last().ToString()); Console.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) { 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 } } switch (fromType.Name) { case nameof(PK1): pkm = PKMType == typeof(PK2) ? ((PK1)pk).convertToPK2() : null; if (toFormat == 2) { break; } pkm = ((PK2)pk).convertToPK3(); if (toFormat == 3) { break; } pkm = ((PK3)pkm).convertToPK4(); if (toFormat == 4) { if (PKMType == typeof(BK4)) { pkm = ((PK4)pkm).convertToBK4(); } break; } pkm = ((PK4)pkm).convertToPK5(); if (toFormat == 5) { break; } pkm = ((PK5)pkm).convertToPK6(); if (toFormat == 6) { break; } pkm = new PK7(pkm.Data, pkm.Identifier); break; //if (toFormat == 7) // pkm = null; // pkm.convertPK1toPK7(); //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(); //} //else if (PKMType == typeof(PK3)) //{ // pkm = ((PK2)pk).convertToPK3(); //} //else // pkm = null; pkm = ((PK2)pk).convertToPK3(); if (toFormat == 3) { break; } pkm = ((PK3)pkm).convertToPK4(); if (toFormat == 4) { if (PKMType == typeof(BK4)) { pkm = ((PK4)pkm).convertToBK4(); } break; } pkm = ((PK4)pkm).convertToPK5(); if (toFormat == 5) { break; } pkm = ((PK5)pkm).convertToPK6(); if (toFormat == 6) { break; } pkm = new PK7(pkm.Data, pkm.Identifier); 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 == 2) { pkm = ((PK3)pkm).convertToPK2(); break; } 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)) { pkm = ((PK4)pkm).convertToBK4(); break; } 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): pkm = ((PK6)pkm).convertToPK7(); if (toFormat == 7) { break; } goto case nameof(PK7); case nameof(PK7): break; } } else // fromFormat > toFormat - we're going backwards, normally unsupported - obviously not perfect, but its cool i guess { 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 } } switch (fromType.Name) { case "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(); } else { pkm = null; } break; case "PK7": if ( (toFormat == 6 && pk.Species > 721) || (toFormat == 5 && pk.Species > 649) || (toFormat == 4 && pk.Species > 493) || (toFormat == 3 && pk.Species > 386) || (toFormat == 2 && pk.Species > 251) || (toFormat == 1 && pk.Species > 151) ) { pkm = null; break; } // how awkward im the worst pkm = new PK6(pkm.Data, pkm.Identifier); if (toFormat == 6) { break; } pkm = ((PK6)pkm).convertToPK5(); if (toFormat == 5) { break; } pkm = ((PK5)pkm).convertToPK4(); if (toFormat == 4) { break; } pkm = ((PK4)pkm).convertToPK3(); if (toFormat == 3) { break; } pkm = ((PK3)pkm).convertToPK2(); if (toFormat == 2) { break; } pkm = ((PK2)pkm).convertToPK1(); break; case "PK6": if ( (toFormat == 5 && pk.Species > 649) || (toFormat == 4 && pk.Species > 493) || (toFormat == 3 && pk.Species > 386) || (toFormat == 2 && pk.Species > 251) || (toFormat == 1 && pk.Species > 151) ) { pkm = null; break; } // how awkward im the worst pkm = ((PK6)pkm).convertToPK5(); if (toFormat == 5) { break; } pkm = ((PK5)pkm).convertToPK4(); if (toFormat == 4) { break; } pkm = ((PK4)pkm).convertToPK3(); if (toFormat == 3) { break; } pkm = ((PK3)pkm).convertToPK2(); if (toFormat == 2) { break; } pkm = ((PK2)pkm).convertToPK1(); break; case "PK5": if ( (toFormat == 4 && pk.Species > 493) || (toFormat == 3 && pk.Species > 386) || (toFormat == 2 && pk.Species > 251) || (toFormat == 1 && pk.Species > 151) ) { pkm = null; break; } // how awkward im the worst pkm = ((PK5)pkm).convertToPK4(); if (toFormat == 4) { break; } pkm = ((PK4)pkm).convertToPK3(); if (toFormat == 3) { break; } pkm = ((PK3)pkm).convertToPK2(); if (toFormat == 2) { break; } pkm = ((PK2)pkm).convertToPK1(); break; case "PK4": if ( (toFormat == 3 && pk.Species > 386) || (toFormat == 2 && pk.Species > 251) || (toFormat == 1 && pk.Species > 151) ) { pkm = null; break; } // how awkward im the worst pkm = ((PK4)pkm).convertToPK3(); if (toFormat == 3) { break; } pkm = ((PK3)pkm).convertToPK2(); if (toFormat == 2) { break; } pkm = ((PK2)pkm).convertToPK1(); break; case "CK3": case "XK3": // interconverting C/XD needs to visit main series format // ends up stripping purification/shadow etc stats pkm = pkm.convertToPK3(); goto case "PK3"; // fall through case "PK3": if ( (toFormat == 2 && pk.Species > 251) || (toFormat == 1 && pk.Species > 151) ) { pkm = null; break; } // how awkward im the worst pkm = ((PK3)pkm).convertToPK2(); if (toFormat == 2) { break; } pkm = ((PK2)pkm).convertToPK1(); break; } } comment = pkm == null ? $"Cannot convert a {fromType.Name} to a {PKMType.Name}." : $"Converted from {fromType.Name} to {PKMType.Name}."; return(pkm); }
/// <summary> /// Applies all shared properties from <see cref="Source"/> to <see cref="Destination"/>. /// </summary> /// <param name="Source"><see cref="PKM"/> that supplies property values.</param> /// <param name="Destination"><see cref="PKM"/> that receives property values.</param> protected void TransferPropertiesWithReflection(PKM Source, PKM Destination) { // Only transfer declared properties not defined in PKM.cs but in the actual type var SourceProperties = ReflectUtil.getPropertiesCanWritePublicDeclared(Source.GetType()); var DestinationProperties = ReflectUtil.getPropertiesCanWritePublicDeclared(Destination.GetType()); foreach (string property in SourceProperties.Intersect(DestinationProperties)) { var prop = ReflectUtil.GetValue(this, property); if (prop != null) { ReflectUtil.SetValue(Destination, property, prop); } } }
public virtual void setStoredSlot(PKM pkm, int offset, bool? trade = null, bool? dex = null) { if (pkm == null) return; if (pkm.GetType() != PKMType) throw new InvalidCastException($"PKM Format needs to be {PKMType} when setting to a {GetType().Name.Last()} Save File."); if (trade ?? SetUpdatePKM) setPKM(pkm); if (dex ?? SetUpdateDex) setDex(pkm); setData(pkm.EncryptedBoxData, offset); Edited = true; }
protected void TransferPropertiesWithReflection(PKM Source, PKM Destination) { var SourceProperties = ReflectUtil.getPropertiesCanWritePublic(Source.GetType()); var DestinationProperties = ReflectUtil.getPropertiesCanWritePublic(Destination.GetType()); foreach (string property in SourceProperties.Intersect(DestinationProperties).Where(prop => prop != nameof(Data))) { var prop = ReflectUtil.GetValue(this, property); if (prop == null) continue; ReflectUtil.SetValue(Destination, property, prop); } }