Ejemplo n.º 1
0
        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();
        }
Ejemplo n.º 2
0
 /// <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);
Ejemplo n.º 3
0
        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);
            }
        }
Ejemplo n.º 4
0
    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));
        }
    }
Ejemplo n.º 5
0
 /// <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);
     }
Ejemplo n.º 6
0
        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);
        }
Ejemplo n.º 7
0
 public override void Verify(LegalityAnalysis data)
 {
     VerifyMedalsRegular(data);
     VerifyMedalsEvent(data);
 }
Ejemplo n.º 8
0
        private static string GetReport(PKM pk)
        {
            var la = new LegalityAnalysis(pk);

            return(la.Report());
        }
Ejemplo n.º 9
0
        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();
            }
        }
Ejemplo n.º 10
0
        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);
        }
Ejemplo n.º 11
0
        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);
        }
Ejemplo n.º 12
0
        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);
        }
Ejemplo n.º 13
0
    /// <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
        })
Ejemplo n.º 14
0
        /// <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);
        }
Ejemplo n.º 15
0
        // 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);
        }
Ejemplo n.º 16
0
    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));
        }
    }
Ejemplo n.º 17
0
        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);
        }
Ejemplo n.º 18
0
        public static int GetSuggestedCatchRate(PK1 pk1, SaveFile sav)
        {
            var la = new LegalityAnalysis(pk1);

            return(GetSuggestedCatchRate(pk1, sav, la));
        }
Ejemplo n.º 19
0
        /// <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);
        }
Ejemplo n.º 20
0
        public static bool ValidBall(this PKM pk)
        {
            var rep = new LegalityAnalysis(pk).Report(true);

            return(rep.Contains(LegalityCheckStrings.LBallEnc) || rep.Contains(LegalityCheckStrings.LBallSpeciesPass));
        }
Ejemplo n.º 21
0
    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));
        }
    }
Ejemplo n.º 22
0
    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)));
            }
        }
    }
Ejemplo n.º 23
0
        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);
        }
Ejemplo n.º 24
0
 public void SendNotification(PokeRoutineExecutor routine, LegalityAnalysis la) => Notifier.SendNotification(routine, this, la);
Ejemplo n.º 25
0
        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);
        }
Ejemplo n.º 26
0
        /// <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);
        }
Ejemplo n.º 27
0
 public static string GetVerboseLegalityReport(LegalityAnalysis la) => Formatter.GetReportVerbose(la);
Ejemplo n.º 28
0
        /// <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);
        }
Ejemplo n.º 29
0
        /// <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);
            }
        }
Ejemplo n.º 30
0
        // 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);
        }