public dynamic CheckLegality([FromForm][Required] IFormFile pokemon, [FromForm] string generation, bool bot) { using var memoryStream = new MemoryStream(); pokemon.CopyTo(memoryStream); PKM pkm; byte[] data = memoryStream.ToArray(); try { if (string.IsNullOrEmpty(generation)) { pkm = PKMConverter.GetPKMfromBytes(data); if (pkm == null) { throw new System.ArgumentException("Bad data!"); } generation = Utils.GetGeneration(pkm); } else { pkm = Utils.GetPKMwithGen(generation, data); if (pkm == null) { throw new System.ArgumentException("Bad generation!"); } } } catch { Response.StatusCode = 400; return("Bad Data Was Provided"); } if (!Utils.PokemonExistsInGeneration(generation, pkm.Species)) { Response.StatusCode = 400; return("Pokemon not in generation!"); } var la = new LegalityAnalysis(pkm); if (bot) { return(la.Report()); } return(new { report = la.Report().Replace("\r", string.Empty).Split('\n'), legal = la.Valid }); }
/// <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="ShowdownSet"/>.</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 satisfactory, otherwise use deprecated bruteforce auto legality functionality</param> public static PKM GetLegalFromTemplate(this ITrainerInfo dest, PKM template, ShowdownSet set, out bool satisfied) { set = set.PreProcessShowdownSet(); var Form = SanityCheckForm(template, ref set); template.ApplySetDetails(set); template.SetRecordFlags(); // Validate TR moves for the encounter 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(); EncounterMovesetGenerator.PriorityList = new[] { EncounterOrder.Egg, EncounterOrder.Static, EncounterOrder.Trade, EncounterOrder.Slot, EncounterOrder.Mystery }; var encounters = EncounterMovesetGenerator.GenerateEncounters(pk: template, moves: set.Moves, gamelist); if (template.Species <= 721) { encounters = encounters.Concat(GetFriendSafariEncounters(template)); } foreach (var enc in encounters) { var ver = enc is IVersion v ? v.Version : destVer; var gen = enc is IGeneration g ? g.Generation : dest.Generation; var tr = UseTrainerData ? TrainerSettings.GetSavedTrainerData(ver, gen) : TrainerSettings.DefaultFallback(gen); var raw = SanityCheckEncounters(enc).ConvertToPKM(tr); if (raw.IsEgg) // PGF events are sometimes eggs. Force hatch them before proceeding { raw.HandleEggEncounters(enc, tr); } var pk = PKMConverter.ConvertToType(raw, destType, out _); if (pk == null) { continue; } ApplySetDetails(pk, set, Form, raw, dest, enc); if (set.CanGigantamax && pk is IGigantamax gmax) { if (!gmax.CanGigantamax) { continue; } } var la = new LegalityAnalysis(pk); if (la.Valid) { satisfied = true; return(pk); } Debug.WriteLine(la.Report()); } satisfied = false; return(template); }
/// <summary> /// Set a valid Pokeball based on a legality check's suggestions. /// </summary> /// <param name="pk">Pokémon to modify</param> /// <param name="matching">Set matching ball</param> public static void SetSuggestedBall(this PKM pk, bool matching = true) { if (matching) { if (!pk.IsShiny) { pk.SetMatchingBall(); } else { Aesthetics.ApplyShinyBall(pk); } } var la = new LegalityAnalysis(pk); var report = la.Report(); if (!report.Contains(LegalityCheckStrings.LBallEncMismatch)) { return; } if (pk.GenNumber == 5 && pk.Met_Location == 75) { pk.Ball = (int)Ball.Dream; } else { pk.Ball = 4; } }
private async Task LegalityCheck(IAttachment att, bool verbose) { var download = await NetUtil.DownloadPKMAsync(att).ConfigureAwait(false); if (!download.Success) { await ReplyAsync(download.ErrorMessage).ConfigureAwait(false); return; } var pkm = download.Data !; var la = new LegalityAnalysis(pkm); var builder = new EmbedBuilder { Color = la.Valid ? Color.Green : Color.Red, Description = $"Legality Report for {download.SanitizedFileName}:" }; builder.AddField(x => { x.Name = la.Valid ? "Valid" : "Invalid"; x.Value = la.Report(verbose); x.IsInline = false; }); await ReplyAsync("Here's the legality report!", false, builder.Build()).ConfigureAwait(false); }
private static void Main(string[] args) { var pk = CreatePKMfromArgs(args); if (args.Contains(RequestLegalityCheck)) { var lc = new LegalityAnalysis(pk); var verbose = args.Contains("--verbose"); Console.WriteLine(lc.Report(verbose)); } if (!args.Contains(RequestLegalization)) { return; } if (!args.Contains("--version")) { Console.WriteLine("Specify version with the [--version] tag"); return; } var ver = GetArgVal(args, "--version"); pk = ConsoleLegalizer.GetLegalPKM(pk, ver); var outPath = GetOutputPath(args, pk); File.WriteAllBytes(outPath, pk.DecryptedBoxData); }
/// <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="ShowdownSet"/>.</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 satisfactory, otherwise use current auto legality functionality</param> public static PKM GetLegalFromTemplate(this ITrainerInfo dest, PKM template, ShowdownSet set, out bool satisfied) { var Form = SanityCheckForm(template, ref set); template.ApplySetDetails(set); var destType = template.GetType(); var destVer = (GameVersion)dest.Game; if (destVer <= 0 && dest is SaveFile s) { destVer = s.Version; } var encounters = EncounterMovesetGenerator.GenerateEncounters(pk: template, moves: set.Moves); foreach (var enc in encounters) { var ver = enc is IVersion v ? v.Version : destVer; var gen = enc is IGeneration g ? g.Generation : dest.Generation; var tr = TrainerSettings.GetSavedTrainerData(ver, gen); var raw = enc.ConvertToPKM(tr); var pk = PKMConverter.ConvertToType(raw, destType, out _); ApplySetDetails(pk, set, Form, raw, dest); var la = new LegalityAnalysis(pk); if (la.Valid) { satisfied = true; return(pk); } Debug.WriteLine(la.Report()); } satisfied = false; return(template); }
public string Post() { if (Request.ContentType != "application/octet-stream") { return(string.Empty); } if (Request.Body.Length == 0) { return(string.Empty); } var ver = Request.Headers["Version"]; if (string.IsNullOrWhiteSpace(ver)) { return(string.Empty); } var data = new byte[Request.Body.Length]; using (var ms = new MemoryStream(data)) Request.Body.CopyTo(ms); try { var pk = PKMConverter.GetPKMfromBytes(data); var la = new LegalityAnalysis(pk); return(la.Report()); } catch (Exception ex) { Console.WriteLine(ex.Message); return(string.Empty); } }
private async Task <PokeTradeResult> ProcessGiveawayUploadAsync(PokeTradeDetail <PK8> detail, CancellationToken token) { int ctr = 0; var time = TimeSpan.FromSeconds(Hub.Config.Trade.MaxDumpTradeTime); var start = DateTime.Now; var pkprev = new PK8(); var poolEntry = detail.PoolEntry; while (ctr < 1 && DateTime.Now - start < time) { var pk = await ReadUntilPresent(LinkTradePartnerPokemonOffset, 3_000, 1_000, token).ConfigureAwait(false); if (pk == null || pk.Species < 1 || !pk.ChecksumValid || SearchUtil.HashByDetails(pk) == SearchUtil.HashByDetails(pkprev)) { continue; } // Save the new Pokémon for comparison next round. pkprev = pk; poolEntry.PK8 = pk; poolEntry.Pokemon = SpeciesName.GetSpeciesName(pk.Species, 2); if (Hub.Config.Legality.VerifyLegality) { LogUtil.LogInfo($"Performing legality check on {poolEntry.Pokemon}", "PokeTradeBot.GiveawayUpload"); var la = new LegalityAnalysis(poolEntry.PK8); var verbose = la.Report(true); LogUtil.LogInfo($"Shown Pokémon is {(la.Valid ? "Valid" : "Invalid")}.", "PokeTradeBot.GiveawayUpload"); detail.SendNotification(this, pk, $"Pokémon sent is {(la.Valid ? "Valid" : "Invalid")}."); detail.SendNotification(this, pk, verbose); if (!la.Valid) { detail.SendNotification(this, pk, $"Show a different pokemon to continue or exit the trade to end."); continue; } } LogUtil.LogInfo("Creating new database entry", "PokeTradeBot.GiveawayUpload"); Hub.GiveawayPoolDatabase.NewEntry(poolEntry); if (Hub.Config.Discord.ReturnPK8s) { detail.SendNotification(this, pk, "Here's what you showed me!"); } ctr++; } LogUtil.LogInfo($"Ended Giveaway pool upload", "PokeTradeBot.GiveawayUpload"); await ExitSeedCheckTrade(Hub.Config, token).ConfigureAwait(false); if (ctr == 0) { return(PokeTradeResult.TrainerTooSlow); } detail.Notifier.SendNotification(this, detail, $"Finished uploading Pokémon to the Giveaway Pool."); detail.Notifier.TradeFinished(this, detail, detail.TradeData); // blank pk8 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 satisfactory, otherwise use deprecated bruteforce auto legality functionality</param> public static PKM GetLegalFromTemplate(this ITrainerInfo dest, PKM template, IBattleTemplate set, out bool satisfied) { if (set is RegenTemplate t) { t.FixGender(template.PersonalInfo); } 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(); var encounters = EncounterMovesetGenerator.GenerateEncounters(pk: template, moves: set.Moves, gamelist); encounters = encounters.Concat(GetFriendSafariEncounters(template)); foreach (var enc in encounters) { if (!IsEncounterValid(set, enc, isHidden, destVer, out var ver)) { continue; } var tr = UseTrainerData ? TrainerSettings.GetSavedTrainerData(ver, enc.Generation) : TrainerSettings.DefaultFallback(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); } var pk = PKMConverter.ConvertToType(raw, destType, out _); if (pk == null) { continue; } ApplySetDetails(pk, set, raw, dest, enc); if (pk is IGigantamax gmax && gmax.CanGigantamax != set.CanGigantamax) { continue; } var la = new LegalityAnalysis(pk); if (la.Valid) { satisfied = true; return(pk); } Debug.WriteLine($"{la.Report()}\n"); } satisfied = false; return(template); }
private async Task <PokeTradeResult> ProcessDumpTradeAsync(PokeTradeDetail <PB8> detail, CancellationToken token) { int ctr = 0; var time = TimeSpan.FromSeconds(Hub.Config.Trade.MaxDumpTradeTime); var start = DateTime.Now; while (ctr < Hub.Config.Trade.MaxDumpsPerTrade && DateTime.Now - start < time) { // Wait for user input... Needs to be different from the previously offered Pokémon. var tradeOffered = await ReadUntilChanged(LinkTradePokemonOffset, lastOffered, 3_000, 1_000, false, true, token).ConfigureAwait(false); if (!tradeOffered) { continue; } // If we detected a change, they offered something. var pk = await ReadPokemon(LinkTradePokemonOffset, BoxFormatSlotSize, token).ConfigureAwait(false); var newEC = await SwitchConnection.ReadBytesAbsoluteAsync(LinkTradePokemonOffset, 8, token).ConfigureAwait(false); if (pk == null || pk.Species < 1 || !pk.ChecksumValid || lastOffered == newEC) { continue; } lastOffered = newEC; // Send results from separate thread; the bot doesn't need to wait for things to be calculated. if (DumpSetting.Dump) { var subfolder = detail.Type.ToString().ToLower(); DumpPokemon(DumpSetting.DumpFolder, subfolder, pk); // received } var la = new LegalityAnalysis(pk); var verbose = la.Report(true); Log($"Shown Pokémon is: {(la.Valid ? "Valid" : "Invalid")}."); detail.SendNotification(this, pk, verbose); ctr++; } Log($"Ended Dump loop after processing {ctr} Pokémon."); if (ctr == 0) { return(PokeTradeResult.TrainerTooSlow); } TradeSettings.AddCompletedDumps(); detail.Notifier.SendNotification(this, detail, $"Dumped {ctr} Pokémon."); detail.Notifier.TradeFinished(this, detail, detail.TradeData); // blank pk8 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="ShowdownSet"/>.</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 satisfactory, otherwise use deprecated bruteforce auto legality functionality</param> public static PKM GetLegalFromTemplate(this ITrainerInfo dest, PKM template, ShowdownSet set, out bool satisfied) { var Form = SanityCheckForm(template, ref set); template.ApplySetDetails(set); template.SetRecordFlags(); // Validate TR moves for the encounter 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(); var encounters = EncounterMovesetGenerator.GenerateEncounters(pk: template, moves: set.Moves, gamelist); foreach (var enc in encounters) { var ver = enc is IVersion v ? v.Version : destVer; var gen = enc is IGeneration g ? g.Generation : dest.Generation; ITrainerInfo tr = new SimpleTrainerInfo(ver); if (UseTrainerData) { tr = TrainerSettings.GetSavedTrainerData(ver, gen, new SimpleTrainerInfo(ver)); } var raw = SanityCheckEncounters(enc).ConvertToPKM(tr); var pk = PKMConverter.ConvertToType(raw, destType, out _); if (pk == null) { continue; } ApplySetDetails(pk, set, Form, raw, dest, enc); if (set.CanGigantamax && pk is IGigantamax gmax) { if (!gmax.CanGigantamax) { continue; } } var la = new LegalityAnalysis(pk); if (la.Valid) { satisfied = true; return(pk); } Debug.WriteLine(la.Report()); } satisfied = false; return(template); }
public static void CheckAndSetFateful(PKM pk) { LegalityAnalysis la = new LegalityAnalysis(pk); string Report = la.Report(); if (Report.Contains(LFatefulMysteryMissing) || Report.Contains(LFatefulMissing)) { pk.FatefulEncounter = true; } if (Report.Contains(LFatefulInvalid)) { pk.FatefulEncounter = false; } }
private async Task <PokeTradeResult> ProcessDumpTradeAsync(PokeTradeDetail <PK8> detail, CancellationToken token) { int ctr = 0; var time = TimeSpan.FromSeconds(Hub.Config.Trade.MaxDumpTradeTime); var start = DateTime.Now; while (ctr < Hub.Config.Trade.MaxDumpsPerTrade && DateTime.Now - start < time) { bool found = await WaitForPokemonChanged(LinkTradePartnerPokemonOffset, 15_000, 1_000, token); if (!found) { continue; } var pk = await ReadUntilPresent(LinkTradePartnerPokemonOffset, 3_000, 1_000, token).ConfigureAwait(false); if (pk == null || pk.Species < 1 || !pk.ChecksumValid) { continue; } // Send results from separate thread; the bot doesn't need to wait for things to be calculated. if (DumpSetting.Dump) { var subfolder = detail.Type.ToString().ToLower(); DumpPokemon(DumpSetting.DumpFolder, subfolder, pk); // received } var la = new LegalityAnalysis(pk); var verbose = la.Report(true); Log($"Shown Pokémon is {(la.Valid ? "Valid" : "Invalid")}."); detail.SendNotification(this, pk, verbose); ctr++; } Log($"Ended Dump loop after processing {ctr} Pokémon"); await ExitSeedCheckTrade(Hub.Config, token).ConfigureAwait(false); if (ctr == 0) { return(PokeTradeResult.TrainerTooSlow); } Hub.Counts.AddCompletedDumps(); detail.Notifier.SendNotification(this, detail, $"Dumped {ctr} Pokémon."); detail.Notifier.TradeFinished(this, detail, detail.TradeData); // blank pk8 return(PokeTradeResult.Success); }
public static void CheckAndSetFateful(PKM pk) { LegalityAnalysis la = new LegalityAnalysis(pk); string Report = la.Report(); if (Report.Contains(V322) || Report.Contains(V324)) { pk.FatefulEncounter = true; } if (Report.Contains(V325)) { pk.FatefulEncounter = false; } }
/// <summary> /// Quick Gender Toggle /// </summary> /// <param name="pk">PKM whose gender needs to be toggled</param> /// <param name="set">Showdown Set for Gender reference</param> public static void FixGender(this PKM pk, ShowdownSet set) { pk.SetGender(set.Gender); var la = new LegalityAnalysis(pk); string Report = la.Report(); if (Report.Contains(LegalityCheckStrings.LPIDGenderMismatch)) { pk.Gender = pk.Gender == 0 ? 1 : 0; } if (pk.Gender != 0 && pk.Gender != 1) { pk.Gender = pk.GetSaneGender(); } }
public void SendNotification(PokeRoutineExecutor routine, PokeTradeDetail <T> info, LegalityAnalysis la) { var builder = new EmbedBuilder { Color = la.Valid ? Color.Green : Color.Red, Description = $"Legality Report for {info.TradeData.Species}:" }; builder.AddField(x => { x.Name = la.Valid ? "Valid" : "Invalid"; x.Value = la.Report(true); x.IsInline = false; }); LogUtil.LogInfo("We're running the LC!", "Discord"); Trader.SendMessageAsync(embed: builder.Build()).ConfigureAwait(false); }
/// <summary> /// Set a valid Pokeball based on a legality check's suggestions. /// </summary> /// <param name="pk">Pokémon to modify</param> public static void SetSuggestedBall(this PKM pk) { var la = new LegalityAnalysis(pk); var report = la.Report(); if (!report.Contains(LegalityCheckStrings.LBallEncMismatch)) { return; } if (pk.GenNumber == 5 && pk.Met_Location == 75) { pk.Ball = (int)Ball.Dream; } else { pk.Ball = 4; } }
private static PKM M2EventFix(PKM pk, bool shiny) { int eggloc = pk.Egg_Location; bool feFlag = pk.FatefulEncounter; pk.Egg_Location = 0; pk.FatefulEncounter = true; string[] NatureHPIVs = IVtoPIDGenerator.GetIVPID((uint)pk.Nature, pk.HPType, false, IVPIDMethod.M2); pk.PID = Util.GetHexValue(NatureHPIVs[0]); if (pk.GenNumber < 5) { pk.EncryptionConstant = pk.PID; } pk.IV_HP = Convert.ToInt32(NatureHPIVs[1]); pk.IV_ATK = Convert.ToInt32(NatureHPIVs[2]); pk.IV_DEF = Convert.ToInt32(NatureHPIVs[3]); pk.IV_SPA = Convert.ToInt32(NatureHPIVs[4]); pk.IV_SPD = Convert.ToInt32(NatureHPIVs[5]); pk.IV_SPE = Convert.ToInt32(NatureHPIVs[6]); if (shiny) { pk.SetShinySID(); } var recheckLA = new LegalityAnalysis(pk); string 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(LPIDTypeMismatch) || UsesEventBasedMethod(pk.Species, pk.Moves, PIDType.Method_2)) { return(pk); } Debug.WriteLine(GetReport(pk)); pk.FatefulEncounter = feFlag; pk.Egg_Location = eggloc; return(pk); }
private PKM Legalize(PKM pk, GameVersion ver) { Report = la.Report(); var sav = SaveUtil.GetBlankSAV(ver, pk.OT_Name); sav.TID = pk.TID; sav.SID = pk.SID; sav.Language = pk.Language; PKM upd = sav.Legalize(pk.Clone()); upd.SetTrainerData(GetTrainerInfo(pk, ver)); la = new LegalityAnalysis(upd); if (la.Valid) { legalpk = upd; Successful = true; return(legalpk); } return(null); }
private PKM ProcessALM(PKM pkm, CancellationTokenSource cts, GameVersion ver = GameVersion.GP) { la = new LegalityAnalysis(pkm); if (la.Valid) { legalpk = pkm; Ran = false; Report = la.Report(); cts.Cancel(); return(legalpk); } Task.Run(() => { var thread = Thread.CurrentThread.ManagedThreadId; Console.WriteLine($"Legalization on Thread ({thread}) has started at: {DateTime.Now:F}"); legalpk = Legalize(pkm, ver); Console.WriteLine($"Legalization on Thread ({thread}) has finished at: {DateTime.Now:F}"); cts.Cancel(); }, cts.Token); return(legalpk); }
/// <summary> /// Quick Gender Toggle /// </summary> /// <param name="pk">PKM whose gender needs to be toggled</param> /// <param name="set">Showdown Set for Gender reference</param> public static void FixGender(this PKM pk, IBattleTemplate set) { pk.ApplySetGender(set); var la = new LegalityAnalysis(pk); if (la.Valid) { return; } string Report = la.Report(); if (Report.Contains(LegalityCheckStrings.LPIDGenderMismatch)) { pk.Gender = pk.Gender == 0 ? 1 : 0; } if (pk.Gender != 0 && pk.Gender != 1) { pk.Gender = pk.GetSaneGender(); } }
private void UpdateLegality(PKM pkm, bool skipMoveRepop = false) { LegalityAnalysis Legality = new LegalityAnalysis(pkm); if (debug) { Console.WriteLine(Legality.Report(true)); } // Refresh Move Legality bool[] validmoves = new bool[] { false, false, false, false }; for (int i = 0; i < 4; i++) { validmoves[i] = !Legality.Info?.Moves[i].Valid ?? false; } bool[] validrelearn = new bool[] { false, false, false, false }; if (pkm.Format >= 6) { for (int i = 0; i < 4; i++) { validrelearn[i] = !Legality.Info?.Relearn[i].Valid ?? false; } } if (skipMoveRepop) { return; } // Resort moves bool fieldsLoaded = true; bool tmp = fieldsLoaded; fieldsLoaded = false; var cb = new[] { pkm.Move1, pkm.Move2, pkm.Move3, pkm.Move4 }; var moves = Legality.AllSuggestedMovesAndRelearn; var moveList = GameInfo.MoveDataSource.OrderByDescending(m => moves.Contains(m.Value)).ToArray(); fieldsLoaded |= tmp; LegalityChanged?.Invoke(Legality.Valid, null); }
private async Task LegalityCheck(IAttachment att, bool verbose) { if (!PKX.IsPKM(att.Size)) { await ReplyAsync($"{att.Filename}: Invalid size.").ConfigureAwait(false); return; } string url = att.Url; // Download the resource and load the bytes into a buffer. byte[] buffer = await webClient.DownloadDataTaskAsync(url).ConfigureAwait(false); var pkm = PKMConverter.GetPKMfromBytes(buffer); if (pkm == null) { await ReplyAsync($"{att.Filename}: Invalid pkm attachment.").ConfigureAwait(false); return; } var la = new LegalityAnalysis(pkm); var builder = new EmbedBuilder { Color = la.Valid ? Color.Green : Color.Red, Description = $"Legality Report for {att.Filename}:" }; builder.AddField(x => { x.Name = la.Valid ? "Valid" : "Invalid"; x.Value = la.Report(verbose); x.IsInline = false; }); await ReplyAsync("Here's the legality report!", false, builder.Build()).ConfigureAwait(false); }
public static PKM Legalize(PKM pk, GameVersion ver, LegalityAnalysis old = null) { if (old != null) { Debug.WriteLine(old.Report()); } var sav = SaveUtil.GetBlankSAV(ver, "PKHeX"); var updated = sav.Legalize(pk); var la = new LegalityAnalysis(updated); if (!la.Valid) { return(pk); } Console.WriteLine("===================================="); Console.WriteLine("= Legalized with Auto Legality Mod ="); Console.WriteLine("===================================="); Console.WriteLine(la.Report(true)); return(updated); }
/// <summary> /// Quick Gender Toggle /// </summary> /// <param name="pk">PKM whose gender needs to be toggled</param> /// <param name="SSet">Showdown Set for Gender reference</param> public static void FixGender(PKM pk, ShowdownSet SSet) { pk.SetGender(SSet.Gender); LegalityAnalysis la = new LegalityAnalysis(pk); string Report = la.Report(); if (Report.Contains(V255)) { if (pk.Gender == 0) { pk.Gender = 1; } else { pk.Gender = 0; } } if (pk.Gender != 0 && pk.Gender != 1) { pk.Gender = pk.GetSaneGender(); } }
/// <summary> /// Set a valid Pokeball based on a legality check's suggestions. /// </summary> /// <param name="pk">Pokémon to modify</param> /// <param name="matching">Set matching ball</param> /// <param name="force"></param> /// <param name="ball"></param> public static void SetSuggestedBall(this PKM pk, bool matching = true, bool force = false, Ball ball = Ball.None) { if (ball != Ball.None) { var orig = pk.Ball; pk.Ball = (int)ball; if (!force && !pk.ValidBall()) { pk.Ball = orig; } } else if (matching) { if (!pk.IsShiny) { pk.SetMatchingBall(); } else { Aesthetics.ApplyShinyBall(pk); } } var la = new LegalityAnalysis(pk); var report = la.Report(); if (!report.Contains(LegalityCheckStrings.LBallEncMismatch) || force) { return; } if (pk.Generation == 5 && pk.Met_Location == 75) { pk.Ball = (int)Ball.Dream; } else { pk.Ball = 4; } }
private bool IsLegal(PK8 pk, PokeTradeDetail <PK8> poke) { var la = new LegalityAnalysis(pk); if (!la.Valid && Hub.Config.Legality.VerifyLegality) { Log($"Clone request has detected an invalid Pokémon: {(Species)pk.Species}"); if (DumpSetting.Dump) { DumpPokemon(DumpSetting.DumpFolder, "hacked", pk); } 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(false); } else { return(true); } }
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); } }
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> /// <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); }