Exemplo n.º 1
0
        private CheckResult VerifyForm(LegalityAnalysis data)
        {
            var pkm          = data.pkm;
            var PersonalInfo = data.PersonalInfo;

            int count = PersonalInfo.FormCount;
            var form  = pkm.Form;

            if (count <= 1 && form == 0)
            {
                return(VALID); // no forms to check
            }
            var species = pkm.Species;
            var enc     = data.EncounterMatch;
            var Info    = data.Info;

            if (!PersonalInfo.IsFormWithinRange(form) && !FormInfo.IsValidOutOfBoundsForm(species, form, Info.Generation))
            {
                return(GetInvalid(string.Format(LFormInvalidRange, count - 1, form)));
            }

            switch (enc)
            {
            case EncounterSlot w when w.Area.Type == SlotType.FriendSafari:
                VerifyFormFriendSafari(data);
                break;

            case EncounterEgg e when FormInfo.IsTotemForm(species, form, e.Generation):
                return(GetInvalid(LFormInvalidGame));
            }

            switch ((Species)species)
            {
            case Pikachu when Info.Generation == 6:     // Cosplay
                bool isStatic     = enc is EncounterStatic;
                bool validCosplay = form == (isStatic ? enc.Form : 0);
                if (!validCosplay)
                {
                    return(GetInvalid(isStatic ? LFormPikachuCosplayInvalid : LFormPikachuCosplay));
                }
                break;

            case Pikachu when Info.Generation >= 7:     // Cap
                bool validCap = form == (enc is EncounterInvalid or EncounterEgg ? 0 : enc.Form);
                if (!validCap)
                {
                    bool gift = enc is MysteryGift g && g.Form != form;
                    var  msg  = gift ? LFormPikachuEventInvalid : LFormInvalidGame;
                    return(GetInvalid(msg));
                }
                break;

            case Unown when Info.Generation == 2 && form >= 26:
                return(GetInvalid(string.Format(LFormInvalidRange, "Z", form == 26 ? "!" : "?")));

            case Giratina when form == 1 ^ pkm.HeldItem == 112:     // Giratina, Origin form only with Griseous Orb
                return(GetInvalid(LFormItemInvalid));

            case Arceus:
            {
                int arceus = GetArceusFormFromHeldItem(pkm.HeldItem, pkm.Format);
                return(arceus != form?GetInvalid(LFormItemInvalid) : GetValid(LFormItem));
            }

            case Keldeo when pkm.Format < 8 && enc.Generation != 5:
                // can mismatch in gen5 via BW tutor and transfer up
                // can mismatch in gen8+ as the form activates in battle when knowing the move; outside of battle can be either state.
                bool hasSword = pkm.HasMove((int)Move.SecretSword);
                bool isSword  = pkm.Form == 1;
                if (isSword != hasSword)
                {
                    return(GetInvalid(LMoveKeldeoMismatch));
                }
                break;

            case Genesect:
            {
                int genesect = GetGenesectFormFromHeldItem(pkm.HeldItem);
                return(genesect != form?GetInvalid(LFormItemInvalid) : GetValid(LFormItem));
            }

            case Greninja:
                if (form > 1)     // Ash Battle Bond active
                {
                    return(GetInvalid(LFormBattle));
                }
                if (form != 0 && enc is not MysteryGift)     // Formes are not breedable, MysteryGift already checked
                {
                    return(GetInvalid(string.Format(LFormInvalidRange, 0, form)));
                }
                break;

            case Scatterbug or Spewpa:
                if (form > 17)     // Fancy & Pokéball
                {
                    return(GetInvalid(LFormVivillonEventPre));
                }
                if (pkm is not IRegionOrigin tr)
                {
                    break;
                }
                if (!Vivillon3DS.IsPatternValid(form, (byte)tr.Country, (byte)tr.Region))
                {
                    data.AddLine(Get(LFormVivillonInvalid, Severity.Fishy));
                }
                break;

            case Vivillon:
                if (form > 17)     // Fancy & Pokéball
                {
                    if (enc is not MysteryGift)
                    {
                        return(GetInvalid(LFormVivillonInvalid));
                    }
                    return(GetValid(LFormVivillon));
                }
                if (pkm is not IRegionOrigin trv)
                {
                    break;
                }
                if (!Vivillon3DS.IsPatternValid(form, (byte)trv.Country, (byte)trv.Region))
                {
                    data.AddLine(Get(LFormVivillonInvalid, Severity.Fishy));
                }
                break;

            case Floette when form == 5:     // Floette Eternal Flower -- Never Released
                if (enc is not MysteryGift)
                {
                    return(GetInvalid(LFormEternalInvalid));
                }
                return(GetValid(LFormEternal));

            case Meowstic when form != pkm.Gender:
                return(GetInvalid(LGenderInvalidNone));

            case Silvally:
            {
                int silvally = GetSilvallyFormFromHeldItem(pkm.HeldItem);
                return(silvally != form?GetInvalid(LFormItemInvalid) : GetValid(LFormItem));
            }

            // Form doesn't exist in SM; cannot originate from that game.
            case Lillipup when enc.Generation == 7 && form == 1 && pkm.SM:
            case Lycanroc when enc.Generation == 7 && form == 2 && pkm.SM:
                return(GetInvalid(LFormInvalidGame));

            // Toxel encounters have already been checked for the nature-specific evolution criteria.
            case Toxtricity when enc.Species == (int)Toxtricity:
            {
                // The game enforces the Nature for Toxtricity encounters too!
                if (pkm.Form != EvolutionMethod.GetAmpLowKeyResult(pkm.Nature))
                {
                    return(GetInvalid(LFormInvalidNature));
                }
                break;
            }

            // Impossible Egg forms
            case Rotom when pkm.IsEgg && form != 0:
            case Furfrou when pkm.IsEgg && form != 0:
                return(GetInvalid(LEggSpecies));

            // Party Only Forms
            case Shaymin:
            case Furfrou:
            case Hoopa:
                if (form != 0 && pkm.Box > -1 && pkm.Format <= 6)     // has form but stored in box
                {
                    return(GetInvalid(LFormParty));
                }
                break;
            }

            var format = pkm.Format;

            if (FormInfo.IsBattleOnlyForm(species, form, format))
            {
                return(GetInvalid(LFormBattle));
            }

            if (form == 0)
            {
                return(VALID);
            }

            // everything below here is not Form 0, so it has a form.
            if (format >= 7 && Info.Generation < 7)
            {
                if (species == 25 || Legal.AlolanOriginForms.Contains(species) || Legal.AlolanVariantEvolutions12.Contains(enc.Species))
                {
                    return(GetInvalid(LFormInvalidGame));
                }
            }
            if (format >= 8 && Info.Generation < 8)
            {
                var orig = enc.Species;
                if (Legal.GalarOriginForms.Contains(species) || Legal.GalarVariantFormEvolutions.Contains(orig))
                {
                    if (species == (int)Meowth && enc.Form != 2)
                    {
                        // We're okay here. There's also Alolan Meowth...
                    }
                    else if (((Species)orig is MrMime or MimeJr) && pkm.CurrentLevel > enc.LevelMin && Info.Generation >= 4)
                    {
                        // We're okay with a Mime Jr. that has evolved via level up.
                    }
                    else if (enc.Version != GameVersion.GO)
                    {
                        return(GetInvalid(LFormInvalidGame));
                    }
                }
            }
Exemplo n.º 2
0
        public static IEnumerable <EncounterEgg> GenerateEggs(PKM pkm, IReadOnlyList <EvoCriteria> chain, int generation, bool all = false)
        {
            System.Diagnostics.Debug.Assert(generation >= 3); // if generating Gen2 eggs, use the other generator.
            int currentSpecies = pkm.Species;

            if (!Breeding.CanHatchAsEgg(currentSpecies))
            {
                yield break;
            }

            var currentForm = pkm.Form;

            if (!Breeding.CanHatchAsEgg(currentSpecies, currentForm, generation))
            {
                yield break; // can't originate from eggs
            }
            // version is a true indicator for all generation 3-5 origins
            var ver = (GameVersion)pkm.Version;

            if (!Breeding.CanGameGenerateEggs(ver))
            {
                yield break;
            }

            int lvl = EggStateLegality.GetEggLevel(generation);
            int max = GetMaxSpeciesOrigin(generation);

            var(species, form) = GetBaseSpecies(chain, 0);
            if ((uint)species <= max)
            {
                // NOTE: THE SPLIT-BREED SECTION OF CODE SHOULD BE EXACTLY THE SAME AS THE BELOW SECTION
                if (FormInfo.IsBattleOnlyForm(species, form, generation))
                {
                    form = FormInfo.GetOutOfBattleForm(species, form, generation);
                }
                if (Breeding.CanHatchAsEgg(species, form, ver))
                {
                    yield return(new EncounterEgg(species, form, lvl, generation, ver));

                    if (generation > 5 && (pkm.WasTradedEgg || all) && HasOtherGamePair(ver))
                    {
                        yield return(new EncounterEgg(species, form, lvl, generation, GetOtherTradePair(ver)));
                    }
                }
            }

            if (!Breeding.GetSplitBreedGeneration(generation).Contains(currentSpecies))
            {
                yield break; // no other possible species
            }
            var otherSplit = species;

            (species, form) = GetBaseSpecies(chain, 1);
            if ((uint)species == otherSplit)
            {
                yield break;
            }

            if (species <= max)
            {
                // NOTE: THIS SECTION OF CODE SHOULD BE EXACTLY THE SAME AS THE ABOVE SECTION
                if (FormInfo.IsBattleOnlyForm(species, form, generation))
                {
                    form = FormInfo.GetOutOfBattleForm(species, form, generation);
                }
                if (Breeding.CanHatchAsEgg(species, form, ver))
                {
                    yield return(new EncounterEgg(species, form, lvl, generation, ver));

                    if (generation > 5 && (pkm.WasTradedEgg || all) && HasOtherGamePair(ver))
                    {
                        yield return(new EncounterEgg(species, form, lvl, generation, GetOtherTradePair(ver)));
                    }
                }
            }
        }