private void button1_Click(object sender, EventArgs e) { IPAddress PKSMAddress; if (!IPAddress.TryParse(textBox1.Text, out PKSMAddress)) { DisplayUsage(); return; } Console.Text += ("Loading mgdb in memory..."); Legal.RefreshMGDB(MGDatabasePath); byte[] inputBuffer = new byte[HEADER.Length + GAME_LEN + PKSIZE]; byte[] outputBuffer = new byte[HEADER.Length + GAME_LEN + PKSIZE]; IPAddress serverAddress = IPAddress.Parse(GetLocalIPAddress()); if (textBox2.Text != "") { if (!IPAddress.TryParse(textBox2.Text, out serverAddress)) { return; } } TcpListener listener = new TcpListener(serverAddress, 9000); Console.Text += Environment.NewLine + "Waiting for a connection from PKSM (running on address " + PKSMAddress + ")...\n"; button1.Text = "Server Running..."; new Thread(() => { while (true) { try { listener.Start(); Socket inputSocket = listener.AcceptSocket(); inputSocket.Receive(inputBuffer); inputSocket.Close(); listener.Stop(); ClearTextBox(); PrintLegality(inputBuffer, verbose); PKM pk = GetPKMFromPayload(inputBuffer); ServeLegality.AutoLegality al = new ServeLegality.AutoLegality(); PKM legal = al.LoadShowdownSetModded_PKSM(pk); LegalityAnalysis la = new LegalityAnalysis(legal); AppendTextBox(Environment.NewLine + Environment.NewLine + "AutoLegality final report:" + Environment.NewLine + Environment.NewLine + la.Report(verbose) + Environment.NewLine); Array.Copy(Encoding.ASCII.GetBytes(HEADER), 0, outputBuffer, 0, HEADER.Length); Array.Copy(legal.Data, 0, outputBuffer, 7, PKSIZE); TcpClient client = new TcpClient(); client.Connect(PKSMAddress, 9000); Stream stream = client.GetStream(); stream.Write(outputBuffer, 0, outputBuffer.Length); client.Close(); } catch (Exception ex) { System.Console.WriteLine("Error" + ex.StackTrace); } } }).Start(); }
/// <summary> /// Creates a report message with optional verbosity for in-depth analysis. /// </summary> /// <param name="la">Legality result to format</param> /// <param name="verbose">Include all details in the parse, including valid check messages.</param> /// <returns>Single line string</returns> public static string Report(this LegalityAnalysis la, bool verbose = false) => verbose?GetVerboseLegalityReport(la) : GetLegalityReport(la);
public Pokemon CreatePKMN() { try { var country = "N/A"; var region = "N/A"; var dsregion = "N/A"; if (CountryID != "N/A" && CountryID != "0") { System.Tuple <string, string> cr = GeoLocation.GetCountryRegionText(int.Parse(CountryID), int.Parse(RegionID), "en"); country = cr.Item1; region = cr.Item2; } switch (DSRegionID) { case "N/A": dsregion = "None"; break; case "0": dsregion = "Japan"; break; case "1": dsregion = "North America"; break; case "2": dsregion = "Europe"; break; case "3": dsregion = "China"; break; case "4": dsregion = "Korea"; break; case "5": dsregion = "Taiwan"; break; } var lc = new LegalityAnalysis(pkm); var pkmn = new Pokemon { ATK = ATK, ATK_EV = ATK_EV, ATK_IV = ATK_IV, Ability = Ability, AbilityNum = AbilityNum, AltForms = AltForms, Ball = Ball, Beauty = Beauty, Cool = Cool, Country = country, CountryID = CountryID, Cute = Cute, DEF = DEF, DEF_EV = DEF_EV, DEF_IV = DEF_IV, DSRegion = dsregion, DSRegionID = DSRegionID, EC = EC, ESV = ESV, EXP = EXP, EggLoc = EggLoc, Egg_Day = Egg_Day, Egg_Month = Egg_Month, Egg_Year = Egg_Year, Encounter = Encounter, FatefulFlag = FatefulFlag, Friendship = Friendship, Gender = Gender, GenderFlag = GenderFlag, Size = pkm.SIZE_STORED, HP = HP, HP_EV = HP_EV, HP_IV = HP_IV, HP_Type = HP_Type, HT = pkm.HT_Name, HeldItem = HeldItem, IsEgg = IsEgg, IsNicknamed = IsNicknamed, IsShiny = IsShiny, Legal = Legal, Level = Level, Markings = Markings, MetLevel = MetLevel, MetLoc = MetLoc, Met_Day = Met_Day, Met_Month = Met_Month, Met_Year = Met_Year, Move1 = Move1, Move1_PP = Move1_PP, Move1_PPUp = Move1_PPUp, Move2 = Move2, Move2_PP = Move2_PP, Move2_PPUp = Move2_PPUp, Move3 = Move3, Move3_PP = Move3_PP, Move3_PPUp = Move3_PPUp, Move4 = Move4, Move4_PP = Move4_PP, Move4_PPUp = Move4_PPUp, Nature = Nature, Nickname = Nickname, NotOT = NotOT, OT = OT, OTLang = OTLang, OT_Affection = OT_Affection, OT_Gender = OT_Gender, PID = PID, PKRS_Days = PKRS_Days, PKRS_Strain = PKRS_Strain, Position = Position ?? "", Region = region, RegionID = RegionID, Relearn1 = Relearn1, Relearn2 = Relearn2, Relearn3 = Relearn3, Relearn4 = Relearn4, SID = SID, SPA = SPA, SPA_EV = SPA_EV, SPA_IV = SPA_IV, SPD = SPD, SPD_EV = SPD_EV, SPD_IV = SPD_IV, SPE = SPE, SPE_EV = SPE_EV, SPE_IV = SPE_IV, Sheen = Sheen, Smart = Smart, Species = Species, SpecForm = pkm.SpecForm, TID = TID, TSV = TSV, Tough = Tough, Version = Version, IllegalReasons = lc.Report(), Checksum = Checksum, ItemNum = pkm.HeldItem }; if (pkm.HT_Name == "") { pkmn.HT = OT; } var ds = FormConverter.GetFormList(pkm.Species, GameInfo.Strings.types, GameInfo.Strings.forms, GameInfo.GenderSymbolUnicode, pkm.Format); if (ds.Count() > 1) { pkmn.Form = ds[pkmn.AltForms]; } else { pkmn.Form = ds[0]; } pkmn.HeldItemSpriteURL = ""; pkmn.Move1_Type = ConsoleIndex.mt[pkm.Move1].Type; pkmn.Move2_Type = ConsoleIndex.mt[pkm.Move2].Type; pkmn.Move3_Type = ConsoleIndex.mt[pkm.Move3].Type; pkmn.Move4_Type = ConsoleIndex.mt[pkm.Move4].Type; if (pkm.GetType() == typeof(PK4)) { pkmn.Generation = "4"; } else if (pkm.GetType() == typeof(PK5)) { pkmn.Generation = "5"; } else if (pkm.GetType() == typeof(PK6)) { pkmn.Generation = "6"; } else if (pkm.GetType() == typeof(PK7)) { pkmn.Generation = "7"; } else if (pkm.GetType() == typeof(PB7)) { pkmn.Generation = "LGPE"; } else if (pkm.GetType() == typeof(PK8)) { pkmn.Generation = "8"; } else if (pkm.GetType() == typeof(PK3)) { pkmn.Generation = "3"; } else if (pkm.GetType() == typeof(PK2)) { pkmn.Generation = "2"; } else if (pkm.GetType() == typeof(PK1)) { pkmn.Generation = "1"; } pkmn.SpeciesSpriteURL = GetPokeSprite(pkm.Species, pkmn.Species, pkmn.Gender, pkmn.Version, pkmn.Form, pkmn.Generation, pkmn.IsShiny); return(pkmn); } catch (Exception ex) { Console.WriteLine(ex.ToString()); return(null); } }
public override void Verify(LegalityAnalysis data) { var pk = data.Entity; var enc = data.EncounterOriginal; if (enc is MysteryGift gift) { if (gift.Level != pk.Met_Level && pk.HasOriginalMetLocation) { switch (gift) { case WC3 wc3 when wc3.Met_Level == pk.Met_Level || wc3.IsEgg: break; case WC7 wc7 when wc7.MetLevel == pk.Met_Level: break; case PGT { IsManaphyEgg: true } when pk.Met_Level == 0 : break; default: data.AddLine(GetInvalid(LLevelMetGift)); return; } } if (gift.Level > pk.CurrentLevel) { data.AddLine(GetInvalid(LLevelMetGiftFail)); return; } } if (pk.IsEgg) { int elvl = enc.LevelMin; if (elvl != pk.CurrentLevel) { data.AddLine(GetInvalid(string.Format(LEggFMetLevel_0, elvl))); return; } var reqEXP = enc is EncounterStatic2Odd ? 125 // Gen2 Dizzy Punch gifts always have 125 EXP, even if it's more than the Lv5 exp required. : Experience.GetEXP(elvl, pk.PersonalInfo.EXPGrowth); if (reqEXP != pk.EXP) { data.AddLine(GetInvalid(LEggEXP)); } return; } int lvl = pk.CurrentLevel; if (lvl >= 100) { var expect = Experience.GetEXP(100, pk.PersonalInfo.EXPGrowth); if (pk.EXP != expect) { data.AddLine(GetInvalid(LLevelEXPTooHigh)); } } if (lvl < pk.Met_Level) { data.AddLine(GetInvalid(LLevelMetBelow)); } else if (!enc.IsWithinEncounterRange(pk) && lvl != 100 && pk.EXP == Experience.GetEXP(lvl, pk.PersonalInfo.EXPGrowth)) { data.AddLine(Get(LLevelEXPThreshold, Severity.Fishy)); } else { data.AddLine(GetValid(LLevelMetSane)); } }
/// <summary> /// Sets the contests stats as requested. /// </summary> /// <param name="pk">Pokémon to modify.</param> /// <param name="la">Legality Information matched to.</param> /// <param name="option">Option to apply with</param> public static ModifyResult SetContestStats(PKM pk, LegalityAnalysis la, string option) { if (option.Length != 0 && option[BatchEditing.CONST_SUGGEST.Length..] is not "0") { pk.SetMaxContestStats(la.EncounterMatch, la.Info.EvoChainsAllGens); }
public bool LoadFolder(string path) { Clear(); Files.Clear(); if (!Directory.Exists(path)) { return(false); } var loadedAny = false; var files = Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories); var matchFiles = LoadUtil.GetFilesOfSize(files, ExpectedSize); int surpriseBlocked = 0; foreach (var file in matchFiles) { var data = File.ReadAllBytes(file); var pkm = PKMConverter.GetPKMfromBytes(data); if (!(pkm is T dest)) { continue; } if (dest.Species == 0 || !(dest is PK8 pk8)) { LogUtil.LogInfo("SKIPPED: Provided pk8 is not valid: " + dest.FileName, nameof(PokemonPool <T>)); continue; } if (!dest.CanBeTraded()) { LogUtil.LogInfo("SKIPPED: Provided pk8 cannot be traded: " + dest.FileName, nameof(PokemonPool <T>)); continue; } var la = new LegalityAnalysis(pk8); if (!la.Valid && Settings.Legality.VerifyLegality) { var reason = la.Report(); LogUtil.LogInfo($"SKIPPED: Provided pk8 is not legal: {dest.FileName} -- {reason}", nameof(PokemonPool <T>)); continue; } if (DisallowSurpriseTrade(pk8)) { LogUtil.LogInfo("Provided pk8 was loaded but can't be Surprise Traded: " + dest.FileName, nameof(PokemonPool <T>)); surpriseBlocked++; } if (Settings.Legality.ResetHOMETracker) { pk8.Tracker = 0; } var fn = Path.GetFileNameWithoutExtension(file); fn = StringsUtil.Sanitize(fn); // Since file names can be sanitized to the same string, only add one of them. if (!Files.ContainsKey(fn)) { Add(dest); Files.Add(fn, new LedyRequest <T>(dest, fn)); } else { LogUtil.LogInfo("Provided pk8 was not added due to duplicate name: " + dest.FileName, nameof(PokemonPool <T>)); } loadedAny = true; } if (surpriseBlocked == Count) { LogUtil.LogInfo("Surprise trading will fail; failed to load any compatible files.", nameof(PokemonPool <T>)); } return(loadedAny); }
public override void Verify(LegalityAnalysis data) { VerifyMedalsRegular(data); VerifyMedalsEvent(data); }
private static string GetReport(PKM pk) { var la = new LegalityAnalysis(pk); return(la.Report()); }
private static void SetPIDSID(PKM pk, bool shiny, bool XD = false) { uint hp = (uint)pk.IV_HP; uint atk = (uint)pk.IV_ATK; uint def = (uint)pk.IV_DEF; uint spa = (uint)pk.IV_SPA; uint spd = (uint)pk.IV_SPD; uint spe = (uint)pk.IV_SPE; void LoadOldIVs() { pk.IV_HP = (int)hp; pk.IV_ATK = (int)atk; pk.IV_DEF = (int)def; pk.IV_SPA = (int)spa; pk.IV_SPD = (int)spd; pk.IV_SPE = (int)spe; } uint nature = (uint)pk.Nature; var type = XD ? RNGReporter.FrameType.ColoXD : RNGReporter.FrameType.Method1; var pidsid = IVtoPIDGenerator.Generate(hp, atk, def, spa, spd, spe, nature, 0, type); if (pk.Species == 490 && pk.Gen4) { pk.WasEgg = true; pk.Egg_Location = 2002; pk.FatefulEncounter = true; } pk.PID = Util.GetHexValue(pidsid[0]); if (pk.GenNumber < 5) { pk.EncryptionConstant = pk.PID; } pk.SID = Convert.ToInt32(pidsid[1]); if (shiny) { pk.SetShinySID(); } var recheckLA = new LegalityAnalysis(pk); string updatedReport = recheckLA.Report(); Debug.WriteLine(updatedReport); if (!updatedReport.Contains(LPIDTypeMismatch)) { return; } var NatureHPIVs = IVtoPIDGenerator.GetIVPID(nature, pk.HPType, XD); Debug.WriteLine(XD); pk.PID = Util.GetHexValue(NatureHPIVs[0]); if (pk.GenNumber < 5) { pk.EncryptionConstant = pk.PID; } SetIVs(pk, NatureHPIVs); if (shiny) { pk.SetShinySID(); } recheckLA = new LegalityAnalysis(pk); updatedReport = recheckLA.Report(); bool pidsidmethod = updatedReport.Contains(LPIDTypeMismatch); if (pidsid[0] == "0" && pidsid[1] == "0" && pidsidmethod) { pk.PID = PKX.GetRandomPID(pk.Species, pk.Gender, pk.Version, pk.Nature, pk.Format, (uint)(pk.AbilityNumber * 0x10001)); LoadOldIVs(); } if (shiny) { pk.SetShinySID(); } recheckLA = new LegalityAnalysis(pk); updatedReport = recheckLA.Report(); if (updatedReport.Contains(LPIDGenderMismatch)) { pk.Gender = pk.Gender == 0 ? 1 : 0; var recheckLA2 = new LegalityAnalysis(pk); updatedReport = recheckLA2.Report(); } if (updatedReport.Contains(LHyperBelow100)) { pk.CurrentLevel = 100; var recheckLA2 = new LegalityAnalysis(pk); updatedReport = recheckLA2.Report(); } var la = new LegalityAnalysis(pk); if (la.Valid) { return; } // Fix Moves if a slot is empty pk.FixMoves(); pk.RefreshAbility(pk.AbilityNumber < 6 ? pk.AbilityNumber >> 1 : 0); if (updatedReport.Contains(LPIDTypeMismatch) || UsesEventBasedMethod(pk.Species, pk.Moves, PIDType.Method_2)) { if (pk.GenNumber == 3 || UsesEventBasedMethod(pk.Species, pk.Moves, PIDType.Method_2)) { pk = M2EventFix(pk, shiny); if (!new LegalityAnalysis(pk).Report().Contains(LPIDTypeMismatch) || UsesEventBasedMethod(pk.Species, pk.Moves, PIDType.Method_2)) { return; } } LoadOldIVs(); } }
private static bool CommonErrorHandling2(PKM pk) { var report = GetReport(pk); // f*****g M2 if (GameVersion.FRLG.Contains(pk.Version) && UsesEventBasedMethod(pk.Species, pk.Moves, PIDType.Method_2)) { pk = M2EventFix(pk, pk.IsShiny); report = GetReport(pk); } if (UsesEventBasedMethod(pk.Species, pk.Moves, PIDType.BACD_R) && pk.Version == (int)GameVersion.R) { pk = BACD_REventFix(pk, pk.IsShiny); report = GetReport(pk); } if (report.Contains(LNickMatchLanguageFail)) { pk.Nickname = PKX.GetSpeciesNameGeneration(pk.Species, pk.Language, pk.Format); // failsafe to reset nick report = GetReport(pk); } if (report.Contains(LStatIncorrectCP)) { ((PB7)pk).ResetCP(); report = GetReport(pk); } if (report.Contains(LAbilityMismatch)) //V223 = Ability mismatch for encounter. { pk.RefreshAbility(pk.AbilityNumber < 6 ? pk.AbilityNumber >> 1 : 0); report = GetReport(pk); if (report.Contains(LAbilityMismatch)) //V223 = Ability mismatch for encounter. { AlternateAbilityRefresh(pk); } report = GetReport(pk); } if (report.Contains(LTransferEggLocationTransporter)) //V61 = Invalid Met Location, expected Transporter. { pk.Met_Location = 30001; report = GetReport(pk); } if (report.Contains(LBallEncMismatch)) //V118 = Can't have ball for encounter type. { if (pk.B2W2) { pk.Ball = 25; //Dream Ball report = GetReport(pk); } else { pk.Ball = 0; report = GetReport(pk); } } if (report.Contains(LEncUnreleasedEMewJP)) //V353 = Non japanese Mew from Faraway Island. Unreleased event. { bool shiny = pk.IsShiny; pk.Language = 1; pk.FatefulEncounter = true; pk.Nickname = PKX.GetSpeciesNameGeneration(pk.Species, pk.Language, 3); pk.PID = PKX.GetRandomPID(pk.Species, pk.Gender, pk.Version, pk.Nature, pk.Format, (uint)(pk.AbilityNumber * 0x10001)); if (shiny) { pk.SetShinySID(); } report = GetReport(pk); } if (report.Contains(LPIDEqualsEC)) //V208 = Encryption Constant matches PID. { pk.SetRandomEC(); report = GetReport(pk); } if (report.Contains(LTransferPIDECEquals)) //V216 = PID should be equal to EC! { pk.EncryptionConstant = pk.PID; report = GetReport(pk); } if (report.Contains(LTransferPIDECBitFlip)) //V215 = PID should be equal to EC [with top bit flipped]! { pk.PID = PKX.GetRandomPID(pk.Species, pk.Gender, pk.Version, pk.Nature, pk.Format, (uint)(pk.AbilityNumber * 0x10001)); if (pk.IsShiny) { pk.SetShiny(); } report = GetReport(pk); } if (report.Contains(LPIDGenderMismatch)) //V251 = PID-Gender mismatch. { pk.Gender = pk.Gender == 0 ? 1 : 0; report = GetReport(pk); } if (report.Contains(LG3OTGender) || report.Contains(LG1OTGender)) //V407 = OT from Colosseum/XD cannot be female. V408 = Female OT from Generation 1 / 2 is invalid. { pk.OT_Gender = 0; report = GetReport(pk); } if (report.Contains(LLevelMetBelow)) //V85 = Current level is below met level. { pk.CurrentLevel = 100; report = GetReport(pk); } if (report.Contains(string.Format(LRibbonFMissing_0, "National"))) //V600 = Missing Ribbons: {0} (National in this case) { if (pk is IRibbonSetEvent3 e3) { e3.RibbonNational = true; } report = GetReport(pk); } if (report.Contains(string.Format(LRibbonFInvalid_0, "National"))) //V601 = Invalid Ribbons: {0} (National in this case) { if (pk is IRibbonSetEvent3 e3) { e3.RibbonNational = false; } report = GetReport(pk); } if (report.Contains(LOTLong)) //V38 = OT Name too long. { pk.OT_Name = "ARCH"; report = GetReport(pk); } if (report.Contains(LG1CharOT)) //V421 = OT from Generation 1/2 uses unavailable characters. { pk.OT_Name = "ARCH"; report = GetReport(pk); } if (report.Contains(LGeoNoCountryHT)) { var g = (IGeoTrack)pk; g.Geo1_Country = 1; report = GetReport(pk); } if (report.Contains(LMemoryMissingHT)) //V150 = Memory: Handling Trainer Memory missing. { pk.HT_Memory = 3; pk.HT_TextVar = 9; pk.HT_Intensity = 1; pk.HT_Feeling = Util.Rand.Next(0, 10); // 0-9 pk.HT_Friendship = pk.OT_Friendship; report = GetReport(pk); } if (report.Contains(LMemoryMissingOT)) //V152 = Memory: Original Trainer Memory missing. { pk.OT_Memory = 3; pk.OT_TextVar = 9; pk.OT_Intensity = 1; pk.OT_Feeling = Util.Rand.Next(0, 10); // 0-9 report = GetReport(pk); } if (report.Contains(string.Format(LMemoryFeelInvalid, "OT")) || report.Contains(string.Format(LMemoryFeelInvalid, "HT"))) //V255 = {0} Memory: Invalid Feeling (0 = OT/HT) { pk.HT_Memory = 3; pk.HT_TextVar = 9; pk.HT_Intensity = 1; pk.HT_Feeling = Memories.GetRandomFeeling(pk.HT_Memory); pk.HT_Friendship = pk.OT_Friendship; pk.OT_Memory = 3; pk.OT_TextVar = 9; pk.OT_Intensity = 1; pk.OT_Feeling = Memories.GetRandomFeeling(pk.OT_Memory); report = GetReport(pk); } if (report.Contains(LMemoryIndexIDOT0)) //V130 = Can't have any OT Memory. { pk.ClearOTMemory(); report = GetReport(pk); } if (report.Contains(LGeoMemoryMissing)) //V137 = GeoLocation Memory: Memories should be present. { var g = (IGeoTrack)pk; g.Geo1_Country = 1; report = GetReport(pk); } if (report.Contains(LBallEncMismatch)) //V118 = Can't have ball for encounter type. { pk.Ball = 4; report = GetReport(pk); } if (report.Contains(LGeoHardwareInvalid)) //Geolocation: Country is not in 3DS region. { pk.Country = 0; pk.Region = 0; pk.ConsoleRegion = 2; report = GetReport(pk); } if (report.Contains(LFormBattle)) //V310 = Form cannot exist outside of a battle. { if (pk.Species == 718 && pk.Ability == 211) { pk.AltForm = 3; // Zygarde Edge case } else { pk.AltForm = 0; } report = GetReport(pk); } if (report.Contains(LFatefulMissing)) //V324 = Special ingame Fateful Encounter flag missing. { pk.FatefulEncounter = true; report = GetReport(pk); } if (report.Contains(LFatefulInvalid)) //V325 = Fateful Encounter should not be checked. { pk.FatefulEncounter = false; report = GetReport(pk); } if (report.Contains(LEncTypeMismatch)) //V381 = Encounter Type does not match encounter. { var match = new LegalityAnalysis(pk).Info.EncounterMatch; var type = GetRequiredEncounterType(pk, match); if (!type.Contains(pk.EncounterType)) { pk.EncounterType = Convert.ToInt32(Math.Log((int)type, 2)); } else { Debug.WriteLine("This should never happen"); } report = GetReport(pk); } if (report.Contains(LEvoInvalid)) //V86 = Evolution not valid (or level/trade evolution unsatisfied). { pk.Met_Level--; report = GetReport(pk); } if (report.Contains(LPIDTypeMismatch)) //V411 = Encounter Type PID mismatch. { SetPIDSID(pk, pk.IsShiny, pk.Version == (int)GameVersion.CXD); if (new LegalityAnalysis(pk).Valid) { return(false); } report = GetReport(pk); if (report.Equals(LPIDTypeMismatch)) // V411 = Encounter Type PID mismatch. { return(true); } if (report.Contains(LPIDGenderMismatch)) // V251 = PID-Gender mismatch. { pk.Gender = pk.Gender == 0 ? 1 : 0; report = GetReport(pk); if (new LegalityAnalysis(pk).Valid) { return(false); } } } if (report.Contains(LHyperPerfectAll)) // V41 = Can't Hyper Train a Pokémon with perfect IVs. { ((IHyperTrain)pk).HyperTrainClear(); report = GetReport(pk); } if (report.Contains(LHyperPerfectOne)) // V42 = Can't Hyper Train a perfect IV. { pk.ClearHyperTrainedPerfectIVs(); } return(false); }
private static bool BruteForceEgg(PKM pk, ShowdownSet set, ITrainerInfo trainer, bool shiny) { foreach (var game in BruteTables.GameVersionList) { if (pk.DebutGeneration > game.GetGeneration()) { continue; } pk.Version = (int)game; pk.RestoreIVs(set.IVs); // Restore IVs to template, and HT to false pk.Language = 2; pk.OT_Name = trainer.OT; pk.TID = trainer.TID; pk.SID = trainer.SID; pk.OT_Gender = trainer.Gender; pk.MetDate = DateTime.Today; pk.EggMetDate = DateTime.Today; pk.Egg_Location = pk.Version < (int)GameVersion.W ? 2002 : 60002; pk.Met_Level = 1; pk.ConsoleRegion = 2; if (pk.Version == (int)GameVersion.RD || pk.Version == (int)GameVersion.BU || pk.Version == (int)GameVersion.YW || pk.Version == (int)GameVersion.GN) { pk.SID = 0; pk.Met_Location = 30013; pk.Met_Level = 100; } if (pk.Version == (int)GameVersion.CXD) { pk.Met_Location = 30001; pk.Met_Level = 100; } else { pk.SetSuggestedMetLocation(); } if (pk.GenNumber > 4) { pk.Met_Level = 1; } pk.SetMarkings(); pk.CurrentHandler = 1; pk.HT_Name = "Archit"; pk.SetSuggestedRelearnMoves(); pk.SetPIDNature(pk.Nature); if (shiny) { pk.SetShiny(); } if (pk.PID == 0) { pk.PID = PKX.GetRandomPID(pk.Species, pk.Gender, pk.Version, pk.Nature, pk.Format, (uint)(pk.AbilityNumber * 0x10001)); if (shiny) { pk.SetShiny(); } } pk.SetSuggestedMemories(); if (pk.GenNumber < 6) { pk.EncryptionConstant = pk.PID; } if (CommonErrorHandling2(pk)) { pk.HyperTrain(); if (shiny && !pk.IsShiny) { pk.SetShiny(); } { return(true); } } pk.HyperTrain(); bool legalized = new LegalityAnalysis(pk).Valid; if (pk.GenNumber < 6 && !legalized) { pk.EncryptionConstant = pk.PID; } if (new LegalityAnalysis(pk).Valid&& pk.Format >= pk.GenNumber) { pk.SetHappiness(); pk.SetBelugaValues(); if (shiny && !pk.IsShiny) { pk.SetShinySID(); } { return(true); } } else { var la = new LegalityAnalysis(pk); Debug.WriteLine(la.Report()); } } return(false); }
private static bool InnerBruteForce(PKM pk, GameVersion game, bool shiny, int abilitynum, ShowdownSet set) { pk.ClearRelearnMoves(); switch (game) { case GameVersion.RD: case GameVersion.BU: case GameVersion.YW: case GameVersion.GN: pk.Met_Location = 30013; pk.Met_Level = 100; break; case GameVersion.GD: case GameVersion.SV: case GameVersion.C: pk.Met_Location = 30017; pk.Met_Level = 100; break; case GameVersion.CXD: pk.Met_Location = 30001; pk.Met_Level = 100; break; default: pk.SetSuggestedMetLocation(); break; } pk.SetSuggestedRelearnMoves(); pk.CurrentHandler = 1; pk.HT_Name = "Archit"; pk.PID = PKX.GetRandomPID(pk.Species, pk.Gender, pk.Version, pk.Nature, pk.Format, (uint)(pk.AbilityNumber * 0x10001)); if (shiny) { pk.SetShiny(); } if (pk.PID == 0) { pk.PID = PKX.GetRandomPID(pk.Species, pk.Gender, pk.Version, pk.Nature, pk.Format, (uint)(pk.AbilityNumber * 0x10001)); if (shiny) { pk.SetShiny(); } } pk.RefreshAbility(abilitynum); pk.SetSuggestedMemories(); if (pk.GenNumber < 6) { pk.EncryptionConstant = pk.PID; } if (CommonErrorHandling2(pk)) { pk.HyperTrain(); if (shiny) { pk.SetShiny(); } return(true); } pk.HyperTrain(); bool legalized = new LegalityAnalysis(pk).Valid; AlternateAbilityRefresh(pk); if (pk.GenNumber < 6 && !legalized) { pk.EncryptionConstant = pk.PID; } if (new LegalityAnalysis(pk).Valid&& pk.Format >= pk.GenNumber) { pk.SetHappiness(); if (shiny && pk.IsShiny) { return(true); } if (!set.Shiny || pk.IsShiny) { return(true); } pk.SetShinySID(); if (new LegalityAnalysis(pk).Valid) { return(true); } pk.SetShiny(); if (new LegalityAnalysis(pk).Valid) { return(true); } } else { var edge = EncounterMovesetGenerator.GenerateEncounters(pk).OfType <EncounterStatic>(); foreach (EncounterStatic el in edge) { ApplyEncounterAttributes(pk, set, el); var la = new LegalityAnalysis(pk); if (la.Valid) { return(true); } Debug.WriteLine(la.Report()); } } return(false); }
/// <summary> /// Fetches <see cref="PKM.RelearnMoves"/> based on the provided <see cref="LegalityAnalysis"/>. /// </summary> /// <param name="legal"><see cref="LegalityAnalysis"/> which contains parsed information pertaining to legality.</param> /// <param name="enc">Encounter the relearn moves should be suggested for. If not provided, will try to detect it via legality analysis. </param> /// <returns><see cref="PKM.RelearnMoves"/> best suited for the current <see cref="PKM"/> data.</returns> public static IReadOnlyList <int> GetSuggestedRelearnMoves(this LegalityAnalysis legal, IEncounterTemplate?enc = null) { enc ??= legal.EncounterOriginal; var m = legal.GetSuggestedRelearnMovesFromEncounter(enc); if (m.Any(z => z != 0)) { return(m); } if (enc is MysteryGift or EncounterEgg) { return(m); } if (enc is EncounterSlot6AO { CanDexNav : true } dn) { var moves = legal.Info.Moves; for (int i = 0; i < moves.Length; i++) { if (!moves[i].ShouldBeInRelearnMoves()) { continue; } var move = legal.Entity.GetMove(i); if (dn.CanBeDexNavMove(move)) { return new[] { move, 0, 0, 0 } } ; } } if (enc is EncounterSlot8b { IsUnderground : true } ug) { var moves = legal.Info.Moves; for (int i = 0; i < moves.Length; i++) { if (!moves[i].ShouldBeInRelearnMoves()) { continue; } var move = legal.Entity.GetMove(i); if (ug.CanBeUndergroundMove(move)) { return new[] { move, 0, 0, 0 } } ; } if (ug.GetBaseEggMove(out int any)) return new[] { any, 0, 0, 0 } ; } var encounter = EncounterSuggestion.GetSuggestedMetInfo(legal.Entity); if (encounter is IRelearn { Relearn : { Count : > 0 } r })
/// <summary> /// Main function that auto legalizes based on the legality /// </summary> /// <remarks>Leverages <see cref="Core"/>'s <see cref="EncounterMovesetGenerator"/> to create a <see cref="PKM"/> from a <see cref="IBattleTemplate"/>.</remarks> /// <param name="dest">Destination for the generated pkm</param> /// <param name="template">rough pkm that has all the <see cref="set"/> values entered</param> /// <param name="set">Showdown set object</param> /// <param name="satisfied">If the final result is legal or not</param> public static PKM GetLegalFromTemplate(this ITrainerInfo dest, PKM template, IBattleTemplate set, out LegalizationResult satisfied) { RegenSet regen; if (set is RegenTemplate t) { t.FixGender(template.PersonalInfo); regen = t.Regen; } else { regen = RegenSet.Default; } template.ApplySetDetails(set); template.SetRecordFlags(); // Validate TR moves for the encounter var isHidden = template.AbilityNumber == 4; if (template.PersonalInfo.Abilities.Count > 2) // Hidden ability exists for the template { isHidden = isHidden || template.PersonalInfo.Abilities[2] == template.Ability; } var destType = template.GetType(); var destVer = (GameVersion)dest.Game; if (destVer <= 0 && dest is SaveFile s) { destVer = s.Version; } var timer = Stopwatch.StartNew(); var gamelist = FilteredGameList(template, destVer); var encounters = EncounterMovesetGenerator.GenerateEncounters(pk: template, moves: set.Moves, gamelist); var criteria = EncounterCriteria.GetCriteria(set); foreach (var enc in encounters) { // Return out if set times out if (timer.Elapsed.TotalSeconds >= Timeout) { timer.Stop(); satisfied = LegalizationResult.Timeout; return(template); } // Look before we leap -- don't waste time generating invalid / incompatible junk. if (!IsEncounterValid(set, enc, isHidden, destVer)) { continue; } // Create the PKM from the template. var tr = GetTrainer(regen, enc.Version, enc.Generation); var raw = enc.ConvertToPKM(tr, criteria); raw = raw.SanityCheckLocation(enc); if (raw.IsEgg) // PGF events are sometimes eggs. Force hatch them before proceeding { raw.HandleEggEncounters(enc, tr); } raw.PreSetPIDIV(enc, set); // Transfer any VC1 via VC2, as there may be GSC exclusive moves requested. if (dest.Generation >= 7 && raw is PK1 basepk1) { raw = basepk1.ConvertToPK2(); } // Bring to the target generation, then apply final details. var pk = PKMConverter.ConvertToType(raw, destType, out _); if (pk == null) { continue; } ApplySetDetails(pk, set, raw, dest, enc, regen); // Apply final tweaks to the data. if (pk is IGigantamax gmax && gmax.CanGigantamax != set.CanGigantamax) { if (!gmax.CanToggleGigantamax(pk.Species, pk.Form, enc.Species, enc.Form)) { continue; } gmax.CanGigantamax = set.CanGigantamax; // soup hax } // Try applying batch editor values. if (AllowBatchCommands && regen.HasBatchSettings) { pk.RefreshChecksum(); var b = regen.Batch; if (!BatchEditing.TryModify(pk, b.Filters, b.Instructions)) { continue; } } if (pk is PK1 pk1 && ParseSettings.AllowGen1Tradeback) { pk1.Catch_Rate = pk1.Gen2Item; // Simulate a gen 2 trade/tradeback to allow tradeback moves } // Verify the Legality of what we generated, and exit if it is valid. var la = new LegalityAnalysis(pk); if (la.Valid) { satisfied = LegalizationResult.Regenerated; return(pk); } Debug.WriteLine($"{la.Report()}\n"); } satisfied = LegalizationResult.Failed; return(template); }
// Helper functions for commands public static bool AddToWaitingList(string setstring, string display, string username, bool sub, out string msg) { if (!TwitchBot.Info.GetCanQueue()) { msg = "Sorry, I am not currently accepting queue requests!"; return(false); } var set = ShowdownUtil.ConvertToShowdown(setstring); if (set == null) { msg = $"Skipping trade, @{username}: Empty nickname provided for the species."; return(false); } var template = AutoLegalityWrapper.GetTemplate(set); if (template.Species < 1) { msg = $"Skipping trade, @{username}: Please read what you are supposed to type as the command argument."; return(false); } if (set.InvalidLines.Count != 0) { msg = $"Skipping trade, @{username}: Unable to parse Showdown Set:\n{string.Join("\n", set.InvalidLines)}"; return(false); } var sav = AutoLegalityWrapper.GetTrainerInfo(PKX.Generation); PKM pkm = sav.GetLegal(template, out var result); if (pkm.Nickname == "Egg") { TradeExtensions.EggTrade((PK8)pkm); } if (pkm.Species == 132) { TradeExtensions.DittoTrade((PK8)pkm); } if (!pkm.CanBeTraded()) { var reason = result == "Timeout" ? "Set took too long to generate." : "Unable to legalize the Pokémon."; msg = $"Skipping trade, @{username}: {reason}"; return(false); } var valid = new LegalityAnalysis(pkm).Valid; if (valid && pkm is PK8 pk8) { var tq = new TwitchQueue(pk8, new PokeTradeTrainerInfo(display), username, sub); TwitchBot.QueuePool.RemoveAll(z => z.UserName == username); // remove old requests if any TwitchBot.QueuePool.Add(tq); msg = $"@{username} - added to the waiting list. Please whisper your trade code to me! Your request from the waiting list will be removed if you are too slow!"; return(true); } msg = $"Skipping trade, @{username}: Unable to legalize the Pokémon."; return(false); }
public override void Verify(LegalityAnalysis data) { var pk = data.Entity; if (pk is IAwakened a) { VerifyAwakenedValues(data, a); return; } var enc = data.EncounterMatch; if (pk.IsEgg) { if (pk.EVTotal is not 0) { data.AddLine(GetInvalid(LEffortEgg)); } return; } // In Generations I and II, when a Pokémon is taken out of the Day Care, its experience will lower to the minimum value for its current level. int format = pk.Format; if (format < 3) // can abuse daycare for EV training without EXP gain { return; } int sum = pk.EVTotal; if (sum > 510) // format >= 3 { data.AddLine(GetInvalid(LEffortAbove510)); } Span <int> evs = stackalloc int[6]; pk.GetEVs(evs); if (format >= 6 && evs.Find(ev => ev > 252) != default) { data.AddLine(GetInvalid(LEffortAbove252)); } const int vitaMax = 100; // Vitamin Max if (format < 5) // 3/4 { if (enc.LevelMin == 100) // only true for Gen4 and Format=4 { // Cannot EV train at level 100 -- Certain events are distributed at level 100. if (evs.Find(ev => ev > vitaMax) != default) // EVs can only be increased by vitamins to a max of 100. { data.AddLine(GetInvalid(LEffortCap100)); } } else // check for gained EVs without gaining EXP -- don't check gen5+ which have wings to boost above 100. { var growth = PersonalTable.HGSS[enc.Species].EXPGrowth; var baseEXP = Experience.GetEXP(enc.LevelMin, growth); if (baseEXP == pk.EXP && evs.Find(ev => ev > vitaMax) != default) { data.AddLine(GetInvalid(string.Format(LEffortUntrainedCap, vitaMax))); } } } // Only one of the following can be true: 0, 508, and x%6!=0 if (sum == 0 && !enc.IsWithinEncounterRange(pk)) { data.AddLine(Get(LEffortEXPIncreased, Severity.Fishy)); } else if (sum == 508) { data.AddLine(Get(LEffort2Remaining, Severity.Fishy)); } else if (evs[0] != 0 && evs.Count(evs[0]) == evs.Length) { data.AddLine(Get(LEffortAllEqual, Severity.Fishy)); } }
private async Task <PokeTradeResult> PerformLinkCodeTrade(SAV8SWSH sav, PokeTradeDetail <PK8> poke, CancellationToken token) { // Update Barrier Settings UpdateBarrier(poke.IsSynchronized); poke.TradeInitialize(this); Hub.Config.Stream.EndEnterCode(this); if (await CheckIfSoftBanned(token).ConfigureAwait(false)) { await Unban(token).ConfigureAwait(false); } var pkm = poke.TradeData; if (pkm.Species != 0) { await SetBoxPokemon(pkm, InjectBox, InjectSlot, token, sav).ConfigureAwait(false); } if (!await IsOnOverworld(Hub.Config, token).ConfigureAwait(false)) { await ExitTrade(true, token).ConfigureAwait(false); return(PokeTradeResult.RecoverStart); } if (await CheckIfSearchingForLinkTradePartner(token).ConfigureAwait(false)) { Log("Still searching, reset bot position."); await ResetTradePosition(Hub.Config, token).ConfigureAwait(false); } Log("Opening Y-Comm Menu"); await Click(Y, 2_000, token).ConfigureAwait(false); Log("Selecting Link Trade"); await Click(A, 1_500, token).ConfigureAwait(false); Log("Selecting Link Trade Code"); await Click(DDOWN, 500, token).ConfigureAwait(false); for (int i = 0; i < 2; i++) { await Click(A, 1_500, token).ConfigureAwait(false); } // All other languages require an extra A press at this menu. if (GameLang != LanguageID.English && GameLang != LanguageID.Spanish) { await Click(A, 1_500, token).ConfigureAwait(false); } // Loading Screen await Task.Delay(1_000, token).ConfigureAwait(false); Hub.Config.Stream.StartEnterCode(this); await Task.Delay(1_000, token).ConfigureAwait(false); var code = poke.Code; Log($"Entering Link Trade Code: {code:0000}..."); await EnterTradeCode(code, token).ConfigureAwait(false); // Wait for Barrier to trigger all bots simultaneously. WaitAtBarrierIfApplicable(token); await Click(PLUS, 1_000, token).ConfigureAwait(false); // Start a Link Trade, in case of Empty Slot/Egg/Bad Pokémon we press sometimes B to return to the Overworld and skip this Slot. // Confirming... for (int i = 0; i < 4; i++) { await Click(A, 1_000, token).ConfigureAwait(false); } Hub.Config.Stream.EndEnterCode(this); // Should be on overworld by now. if (!await IsOnOverworld(Hub.Config, token).ConfigureAwait(false)) { await ExitTrade(true, token).ConfigureAwait(false); return(PokeTradeResult.RecoverPostLinkCode); } // Clear the shown data offset right as we start waiting on overworld. await Connection.WriteBytesAsync(PokeTradeBotUtil.EMPTY_SLOT, LinkTradePartnerPokemonOffset, token).ConfigureAwait(false); poke.TradeSearching(this); await Task.Delay(0_500, token).ConfigureAwait(false); // Wait until search finishes // Wait 30 Seconds for Trainer... Log("Waiting for trainer ..."); bool partnerFound; const uint ofs = LinkTradePartnerPokemonOffset; if (Hub.Config.Trade.SpinTrade) { partnerFound = await SpinUntilChangedLink(30_000, token).ConfigureAwait(false); } else { partnerFound = await ReadUntilChanged(ofs, PokeTradeBotUtil.EMPTY_EC, 30_000, 0_200, token).ConfigureAwait(false); } // Wait 15 more seconds. First 30 seconds is for spin if (!partnerFound) { Log("Still no partner found.. waiting 15 more seconds"); partnerFound = await ReadUntilChanged(ofs, PokeTradeBotUtil.EMPTY_EC, 15_000, 0_200, token).ConfigureAwait(false); } if (token.IsCancellationRequested) { return(PokeTradeResult.Aborted); } if (!partnerFound) { await ResetTradePosition(Hub.Config, token).ConfigureAwait(false); return(PokeTradeResult.NoTrainerFound); } // Select Pokemon // pkm already injected to b1s1 var TrainerName = await GetTradePartnerName(TradeMethod.LinkTrade, token).ConfigureAwait(false); Log($"Found Trading Partner: {TrainerName} ..."); await Task.Delay(1_500, token).ConfigureAwait(false); // necessary delay to get to the box properly if (!await IsCorrectScreen(CurrentScreen_Box, token).ConfigureAwait(false)) { await ExitTrade(true, token).ConfigureAwait(false); return(PokeTradeResult.RecoverOpenBox); } // Confirm Box 1 Slot 1 if (poke.Type == PokeTradeType.Specific) { for (int i = 0; i < 5; i++) { await Click(A, 0_500, token).ConfigureAwait(false); } } poke.SendNotification(this, $"Found Trading Partner: {TrainerName}. Waiting for a Pokémon..."); if (poke.Type == PokeTradeType.Dump) { return(await ProcessDumpTradeAsync(poke, token).ConfigureAwait(false)); } // Wait for User Input... var pk = await ReadUntilPresent(LinkTradePartnerPokemonOffset, 25_000, 1_000, token).ConfigureAwait(false); if (pk == null) { await ExitTrade(true, token).ConfigureAwait(false); return(PokeTradeResult.TrainerTooSlow); } if (poke.Type == PokeTradeType.Seed) { // Immediately exit, we aren't trading anything. return(await EndSeedCheckTradeAsync(poke, pk, token).ConfigureAwait(false)); } if (poke.Type == PokeTradeType.Random) // distribution { // Allow the trade partner to do a Ledy swap. var trade = Hub.Ledy.GetLedyTrade(pk, Hub.Config.Distribute.LedySpecies); pkm = trade.Receive; poke.TradeData = pkm; if (trade.Type != LedyResponseType.Random) { poke.SendNotification(this, "Injecting your requested Pokémon."); await Click(A, 0_800, token).ConfigureAwait(false); await SetBoxPokemon(pkm, InjectBox, InjectSlot, token, sav).ConfigureAwait(false); await Task.Delay(2_500, token).ConfigureAwait(false); } for (int i = 0; i < 5; i++) { await Click(A, 0_500, token).ConfigureAwait(false); } } else if (poke.Type == PokeTradeType.Clone) { // Inject the shown Pokémon. var clone = (PK8)pk.Clone(); if (Hub.Config.Discord.ReturnPK8s) { poke.SendNotification(this, clone, "Here's what you showed me!"); } var la = new LegalityAnalysis(clone); if (!la.Valid && Hub.Config.Legality.VerifyLegality) { Log($"Clone request has detected an invalid Pokémon: {(Species)clone.Species}"); if (DumpSetting.Dump) { DumpPokemon(DumpSetting.DumpFolder, "hacked", clone); } var report = la.Report(); Log(report); poke.SendNotification(this, "This Pokémon is not legal per PKHeX's legality checks. I am forbidden from cloning this. Exiting trade."); poke.SendNotification(this, report); return(PokeTradeResult.IllegalTrade); } if (Hub.Config.Legality.ResetHOMETracker) { clone.Tracker = 0; } poke.SendNotification(this, $"**Cloned your {(Species)clone.Species}!**\nNow press B to cancel your offer and trade me a Pokémon you don't want."); Log($"Cloned a {(Species)clone.Species}. Waiting for user to change their Pokémon..."); // Clear the shown data offset. await Connection.WriteBytesAsync(PokeTradeBotUtil.EMPTY_SLOT, LinkTradePartnerPokemonOffset, token).ConfigureAwait(false); // Wait for User Input... var pk2 = await ReadUntilPresent(LinkTradePartnerPokemonOffset, 10_000, 1_000, token).ConfigureAwait(false); if (pk2 == null || SearchUtil.HashByDetails(pk2) == SearchUtil.HashByDetails(pk)) { poke.SendNotification(this, "**HEY CHANGE IT NOW OR I AM LEAVING!!!**"); // They get one more chance. // Clear the shown data offset. await Connection.WriteBytesAsync(PokeTradeBotUtil.EMPTY_SLOT, LinkTradePartnerPokemonOffset, token).ConfigureAwait(false); // Wait for User Input... pk2 = await ReadUntilPresent(LinkTradePartnerPokemonOffset, 5_000, 1_000, token).ConfigureAwait(false); if (pk2 == null || SearchUtil.HashByDetails(pk2) == SearchUtil.HashByDetails(pk)) { Log("Trading partner did not change their Pokémon."); await ExitTrade(true, token).ConfigureAwait(false); return(PokeTradeResult.TrainerTooSlow); } } await Click(A, 0_800, token).ConfigureAwait(false); await SetBoxPokemon(clone, InjectBox, InjectSlot, token, sav).ConfigureAwait(false); pkm = clone; for (int i = 0; i < 5; i++) { await Click(A, 0_500, token).ConfigureAwait(false); } } await Click(A, 3_000, token).ConfigureAwait(false); for (int i = 0; i < 5; i++) { await Click(A, 1_500, token).ConfigureAwait(false); } var delay_count = 0; while (!await IsCorrectScreen(CurrentScreen_Box, token).ConfigureAwait(false)) { await Click(A, 3_000, token).ConfigureAwait(false); delay_count++; if (delay_count >= 50) { break; } if (await IsOnOverworld(Hub.Config, token).ConfigureAwait(false)) // In case we are in a Trade Evolution/PokeDex Entry and the Trade Partner quits we land on the Overworld { break; } } await Task.Delay(1_000 + Util.Rand.Next(0_700, 1_000), token).ConfigureAwait(false); await ExitTrade(false, token).ConfigureAwait(false); Log("Exited Trade!"); if (token.IsCancellationRequested) { return(PokeTradeResult.Aborted); } // Trade was Successful! var traded = await ReadBoxPokemon(InjectBox, InjectSlot, token).ConfigureAwait(false); // Pokémon in b1s1 is same as the one they were supposed to receive (was never sent). if (SearchUtil.HashByDetails(traded) == SearchUtil.HashByDetails(pkm)) { Log("User did not complete the trade."); return(PokeTradeResult.TrainerTooSlow); } else { // As long as we got rid of our inject in b1s1, assume the trade went through. Log("User completed the trade."); poke.TradeFinished(this, traded); // Only log if we completed the trade. var counts = Hub.Counts; if (poke.Type == PokeTradeType.Random) { counts.AddCompletedDistribution(); } else if (poke.Type == PokeTradeType.Clone) { counts.AddCompletedClones(); } else { Hub.Counts.AddCompletedTrade(); } if (DumpSetting.Dump && !string.IsNullOrEmpty(DumpSetting.DumpFolder)) { var subfolder = poke.Type.ToString().ToLower(); DumpPokemon(DumpSetting.DumpFolder, subfolder, traded); // received if (poke.Type == PokeTradeType.Specific || poke.Type == PokeTradeType.Clone) { DumpPokemon(DumpSetting.DumpFolder, "traded", pkm); // sent to partner } } } return(PokeTradeResult.Success); }
public static int GetSuggestedCatchRate(PK1 pk1, SaveFile sav) { var la = new LegalityAnalysis(pk1); return(GetSuggestedCatchRate(pk1, sav, la)); }
/// <summary> /// Main function that auto legalizes based on the legality /// </summary> /// <param name="roughPK">rough pkm that has all the SSet values entered</param> /// <param name="SSet">Showdown set object</param> /// <param name="satisfied">If the final result is satisfactory, otherwise use current auto legality functionality</param> /// <returns></returns> public static PKM APILegality(PKM roughPK, ShowdownSet SSet, out bool satisfied) { bool changedForm = false; if (SSet.Form != null) { changedForm = FixFormes(SSet, out SSet); } satisfied = false; // true when all features of the PKM are satisfied int Form = roughPK.AltForm; if (changedForm) { Form = SSet.FormIndex; roughPK.ApplySetDetails(SSet); } int HPType = roughPK.HPType; // List of candidate PKM files int[] moves = SSet.Moves; var f = GeneratePKMs(roughPK, SAV, moves); foreach (PKM pkmn in f) { if (pkmn != null) { PKM pk = PKMConverter.ConvertToType(pkmn, SAV.PKMType, out _); // All Possible PKM files LegalInfo info = new LegalInfo(pk); var pidiv = info.PIDIV ?? MethodFinder.Analyze(pk); PIDType Method = PIDType.None; if (pidiv != null) { Method = pidiv.Type; } SetVersion(pk, pkmn); // PreEmptive Version setting SetSpeciesLevel(pk, SSet, Form); SetMovesEVsItems(pk, SSet); SetTrainerDataAndMemories(pk); SetNatureAbility(pk, SSet); SetIVsPID(pk, SSet, Method, HPType, pkmn); PrintLegality(pk); ColosseumFixes(pk); pk.SetSuggestedHyperTrainingData(pk.IVs); // Hypertrain SetEncryptionConstant(pk); SetShinyBoolean(pk, SSet.Shiny); CheckAndSetFateful(pk); FixGender(pk, SSet); FixRibbons(pk); FixMemoriesPKM(pk); SetSpeciesBall(pk); SetHappiness(pk); LegalityAnalysis la = new LegalityAnalysis(pk); if (la.Valid) { satisfied = true; } if (satisfied) { return(pk); } else { Console.WriteLine(la.Report()); } } } return(roughPK); }
public static bool ValidBall(this PKM pk) { var rep = new LegalityAnalysis(pk).Report(true); return(rep.Contains(LegalityCheckStrings.LBallEnc) || rep.Contains(LegalityCheckStrings.LBallSpeciesPass)); }
private void VerifyMedalsRegular(LegalityAnalysis data) { var pk = data.Entity; var train = (ISuperTrain)pk; var Info = data.Info; uint value = System.Buffers.Binary.BinaryPrimitives.ReadUInt32LittleEndian(data.Entity.Data.AsSpan(0x2C)); if ((value & 3) != 0) // 2 unused flags { data.AddLine(GetInvalid(LSuperUnused)); } int TrainCount = train.SuperTrainingMedalCount(); if (pk.IsEgg) { // Can't have any super training data as an egg. if (TrainCount > 0) { data.AddLine(GetInvalid(LSuperEgg)); } if (train.SecretSuperTrainingUnlocked) { data.AddLine(GetInvalid(LSuperNoUnlocked)); } if (train.SecretSuperTrainingComplete) { data.AddLine(GetInvalid(LSuperNoComplete)); } return; } if (Info.Generation is >= 7 or <= 2) { // Can't have any super training data if it never visited Gen6. if (TrainCount > 0) { data.AddLine(GetInvalid(LSuperUnavailable)); } if (train.SecretSuperTrainingUnlocked) { data.AddLine(GetInvalid(LSuperNoUnlocked)); } if (train.SecretSuperTrainingComplete) { data.AddLine(GetInvalid(LSuperNoComplete)); } return; } if (pk.Format >= 7) { // Gen6->Gen7 transfer wipes the two Secret flags. if (train.SecretSuperTrainingUnlocked) { data.AddLine(GetInvalid(LSuperNoUnlocked)); } if (train.SecretSuperTrainingComplete) { data.AddLine(GetInvalid(LSuperNoComplete)); } return; } // Only reach here if Format==6. if (TrainCount == 30 ^ train.SecretSuperTrainingComplete) { data.AddLine(GetInvalid(LSuperComplete)); } }
public override void Verify(LegalityAnalysis data) { var pk = data.Entity; if (pk is not IContestStats s) { return; } // If no stats have been increased from the initial amount, then we're done here. // some encounters have contest stats built in. they're already checked by the initial encounter match. if (!s.HasContestStats()) { return; } // Check the correlation of Stats & Sheen! // In generations 3,4 and BDSP, blocks/poffins have a feel(sheen) equal to sheen=sum(stats)/5, with +/- 10% for a favored stat. // In generation 6 (ORAS), they don't award any sheen, so any value is legal. var correlation = GetContestStatRestriction(pk, data.Info.Generation, data.Info.EvoChainsAllGens); if (correlation == None) { // We're only here because we have contest stat values. We aren't permitted to have any, so flag it. data.AddLine(GetInvalid(LContestZero)); } else if (correlation == NoSheen) { // We can get contest stat values, but we can't get any for Sheen. // Any combination of non-sheen is ok, but nonzero sheen is illegal. if (s.CNT_Sheen != 0) { data.AddLine(GetInvalid(LContestZeroSheen)); } } else if (correlation == CorrelateSheen) { bool gen3 = data.Info.Generation == 3; bool bdsp = pk.HasVisitedBDSP(data.Info.EvoChainsAllGens.Gen8b); var method = gen3 ? ContestStatGrantingSheen.Gen3 : bdsp ? ContestStatGrantingSheen.Gen8b : ContestStatGrantingSheen.Gen4; // Check for stat values that exceed a valid sheen value. var initial = GetReferenceTemplate(data.Info.EncounterMatch); var minSheen = CalculateMinimumSheen(s, initial, pk, method); if (s.CNT_Sheen < minSheen) { data.AddLine(GetInvalid(string.Format(LContestSheenTooLow_0, minSheen))); } // Check for sheen values that are too high. var maxSheen = CalculateMaximumSheen(s, pk.Nature, initial, gen3); if (s.CNT_Sheen > maxSheen) { data.AddLine(GetInvalid(string.Format(LContestSheenTooHigh_0, maxSheen))); } } else if (correlation == Mixed) { bool gen3 = data.Info.Generation == 3; // Check for sheen values that are too high. var initial = GetReferenceTemplate(data.Info.EncounterMatch); var maxSheen = CalculateMaximumSheen(s, pk.Nature, initial, gen3); if (s.CNT_Sheen > maxSheen) { data.AddLine(GetInvalid(string.Format(LContestSheenTooHigh_0, maxSheen))); } } }
public async Task EggRollAsync() { if (!Info.Hub.Config.Trade.EggRollChannels.Contains(Context.Channel.Id.ToString()) && !Info.Hub.Config.Trade.EggRollChannels.Equals("")) { await ReplyAsync($"You're typing the command in the wrong channel!").ConfigureAwait(false); return; } if (Info.Hub.Config.Trade.EggRollCooldown < 0) { Info.Hub.Config.Trade.EggRollCooldown = default; } var id = Context.User.Id.ToString(); var line = TradeExtensions.EggRollCooldown.FirstOrDefault(z => z.Contains(id)); System.DateTime.TryParse(line != null ? line.Split(',')[1] : string.Empty, out System.DateTime time); var timer = time.AddHours(Info.Hub.Config.Trade.EggRollCooldown); var timeRemaining = timer - System.DateTime.Now; if (System.DateTime.Now < timer) { await ReplyAsync($"{Context.User.Mention}, please try again in {timeRemaining.Hours:N0}h : {timeRemaining.Minutes:N0}m : {timeRemaining.Seconds:N0}s!").ConfigureAwait(false); return; } var code = Info.GetRandomTradeCode(); var rng = new System.Random(); int shinyRng = rng.Next(0, TradeExtensions.shinyOdds.Length); int abilityRng = rng.Next(0, TradeExtensions.abilityIndex.Length); var set = new ShowdownSet($"Egg({SpeciesName.GetSpeciesName((int)TradeExtensions.validEgg.GetValue(rng.Next(0, TradeExtensions.validEgg.Length)), 2)})"); var template = AutoLegalityWrapper.GetTemplate(set); var sav = AutoLegalityWrapper.GetTrainerInfo(8); var pkm = (PK8)sav.GetLegal(template, out _); if (TradeExtensions.regional.ToList().Contains(pkm.Species)) { int formRng = rng.Next(0, TradeExtensions.formIndex1.Length); int formRng2 = rng.Next(0, TradeExtensions.formIndex2.Length); if (pkm.Species != 52) { pkm.SetAltForm(TradeExtensions.formIndex1[formRng]); } else { pkm.SetAltForm(TradeExtensions.formIndex2[formRng2]); } if (pkm.AltForm != 0) { switch (pkm.Species) { case 27: pkm.RelearnMove3 = 10; break; case 37: pkm.RelearnMove4 = 39; break; case 52: pkm.RelearnMove2 = 252; pkm.RelearnMove3 = 45; break; case 83: pkm.RelearnMove1 = 64; pkm.RelearnMove4 = 28; break; case 222: pkm.RelearnMove1 = 33; break; case 263: pkm.RelearnMove2 = 43; pkm.RelearnMove3 = 0; pkm.RelearnMove4 = 0; break; } ; } } TradeExtensions.EggTrade(pkm); pkm.Nature = rng.Next(0, 24); pkm.StatNature = pkm.Nature; pkm.SetAbilityIndex(TradeExtensions.abilityIndex[abilityRng]); pkm.IVs = pkm.SetRandomIVs(3); BallApplicator.ApplyBallLegalRandom(pkm); switch (TradeExtensions.shinyOdds[shinyRng]) { case 3: CommonEdits.SetShiny(pkm, Shiny.Never); pkm.SetUnshiny(); break; case 5: CommonEdits.SetShiny(pkm, Shiny.AlwaysStar); break; case 6: CommonEdits.SetShiny(pkm, Shiny.AlwaysSquare); break; } ; var la = new LegalityAnalysis(pkm); var spec = GameInfo.Strings.Species[template.Species]; var invalid = !(pkm is PK8) || (!la.Valid && SysCordInstance.Self.Hub.Config.Legality.VerifyLegality); if (invalid) { var imsg = $"Oops! I scrambled your egg! Don't tell Ramsay! Here's my best attempt for that {spec}!"; await Context.Channel.SendPKMAsync(pkm, imsg).ConfigureAwait(false); return; } pkm.ResetPartyStats(); var sudo = Context.User.GetIsSudo(); await Context.AddToQueueAsync(code, Context.User.Username, sudo, pkm, PokeRoutineType.EggRoll, PokeTradeType.EggRoll).ConfigureAwait(false); }
public void SendNotification(PokeRoutineExecutor routine, LegalityAnalysis la) => Notifier.SendNotification(routine, this, la);
private async Task <PokeTradeResult> PerformLinkCodeTrade(SAV8SWSH sav, PokeTradeDetail <PK8> poke, CancellationToken token) { // Update Barrier Settings UpdateBarrier(poke.IsSynchronized); poke.TradeInitialize(this); Hub.Config.Stream.EndEnterCode(this); if (await CheckIfSoftBanned(token).ConfigureAwait(false)) { await Unban(token).ConfigureAwait(false); } var pkm = poke.TradeData; if (pkm.Species != 0) { await SetBoxPokemon(pkm, InjectBox, InjectSlot, token, sav).ConfigureAwait(false); } if (!await IsOnOverworld(Hub.Config, token).ConfigureAwait(false)) { await ExitTrade(Hub.Config, true, token).ConfigureAwait(false); return(PokeTradeResult.RecoverStart); } while (await CheckIfSearchingForLinkTradePartner(token).ConfigureAwait(false)) { Log("Still searching, reset bot position."); await ResetTradePosition(Hub.Config, token).ConfigureAwait(false); } Log("Opening Y-Comm Menu"); await Click(Y, 2_000, token).ConfigureAwait(false); Log("Selecting Link Trade"); await Click(A, 1_500, token).ConfigureAwait(false); Log("Selecting Link Trade Code"); await Click(DDOWN, 500, token).ConfigureAwait(false); for (int i = 0; i < 2; i++) { await Click(A, 1_500, token).ConfigureAwait(false); } // All other languages require an extra A press at this menu. if (GameLang != LanguageID.English && GameLang != LanguageID.Spanish) { await Click(A, 1_500, token).ConfigureAwait(false); } // Loading Screen await Task.Delay(1_000, token).ConfigureAwait(false); if (poke.Type != PokeTradeType.Random) { Hub.Config.Stream.StartEnterCode(this); } await Task.Delay(1_000, token).ConfigureAwait(false); var code = poke.Code; Log($"Entering Link Trade Code: {code:0000 0000}..."); await EnterTradeCode(code, token).ConfigureAwait(false); // Wait for Barrier to trigger all bots simultaneously. WaitAtBarrierIfApplicable(token); await Click(PLUS, 1_000, token).ConfigureAwait(false); Hub.Config.Stream.EndEnterCode(this); // Confirming and return to overworld. var delay_count = 0; while (!await IsOnOverworld(Hub.Config, token).ConfigureAwait(false)) { if (delay_count >= 5) { await ExitTrade(Hub.Config, true, token).ConfigureAwait(false); return(PokeTradeResult.RecoverPostLinkCode); } for (int i = 0; i < 5; i++) { await Click(A, 0_800, token).ConfigureAwait(false); } delay_count++; } poke.TradeSearching(this); await Task.Delay(0_500, token).ConfigureAwait(false); // Wait for a Trainer... Log("Waiting for trainer..."); bool partnerFound = await WaitForPokemonChanged(LinkTradePartnerPokemonOffset, Hub.Config.Trade.TradeWaitTime * 1_000, 0_200, token); if (token.IsCancellationRequested) { return(PokeTradeResult.Aborted); } if (!partnerFound) { await ResetTradePosition(Hub.Config, token).ConfigureAwait(false); return(PokeTradeResult.NoTrainerFound); } // Select Pokemon // pkm already injected to b1s1 await Task.Delay(5_500, token).ConfigureAwait(false); // necessary delay to get to the box properly var TrainerName = await GetTradePartnerName(TradeMethod.LinkTrade, token).ConfigureAwait(false); Log($"Found Trading Partner: {TrainerName}..."); if (!await IsInBox(token).ConfigureAwait(false)) { await ExitTrade(Hub.Config, true, token).ConfigureAwait(false); return(PokeTradeResult.RecoverOpenBox); } // Confirm Box 1 Slot 1 if (poke.Type == PokeTradeType.Specific) { for (int i = 0; i < 5; i++) { await Click(A, 0_500, token).ConfigureAwait(false); } } poke.SendNotification(this, $"Found Trading Partner: {TrainerName}. Waiting for a Pokémon..."); if (poke.Type == PokeTradeType.Dump) { return(await ProcessDumpTradeAsync(poke, token).ConfigureAwait(false)); } // Wait for User Input... var pk = await ReadUntilPresent(LinkTradePartnerPokemonOffset, 25_000, 1_000, token).ConfigureAwait(false); var oldEC = await Connection.ReadBytesAsync(LinkTradePartnerPokemonOffset, 4, token).ConfigureAwait(false); if (pk == null) { await ExitTrade(Hub.Config, true, token).ConfigureAwait(false); return(PokeTradeResult.TrainerTooSlow); } if (poke.Type == PokeTradeType.Seed) { // Immediately exit, we aren't trading anything. return(await EndSeedCheckTradeAsync(poke, pk, token).ConfigureAwait(false)); } if (poke.Type == PokeTradeType.Random) // distribution { // Allow the trade partner to do a Ledy swap. var trade = Hub.Ledy.GetLedyTrade(pk, Hub.Config.Distribution.LedySpecies); if (trade != null) { pkm = trade.Receive; poke.TradeData = pkm; poke.SendNotification(this, "Injecting the requested Pokémon."); await Click(A, 0_800, token).ConfigureAwait(false); await SetBoxPokemon(pkm, InjectBox, InjectSlot, token, sav).ConfigureAwait(false); await Task.Delay(2_500, token).ConfigureAwait(false); } for (int i = 0; i < 5; i++) { await Click(A, 0_500, token).ConfigureAwait(false); } } else if (poke.Type == PokeTradeType.FixAdOT) { var clone = (PK8)pk.Clone(); var adOT = System.Text.RegularExpressions.Regex.Match(clone.OT_Name, @"(YT$)|(YT\w*$)|(Lab$)|(\.\w*)|(TV$)|(PKHeX)|(FB:)|(SysBot)").Value != "" || System.Text.RegularExpressions.Regex.Match(clone.Nickname, @"(YT$)|(YT\w*$)|(Lab$)|(\.\w*)|(TV$)|(PKHeX)|(FB:)|(SysBot)").Value != ""; if (adOT && clone.OT_Name != $"{TrainerName}") { clone.OT_Name = $"{TrainerName}"; clone.ClearNickname(); clone.PKRS_Infected = false; clone.PKRS_Cured = false; clone.PKRS_Days = 0; clone.PKRS_Strain = 0; poke.SendNotification(this, $"```fix\nDetected an ad OT/Nickname with your {(Species)clone.Species}! Fixed it for you!```"); } else { poke.SendNotification(this, "```fix\nNo website ad detected in Nickname or OT. Exiting trade...```"); await ExitTrade(Hub.Config, true, token).ConfigureAwait(false); return(PokeTradeResult.IllegalTrade); } var la = new LegalityAnalysis(clone); if (!la.Valid && Hub.Config.Legality.VerifyLegality) { Log($"FixAd request has detected an invalid Pokémon: {(Species)clone.Species}"); if (DumpSetting.Dump) { DumpPokemon(DumpSetting.DumpFolder, "hacked", clone); } var report = la.Report(); Log(report); poke.SendNotification(this, "This Pokémon is not legal per PKHeX's legality checks. I am forbidden from cloning this. Exiting trade."); poke.SendNotification(this, report); await ExitTrade(Hub.Config, true, token).ConfigureAwait(false); return(PokeTradeResult.IllegalTrade); } if (Hub.Config.Legality.ResetHOMETracker) { clone.Tracker = 0; } poke.SendNotification(this, $"```fix\nFixed your {(Species)clone.Species}!\nNow confirm the trade!```"); Log($"Fixed Nickname/OT for {(Species)clone.Species}."); await ReadUntilPresent(LinkTradePartnerPokemonOffset, 3_000, 1_000, token).ConfigureAwait(false); await Click(A, 0_800, token).ConfigureAwait(false); await SetBoxPokemon(clone, InjectBox, InjectSlot, token, sav).ConfigureAwait(false); pkm = clone; for (int i = 0; i < 5; i++) { await Click(A, 0_500, token).ConfigureAwait(false); } } else if (poke.Type == PokeTradeType.Clone) { // Inject the shown Pokémon. var clone = (PK8)pk.Clone(); if (Hub.Config.Discord.ReturnPK8s) { poke.SendNotification(this, clone, "Here's what you showed me!"); } var la = new LegalityAnalysis(clone); if (!la.Valid && Hub.Config.Legality.VerifyLegality) { Log($"Clone request has detected an invalid Pokémon: {(Species)clone.Species}"); if (DumpSetting.Dump) { DumpPokemon(DumpSetting.DumpFolder, "hacked", clone); } var report = la.Report(); Log(report); poke.SendNotification(this, "This Pokémon is not legal per PKHeX's legality checks. I am forbidden from cloning this. Exiting trade."); poke.SendNotification(this, report); await ExitTrade(Hub.Config, true, token).ConfigureAwait(false); return(PokeTradeResult.IllegalTrade); } if (Hub.Config.Legality.ResetHOMETracker) { clone.Tracker = 0; } poke.SendNotification(this, $"**Cloned your {(Species)clone.Species}!**\nNow press B to cancel your offer and trade me a Pokémon you don't want."); Log($"Cloned a {(Species)clone.Species}. Waiting for user to change their Pokémon..."); // Separate this out from WaitForPokemonChanged since we compare to old EC from original read. partnerFound = await ReadUntilChanged(LinkTradePartnerPokemonOffset, oldEC, 15_000, 0_200, false, token).ConfigureAwait(false); if (!partnerFound) { poke.SendNotification(this, "**HEY CHANGE IT NOW OR I AM LEAVING!!!**"); // They get one more chance. partnerFound = await ReadUntilChanged(LinkTradePartnerPokemonOffset, oldEC, 15_000, 0_200, false, token).ConfigureAwait(false); } var pk2 = await ReadUntilPresent(LinkTradePartnerPokemonOffset, 3_000, 1_000, token).ConfigureAwait(false); if (!partnerFound || pk2 == null || SearchUtil.HashByDetails(pk2) == SearchUtil.HashByDetails(pk)) { Log("Trading partner did not change their Pokémon."); await ExitTrade(Hub.Config, true, token).ConfigureAwait(false); return(PokeTradeResult.TrainerTooSlow); } await Click(A, 0_800, token).ConfigureAwait(false); await SetBoxPokemon(clone, InjectBox, InjectSlot, token, sav).ConfigureAwait(false); pkm = clone; for (int i = 0; i < 5; i++) { await Click(A, 0_500, token).ConfigureAwait(false); } } await Click(A, 3_000, token).ConfigureAwait(false); for (int i = 0; i < 5; i++) { await Click(A, 1_500, token).ConfigureAwait(false); } delay_count = 0; while (!await IsInBox(token).ConfigureAwait(false)) { await Click(A, 3_000, token).ConfigureAwait(false); delay_count++; if (delay_count >= 50) { break; } if (await IsOnOverworld(Hub.Config, token).ConfigureAwait(false)) // In case we are in a Trade Evolution/PokeDex Entry and the Trade Partner quits we land on the Overworld { break; } } await Task.Delay(1_000 + Util.Rand.Next(0_700, 1_000), token).ConfigureAwait(false); await ExitTrade(Hub.Config, false, token).ConfigureAwait(false); Log("Exited Trade!"); if (token.IsCancellationRequested) { return(PokeTradeResult.Aborted); } // Trade was Successful! var traded = await ReadBoxPokemon(InjectBox, InjectSlot, token).ConfigureAwait(false); // Pokémon in b1s1 is same as the one they were supposed to receive (was never sent). if (poke.Type != PokeTradeType.FixAdOT && SearchUtil.HashByDetails(traded) == SearchUtil.HashByDetails(pkm)) { Log("User did not complete the trade."); return(PokeTradeResult.TrainerTooSlow); } else { // As long as we got rid of our inject in b1s1, assume the trade went through. Log("User completed the trade."); poke.TradeFinished(this, traded); // Only log if we completed the trade. var counts = Hub.Counts; if (poke.Type == PokeTradeType.Random) { counts.AddCompletedDistribution(); } else if (poke.Type == PokeTradeType.Clone) { counts.AddCompletedClones(); } else { Hub.Counts.AddCompletedTrade(); } if (DumpSetting.Dump && !string.IsNullOrEmpty(DumpSetting.DumpFolder)) { var subfolder = poke.Type.ToString().ToLower(); DumpPokemon(DumpSetting.DumpFolder, subfolder, traded); // received if (poke.Type == PokeTradeType.Specific || poke.Type == PokeTradeType.Clone) { DumpPokemon(DumpSetting.DumpFolder, "traded", pkm); // sent to partner } } } return(PokeTradeResult.Success); }
/// <summary> /// Main function that auto legalizes based on the legality /// </summary> /// <remarks>Leverages <see cref="Core"/>'s <see cref="EncounterMovesetGenerator"/> to create a <see cref="PKM"/> from a <see cref="IBattleTemplate"/>.</remarks> /// <param name="dest">Destination for the generated pkm</param> /// <param name="template">rough pkm that has all the <see cref="set"/> values entered</param> /// <param name="set">Showdown set object</param> /// <param name="satisfied">If the final result is legal or not</param> public static PKM GetLegalFromTemplate(this ITrainerInfo dest, PKM template, IBattleTemplate set, out bool satisfied) { RegenSet regen; if (set is RegenTemplate t) { t.FixGender(template.PersonalInfo); regen = t.Regen; } else { regen = RegenSet.Default; } template.ApplySetDetails(set); template.SetRecordFlags(); // Validate TR moves for the encounter var isHidden = template.AbilityNumber == 4; var destType = template.GetType(); var destVer = (GameVersion)dest.Game; if (destVer <= 0 && dest is SaveFile s) { destVer = s.Version; } var gamelist = GameUtil.GetVersionsWithinRange(template, template.Format).OrderByDescending(c => c.GetGeneration()).ToArray(); if (PrioritizeGame) { gamelist = PrioritizeGameVersion == GameVersion.Any ? PrioritizeVersion(gamelist, destVer) : PrioritizeVersion(gamelist, PrioritizeGameVersion); } var encounters = EncounterMovesetGenerator.GenerateEncounters(pk: template, moves: set.Moves, gamelist); foreach (var enc in encounters) { // Look before we leap -- don't waste time generating invalid / incompatible junk. if (!IsEncounterValid(set, enc, isHidden, destVer, out var ver)) { continue; } // Create the PKM from the template. var tr = GetTrainer(regen, ver, enc.Generation); var raw = SanityCheckEncounters(enc).ConvertToPKM(tr); if (raw.IsEgg) // PGF events are sometimes eggs. Force hatch them before proceeding { raw.HandleEggEncounters(enc, tr); } // Bring to the target generation, then apply final details. var pk = PKMConverter.ConvertToType(raw, destType, out _); if (pk == null) { continue; } ApplySetDetails(pk, set, raw, dest, enc, regen); // Apply final tweaks to the data. if (pk is IGigantamax gmax && gmax.CanGigantamax != set.CanGigantamax) { if (!gmax.CanToggleGigantamax(pk.Species, enc.Species)) { continue; } gmax.CanGigantamax = set.CanGigantamax; // soup hax } // Try applying batch editor values. if (AllowBatchCommands && regen.HasBatchSettings) { pk.RefreshChecksum(); var b = regen.Batch; if (!BatchEditing.TryModify(pk, b.Filters, b.Instructions)) { continue; } } if (pk is PK1 pk1 && ParseSettings.AllowGen1Tradeback) { pk1.Catch_Rate = pk1.Gen2Item; // Simulate a gen 2 trade/tradeback to allow tradeback moves } // Verify the Legality of what we generated, and exit if it is valid. var la = new LegalityAnalysis(pk); if (la.Valid) { satisfied = true; return(pk); } Debug.WriteLine($"{la.Report()}\n"); } satisfied = false; return(template); }
public static string GetVerboseLegalityReport(LegalityAnalysis la) => Formatter.GetReportVerbose(la);
/// <summary> /// Method to set PID, IV while validating nature. /// </summary> /// <param name="pk">PKM to modify</param> /// <param name="Method">Given Method</param> /// <param name="HPType">HPType INT for preserving Hidden powers</param> /// <param name="shiny">Only used for CHANNEL RNG type</param> /// <param name="enc"></param> private static void FindPIDIV(PKM pk, PIDType Method, int HPType, bool shiny, IEncounterable enc) { if (Method == PIDType.None) { if (enc is WC3 wc3) { Method = wc3.Method; } else { Method = FindLikelyPIDType(pk); } if (pk.Version == (int)GameVersion.CXD && Method != PIDType.PokeSpot) { Method = PIDType.CXD; } if (Method == PIDType.None) { pk.SetPIDGender(pk.Gender); } } if (Method == PIDType.Method_1_Roamer && pk.HPType != (int)MoveType.Fighting - 1) // M1 Roamers can only be HP fighting { return; } if (Method == PIDType.Pokewalker && (pk.Nature >= 24 || pk.AbilityNumber == 4)) // No possible pokewalker matches { return; } var iterPKM = pk.Clone(); var count = 0; do { uint seed = Util.Rand32(); if (PokeWalkerSeedFail(seed, Method, pk, iterPKM)) { continue; } PIDGenerator.SetValuesFromSeed(pk, Method, seed); if (!(pk.Ability == iterPKM.Ability && pk.AbilityNumber == iterPKM.AbilityNumber && pk.Nature == iterPKM.Nature)) { continue; } if (HPType >= 0 && pk.HPType != HPType) { continue; } if (pk.PID % 25 != iterPKM.Nature) // Util.Rand32 is the way to go { continue; } if (pk.Version == (int)GameVersion.CXD && Method == PIDType.CXD) // verify locks { pk.EncryptionConstant = pk.PID; var la = new LegalityAnalysis(pk); if (la.Info.PIDIV.Type != PIDType.CXD || !la.Info.PIDIVMatches) { continue; } } if (Method == PIDType.Channel && shiny != pk.IsShiny) { continue; } break; } while (++count < 10_000_000); }
/// <summary> /// Gets a legal <see cref="PKM"/> from a random in-game encounter's data. /// </summary> /// <param name="blank">Template data that will have its properties modified</param> /// <param name="tr">Trainer Data to use in generating the encounter</param> /// <param name="species">Species ID to generate</param> /// <returns>Result legal pkm, null if data should be ignored.</returns> private static PKM?GetRandomEncounter(PKM blank, ITrainerInfo tr, int species) { blank.Species = species; blank.Gender = blank.GetSaneGender(); if (species is ((int)Species.Meowstic)or((int)Species.Indeedee)) { blank.Form = blank.Gender; } var legalencs = EncounterMovesetGenerator.GeneratePKMs(blank, tr).Where(z => new LegalityAnalysis(z).Valid); var firstenc = legalencs.FirstOrDefault(); if (firstenc == null) { return(null); } var f = PKMConverter.ConvertToType(firstenc, blank.GetType(), out _); if (f == null) { var template = PKMConverter.GetBlank(tr.Generation, (GameVersion)tr.Game); var set = new ShowdownSet(new ShowdownSet(blank).Text.Split('\r')[0]); template.ApplySetDetails(set); var success = tr.TryAPIConvert(set, template, out PKM pk); return(success == LegalizationResult.Regenerated ? pk : null); } var an = f.AbilityNumber; f.Species = species; f.Gender = f.GetSaneGender(); if (species is ((int)Species.Meowstic)or((int)Species.Indeedee)) { f.Form = f.Gender; } f.CurrentLevel = 100; f.Nickname = SpeciesName.GetSpeciesNameGeneration(f.Species, f.Language, f.Format); f.IsNicknamed = false; f.SetSuggestedMoves(); f.SetSuggestedMovePP(0); f.SetSuggestedMovePP(1); f.SetSuggestedMovePP(2); f.SetSuggestedMovePP(3); f.RefreshAbility(an >> 1); var info = new LegalityAnalysis(f).Info; if (info.Generation > 0 && info.EvoChainsAllGens[info.Generation].All(z => z.Species != info.EncounterMatch.Species)) { f.CurrentHandler = 1; f.HT_Name = f.OT_Name; if (f is IHandlerLanguage h) { h.HT_Language = 1; } } if (f is IFormArgument fa) { fa.FormArgument = ShowdownEdits.GetSuggestedFormArgument(f, info.EncounterMatch.Species); } int wIndex = WurmpleUtil.GetWurmpleEvoGroup(f.Species); if (wIndex != -1) { f.EncryptionConstant = WurmpleUtil.GetWurmpleEncryptionConstant(wIndex); } if (f is IHomeTrack { Tracker : 0 } ht&& APILegality.SetRandomTracker) { ht.Tracker = APILegality.GetRandomULong(); } if (new LegalityAnalysis(f).Valid) { return(f); } // local name clashes! { var template = PKMConverter.GetBlank(tr.Generation, (GameVersion)tr.Game); var set = new ShowdownSet(new ShowdownSet(blank).Text.Split('\r')[0]); template.ApplySetDetails(set); var success = tr.TryAPIConvert(set, template, out PKM pk); return(success == LegalizationResult.Regenerated ? pk : null); } }
// Helper functions for commands public static bool AddToWaitingList(string setstring, string display, string username, ulong mUserId, bool sub, out string msg) { if (!TwitchBot <T> .Info.GetCanQueue()) { msg = "Sorry, I am not currently accepting queue requests!"; return(false); } var set = ShowdownUtil.ConvertToShowdown(setstring); if (set == null) { msg = $"Skipping trade, @{username}: Empty nickname provided for the species."; return(false); } var template = AutoLegalityWrapper.GetTemplate(set); if (template.Species < 1) { msg = $"Skipping trade, @{username}: Please read what you are supposed to type as the command argument."; return(false); } if (set.InvalidLines.Count != 0) { msg = $"Skipping trade, @{username}: Unable to parse Showdown Set:\n{string.Join("\n", set.InvalidLines)}"; return(false); } try { var sav = AutoLegalityWrapper.GetTrainerInfo <T>(); PKM pkm = sav.GetLegal(template, out var result); var nickname = pkm.Nickname.ToLower(); if (nickname == "egg" && Breeding.CanHatchAsEgg(pkm.Species)) { TradeExtensions <T> .EggTrade(pkm); } if (pkm.Species == 132 && (nickname.Contains("atk") || nickname.Contains("spa") || nickname.Contains("spe") || nickname.Contains("6iv"))) { TradeExtensions <T> .DittoTrade(pkm); } if (!pkm.CanBeTraded()) { msg = $"Skipping trade, @{username}: Provided Pokémon content is blocked from trading!"; return(false); } if (pkm is T pk) { var valid = new LegalityAnalysis(pkm).Valid; if (valid) { var tq = new TwitchQueue <T>(pk, new PokeTradeTrainerInfo(display, mUserId), username, sub); TwitchBot <T> .QueuePool.RemoveAll(z => z.UserName == username); // remove old requests if any TwitchBot <T> .QueuePool.Add(tq); msg = $"@{username} - added to the waiting list. Please whisper your trade code to me! Your request from the waiting list will be removed if you are too slow!"; return(true); } } var reason = result == "Timeout" ? "Set took too long to generate." : "Unable to legalize the Pokémon."; msg = $"Skipping trade, @{username}: {reason}"; } #pragma warning disable CA1031 // Do not catch general exception types catch (Exception ex) #pragma warning restore CA1031 // Do not catch general exception types { LogUtil.LogSafe(ex, nameof(TwitchCommandsHelper <T>)); msg = $"Skipping trade, @{username}: An unexpected problem occurred."; } return(false); }