mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-10 14:44:24 +00:00
Privatize some static fields, more robust legal helper classes. (#3865)
* Uses LearnSource more throughout the codebase when appropriate, rather than loosely coupled pivot methods. * Hides Learnset/EggMove data inside the LearnSource classes. * Extracts functionality from the large Legal class & partial Table*.cs files into better performing helper classes. * Cleans up some code from prior LearnSource commits.
This commit is contained in:
parent
9a768dded3
commit
5bdc6b9ef8
117 changed files with 1281 additions and 1658 deletions
|
@ -46,12 +46,8 @@ public static class MoveShopRecordApplicator
|
|||
/// </summary>
|
||||
public static void SetMoveShopFlags(this IMoveShop8Mastery shop, ReadOnlySpan<ushort> moves, PKM pk)
|
||||
{
|
||||
var index = PersonalTable.LA.GetFormIndex(pk.Species, pk.Form);
|
||||
var learn = Legal.LevelUpLA[index];
|
||||
var mastery = Legal.MasteryLA[index];
|
||||
var level = pk.CurrentLevel;
|
||||
|
||||
shop.SetMoveShopFlags(moves, learn, mastery, level);
|
||||
var (learn, mastery) = LearnSource8LA.GetLearnsetAndMastery(pk.Species, pk.Form);
|
||||
shop.SetMoveShopFlags(moves, learn, mastery, pk.CurrentLevel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -59,12 +55,8 @@ public static class MoveShopRecordApplicator
|
|||
/// </summary>
|
||||
public static void SetMoveShopFlagsAll(this IMoveShop8Mastery shop, PKM pk)
|
||||
{
|
||||
var index = PersonalTable.LA.GetFormIndex(pk.Species, pk.Form);
|
||||
var learn = Legal.LevelUpLA[index];
|
||||
var mastery = Legal.MasteryLA[index];
|
||||
var level = pk.CurrentLevel;
|
||||
|
||||
shop.SetMoveShopFlagsAll(learn, mastery, level);
|
||||
var (learn, mastery) = LearnSource8LA.GetLearnsetAndMastery(pk.Species, pk.Form);
|
||||
shop.SetMoveShopFlagsAll(learn, mastery, pk.CurrentLevel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -20,7 +20,7 @@ public static class BatchMods
|
|||
new TypeSuggestion<IGeoTrack>(nameof(Extensions.ClearGeoLocationData), p => p.ClearGeoLocationData()),
|
||||
new TypeSuggestion<IAwakened>(nameof(AwakeningUtil.AwakeningClear), p => p.AwakeningClear()),
|
||||
new TypeSuggestion<IAwakened>(nameof(AwakeningUtil.AwakeningMinimum), p => p.AwakeningMinimum()),
|
||||
new TypeSuggestion<IAwakened>(nameof(AwakeningUtil.AwakeningMax), p => p.AwakeningMax()),
|
||||
new TypeSuggestion<IAwakened>(nameof(AwakeningUtil.AwakeningMaximize), p => p.AwakeningMaximize()),
|
||||
new TypeSuggestion<IGanbaru>(nameof(GanbaruExtensions.ClearGanbaruValues), p => p.ClearGanbaruValues()),
|
||||
new TypeSuggestion<IGanbaru>(nameof(GanbaruExtensions.SetSuggestedGanbaruValues), p => p.SetSuggestedGanbaruValues((PKM)p)),
|
||||
|
||||
|
|
|
@ -50,8 +50,8 @@ public static class Pokerus
|
|||
if (!IsObtainable(pk))
|
||||
return IsSusceptible(strain, days);
|
||||
if (pk.Format <= 2)
|
||||
return IsStrainValid2(strain);
|
||||
return IsStrainValid(strain);
|
||||
return IsStrainValid2(strain, days);
|
||||
return IsStrainValid(strain, days);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IsStrainValid(PKM,int,int)"/>
|
||||
|
|
|
@ -106,8 +106,8 @@ public static class ShowdownParsing
|
|||
|
||||
(int)Greninja or (int)Rockruff or (int)Koraidon or (int)Miraidon => string.Empty,
|
||||
|
||||
_ => Legal.Totem_USUM.Contains(species) && form == "Large"
|
||||
? Legal.Totem_Alolan.Contains(species) && species != (int)Mimikyu ? "Alola-Totem" : "Totem"
|
||||
_ => FormInfo.HasTotemForm(species) && form == "Large"
|
||||
? species is (int)Raticate or (int)Marowak ? "Alola-Totem" : "Totem"
|
||||
: form.Replace(' ', '-'),
|
||||
};
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ public static class ShowdownParsing
|
|||
(int)Maushold when form == "Four" => "Family of Four",
|
||||
(int)Urshifu or (int)Pikachu or (int)Alcremie => form.Replace('-', ' '), // Strike and Cosplay
|
||||
|
||||
_ => Legal.Totem_USUM.Contains(species) && form.EndsWith("Totem", StringComparison.OrdinalIgnoreCase) ? "Large" : form,
|
||||
_ => FormInfo.HasTotemForm(species) && form.EndsWith("Totem", StringComparison.OrdinalIgnoreCase) ? "Large" : form,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ public sealed class FilteredGameDataSource
|
|||
var legal = source.LegalMoveDataSource;
|
||||
return sav switch
|
||||
{
|
||||
SAV7b => legal.Where(s => Legal.IsAllowedMoveGG((ushort)s.Value)), // LGPE: Not all moves are available
|
||||
SAV7b => legal.Where(s => MoveInfo7b.IsAllowedMoveGG((ushort)s.Value)), // LGPE: Not all moves are available
|
||||
_ => legal.Where(m => m.Value <= sav.MaxMoveID),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -6,16 +6,14 @@ public sealed class ItemStorage7GG : IItemStorage
|
|||
{
|
||||
public static readonly ItemStorage7GG Instance = new();
|
||||
|
||||
private static ReadOnlySpan<ushort> Pouch_Candy_GG_Regular => new ushort[]
|
||||
private static ReadOnlySpan<ushort> Pouch_Candy_GG => new ushort[]
|
||||
{
|
||||
050, // Rare Candy
|
||||
960, 961, 962, 963, 964, 965, // S
|
||||
966, 967, 968, 969, 970, 971, // L
|
||||
972, 973, 974, 975, 976, 977, // XL
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<ushort> Pouch_Candy_GG_Species => new ushort[]
|
||||
{
|
||||
// Species
|
||||
978, 979,
|
||||
980, 981, 982, 983, 984, 985, 986, 987, 988, 989,
|
||||
990, 991, 992, 993, 994, 995, 996, 997, 998, 999,
|
||||
|
@ -28,8 +26,6 @@ public sealed class ItemStorage7GG : IItemStorage
|
|||
1057,
|
||||
};
|
||||
|
||||
private static readonly ushort[] Pouch_Candy_GG = ArrayUtil.ConcatAll(Pouch_Candy_GG_Regular, Pouch_Candy_GG_Species);
|
||||
|
||||
private static ReadOnlySpan<ushort> Pouch_Medicine_GG => new ushort[]
|
||||
{
|
||||
017, 018, 019, 020, 021, 022, 023, 024, 025, 026, 027, 028, 029, 030, 031, 032, 038, 039, 040, 041, 709, 903,
|
||||
|
@ -117,7 +113,6 @@ public sealed class ItemStorage7GG : IItemStorage
|
|||
|
||||
public ReadOnlySpan<ushort> GetItems(InventoryType type) => type switch
|
||||
{
|
||||
|
||||
InventoryType.Medicine => Pouch_Medicine_GG,
|
||||
InventoryType.TMHMs => Pouch_TM_GG,
|
||||
InventoryType.Balls => Pouch_Catching_GG,
|
||||
|
|
|
@ -468,10 +468,16 @@ public sealed class ItemStorage8SWSH : IItemStorage
|
|||
1578, // ★Aql7235
|
||||
};
|
||||
|
||||
private const int DMAX_START = 1279;
|
||||
private const int DMAX_END = 1578;
|
||||
private const int DMAX_LEGAL_END = 1290; // ★Sgr7194 (Eevee)
|
||||
public static bool IsDynamaxCrystal(ushort item) => item is >= DMAX_START and <= DMAX_END;
|
||||
public static bool IsDynamaxCrystalAvailable(ushort item) => item is >= DMAX_START and <= DMAX_LEGAL_END;
|
||||
|
||||
public static bool IsItemLegal(ushort item)
|
||||
{
|
||||
if (Legal.IsDynamaxCrystal(item))
|
||||
return Legal.IsDynamaxCrystalAvailable(item);
|
||||
if (IsDynamaxCrystal(item))
|
||||
return IsDynamaxCrystalAvailable(item);
|
||||
return Unreleased.BinarySearch(item) < 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,8 +50,6 @@ public static class Breeding
|
|||
/// <returns>True if can inherit moves, false if cannot.</returns>
|
||||
internal static bool GetCanInheritMoves(ushort species)
|
||||
{
|
||||
if (Legal.FixedGenderFromBiGender.Contains(species)) // Nincada -> Shedinja loses gender causing 'false', edge case
|
||||
return true;
|
||||
var pi = PKX.Personal[species];
|
||||
if (pi is { Genderless: false, OnlyMale: false })
|
||||
return true;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using static PKHeX.Core.BinLinkerAccessor;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
|
@ -8,60 +7,135 @@ namespace PKHeX.Core;
|
|||
/// </summary>
|
||||
public static partial class Legal
|
||||
{
|
||||
// Gen 1
|
||||
internal static readonly Learnset[] LevelUpRB = LearnsetReader.GetArray(Util.GetBinaryResource("lvlmove_rb.pkl"), MaxSpeciesID_1);
|
||||
internal static readonly Learnset[] LevelUpY = LearnsetReader.GetArray(Util.GetBinaryResource("lvlmove_y.pkl"), MaxSpeciesID_1);
|
||||
internal const int MaxSpeciesID_1 = 151;
|
||||
internal const int MaxMoveID_1 = 165;
|
||||
internal const int MaxItemID_1 = 255;
|
||||
internal const int MaxAbilityID_1 = 0;
|
||||
|
||||
// Gen 2
|
||||
internal static readonly EggMoves2[] EggMovesGS = EggMoves2.GetArray(Util.GetBinaryResource("eggmove_gs.pkl"), MaxSpeciesID_2);
|
||||
internal static readonly Learnset[] LevelUpGS = LearnsetReader.GetArray(Util.GetBinaryResource("lvlmove_gs.pkl"), MaxSpeciesID_2);
|
||||
internal static readonly EggMoves2[] EggMovesC = EggMoves2.GetArray(Util.GetBinaryResource("eggmove_c.pkl"), MaxSpeciesID_2);
|
||||
internal static readonly Learnset[] LevelUpC = LearnsetReader.GetArray(Util.GetBinaryResource("lvlmove_c.pkl"), MaxSpeciesID_2);
|
||||
internal const int MaxSpeciesID_2 = 251;
|
||||
internal const int MaxMoveID_2 = 251;
|
||||
internal const int MaxItemID_2 = 255;
|
||||
internal const int MaxAbilityID_2 = 0;
|
||||
|
||||
// Gen 3
|
||||
internal static readonly Learnset[] LevelUpE = LearnsetReader.GetArray(Get(Util.GetBinaryResource("lvlmove_e.pkl"), "em"));
|
||||
internal static readonly Learnset[] LevelUpRS = LearnsetReader.GetArray(Get(Util.GetBinaryResource("lvlmove_rs.pkl"), "rs"));
|
||||
internal static readonly Learnset[] LevelUpFR = LearnsetReader.GetArray(Get(Util.GetBinaryResource("lvlmove_fr.pkl"), "fr"));
|
||||
internal static readonly Learnset[] LevelUpLG = LearnsetReader.GetArray(Get(Util.GetBinaryResource("lvlmove_lg.pkl"), "lg"));
|
||||
internal static readonly EggMoves6[] EggMovesRS = EggMoves6.GetArray(Get(Util.GetBinaryResource("eggmove_rs.pkl"), "rs"));
|
||||
internal const int MaxSpeciesIndex_3 = 412;
|
||||
internal const int MaxSpeciesID_3 = 386;
|
||||
internal const int MaxMoveID_3 = 354;
|
||||
internal const int MaxItemID_3 = 374;
|
||||
internal const int MaxItemID_3_COLO = 547;
|
||||
internal const int MaxItemID_3_XD = 593;
|
||||
internal const int MaxAbilityID_3 = 77;
|
||||
internal const int MaxBallID_3 = 0xC;
|
||||
internal const int MaxGameID_3 = 15; // CXD
|
||||
|
||||
// Gen 4
|
||||
internal static readonly Learnset[] LevelUpDP = LearnsetReader.GetArray(Get(Util.GetBinaryResource("lvlmove_dp.pkl"), "dp"));
|
||||
internal static readonly Learnset[] LevelUpPt = LearnsetReader.GetArray(Get(Util.GetBinaryResource("lvlmove_pt.pkl"), "pt"));
|
||||
internal static readonly Learnset[] LevelUpHGSS = LearnsetReader.GetArray(Get(Util.GetBinaryResource("lvlmove_hgss.pkl"), "hs"));
|
||||
internal static readonly EggMoves6[] EggMovesDPPt = EggMoves6.GetArray(Get(Util.GetBinaryResource("eggmove_dppt.pkl"), "dp"));
|
||||
internal static readonly EggMoves6[] EggMovesHGSS = EggMoves6.GetArray(Get(Util.GetBinaryResource("eggmove_hgss.pkl"), "hs"));
|
||||
internal const int MaxSpeciesID_4 = 493;
|
||||
internal const int MaxMoveID_4 = 467;
|
||||
internal const int MaxItemID_4_DP = 464;
|
||||
internal const int MaxItemID_4_Pt = 467;
|
||||
internal const int MaxItemID_4_HGSS = 536;
|
||||
internal const int MaxAbilityID_4 = 123;
|
||||
internal const int MaxBallID_4 = 0x18;
|
||||
internal const int MaxGameID_4 = 15; // CXD
|
||||
|
||||
// Gen 5
|
||||
internal static readonly Learnset[] LevelUpBW = LearnsetReader.GetArray(Get(Util.GetBinaryResource("lvlmove_bw.pkl"), "51"));
|
||||
internal static readonly Learnset[] LevelUpB2W2 = LearnsetReader.GetArray(Get(Util.GetBinaryResource("lvlmove_b2w2.pkl"), "52"));
|
||||
internal static readonly EggMoves6[] EggMovesBW = EggMoves6.GetArray(Get(Util.GetBinaryResource("eggmove_bw.pkl"), "bw"));
|
||||
internal const int MaxSpeciesID_5 = 649;
|
||||
internal const int MaxMoveID_5 = 559;
|
||||
internal const int MaxItemID_5_BW = 632;
|
||||
internal const int MaxItemID_5_B2W2 = 638;
|
||||
internal const int MaxAbilityID_5 = 164;
|
||||
internal const int MaxBallID_5 = 0x19;
|
||||
internal const int MaxGameID_5 = 23; // B2
|
||||
|
||||
// Gen 6
|
||||
internal static readonly EggMoves6[] EggMovesXY = EggMoves6.GetArray(Get(Util.GetBinaryResource("eggmove_xy.pkl"), "xy"));
|
||||
internal static readonly Learnset[] LevelUpXY = LearnsetReader.GetArray(Get(Util.GetBinaryResource("lvlmove_xy.pkl"), "xy"));
|
||||
internal static readonly EggMoves6[] EggMovesAO = EggMoves6.GetArray(Get(Util.GetBinaryResource("eggmove_ao.pkl"), "ao"));
|
||||
internal static readonly Learnset[] LevelUpAO = LearnsetReader.GetArray(Get(Util.GetBinaryResource("lvlmove_ao.pkl"), "ao"));
|
||||
internal const int MaxSpeciesID_6 = 721;
|
||||
internal const int MaxMoveID_6_XY = 617;
|
||||
internal const int MaxMoveID_6_AO = 621;
|
||||
internal const int MaxItemID_6_XY = 717;
|
||||
internal const int MaxItemID_6_AO = 775;
|
||||
internal const int MaxAbilityID_6_XY = 188;
|
||||
internal const int MaxAbilityID_6_AO = 191;
|
||||
internal const int MaxBallID_6 = 0x19;
|
||||
internal const int MaxGameID_6 = 27; // OR
|
||||
|
||||
// Gen 7
|
||||
internal static readonly EggMoves7[] EggMovesSM = EggMoves7.GetArray(Get(Util.GetBinaryResource("eggmove_sm.pkl"), "sm"));
|
||||
internal static readonly Learnset[] LevelUpSM = LearnsetReader.GetArray(Get(Util.GetBinaryResource("lvlmove_sm.pkl"), "sm"));
|
||||
internal static readonly EggMoves7[] EggMovesUSUM = EggMoves7.GetArray(Get(Util.GetBinaryResource("eggmove_uu.pkl"), "uu"));
|
||||
internal static readonly Learnset[] LevelUpUSUM = LearnsetReader.GetArray(Get(Util.GetBinaryResource("lvlmove_uu.pkl"), "uu"));
|
||||
internal static readonly Learnset[] LevelUpGG = LearnsetReader.GetArray(Get(Util.GetBinaryResource("lvlmove_gg.pkl"), "gg"));
|
||||
internal const int MaxSpeciesID_7 = 802;
|
||||
internal const int MaxMoveID_7 = 719;
|
||||
internal const int MaxItemID_7 = 920;
|
||||
internal const int MaxAbilityID_7 = 232;
|
||||
internal const int MaxBallID_7 = 0x1A; // 26
|
||||
internal const int MaxGameID_7 = 41; // Crystal (VC?)
|
||||
|
||||
// Gen 8
|
||||
internal static readonly EggMoves7[] EggMovesSWSH = EggMoves7.GetArray(Get(Util.GetBinaryResource("eggmove_swsh.pkl"), "ss"));
|
||||
internal static readonly Learnset[] LevelUpSWSH = LearnsetReader.GetArray(Get(Util.GetBinaryResource("lvlmove_swsh.pkl"), "ss"));
|
||||
internal static readonly EggMoves6[] EggMovesBDSP = EggMoves6.GetArray(Get(Util.GetBinaryResource("eggmove_bdsp.pkl"), "bs"));
|
||||
internal static readonly Learnset[] LevelUpBDSP = LearnsetReader.GetArray(Get(Util.GetBinaryResource("lvlmove_bdsp.pkl"), "bs"));
|
||||
internal static readonly Learnset[] LevelUpLA = LearnsetReader.GetArray(Get(Util.GetBinaryResource("lvlmove_la.pkl"), "la"));
|
||||
internal static readonly Learnset[] MasteryLA = LearnsetReader.GetArray(Get(Util.GetBinaryResource("mastery_la.pkl"), "la"));
|
||||
internal const int MaxSpeciesID_7_USUM = 807;
|
||||
internal const int MaxMoveID_7_USUM = 728;
|
||||
internal const int MaxItemID_7_USUM = 959;
|
||||
internal const int MaxAbilityID_7_USUM = 233;
|
||||
|
||||
// Gen 9
|
||||
internal static readonly ushort[][] EggMovesSV = EggMoves9.GetArray(Get(Util.GetBinaryResource("eggmove_sv.pkl"), "sv"));
|
||||
internal static readonly ushort[][] ReminderSV = EggMoves9.GetArray(Get(Util.GetBinaryResource("reminder_sv.pkl"), "sv"));
|
||||
internal static readonly Learnset[] LevelUpSV = LearnsetReader.GetArray(Get(Util.GetBinaryResource("lvlmove_sv.pkl"), "sv"));
|
||||
internal const int MaxSpeciesID_7b = 809; // Melmetal
|
||||
internal const int MaxMoveID_7b = 742; // Double Iron Bash
|
||||
internal const int MaxItemID_7b = 1057; // Magmar Candy
|
||||
internal const int MaxBallID_7b = (int)Ball.Beast;
|
||||
internal const int MaxGameID_7b = (int)GameVersion.GE;
|
||||
internal const int MaxAbilityID_7b = MaxAbilityID_7_USUM;
|
||||
|
||||
// Current Binaries
|
||||
internal const int MaxSpeciesID_8 = MaxSpeciesID_8_R2;
|
||||
internal const int MaxMoveID_8 = MaxMoveID_8_R2;
|
||||
internal const int MaxItemID_8 = MaxItemID_8_R2;
|
||||
internal const int MaxAbilityID_8 = MaxAbilityID_8_R2;
|
||||
|
||||
// Orion (No DLC)
|
||||
internal const int MaxSpeciesID_8_O0 = 890; // Eternatus
|
||||
internal const int MaxMoveID_8_O0 = 796; // Steel Beam
|
||||
internal const int MaxItemID_8_O0 = 1278; // Rotom Catalog, ignore all catalog parts
|
||||
internal const int MaxAbilityID_8_O0 = 258; // Hunger Switch
|
||||
|
||||
// Rigel 1 (DLC 1: Isle of Armor)
|
||||
internal const int MaxSpeciesID_8_R1 = 893; // Zarude
|
||||
internal const int MaxMoveID_8_R1 = 818; // Surging Strikes
|
||||
internal const int MaxItemID_8_R1 = 1589; // Mark Charm
|
||||
internal const int MaxAbilityID_8_R1 = 260; // Unseen Fist
|
||||
|
||||
// Rigel 2 (DLC 2: Crown Tundra)
|
||||
internal const int MaxSpeciesID_8_R2 = 898; // Calyrex
|
||||
internal const int MaxMoveID_8_R2 = 826; // Eerie Spell
|
||||
internal const int MaxItemID_8_R2 = 1607; // Reins of Unity
|
||||
internal const int MaxAbilityID_8_R2 = 267; // As One (Glastrier)
|
||||
|
||||
internal const int MaxBallID_8 = 0x1A; // 26 Beast
|
||||
internal const int MaxGameID_8 = 45; // Shield
|
||||
|
||||
internal const int MaxSpeciesID_8a = (int)Species.Enamorus;
|
||||
internal const int MaxMoveID_8a = (int)Move.TakeHeart;
|
||||
internal const int MaxItemID_8a = 1828; // Legend Plate
|
||||
internal const int MaxBallID_8a = (int)Ball.LAOrigin;
|
||||
internal const int MaxGameID_8a = (int)GameVersion.SP;
|
||||
internal const int MaxAbilityID_8a = MaxAbilityID_8_R2;
|
||||
|
||||
internal const int MaxSpeciesID_8b = MaxSpeciesID_4; // Arceus-493
|
||||
internal const int MaxMoveID_8b = MaxMoveID_8_R2;
|
||||
internal const int MaxItemID_8b = 1822; // DS Sounds
|
||||
internal const int MaxBallID_8b = (int)Ball.LAOrigin;
|
||||
internal const int MaxGameID_8b = (int)GameVersion.SP;
|
||||
internal const int MaxAbilityID_8b = MaxAbilityID_8_R2;
|
||||
|
||||
internal const int MaxSpeciesID_9 = (int)Species.IronLeaves;
|
||||
internal const int MaxMoveID_9 = (int)Move.MagicalTorque;
|
||||
internal const int MaxItemID_9 = 2400; // Yellow Dish
|
||||
internal const int MaxAbilityID_9 = (int)Ability.MyceliumMight;
|
||||
|
||||
internal const int MaxBallID_9 = (int)Ball.LAOrigin;
|
||||
internal const int MaxGameID_9 = (int)GameVersion.VL;
|
||||
|
||||
internal static readonly ushort[] HeldItems_GSC = ItemStorage2.GetAllHeld();
|
||||
internal static readonly ushort[] HeldItems_RS = ItemStorage3RS.GetAllHeld();
|
||||
internal static readonly ushort[] HeldItems_DP = ItemStorage4DP.GetAllHeld();
|
||||
internal static readonly ushort[] HeldItems_Pt = ItemStorage4Pt.GetAllHeld(); // Griseous Orb Added
|
||||
internal static readonly ushort[] HeldItems_HGSS = HeldItems_Pt;
|
||||
internal static readonly ushort[] HeldItems_BW = ItemStorage5.GetAllHeld();
|
||||
internal static readonly ushort[] HeldItem_AO = ItemStorage6XY.GetAllHeld();
|
||||
internal static readonly ushort[] HeldItems_SM = ItemStorage7SM.GetAllHeld();
|
||||
internal static readonly ushort[] HeldItems_USUM = ItemStorage7USUM.GetAllHeld();
|
||||
internal static readonly ushort[] HeldItems_GG = Array.Empty<ushort>();
|
||||
internal static readonly ushort[] HeldItems_SWSH = ItemStorage8SWSH.GetAllHeld();
|
||||
internal static readonly ushort[] HeldItems_BS = ItemStorage8BDSP.GetAll();
|
||||
internal static readonly ushort[] HeldItems_LA = Array.Empty<ushort>();
|
||||
internal static readonly ushort[] HeldItems_SV = ItemStorage9SV.GetAllHeld();
|
||||
|
||||
internal static int GetMaxSpeciesOrigin(int generation) => generation switch
|
||||
{
|
||||
|
|
|
@ -153,8 +153,9 @@ public sealed record EncounterEgg(ushort Species, byte Form, byte Level, int Gen
|
|||
|
||||
private void SetEncounterMoves(PKM pk, GameVersion version)
|
||||
{
|
||||
var learnset = GameData.GetLearnset(version, Species, Form);
|
||||
var baseMoves = learnset.GetBaseEggMoves(Level);
|
||||
pk.SetMoves(baseMoves);
|
||||
var ls = GameData.GetLearnSource(version);
|
||||
var learn = ls.GetLearnset(Species, Form);
|
||||
var initial = learn.GetBaseEggMoves(LevelMin);
|
||||
pk.SetMoves(initial);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,7 +125,8 @@ public abstract record EncounterSlot(EncounterArea Area, ushort Species, byte Fo
|
|||
protected virtual void SetEncounterMoves(PKM pk, GameVersion version, int level)
|
||||
{
|
||||
Span<ushort> moves = stackalloc ushort[4];
|
||||
MoveLevelUp.GetEncounterMoves(moves, pk, level, version);
|
||||
var source = GameData.GetLearnSource(version);
|
||||
source.SetEncounterMoves(Species, Form, level, moves);
|
||||
pk.SetMoves(moves);
|
||||
pk.SetMaximumPPCurrent(moves);
|
||||
}
|
||||
|
|
|
@ -84,13 +84,7 @@ public sealed record EncounterSlot8a : EncounterSlot, IAlphaReadOnly, IMasteryIn
|
|||
}
|
||||
}
|
||||
|
||||
public (Learnset Learn, Learnset Mastery) GetLevelUpInfo()
|
||||
{
|
||||
var index = PersonalTable.LA.GetFormIndex(Species, Form);
|
||||
var learn = Legal.LevelUpLA[index];
|
||||
var mastery = Legal.MasteryLA[index];
|
||||
return (learn, mastery);
|
||||
}
|
||||
public (Learnset Learn, Learnset Mastery) GetLevelUpInfo() => LearnSource8LA.GetLearnsetAndMastery(Species, Form);
|
||||
|
||||
protected override void SetFormatSpecificData(PKM pk)
|
||||
{
|
||||
|
@ -174,14 +168,12 @@ public sealed record EncounterSlot8a : EncounterSlot, IAlphaReadOnly, IMasteryIn
|
|||
|
||||
bool allowAlphaPurchaseBug = Area.Type is not SlotType.OverworldMMO; // Everything else Alpha is pre-1.1
|
||||
var level = pk.Met_Level;
|
||||
var index = PersonalTable.LA.GetFormIndex(Species, Form);
|
||||
var learn = Legal.LevelUpLA[index];
|
||||
var (learn, mastery) = GetLevelUpInfo();
|
||||
ushort alpha = pk is PA8 pa ? pa.AlphaMove : (ushort)0;
|
||||
if (!p.IsValidPurchasedEncounter(learn, level, alpha, allowAlphaPurchaseBug))
|
||||
return false;
|
||||
|
||||
Span<ushort> moves = stackalloc ushort[4];
|
||||
var mastery = Legal.MasteryLA[index];
|
||||
if (pk is PA8 { AlphaMove: not 0 } pa8)
|
||||
{
|
||||
moves[0] = pa8.AlphaMove;
|
||||
|
|
|
@ -41,10 +41,10 @@ public sealed record EncounterSlot8b : EncounterSlot
|
|||
var et = PersonalTable.BDSP;
|
||||
var sf = et.GetFormEntry(Species, Form);
|
||||
var species = sf.HatchSpecies;
|
||||
var baseEgg = Legal.EggMovesBDSP[species].Moves;
|
||||
var baseEgg = LearnSource8BDSP.Instance.GetEggMoves(species, 0);
|
||||
if (baseEgg.Length == 0)
|
||||
return move == 0;
|
||||
return Array.IndexOf(baseEgg, move) >= 0;
|
||||
return baseEgg.Contains(move);
|
||||
}
|
||||
|
||||
public bool GetBaseEggMove(out ushort move)
|
||||
|
@ -52,7 +52,7 @@ public sealed record EncounterSlot8b : EncounterSlot
|
|||
var et = PersonalTable.BDSP;
|
||||
var sf = et.GetFormEntry(Species, Form);
|
||||
var species = sf.HatchSpecies;
|
||||
var baseEgg = Legal.EggMovesBDSP[species].Moves;
|
||||
var baseEgg = LearnSource8BDSP.Instance.GetEggMoves(species, 0);
|
||||
if (baseEgg.Length == 0)
|
||||
{
|
||||
move = 0;
|
||||
|
|
|
@ -50,7 +50,8 @@ public sealed record EncounterSlot7GO : EncounterSlotGO
|
|||
protected override void SetEncounterMoves(PKM pk, GameVersion version, int level)
|
||||
{
|
||||
Span<ushort> moves = stackalloc ushort[4];
|
||||
MoveLevelUp.GetEncounterMoves(moves, pk, level, GameVersion.GG);
|
||||
var source = GameData.GetLearnSource(GameVersion.GG);
|
||||
source.SetEncounterMoves(Species, Form, level, moves);
|
||||
pk.SetMoves(moves);
|
||||
pk.SetMaximumPPCurrent(moves);
|
||||
}
|
||||
|
|
|
@ -139,7 +139,11 @@ public sealed record EncounterSlot8GO : EncounterSlotGO, IFixedOTFriendship
|
|||
pk.SetMaximumPPCurrent(moves);
|
||||
}
|
||||
|
||||
public void GetInitialMoves(int level, Span<ushort> moves) => MoveLevelUp.GetEncounterMoves(moves, Species, Form, level, OriginGroup);
|
||||
public void GetInitialMoves(int level, Span<ushort> moves)
|
||||
{
|
||||
var source = GameData.GetLearnSource(OriginGroup);
|
||||
source.SetEncounterMoves(Species, Form, level, moves);
|
||||
}
|
||||
|
||||
public override EncounterMatchRating GetMatchRating(PKM pk)
|
||||
{
|
||||
|
|
|
@ -161,7 +161,8 @@ public abstract record EncounterStatic(GameVersion Version) : IEncounterable, IM
|
|||
else
|
||||
{
|
||||
Span<ushort> moves = stackalloc ushort[4];
|
||||
MoveLevelUp.GetEncounterMoves(moves, pk, level, version);
|
||||
var source = GameData.GetLearnSource(version);
|
||||
source.SetEncounterMoves(Species, Form, level, moves);
|
||||
pk.SetMoves(moves);
|
||||
pk.SetMaximumPPCurrent(moves);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ public sealed record EncounterStatic7(GameVersion Version) : EncounterStatic(Ver
|
|||
public Moveset Relearn { get; init; }
|
||||
|
||||
public bool IsTotem => FormInfo.IsTotemForm(Species, Form);
|
||||
public bool IsTotemNoTransfer => Legal.Totem_NoTransfer.Contains(Species);
|
||||
public bool IsTotemNoTransfer => Species is (int)Core.Species.Marowak or (int)Core.Species.Araquanid or (int)Core.Species.Togedemaru or (int)Core.Species.Ribombee;
|
||||
public int GetTotemBaseForm() => FormInfo.GetTotemBaseForm(Species, Form);
|
||||
|
||||
public bool IsRandomUnspecificForm => Form >= FormDynamic;
|
||||
|
|
|
@ -135,13 +135,11 @@ public sealed record EncounterStatic8a(GameVersion Version) : EncounterStatic(Ve
|
|||
|
||||
const bool allowAlphaPurchaseBug = true; // Everything else Alpha is pre-1.1
|
||||
var level = pk.Met_Level;
|
||||
var index = PersonalTable.LA.GetFormIndex(Species, Form);
|
||||
var learn = Legal.LevelUpLA[index];
|
||||
var (learn, mastery) = GetLevelUpInfo();
|
||||
if (!p.IsValidPurchasedEncounter(learn, level, alpha, allowAlphaPurchaseBug))
|
||||
return false;
|
||||
|
||||
Span<ushort> moves = stackalloc ushort[4];
|
||||
var mastery = Legal.MasteryLA[index];
|
||||
if (Moves.HasMoves)
|
||||
Moves.CopyTo(moves);
|
||||
else
|
||||
|
@ -165,10 +163,7 @@ public sealed record EncounterStatic8a(GameVersion Version) : EncounterStatic(Ve
|
|||
|
||||
public (Learnset Learn, Learnset Mastery) GetLevelUpInfo()
|
||||
{
|
||||
var index = PersonalTable.LA.GetFormIndex(Species, Form);
|
||||
var learn = Legal.LevelUpLA[index];
|
||||
var mastery = Legal.MasteryLA[index];
|
||||
return (learn, mastery);
|
||||
return LearnSource8LA.GetLearnsetAndMastery(Species, Form);
|
||||
}
|
||||
|
||||
public void LoadInitialMoveset(PA8 pa8, Span<ushort> moves, Learnset learn, int level)
|
||||
|
|
|
@ -166,7 +166,8 @@ public abstract record EncounterTrade(GameVersion Version) : IEncounterable, IMo
|
|||
else
|
||||
{
|
||||
Span<ushort> moves = stackalloc ushort[4];
|
||||
MoveLevelUp.GetEncounterMoves(moves, pk, level, version);
|
||||
var source = GameData.GetLearnSource(version);
|
||||
source.SetEncounterMoves(Species, Form, level, moves);
|
||||
pk.SetMoves(moves);
|
||||
pk.SetMaximumPPCurrent(moves);
|
||||
}
|
||||
|
|
|
@ -174,7 +174,7 @@ public static class EncounterFinder
|
|||
private static bool WasGiftEgg(PKM pk, int gen, ushort loc) => !pk.FatefulEncounter && gen switch
|
||||
{
|
||||
3 => pk.IsEgg && (byte)pk.Met_Location == 253, // Gift Egg, indistinguishable from normal eggs after hatch
|
||||
4 => Legal.GiftEggLocation4.Contains(loc) || (pk.Format != 4 && (loc == Locations.Faraway4 && pk.HGSS)),
|
||||
4 => (uint)(loc - 2009) <= (2014 - 2009) || (pk.Format != 4 && (loc == Locations.Faraway4 && pk.HGSS)),
|
||||
5 => loc is Locations.Breeder5,
|
||||
_ => loc is Locations.Breeder6,
|
||||
};
|
||||
|
|
|
@ -302,7 +302,8 @@ public static class EncounterMovesetGenerator
|
|||
continue;
|
||||
}
|
||||
|
||||
var eggMoves = MoveEgg.GetEggMoves(egg.Species, egg.Form, egg.Version, egg.Generation);
|
||||
var source = GameData.GetLearnSource(egg.Version);
|
||||
var eggMoves = source.GetEggMoves(egg.Species, egg.Form);
|
||||
int flags = Moveset.BitOverlap(eggMoves, needs);
|
||||
var vt = Array.IndexOf(needs, (ushort)Move.VoltTackle);
|
||||
if (vt != -1 && egg is EncounterEgg { CanHaveVoltTackle: true })
|
||||
|
@ -463,7 +464,8 @@ public static class EncounterMovesetGenerator
|
|||
private static int GetMoveMaskGen2(ReadOnlySpan<ushort> needs, IEncounterTemplate enc)
|
||||
{
|
||||
Span<ushort> moves = stackalloc ushort[4];
|
||||
MoveLevelUp.GetEncounterMoves(moves, enc.Species, 0, enc.LevelMin, enc.Version);
|
||||
var source = GameData.GetLearnSource(enc.Version);
|
||||
source.SetEncounterMoves(enc.Species, 0, enc.LevelMin, moves);
|
||||
return Moveset.BitOverlap(moves, needs);
|
||||
}
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ public static class EncounterSuggestion
|
|||
if (pk.Format == 4) // Pal Park
|
||||
return Locations.Transfer3;
|
||||
if (pk.Format >= 5) // Transporter
|
||||
return Legal.GetTransfer45MetLocation(pk);
|
||||
return PK5.GetTransferMetLocation4(pk);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
using System;
|
||||
using static PKHeX.Core.GameVersion;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static class EggHatchLocation3
|
||||
{
|
||||
private const byte MaskRS = 1 << 0; // 1
|
||||
private const byte MaskE = 1 << 1; // 2
|
||||
private const byte MaskFRLG = 1 << 2; // 4
|
||||
private const byte MaskAll = MaskRS | MaskE | MaskFRLG; // 7
|
||||
|
||||
public static bool IsValidMet3(int location, GameVersion game) => game switch
|
||||
{
|
||||
R or S => IsValidMet3RS(location),
|
||||
E => IsValidMet3E(location),
|
||||
FR or LG => IsValidMet3FRLG(location),
|
||||
_ => false,
|
||||
};
|
||||
|
||||
public static bool IsValidMet3RS(int location) => HasLocationFlag(LocationPermitted3, MaskRS, location);
|
||||
public static bool IsValidMet3E(int location) => HasLocationFlag(LocationPermitted3, MaskE, location);
|
||||
public static bool IsValidMet3FRLG(int location) => HasLocationFlag(LocationPermitted3, MaskFRLG, location);
|
||||
public static bool IsValidMet3Any(int location) => HasLocationFlag(LocationPermitted3, MaskAll, location);
|
||||
|
||||
private static bool HasLocationFlag(ReadOnlySpan<byte> arr, byte mask, int location)
|
||||
{
|
||||
if ((uint)location >= arr.Length)
|
||||
return false;
|
||||
var flags = arr[location];
|
||||
return (flags & mask) != 0;
|
||||
}
|
||||
|
||||
// 064 is an unused location for Meteor Falls
|
||||
// 084 is Inside of a truck, no possible pokemon can be hatched there
|
||||
// 071 is Mirage island, cannot be obtained as the player is technically still on Route 130's map.
|
||||
// 075 is an unused location for Fiery Path
|
||||
// 077 is an unused location for Jagged Pass
|
||||
|
||||
// 155 - 158 Sevii Isle 6-9 Unused
|
||||
// 171 - 173 Sevii Isle 22-24 Unused
|
||||
private static ReadOnlySpan<byte> LocationPermitted3 => new byte[]
|
||||
{
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 0, 3, 3, 3, 3, 3,
|
||||
3, 0, 3, 3, 3, 0, 3, 0, 3, 3,
|
||||
3, 3, 3, 3, 0, 3, 3, 7, 4, 4, // 87 = all
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 0, 0, 0, 0, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 0, 0, 0, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 6, 2, 2, 2, // 196 = fr/lg & e
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2,
|
||||
};
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
using static PKHeX.Core.GameVersion;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static class EggHatchLocation4
|
||||
{
|
||||
private const byte MaskDP = 1 << 0; // 1
|
||||
private const byte MaskPt = 1 << 1; // 2
|
||||
private const byte MaskHGSS = 1 << 2; // 4
|
||||
private const byte MaskAll4 = MaskDP | MaskPt | MaskHGSS; // 7
|
||||
|
||||
public static bool IsValidMet4(int location, GameVersion game) => game switch
|
||||
{
|
||||
D or P => IsValidMet4DP(location),
|
||||
Pt => IsValidMet4Pt(location),
|
||||
HG or SS => IsValidMet4HGSS(location),
|
||||
_ => false,
|
||||
};
|
||||
|
||||
public static bool IsValidMet4DP(int location) => HasLocationFlag(LocationPermitted4, MaskDP, location);
|
||||
public static bool IsValidMet4Pt(int location) => HasLocationFlag(LocationPermitted4, MaskPt, location);
|
||||
public static bool IsValidMet4HGSS(int location) => HasLocationFlag(LocationPermitted4, MaskHGSS, location);
|
||||
public static bool IsValidMet4Any(int location) => HasLocationFlag(LocationPermitted4, MaskAll4, location);
|
||||
|
||||
private static bool HasLocationFlag(ReadOnlySpan<byte> arr, byte mask, int location)
|
||||
{
|
||||
if ((uint)location >= arr.Length)
|
||||
return false;
|
||||
var flags = arr[location];
|
||||
return (flags & mask) != 0;
|
||||
}
|
||||
|
||||
private static ReadOnlySpan<byte> LocationPermitted4 => new byte[]
|
||||
{
|
||||
0, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 2, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 2,
|
||||
7, 3, 3, 3, 3, 2, 0, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 6, 6, 6, 6, 6, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 0, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
4, 4, 4, 0, 4,
|
||||
};
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
using static PKHeX.Core.GameVersion;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static class EggHatchLocation5
|
||||
{
|
||||
private const byte MaskWhite = 1 << 0; // 1
|
||||
private const byte MaskBlack = 1 << 1; // 2
|
||||
private const byte MaskWhite2 = 1 << 2; // 4
|
||||
private const byte MaskBlack2 = 1 << 3; // 8
|
||||
|
||||
public static bool IsValidMet5(int location, GameVersion game)
|
||||
{
|
||||
var shift = (uint)((int)game - (int)W);
|
||||
if (shift >= 4)
|
||||
return false;
|
||||
|
||||
var mask = (byte)(1 << (int)shift);
|
||||
return HasLocationFlag(LocationPermitted5, mask, location);
|
||||
}
|
||||
|
||||
public static bool IsValidMet5W(int location) => HasLocationFlag(LocationPermitted5, MaskWhite, location);
|
||||
public static bool IsValidMet5B(int location) => HasLocationFlag(LocationPermitted5, MaskBlack, location);
|
||||
public static bool IsValidMet5W2(int location) => HasLocationFlag(LocationPermitted5, MaskWhite2, location);
|
||||
public static bool IsValidMet5B2(int location) => HasLocationFlag(LocationPermitted5, MaskBlack2, location);
|
||||
|
||||
private static bool HasLocationFlag(ReadOnlySpan<byte> arr, byte mask, int location)
|
||||
{
|
||||
if ((uint)location >= arr.Length)
|
||||
return false;
|
||||
var flags = arr[location];
|
||||
return (flags & mask) != 0;
|
||||
}
|
||||
|
||||
// Two game-specific locations we need to double check for.
|
||||
// White / White2 cannot access Black Gate (112)
|
||||
// Black / Black2 cannot access White Gate (113)
|
||||
private static ReadOnlySpan<byte> LocationPermitted5 => new byte[]
|
||||
{
|
||||
00, 00, 00, 00, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 03, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
03, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 03,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 03, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 15, 10, 05, 15, 15, 15, 12, 12, 12,
|
||||
12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
|
||||
12, 12, 12, 12, 12, 12, 12, 12, 00, 12,
|
||||
12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
|
||||
12, 12, 12, 12,
|
||||
};
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
namespace PKHeX.Core;
|
||||
|
||||
public static class EggHatchLocation6
|
||||
{
|
||||
public static bool IsValidMet6XY(int location)
|
||||
{
|
||||
const int min = 6;
|
||||
const int max = 168;
|
||||
var delta = location - min;
|
||||
if ((uint)delta >= max - min)
|
||||
return false;
|
||||
|
||||
if (location % 2 != 0)
|
||||
return false; // All locations are even
|
||||
return location != 80; // unused
|
||||
}
|
||||
|
||||
public static bool IsValidMet6AO(int location)
|
||||
{
|
||||
const int min = 170;
|
||||
const int max = 354;
|
||||
var delta = location - min;
|
||||
if ((uint)delta >= max - min)
|
||||
return false;
|
||||
|
||||
if (location % 2 != 0)
|
||||
return false; // All locations are even
|
||||
return location != 348; // unused
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static class EggHatchLocation7
|
||||
{
|
||||
private const byte MaskSM = 1 << 0; // 1
|
||||
private const byte MaskUSUM = 1 << 1; // 2
|
||||
|
||||
public static bool IsValidMet7SM(int location)
|
||||
{
|
||||
if (HasLocationFlag(LocationPermitted7, MaskSM, location))
|
||||
return true;
|
||||
return location == Locations.Pelago7; // 30016
|
||||
}
|
||||
|
||||
public static bool IsValidMet7USUM(int location)
|
||||
{
|
||||
if (HasLocationFlag(LocationPermitted7, MaskUSUM, location))
|
||||
return true;
|
||||
return location == Locations.Pelago7; // 30016
|
||||
}
|
||||
|
||||
private static bool HasLocationFlag(ReadOnlySpan<byte> arr, byte mask, int location)
|
||||
{
|
||||
if ((uint)location >= arr.Length)
|
||||
return false;
|
||||
var flags = arr[location];
|
||||
return (flags & mask) != 0;
|
||||
}
|
||||
|
||||
private static ReadOnlySpan<byte> LocationPermitted7 => new byte[]
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 3, 0, 3, 0, // 000
|
||||
3, 0, 3, 0, 3, 0, 3, 0, 3, 0,
|
||||
3, 0, 3, 0, 3, 0, 3, 0, 3, 0,
|
||||
3, 0, 3, 0, 3, 0, 3, 0, 3, 0,
|
||||
3, 0, 3, 0, 3, 0, 3, 0, 3, 0,
|
||||
3, 0, 3, 0, 3, 0, 3, 0, 3, 0,
|
||||
3, 0, 3, 0, 3, 0, 0, 0, 3, 0,
|
||||
3, 0, 3, 0, 3, 0, 3, 0, 3, 0,
|
||||
0, 0, 3, 0, 3, 0, 3, 0, 3, 0,
|
||||
3, 0, 3, 0, 3, 0, 0, 0, 0, 0,
|
||||
3, 0, 3, 0, 3, 0, 3, 0, 3, 0, // 100
|
||||
3, 0, 3, 0, 3, 0, 3, 0, 3, 0,
|
||||
3, 0, 3, 0, 3, 0, 3, 0, 3, 0,
|
||||
3, 0, 3, 0, 3, 0, 3, 0, 3, 0,
|
||||
3, 0, 3, 0, 3, 0, 3, 0, 3, 0,
|
||||
3, 0, 3, 0, 3, 0, 3, 0, 3, 0,
|
||||
3, 0, 3, 0, 3, 0, 3, 0, 3, 0,
|
||||
3, 0, 3, 0, 3, 0, 3, 0, 3, 0,
|
||||
3, 0, 3, 0, 3, 0, 3, 0, 3, 0,
|
||||
3, 0, 3, 0, 0, 0, 0, 0, 2, 0,
|
||||
2, 0, 2, 0, 2, 0, 2, 0, 2, 0, // 200
|
||||
2, 0, 2, 0, 2, 0, 2, 0, 2, 0,
|
||||
2, 0, 2, 0, 2, 0, 2, 0, 2, 0,
|
||||
2, 0, 2,
|
||||
};
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static class EggHatchLocation8
|
||||
{
|
||||
public static bool IsValidMet8SWSH(int location)
|
||||
{
|
||||
if (location % 2 != 0)
|
||||
return false;
|
||||
|
||||
var index = location >> 1;
|
||||
var arr = LocationPermitted8;
|
||||
if ((uint)index >= arr.Length)
|
||||
return false;
|
||||
return arr[index] != 0;
|
||||
}
|
||||
|
||||
// Odd indexes ignored.
|
||||
private static ReadOnlySpan<byte> LocationPermitted8 => new byte[]
|
||||
{
|
||||
0, 0, 0, 1, 1, 0, 1, 1, 1, 1,
|
||||
1, 1, 1, 0, 1, 1, 1, 1, 1, 0,
|
||||
1, 0, 1, 1, 1, 0, 1, 1, 1, 1,
|
||||
1, 0, 1, 1, 1, 1, 1, 0, 1, 1,
|
||||
1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1,
|
||||
};
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static class EggHatchLocation8b
|
||||
{
|
||||
private const byte MaskBD = 1 << 0; // 1
|
||||
private const byte MaskSP = 1 << 1; // 2
|
||||
|
||||
public static bool IsValidMet8BD(int location)
|
||||
{
|
||||
if (HasLocationFlag(LocationPermitted8b, MaskBD, location))
|
||||
return true;
|
||||
return location == Locations.Pelago7; // 30016
|
||||
}
|
||||
|
||||
public static bool IsValidMet8SP(int location)
|
||||
{
|
||||
if (HasLocationFlag(LocationPermitted8b, MaskSP, location))
|
||||
return true;
|
||||
return location == Locations.Pelago7; // 30016
|
||||
}
|
||||
|
||||
private static bool HasLocationFlag(ReadOnlySpan<byte> arr, byte mask, int location)
|
||||
{
|
||||
if ((uint)location >= arr.Length)
|
||||
return false;
|
||||
var flags = arr[location];
|
||||
return (flags & mask) != 0;
|
||||
}
|
||||
|
||||
// BD Exclusive
|
||||
// 216, // Spear Pillar
|
||||
// 218, // Hall of Origin
|
||||
// 498, // Ramanas Park (Johto Room)
|
||||
// 503, // Ramanas Park (Rainbow Room)
|
||||
// 650, // Ramanas Park (Johto Room)
|
||||
// 655, // Ramanas Park (Rainbow Room)
|
||||
|
||||
// SP Exclusive
|
||||
// 217, // Spear Pillar
|
||||
// 497, // Ramanas Park (Kanto Room)
|
||||
// 504, // Ramanas Park (Squall Room)
|
||||
// 618, // Hall of Origin
|
||||
// 649, // Ramanas Park (Kanto Room)
|
||||
// 656, // Ramanas Park (Squall Room)
|
||||
|
||||
// Unobtainable
|
||||
// 094, 103, 107, // Hearthome City
|
||||
// 154, 155, 158, // Sunyshore City
|
||||
// 181, 182, 183, // Pokémon League
|
||||
// 329, // Lake Acuity
|
||||
// 337, 338, // Battle Park
|
||||
// 339, 340, 341, 342, 343, 344, // Battle Tower
|
||||
// 345, 353, 421, // Mystery Zone
|
||||
// 474, // Resort Area
|
||||
// 483, 484, // Mystery Zone
|
||||
// 491, 492, 493, // Mystery Zone
|
||||
// 495, // Ramanas Park
|
||||
// 620, 621, 622, 623, // Grand Underground (Secret Base)
|
||||
// 625, // Sea (sailing animation)
|
||||
// 627, 628, 629, 630, 631, 632, // Grand Underground (Secret Base)
|
||||
// 633, 634, 635, 636, 637, 638, // Grand Underground (Secret Base)
|
||||
// 639, 640, 641, 642, 643, 644, // Grand Underground (Secret Base)
|
||||
// 645, 646, 647, // Grand Underground (Secret Base)
|
||||
|
||||
private static ReadOnlySpan<byte> LocationPermitted8b => new byte[]
|
||||
{
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 0, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 3, 3, 0, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 1, 3, 1, 3, 0, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 0, 0, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, 0, 3, 2, 3, 3, 3, 3, 3, 3, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 3, 3, 3, 3, 3, 3, 2, 3,
|
||||
};
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static class EggHatchLocation9
|
||||
{
|
||||
private const byte MaskScarlet = 1 << 0; // 1
|
||||
private const byte MaskViolet = 1 << 1; // 2
|
||||
public static bool IsValidMet9SL(int location) => HasLocationFlag(LocationPermitted9, MaskScarlet, location);
|
||||
public static bool IsValidMet9VL(int location) => HasLocationFlag(LocationPermitted9, MaskViolet, location);
|
||||
|
||||
private static bool HasLocationFlag(ReadOnlySpan<byte> arr, byte mask, int location)
|
||||
{
|
||||
if ((uint)location >= arr.Length)
|
||||
return false;
|
||||
var flags = arr[location];
|
||||
return (flags & mask) != 0;
|
||||
}
|
||||
|
||||
// 130 Naranja Academy does not exist in Violet
|
||||
// 131 Uva Academy does not exist in Scarlet
|
||||
private static ReadOnlySpan<byte> LocationPermitted9 => new byte[]
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
|
||||
3, 0, 3, 0, 3, 0, 3, 0, 3, 0,
|
||||
3, 0, 3, 0, 3, 0, 3, 0, 3, 0,
|
||||
3, 0, 3, 0, 3, 0, 3, 0, 3, 0,
|
||||
3, 0, 0, 0, 3, 0, 3, 0, 3, 0,
|
||||
3, 0, 3, 0, 0, 0, 3, 0, 3, 0,
|
||||
3, 0, 3, 0, 3, 0, 0, 3, 0, 3,
|
||||
3, 0, 3, 0, 0, 0, 3, 0, 3, 0,
|
||||
3, 0, 3, 0, 3, 0, 3, 0, 3, 0,
|
||||
3, 0, 3, 0, 3, 0, 3, 0, 0, 3,
|
||||
0, 3, 0, 3, 0, 3, 0, 3, 0, 3,
|
||||
0, 3, 0, 3, 0, 3, 0, 3, 3, 0,
|
||||
0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
|
||||
1, 2,
|
||||
};
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static PKHeX.Core.LegalityCheckStrings;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
@ -27,21 +26,21 @@ public static class EncounterVerifier
|
|||
EncounterSlot w => VerifyEncounterWild(w),
|
||||
EncounterStatic s => VerifyEncounterStatic(pk, s),
|
||||
MysteryGift g => VerifyEncounterEvent(pk, g),
|
||||
_ => new CheckResult(Severity.Invalid, LEncInvalid, CheckIdentifier.Encounter),
|
||||
_ => GetInvalid(LEncInvalid),
|
||||
};
|
||||
|
||||
private static CheckResult VerifyEncounterG12(PKM pk, IEncounterTemplate enc)
|
||||
{
|
||||
if (enc.EggEncounter)
|
||||
return VerifyEncounterEgg(pk, enc.Generation);
|
||||
return VerifyEncounterEgg(pk, 2);
|
||||
|
||||
return enc switch
|
||||
{
|
||||
EncounterSlot1 => new CheckResult(Severity.Valid, LEncCondition, CheckIdentifier.Encounter),
|
||||
EncounterSlot1 => GetValid(LEncCondition),
|
||||
EncounterSlot2 s2 => VerifyWildEncounterGen2(pk, s2),
|
||||
EncounterStatic s => VerifyEncounterStatic(pk, s),
|
||||
EncounterTrade t => VerifyEncounterTrade(pk, t),
|
||||
_ => new CheckResult(Severity.Invalid, LEncInvalid, CheckIdentifier.Encounter),
|
||||
_ => GetInvalid(LEncInvalid),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -57,21 +56,21 @@ public static class EncounterVerifier
|
|||
switch (encounter.Location)
|
||||
{
|
||||
case 19: // National Park
|
||||
return new CheckResult(Severity.Invalid, LG2InvalidTilePark, CheckIdentifier.Encounter);
|
||||
return GetInvalid(LG2InvalidTilePark);
|
||||
case 76: // Route 14
|
||||
return new CheckResult(Severity.Invalid, LG2InvalidTileR14, CheckIdentifier.Encounter);
|
||||
return GetInvalid(LG2InvalidTileR14);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return new CheckResult(Severity.Valid, LEncCondition, CheckIdentifier.Encounter);
|
||||
return GetValid(LEncCondition);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyWildEncounterCrystalHeadbutt(ITrainerID32 tr, EncounterSlot2 s2)
|
||||
{
|
||||
return s2.IsTreeAvailable(tr.TID16)
|
||||
? new CheckResult(Severity.Valid, LG2TreeID, CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Invalid, LG2InvalidTileTreeNotFound, CheckIdentifier.Encounter);
|
||||
? GetValid(LG2TreeID)
|
||||
: GetInvalid(LG2InvalidTileTreeNotFound);
|
||||
}
|
||||
|
||||
// Eggs
|
||||
|
@ -86,20 +85,20 @@ public static class EncounterVerifier
|
|||
8 when GameVersion.BDSP.Contains((GameVersion)pk.Version) => pk.IsEgg ? VerifyUnhatchedEgg(pk, Locations.LinkTrade6NPC, Locations.Default8bNone) : VerifyEncounterEgg8BDSP(pk),
|
||||
8 => pk.IsEgg ? VerifyUnhatchedEgg(pk, Locations.LinkTrade6) : VerifyEncounterEgg8(pk),
|
||||
9 => pk.IsEgg ? VerifyUnhatchedEgg(pk, Locations.LinkTrade6) : VerifyEncounterEgg9(pk),
|
||||
_ => new CheckResult(Severity.Invalid, LEggLocationInvalid, CheckIdentifier.Encounter),
|
||||
_ => GetInvalid(LEggLocationInvalid),
|
||||
};
|
||||
|
||||
private static CheckResult VerifyUnhatchedEgg3(PKM pk)
|
||||
{
|
||||
if (pk.Met_Level != 0)
|
||||
return new CheckResult(Severity.Invalid, string.Format(LEggFMetLevel_0, 0), CheckIdentifier.Encounter);
|
||||
return GetInvalid(string.Format(LEggFMetLevel_0, 0));
|
||||
|
||||
// Only EncounterEgg should reach here.
|
||||
var loc = pk.FRLG ? Locations.HatchLocationFRLG : Locations.HatchLocationRSE;
|
||||
if (pk.Met_Location != loc)
|
||||
return new CheckResult(Severity.Invalid, LEggMetLocationFail, CheckIdentifier.Encounter);
|
||||
return GetInvalid(LEggMetLocationFail);
|
||||
|
||||
return new CheckResult(Severity.Valid, LEggLocation, CheckIdentifier.Encounter);
|
||||
return GetValid(LEggLocation);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterEgg3(PKM pk)
|
||||
|
@ -108,172 +107,192 @@ public static class EncounterVerifier
|
|||
return VerifyEncounterEgg3Transfer(pk);
|
||||
|
||||
if (pk.Met_Level != 0)
|
||||
return new CheckResult(Severity.Invalid, string.Format(LEggFMetLevel_0, 0), CheckIdentifier.Encounter);
|
||||
return GetInvalid(string.Format(LEggFMetLevel_0, 0));
|
||||
|
||||
// Check the origin game list.
|
||||
var met = (byte)pk.Met_Location;
|
||||
var locs = pk.FRLG ? Legal.ValidMet_FRLG : pk.E ? Legal.ValidMet_E : Legal.ValidMet_RS;
|
||||
if (locs.Contains(met))
|
||||
return new CheckResult(Severity.Valid, LEggLocation, CheckIdentifier.Encounter);
|
||||
bool valid = EggHatchLocation3.IsValidMet3(met, (GameVersion)pk.Version);
|
||||
if (valid)
|
||||
return GetValid(LEggLocation);
|
||||
|
||||
// Version isn't updated when hatching on a different game. Check any game.
|
||||
if (Legal.ValidMet_FRLG.Contains(met) || Legal.ValidMet_E.Contains(met) || Legal.ValidMet_RS.Contains(met))
|
||||
return new CheckResult(Severity.Valid, LEggLocationTrade, CheckIdentifier.Encounter);
|
||||
return new CheckResult(Severity.Invalid, LEggLocationInvalid, CheckIdentifier.Encounter);
|
||||
if (EggHatchLocation3.IsValidMet3Any(met))
|
||||
return GetValid(LEggLocationTrade);
|
||||
return GetInvalid(LEggLocationInvalid);
|
||||
}
|
||||
|
||||
private static CheckResult GetInvalid(string message, CheckIdentifier ident = CheckIdentifier.Encounter) => new(Severity.Invalid, message, ident);
|
||||
private static CheckResult GetValid(string message) => new(Severity.Valid, message, CheckIdentifier.Encounter);
|
||||
|
||||
private static CheckResult VerifyEncounterEgg3Transfer(PKM pk)
|
||||
{
|
||||
if (pk.IsEgg)
|
||||
return new CheckResult(Severity.Invalid, LTransferEgg, CheckIdentifier.Encounter);
|
||||
return GetInvalid(LTransferEgg);
|
||||
if (pk.Met_Level < 5)
|
||||
return new CheckResult(Severity.Invalid, LTransferEggMetLevel, CheckIdentifier.Encounter);
|
||||
return GetInvalid(LTransferEggMetLevel);
|
||||
|
||||
var expectEgg = pk is PB8 ? Locations.Default8bNone : 0;
|
||||
if (pk.Egg_Location != expectEgg)
|
||||
return new CheckResult(Severity.Invalid, LEggLocationNone, CheckIdentifier.Encounter);
|
||||
return GetInvalid(LEggLocationNone);
|
||||
|
||||
if (pk.Format != 4)
|
||||
{
|
||||
if (pk.Met_Location != Locations.Transfer4)
|
||||
return new CheckResult(Severity.Invalid, LTransferEggLocationTransporter, CheckIdentifier.Encounter);
|
||||
return GetInvalid(LTransferEggLocationTransporter);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pk.Met_Location != Locations.Transfer3)
|
||||
return new CheckResult(Severity.Invalid, LEggLocationPalPark, CheckIdentifier.Encounter);
|
||||
return GetInvalid(LEggLocationPalPark);
|
||||
}
|
||||
|
||||
return new CheckResult(Severity.Valid, LEggLocation, CheckIdentifier.Encounter);
|
||||
return GetValid(LEggLocation);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterEgg4(PKM pk)
|
||||
{
|
||||
if (pk.Format == 4)
|
||||
if (pk.Format != 4) // transferred
|
||||
{
|
||||
// Traded eggs don't update Version, like in future games.
|
||||
var locations = pk.WasTradedEgg ? Legal.ValidMet_4 :
|
||||
pk.HGSS ? Legal.ValidMet_HGSS :
|
||||
pk.Pt ? Legal.ValidMet_Pt :
|
||||
Legal.ValidMet_DP;
|
||||
return VerifyEncounterEggLevelLoc(pk, 0, locations);
|
||||
if (pk.IsEgg)
|
||||
return GetInvalid(LTransferEgg);
|
||||
if (pk.Met_Level < 1)
|
||||
return GetInvalid(LTransferEggMetLevel);
|
||||
if (pk.Met_Location != Locations.Transfer4)
|
||||
return GetInvalid(LTransferEggLocationTransporter);
|
||||
return GetValid(LEggLocation);
|
||||
}
|
||||
if (pk.IsEgg)
|
||||
return new CheckResult(Severity.Invalid, LTransferEgg, CheckIdentifier.Encounter);
|
||||
|
||||
// transferred
|
||||
if (pk.Met_Level < 1)
|
||||
return new CheckResult(Severity.Invalid, LTransferEggMetLevel, CheckIdentifier.Encounter);
|
||||
if (pk.Met_Location != Locations.Transfer4)
|
||||
return new CheckResult(Severity.Invalid, LTransferEggLocationTransporter, CheckIdentifier.Encounter);
|
||||
return new CheckResult(Severity.Valid, LEggLocation, CheckIdentifier.Encounter);
|
||||
// Native
|
||||
const byte level = 0;
|
||||
if (pk.Met_Level != level)
|
||||
return GetInvalid(string.Format(LEggFMetLevel_0, level));
|
||||
|
||||
var met = (ushort)pk.Met_Location;
|
||||
bool valid = EggHatchLocation4.IsValidMet4(met, (GameVersion)pk.Version);
|
||||
if (valid)
|
||||
return GetValid(LEggLocation);
|
||||
|
||||
// Version isn't updated when hatching on a different game. Check any game.
|
||||
if (EggHatchLocation4.IsValidMet4Any(met))
|
||||
return GetValid(LEggLocationTrade);
|
||||
return GetInvalid(LEggLocationInvalid);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterEgg5(PKM pk)
|
||||
{
|
||||
// Two game-specific locations we need to double check for.
|
||||
// White / White2 cannot access Black Gate (112)
|
||||
// Black / Black2 cannot access White Gate (113)
|
||||
var met = pk.Met_Location;
|
||||
var delta = (uint)(met - 112);
|
||||
if (delta <= 1)
|
||||
{
|
||||
var ver = pk.Version & 1; // W*=0, B*=1
|
||||
if (ver == delta)
|
||||
return new CheckResult(Severity.Invalid, LEggLocationInvalid, CheckIdentifier.Encounter);
|
||||
}
|
||||
return VerifyEncounterEggLevelLoc(pk, 1, pk.B2W2 ? Legal.ValidMet_B2W2 : Legal.ValidMet_BW);
|
||||
const byte level = 1;
|
||||
if (pk.Met_Level != level)
|
||||
return GetInvalid(string.Format(LEggFMetLevel_0, level));
|
||||
|
||||
var met = (ushort)pk.Met_Location;
|
||||
bool valid = EggHatchLocation5.IsValidMet5(met, (GameVersion)pk.Version);
|
||||
|
||||
if (valid)
|
||||
return GetValid(LEggLocation);
|
||||
return GetInvalid(LEggLocationInvalid);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterEgg6(PKM pk)
|
||||
{
|
||||
if (pk.AO)
|
||||
return VerifyEncounterEggLevelLoc(pk, 1, Legal.ValidMet_AO);
|
||||
const byte level = 1;
|
||||
if (pk.Met_Level != level)
|
||||
return GetInvalid(string.Format(LEggFMetLevel_0, level));
|
||||
|
||||
if (pk.Egg_Location == Locations.HatchLocation6AO) // Battle Resort Daycare is only OR/AS.
|
||||
return new CheckResult(Severity.Invalid, LEggMetLocationFail, CheckIdentifier.Encounter);
|
||||
var met = (ushort)pk.Met_Location;
|
||||
bool valid = pk.XY
|
||||
? EggHatchLocation6.IsValidMet6XY(met)
|
||||
: EggHatchLocation6.IsValidMet6AO(met);
|
||||
|
||||
return VerifyEncounterEggLevelLoc(pk, 1, Legal.ValidMet_XY);
|
||||
if (valid)
|
||||
return GetValid(LEggLocation);
|
||||
return GetInvalid(LEggLocationInvalid);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterEgg7(PKM pk)
|
||||
{
|
||||
if (pk.SM)
|
||||
return VerifyEncounterEggLevelLoc(pk, 1, Legal.ValidMet_SM);
|
||||
if (pk.USUM)
|
||||
return VerifyEncounterEggLevelLoc(pk, 1, Legal.ValidMet_USUM);
|
||||
const byte level = 1;
|
||||
if (pk.Met_Level != level)
|
||||
return GetInvalid(string.Format(LEggFMetLevel_0, level));
|
||||
|
||||
// no other games
|
||||
return new CheckResult(Severity.Invalid, LEggLocationInvalid, CheckIdentifier.Encounter);
|
||||
var met = (ushort)pk.Met_Location;
|
||||
bool valid = pk.SM
|
||||
? EggHatchLocation7.IsValidMet7SM(met)
|
||||
: EggHatchLocation7.IsValidMet7USUM(met);
|
||||
|
||||
if (valid)
|
||||
return GetValid(LEggLocation);
|
||||
return GetInvalid(LEggLocationInvalid);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterEgg8(PKM pk)
|
||||
{
|
||||
if (pk.SWSH)
|
||||
{
|
||||
if (pk.BDSP)
|
||||
return VerifyEncounterEggLevelLoc(pk, 1, (location, game) => location == (game == GameVersion.SW ? Locations.HOME_SWBD : Locations.HOME_SHSP));
|
||||
return VerifyEncounterEggLevelLoc(pk, 1, Legal.ValidMet_SWSH);
|
||||
}
|
||||
const byte level = 1;
|
||||
if (pk.Met_Level != level)
|
||||
return GetInvalid(string.Format(LEggFMetLevel_0, level));
|
||||
|
||||
// no other games
|
||||
return new CheckResult(Severity.Invalid, LEggLocationInvalid, CheckIdentifier.Encounter);
|
||||
}
|
||||
var met = (ushort)pk.Met_Location;
|
||||
bool valid = pk.BDSP // Transferred from BD/SP, now acting like a SW/SH egg.
|
||||
? Locations.IsValidMetBDSP(met, pk.Version)
|
||||
: EggHatchLocation8.IsValidMet8SWSH(met);
|
||||
|
||||
private static CheckResult VerifyEncounterEgg9(PKM pk)
|
||||
{
|
||||
if (pk.SV)
|
||||
return VerifyEncounterEggLevelLoc(pk, 1, Legal.IsValidEggHatchLocation9);
|
||||
|
||||
// no other games
|
||||
return new CheckResult(Severity.Invalid, LEggLocationInvalid, CheckIdentifier.Encounter);
|
||||
if (valid)
|
||||
return GetValid(LEggLocation);
|
||||
return GetInvalid(LEggLocationInvalid);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterEgg8BDSP(PKM pk)
|
||||
{
|
||||
if (pk.BDSP)
|
||||
return VerifyEncounterEggLevelLoc(pk, 1, Legal.IsValidEggHatchLocation8b);
|
||||
const byte level = 1;
|
||||
if (pk.Met_Level != level)
|
||||
return GetInvalid(string.Format(LEggFMetLevel_0, level));
|
||||
|
||||
// no other games
|
||||
return new CheckResult(Severity.Invalid, LEggLocationInvalid, CheckIdentifier.Encounter);
|
||||
var met = (ushort)pk.Met_Location;
|
||||
bool valid = pk.Version == (int)GameVersion.BD
|
||||
? EggHatchLocation8b.IsValidMet8BD(met)
|
||||
: EggHatchLocation8b.IsValidMet8SP(met);
|
||||
|
||||
if (valid)
|
||||
return GetValid(LEggLocation);
|
||||
return GetInvalid(LEggLocationInvalid);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterEggLevelLoc(PKM pk, int eggLevel, IReadOnlySet<ushort> MetLocations)
|
||||
private static CheckResult VerifyEncounterEgg9(PKM pk)
|
||||
{
|
||||
return VerifyEncounterEggLevelLoc(pk, eggLevel, (location, _) => MetLocations.Contains(location));
|
||||
}
|
||||
const byte level = 1;
|
||||
if (pk.Met_Level != level)
|
||||
return GetInvalid(string.Format(LEggFMetLevel_0, level));
|
||||
|
||||
// (hatch location, hatch version, bool result)
|
||||
private static CheckResult VerifyEncounterEggLevelLoc(PKM pk, int eggLevel, Func<ushort, GameVersion, bool> isValid)
|
||||
{
|
||||
if (pk.Met_Level != eggLevel)
|
||||
return new CheckResult(Severity.Invalid, string.Format(LEggFMetLevel_0, eggLevel), CheckIdentifier.Encounter);
|
||||
return isValid((ushort)pk.Met_Location, (GameVersion)pk.Version)
|
||||
? new CheckResult(Severity.Valid, LEggLocation, CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Invalid, LEggLocationInvalid, CheckIdentifier.Encounter);
|
||||
var met = (ushort)pk.Met_Location;
|
||||
bool valid = pk.Version == (int)GameVersion.SL
|
||||
? EggHatchLocation9.IsValidMet9SL(met)
|
||||
: EggHatchLocation9.IsValidMet9VL(met);
|
||||
|
||||
if (valid)
|
||||
return GetValid(LEggLocation);
|
||||
return GetInvalid(LEggLocationInvalid);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyUnhatchedEgg(PKM pk, int tradeLoc, int noneLoc = 0)
|
||||
{
|
||||
var eggLevel = pk.Format < 5 ? 0 : 1;
|
||||
if (pk.Met_Level != eggLevel)
|
||||
return new CheckResult(Severity.Invalid, string.Format(LEggFMetLevel_0, eggLevel), CheckIdentifier.Encounter);
|
||||
return GetInvalid(string.Format(LEggFMetLevel_0, eggLevel));
|
||||
if (pk.Egg_Location == tradeLoc)
|
||||
return new CheckResult(Severity.Invalid, LEggLocationTradeFail, CheckIdentifier.Encounter);
|
||||
return GetInvalid(LEggLocationTradeFail);
|
||||
|
||||
var met = pk.Met_Location;
|
||||
if (met == tradeLoc)
|
||||
return new CheckResult(Severity.Valid, LEggLocationTrade, CheckIdentifier.Encounter);
|
||||
return GetValid(LEggLocationTrade);
|
||||
return met == noneLoc
|
||||
? new CheckResult(Severity.Valid, LEggUnhatched, CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Invalid, LEggLocationNone, CheckIdentifier.Encounter);
|
||||
? GetValid(LEggUnhatched)
|
||||
: GetInvalid(LEggLocationNone);
|
||||
}
|
||||
|
||||
// Other
|
||||
private static CheckResult VerifyEncounterWild(EncounterSlot slot)
|
||||
{
|
||||
var summary = slot.GetConditionString(out bool valid);
|
||||
return new CheckResult(valid ? Severity.Valid : Severity.Invalid, summary, CheckIdentifier.Encounter);
|
||||
return valid ? GetValid(summary) : GetInvalid(summary);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterStatic(PKM pk, EncounterStatic s)
|
||||
|
@ -283,24 +302,24 @@ public static class EncounterVerifier
|
|||
{
|
||||
case 3:
|
||||
if (s is EncounterStaticShadow {EReader: true} && pk.Language != (int)LanguageID.Japanese) // Non-JP E-reader Pokemon
|
||||
return new CheckResult(Severity.Invalid, LG3EReader, CheckIdentifier.Encounter);
|
||||
return GetInvalid(LG3EReader);
|
||||
|
||||
switch (s.Species)
|
||||
{
|
||||
case (int)Species.Mew when s.Location == 201 && pk.Language != (int)LanguageID.Japanese: // Non-JP Mew (Old Sea Map)
|
||||
return new CheckResult(Severity.Invalid, LEncUnreleasedEMewJP, CheckIdentifier.Encounter);
|
||||
return GetInvalid(LEncUnreleasedEMewJP);
|
||||
case (int)Species.Deoxys when s.Location == 200 && pk.Language == (int)LanguageID.Japanese: // JP Deoxys (Birth Island)
|
||||
return new CheckResult(Severity.Invalid, LEncUnreleased, CheckIdentifier.Encounter);
|
||||
return GetInvalid(LEncUnreleased);
|
||||
}
|
||||
|
||||
break;
|
||||
case 4:
|
||||
if (s is EncounterStatic4 {Roaming: true} && pk.Met_Location == 193 && pk is IGroundTile {GroundTile:GroundTileType.Water}) // Roaming pokemon surfing in Johto Route 45
|
||||
return new CheckResult(Severity.Invalid, LG4InvalidTileR45Surf, CheckIdentifier.Encounter);
|
||||
return GetInvalid(LG4InvalidTileR45Surf);
|
||||
break;
|
||||
case 7:
|
||||
if (s.EggLocation == Locations.Daycare5 && pk.RelearnMove1 != 0) // Eevee gift egg
|
||||
return new CheckResult(Severity.Invalid, LEncStaticRelearn, CheckIdentifier.RelearnMove); // not gift egg
|
||||
return GetInvalid(LEncStaticRelearn, CheckIdentifier.RelearnMove); // not gift egg
|
||||
break;
|
||||
}
|
||||
if (s.EggEncounter && !pk.IsEgg) // hatched
|
||||
|
@ -310,7 +329,7 @@ public static class EncounterVerifier
|
|||
return hatchCheck;
|
||||
}
|
||||
|
||||
return new CheckResult(Severity.Valid, LEncStaticMatch, CheckIdentifier.Encounter);
|
||||
return GetValid(LEncStaticMatch);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterTrade(ISpeciesForm pk, EncounterTrade trade)
|
||||
|
@ -323,9 +342,9 @@ public static class EncounterVerifier
|
|||
var names = ParseSettings.SpeciesStrings;
|
||||
var evolved = names[species + 1];
|
||||
var unevolved = names[species];
|
||||
return new CheckResult(Severity.Invalid, string.Format(LEvoTradeReq, unevolved, evolved), CheckIdentifier.Encounter);
|
||||
return GetInvalid(string.Format(LEvoTradeReq, unevolved, evolved));
|
||||
}
|
||||
return new CheckResult(Severity.Valid, LEncTradeMatch, CheckIdentifier.Encounter);
|
||||
return GetValid(LEncTradeMatch);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterEvent(PKM pk, MysteryGift gift)
|
||||
|
@ -334,7 +353,7 @@ public static class EncounterVerifier
|
|||
{
|
||||
case PCD pcd:
|
||||
if (!pcd.CanBeReceivedByVersion(pk.Version) && pcd.Gift.PK.Version == 0)
|
||||
return new CheckResult(Severity.Invalid, string.Format(L_XMatches0_1, gift.CardHeader, $"-- {LEncGiftVersionNotDistributed}"), CheckIdentifier.Encounter);
|
||||
return GetInvalid(string.Format(L_XMatches0_1, gift.CardHeader, $"-- {LEncGiftVersionNotDistributed}"));
|
||||
break;
|
||||
}
|
||||
if (!pk.IsEgg && gift.IsEgg) // hatched
|
||||
|
@ -345,6 +364,6 @@ public static class EncounterVerifier
|
|||
}
|
||||
|
||||
// Strict matching already performed by EncounterGenerator. May be worth moving some checks here to better flag invalid gifts.
|
||||
return new CheckResult(Severity.Valid, string.Format(L_XMatches0_1, gift.CardHeader, string.Empty), CheckIdentifier.Encounter);
|
||||
return GetValid(string.Format(L_XMatches0_1, gift.CardHeader, string.Empty));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -153,10 +153,10 @@ public sealed class LearnGroup1 : ILearnGroup
|
|||
|
||||
private static void GetEncounterMoves(IEncounterTemplate enc, Span<ushort> moves)
|
||||
{
|
||||
if (enc.Version is GameVersion.YW or GameVersion.RBY)
|
||||
LearnSource1YW.Instance.GetEncounterMoves(enc, enc.LevelMin, moves);
|
||||
else
|
||||
LearnSource1RB.Instance.GetEncounterMoves(enc, enc.LevelMin, moves);
|
||||
ILearnSource ls = enc.Version is GameVersion.YW or GameVersion.RBY
|
||||
? LearnSource1YW.Instance
|
||||
: LearnSource1RB.Instance;
|
||||
ls.SetEncounterMoves(enc.Species, 0, enc.LevelMin, moves);
|
||||
}
|
||||
|
||||
private static void Check(Span<MoveResult> result, ReadOnlySpan<ushort> current, PKM pk, EvoCriteria evo, int stage, LearnOption option = LearnOption.Current, MoveSourceType types = MoveSourceType.All)
|
||||
|
|
|
@ -13,7 +13,7 @@ public sealed class LearnSource1RB : ILearnSource<PersonalInfo1>
|
|||
{
|
||||
public static readonly LearnSource1RB Instance = new();
|
||||
private static readonly PersonalTable1 Personal = PersonalTable.RB;
|
||||
private static readonly Learnset[] Learnsets = Legal.LevelUpRB;
|
||||
private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(Util.GetBinaryResource("lvlmove_rb.pkl"), Legal.MaxSpeciesID_1);
|
||||
private const LearnEnvironment Game = RB;
|
||||
private const int MaxSpecies = Legal.MaxSpeciesID_1;
|
||||
|
||||
|
@ -100,9 +100,8 @@ public sealed class LearnSource1RB : ILearnSource<PersonalInfo1>
|
|||
}
|
||||
}
|
||||
|
||||
public void GetEncounterMoves(ISpeciesForm enc, int level, Span<ushort> init)
|
||||
public void SetEncounterMoves(ushort species, byte form, int level, Span<ushort> init)
|
||||
{
|
||||
var species = enc.Species;
|
||||
if (!TryGetPersonal(species, 0, out var personal))
|
||||
return;
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ public sealed class LearnSource1YW : ILearnSource<PersonalInfo1>
|
|||
{
|
||||
public static readonly LearnSource1YW Instance = new();
|
||||
private static readonly PersonalTable1 Personal = PersonalTable.Y;
|
||||
private static readonly Learnset[] Learnsets = Legal.LevelUpY;
|
||||
private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(Util.GetBinaryResource("lvlmove_y.pkl"), Legal.MaxSpeciesID_1);
|
||||
private const LearnEnvironment Game = YW;
|
||||
private const int MaxSpecies = Legal.MaxSpeciesID_1;
|
||||
|
||||
|
@ -100,9 +100,8 @@ public sealed class LearnSource1YW : ILearnSource<PersonalInfo1>
|
|||
}
|
||||
}
|
||||
|
||||
public void GetEncounterMoves(ISpeciesForm enc, int level, Span<ushort> init)
|
||||
public void SetEncounterMoves(ushort species, byte form, int level, Span<ushort> init)
|
||||
{
|
||||
var species = enc.Species;
|
||||
if (!TryGetPersonal(species, 0, out var personal))
|
||||
return;
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@ public sealed class LearnSource2C : ILearnSource<PersonalInfo2>, IEggSource
|
|||
{
|
||||
public static readonly LearnSource2C Instance = new();
|
||||
private static readonly PersonalTable2 Personal = PersonalTable.C;
|
||||
private static readonly EggMoves2[] EggMoves = Legal.EggMovesC;
|
||||
private static readonly Learnset[] Learnsets = Legal.LevelUpC;
|
||||
private static readonly EggMoves2[] EggMoves = EggMoves2.GetArray(Util.GetBinaryResource("eggmove_c.pkl"), Legal.MaxSpeciesID_2);
|
||||
private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(Util.GetBinaryResource("lvlmove_c.pkl"), Legal.MaxSpeciesID_2);
|
||||
private const int MaxSpecies = Legal.MaxSpeciesID_2;
|
||||
private const LearnEnvironment Game = C;
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@ public sealed class LearnSource2GS : ILearnSource<PersonalInfo2>, IEggSource
|
|||
{
|
||||
public static readonly LearnSource2GS Instance = new();
|
||||
private static readonly PersonalTable2 Personal = PersonalTable.GS;
|
||||
private static readonly EggMoves2[] EggMoves = Legal.EggMovesGS;
|
||||
private static readonly Learnset[] Learnsets = Legal.LevelUpGS;
|
||||
private static readonly EggMoves2[] EggMoves = EggMoves2.GetArray(Util.GetBinaryResource("eggmove_gs.pkl"), Legal.MaxSpeciesID_2);
|
||||
private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(Util.GetBinaryResource("lvlmove_gs.pkl"), Legal.MaxSpeciesID_2);
|
||||
private const int MaxSpecies = Legal.MaxSpeciesID_2;
|
||||
private const LearnEnvironment Game = GS;
|
||||
|
||||
|
|
|
@ -2,19 +2,17 @@ using System;
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using static PKHeX.Core.LearnMethod;
|
||||
using static PKHeX.Core.LearnEnvironment;
|
||||
using static PKHeX.Core.LearnSource3;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Exposes information about how moves are learned in <see cref="E"/>.
|
||||
/// </summary>
|
||||
public sealed class LearnSource3E : ILearnSource<PersonalInfo3>, IEggSource
|
||||
public sealed class LearnSource3E : LearnSource3, ILearnSource<PersonalInfo3>, IEggSource
|
||||
{
|
||||
public static readonly LearnSource3E Instance = new();
|
||||
private static readonly PersonalTable3 Personal = PersonalTable.E;
|
||||
private static readonly Learnset[] Learnsets = Legal.LevelUpE;
|
||||
private static readonly EggMoves6[] EggMoves = Legal.EggMovesRS; // same for all Gen3 games
|
||||
private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_e.pkl"), "em"));
|
||||
private const int MaxSpecies = Legal.MaxSpeciesID_3;
|
||||
private const LearnEnvironment Game = E;
|
||||
private const int Generation = 3;
|
||||
|
|
|
@ -2,19 +2,17 @@ using System;
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using static PKHeX.Core.LearnMethod;
|
||||
using static PKHeX.Core.LearnEnvironment;
|
||||
using static PKHeX.Core.LearnSource3;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Exposes information about how moves are learned in <see cref="FR"/>.
|
||||
/// </summary>
|
||||
public sealed class LearnSource3FR : ILearnSource<PersonalInfo3>, IEggSource
|
||||
public sealed class LearnSource3FR : LearnSource3, ILearnSource<PersonalInfo3>, IEggSource
|
||||
{
|
||||
public static readonly LearnSource3FR Instance = new();
|
||||
private static readonly PersonalTable3 Personal = PersonalTable.FR;
|
||||
private static readonly Learnset[] Learnsets = Legal.LevelUpFR;
|
||||
private static readonly EggMoves6[] EggMoves = Legal.EggMovesRS; // same for all Gen3 games
|
||||
private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_fr.pkl"), "fr"));
|
||||
private const int MaxSpecies = Legal.MaxSpeciesID_3;
|
||||
private const LearnEnvironment Game = FR;
|
||||
private const int Generation = 3;
|
||||
|
|
|
@ -2,19 +2,17 @@ using System;
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using static PKHeX.Core.LearnMethod;
|
||||
using static PKHeX.Core.LearnEnvironment;
|
||||
using static PKHeX.Core.LearnSource3;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Exposes information about how moves are learned in <see cref="LG"/>.
|
||||
/// </summary>
|
||||
public sealed class LearnSource3LG : ILearnSource<PersonalInfo3>, IEggSource
|
||||
public sealed class LearnSource3LG : LearnSource3, ILearnSource<PersonalInfo3>, IEggSource
|
||||
{
|
||||
public static readonly LearnSource3LG Instance = new();
|
||||
private static readonly PersonalTable3 Personal = PersonalTable.LG;
|
||||
private static readonly Learnset[] Learnsets = Legal.LevelUpLG;
|
||||
private static readonly EggMoves6[] EggMoves = Legal.EggMovesRS; // same for all Gen3 games
|
||||
private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_lg.pkl"), "lg"));
|
||||
private const int MaxSpecies = Legal.MaxSpeciesID_3;
|
||||
private const LearnEnvironment Game = LG;
|
||||
private const int Generation = 3;
|
||||
|
|
|
@ -2,19 +2,17 @@ using System;
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using static PKHeX.Core.LearnMethod;
|
||||
using static PKHeX.Core.LearnEnvironment;
|
||||
using static PKHeX.Core.LearnSource3;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Exposes information about how moves are learned in <see cref="RS"/>.
|
||||
/// </summary>
|
||||
public sealed class LearnSource3RS : ILearnSource<PersonalInfo3>, IEggSource
|
||||
public sealed class LearnSource3RS : LearnSource3, ILearnSource<PersonalInfo3>, IEggSource
|
||||
{
|
||||
public static readonly LearnSource3RS Instance = new();
|
||||
private static readonly PersonalTable3 Personal = PersonalTable.RS;
|
||||
private static readonly Learnset[] Learnsets = Legal.LevelUpRS;
|
||||
private static readonly EggMoves6[] EggMoves = Legal.EggMovesRS; // same for all Gen3 games
|
||||
private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_rs.pkl"), "rs"));
|
||||
private const int MaxSpecies = Legal.MaxSpeciesID_3;
|
||||
private const LearnEnvironment Game = RS;
|
||||
private const int Generation = 3;
|
||||
|
|
|
@ -2,19 +2,17 @@ using System;
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using static PKHeX.Core.LearnMethod;
|
||||
using static PKHeX.Core.LearnEnvironment;
|
||||
using static PKHeX.Core.LearnSource4;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Exposes information about how moves are learned in <see cref="DP"/>.
|
||||
/// </summary>
|
||||
public sealed class LearnSource4DP : ILearnSource<PersonalInfo4>, IEggSource
|
||||
public sealed class LearnSource4DP : LearnSource4, ILearnSource<PersonalInfo4>, IEggSource
|
||||
{
|
||||
public static readonly LearnSource4DP Instance = new();
|
||||
private static readonly PersonalTable4 Personal = PersonalTable.DP;
|
||||
private static readonly Learnset[] Learnsets = Legal.LevelUpDP;
|
||||
private static readonly EggMoves6[] EggMoves = Legal.EggMovesDPPt;
|
||||
private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_dp.pkl"), "dp"));
|
||||
private const int MaxSpecies = Legal.MaxSpeciesID_4;
|
||||
private const LearnEnvironment Game = DP;
|
||||
private const int Generation = 4;
|
||||
|
|
|
@ -13,8 +13,8 @@ public sealed class LearnSource4HGSS : ILearnSource<PersonalInfo4>, IEggSource
|
|||
{
|
||||
public static readonly LearnSource4HGSS Instance = new();
|
||||
private static readonly PersonalTable4 Personal = PersonalTable.HGSS;
|
||||
private static readonly Learnset[] Learnsets = Legal.LevelUpHGSS;
|
||||
private static readonly EggMoves6[] EggMoves = Legal.EggMovesHGSS;
|
||||
private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_hgss.pkl"), "hs"));
|
||||
private static readonly EggMoves6[] EggMoves = EggMoves6.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("eggmove_hgss.pkl"), "hs"));
|
||||
private const int MaxSpecies = Legal.MaxSpeciesID_4;
|
||||
private const LearnEnvironment Game = HGSS;
|
||||
private const int Generation = 4;
|
||||
|
|
|
@ -2,19 +2,17 @@ using System;
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using static PKHeX.Core.LearnMethod;
|
||||
using static PKHeX.Core.LearnEnvironment;
|
||||
using static PKHeX.Core.LearnSource4;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Exposes information about how moves are learned in <see cref="Pt"/>.
|
||||
/// </summary>
|
||||
public sealed class LearnSource4Pt : ILearnSource<PersonalInfo4>, IEggSource
|
||||
public sealed class LearnSource4Pt : LearnSource4, ILearnSource<PersonalInfo4>, IEggSource
|
||||
{
|
||||
public static readonly LearnSource4Pt Instance = new();
|
||||
private static readonly PersonalTable4 Personal = PersonalTable.Pt;
|
||||
private static readonly Learnset[] Learnsets = Legal.LevelUpPt;
|
||||
private static readonly EggMoves6[] EggMoves = Legal.EggMovesDPPt;
|
||||
private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_pt.pkl"), "pt"));
|
||||
private const int MaxSpecies = Legal.MaxSpeciesID_4;
|
||||
private const LearnEnvironment Game = Pt;
|
||||
private const int Generation = 4;
|
||||
|
|
|
@ -2,19 +2,17 @@ using System;
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using static PKHeX.Core.LearnMethod;
|
||||
using static PKHeX.Core.LearnEnvironment;
|
||||
using static PKHeX.Core.LearnSource5;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Exposes information about how moves are learned in <see cref="B2W2"/>.
|
||||
/// </summary>
|
||||
public sealed class LearnSource5B2W2 : ILearnSource<PersonalInfo5B2W2>, IEggSource
|
||||
public sealed class LearnSource5B2W2 : LearnSource5, ILearnSource<PersonalInfo5B2W2>, IEggSource
|
||||
{
|
||||
public static readonly LearnSource5B2W2 Instance = new();
|
||||
private static readonly PersonalTable5B2W2 Personal = PersonalTable.B2W2;
|
||||
private static readonly Learnset[] Learnsets = Legal.LevelUpB2W2;
|
||||
private static readonly EggMoves6[] EggMoves = Legal.EggMovesBW; // same
|
||||
private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_b2w2.pkl"), "52"));
|
||||
private const int MaxSpecies = Legal.MaxSpeciesID_5;
|
||||
private const LearnEnvironment Game = B2W2;
|
||||
|
||||
|
|
|
@ -2,19 +2,17 @@ using System;
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using static PKHeX.Core.LearnMethod;
|
||||
using static PKHeX.Core.LearnEnvironment;
|
||||
using static PKHeX.Core.LearnSource5;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Exposes information about how moves are learned in <see cref="BW"/>.
|
||||
/// </summary>
|
||||
public sealed class LearnSource5BW : ILearnSource<PersonalInfo5BW>, IEggSource
|
||||
public sealed class LearnSource5BW : LearnSource5, ILearnSource<PersonalInfo5BW>, IEggSource
|
||||
{
|
||||
public static readonly LearnSource5BW Instance = new();
|
||||
private static readonly PersonalTable5BW Personal = PersonalTable.BW;
|
||||
private static readonly Learnset[] Learnsets = Legal.LevelUpBW;
|
||||
private static readonly EggMoves6[] EggMoves = Legal.EggMovesBW;
|
||||
private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_bw.pkl"), "51"));
|
||||
private const int MaxSpecies = Legal.MaxSpeciesID_5;
|
||||
private const LearnEnvironment Game = BW;
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@ public sealed class LearnSource6AO : ILearnSource<PersonalInfo6AO>, IEggSource
|
|||
{
|
||||
public static readonly LearnSource6AO Instance = new();
|
||||
private static readonly PersonalTable6AO Personal = PersonalTable.AO;
|
||||
private static readonly Learnset[] Learnsets = Legal.LevelUpAO;
|
||||
private static readonly EggMoves6[] EggMoves = Legal.EggMovesAO;
|
||||
private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_ao.pkl"), "ao"));
|
||||
private static readonly EggMoves6[] EggMoves = EggMoves6.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("eggmove_ao.pkl"), "ao"));
|
||||
private const int MaxSpecies = Legal.MaxSpeciesID_6;
|
||||
private const LearnEnvironment Game = ORAS;
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@ public sealed class LearnSource6XY : ILearnSource<PersonalInfo6XY>, IEggSource
|
|||
{
|
||||
public static readonly LearnSource6XY Instance = new();
|
||||
private static readonly PersonalTable6XY Personal = PersonalTable.XY;
|
||||
private static readonly Learnset[] Learnsets = Legal.LevelUpXY;
|
||||
private static readonly EggMoves6[] EggMoves = Legal.EggMovesXY;
|
||||
private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_xy.pkl"), "xy"));
|
||||
private static readonly EggMoves6[] EggMoves = EggMoves6.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("eggmove_xy.pkl"), "xy"));
|
||||
private const int MaxSpecies = Legal.MaxSpeciesID_6;
|
||||
private const LearnEnvironment Game = XY;
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ public sealed class LearnSource7GG : ILearnSource<PersonalInfo7GG>
|
|||
{
|
||||
public static readonly LearnSource7GG Instance = new();
|
||||
private static readonly PersonalTable7GG Personal = PersonalTable.GG;
|
||||
private static readonly Learnset[] Learnsets = Legal.LevelUpGG;
|
||||
private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_gg.pkl"), "gg"));
|
||||
private const int MaxSpecies = Legal.MaxSpeciesID_7b;
|
||||
private const LearnEnvironment Game = GG;
|
||||
private const int ReminderBonus = 100; // Move reminder allows re-learning ALL level up moves regardless of level.
|
||||
|
|
|
@ -13,8 +13,8 @@ public sealed class LearnSource7SM : ILearnSource<PersonalInfo7>, IEggSource
|
|||
{
|
||||
public static readonly LearnSource7SM Instance = new();
|
||||
private static readonly PersonalTable7 Personal = PersonalTable.SM;
|
||||
private static readonly Learnset[] Learnsets = Legal.LevelUpSM;
|
||||
private static readonly EggMoves7[] EggMoves = Legal.EggMovesSM;
|
||||
private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_sm.pkl"), "sm"));
|
||||
private static readonly EggMoves7[] EggMoves = EggMoves7.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("eggmove_sm.pkl"), "sm"));
|
||||
private const int MaxSpecies = Legal.MaxSpeciesID_7;
|
||||
private const LearnEnvironment Game = SM;
|
||||
private const int ReminderBonus = 100; // Move reminder allows re-learning ALL level up moves regardless of level.
|
||||
|
@ -34,15 +34,15 @@ public sealed class LearnSource7SM : ILearnSource<PersonalInfo7>, IEggSource
|
|||
{
|
||||
if (species > MaxSpecies)
|
||||
return false;
|
||||
var moves = MoveEgg.GetFormEggMoves(species, form, EggMoves).AsSpan();
|
||||
return moves.IndexOf(move) != -1;
|
||||
var moves = EggMoves.GetFormEggMoves(species, form);
|
||||
return moves.Contains(move);
|
||||
}
|
||||
|
||||
public ReadOnlySpan<ushort> GetEggMoves(ushort species, byte form)
|
||||
{
|
||||
if (species > MaxSpecies)
|
||||
return ReadOnlySpan<ushort>.Empty;
|
||||
return MoveEgg.GetFormEggMoves(species, form, EggMoves);
|
||||
return EggMoves.GetFormEggMoves(species, form);
|
||||
}
|
||||
|
||||
public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo7 pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current)
|
||||
|
|
|
@ -13,8 +13,8 @@ public sealed class LearnSource7USUM : ILearnSource<PersonalInfo7>, IEggSource
|
|||
{
|
||||
public static readonly LearnSource7USUM Instance = new();
|
||||
private static readonly PersonalTable7 Personal = PersonalTable.USUM;
|
||||
private static readonly Learnset[] Learnsets = Legal.LevelUpUSUM;
|
||||
private static readonly EggMoves7[] EggMoves = Legal.EggMovesUSUM;
|
||||
private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_uu.pkl"), "uu"));
|
||||
private static readonly EggMoves7[] EggMoves = EggMoves7.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("eggmove_uu.pkl"), "uu"));
|
||||
private const int MaxSpecies = Legal.MaxSpeciesID_7_USUM;
|
||||
private const LearnEnvironment Game = USUM;
|
||||
private const int ReminderBonus = 100; // Move reminder allows re-learning ALL level up moves regardless of level.
|
||||
|
@ -34,15 +34,15 @@ public sealed class LearnSource7USUM : ILearnSource<PersonalInfo7>, IEggSource
|
|||
{
|
||||
if (species > MaxSpecies)
|
||||
return false;
|
||||
var moves = MoveEgg.GetFormEggMoves(species, form, EggMoves).AsSpan();
|
||||
return moves.IndexOf(move) != -1;
|
||||
var moves = EggMoves.GetFormEggMoves(species, form);
|
||||
return moves.Contains(move);
|
||||
}
|
||||
|
||||
public ReadOnlySpan<ushort> GetEggMoves(ushort species, byte form)
|
||||
{
|
||||
if (species > MaxSpecies)
|
||||
return ReadOnlySpan<ushort>.Empty;
|
||||
return MoveEgg.GetFormEggMoves(species, form, EggMoves);
|
||||
return EggMoves.GetFormEggMoves(species, form);
|
||||
}
|
||||
|
||||
public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo7 pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current)
|
||||
|
|
|
@ -12,8 +12,8 @@ public sealed class LearnSource8BDSP : ILearnSource<PersonalInfo8BDSP>, IEggSour
|
|||
{
|
||||
public static readonly LearnSource8BDSP Instance = new();
|
||||
private static readonly PersonalTable8BDSP Personal = PersonalTable.BDSP;
|
||||
private static readonly Learnset[] Learnsets = Legal.LevelUpBDSP;
|
||||
private static readonly EggMoves6[] EggMoves = Legal.EggMovesBDSP;
|
||||
private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_bdsp.pkl"), "bs"));
|
||||
private static readonly EggMoves6[] EggMoves = EggMoves6.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("eggmove_bdsp.pkl"), "bs"));
|
||||
private const int MaxSpecies = Legal.MaxSpeciesID_8b;
|
||||
private const LearnEnvironment Game = BDSP;
|
||||
|
||||
|
|
|
@ -12,12 +12,19 @@ public sealed class LearnSource8LA : ILearnSource<PersonalInfo8LA>
|
|||
{
|
||||
public static readonly LearnSource8LA Instance = new();
|
||||
private static readonly PersonalTable8LA Personal = PersonalTable.LA;
|
||||
private static readonly Learnset[] Learnsets = Legal.LevelUpLA;
|
||||
private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_la.pkl"), "la"));
|
||||
private static readonly Learnset[] Mastery = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("mastery_la.pkl"), "la"));
|
||||
private const int MaxSpecies = Legal.MaxSpeciesID_8a;
|
||||
private const LearnEnvironment Game = PLA;
|
||||
|
||||
public Learnset GetLearnset(ushort species, byte form) => Learnsets[Personal.GetFormIndex(species, form)];
|
||||
|
||||
public static (Learnset Learn, Learnset Mastery) GetLearnsetAndMastery(ushort species, byte form)
|
||||
{
|
||||
var index = Personal.GetFormIndex(species, form);
|
||||
return (Learnsets[index], Mastery[index]);
|
||||
}
|
||||
|
||||
public bool TryGetPersonal(ushort species, byte form, [NotNullWhen(true)] out PersonalInfo8LA? pi)
|
||||
{
|
||||
pi = null;
|
||||
|
|
|
@ -12,8 +12,8 @@ public sealed class LearnSource8SWSH : ILearnSource<PersonalInfo8SWSH>, IEggSour
|
|||
{
|
||||
public static readonly LearnSource8SWSH Instance = new();
|
||||
private static readonly PersonalTable8SWSH Personal = PersonalTable.SWSH;
|
||||
private static readonly Learnset[] Learnsets = Legal.LevelUpSWSH;
|
||||
private static readonly EggMoves7[] EggMoves = Legal.EggMovesSWSH;
|
||||
private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_swsh.pkl"), "ss"));
|
||||
private static readonly EggMoves7[] EggMoves = EggMoves7.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("eggmove_swsh.pkl"), "ss"));
|
||||
private const int MaxSpecies = Legal.MaxSpeciesID_8_R2;
|
||||
private const LearnEnvironment Game = SWSH;
|
||||
|
||||
|
@ -32,15 +32,15 @@ public sealed class LearnSource8SWSH : ILearnSource<PersonalInfo8SWSH>, IEggSour
|
|||
{
|
||||
if (species > MaxSpecies)
|
||||
return false;
|
||||
var moves = MoveEgg.GetFormEggMoves(species, form, EggMoves).AsSpan();
|
||||
return moves.IndexOf(move) != -1;
|
||||
var moves = EggMoves.GetFormEggMoves(species, form);
|
||||
return moves.Contains(move);
|
||||
}
|
||||
|
||||
public ReadOnlySpan<ushort> GetEggMoves(ushort species, byte form)
|
||||
{
|
||||
if (species > MaxSpecies)
|
||||
return ReadOnlySpan<ushort>.Empty;
|
||||
return MoveEgg.GetFormEggMoves(species, form, EggMoves);
|
||||
return EggMoves.GetFormEggMoves(species, form);
|
||||
}
|
||||
|
||||
public MoveLearnInfo GetCanLearn(PKM pk, PersonalInfo8SWSH pi, EvoCriteria evo, ushort move, MoveSourceType types = MoveSourceType.All, LearnOption option = LearnOption.Current)
|
||||
|
|
|
@ -12,9 +12,9 @@ public sealed class LearnSource9SV : ILearnSource<PersonalInfo9SV>, IEggSource,
|
|||
{
|
||||
public static readonly LearnSource9SV Instance = new();
|
||||
private static readonly PersonalTable9SV Personal = PersonalTable.SV;
|
||||
private static readonly Learnset[] Learnsets = Legal.LevelUpSV;
|
||||
private static readonly ushort[][] EggMoves = Legal.EggMovesSV;
|
||||
private static readonly ushort[][] Reminder = Legal.ReminderSV;
|
||||
private static readonly Learnset[] Learnsets = LearnsetReader.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("lvlmove_sv.pkl"), "sv"));
|
||||
private static readonly ushort[][] EggMoves = EggMoves9.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("eggmove_sv.pkl"), "sv"));
|
||||
private static readonly ushort[][] Reminder = EggMoves9.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("reminder_sv.pkl"), "sv"));
|
||||
private const int MaxSpecies = Legal.MaxSpeciesID_9;
|
||||
private const LearnEnvironment Game = SV;
|
||||
|
||||
|
|
|
@ -23,6 +23,15 @@ public interface ILearnSource
|
|||
/// <param name="species">Entity species</param>
|
||||
/// <param name="form">Entity form</param>
|
||||
public Learnset GetLearnset(ushort species, byte form);
|
||||
|
||||
public void SetEncounterMoves(ushort species, byte form, int level, Span<ushort> init)
|
||||
{
|
||||
var start = (init.LastIndexOfAnyExcept<ushort>(0) + 1) & 3;
|
||||
var learn = GetLearnset(species, form);
|
||||
learn.SetEncounterMoves(level, init, start);
|
||||
}
|
||||
|
||||
public ReadOnlySpan<ushort> GetEggMoves(ushort species, byte form) => ReadOnlySpan<ushort>.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -2,8 +2,10 @@ using System;
|
|||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
internal static class LearnSource3
|
||||
public abstract class LearnSource3
|
||||
{
|
||||
private protected readonly EggMoves6[] EggMoves = EggMoves6.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("eggmove_rs.pkl"), "rs")); // same for all Gen3 games
|
||||
|
||||
internal static ReadOnlySpan<ushort> TM_3 => new ushort[]
|
||||
{
|
||||
264, 337, 352, 347, 046, 092, 258, 339, 331, 237,
|
||||
|
|
|
@ -2,8 +2,10 @@ using System;
|
|||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
internal static class LearnSource4
|
||||
public abstract class LearnSource4
|
||||
{
|
||||
private protected static readonly EggMoves6[] EggMoves = EggMoves6.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("eggmove_dppt.pkl"), "dp"));
|
||||
|
||||
/// <summary>
|
||||
/// Gets the preferred list of HM moves to disallow on transfer from <see cref="PK4"/> to <see cref="PK5"/>.
|
||||
/// </summary>
|
||||
|
|
|
@ -2,8 +2,10 @@ using System;
|
|||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
internal static class LearnSource5
|
||||
public abstract class LearnSource5
|
||||
{
|
||||
private protected readonly EggMoves6[] EggMoves = EggMoves6.GetArray(BinLinkerAccessor.Get(Util.GetBinaryResource("eggmove_bw.pkl"), "bw"));
|
||||
|
||||
internal static ReadOnlySpan<ushort> TMHM_BW => new ushort[]
|
||||
{
|
||||
468, 337, 473, 347, 046, 092, 258, 339, 474, 237,
|
||||
|
|
|
@ -31,7 +31,9 @@ internal static class LearnVerifierEgg
|
|||
}
|
||||
else
|
||||
{
|
||||
ReadOnlySpan<ushort> initial = GameData.GetLearnset(enc.Version, enc.Species, enc.Form).GetBaseEggMoves(enc.LevelMin);
|
||||
var ls = GameData.GetLearnSource(enc.Version);
|
||||
var learn = ls.GetLearnset(enc.Species, enc.Form);
|
||||
var initial = learn.GetBaseEggMoves(enc.LevelMin);
|
||||
VerifyMovesInitial(result, current, initial);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,6 +125,30 @@ public sealed class EggMoves7 : EggMoves
|
|||
}
|
||||
}
|
||||
|
||||
internal static class EggMovesExtensions
|
||||
{
|
||||
public static ReadOnlySpan<ushort> GetFormEggMoves(this EggMoves7[] table, ushort species, byte form)
|
||||
{
|
||||
if (species >= table.Length)
|
||||
return ReadOnlySpan<ushort>.Empty;
|
||||
|
||||
var entry = table[species];
|
||||
if (form == 0 || species >= entry.FormTableIndex)
|
||||
return entry.Moves;
|
||||
|
||||
// Sanity check form in the event it is out of range.
|
||||
var baseIndex = entry.FormTableIndex;
|
||||
var index = baseIndex + form - 1;
|
||||
if ((uint)index >= table.Length)
|
||||
return ReadOnlySpan<ushort>.Empty;
|
||||
entry = table[index];
|
||||
if (entry.FormTableIndex != baseIndex)
|
||||
return ReadOnlySpan<ushort>.Empty;
|
||||
|
||||
return entry.Moves;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raw Egg Move storage
|
||||
/// </summary>
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
using System;
|
||||
using static PKHeX.Core.Legal;
|
||||
using static PKHeX.Core.GameVersion;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Logic for obtaining a list of moves.
|
||||
/// </summary>
|
||||
internal static class MoveList
|
||||
{
|
||||
internal static void GetCurrentMoves(PKM pk, ushort species, byte form, GameVersion gameSource, int lvl, Span<ushort> moves) => _ = gameSource switch
|
||||
{
|
||||
GSC or GS => Get(moves, LevelUpGS, species, lvl, pk.Format),
|
||||
C => Get(moves, LevelUpC, species, lvl, pk.Format),
|
||||
|
||||
R or S or RS => Get(moves, LevelUpRS, species, lvl),
|
||||
E => Get(moves, LevelUpE, species, lvl),
|
||||
FR or LG or FRLG => Get(moves, LevelUpFR, species, lvl),
|
||||
|
||||
D or P or DP => Get(moves, LevelUpDP, species, lvl),
|
||||
Pt => Get(moves, LevelUpPt, species, lvl),
|
||||
HG or SS or HGSS => Get(moves, LevelUpHGSS, species, lvl),
|
||||
|
||||
B or W or BW => Get(moves, LevelUpBW, species, lvl),
|
||||
B2 or W2 or B2W2 => Get(moves, LevelUpB2W2, species, lvl),
|
||||
|
||||
X or Y or XY => Get(moves, LevelUpXY, species, lvl),
|
||||
AS or OR or ORAS => Get(moves, LevelUpAO, species, lvl),
|
||||
|
||||
SN or MN or SM => Get(moves, LevelUpSM, PersonalTable.SM, species, form, lvl),
|
||||
US or UM or USUM => Get(moves, LevelUpUSUM, PersonalTable.USUM, species, form, lvl),
|
||||
SW or SH or SWSH => Get(moves, LevelUpSWSH, PersonalTable.SWSH, species, form, lvl),
|
||||
BD or SP or BDSP => Get(moves, LevelUpBDSP, PersonalTable.BDSP, species, form, lvl),
|
||||
PLA => Get(moves, LevelUpLA, PersonalTable.LA, species, form, lvl),
|
||||
|
||||
SL or VL or SV => Get(moves, LevelUpSV, PersonalTable.SV, species, form, lvl),
|
||||
|
||||
_ => moves,
|
||||
};
|
||||
|
||||
private static Span<ushort> Get(Span<ushort> moves, Learnset[] source, ushort species, int lvl)
|
||||
{
|
||||
if (species >= source.Length)
|
||||
return moves;
|
||||
source[species].SetLevelUpMoves(1, lvl, moves);
|
||||
return moves;
|
||||
}
|
||||
|
||||
private static Span<ushort> Get<T>(Span<ushort> moves, Learnset[] source, T pt, ushort species, byte form, int lvl) where T : IPersonalTable
|
||||
{
|
||||
if (!pt.IsPresentInGame(species, form))
|
||||
return moves;
|
||||
|
||||
int index = pt.GetFormIndex(species, form);
|
||||
source[index].SetLevelUpMoves(1, lvl, moves);
|
||||
return moves;
|
||||
}
|
||||
|
||||
private static Span<ushort> Get(Span<ushort> moves, Learnset[] source, ushort species, int lvl, int format)
|
||||
{
|
||||
if (species > MaxSpeciesID_2)
|
||||
return moves;
|
||||
|
||||
source[species].SetLevelUpMoves(1, lvl, moves);
|
||||
if (format != 1)
|
||||
return moves;
|
||||
|
||||
// If checking back-transfer specimen (GSC->RBY), remove moves that must be deleted prior to transfer
|
||||
// Remove all values greater than MaxMoveID_1, and shift the remaining indexes down.
|
||||
for (int i = 0; i < moves.Length; i++)
|
||||
{
|
||||
if (moves[i] <= MaxMoveID_1)
|
||||
continue;
|
||||
// Shift remaining indexes down, set last index to 0
|
||||
for (int j = i; j < moves.Length - 1; j++)
|
||||
moves[j] = moves[j + 1];
|
||||
|
||||
moves[^1] = 0;
|
||||
}
|
||||
|
||||
return moves;
|
||||
}
|
||||
}
|
|
@ -12,7 +12,8 @@ public static class MoveListSuggest
|
|||
{
|
||||
if (pk is { IsEgg: true, Format: <= 5 }) // pre relearn
|
||||
{
|
||||
MoveList.GetCurrentMoves(pk, pk.Species, 0, (GameVersion)pk.Version, pk.CurrentLevel, moves);
|
||||
var source = GameData.GetLearnSource(enc.Version);
|
||||
source.SetEncounterMoves(enc.Species, 0, enc.LevelMin, moves);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -26,14 +27,16 @@ public static class MoveListSuggest
|
|||
if (enc.Generation <= 2)
|
||||
{
|
||||
var lvl = pk.Format >= 7 ? pk.Met_Level : pk.CurrentLevel;
|
||||
var ver = enc.Version;
|
||||
MoveLevelUp.GetEncounterMoves(moves, enc.Species, 0, lvl, ver);
|
||||
var source = GameData.GetLearnSource(enc.Version);
|
||||
source.SetEncounterMoves(enc.Species, 0, lvl, moves);
|
||||
return;
|
||||
}
|
||||
|
||||
if (pk.Species == enc.Species)
|
||||
{
|
||||
MoveLevelUp.GetEncounterMoves(moves, pk.Species, pk.Form, pk.CurrentLevel, (GameVersion)pk.Version);
|
||||
var game = (GameVersion)pk.Version; // account for SW/SH foreign mutated versions
|
||||
var source = GameData.GetLearnSource(game);
|
||||
source.SetEncounterMoves(pk.Species, pk.Form, pk.CurrentLevel, moves);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -73,10 +73,8 @@ public static class MoveBreed
|
|||
|
||||
// Well, that didn't work; probably because one or more moves aren't valid.
|
||||
// Let's remove all present base moves, and get a fresh set of base moves.
|
||||
var learn = GameData.GetLearnsets(version);
|
||||
var table = GameData.GetPersonal(version);
|
||||
var index = table.GetFormIndex(species, form);
|
||||
var learnset = learn[index];
|
||||
var learn = GameData.GetLearnSource(version);
|
||||
var learnset = learn.GetLearnset(species, form);
|
||||
var eggLevel = EggStateLegality.GetEggLevel(generation);
|
||||
var baseMoves = learnset.GetBaseEggMoves(eggLevel);
|
||||
|
||||
|
|
|
@ -23,22 +23,21 @@ public static class MoveBreed2
|
|||
if (count == -1)
|
||||
count = moves.Length;
|
||||
|
||||
(Learnset[] learn, PersonalTable2 table) = version == GameVersion.C
|
||||
? (Legal.LevelUpC, PersonalTable.C)
|
||||
: (Legal.LevelUpGS, PersonalTable.GS);
|
||||
if (!table.IsSpeciesInGame(species))
|
||||
ILearnSource<PersonalInfo2> ls = version == GameVersion.C ? LearnSource2C.Instance : LearnSource2GS.Instance;
|
||||
if (!ls.TryGetPersonal(species, 0, out var pi))
|
||||
return false;
|
||||
|
||||
var learnset = learn[species];
|
||||
var pi = table[species];
|
||||
var egg = (version == GameVersion.C ? Legal.EggMovesC : Legal.EggMovesGS)[species].Moves;
|
||||
var learnset = ls.GetLearnset(species, 0);
|
||||
var eggMoves = version == GameVersion.C
|
||||
? LearnSource2C.Instance.GetEggMoves(species, 0)
|
||||
: LearnSource2GS.Instance.GetEggMoves(species, 0);
|
||||
|
||||
var actual = MemoryMarshal.Cast<byte, EggSource2>(origins);
|
||||
Span<byte> possible = stackalloc byte[count];
|
||||
var value = new BreedInfo<EggSource2>(actual, possible, learnset, moves, level);
|
||||
|
||||
bool inherit = Breeding.GetCanInheritMoves(species);
|
||||
MarkMovesForOrigin(value, egg, count, inherit, pi, version);
|
||||
MarkMovesForOrigin(value, eggMoves, count, inherit, pi, version);
|
||||
var valid = RecurseMovesForOrigin(value, count - 1);
|
||||
if (!valid)
|
||||
CleanResult(actual, possible);
|
||||
|
|
|
@ -24,20 +24,19 @@ public static class MoveBreed3
|
|||
if (count == -1)
|
||||
count = moves.Length;
|
||||
|
||||
(Learnset[] learn, PersonalTable3 table) = version switch
|
||||
ILearnSource<PersonalInfo3> ls = version switch
|
||||
{
|
||||
R or S => (Legal.LevelUpRS, PersonalTable.RS),
|
||||
E => (Legal.LevelUpE, PersonalTable.E ),
|
||||
FR => (Legal.LevelUpFR, PersonalTable.FR),
|
||||
LG => (Legal.LevelUpLG, PersonalTable.LG),
|
||||
_ => throw new ArgumentException($"Invalid version: {version}"),
|
||||
R => LearnSource3RS.Instance,
|
||||
S => LearnSource3RS.Instance,
|
||||
E => LearnSource3E.Instance,
|
||||
FR => LearnSource3FR.Instance,
|
||||
LG => LearnSource3LG.Instance,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(version), version, $"Invalid version: {version}"),
|
||||
};
|
||||
if (!table.IsSpeciesInGame(species))
|
||||
if (!ls.TryGetPersonal(species, 0, out var pi))
|
||||
return false;
|
||||
|
||||
var learnset = learn[species];
|
||||
var pi = table[species];
|
||||
|
||||
var learnset = ls.GetLearnset(species, 0);
|
||||
var actual = MemoryMarshal.Cast<byte, EggSource34>(origins);
|
||||
Span<byte> possible = stackalloc byte[count];
|
||||
var value = new BreedInfo<EggSource34>(actual, possible, learnset, moves, level);
|
||||
|
@ -51,7 +50,7 @@ public static class MoveBreed3
|
|||
}
|
||||
else
|
||||
{
|
||||
var egg = Legal.EggMovesRS[species].Moves;
|
||||
var egg = ls.GetEggMoves(species, 0);
|
||||
bool inherit = Breeding.GetCanInheritMoves(species);
|
||||
MarkMovesForOrigin(value, egg, count, inherit, pi);
|
||||
valid = RecurseMovesForOrigin(value, count - 1);
|
||||
|
|
|
@ -24,8 +24,8 @@ public static class MoveBreed4
|
|||
if (count == -1)
|
||||
count = moves.Length;
|
||||
|
||||
var learn = GameData.GetLearnsets(version);
|
||||
var learnset = learn[species];
|
||||
var learn = GameData.GetLearnSource(version);
|
||||
var learnset = learn.GetLearnset(species, 0);
|
||||
var table = version switch
|
||||
{
|
||||
HG or SS => PersonalTable.HGSS,
|
||||
|
@ -48,8 +48,10 @@ public static class MoveBreed4
|
|||
else
|
||||
{
|
||||
bool inherit = Breeding.GetCanInheritMoves(species);
|
||||
var egg = (version is HG or SS ? Legal.EggMovesHGSS : Legal.EggMovesDPPt)[species].Moves;
|
||||
MarkMovesForOrigin(value, egg, count, inherit, pi, version);
|
||||
var eggMoves = version is HG or SS
|
||||
? LearnSource4HGSS.Instance.GetEggMoves(species, 0)
|
||||
: LearnSource4DP.Instance.GetEggMoves(species, 0);
|
||||
MarkMovesForOrigin(value, eggMoves, count, inherit, pi, version);
|
||||
valid = RecurseMovesForOrigin(value, count - 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@ public static class MoveBreed5
|
|||
if (count == -1)
|
||||
count = moves.Length;
|
||||
|
||||
var learn = GameData.GetLearnsets(version);
|
||||
var learnset = learn[species];
|
||||
var learn = GameData.GetLearnSource(version);
|
||||
var learnset = learn.GetLearnset(species, 0);
|
||||
IPersonalInfoTM pi = version switch
|
||||
{
|
||||
GameVersion.B or GameVersion.W => PersonalTable.BW[species],
|
||||
|
@ -44,7 +44,7 @@ public static class MoveBreed5
|
|||
else
|
||||
{
|
||||
bool inherit = Breeding.GetCanInheritMoves(species);
|
||||
var egg = Legal.EggMovesBW[species].Moves;
|
||||
var egg = LearnSource5BW.Instance.GetEggMoves(species, 0);
|
||||
MarkMovesForOrigin(value, egg, count, inherit, pi);
|
||||
valid = RecurseMovesForOrigin(value, count - 1);
|
||||
}
|
||||
|
|
|
@ -22,10 +22,8 @@ public static class MoveBreed6
|
|||
if (count == -1)
|
||||
count = moves.Length;
|
||||
|
||||
var learn = GameData.GetLearnsets(version);
|
||||
var table = GameData.GetPersonal(version);
|
||||
var index = table.GetFormIndex(species, form);
|
||||
var learnset = learn[index];
|
||||
var learn = GameData.GetLearnSource(version);
|
||||
var learnset = learn.GetLearnset(species, form);
|
||||
|
||||
var actual = MemoryMarshal.Cast<byte, EggSource6>(origins);
|
||||
Span<byte> possible = stackalloc byte[count];
|
||||
|
@ -40,7 +38,7 @@ public static class MoveBreed6
|
|||
}
|
||||
else
|
||||
{
|
||||
var egg = MoveEgg.GetEggMoves(generation, species, form, version);
|
||||
var egg = learn.GetEggMoves(species, form);
|
||||
bool inherit = Breeding.GetCanInheritMoves(species);
|
||||
MarkMovesForOrigin(value, egg, count, inherit);
|
||||
valid = RecurseMovesForOrigin(value, count - 1);
|
||||
|
|
|
@ -5,62 +5,53 @@ namespace PKHeX.Core;
|
|||
|
||||
public static class GameData
|
||||
{
|
||||
public static Learnset[] GetLearnsets(GameVersion game) => Learnsets(game);
|
||||
public static IPersonalTable GetPersonal(GameVersion game) => Personal(game);
|
||||
|
||||
public static Learnset GetLearnset(GameVersion game, ushort species, byte form)
|
||||
public static ILearnSource GetLearnSource(GameVersion game) => game switch
|
||||
{
|
||||
var pt = Personal(game);
|
||||
var index = pt.GetFormIndex(species, form);
|
||||
var sets = Learnsets(game);
|
||||
return sets[index];
|
||||
}
|
||||
RD or GN or BU or RB => LearnSource1RB.Instance,
|
||||
YW or RBY => LearnSource1YW.Instance,
|
||||
GD or SI or GS => LearnSource2GS.Instance,
|
||||
C or GSC => LearnSource2C.Instance,
|
||||
|
||||
private static Learnset[] Learnsets(GameVersion game) => game switch
|
||||
{
|
||||
RD or GN or BU or RB => Legal.LevelUpRB,
|
||||
YW or RBY => Legal.LevelUpY,
|
||||
GD or SI or GS => Legal.LevelUpGS,
|
||||
C or GSC => Legal.LevelUpC,
|
||||
R or S or RS or RSE => LearnSource3RS.Instance,
|
||||
E or COLO or XD or FRLG or CXD => LearnSource3E.Instance,
|
||||
FR => LearnSource3FR.Instance,
|
||||
LG => LearnSource3LG.Instance,
|
||||
|
||||
R or S or RS or RSE => Legal.LevelUpRS,
|
||||
E or COLO or XD or FRLG or CXD => Legal.LevelUpE,
|
||||
FR => Legal.LevelUpFR,
|
||||
LG => Legal.LevelUpLG,
|
||||
D or P or DP => LearnSource4DP.Instance,
|
||||
Pt or DPPt => LearnSource4Pt.Instance,
|
||||
HG or SS or HGSS => LearnSource4HGSS.Instance,
|
||||
|
||||
D or P or DP => Legal.LevelUpDP,
|
||||
Pt or DPPt => Legal.LevelUpPt,
|
||||
HG or SS or HGSS => Legal.LevelUpHGSS,
|
||||
B or W or BW => LearnSource5BW.Instance,
|
||||
B2 or W2 or B2W2 => LearnSource5B2W2.Instance,
|
||||
|
||||
B or W or BW => Legal.LevelUpBW,
|
||||
B2 or W2 or B2W2 => Legal.LevelUpB2W2,
|
||||
X or Y or XY => LearnSource6XY.Instance,
|
||||
AS or OR or ORAS => LearnSource6AO.Instance,
|
||||
|
||||
X or Y or XY => Legal.LevelUpXY,
|
||||
AS or OR or ORAS => Legal.LevelUpAO,
|
||||
SN or MN or SM => LearnSource7SM.Instance,
|
||||
US or UM or USUM => LearnSource7USUM.Instance,
|
||||
GO or GP or GE or GG => LearnSource7GG.Instance,
|
||||
|
||||
SN or MN or SM => Legal.LevelUpSM,
|
||||
US or UM or USUM => Legal.LevelUpUSUM,
|
||||
GO or GP or GE or GG => Legal.LevelUpGG,
|
||||
SW or SH or SWSH => LearnSource8SWSH.Instance,
|
||||
BD or SP or BDSP => LearnSource8BDSP.Instance,
|
||||
PLA => LearnSource8LA.Instance,
|
||||
|
||||
SW or SH or SWSH => Legal.LevelUpSWSH,
|
||||
BD or SP or BDSP => Legal.LevelUpBDSP,
|
||||
PLA => Legal.LevelUpLA,
|
||||
SL or VL or SV => LearnSource9SV.Instance,
|
||||
|
||||
SL or VL or SV => Legal.LevelUpSV,
|
||||
Gen1 => LearnSource1YW.Instance,
|
||||
Gen2 => LearnSource2C.Instance,
|
||||
Gen3 => LearnSource3E.Instance,
|
||||
Gen4 => LearnSource4HGSS.Instance,
|
||||
Gen5 => LearnSource5B2W2.Instance,
|
||||
Gen6 => LearnSource6AO.Instance,
|
||||
Gen7 => LearnSource7USUM.Instance,
|
||||
Gen7b => LearnSource7GG.Instance,
|
||||
Gen8 => LearnSource8BDSP.Instance,
|
||||
Gen9 => LearnSource9SV.Instance,
|
||||
|
||||
Gen1 => Legal.LevelUpY,
|
||||
Gen2 => Legal.LevelUpC,
|
||||
Gen3 => Legal.LevelUpE,
|
||||
Gen4 => Legal.LevelUpHGSS,
|
||||
Gen5 => Legal.LevelUpB2W2,
|
||||
Gen6 => Legal.LevelUpAO,
|
||||
Gen7 => Legal.LevelUpSM,
|
||||
Gen7b => Legal.LevelUpGG,
|
||||
Gen8 => Legal.LevelUpSWSH,
|
||||
Gen9 => Legal.LevelUpSV,
|
||||
|
||||
Stadium => Legal.LevelUpY,
|
||||
Stadium2 => Legal.LevelUpGS,
|
||||
Stadium => LearnSource1YW.Instance,
|
||||
Stadium2 => LearnSource2GS.Instance,
|
||||
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(game), $"{game} is not a valid entry in the expression."),
|
||||
};
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static PKHeX.Core.Legal;
|
||||
using static PKHeX.Core.GameVersion;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Shared logic for interacting with <see cref="EggMoves"/> data sources.
|
||||
/// </summary>
|
||||
public static class MoveEgg
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="EggMoves"/> data for the <see cref="version"/> and <see cref="species"/>.
|
||||
/// </summary>
|
||||
public static ReadOnlySpan<ushort> GetEggMoves(ushort species, byte form, GameVersion version, int generation)
|
||||
{
|
||||
if (!Breeding.CanGameGenerateEggs(version))
|
||||
return Array.Empty<ushort>();
|
||||
|
||||
return GetEggMoves(generation, species, form, version);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="EggMoves"/> data for the <see cref="version"/> and <see cref="species"/>.
|
||||
/// </summary>
|
||||
/// <remarks>Only use this if you're sure the game can generate eggs.</remarks>
|
||||
public static ReadOnlySpan<ushort> GetEggMoves(int generation, ushort species, byte form, GameVersion version) => generation switch
|
||||
{
|
||||
1 or 2 => GetMovesSafe(version == C ? EggMovesC : EggMovesGS, species),
|
||||
3 => GetMovesSafe(EggMovesRS, species),
|
||||
4 when version is D or P or Pt => GetMovesSafe(EggMovesDPPt, species),
|
||||
4 when version is HG or SS => GetMovesSafe(EggMovesHGSS, species),
|
||||
5 => GetMovesSafe(EggMovesBW, species),
|
||||
|
||||
6 when version is X or Y => GetMovesSafe(EggMovesXY, species),
|
||||
6 when version is OR or AS => GetMovesSafe(EggMovesAO, species),
|
||||
|
||||
7 when version is SN or MN => GetFormEggMoves(species, form, EggMovesSM),
|
||||
7 when version is US or UM => GetFormEggMoves(species, form, EggMovesUSUM),
|
||||
8 when version is SW or SH => GetFormEggMoves(species, form, EggMovesSWSH),
|
||||
8 when version is BD or SP => GetMovesSafe(EggMovesBDSP, species),
|
||||
9 when version is SL or VL => GetFormEggMoves(EggMovesSV, PersonalTable.SV.GetFormIndex(species, form)),
|
||||
_ => Array.Empty<ushort>(),
|
||||
};
|
||||
|
||||
private static ushort[] GetMovesSafe<T>(IReadOnlyList<T> moves, ushort species) where T : EggMoves
|
||||
{
|
||||
if (species >= moves.Count)
|
||||
return Array.Empty<ushort>();
|
||||
return moves[species].Moves;
|
||||
}
|
||||
|
||||
public static ushort[] GetFormEggMoves(IReadOnlyList<ushort[]> moves, int index)
|
||||
{
|
||||
if ((ushort)index >= moves.Count)
|
||||
return Array.Empty<ushort>();
|
||||
return moves[index];
|
||||
}
|
||||
|
||||
public static ushort[] GetFormEggMoves(ushort species, byte form, IReadOnlyList<EggMoves7> table)
|
||||
{
|
||||
if (species >= table.Count)
|
||||
return Array.Empty<ushort>();
|
||||
|
||||
var entry = table[species];
|
||||
if (form == 0 || species >= entry.FormTableIndex)
|
||||
return entry.Moves;
|
||||
|
||||
// Sanity check form in the event it is out of range.
|
||||
var baseIndex = entry.FormTableIndex;
|
||||
var index = baseIndex + form - 1;
|
||||
if ((uint)index >= table.Count)
|
||||
return Array.Empty<ushort>();
|
||||
entry = table[index];
|
||||
if (entry.FormTableIndex != baseIndex)
|
||||
return Array.Empty<ushort>();
|
||||
|
||||
return entry.Moves;
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
using System;
|
||||
|
||||
using static PKHeX.Core.GameVersion;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static class MoveLevelUp
|
||||
{
|
||||
public static void GetEncounterMoves(Span<ushort> moves, PKM pk, int level, GameVersion version)
|
||||
{
|
||||
if (version <= 0)
|
||||
version = (GameVersion)pk.Version;
|
||||
GetEncounterMoves(moves, pk.Species, pk.Form, level, version);
|
||||
}
|
||||
|
||||
private static void GetEncounterMoves1(Span<ushort> result, ushort species, int level, GameVersion version)
|
||||
{
|
||||
var learn = GameData.GetLearnsets(version);
|
||||
var table = version is YW or RBY ? PersonalTable.Y : PersonalTable.RB;
|
||||
var index = table.GetFormIndex(species, 0);
|
||||
|
||||
// The initial moves are seeded from Personal rather than learn.
|
||||
table[index].GetMoves(result);
|
||||
int start = Math.Max(0, result.IndexOf<ushort>(0));
|
||||
|
||||
learn[index].SetEncounterMoves(level, result, start);
|
||||
}
|
||||
|
||||
public static void GetEncounterMoves(Span<ushort> result, ushort species, byte form, int level, GameVersion version)
|
||||
{
|
||||
if (RBY.Contains(version))
|
||||
{
|
||||
GetEncounterMoves1(result, species, level, version);
|
||||
}
|
||||
else
|
||||
{
|
||||
var learn = GameData.GetLearnsets(version);
|
||||
var table = GameData.GetPersonal(version);
|
||||
var index = table.GetFormIndex(species, form);
|
||||
learn[index].SetEncounterMoves(level, result);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -47,4 +47,41 @@ public static class ItemRestrictions
|
|||
EntityContext.Gen8b => ReleasedHeldItems_8b,
|
||||
_ => Array.Empty<bool>(), // lgp/e, pla, etc
|
||||
};
|
||||
|
||||
private static readonly bool[] ReleasedHeldItems_2 = GetPermitList(MaxItemID_2, HeldItems_GSC);
|
||||
private static readonly bool[] ReleasedHeldItems_3 = GetPermitList(MaxItemID_3, HeldItems_RS, ItemStorage3RS.Unreleased); // Safari Ball
|
||||
private static readonly bool[] ReleasedHeldItems_4 = GetPermitList(MaxItemID_4_HGSS, HeldItems_HGSS, ItemStorage4.Unreleased);
|
||||
private static readonly bool[] ReleasedHeldItems_5 = GetPermitList(MaxItemID_5_B2W2, HeldItems_BW, ItemStorage5.Unreleased);
|
||||
private static readonly bool[] ReleasedHeldItems_6 = GetPermitList(MaxItemID_6_AO, HeldItem_AO, ItemStorage6XY.Unreleased);
|
||||
private static readonly bool[] ReleasedHeldItems_7 = GetPermitList(MaxItemID_7_USUM, HeldItems_USUM, ItemStorage7SM.Unreleased);
|
||||
private static readonly bool[] ReleasedHeldItems_8 = GetPermitList(MaxItemID_8, HeldItems_SWSH, ItemStorage8SWSH.Unreleased);
|
||||
private static readonly bool[] ReleasedHeldItems_8b = GetPermitList(MaxItemID_8b, HeldItems_BS, ItemStorage8BDSP.Unreleased);
|
||||
private static readonly bool[] ReleasedHeldItems_9 = GetPermitList(MaxItemID_9, HeldItems_SV, ItemStorage9SV.Unreleased);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a permit list with the permitted indexes, then un-flags the indexes that are not permitted.
|
||||
/// </summary>
|
||||
/// <param name="max">Maximum index expected to allow</param>
|
||||
/// <param name="allowed">Allowed indexes</param>
|
||||
private static bool[] GetPermitList(int max, ReadOnlySpan<ushort> allowed)
|
||||
{
|
||||
var result = new bool[max + 1];
|
||||
foreach (var index in allowed)
|
||||
result[index] = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a permit list with the permitted indexes, then un-flags the indexes that are not permitted.
|
||||
/// </summary>
|
||||
/// <param name="max">Maximum index expected to allow</param>
|
||||
/// <param name="allowed">Allowed indexes (may have some disallowed)</param>
|
||||
/// <param name="disallow">Disallowed indexes</param>
|
||||
private static bool[] GetPermitList(int max, ReadOnlySpan<ushort> allowed, ReadOnlySpan<ushort> disallow)
|
||||
{
|
||||
var result = GetPermitList(max, allowed);
|
||||
foreach (var index in disallow)
|
||||
result[index] = false;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,8 @@ public static class MemoryPermissions
|
|||
// Relearns can be wiped via Battle Version. Check for eggs too.
|
||||
if (IsSpecialEncounterMoveEggDeleted(pk, enc))
|
||||
{
|
||||
var em = MoveEgg.GetEggMoves(enc.Generation, enc.Species, enc.Form, enc.Version);
|
||||
var learn = GameData.GetLearnSource(enc.Version);
|
||||
var em = learn.GetEggMoves(enc.Species, enc.Form);
|
||||
if (em.Contains(move))
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ public interface IMasteryInitialMoveShop8
|
|||
{
|
||||
Span<ushort> moves = stackalloc ushort[4];
|
||||
var level = pa8.Met_Level;
|
||||
var (learn, mastery) = GetLevelUpInfo();
|
||||
var (learn, mastery) = LearnSource8LA.GetLearnsetAndMastery(pk.Species, pk.Form);
|
||||
LoadInitialMoveset(pa8, moves, learn, level);
|
||||
pa8.SetEncounterMasteryFlags(moves, mastery, level);
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ public static class FormInfo
|
|||
return false;
|
||||
}
|
||||
|
||||
public static bool IsFormChangeEgg(ushort species) => FormChangeEgg.IndexOf(species) != -1;
|
||||
public static bool IsFormChangeEgg(ushort species) => FormChangeEgg.Contains(species);
|
||||
|
||||
private static ReadOnlySpan<ushort> FormChangeEgg => new ushort[]
|
||||
{
|
||||
|
@ -237,6 +237,28 @@ public static class FormInfo
|
|||
return hs;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Species has a Totem form in Gen7 (S/M & US/UM) that can be captured and owned.
|
||||
/// </summary>
|
||||
/// <param name="species"></param>
|
||||
/// <returns>True if the species exists as a Totem.</returns>
|
||||
/// <remarks>Excludes <see cref="Wishiwashi"/> because it cannot be captured.</remarks>
|
||||
public static bool HasTotemForm(ushort species) => species switch
|
||||
{
|
||||
(ushort)Raticate => true,
|
||||
(ushort)Marowak => true,
|
||||
(ushort)Gumshoos => true,
|
||||
(ushort)Vikavolt => true,
|
||||
(ushort)Ribombee => true,
|
||||
(ushort)Araquanid => true,
|
||||
(ushort)Lurantis => true,
|
||||
(ushort)Salazzle => true,
|
||||
(ushort)Mimikyu => true,
|
||||
(ushort)Kommoo => true,
|
||||
(ushort)Togedemaru => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the <see cref="form"/> for the <see cref="species"/> is a Totem form.
|
||||
/// </summary>
|
||||
|
@ -255,11 +277,11 @@ public static class FormInfo
|
|||
{
|
||||
if (form == 0)
|
||||
return false;
|
||||
if (!Legal.Totem_USUM.Contains(species))
|
||||
if (!HasTotemForm(species))
|
||||
return false;
|
||||
if (species == (int)Mimikyu)
|
||||
return form is 2 or 3;
|
||||
if (Legal.Totem_Alolan.Contains(species))
|
||||
if (species is (int)Raticate or (int)Marowak)
|
||||
return form == 2;
|
||||
return form == 1;
|
||||
}
|
||||
|
@ -323,7 +345,7 @@ public static class FormInfo
|
|||
if (format <= 3 && species != (int)Unown)
|
||||
return false;
|
||||
|
||||
if (HasFormValuesNotIndicatedByPersonal.Contains(species))
|
||||
if (HasFormValuesNotIndicatedByPersonal(species))
|
||||
return true;
|
||||
|
||||
int count = pi.FormCount;
|
||||
|
@ -333,10 +355,11 @@ public static class FormInfo
|
|||
/// <summary>
|
||||
/// <seealso cref="IsValidOutOfBoundsForm"/>
|
||||
/// </summary>
|
||||
private static readonly HashSet<ushort> HasFormValuesNotIndicatedByPersonal = new()
|
||||
private static bool HasFormValuesNotIndicatedByPersonal(ushort species) => species switch
|
||||
{
|
||||
(int)Unown,
|
||||
(int)Mothim, // (Burmy form is not cleared on evolution)
|
||||
(int)Scatterbug, (int)Spewpa, // Vivillon pre-evos
|
||||
(int)Unown => true,
|
||||
(int)Mothim => true, // (Burmy form is not cleared on evolution)
|
||||
(int)Scatterbug or (int)Spewpa => true, // Vivillon pre-evos
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
|
89
PKHeX.Core/Legality/Tables/SpeciesCategory.cs
Normal file
89
PKHeX.Core/Legality/Tables/SpeciesCategory.cs
Normal file
|
@ -0,0 +1,89 @@
|
|||
using System.Collections.Generic;
|
||||
using static PKHeX.Core.Species;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Categorizes <see cref="Species"/> into groups, or specific edge-case qualities.
|
||||
/// </summary>
|
||||
public static class SpeciesCategory
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks if a Species is classified as a Mythical Distributions (disallowed species for competitive rulesets)
|
||||
/// </summary>
|
||||
public static bool IsMythical(ushort species) => Mythicals.Contains(species);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a Species is classified as "Legend" by the game code.
|
||||
/// </summary>
|
||||
/// <remarks>Previous games may have included Mythicals in this species list, but that list should be considered separately.</remarks>
|
||||
public static bool IsLegendary(ushort species) => Legends.Contains(species);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a Species is classified as "SubLegend" by the game code.
|
||||
/// </summary>
|
||||
public static bool IsSubLegendary(ushort species) => SubLegends.Contains(species);
|
||||
|
||||
private static readonly HashSet<ushort> Mythicals = new()
|
||||
{
|
||||
(int)Mew,
|
||||
(int)Celebi,
|
||||
(int)Jirachi, (int)Deoxys,
|
||||
(int)Phione, (int)Manaphy, (int)Darkrai, (int)Shaymin, (int)Arceus,
|
||||
(int)Victini, (int)Keldeo, (int)Meloetta, (int)Genesect,
|
||||
(int)Diancie, (int)Hoopa, (int)Volcanion,
|
||||
(int)Magearna, (int)Marshadow,
|
||||
(int)Zeraora, (int)Meltan, (int)Melmetal,
|
||||
(int)Zarude,
|
||||
};
|
||||
|
||||
private static readonly HashSet<ushort> Legends = new()
|
||||
{
|
||||
(int)Mewtwo,
|
||||
(int)Lugia, (int)HoOh,
|
||||
(int)Kyogre, (int)Groudon, (int)Rayquaza,
|
||||
(int)Dialga, (int)Palkia, (int)Giratina,
|
||||
(int)Reshiram, (int)Zekrom, (int)Kyurem,
|
||||
(int)Xerneas, (int)Yveltal, (int)Zygarde,
|
||||
(int)Cosmog, (int)Cosmoem, (int)Solgaleo, (int)Lunala, (int)Necrozma,
|
||||
(int)Zacian, (int)Zamazenta, (int)Eternatus, (int)Calyrex,
|
||||
(int)Koraidon, (int)Miraidon,
|
||||
};
|
||||
|
||||
private static readonly HashSet<ushort> SubLegends = new()
|
||||
{
|
||||
(int)Articuno, (int)Zapdos, (int)Moltres,
|
||||
(int)Raikou, (int)Entei, (int)Suicune,
|
||||
(int)Regirock, (int)Regice, (int)Registeel, (int)Latias, (int)Latios,
|
||||
(int)Uxie, (int)Mesprit, (int)Azelf, (int)Heatran, (int)Regigigas, (int)Cresselia,
|
||||
(int)Cobalion, (int)Terrakion, (int)Virizion, (int)Tornadus, (int)Thundurus, (int)Landorus,
|
||||
(int)TypeNull, (int)Silvally, (int)TapuKoko, (int)TapuLele, (int)TapuBulu, (int)TapuFini,
|
||||
(int)Kubfu, (int)Urshifu, (int)Regieleki, (int)Regidrago, (int)Glastrier, (int)Spectrier, (int)Enamorus,
|
||||
(int)WoChien, (int)ChienPao, (int)TingLu, (int)ChiYu,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the <see cref="species"/> is an Ultra Beast Pokémon.
|
||||
/// </summary>
|
||||
public static bool IsUltraBeast(ushort species) => species is (>= (int)Nihilego and <= (int)Guzzlord) or (>= (int)Poipole and <= (int)Blacephalon);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the <see cref="species"/> is a Paradox Pokémon.
|
||||
/// </summary>
|
||||
public static bool IsParadox(ushort species) => species is (>= (int)GreatTusk and <= (int)IronThorns) or (int)RoaringMoon or (int)IronValiant;
|
||||
|
||||
public static bool IsFixedGenderFromDual(ushort currentSpecies) => currentSpecies switch
|
||||
{
|
||||
(int)Shedinja => true, // Genderless
|
||||
|
||||
(int)Wormadam => true, //(F)
|
||||
(int)Mothim => true, // (M)
|
||||
|
||||
(int)Gallade => true, // (M)
|
||||
(int)Froslass => true, // (F)
|
||||
(int)Meowstic => true, // (M/F) form specific
|
||||
(int)Oinkologne => true, // (M/F) form specific
|
||||
|
||||
_ => false,
|
||||
};
|
||||
}
|
|
@ -1,136 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static PKHeX.Core.Species;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static partial class Legal
|
||||
{
|
||||
/// <summary>
|
||||
/// Generation 3 & 4 Battle Frontier Species banlist. When referencing this in context to generation 4, be sure to disallow <see cref="Pichu"/> with Form 1 (Spiky).
|
||||
/// </summary>
|
||||
public static readonly HashSet<ushort> BattleFrontierBanlist = new()
|
||||
{
|
||||
(int)Mewtwo, (int)Mew,
|
||||
(int)Lugia, (int)HoOh, (int)Celebi,
|
||||
(int)Kyogre, (int)Groudon, (int)Rayquaza, (int)Jirachi, (int)Deoxys,
|
||||
(int)Dialga, (int)Palkia, (int)Giratina, (int)Phione, (int)Manaphy, (int)Darkrai, (int)Shaymin, (int)Arceus,
|
||||
(int)Victini, (int)Reshiram, (int)Zekrom, (int)Kyurem, (int)Keldeo, (int)Meloetta, (int)Genesect,
|
||||
(int)Xerneas, (int)Yveltal, (int)Zygarde, (int)Diancie, (int)Hoopa, (int)Volcanion,
|
||||
(int)Cosmog, (int)Cosmoem, (int)Solgaleo, (int)Lunala, (int)Necrozma, (int)Magearna, (int)Marshadow, (int)Zeraora,
|
||||
(int)Meltan, (int)Melmetal,
|
||||
(int)Koraidon, (int)Miraidon,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Species that are from Mythical Distributions (disallowed species for competitive rulesets)
|
||||
/// </summary>
|
||||
public static readonly HashSet<ushort> Mythicals = new()
|
||||
{
|
||||
(int)Mew,
|
||||
(int)Celebi,
|
||||
(int)Jirachi, (int)Deoxys,
|
||||
(int)Phione, (int)Manaphy, (int)Darkrai, (int)Shaymin, (int)Arceus,
|
||||
(int)Victini, (int)Keldeo, (int)Meloetta, (int)Genesect,
|
||||
(int)Diancie, (int)Hoopa, (int)Volcanion,
|
||||
(int)Magearna, (int)Marshadow,
|
||||
(int)Zeraora, (int)Meltan, (int)Melmetal,
|
||||
(int)Zarude,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Species classified as "Legend" by the game code.
|
||||
/// </summary>
|
||||
/// <remarks>Previous games may have included Mythicals in this species list, but that list should be considered separately.</remarks>
|
||||
public static readonly HashSet<ushort> Legends = new()
|
||||
{
|
||||
(int)Mewtwo,
|
||||
(int)Lugia, (int)HoOh,
|
||||
(int)Kyogre, (int)Groudon, (int)Rayquaza,
|
||||
(int)Dialga, (int)Palkia, (int)Giratina,
|
||||
(int)Reshiram, (int)Zekrom, (int)Kyurem,
|
||||
(int)Xerneas, (int)Yveltal, (int)Zygarde,
|
||||
(int)Cosmog, (int)Cosmoem, (int)Solgaleo, (int)Lunala, (int)Necrozma,
|
||||
(int)Zacian, (int)Zamazenta, (int)Eternatus, (int)Calyrex,
|
||||
(int)Koraidon, (int)Miraidon,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Species classified as "SubLegend" by the game code.
|
||||
/// </summary>
|
||||
public static readonly HashSet<ushort> SubLegends = new()
|
||||
{
|
||||
(int)Articuno, (int)Zapdos, (int)Moltres,
|
||||
(int)Raikou, (int)Entei, (int)Suicune,
|
||||
(int)Regirock, (int)Regice, (int)Registeel, (int)Latias, (int)Latios,
|
||||
(int)Uxie, (int)Mesprit, (int)Azelf, (int)Heatran, (int)Regigigas, (int)Cresselia,
|
||||
(int)Cobalion, (int)Terrakion, (int)Virizion, (int)Tornadus, (int)Thundurus, (int)Landorus,
|
||||
(int)TypeNull, (int)Silvally, (int)TapuKoko, (int)TapuLele, (int)TapuBulu, (int)TapuFini,
|
||||
(int)Kubfu, (int)Urshifu, (int)Regieleki, (int)Regidrago, (int)Glastrier, (int)Spectrier, (int)Enamorus,
|
||||
(int)WoChien, (int)ChienPao, (int)TingLu, (int)ChiYu,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the <see cref="species"/> is an Ultra Beast Pokémon.
|
||||
/// </summary>
|
||||
public static bool IsUltraBeast(ushort species) => species is
|
||||
(int)Nihilego or (int)Buzzwole or (int)Pheromosa or (int)Xurkitree or (int)Celesteela or (int)Kartana or (int)Guzzlord or
|
||||
(int)Poipole or (int)Naganadel or (int)Stakataka or (int)Blacephalon;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the <see cref="species"/> is a Paradox Pokémon.
|
||||
/// </summary>
|
||||
public static bool IsParadox(ushort species) => species is (>= (int)GreatTusk and <= (int)IronThorns) or (int)RoaringMoon or (int)IronValiant;
|
||||
|
||||
/// <summary>
|
||||
/// Species that evolve from a Bi-Gendered species into a Single-Gender.
|
||||
/// </summary>
|
||||
public static readonly HashSet<ushort> FixedGenderFromBiGender = new()
|
||||
{
|
||||
(int)Nincada,
|
||||
(int)Shedinja, // (G)
|
||||
|
||||
(int)Burmy,
|
||||
(int)Wormadam, //(F)
|
||||
(int)Mothim, // (M)
|
||||
|
||||
(int)Ralts,
|
||||
(int)Gallade, // (M)
|
||||
|
||||
(int)Snorunt,
|
||||
(int)Froslass, // (F)
|
||||
|
||||
(int)Espurr,
|
||||
(int)Meowstic, // (M/F) form specific
|
||||
|
||||
(int)Lechonk,
|
||||
(int)Oinkologne, // (M/F) form specific
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Gets a permit list with the permitted indexes, then un-flags the indexes that are not permitted.
|
||||
/// </summary>
|
||||
/// <param name="max">Maximum index expected to allow</param>
|
||||
/// <param name="allowed">Allowed indexes</param>
|
||||
private static bool[] GetPermitList(int max, ReadOnlySpan<ushort> allowed)
|
||||
{
|
||||
var result = new bool[max + 1];
|
||||
foreach (var index in allowed)
|
||||
result[index] = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a permit list with the permitted indexes, then un-flags the indexes that are not permitted.
|
||||
/// </summary>
|
||||
/// <param name="max">Maximum index expected to allow</param>
|
||||
/// <param name="allowed">Allowed indexes (may have some disallowed)</param>
|
||||
/// <param name="disallow">Disallowed indexes</param>
|
||||
private static bool[] GetPermitList(int max, ReadOnlySpan<ushort> allowed, ReadOnlySpan<ushort> disallow)
|
||||
{
|
||||
var result = GetPermitList(max, allowed);
|
||||
foreach (var index in disallow)
|
||||
result[index] = false;
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
namespace PKHeX.Core;
|
||||
|
||||
public static partial class Legal
|
||||
{
|
||||
internal const int MaxSpeciesID_1 = 151;
|
||||
internal const int MaxMoveID_1 = 165;
|
||||
internal const int MaxItemID_1 = 255;
|
||||
internal const int MaxAbilityID_1 = 0;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
namespace PKHeX.Core;
|
||||
|
||||
public static partial class Legal
|
||||
{
|
||||
internal const int MaxSpeciesID_2 = 251;
|
||||
internal const int MaxMoveID_2 = 251;
|
||||
internal const int MaxItemID_2 = 255;
|
||||
internal const int MaxAbilityID_2 = 0;
|
||||
|
||||
internal static readonly ushort[] HeldItems_GSC = ItemStorage2.GetAllHeld();
|
||||
|
||||
internal static readonly bool[] ReleasedHeldItems_2 = GetPermitList(MaxItemID_2, HeldItems_GSC);
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static partial class Legal
|
||||
{
|
||||
internal const int MaxSpeciesIndex_3 = 412;
|
||||
internal const int MaxSpeciesID_3 = 386;
|
||||
internal const int MaxMoveID_3 = 354;
|
||||
internal const int MaxItemID_3 = 374;
|
||||
internal const int MaxItemID_3_COLO = 547;
|
||||
internal const int MaxItemID_3_XD = 593;
|
||||
internal const int MaxAbilityID_3 = 77;
|
||||
internal const int MaxBallID_3 = 0xC;
|
||||
internal const int MaxGameID_3 = 15; // CXD
|
||||
|
||||
#region RS
|
||||
|
||||
internal static readonly ushort[] HeldItems_RS = ItemStorage3RS.GetAllHeld();
|
||||
#endregion
|
||||
|
||||
|
||||
internal static readonly bool[] ReleasedHeldItems_3 = GetPermitList(MaxItemID_3, HeldItems_RS, ItemStorage3RS.Unreleased); // Safari Ball
|
||||
|
||||
// 064 is an unused location for Meteor Falls
|
||||
// 084 is Inside of a truck, no possible pokemon can be hatched there
|
||||
// 071 is Mirage island, cannot be obtained as the player is technically still on Route 130's map.
|
||||
// 075 is an unused location for Fiery Path
|
||||
// 077 is an unused location for Jagged Pass
|
||||
internal static readonly HashSet<byte> ValidMet_RS = new()
|
||||
{
|
||||
000, 001, 002, 003, 004, 005, 006, 007, 008, 009,
|
||||
010, 011, 012, 013, 014, 015, 016, 017, 018, 019,
|
||||
020, 021, 022, 023, 024, 025, 026, 027, 028, 029,
|
||||
030, 031, 032, 033, 034, 035, 036, 037, 038, 039,
|
||||
040, 041, 042, 043, 044, 045, 046, 047, 048, 049,
|
||||
050, 051, 052, 053, 054, 055, 056, 057, 058, 059,
|
||||
060, 061, 062, 063, 065, 066, 067, 068, 069,
|
||||
070, 072, 073, 074, 076, 078, 079,
|
||||
080, 081, 082, 083, 085, 086, 087,
|
||||
};
|
||||
|
||||
// 155 - 158 Sevii Isle 6-9 Unused
|
||||
// 171 - 173 Sevii Isle 22-24 Unused
|
||||
internal static readonly HashSet<byte> ValidMet_FRLG = new()
|
||||
{
|
||||
087, 088, 089,
|
||||
090, 091, 092, 093, 094, 095, 096, 097, 098, 099,
|
||||
100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
|
||||
110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
|
||||
120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
|
||||
130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
|
||||
140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
|
||||
150, 151, 152, 153, 154, 159,
|
||||
160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
|
||||
170, 174, 175, 176, 177, 178, 179,
|
||||
180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
|
||||
190, 191, 192, 193, 194, 195, 196,
|
||||
};
|
||||
|
||||
internal static readonly HashSet<byte> ValidMet_E = new(ValidMet_RS)
|
||||
{
|
||||
196, 197, 198, 199,
|
||||
200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
|
||||
210, 211, 212,
|
||||
};
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static partial class Legal
|
||||
{
|
||||
internal const int MaxSpeciesID_4 = 493;
|
||||
internal const int MaxMoveID_4 = 467;
|
||||
internal const int MaxItemID_4_DP = 464;
|
||||
internal const int MaxItemID_4_Pt = 467;
|
||||
internal const int MaxItemID_4_HGSS = 536;
|
||||
internal const int MaxAbilityID_4 = 123;
|
||||
internal const int MaxBallID_4 = 0x18;
|
||||
internal const int MaxGameID_4 = 15; // CXD
|
||||
|
||||
internal static readonly ushort[] HeldItems_DP = ItemStorage4DP.GetAllHeld();
|
||||
internal static readonly ushort[] HeldItems_Pt = ItemStorage4Pt.GetAllHeld(); // Griseous Orb Added
|
||||
internal static readonly ushort[] HeldItems_HGSS = HeldItems_Pt;
|
||||
|
||||
internal static readonly bool[] ReleasedHeldItems_4 = GetPermitList(MaxItemID_4_HGSS, HeldItems_HGSS, ItemStorage4.Unreleased);
|
||||
|
||||
internal static readonly HashSet<ushort> ValidMet_DP = new()
|
||||
{
|
||||
// 063: Flower Paradise unreleased DP event
|
||||
// 079: Newmoon Island unreleased DP event
|
||||
// 085: Seabreak Path unreleased DP event
|
||||
// 086: Hall of Origin unreleased event
|
||||
001, 002, 003, 004, 005, 006, 007, 008, 009,
|
||||
010, 011, 012, 013, 014, 015, 016, 017, 018, 019,
|
||||
020, 021, 022, 023, 024, 025, 026, 027, 028, 029,
|
||||
030, 031, 032, 033, 034, 035, 036, 037, 038, 039,
|
||||
040, 041, 042, 043, 044, 045, 046, 047, 048, 049,
|
||||
050, 051, 052, 053, 054, 055, 056, 057, 058, 059,
|
||||
060, 061, 062, 064, 065, 066, 067, 068, 069,
|
||||
070, 071, 072, 073, 074, 075, 076, 077, 078,
|
||||
080, 081, 082, 083, 084, 087, 088, 089,
|
||||
090, 091, 092, 093, 094, 095, 096, 097, 098, 099,
|
||||
100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
|
||||
110, 111,
|
||||
};
|
||||
|
||||
internal static readonly HashSet<ushort> ValidMet_Pt = new(ValidMet_DP)
|
||||
{
|
||||
// 086: Hall of Origin unreleased event
|
||||
63, 79, 85,
|
||||
112, 113, 114, 115, 116, 117, 118, 119,
|
||||
120, 121, 122, 123, 124, 125,
|
||||
};
|
||||
|
||||
internal static readonly HashSet<ushort> ValidMet_HGSS = new()
|
||||
{
|
||||
080,
|
||||
112, 113, 114, 115, 116,
|
||||
126, 127, 128, 129,
|
||||
130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
|
||||
140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
|
||||
150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
|
||||
160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
|
||||
170, 172, 173, 174, 175, 176, 177, 178, 179, //171: Route 23 no longer exists
|
||||
180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
|
||||
190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
|
||||
200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
|
||||
210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
|
||||
220, 221, 222, 223, 224, 225, 226, 227, 228, 229,
|
||||
230, 231, 232, 234, //233: Pokéwalker
|
||||
};
|
||||
|
||||
internal static readonly HashSet<ushort> ValidMet_4 = new(ValidMet_Pt.Concat(ValidMet_HGSS));
|
||||
|
||||
internal static readonly HashSet<ushort> GiftEggLocation4 = new()
|
||||
{
|
||||
2009, 2010, 2011, 2013, 2014,
|
||||
};
|
||||
|
||||
internal static int GetTransfer45MetLocation(PKM pk)
|
||||
{
|
||||
// Everything except for crown beasts and Celebi get the default transfer location.
|
||||
// Crown beasts and Celebi are 100% identifiable by the species ID and fateful encounter, originating from Gen4.
|
||||
if (!pk.Gen4 || !pk.FatefulEncounter)
|
||||
return Locations.Transfer4; // Pokétransfer
|
||||
|
||||
return pk.Species switch
|
||||
{
|
||||
// Crown Beast
|
||||
(int)Species.Raikou or (int)Species.Entei or (int)Species.Suicune => Locations.Transfer4_CrownUnused,
|
||||
// Celebi
|
||||
(int)Species.Celebi => Locations.Transfer4_CelebiUnused,
|
||||
// Default
|
||||
_ => Locations.Transfer4,
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static partial class Legal
|
||||
{
|
||||
internal const int MaxSpeciesID_5 = 649;
|
||||
internal const int MaxMoveID_5 = 559;
|
||||
internal const int MaxItemID_5_BW = 632;
|
||||
internal const int MaxItemID_5_B2W2 = 638;
|
||||
internal const int MaxAbilityID_5 = 164;
|
||||
internal const int MaxBallID_5 = 0x19;
|
||||
internal const int MaxGameID_5 = 23; // B2
|
||||
|
||||
internal static readonly ushort[] HeldItems_BW = ItemStorage5.GetAllHeld();
|
||||
|
||||
internal static readonly bool[] ReleasedHeldItems_5 = GetPermitList(MaxItemID_5_B2W2, HeldItems_BW, ItemStorage5.Unreleased);
|
||||
|
||||
internal static readonly HashSet<ushort> ValidMet_BW = new()
|
||||
{
|
||||
004, 005, 006, 007, 008, 009,
|
||||
010, 011, 012, 013, 014, 015, 016, 017, 018, 019,
|
||||
020, 021, 022, 023, 024, 025, 026, 027, 028, 029,
|
||||
030, 031, 032, 033, 034, 035, 036, 037, 038, 039,
|
||||
040, 041, 042, 043, 044, 045, 046, 047, 048, 049,
|
||||
050, 051, 052, 053, 054, 055, 056, 057, 058, 059,
|
||||
060, 061, 062, 063, 064, 065, 066, 067, 068, 069,
|
||||
070, 071, 072, 073, 074, 075, 076, 077, 078, 079,
|
||||
080, 081, 082, 083, 084, 085, 086, 087, 088, 089,
|
||||
090, 091, 092, 093, 094, 095, 096, 097, 098, 099,
|
||||
100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
|
||||
110, 111, 112, 113, 114, 115, 116,
|
||||
};
|
||||
|
||||
internal static readonly HashSet<ushort> ValidMet_B2W2 = new()
|
||||
{
|
||||
004, 005, 006, 007, 008, 009,
|
||||
010, 011, 012, 013, 014, 015, 016, 017, 018, 019,
|
||||
020, 021, 022, 024, 025, 026, 027, 028, 029, // 023 Route 10
|
||||
030, 031, 032, 033, 034, 035, 036, 037, 038, 039,
|
||||
041, 042, 043, 044, 045, 046, 047, 048, 049, // 040->134 Victory Road
|
||||
050, 051, 052, 053, 054, 055, 056, 057, 058, // 059 Challenger's cave
|
||||
060, 061, 062, 063, 064, 065, 066, 067, 068, 069,
|
||||
070, 071, 072, 074, 075, 076, 077, 078, 079, // 073 Trial Chamber
|
||||
080, 081, 082, 083, 084, 085, 086, 087, 088, 089,
|
||||
090, 091, 092, 093, 094, 095, 096, 097, 098, 099,
|
||||
100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
|
||||
110, 111, 112, 113, 114, 115, 116,
|
||||
117, 118, 119,
|
||||
120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
|
||||
130, 131, 132, 133, 134, 135, 136, 137, 139, // 138 ---
|
||||
140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
|
||||
150, 151, 152, 153,
|
||||
};
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static partial class Legal
|
||||
{
|
||||
internal const int MaxSpeciesID_6 = 721;
|
||||
internal const int MaxMoveID_6_XY = 617;
|
||||
internal const int MaxMoveID_6_AO = 621;
|
||||
internal const int MaxItemID_6_XY = 717;
|
||||
internal const int MaxItemID_6_AO = 775;
|
||||
internal const int MaxAbilityID_6_XY = 188;
|
||||
internal const int MaxAbilityID_6_AO = 191;
|
||||
internal const int MaxBallID_6 = 0x19;
|
||||
internal const int MaxGameID_6 = 27; // OR
|
||||
|
||||
internal static readonly ushort[] HeldItem_AO = ItemStorage6XY.GetAllHeld();
|
||||
|
||||
internal static readonly HashSet<ushort> ValidMet_XY = new()
|
||||
{
|
||||
006, 008,
|
||||
010, 012, 014, 016, 018,
|
||||
020, 022, 024, 026, 028,
|
||||
030, 032, 034, 036, 038,
|
||||
040, 042, 044, 046, 048,
|
||||
050, 052, 054, 056, 058,
|
||||
060, 062, 064, 066, 068,
|
||||
070, 072, 074, 076, 078,
|
||||
082, 084, 086, 088,
|
||||
090, 092, 094, 096, 098,
|
||||
100, 102, 104, 106, 108,
|
||||
110, 112, 114, 116, 118,
|
||||
120, 122, 124, 126, 128,
|
||||
130, 132, 134, 136, 138,
|
||||
140, 142, 144, 146, 148,
|
||||
150, 152, 154, 156, 158,
|
||||
160, 162, 164, 166, 168,
|
||||
};
|
||||
|
||||
internal static readonly HashSet<ushort> ValidMet_AO = new()
|
||||
{
|
||||
170, 172, 174, 176, 178,
|
||||
180, 182, 184, 186, 188,
|
||||
190, 192, 194, 196, 198,
|
||||
200, 202, 204, 206, 208,
|
||||
210, 212, 214, 216, 218,
|
||||
220, 222, 224, 226, 228,
|
||||
230, 232, 234, 236, 238,
|
||||
240, 242, 244, 246, 248,
|
||||
250, 252, 254, 256, 258,
|
||||
260, 262, 264, 266, 268,
|
||||
270, 272, 274, 276, 278,
|
||||
280, 282, 284, 286, 288,
|
||||
290, 292, 294, 296, 298,
|
||||
300, 302, 304, 306, 308,
|
||||
310, 312, 314, 316, 318,
|
||||
320, 322, 324, 326, 328,
|
||||
330, 332, 334, 336, 338,
|
||||
340, 342, 344, 346,
|
||||
350, 352, 354,
|
||||
};
|
||||
|
||||
internal static readonly bool[] ReleasedHeldItems_6 = GetPermitList(MaxItemID_6_AO, HeldItem_AO, ItemStorage6XY.Unreleased);
|
||||
}
|
|
@ -1,174 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using static PKHeX.Core.Species;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static partial class Legal
|
||||
{
|
||||
internal const int MaxSpeciesID_7 = 802;
|
||||
internal const int MaxMoveID_7 = 719;
|
||||
internal const int MaxItemID_7 = 920;
|
||||
internal const int MaxAbilityID_7 = 232;
|
||||
internal const int MaxBallID_7 = 0x1A; // 26
|
||||
internal const int MaxGameID_7 = 41; // Crystal (VC?)
|
||||
|
||||
internal const int MaxSpeciesID_7_USUM = 807;
|
||||
internal const int MaxMoveID_7_USUM = 728;
|
||||
internal const int MaxItemID_7_USUM = 959;
|
||||
internal const int MaxAbilityID_7_USUM = 233;
|
||||
|
||||
private static Dictionary<ushort, ushort> GetDictionary(IReadOnlyList<ushort> key, IReadOnlyList<ushort> held)
|
||||
{
|
||||
var result = new Dictionary<ushort, ushort>(held.Count);
|
||||
for (int i = 0; i < key.Count; i++)
|
||||
result.Add(key[i], held[i]);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static readonly ushort[] HeldItems_SM = ItemStorage7SM.GetAllHeld();
|
||||
internal static readonly ushort[] HeldItems_USUM = ItemStorage7USUM.GetAllHeld();
|
||||
|
||||
internal static readonly HashSet<ushort> AlolanOriginForms = new()
|
||||
{
|
||||
(int)Rattata,
|
||||
(int)Raticate,
|
||||
(int)Sandshrew,
|
||||
(int)Sandslash,
|
||||
(int)Vulpix,
|
||||
(int)Ninetales,
|
||||
(int)Diglett,
|
||||
(int)Dugtrio,
|
||||
(int)Meowth,
|
||||
(int)Persian,
|
||||
(int)Geodude,
|
||||
(int)Graveler,
|
||||
(int)Golem,
|
||||
(int)Grimer,
|
||||
(int)Muk,
|
||||
};
|
||||
|
||||
internal static readonly HashSet<ushort> AlolanVariantEvolutions12 = new()
|
||||
{
|
||||
(int)Raichu,
|
||||
(int)Exeggutor,
|
||||
(int)Marowak,
|
||||
};
|
||||
|
||||
public static readonly HashSet<ushort> PastGenAlolanNatives = new()
|
||||
{
|
||||
010, 011, 012, 019, 020, 021, 022, 025, 026, 027, 028, 035, 036, 037, 038, 039, 040, 041, 042, 046, 047, 050,
|
||||
051, 052, 053, 054, 055, 056, 057, 058, 059, 060, 061, 062, 063, 064, 065, 066, 067, 068, 072, 073, 074, 075,
|
||||
076, 079, 080, 081, 082, 088, 089, 090, 091, 092, 093, 094, 096, 097, 102, 103, 104, 105, 113, 115, 118, 119,
|
||||
120, 121, 123, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 142, 143, 147, 148, 149, 165,
|
||||
166, 167, 168, 169, 170, 171, 172, 173, 174, 185, 186, 196, 197, 198, 199, 200, 209, 210, 212, 215, 222, 225,
|
||||
227, 233, 235, 239, 240, 241, 242, 278, 279, 283, 284, 296, 297, 299, 302, 318, 319, 320, 321, 324, 327, 328,
|
||||
329, 330, 339, 340, 349, 350, 351, 359, 361, 362, 369, 370, 371, 372, 373, 374, 375, 376, 408, 409, 410, 411,
|
||||
422, 423, 425, 426, 429, 430, 438, 440, 443, 444, 445, 446, 447, 448, 456, 457, 461, 462, 466, 467, 470, 471,
|
||||
474, 476, 478, 506, 507, 508, 524, 525, 526, 546, 547, 548, 549, 551, 552, 553, 564, 565, 566, 567, 568, 569,
|
||||
582, 583, 584, 587, 594, 627, 628, 629, 630, 661, 662, 663, 674, 675, 700, 703, 704, 705, 706, 707, 708, 709,
|
||||
718,
|
||||
|
||||
// Regular
|
||||
023, 086, 108, 122, 138, 140, 163, 177, 179, 190, 204,
|
||||
206, 214, 223, 228, 238, 246, 303, 309, 341, 343,
|
||||
345, 347, 352, 353, 357, 366, 427, 439, 458, 550,
|
||||
559, 570, 572, 592, 605, 619, 621, 622, 624, 636,
|
||||
667, 669, 676, 686, 690, 692, 696, 698, 701, 702,
|
||||
714,
|
||||
|
||||
// Wormhole
|
||||
333, 334, // Altaria
|
||||
193, 469, // Yanmega
|
||||
561, // Sigilyph
|
||||
580, 581, // Swanna
|
||||
276, 277, // Swellow
|
||||
451, 452, // Drapion
|
||||
531, // Audino
|
||||
694, 695, // Heliolisk
|
||||
273, 274, 275, // Nuzleaf
|
||||
325, 326, // Gumpig
|
||||
459, 460, // Abomasnow
|
||||
307, 308, // Medicham
|
||||
449, 450, // Hippowdon
|
||||
557, 558, // Crustle
|
||||
218, 219, // Magcargo
|
||||
688, 689, // Barbaracle
|
||||
270, 271, 272, // Lombre
|
||||
618, // Stunfisk
|
||||
418, 419, // Floatzel
|
||||
194, 195, // Quagsire
|
||||
|
||||
100, 101, // Voltorb & Electrode
|
||||
};
|
||||
|
||||
internal static readonly HashSet<ushort> Totem_Alolan = new()
|
||||
{
|
||||
(int)Raticate, // (Normal, Alolan, Totem)
|
||||
(int)Marowak, // (Normal, Alolan, Totem)
|
||||
(int)Mimikyu, // (Normal, Busted, Totem, Totem_Busted)
|
||||
};
|
||||
|
||||
internal static readonly HashSet<ushort> Totem_NoTransfer = new()
|
||||
{
|
||||
(int)Marowak,
|
||||
(int)Araquanid,
|
||||
(int)Togedemaru,
|
||||
(int)Ribombee,
|
||||
};
|
||||
|
||||
internal static readonly HashSet<ushort> Totem_USUM = new()
|
||||
{
|
||||
(int)Raticate,
|
||||
(int)Gumshoos,
|
||||
//(int)Wishiwashi,
|
||||
(int)Salazzle,
|
||||
(int)Lurantis,
|
||||
(int)Vikavolt,
|
||||
(int)Mimikyu,
|
||||
(int)Kommoo,
|
||||
(int)Marowak,
|
||||
(int)Araquanid,
|
||||
(int)Togedemaru,
|
||||
(int)Ribombee,
|
||||
};
|
||||
|
||||
internal static readonly HashSet<ushort> ValidMet_SM = new()
|
||||
{
|
||||
006, 008,
|
||||
010, 012, 014, 016, 018,
|
||||
020, 022, 024, 026, 028,
|
||||
030, 032, 034, 036, 038,
|
||||
040, 042, 044, 046, 048,
|
||||
050, 052, 054, 056, 058,
|
||||
060, 062, 064, 068,
|
||||
070, 072, 074, 076, 078,
|
||||
082, 084, 086, 088,
|
||||
090, 092, 094,
|
||||
100, 102, 104, 106, 108,
|
||||
110, 112, 114, 116, 118,
|
||||
120, 122, 124, 126, 128,
|
||||
130, 132, 134, 136, 138,
|
||||
140, 142, 144, 146, 148,
|
||||
150, 152, 154, 156, 158,
|
||||
160, 162, 164, 166, 168,
|
||||
170, 172, 174, 176, 178,
|
||||
180, 182, 184, 186, 188,
|
||||
190, 192,
|
||||
|
||||
Locations.Pelago7, // 30016
|
||||
};
|
||||
|
||||
internal static readonly HashSet<ushort> ValidMet_USUM = new(ValidMet_SM)
|
||||
{
|
||||
// 194, 195, 196, 197, // Unobtainable new Locations
|
||||
198,
|
||||
200, 202, 204, 206, 208,
|
||||
210, 212, 214, 216, 218,
|
||||
220, 222, 224, 226, 228,
|
||||
230, 232,
|
||||
};
|
||||
|
||||
#region Unreleased Items
|
||||
internal static readonly bool[] ReleasedHeldItems_7 = GetPermitList(MaxItemID_7_USUM, HeldItems_USUM, ItemStorage7SM.Unreleased);
|
||||
#endregion
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static partial class Legal
|
||||
{
|
||||
internal const int MaxSpeciesID_7b = 809; // Melmetal
|
||||
internal const int MaxMoveID_7b = 742; // Double Iron Bash
|
||||
internal const int MaxItemID_7b = 1057; // Magmar Candy
|
||||
internal const int MaxBallID_7b = (int)Ball.Beast;
|
||||
internal const int MaxGameID_7b = (int)GameVersion.GE;
|
||||
internal const int MaxAbilityID_7b = MaxAbilityID_7_USUM;
|
||||
internal static readonly ushort[] HeldItems_GG = Array.Empty<ushort>();
|
||||
public const byte AwakeningMax = 200;
|
||||
|
||||
#region Moves
|
||||
|
||||
public static bool IsAllowedMoveGG(ushort move) => AllowedMovesGG.BinarySearch(move) >= 0;
|
||||
|
||||
private static ReadOnlySpan<ushort> AllowedMovesGG => new ushort[]
|
||||
{
|
||||
000, 001, 002, 003, 004, 005, 006, 007, 008, 009,
|
||||
010, 011, 012, 013, 014, 015, 016, 017, 018, 019,
|
||||
020, 021, 022, 023, 024, 025, 026, 027, 028, 029,
|
||||
030, 031, 032, 033, 034, 035, 036, 037, 038, 039,
|
||||
040, 041, 042, 043, 044, 045, 046, 047, 048, 049,
|
||||
050, 051, 052, 053, 054, 055, 056, 057, 058, 059,
|
||||
060, 061, 062, 063, 064, 065, 066, 067, 068, 069,
|
||||
070, 071, 072, 073, 074, 075, 076, 077, 078, 079,
|
||||
080, 081, 082, 083, 084, 085, 086, 087, 088, 089,
|
||||
090, 091, 092, 093, 094, 095, 096, 097, 098, 099,
|
||||
100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
|
||||
110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
|
||||
120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
|
||||
130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
|
||||
140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
|
||||
150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
|
||||
160, 161, 162, 163, 164,
|
||||
|
||||
182, 188, 200, 224, 227, 231, 242, 243, 247, 252,
|
||||
257, 261, 263, 269, 270, 276, 280, 281, 339, 347,
|
||||
355, 364, 369, 389, 394, 398, 399, 403, 404, 405,
|
||||
406, 417, 420, 430, 438, 446, 453, 483, 492, 499,
|
||||
503, 504, 525, 529, 583, 585, 603, 605, 606, 607,
|
||||
729, 730, 731, 733, 734, 735, 736, 737, 738, 739,
|
||||
740, 742,
|
||||
};
|
||||
|
||||
#endregion
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static partial class Legal
|
||||
{
|
||||
// Current Binaries
|
||||
internal const int MaxSpeciesID_8 = MaxSpeciesID_8_R2;
|
||||
internal const int MaxMoveID_8 = MaxMoveID_8_R2;
|
||||
internal const int MaxItemID_8 = MaxItemID_8_R2;
|
||||
internal const int MaxAbilityID_8 = MaxAbilityID_8_R2;
|
||||
|
||||
// Orion (No DLC)
|
||||
internal const int MaxSpeciesID_8_O0 = 890; // Eternatus
|
||||
internal const int MaxMoveID_8_O0 = 796; // Steel Beam
|
||||
internal const int MaxItemID_8_O0 = 1278; // Rotom Catalog, ignore all catalog parts
|
||||
internal const int MaxAbilityID_8_O0 = 258; // Hunger Switch
|
||||
|
||||
// Rigel 1 (DLC 1: Isle of Armor)
|
||||
internal const int MaxSpeciesID_8_R1 = 893; // Zarude
|
||||
internal const int MaxMoveID_8_R1 = 818; // Surging Strikes
|
||||
internal const int MaxItemID_8_R1 = 1589; // Mark Charm
|
||||
internal const int MaxAbilityID_8_R1 = 260; // Unseen Fist
|
||||
|
||||
// Rigel 2 (DLC 2: Crown Tundra)
|
||||
internal const int MaxSpeciesID_8_R2 = 898; // Calyrex
|
||||
internal const int MaxMoveID_8_R2 = 826; // Eerie Spell
|
||||
internal const int MaxItemID_8_R2 = 1607; // Reins of Unity
|
||||
internal const int MaxAbilityID_8_R2 = 267; // As One (Glastrier)
|
||||
|
||||
internal const int MaxBallID_8 = 0x1A; // 26 Beast
|
||||
internal const int MaxGameID_8 = 45; // Shield
|
||||
|
||||
internal static readonly ushort[] HeldItems_SWSH = ItemStorage8SWSH.GetAllHeld();
|
||||
|
||||
internal static readonly HashSet<ushort> GalarOriginForms = new()
|
||||
{
|
||||
(int)Species.Meowth,
|
||||
(int)Species.Ponyta,
|
||||
(int)Species.Rapidash,
|
||||
(int)Species.Slowpoke,
|
||||
(int)Species.Farfetchd,
|
||||
(int)Species.MrMime,
|
||||
(int)Species.Corsola,
|
||||
(int)Species.Zigzagoon,
|
||||
(int)Species.Linoone,
|
||||
(int)Species.Yamask,
|
||||
(int)Species.Darumaka,
|
||||
(int)Species.Darmanitan,
|
||||
(int)Species.Stunfisk,
|
||||
};
|
||||
|
||||
internal static readonly HashSet<ushort> GalarVariantFormEvolutions = new()
|
||||
{
|
||||
(int)Species.MrMime,
|
||||
(int)Species.Weezing,
|
||||
};
|
||||
|
||||
internal static readonly HashSet<ushort> ValidMet_SWSH = new()
|
||||
{
|
||||
006, 008,
|
||||
012, 014, 016, 018,
|
||||
020, 022, 024, 028,
|
||||
030, 032, 034, 036,
|
||||
040, 044, 046, 048,
|
||||
052, 054, 056, 058,
|
||||
060, 064, 066, 068,
|
||||
070, 072, 076, 078,
|
||||
080, 084, 086, 088,
|
||||
090, 092, 094, 096, 098,
|
||||
102, 104, 106, 108,
|
||||
110, 112, 114, 116, 118,
|
||||
120, 122, 124, 126, 128,
|
||||
130, 132, 134, 136, 138,
|
||||
140, 142, 144, 146, 148,
|
||||
150, 152, 154, 156, 158,
|
||||
160, 164, 166, 168,
|
||||
170, 172, 174, 176, 178,
|
||||
180, 182, 184, 186, 188,
|
||||
190, 192, 194, 196, 198,
|
||||
200,
|
||||
|
||||
202, 204, 206, 208, 210,
|
||||
212, 214, 216, 218, 220,
|
||||
222, 224, 226, 228, 230,
|
||||
232, 234, 236, 238, 240,
|
||||
242, 244, 246,
|
||||
};
|
||||
|
||||
#region Unreleased Items
|
||||
|
||||
private const int DMAX_START = 1279;
|
||||
private const int DMAX_END = 1578;
|
||||
private const int DMAX_LEGAL_END = 1290; // ★Sgr7194 (Eevee)
|
||||
public static bool IsDynamaxCrystal(ushort item) => item is >= DMAX_START and <= DMAX_END;
|
||||
public static bool IsDynamaxCrystalAvailable(ushort item) => item is >= DMAX_START and <= DMAX_LEGAL_END;
|
||||
|
||||
internal static readonly bool[] ReleasedHeldItems_8 = GetPermitList(MaxItemID_8, HeldItems_SWSH, ItemStorage8SWSH.Unreleased);
|
||||
#endregion
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static partial class Legal
|
||||
{
|
||||
internal const int MaxSpeciesID_8a = (int)Species.Enamorus;
|
||||
internal const int MaxMoveID_8a = (int)Move.TakeHeart;
|
||||
internal const int MaxItemID_8a = 1828; // Legend Plate
|
||||
internal const int MaxBallID_8a = (int)Ball.LAOrigin;
|
||||
internal const int MaxGameID_8a = (int)GameVersion.SP;
|
||||
internal const int MaxAbilityID_8a = MaxAbilityID_8_R2;
|
||||
|
||||
internal static readonly ushort[] HeldItems_LA = Array.Empty<ushort>();
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static partial class Legal
|
||||
{
|
||||
internal const int MaxSpeciesID_8b = MaxSpeciesID_4; // Arceus-493
|
||||
internal const int MaxMoveID_8b = MaxMoveID_8_R2;
|
||||
internal const int MaxItemID_8b = 1822; // DS Sounds
|
||||
internal const int MaxBallID_8b = (int)Ball.LAOrigin;
|
||||
internal const int MaxGameID_8b = (int)GameVersion.SP;
|
||||
internal const int MaxAbilityID_8b = MaxAbilityID_8_R2;
|
||||
|
||||
internal static readonly ushort[] HeldItems_BS = ItemStorage8BDSP.GetAll();
|
||||
|
||||
#region Unreleased Items
|
||||
internal static readonly bool[] ReleasedHeldItems_8b = GetPermitList(MaxItemID_8b, HeldItems_BS, ItemStorage8BDSP.Unreleased);
|
||||
#endregion
|
||||
|
||||
private const int MaxValidHatchLocation8b = 657;
|
||||
|
||||
public static bool IsValidEggHatchLocation8b(ushort location, GameVersion version)
|
||||
{
|
||||
if ((uint)location > MaxValidHatchLocation8b)
|
||||
return false;
|
||||
var loc16 = location;
|
||||
if (LocationsNoHatchBDSP.Contains(loc16))
|
||||
return false;
|
||||
|
||||
// Check if the location isn't an exclusive location that is only accessible in the other game.
|
||||
var table = version == GameVersion.BD ? LocationsExclusiveSP : LocationsExclusiveBD;
|
||||
return !table.Contains(loc16);
|
||||
}
|
||||
|
||||
private static readonly HashSet<ushort> LocationsExclusiveBD = new()
|
||||
{
|
||||
216, // Spear Pillar
|
||||
218, // Hall of Origin
|
||||
498, // Ramanas Park (Johto Room)
|
||||
503, // Ramanas Park (Rainbow Room)
|
||||
650, // Ramanas Park (Johto Room)
|
||||
655, // Ramanas Park (Rainbow Room)
|
||||
};
|
||||
|
||||
private static readonly HashSet<ushort> LocationsExclusiveSP = new()
|
||||
{
|
||||
217, // Spear Pillar
|
||||
497, // Ramanas Park (Kanto Room)
|
||||
504, // Ramanas Park (Squall Room)
|
||||
618, // Hall of Origin
|
||||
649, // Ramanas Park (Kanto Room)
|
||||
656, // Ramanas Park (Squall Room)
|
||||
};
|
||||
|
||||
private static readonly HashSet<ushort> LocationsNoHatchBDSP = new()
|
||||
{
|
||||
094, 103, 107, // Hearthome City
|
||||
154, 155, 158, // Sunyshore City
|
||||
181, 182, 183, // Pokémon League
|
||||
329, // Lake Acuity
|
||||
337, 338, // Battle Park
|
||||
339, 340, 341, 342, 343, 344, // Battle Tower
|
||||
345, 353, 421, // Mystery Zone
|
||||
474, // Resort Area
|
||||
483, 484, // Mystery Zone
|
||||
491, 492, 493, // Mystery Zone
|
||||
495, // Ramanas Park
|
||||
620, 621, 622, 623, // Grand Underground (Secret Base)
|
||||
625, // Sea (sailing animation)
|
||||
627, 628, 629, 630, 631, 632, // Grand Underground (Secret Base)
|
||||
633, 634, 635, 636, 637, 638, // Grand Underground (Secret Base)
|
||||
639, 640, 641, 642, 643, 644, // Grand Underground (Secret Base)
|
||||
645, 646, 647, // Grand Underground (Secret Base)
|
||||
};
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
public static partial class Legal
|
||||
{
|
||||
internal const int MaxSpeciesID_9 = (int)Species.IronLeaves;
|
||||
internal const int MaxMoveID_9 = (int)Move.MagicalTorque;
|
||||
internal const int MaxItemID_9 = 2400; // Yellow Dish
|
||||
internal const int MaxAbilityID_9 = (int)Ability.MyceliumMight;
|
||||
|
||||
internal const int MaxBallID_9 = (int)Ball.LAOrigin;
|
||||
internal const int MaxGameID_9 = (int)GameVersion.VL;
|
||||
|
||||
internal static readonly ushort[] HeldItems_SV = ItemStorage9SV.GetAllHeld();
|
||||
|
||||
internal static readonly HashSet<ushort> ValidMet_SV = new()
|
||||
{
|
||||
006,
|
||||
010, 012, 014, 016, 018,
|
||||
020, 022, 024, 026, 028,
|
||||
030, 032, 034, 036, 038,
|
||||
040, 044, 046, 048,
|
||||
050, 052, 056, 058,
|
||||
060, 062, 064,
|
||||
|
||||
067, 069, 070, 072, 076,
|
||||
078, 080, 082, 084, 086,
|
||||
088, 090, 092, 094, 096,
|
||||
|
||||
099, 101, 103, 105, 107,
|
||||
109, 111, 113, 115, 117,
|
||||
118, 124, 130,
|
||||
131,
|
||||
};
|
||||
|
||||
public static bool IsValidEggHatchLocation9(ushort location, GameVersion version)
|
||||
{
|
||||
if (version == GameVersion.SL && location == 131) // Uva Academy does not exist in Scarlet
|
||||
return false;
|
||||
if (version == GameVersion.VL && location == 130) // Naranja Academy does not exist in Violet
|
||||
return false;
|
||||
return ValidMet_SV.Contains(location);
|
||||
}
|
||||
|
||||
#region Unreleased Items
|
||||
|
||||
internal static readonly bool[] ReleasedHeldItems_9 = GetPermitList(MaxItemID_9, HeldItems_SV, ItemStorage9SV.Unreleased);
|
||||
#endregion
|
||||
}
|
|
@ -179,35 +179,6 @@ public sealed class FormVerifier : Verifier
|
|||
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) && pk.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return VALID;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,9 +57,8 @@ public sealed class GenderVerifier : Verifier
|
|||
return IsValidGenderMismatch(pk);
|
||||
|
||||
// check for mixed->fixed gender incompatibility by checking the gender of the original species
|
||||
var original = data.EncounterMatch.Species;
|
||||
if (Legal.FixedGenderFromBiGender.Contains(original))
|
||||
return IsValidFixedGenderFromBiGender(pk, original);
|
||||
if (SpeciesCategory.IsFixedGenderFromDual(pk.Species))
|
||||
return IsValidFixedGenderFromBiGender(pk, data.EncounterMatch.Species);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -82,10 +82,8 @@ public sealed class LegendsArceusVerifier : Verifier
|
|||
private static int LoadBareMinimumMoveset(ISpeciesForm enc, EvolutionHistory h, PA8 pa, Span<ushort> moves)
|
||||
{
|
||||
// Get any encounter moves
|
||||
var pt = PersonalTable.LA;
|
||||
var index = pt.GetFormIndex(enc.Species, enc.Form);
|
||||
var learn = Legal.LevelUpLA;
|
||||
var moveset = learn[index];
|
||||
var ls = LearnSource8LA.Instance;
|
||||
var moveset = ls.GetLearnset(enc.Species, enc.Form);
|
||||
if (enc is IMasteryInitialMoveShop8 ms)
|
||||
ms.LoadInitialMoveset(pa, moves, moveset, pa.Met_Level);
|
||||
else
|
||||
|
@ -114,8 +112,7 @@ public sealed class LegendsArceusVerifier : Verifier
|
|||
for (int i = 0; i < evos.Length - 1; i++)
|
||||
{
|
||||
var evo = evos[i];
|
||||
var x = pt.GetFormIndex(evo.Species, evo.Form);
|
||||
var m = learn[x];
|
||||
var m = ls.GetLearnset(evo.Species, evo.Form);
|
||||
m.SetEvolutionMoves(moves, purchased, count);
|
||||
count = moves.IndexOf((ushort)0);
|
||||
if ((uint)count >= 4)
|
||||
|
@ -123,8 +120,7 @@ public sealed class LegendsArceusVerifier : Verifier
|
|||
}
|
||||
|
||||
// Any tutored moves we don't know about??
|
||||
var currentIndex = pt.GetFormIndex(evos[0].Species, evos[0].Form);
|
||||
var currentLearn = learn[currentIndex];
|
||||
var currentLearn = ls.GetLearnset(evos[0].Species, evos[0].Form);
|
||||
return AddMasteredMissing(pa, moves, count, moveset, currentLearn, level);
|
||||
}
|
||||
|
||||
|
@ -230,9 +226,7 @@ public sealed class LegendsArceusVerifier : Verifier
|
|||
int level = 101;
|
||||
foreach (var evo in data.Info.EvoChainsAllGens.Gen8a)
|
||||
{
|
||||
var pt = PersonalTable.LA;
|
||||
var index = pt.GetFormIndex(evo.Species, evo.Form);
|
||||
var moveset = Legal.LevelUpLA[index];
|
||||
var moveset = LearnSource8LA.Instance.GetLearnset(evo.Species, evo.Form);
|
||||
var lvl = moveset.GetLevelLearnMove(moves[i]);
|
||||
if (lvl == -1)
|
||||
continue; // cannot learn via level up
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static PKHeX.Core.Species;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
||||
|
@ -101,7 +103,7 @@ public static class RibbonRules
|
|||
{
|
||||
// Ranked is still ongoing, but the use of Mythicals was restricted to Series 13 only.
|
||||
var met = pk.MetDate;
|
||||
if (Legal.Mythicals.Contains(pk.Species) && met > new DateOnly(2022, 11, 1))
|
||||
if (SpeciesCategory.IsMythical(pk.Species) && met > new DateOnly(2022, 11, 1))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -113,9 +115,9 @@ public static class RibbonRules
|
|||
private static bool IsRibbonValidMasterRankSV(ISpeciesForm pk)
|
||||
{
|
||||
var species = pk.Species;
|
||||
if (Legal.Mythicals.Contains(species))
|
||||
if (SpeciesCategory.IsMythical(species))
|
||||
return false;
|
||||
if (Legal.Legends.Contains(species))
|
||||
if (SpeciesCategory.IsLegendary(species))
|
||||
return false;
|
||||
|
||||
var pt = PersonalTable.SV;
|
||||
|
@ -146,7 +148,7 @@ public static class RibbonRules
|
|||
if (!evos.HasVisitedBDSP)
|
||||
return false;
|
||||
// Mythicals cannot be used in BD/SP's Battle Tower
|
||||
return !Legal.Mythicals.Contains(evos.Gen8b[0].Species);
|
||||
return !SpeciesCategory.IsMythical(evos.Gen8b[0].Species);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -360,7 +362,7 @@ public static class RibbonRules
|
|||
/// <summary>
|
||||
/// Checks if the input species could have participated in any Battle Frontier trial.
|
||||
/// </summary>
|
||||
public static bool IsAllowedBattleFrontier(ushort species) => !Legal.BattleFrontierBanlist.Contains(species);
|
||||
public static bool IsAllowedBattleFrontier(ushort species) => !BattleFrontierBanlist.Contains(species);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the input species could have participated in Generation 4's Battle Frontier.
|
||||
|
@ -382,4 +384,20 @@ public static class RibbonRules
|
|||
return false;
|
||||
return IsAllowedBattleFrontier(species);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generation 3 & 4 Battle Frontier Species banlist. When referencing this in context to generation 4, be sure to disallow <see cref="Pichu"/> with Form 1 (Spiky).
|
||||
/// </summary>
|
||||
public static readonly HashSet<ushort> BattleFrontierBanlist = new()
|
||||
{
|
||||
(int)Mewtwo, (int)Mew,
|
||||
(int)Lugia, (int)HoOh, (int)Celebi,
|
||||
(int)Kyogre, (int)Groudon, (int)Rayquaza, (int)Jirachi, (int)Deoxys,
|
||||
(int)Dialga, (int)Palkia, (int)Giratina, (int)Phione, (int)Manaphy, (int)Darkrai, (int)Shaymin, (int)Arceus,
|
||||
(int)Victini, (int)Reshiram, (int)Zekrom, (int)Kyurem, (int)Keldeo, (int)Meloetta, (int)Genesect,
|
||||
(int)Xerneas, (int)Yveltal, (int)Zygarde, (int)Diancie, (int)Hoopa, (int)Volcanion,
|
||||
(int)Cosmog, (int)Cosmoem, (int)Solgaleo, (int)Lunala, (int)Necrozma, (int)Magearna, (int)Marshadow, (int)Zeraora,
|
||||
(int)Meltan, (int)Melmetal,
|
||||
(int)Koraidon, (int)Miraidon,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -51,4 +51,35 @@ internal static class MoveInfo7b
|
|||
05, 15, 05, 01, 01, 01, 01, 01, 01, 15, 15, 15, 20, 15, 15, 15, 15, 15, 15, 15,
|
||||
15, 20, 05,
|
||||
};
|
||||
|
||||
public static bool IsAllowedMoveGG(ushort move) => AllowedMovesGG.BinarySearch(move) >= 0;
|
||||
|
||||
private static ReadOnlySpan<ushort> AllowedMovesGG => new ushort[]
|
||||
{
|
||||
000, 001, 002, 003, 004, 005, 006, 007, 008, 009,
|
||||
010, 011, 012, 013, 014, 015, 016, 017, 018, 019,
|
||||
020, 021, 022, 023, 024, 025, 026, 027, 028, 029,
|
||||
030, 031, 032, 033, 034, 035, 036, 037, 038, 039,
|
||||
040, 041, 042, 043, 044, 045, 046, 047, 048, 049,
|
||||
050, 051, 052, 053, 054, 055, 056, 057, 058, 059,
|
||||
060, 061, 062, 063, 064, 065, 066, 067, 068, 069,
|
||||
070, 071, 072, 073, 074, 075, 076, 077, 078, 079,
|
||||
080, 081, 082, 083, 084, 085, 086, 087, 088, 089,
|
||||
090, 091, 092, 093, 094, 095, 096, 097, 098, 099,
|
||||
100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
|
||||
110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
|
||||
120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
|
||||
130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
|
||||
140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
|
||||
150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
|
||||
160, 161, 162, 163, 164,
|
||||
|
||||
182, 188, 200, 224, 227, 231, 242, 243, 247, 252,
|
||||
257, 261, 263, 269, 270, 276, 280, 281, 339, 347,
|
||||
355, 364, 369, 389, 394, 398, 399, 403, 404, 405,
|
||||
406, 417, 420, 430, 438, 446, 453, 483, 492, 499,
|
||||
503, 504, 525, 529, 583, 585, 603, 605, 606, 607,
|
||||
729, 730, 731, 733, 734, 735, 736, 737, 738, 739,
|
||||
740, 742,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -247,7 +247,8 @@ public sealed class PGF : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I
|
|||
if (Move1 == 0) // No moves defined
|
||||
{
|
||||
Span<ushort> moves = stackalloc ushort[4];
|
||||
MoveLevelUp.GetEncounterMoves(moves, Species, Form, Level, (GameVersion)pk.Version);
|
||||
var source = GameData.GetLearnSource((GameVersion)pk.Version);
|
||||
source.SetEncounterMoves(Species, Form, Level, moves);
|
||||
pk.SetMoves(moves);
|
||||
}
|
||||
|
||||
|
|
|
@ -165,8 +165,18 @@ public sealed class WC3 : MysteryGift, IRibbonSetEvent3, ILangNicknamedTemplate
|
|||
{
|
||||
if (!Moves.HasMoves) // not completely defined
|
||||
{
|
||||
var ver = (GameVersion)pk.Version;
|
||||
ILearnSource ls = ver switch
|
||||
{
|
||||
GameVersion.R or GameVersion.S => LearnSource3RS.Instance,
|
||||
GameVersion.FR => LearnSource3FR.Instance,
|
||||
GameVersion.LG => LearnSource3LG.Instance,
|
||||
_ => LearnSource3E.Instance,
|
||||
};
|
||||
|
||||
var learn = ls.GetLearnset(Species, Form);
|
||||
Span<ushort> moves = stackalloc ushort[4];
|
||||
MoveList.GetCurrentMoves(pk, Species, Form, (GameVersion)pk.Version, Level, moves);
|
||||
learn.SetEncounterMoves(Level, moves);
|
||||
Moves = new(moves[0], moves[1], moves[2], moves[3]);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,8 +16,13 @@ public interface IAwakened
|
|||
byte AV_SPD { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logic for interacting with LGP/E Awakening values.
|
||||
/// </summary>
|
||||
public static class AwakeningUtil
|
||||
{
|
||||
public const byte AwakeningMax = 200;
|
||||
|
||||
/// <summary>
|
||||
/// Sums all values.
|
||||
/// </summary>
|
||||
|
@ -34,7 +39,7 @@ public static class AwakeningUtil
|
|||
/// Sets all values to the maximum value.
|
||||
/// </summary>
|
||||
/// <param name="pk">Data to set values for</param>
|
||||
public static void AwakeningMax(this IAwakened pk) => pk.AwakeningSetAllTo(Legal.AwakeningMax);
|
||||
public static void AwakeningMaximize(this IAwakened pk) => pk.AwakeningSetAllTo(AwakeningMax);
|
||||
|
||||
/// <summary>
|
||||
/// Sets all values to the specified value.
|
||||
|
@ -63,7 +68,7 @@ public static class AwakeningUtil
|
|||
/// <param name="pk">Data to set values for</param>
|
||||
/// <param name="min">Minimum value to set</param>
|
||||
/// <param name="max">Maximum value to set</param>
|
||||
public static void AwakeningSetRandom(this IAwakened pk, byte min = 0, int max = Legal.AwakeningMax)
|
||||
public static void AwakeningSetRandom(this IAwakened pk, byte min = 0, int max = AwakeningMax)
|
||||
{
|
||||
if (pk is not PB7 pb7)
|
||||
return;
|
||||
|
@ -117,17 +122,17 @@ public static class AwakeningUtil
|
|||
/// <param name="pk">Data to check</param>
|
||||
public static bool AwakeningAllValid(this IAwakened pk)
|
||||
{
|
||||
if (pk.AV_HP > Legal.AwakeningMax)
|
||||
if (pk.AV_HP > AwakeningMax)
|
||||
return false;
|
||||
if (pk.AV_ATK > Legal.AwakeningMax)
|
||||
if (pk.AV_ATK > AwakeningMax)
|
||||
return false;
|
||||
if (pk.AV_DEF > Legal.AwakeningMax)
|
||||
if (pk.AV_DEF > AwakeningMax)
|
||||
return false;
|
||||
if (pk.AV_SPE > Legal.AwakeningMax)
|
||||
if (pk.AV_SPE > AwakeningMax)
|
||||
return false;
|
||||
if (pk.AV_SPA > Legal.AwakeningMax)
|
||||
if (pk.AV_SPA > AwakeningMax)
|
||||
return false;
|
||||
if (pk.AV_SPD > Legal.AwakeningMax)
|
||||
if (pk.AV_SPD > AwakeningMax)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -189,12 +194,12 @@ public static class AwakeningUtil
|
|||
{
|
||||
Span<byte> result = stackalloc byte[6];
|
||||
SetExpectedMinimumAVs(result, (PB7)a);
|
||||
a.AV_HP = Legal.AwakeningMax;
|
||||
a.AV_ATK = pk.IV_ATK == 0 ? result[1] : Legal.AwakeningMax;
|
||||
a.AV_DEF = Legal.AwakeningMax;
|
||||
a.AV_SPA = Legal.AwakeningMax;
|
||||
a.AV_SPD = Legal.AwakeningMax;
|
||||
a.AV_SPE = pk.IV_SPE == 0 ? result[5] : Legal.AwakeningMax;
|
||||
a.AV_HP = AwakeningMax;
|
||||
a.AV_ATK = pk.IV_ATK == 0 ? result[1] : AwakeningMax;
|
||||
a.AV_DEF = AwakeningMax;
|
||||
a.AV_SPA = AwakeningMax;
|
||||
a.AV_SPD = AwakeningMax;
|
||||
a.AV_SPE = pk.IV_SPE == 0 ? result[5] : AwakeningMax;
|
||||
}
|
||||
|
||||
public static bool IsAwakeningBelow(this IAwakened current, IAwakened initial) => !current.IsAwakeningAboveOrEqual(initial);
|
||||
|
|
|
@ -38,7 +38,8 @@ public static class BattleVersionExtensions
|
|||
pk.SetRelearnMoves(empty);
|
||||
|
||||
Span<ushort> moves = stackalloc ushort[4];
|
||||
MoveLevelUp.GetEncounterMoves(moves, pk, pk.CurrentLevel, version);
|
||||
var source = GameData.GetLearnSource(version);
|
||||
source.SetEncounterMoves(pk.Species, pk.Form, pk.CurrentLevel, moves);
|
||||
pk.SetMoves(moves);
|
||||
pk.FixMoves();
|
||||
v.BattleVersion = (byte)version;
|
||||
|
|
|
@ -1055,11 +1055,7 @@ public sealed class PA8 : PKM, ISanityChecksum, IMoveReset,
|
|||
|
||||
public void ResetMoves()
|
||||
{
|
||||
var learnsets = Legal.LevelUpLA;
|
||||
var table = PersonalTable.LA;
|
||||
|
||||
var index = table.GetFormIndex(Species, Form);
|
||||
var learn = learnsets[index];
|
||||
var learn = LearnSource8LA.Instance.GetLearnset(Species, Form);
|
||||
Span<ushort> moves = stackalloc ushort[4];
|
||||
learn.SetEncounterMoves(CurrentLevel, moves);
|
||||
SetMoves(moves);
|
||||
|
|
|
@ -147,11 +147,7 @@ public sealed class PB8 : G8PKM
|
|||
|
||||
public override void ResetMoves()
|
||||
{
|
||||
var learnsets = Legal.LevelUpBDSP;
|
||||
var table = PersonalTable.BDSP;
|
||||
|
||||
var index = table.GetFormIndex(Species, Form);
|
||||
var learn = learnsets[index];
|
||||
var learn = LearnSource8BDSP.Instance.GetLearnset(Species, Form);
|
||||
Span<ushort> moves = stackalloc ushort[4];
|
||||
learn.SetEncounterMoves(CurrentLevel, moves);
|
||||
SetMoves(moves);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue