mirror of
https://github.com/kwsch/PKHeX
synced 2025-02-17 05:48:44 +00:00
Misc style & minor tweaks
Remove move combobox flicker hack (no longer necessary) Add more Array.Empty usages cache mysterygift sizes seal some classes no functionality changes
This commit is contained in:
parent
0745ba3294
commit
1486b7f14a
68 changed files with 987 additions and 239 deletions
|
@ -34,6 +34,9 @@ namespace PKHeX.Core
|
|||
public IReadOnlyList<string> Natures => natures;
|
||||
|
||||
private string[] Get(string ident) => GameInfo.GetStrings(ident, lang);
|
||||
private const string NPC = "NPC";
|
||||
private static readonly string[] abilIdentifier = { " (1)", " (2)", " (H)" };
|
||||
private static readonly IReadOnlyList<ComboItem> LanguageList = Util.GetUnsortedCBList("languages");
|
||||
|
||||
public GameStrings(string l)
|
||||
{
|
||||
|
@ -63,12 +66,7 @@ namespace PKHeX.Core
|
|||
metGSC_00000 = Get("gsc_00000");
|
||||
|
||||
metCXD_00000 = Get("cxd_00000");
|
||||
// Sanitize a little
|
||||
var metSanitize = (string[])metCXD_00000.Clone();
|
||||
for (int i = 0; i < metSanitize.Length; i++)
|
||||
if (metCXD_00000.Count(r => r == metSanitize[i]) > 1)
|
||||
metSanitize[i] += $" [{i:000}]";
|
||||
metCXD_00000 = metSanitize;
|
||||
metCXD_00000 = SanitizeMetStringsCXD(metCXD_00000);
|
||||
|
||||
// Current Generation strings
|
||||
natures = Util.GetNaturesList(l);
|
||||
|
@ -127,7 +125,19 @@ namespace PKHeX.Core
|
|||
InitializeDataSources();
|
||||
}
|
||||
|
||||
private const string NPC = "NPC";
|
||||
private static string[] SanitizeMetStringsCXD(string[] cxd)
|
||||
{
|
||||
// Mark duplicate locations with their index
|
||||
var metSanitize = (string[])cxd.Clone();
|
||||
for (int i = 0; i < metSanitize.Length; i++)
|
||||
{
|
||||
if (cxd.Count(r => r == metSanitize[i]) > 1)
|
||||
metSanitize[i] += $" [{i:000}]";
|
||||
}
|
||||
|
||||
return metSanitize;
|
||||
}
|
||||
|
||||
private void Sanitize()
|
||||
{
|
||||
SanitizeItemNames();
|
||||
|
@ -139,6 +149,7 @@ namespace PKHeX.Core
|
|||
var none = $"({itemlist[0]})";
|
||||
abilitylist[0] = itemlist[0] = movelist[0] = metXY_00000[0] = metBW2_00000[0] = metHGSS_00000[0] = metCXD_00000[0] = puffs[0] = none;
|
||||
}
|
||||
|
||||
private void SanitizeItemNames()
|
||||
{
|
||||
// Fix Item Names (Duplicate entries)
|
||||
|
@ -175,6 +186,7 @@ namespace PKHeX.Core
|
|||
for (int i = 12; i <= 29; i++) // Differentiate DNA Samples
|
||||
g3coloitems[500 + i] += $" ({i - 11:00})";
|
||||
}
|
||||
|
||||
private void SanitizeMetLocations()
|
||||
{
|
||||
// Fix up some of the Location strings to make them more descriptive
|
||||
|
@ -182,6 +194,7 @@ namespace PKHeX.Core
|
|||
SanitizeMetG6XY();
|
||||
SanitizeMetG7SM();
|
||||
}
|
||||
|
||||
private void SanitizeMetG5BW()
|
||||
{
|
||||
metHGSS_02000[1] += $" ({NPC})"; // Anything from an NPC
|
||||
|
@ -210,6 +223,7 @@ namespace PKHeX.Core
|
|||
|
||||
metBW2_60000[3 - 1] += $" ({eggname})"; // Egg Treasure Hunter/Breeder, whatever...
|
||||
}
|
||||
|
||||
private void SanitizeMetG6XY()
|
||||
{
|
||||
metXY_00000[104] += " (X/Y)"; // Victory Road
|
||||
|
@ -219,6 +233,7 @@ namespace PKHeX.Core
|
|||
metXY_30000[0] += $" ({NPC})"; // Anything from an NPC
|
||||
metXY_30000[1] += $" ({eggname})"; // Egg From Link Trade
|
||||
}
|
||||
|
||||
private void SanitizeMetG7SM()
|
||||
{
|
||||
// Sun/Moon duplicates -- elaborate!
|
||||
|
@ -252,6 +267,7 @@ namespace PKHeX.Core
|
|||
default: return itemlist;
|
||||
}
|
||||
}
|
||||
|
||||
private string[] GetItemStrings3(GameVersion game)
|
||||
{
|
||||
switch (game)
|
||||
|
@ -387,6 +403,7 @@ namespace PKHeX.Core
|
|||
var items = GetItemStrings(generation, game);
|
||||
ItemDataSource = Util.GetCBList(items, (allowed == null || HaX ? Enumerable.Range(0, MaxItemID) : allowed.Select(i => (int)i)).ToArray());
|
||||
}
|
||||
|
||||
public IReadOnlyList<ComboItem> GetLocationList(GameVersion Version, int SaveFormat, bool egg)
|
||||
{
|
||||
if (SaveFormat == 2)
|
||||
|
@ -471,19 +488,22 @@ namespace PKHeX.Core
|
|||
|
||||
// Currently on a future game, return corresponding list for generation
|
||||
if (Version <= GameVersion.CXD && SaveFormat == 4)
|
||||
{
|
||||
return MetGen4.Where(loc => loc.Value == Legal.Transfer3) // Pal Park to front
|
||||
.Concat(MetGen4.Take(4))
|
||||
.Concat(MetGen4.Skip(4).Where(loc => loc.Value != Legal.Transfer3)).ToList();
|
||||
.Concat(MetGen4.Take(4))
|
||||
.Concat(MetGen4.Skip(4).Where(loc => loc.Value != Legal.Transfer3)).ToList();
|
||||
}
|
||||
|
||||
if (Version < GameVersion.X && SaveFormat >= 5) // PokéTransfer to front
|
||||
{
|
||||
return MetGen5.Where(loc => loc.Value == Legal.Transfer4)
|
||||
.Concat(MetGen5.Take(3))
|
||||
.Concat(MetGen5.Skip(3).Where(loc => loc.Value != Legal.Transfer4)).ToList();
|
||||
.Concat(MetGen5.Take(3))
|
||||
.Concat(MetGen5.Skip(3).Where(loc => loc.Value != Legal.Transfer4)).ToList();
|
||||
}
|
||||
|
||||
return MetGen6;
|
||||
}
|
||||
|
||||
private static readonly IReadOnlyList<ComboItem> LanguageList = Util.GetUnsortedCBList("languages");
|
||||
public static IReadOnlyList<ComboItem> LanguageDataSource(int gen)
|
||||
{
|
||||
var languages = LanguageList.ToList();
|
||||
|
@ -494,14 +514,13 @@ namespace PKHeX.Core
|
|||
return languages;
|
||||
}
|
||||
|
||||
private static readonly string[] abilIdentifier = { " (1)", " (2)", " (H)" };
|
||||
public IReadOnlyList<ComboItem> GetAbilityDataSource(IEnumerable<int> abils)
|
||||
{
|
||||
return abils.Select(GetItem).ToList();
|
||||
ComboItem GetItem(int ability, int index) => new ComboItem
|
||||
{
|
||||
Value = ability,
|
||||
Text = GameInfo.Strings.abilitylist[ability] + abilIdentifier[index]
|
||||
Text = abilitylist[ability] + abilIdentifier[index]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace PKHeX.Core
|
|||
public class MemoryStrings
|
||||
{
|
||||
private readonly GameStrings s;
|
||||
|
||||
public MemoryStrings(GameStrings strings)
|
||||
{
|
||||
s = strings;
|
||||
|
@ -30,7 +31,6 @@ namespace PKHeX.Core
|
|||
public List<ComboItem> SpecificLocations => specific.Value;
|
||||
public List<ComboItem> Species => species.Value;
|
||||
|
||||
|
||||
private List<ComboItem> GetMemories()
|
||||
{
|
||||
// Memory Chooser
|
||||
|
@ -47,7 +47,6 @@ namespace PKHeX.Core
|
|||
return Util.GetOffsetCBList(memory_list1, mems, 0, allowed);
|
||||
}
|
||||
|
||||
|
||||
public List<string> GetMemoryQualities()
|
||||
{
|
||||
List<string> list = new List<string>();
|
||||
|
@ -55,6 +54,7 @@ namespace PKHeX.Core
|
|||
list.Add(s.memories[2 + i]);
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<string> GetMemoryFeelings()
|
||||
{
|
||||
List<string> list = new List<string>();
|
||||
|
|
|
@ -10,19 +10,19 @@ namespace PKHeX.Core
|
|||
public static class EncounterEvent
|
||||
{
|
||||
/// <summary>Event Database for Generation 3</summary>
|
||||
public static MysteryGift[] MGDB_G3 { get; private set; } = new MysteryGift[0];
|
||||
public static MysteryGift[] MGDB_G3 { get; private set; } = Array.Empty<MysteryGift>();
|
||||
|
||||
/// <summary>Event Database for Generation 4</summary>
|
||||
public static MysteryGift[] MGDB_G4 { get; private set; } = new MysteryGift[0];
|
||||
public static MysteryGift[] MGDB_G4 { get; private set; } = Array.Empty<MysteryGift>();
|
||||
|
||||
/// <summary>Event Database for Generation 5</summary>
|
||||
public static MysteryGift[] MGDB_G5 { get; private set; } = new MysteryGift[0];
|
||||
public static MysteryGift[] MGDB_G5 { get; private set; } = Array.Empty<MysteryGift>();
|
||||
|
||||
/// <summary>Event Database for Generation 6</summary>
|
||||
public static MysteryGift[] MGDB_G6 { get; private set; } = new MysteryGift[0];
|
||||
public static MysteryGift[] MGDB_G6 { get; private set; } = Array.Empty<MysteryGift>();
|
||||
|
||||
/// <summary>Event Database for Generation 7</summary>
|
||||
public static MysteryGift[] MGDB_G7 { get; private set; } = new MysteryGift[0];
|
||||
public static MysteryGift[] MGDB_G7 { get; private set; } = Array.Empty<MysteryGift>();
|
||||
|
||||
/// <summary>Indicates if the databases are initialized.</summary>
|
||||
public static bool Initialized => MGDB_G3.Length != 0;
|
||||
|
@ -36,6 +36,7 @@ namespace PKHeX.Core
|
|||
yield return data;
|
||||
}
|
||||
}
|
||||
|
||||
private static HashSet<MysteryGift> GetPCDDB(byte[] bin) => new HashSet<MysteryGift>(GetData(bin, PCD.Size).Select(d => new PCD(d)));
|
||||
|
||||
private static HashSet<MysteryGift> GetPGFDB(byte[] bin) => new HashSet<MysteryGift>(GetData(bin, PGF.Size).Select(d => new PGF(d)));
|
||||
|
@ -56,19 +57,21 @@ namespace PKHeX.Core
|
|||
var g7 = GetWC7DB(Util.GetBinaryResource("wc7.pkl"), Util.GetBinaryResource("wc7full.pkl"));
|
||||
|
||||
foreach (var path in paths.Where(Directory.Exists))
|
||||
foreach (var file in Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
var fi = new FileInfo(file);
|
||||
if (!MysteryGift.IsMysteryGift(fi.Length))
|
||||
continue;
|
||||
|
||||
var gift = MysteryGift.GetMysteryGift(File.ReadAllBytes(file), fi.Extension);
|
||||
switch (gift?.Format)
|
||||
foreach (var file in Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
case 4: g4.Add(gift); continue;
|
||||
case 5: g5.Add(gift); continue;
|
||||
case 6: g6.Add(gift); continue;
|
||||
case 7: g7.Add(gift); continue;
|
||||
var fi = new FileInfo(file);
|
||||
if (!MysteryGift.IsMysteryGift(fi.Length))
|
||||
continue;
|
||||
|
||||
var gift = MysteryGift.GetMysteryGift(File.ReadAllBytes(file), fi.Extension);
|
||||
switch (gift?.Format)
|
||||
{
|
||||
case 4: g4.Add(gift); continue;
|
||||
case 5: g5.Add(gift); continue;
|
||||
case 6: g6.Add(gift); continue;
|
||||
case 7: g7.Add(gift); continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -80,9 +80,12 @@ namespace PKHeX.Core
|
|||
internal static void MarkEncountersStaticMagnetPull(IEnumerable<EncounterArea> Areas, PersonalTable t)
|
||||
{
|
||||
foreach (EncounterArea Area in Areas)
|
||||
foreach (var grp in Area.Slots.GroupBy(z => z.Type))
|
||||
MarkEncountersStaticMagnetPull(grp, t);
|
||||
{
|
||||
foreach (var grp in Area.Slots.GroupBy(z => z.Type))
|
||||
MarkEncountersStaticMagnetPull(grp, t);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void MarkEncountersStaticMagnetPull(IEnumerable<EncounterSlot> grp, PersonalTable t)
|
||||
{
|
||||
GetStaticMagnet(t, grp, out List<EncounterSlot> s, out List<EncounterSlot> m);
|
||||
|
@ -99,6 +102,7 @@ namespace PKHeX.Core
|
|||
slot.Permissions.MagnetPullCount = m.Count;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void MarkEncountersStaticMagnetPullPermutation(IEnumerable<EncounterSlot> grp, PersonalTable t, List<EncounterSlot> permuted)
|
||||
{
|
||||
GetStaticMagnet(t, grp, out List<EncounterSlot> s, out List<EncounterSlot> m);
|
||||
|
@ -137,6 +141,7 @@ namespace PKHeX.Core
|
|||
slot.Permissions.MagnetPullCount = m.Count;
|
||||
}
|
||||
}
|
||||
|
||||
private static void GetStaticMagnet(PersonalTable t, IEnumerable<EncounterSlot> grp, out List<EncounterSlot> s, out List<EncounterSlot> m)
|
||||
{
|
||||
const int steel = (int)MoveType.Steel;
|
||||
|
@ -162,8 +167,10 @@ namespace PKHeX.Core
|
|||
internal static void MarkEncountersVersion(IEnumerable<EncounterArea> Areas, GameVersion Version)
|
||||
{
|
||||
foreach (EncounterArea Area in Areas)
|
||||
foreach (var Slot in Area.Slots.OfType<EncounterSlot1>())
|
||||
Slot.Version = Version;
|
||||
{
|
||||
foreach (var Slot in Area.Slots)
|
||||
Slot.Version = Version;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -185,9 +192,12 @@ namespace PKHeX.Core
|
|||
internal static void MarkEncountersGeneration(int Generation, params IEnumerable<EncounterArea>[] Areas)
|
||||
{
|
||||
foreach (var table in Areas)
|
||||
foreach (var area in table)
|
||||
MarkEncountersGeneration(Generation, area.Slots);
|
||||
{
|
||||
foreach (var area in table)
|
||||
MarkEncountersGeneration(Generation, area.Slots);
|
||||
}
|
||||
}
|
||||
|
||||
private static void MarkEncountersGeneration(int Generation, IEnumerable<IGeneration> Encounters)
|
||||
{
|
||||
foreach (IGeneration enc in Encounters)
|
||||
|
@ -215,11 +225,14 @@ namespace PKHeX.Core
|
|||
foreach (var area in areas)
|
||||
MarkEncounterAreas(area);
|
||||
}
|
||||
|
||||
private static void MarkEncounterAreas(params EncounterArea[] areas)
|
||||
{
|
||||
foreach (var area in areas)
|
||||
foreach (var slot in area.Slots)
|
||||
slot.Area = area;
|
||||
{
|
||||
foreach (var slot in area.Slots)
|
||||
slot.Area = area;
|
||||
}
|
||||
}
|
||||
|
||||
internal static EncounterStatic Clone(this EncounterStatic s, int location)
|
||||
|
@ -228,6 +241,7 @@ namespace PKHeX.Core
|
|||
result.Location = location;
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static EncounterStatic[] Clone(this EncounterStatic s, int[] locations)
|
||||
{
|
||||
EncounterStatic[] Encounters = new EncounterStatic[locations.Length];
|
||||
|
@ -235,11 +249,13 @@ namespace PKHeX.Core
|
|||
Encounters[i] = s.Clone(locations[i]);
|
||||
return Encounters;
|
||||
}
|
||||
|
||||
internal static IEnumerable<EncounterStatic> DreamRadarClone(this EncounterStatic s)
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
yield return s.DreamRadarClone(5 * i + 5); // Level from 5->40 depends on the number of badges
|
||||
yield return s.DreamRadarClone((5 * i) + 5); // Level from 5->40 depends on the number of badges
|
||||
}
|
||||
|
||||
private static EncounterStatic DreamRadarClone(this EncounterStatic s, int level)
|
||||
{
|
||||
var result = s.Clone(level);
|
||||
|
|
|
@ -52,8 +52,11 @@ namespace PKHeX.Core
|
|||
table[table.Length - 1] = FishOldGood_RBY;
|
||||
|
||||
foreach (var arr in table)
|
||||
foreach (var slot in arr.Slots)
|
||||
slot.Area = arr;
|
||||
{
|
||||
foreach (var slot in arr.Slots)
|
||||
slot.Area = arr;
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
|
@ -197,6 +200,7 @@ namespace PKHeX.Core
|
|||
new EncounterTrade { Species = 051, Level = 05, Version = GameVersion.RBY }, // Dugtrio - Trade Lickitung (GSC 5)
|
||||
new EncounterTrade { Species = 047, Level = 05, Version = GameVersion.RBY }, // Parasect - Trade Tangela (GSC 5)
|
||||
}).ToArray();
|
||||
|
||||
private static readonly EncounterArea FishOldGood_RBY = new EncounterArea
|
||||
{
|
||||
Location = -1,
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace PKHeX.Core
|
|||
// Fishing
|
||||
var f = EncounterArea.GetArray2_F(Util.GetBinaryResource("encounter_gsc_f.pkl"));
|
||||
|
||||
EncounterArea[] Slots = new EncounterArea[0];
|
||||
var Slots = Array.Empty<EncounterArea>();
|
||||
if (Version.Contains(GameVersion.GS))
|
||||
Slots = GetSlots_GS(f);
|
||||
if (Version.Contains(GameVersion.C))
|
||||
|
@ -265,6 +265,7 @@ namespace PKHeX.Core
|
|||
new EncounterTrade { Species = 021, Level = 10, TID = 01001, Moves = new[] {64,45,43} }, // Spearow @ Goldenrod City for free
|
||||
new EncounterTrade { Species = 213, Level = 15, TID = 00518 }, // Shuckle @ Cianwood City for free
|
||||
};
|
||||
|
||||
internal static readonly string[][] TradeGift_GSC_OTs =
|
||||
{
|
||||
new string[0], // 0 - None
|
||||
|
|
|
@ -92,8 +92,10 @@ namespace PKHeX.Core
|
|||
private static void MarkG3SlotsSafariZones(ref EncounterArea[] Areas, int location)
|
||||
{
|
||||
foreach (EncounterArea Area in Areas.Where(a => a.Location == location))
|
||||
foreach (EncounterSlot Slot in Area.Slots)
|
||||
Slot.Type |= SlotType.Safari;
|
||||
{
|
||||
foreach (EncounterSlot Slot in Area.Slots)
|
||||
Slot.Type |= SlotType.Safari;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly int[] Roaming_MetLocation_FRLG =
|
||||
|
@ -113,6 +115,7 @@ namespace PKHeX.Core
|
|||
36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
|
||||
46, 47, 48, 49,
|
||||
};
|
||||
|
||||
private static readonly EncounterStatic[] Encounter_RSE_Roam =
|
||||
{
|
||||
new EncounterStatic { Species = 380, Level = 40, Version = GameVersion.S, Roaming = true }, // Latias
|
||||
|
@ -120,6 +123,7 @@ namespace PKHeX.Core
|
|||
new EncounterStatic { Species = 381, Level = 40, Version = GameVersion.R, Roaming = true }, // Latios
|
||||
new EncounterStatic { Species = 381, Level = 40, Version = GameVersion.E, Roaming = true }, // Latios
|
||||
};
|
||||
|
||||
private static readonly EncounterStatic[] Encounter_RSE_Regular =
|
||||
{
|
||||
// Starters
|
||||
|
@ -173,6 +177,7 @@ namespace PKHeX.Core
|
|||
new EncounterStatic { Species = 244, Level = 50, Roaming = true, }, // Entei
|
||||
new EncounterStatic { Species = 245, Level = 50, Roaming = true, }, // Suicune
|
||||
};
|
||||
|
||||
private static readonly EncounterStatic[] Encounter_FRLG_Stationary =
|
||||
{
|
||||
// Starters @ Pallet Town
|
||||
|
@ -233,6 +238,7 @@ namespace PKHeX.Core
|
|||
private static readonly int[] TradeContest_Cute = { 05, 05, 30, 05, 05, 10 };
|
||||
private static readonly int[] TradeContest_Clever = { 05, 05, 05, 30, 05, 10 };
|
||||
private static readonly int[] TradeContest_Tough = { 05, 05, 05, 05, 30, 10 };
|
||||
|
||||
internal static readonly EncounterTrade[] TradeGift_RSE =
|
||||
{
|
||||
new EncounterTradePID { Species = 296, Ability = 2, TID = 49562, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {5,5,4,4,4,4}, Level = 05, PID = 0x00009C40, Contest = TradeContest_Tough, Version = GameVersion.RS, }, // Slakoth (Level 5 Breeding) -> Makuhita
|
||||
|
@ -244,6 +250,7 @@ namespace PKHeX.Core
|
|||
new EncounterTradePID { Species = 052, Ability = 1, TID = 25945, SID = 00001, OTGender = 1, Gender = 0, IVs = new[] {4,5,4,5,4,4}, Level = 03, PID = 0x0000008B, Contest = TradeContest_Clever, Version = GameVersion.E, }, // Skitty (Level 3 Trade)-> Meowth*
|
||||
// If Pokémon with * is evolved in a Generation IV or V game, its Ability will become its second Ability.
|
||||
};
|
||||
|
||||
internal static readonly EncounterTrade[] TradeGift_FRLG =
|
||||
{
|
||||
new EncounterTradePID { Species = 122, Ability = 1, TID = 01985, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {20,15,17,24,23,22}, PID = 0x00009CAE, Contest = TradeContest_Clever, }, // Mr. Mime
|
||||
|
@ -259,6 +266,7 @@ namespace PKHeX.Core
|
|||
new EncounterTradePID { Species = 086, Ability = 1, TID = 09853, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {24,15,22,16,23,22}, PID = 0x482CAC89, Contest = TradeContest_Tough, }, // Seel *
|
||||
// If Pokémon with * is evolved in a Generation IV or V game, its Ability will become its second Ability.
|
||||
};
|
||||
|
||||
internal static readonly string[][] TradeRSE =
|
||||
{
|
||||
new string[0], // 0 - None
|
||||
|
@ -270,6 +278,7 @@ namespace PKHeX.Core
|
|||
new string[0], // 6 - None
|
||||
Util.GetStringList("traderse", "es"), // 7
|
||||
};
|
||||
|
||||
internal static readonly string[][] TradeFRLG =
|
||||
{
|
||||
new string[0], // 0 - None
|
||||
|
@ -331,6 +340,7 @@ namespace PKHeX.Core
|
|||
new EncounterSlot { Species = 349, LevelMin = 20, LevelMax = 25, Type = SlotType.Swarm } // Feebas with any Rod (50%)
|
||||
},},
|
||||
};
|
||||
|
||||
private static readonly EncounterArea[] SlotsFRLGUnown =
|
||||
{
|
||||
GetUnownArea(188, new[] { 00,00,00,00,00,00,00,00,00,00,00,26 }), // 188 = Monean Chamber
|
||||
|
@ -341,6 +351,7 @@ namespace PKHeX.Core
|
|||
GetUnownArea(193, new[] { 21,21,21,22,22,22,23,23,12,12,01,01 }), // 193 = Rixy Chamber
|
||||
GetUnownArea(194, new[] { 25,25,25,25,25,25,25,25,25,25,25,27 }), // 194 = Viapois Chamber
|
||||
};
|
||||
|
||||
private static EncounterArea GetUnownArea(int location, IReadOnlyList<int> SlotForms)
|
||||
{
|
||||
return new EncounterArea
|
||||
|
@ -612,7 +623,9 @@ namespace PKHeX.Core
|
|||
}
|
||||
},
|
||||
};
|
||||
|
||||
internal static readonly EncounterStatic[] Encounter_CXD = ConcatAll(Encounter_Colo, Encounter_XD);
|
||||
|
||||
private static IEnumerable<EncounterStatic> CloneMirorB(EncounterStatic arg)
|
||||
{
|
||||
yield return arg;
|
||||
|
|
|
@ -150,7 +150,7 @@ namespace PKHeX.Core
|
|||
MarkHGSSEncounterTypeSlots_MultipleTypes(SS_Slots, Cianwood, EncounterType.RockSmash);
|
||||
}
|
||||
|
||||
private static void MarkG4PokeWalker(EncounterStatic[] t)
|
||||
private static void MarkG4PokeWalker(IEnumerable<EncounterStatic> t)
|
||||
{
|
||||
foreach (EncounterStatic s in t)
|
||||
{
|
||||
|
@ -159,13 +159,17 @@ namespace PKHeX.Core
|
|||
s.Version = GameVersion.HGSS;
|
||||
}
|
||||
}
|
||||
private static void MarkG4SlotsGreatMarsh(EncounterArea[] Areas, int location)
|
||||
|
||||
private static void MarkG4SlotsGreatMarsh(IEnumerable<EncounterArea> Areas, int location)
|
||||
{
|
||||
foreach (EncounterArea Area in Areas.Where(a => a.Location == location))
|
||||
foreach (EncounterSlot Slot in Area.Slots)
|
||||
Slot.Type |= SlotType.Safari;
|
||||
{
|
||||
foreach (EncounterSlot Slot in Area.Slots)
|
||||
Slot.Type |= SlotType.Safari;
|
||||
}
|
||||
}
|
||||
private static void MarkG4SwarmSlots(EncounterArea[] Areas, EncounterArea[] SwarmAreas)
|
||||
|
||||
private static void MarkG4SwarmSlots(IEnumerable<EncounterArea> Areas, EncounterArea[] SwarmAreas)
|
||||
{
|
||||
// Grass Swarm slots replace slots 0 and 1 from encounters data
|
||||
// for surfing only replace slots 0 from encounters data
|
||||
|
@ -192,14 +196,18 @@ namespace PKHeX.Core
|
|||
Area.Slots = Area.Slots.Concat(OutputSlots).Where(a => a.Species > 0).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
// Gen 4 raw encounter data does not contains info for alt slots
|
||||
// Shellos and Gastrodom East Sea form should be modified
|
||||
private static void MarkG4AltFormSlots(EncounterArea[] Areas, int Species, int form, int[] Locations)
|
||||
private static void MarkG4AltFormSlots(IEnumerable<EncounterArea> Areas, int Species, int form, int[] Locations)
|
||||
{
|
||||
foreach (EncounterArea Area in Areas.Where(a => Locations.Contains(a.Location)))
|
||||
foreach (EncounterSlot Slot in Area.Slots.Where(s => s.Species == Species))
|
||||
Slot.Form = form;
|
||||
{
|
||||
foreach (EncounterSlot Slot in Area.Slots.Where(s => s.Species == Species))
|
||||
Slot.Form = form;
|
||||
}
|
||||
}
|
||||
|
||||
private static EncounterType GetEncounterTypeBySlotDPPt(SlotType Type, EncounterType GrassType)
|
||||
{
|
||||
switch (Type)
|
||||
|
@ -221,6 +229,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return EncounterType.None;
|
||||
}
|
||||
|
||||
private static EncounterType GetEncounterTypeBySlotHGSS(SlotType Type, EncounterType GrassType, EncounterType HeadbuttType)
|
||||
{
|
||||
switch (Type)
|
||||
|
@ -254,6 +263,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return EncounterType.None;
|
||||
}
|
||||
|
||||
private static void MarkDPPtEncounterTypeSlots_MultipleTypes(EncounterArea[] Areas, int Location, EncounterType NormalEncounterType, params int[] SpecialEncounterFiles)
|
||||
{
|
||||
var numfile = 0;
|
||||
|
@ -267,6 +277,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void MarkHGSSEncounterTypeSlots_MultipleTypes(EncounterArea[] Areas, int Location, EncounterType NormalEncounterType, params int[] SpecialEncounterFile)
|
||||
{
|
||||
// Area with two different encounter type for grass encounters
|
||||
|
@ -283,6 +294,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void MarkDPPtEncounterTypeSlots(EncounterArea[] Areas)
|
||||
{
|
||||
foreach (EncounterArea Area in Areas)
|
||||
|
@ -299,6 +311,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static EncounterType GetHeadbuttEncounterType(int Location)
|
||||
{
|
||||
if (Location == 195 || Location == 196) // Route 47/48
|
||||
|
@ -306,24 +319,32 @@ namespace PKHeX.Core
|
|||
|
||||
// Routes with trees adjacent to water tiles
|
||||
var allowsurf = HGSS_SurfingHeadbutt_Locations.Contains(Location);
|
||||
|
||||
// Cities
|
||||
if (HGSS_CityLocations.Contains(Location))
|
||||
{
|
||||
return allowsurf
|
||||
? EncounterType.Building_EnigmaStone | EncounterType.Surfing_Fishing
|
||||
: EncounterType.Building_EnigmaStone;
|
||||
}
|
||||
|
||||
// Caves with no exterior zones
|
||||
if (!HGSS_MixInteriorExteriorLocations.Contains(Location) && HGSS_CaveLocations.Contains(Location))
|
||||
{
|
||||
return allowsurf
|
||||
? EncounterType.Cave_HallOfOrigin | EncounterType.Surfing_Fishing
|
||||
: EncounterType.Cave_HallOfOrigin;
|
||||
}
|
||||
|
||||
// Routes and exterior areas
|
||||
// Routes with trees adjacent to grass tiles
|
||||
var allowgrass = HGSS_GrassHeadbutt_Locations.Contains(Location);
|
||||
if (allowgrass)
|
||||
{
|
||||
return allowsurf
|
||||
? EncounterType.TallGrass | EncounterType.Surfing_Fishing
|
||||
: EncounterType.TallGrass;
|
||||
}
|
||||
|
||||
return allowsurf
|
||||
? EncounterType.Surfing_Fishing
|
||||
|
@ -364,12 +385,14 @@ namespace PKHeX.Core
|
|||
69, // Iron Island
|
||||
84, // Stark Mountain
|
||||
};
|
||||
|
||||
private static readonly HashSet<int> DPPt_MixInteriorExteriorLocations = new HashSet<int>
|
||||
{
|
||||
24, // Route 209 (Lost Tower)
|
||||
50, // Mt Coronet
|
||||
84, // Stark Mountain
|
||||
};
|
||||
|
||||
private static readonly int[] DPPt_MtCoronetExteriorEncounters =
|
||||
{
|
||||
4, 5, 70
|
||||
|
@ -461,6 +484,7 @@ namespace PKHeX.Core
|
|||
192, // Route 44
|
||||
214, // Ilex Forest
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Locations with headbutt trees accessible from tall grass tiles
|
||||
/// </summary>
|
||||
|
@ -502,15 +526,18 @@ namespace PKHeX.Core
|
|||
219, // Mt. Silver Cave
|
||||
224, // Viridian Forest
|
||||
};
|
||||
|
||||
private static readonly int[] HGSS_MtSilverCaveExteriorEncounters =
|
||||
{
|
||||
2, 3
|
||||
};
|
||||
|
||||
private static readonly int[] HGSS_MixInteriorExteriorLocations =
|
||||
{
|
||||
209, // Ruins of Alph
|
||||
219, // Mt. Silver Cave
|
||||
};
|
||||
|
||||
#endregion
|
||||
#region Pokéwalker Encounter
|
||||
// all pkm are in Poke Ball and have a met location of "PokeWalker"
|
||||
|
@ -694,6 +721,7 @@ namespace PKHeX.Core
|
|||
47, // Valley Windworks
|
||||
49, // Fuego Ironworks
|
||||
};
|
||||
|
||||
private static readonly int[] Roaming_MetLocation_DPPt_Surf =
|
||||
{
|
||||
// Routes 203-205, 208-210, 212-214, 218-222 can be encountered in water
|
||||
|
@ -702,6 +730,7 @@ namespace PKHeX.Core
|
|||
47, // Valley Windworks
|
||||
49, // Fuego Ironworks
|
||||
};
|
||||
|
||||
private static readonly EncounterStaticTyped[] Encounter_DPPt_Roam_Grass =
|
||||
{
|
||||
new EncounterStaticTyped { Species = 481, Level = 50, Roaming = true, TypeEncounter = EncounterType.TallGrass }, // Mesprit
|
||||
|
@ -710,6 +739,7 @@ namespace PKHeX.Core
|
|||
new EncounterStaticTyped { Species = 145, Level = 60, Roaming = true, TypeEncounter = EncounterType.TallGrass, Version = GameVersion.Pt }, // Zapdos
|
||||
new EncounterStaticTyped { Species = 146, Level = 60, Roaming = true, TypeEncounter = EncounterType.TallGrass, Version = GameVersion.Pt }, // Moltres
|
||||
};
|
||||
|
||||
private static readonly EncounterStaticTyped[] Encounter_DPPt_Roam_Surf =
|
||||
{
|
||||
new EncounterStaticTyped { Species = 481, Level = 50, Roaming = true, TypeEncounter = EncounterType.Surfing_Fishing }, // Mesprit
|
||||
|
@ -718,6 +748,7 @@ namespace PKHeX.Core
|
|||
new EncounterStaticTyped { Species = 145, Level = 60, Roaming = true, TypeEncounter = EncounterType.Surfing_Fishing, Version = GameVersion.Pt }, // Zapdos
|
||||
new EncounterStaticTyped { Species = 146, Level = 60, Roaming = true, TypeEncounter = EncounterType.Surfing_Fishing, Version = GameVersion.Pt }, // Moltres
|
||||
};
|
||||
|
||||
private static readonly EncounterStatic[] Encounter_DPPt_Regular =
|
||||
{
|
||||
//Starters
|
||||
|
@ -778,6 +809,7 @@ namespace PKHeX.Core
|
|||
new EncounterStatic { Species = 492, Form = 0, Level = 30, Location = 063, Fateful = true }, //Shaymin @ Flower Paradise (Unreleased in Diamond and Pearl)
|
||||
new EncounterStaticTyped { Species = 493, Form = 0, Level = 80, Location = 086, TypeEncounter = EncounterType.Cave_HallOfOrigin }, //Arceus @ Hall of Origin (Unreleased)
|
||||
};
|
||||
|
||||
private static readonly EncounterStatic[] Encounter_DPPt = Encounter_DPPt_Roam_Grass.SelectMany(e => e.Clone(Roaming_MetLocation_DPPt_Grass)).Concat(
|
||||
Encounter_DPPt_Roam_Surf.SelectMany(e => e.Clone(Roaming_MetLocation_DPPt_Surf))).Concat(
|
||||
Encounter_DPPt_Regular).ToArray();
|
||||
|
@ -792,22 +824,26 @@ namespace PKHeX.Core
|
|||
177,178,179,180,181,182,183,184,185,186,
|
||||
187, 190,191,192,193,194,
|
||||
};
|
||||
|
||||
private static readonly int[] Roaming_MetLocation_HGSS_Johto_Surf =
|
||||
{
|
||||
// Routes 30-32,34-35,40-45 and 47 can be encountered in water
|
||||
// Won't go to routes 40,41,47,48
|
||||
178,179,180,182,183,190,191,192,193
|
||||
};
|
||||
|
||||
private static readonly EncounterStaticTyped[] Encounter_HGSS_JohtoRoam_Grass =
|
||||
{
|
||||
new EncounterStaticTyped { Species = 243, Level = 40, Roaming = true, TypeEncounter = EncounterType.TallGrass, }, // Raikou
|
||||
new EncounterStaticTyped { Species = 244, Level = 40, Roaming = true, TypeEncounter = EncounterType.TallGrass, }, // Entei
|
||||
};
|
||||
|
||||
private static readonly EncounterStaticTyped[] Encounter_HGSS_JohtoRoam_Surf =
|
||||
{
|
||||
new EncounterStaticTyped { Species = 243, Level = 40, Roaming = true, TypeEncounter = EncounterType.Surfing_Fishing, }, // Raikou
|
||||
new EncounterStaticTyped { Species = 244, Level = 40, Roaming = true, TypeEncounter = EncounterType.Surfing_Fishing, }, // Entei
|
||||
};
|
||||
|
||||
private static readonly int[] Roaming_MetLocation_HGSS_Kanto_Grass =
|
||||
{
|
||||
// Route 01-18,21,22,24,26 and 28 can be encountered in grass
|
||||
|
@ -816,6 +852,7 @@ namespace PKHeX.Core
|
|||
159,160,161,162,163,164,165,166,
|
||||
169,170, 172, 174, 176,
|
||||
};
|
||||
|
||||
private static readonly int[] Roaming_MetLocation_HGSS_Kanto_Surf =
|
||||
{
|
||||
// Route 4,6,9,10,12,13,19-22,24,26 and 28 can be encountered in water
|
||||
|
@ -823,16 +860,19 @@ namespace PKHeX.Core
|
|||
152,154,157,158,160,161,167,168,169,170,
|
||||
172,174,176,
|
||||
};
|
||||
|
||||
private static readonly EncounterStaticTyped[] Encounter_HGSS_KantoRoam_Grass =
|
||||
{
|
||||
new EncounterStaticTyped { Species = 380, Level = 35, Version = GameVersion.HG, Roaming = true, TypeEncounter = EncounterType.TallGrass, }, //Latias
|
||||
new EncounterStaticTyped { Species = 381, Level = 35, Version = GameVersion.SS, Roaming = true, TypeEncounter = EncounterType.TallGrass, }, //Latios
|
||||
};
|
||||
|
||||
private static readonly EncounterStaticTyped[] Encounter_HGSS_KantoRoam_Surf =
|
||||
{
|
||||
new EncounterStaticTyped { Species = 380, Level = 35, Version = GameVersion.HG, Roaming = true, TypeEncounter = EncounterType.Surfing_Fishing, }, //Latias
|
||||
new EncounterStaticTyped { Species = 381, Level = 35, Version = GameVersion.SS, Roaming = true, TypeEncounter = EncounterType.Surfing_Fishing, }, //Latios
|
||||
};
|
||||
|
||||
internal static readonly EncounterStatic SpikyEaredPichu = new EncounterStaticTyped // Spiky-Eared Pichu @ Ilex Forest
|
||||
{
|
||||
Species = 172,
|
||||
|
@ -845,6 +885,7 @@ namespace PKHeX.Core
|
|||
TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio,
|
||||
Shiny = Shiny.Never
|
||||
};
|
||||
|
||||
private static readonly EncounterStatic[] Encounter_HGSS_Regular =
|
||||
{
|
||||
//Starters
|
||||
|
@ -915,6 +956,7 @@ namespace PKHeX.Core
|
|||
new EncounterStaticTyped { Species = 484, Level = 01, Location = 231, Gift = true, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio }, //Palkia @ Sinjoh Ruins
|
||||
new EncounterStaticTyped { Species = 487, Level = 01, Location = 231, Gift = true, TypeEncounter = EncounterType.Starter_Fossil_Gift_Pt_DPTrio, Form = 1, HeldItem = 112 }, //Giratina @ Sinjoh Ruins
|
||||
};
|
||||
|
||||
private static readonly EncounterStatic[] Encounter_HGSS = ConcatAll(
|
||||
Encounter_HGSS_KantoRoam_Grass.SelectMany(e => e.Clone(Roaming_MetLocation_HGSS_Kanto_Grass)),
|
||||
Encounter_HGSS_KantoRoam_Surf.SelectMany(e => e.Clone(Roaming_MetLocation_HGSS_Kanto_Surf)),
|
||||
|
@ -924,6 +966,7 @@ namespace PKHeX.Core
|
|||
#endregion
|
||||
#region Trade Tables
|
||||
internal static readonly string[] RanchOTNames = { null, "ユカリ", "Hayley", "EULALIE", "GIULIA", "EUKALIA", null, "Eulalia" };
|
||||
|
||||
private static readonly EncounterTrade[] RanchGifts =
|
||||
{
|
||||
new EncounterTradePID { Species = 025, Level = 18, Moves = new[] {447,085,148,104}, TID = 1000, SID = 19840, OTGender = 1, Version = GameVersion.D, Location = 0068, Gender = 0, Ability = 1, PID = 323975838, CurrentLevel = 20, }, // Pikachu
|
||||
|
@ -949,6 +992,7 @@ namespace PKHeX.Core
|
|||
new EncounterTradePID { Species = 459, Level = 32, Moves = new[] {452,420,275,059}, TID = 1000, SID = 23360, OTGender = 1, Version = GameVersion.D, Location = 0031, Gender = 0, Ability = 1, PID = 323975582, CurrentLevel = 41, }, // Snover
|
||||
new EncounterTrade { Species = 489, Level = 01, Moves = new[] {447,240,156,057}, TID = 1000, SID = 09248, OTGender = 1, Version = GameVersion.D, Location = 3000, Gender = 2, Fateful = true, CurrentLevel = 50, Ball = 0x10, EggLocation = 3000, }, // Phione
|
||||
};
|
||||
|
||||
internal static readonly EncounterTrade[] TradeGift_DPPt = new[]
|
||||
{
|
||||
new EncounterTradePID { Species = 063, Ability = 1, TID = 25643, SID = 00000, OTGender = 1, Gender = 0, IVs = new[] {15,15,15,20,25,25}, PID = 0x0000008E }, // Abra
|
||||
|
@ -956,6 +1000,7 @@ namespace PKHeX.Core
|
|||
new EncounterTradePID { Species = 093, Ability = 1, TID = 19248, SID = 00000, OTGender = 1, Gender = 0, IVs = new[] {20,25,15,25,15,15}, PID = 0x00000088 }, // Haunter
|
||||
new EncounterTradePID { Species = 129, Ability = 1, TID = 53277, SID = 00000, OTGender = 0, Gender = 1, IVs = new[] {15,25,15,20,25,15}, PID = 0x0000045C }, // Magikarp
|
||||
}.Concat(RanchGifts).ToArray();
|
||||
|
||||
internal static readonly EncounterTrade[] TradeGift_HGSS =
|
||||
{
|
||||
new EncounterTradePID { Species = 095, Ability = 2, TID = 48926, SID = 00000, OTGender = 0, Gender = 0, IVs = new[] {25,20,25,15,15,15}, PID = 0x000025EF }, // Onix
|
||||
|
@ -972,6 +1017,7 @@ namespace PKHeX.Core
|
|||
new EncounterTradePID { Species = 021, Ability = 1, TID = 01001, SID = 00000, OTGender = 0, Gender = 1, IVs = new[] {15,20,15,20,20,20}, PID = 0x00006B5E, Level = 20, Location = 183, Moves = new[]{043,031,228,332} },// Webster's Spearow
|
||||
new EncounterTradePID { Species = 213, Ability = 2, TID = 04336, SID = 00001, OTGender = 0, Gender = 0, IVs = new[] {15,20,15,20,20,20}, PID = 0x000214D7, Level = 20, Location = 130, Moves = new[]{132,117,227,219} },// Kirk's Shuckle
|
||||
};
|
||||
|
||||
internal static readonly string[][] TradeDPPt =
|
||||
{
|
||||
new string[0], // 0 - None
|
||||
|
@ -984,6 +1030,7 @@ namespace PKHeX.Core
|
|||
Util.GetStringList("tradedppt", "es"), // 7
|
||||
Util.GetStringList("tradedppt", "ko"), // 8
|
||||
};
|
||||
|
||||
internal static readonly string[][] TradeHGSS =
|
||||
{
|
||||
new string[0], // 0 - None
|
||||
|
@ -1012,6 +1059,7 @@ namespace PKHeX.Core
|
|||
Slots = new int[25].Select((_, i) => new EncounterSlot { Species = 201, LevelMin = 14, LevelMax = 30, Type = SlotType.Grass, Form = i+1 }).ToArray() // B->?, Unown A is loaded from encounters raw file
|
||||
},
|
||||
};
|
||||
|
||||
private static readonly EncounterArea SlotsHGSS_BCC =
|
||||
|
||||
new EncounterArea
|
||||
|
@ -1100,6 +1148,7 @@ namespace PKHeX.Core
|
|||
new EncounterSlot { Species = 449, LevelMin = 43, LevelMax = 43, Type = SlotType.Grass_Safari }, // Hippopotas
|
||||
new EncounterSlot { Species = 455, LevelMin = 48, LevelMax = 48, Type = SlotType.Grass_Safari }, // Carnivine
|
||||
};
|
||||
|
||||
private static readonly EncounterSlot[] SAFARIZONE_PLAINS =
|
||||
{
|
||||
new EncounterSlot { Species = 019, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Rattata
|
||||
|
@ -1160,6 +1209,7 @@ namespace PKHeX.Core
|
|||
new EncounterSlot { Species = 299, LevelMin = 45, LevelMax = 45, Type = SlotType.Grass_Safari }, // Nosepass
|
||||
new EncounterSlot { Species = 447, LevelMin = 45, LevelMax = 46, Type = SlotType.Grass_Safari }, // Riolu
|
||||
};
|
||||
|
||||
private static readonly EncounterSlot[] SAFARIZONE_FOREST =
|
||||
{
|
||||
new EncounterSlot { Species = 016, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Pidgey
|
||||
|
@ -1179,6 +1229,7 @@ namespace PKHeX.Core
|
|||
new EncounterSlot { Species = 406, LevelMin = 47, LevelMax = 47, Type = SlotType.Grass_Safari }, // Budew
|
||||
new EncounterSlot { Species = 437, LevelMin = 44, LevelMax = 45, Type = SlotType.Grass_Safari }, // Bronzong
|
||||
};
|
||||
|
||||
private static readonly EncounterSlot[] SAFARIZONE_SWAMP =
|
||||
{
|
||||
new EncounterSlot { Species = 039, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Jigglypuff
|
||||
|
@ -1257,6 +1308,7 @@ namespace PKHeX.Core
|
|||
new EncounterSlot { Species = 453, LevelMin = 44, LevelMax = 44, Type = SlotType.Grass_Safari }, // Croagunk
|
||||
new EncounterSlot { Species = 455, LevelMin = 41, LevelMax = 41, Type = SlotType.Grass_Safari }, // Carnivine
|
||||
};
|
||||
|
||||
private static readonly EncounterSlot[] SAFARIZONE_MOUNTAIN =
|
||||
{
|
||||
new EncounterSlot { Species = 019, LevelMin = 15, LevelMax = 16, Type = SlotType.Grass_Safari }, // Rattata
|
||||
|
@ -1277,6 +1329,7 @@ namespace PKHeX.Core
|
|||
new EncounterSlot { Species = 375, LevelMin = 44, LevelMax = 44, Type = SlotType.Grass_Safari }, // Metang
|
||||
new EncounterSlot { Species = 433, LevelMin = 38, LevelMax = 38, Type = SlotType.Grass_Safari }, // Chingling
|
||||
};
|
||||
|
||||
private static readonly EncounterSlot[] SAFARIZONE_ROCKYBEACH =
|
||||
{
|
||||
new EncounterSlot { Species = 041, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Zubat
|
||||
|
@ -1316,6 +1369,7 @@ namespace PKHeX.Core
|
|||
new EncounterSlot { Species = 406, LevelMin = 40, LevelMax = 40, Type = SlotType.Grass_Safari }, // Budew
|
||||
new EncounterSlot { Species = 443, LevelMin = 44, LevelMax = 44, Type = SlotType.Grass_Safari }, // Gible
|
||||
};
|
||||
|
||||
private static readonly EncounterSlot[] SAFARIZONE_WASTELAND =
|
||||
{
|
||||
new EncounterSlot { Species = 022, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Fearow
|
||||
|
@ -1335,6 +1389,7 @@ namespace PKHeX.Core
|
|||
new EncounterSlot { Species = 338, LevelMin = 45, LevelMax = 46, Type = SlotType.Grass_Safari }, // Solrock
|
||||
new EncounterSlot { Species = 451, LevelMin = 44, LevelMax = 45, Type = SlotType.Grass_Safari }, // Skorupi
|
||||
};
|
||||
|
||||
private static readonly EncounterSlot[] SAFARIZONE_SAVANNAH =
|
||||
{
|
||||
new EncounterSlot { Species = 029, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Nidoran♀
|
||||
|
@ -1356,6 +1411,7 @@ namespace PKHeX.Core
|
|||
new EncounterSlot { Species = 332, LevelMin = 42, LevelMax = 42, Type = SlotType.Grass_Safari }, // Cacturne
|
||||
new EncounterSlot { Species = 404, LevelMin = 45, LevelMax = 46, Type = SlotType.Grass_Safari }, // Luxio
|
||||
};
|
||||
|
||||
private static readonly EncounterSlot[] SAFARIZONE_WETLAND =
|
||||
{
|
||||
new EncounterSlot { Species = 021, LevelMin = 15, LevelMax = 17, Type = SlotType.Grass_Safari }, // Spearow
|
||||
|
@ -1415,6 +1471,7 @@ namespace PKHeX.Core
|
|||
SAFARIZONE_SAVANNAH,
|
||||
SAFARIZONE_WETLAND)
|
||||
};
|
||||
|
||||
private static readonly EncounterArea[] SlotsHGSSAlt =
|
||||
{
|
||||
SlotsHGSS_BCC,
|
||||
|
@ -1471,6 +1528,7 @@ namespace PKHeX.Core
|
|||
183,194,195,298,399,400, // Pre-National Pokédex
|
||||
046,102,115,193,285,316,452,454 // Post-National Pokédex
|
||||
};
|
||||
|
||||
private static readonly EncounterArea[] DP_GreatMarshAlt = EncounterArea.GetSimpleEncounterArea(DP_GreatMarshAlt_Species, new[] { 22, 22, 24, 24, 26, 26 }, 52, SlotType.Grass_Safari);
|
||||
|
||||
private static readonly int[] Pt_GreatMarshAlt_Species =
|
||||
|
@ -1479,6 +1537,7 @@ namespace PKHeX.Core
|
|||
194, // Pre-National Pokédex
|
||||
046,102,115,285,316,352,452,454 // Post-National Pokédex
|
||||
};
|
||||
|
||||
private static readonly EncounterArea[] Pt_GreatMarshAlt = EncounterArea.GetSimpleEncounterArea(Pt_GreatMarshAlt_Species, new[] { 27, 30 }, 52, SlotType.Grass_Safari);
|
||||
|
||||
private static readonly int[] Shellos_EastSeaLocation_DP =
|
||||
|
@ -1556,10 +1615,12 @@ namespace PKHeX.Core
|
|||
new EncounterArea {Location = 220, Slots = new[]{new EncounterSlot {Species = 206, Type = SlotType.Grass },},}, // Dunsparce @ Dark Cave
|
||||
new EncounterArea {Location = 224, Slots = new[]{new EncounterSlot {Species = 401, Type = SlotType.Grass },},}, // Kricketot @ Viridian Forest
|
||||
};
|
||||
|
||||
private static readonly EncounterArea[] SlotsHG_Swarm = SlotsHGSS_Swarm.Concat(new[] {
|
||||
new EncounterArea {Location = 151, Slots = new[]{new EncounterSlot {Species = 343, Type = SlotType.Grass },},}, // Baltoy @ Route 3
|
||||
new EncounterArea {Location = 157, Slots = new[]{new EncounterSlot {Species = 302, Type = SlotType.Grass },},}, // Sableye @ Route 9
|
||||
}).ToArray();
|
||||
|
||||
private static readonly EncounterArea[] SlotsSS_Swarm = SlotsHGSS_Swarm.Concat(new[] {
|
||||
new EncounterArea {Location = 151, Slots = new[]{new EncounterSlot {Species = 316, Type = SlotType.Grass },},}, // Gulpin @ Route 3
|
||||
new EncounterArea {Location = 157, Slots = new[]{new EncounterSlot {Species = 303, Type = SlotType.Grass },},}, // Mawile @ Route 9
|
||||
|
|
|
@ -71,6 +71,7 @@ namespace PKHeX.Core
|
|||
area.Slots = Legal.FriendSafari.Select(FriendSafariSlot).ToArray();
|
||||
return area.Slots.ToLookup(s => s.Species);
|
||||
}
|
||||
|
||||
private static void MarkG6XYSlots(ref EncounterArea[] Areas)
|
||||
{
|
||||
foreach (var area in Areas)
|
||||
|
@ -81,6 +82,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
ReduceAreasSize(ref Areas);
|
||||
}
|
||||
|
||||
private static void MarkG6AOSlots(ref EncounterArea[] Areas)
|
||||
{
|
||||
foreach (var area in Areas)
|
||||
|
@ -109,6 +111,7 @@ namespace PKHeX.Core
|
|||
Util.GetStringList("tradexy", "es"), // 7
|
||||
Util.GetStringList("tradexy", "ko"), // 8
|
||||
};
|
||||
|
||||
internal static readonly string[][] TradeAO =
|
||||
{
|
||||
new string[0], // 0 - None
|
||||
|
@ -247,6 +250,7 @@ namespace PKHeX.Core
|
|||
new EncounterStatic { Species = 145, Level = 70, Location = 146, Ability = 1, Shiny = Shiny.Never, IV3 = true }, // Zapdos
|
||||
new EncounterStatic { Species = 146, Level = 70, Location = 146, Ability = 1, Shiny = Shiny.Never, IV3 = true }, // Moltres
|
||||
};
|
||||
|
||||
private static readonly EncounterStatic[] Encounter_AO_Regular =
|
||||
{
|
||||
new EncounterStatic { Gift = true, Species = 252, Level = 5, Location = 204, }, // Treeko
|
||||
|
@ -352,7 +356,9 @@ namespace PKHeX.Core
|
|||
new EncounterStatic { Species = 425, Level = 45, Location = 348 }, // Drifloon
|
||||
new EncounterStatic { Species = 628, Level = 45, Location = 348 }, // Braviary
|
||||
};
|
||||
|
||||
private static readonly EncounterStatic[] Encounter_AO = ConcatAll(Encounter_AO_Regular, PermuteCosplayPikachu().ToArray());
|
||||
|
||||
private static IEnumerable<EncounterStatic> PermuteCosplayPikachu()
|
||||
{
|
||||
var CosplayPikachu = new EncounterStatic
|
||||
|
@ -361,8 +367,13 @@ namespace PKHeX.Core
|
|||
Contest = new[] { 70, 70, 70, 70, 70, 0 }, Gift = true, Shiny = Shiny.Never
|
||||
};
|
||||
foreach (int loc in new[] { 178, 180, 186, 194 })
|
||||
for (int f = 1; f <= 6; f++)
|
||||
{ var pk = CosplayPikachu.Clone(loc); pk.Form = f; yield return pk; }
|
||||
{
|
||||
for (int f = 1; f <= 6; f++)
|
||||
{
|
||||
var pk = CosplayPikachu.Clone(loc); pk.Form = f;
|
||||
yield return pk;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region Trade Tables
|
||||
|
@ -381,6 +392,7 @@ namespace PKHeX.Core
|
|||
|
||||
new EncounterTrade { Species = 280, Level = 5, Ability = 1, Gender = 1, TID = 37110, Nature = Nature.Modest, IVs = new[] {20, 20, 20, 31, 31, 20}, IsNicknamed = false, }, // Ralts
|
||||
};
|
||||
|
||||
internal static readonly EncounterTrade[] TradeGift_AO =
|
||||
{
|
||||
new EncounterTrade { Species = 296, Level = 9, Ability = 2, Gender = 0, TID = 30724, Nature = Nature.Brave, IVs = new[] {-1, 31, -1, -1, -1, -1}, }, // Makuhita
|
||||
|
|
|
@ -60,10 +60,12 @@ namespace PKHeX.Core
|
|||
TradeGift_SM.SetVersion(GameVersion.SM);
|
||||
TradeGift_USUM.SetVersion(GameVersion.USUM);
|
||||
}
|
||||
|
||||
private static void MarkG7REGSlots(ref EncounterArea[] Areas)
|
||||
{
|
||||
ReduceAreasSize(ref Areas);
|
||||
}
|
||||
|
||||
private static void MarkG7SMSlots(ref EncounterArea[] Areas)
|
||||
{
|
||||
foreach (EncounterSlot s in Areas.SelectMany(area => area.Slots))
|
||||
|
@ -173,6 +175,7 @@ namespace PKHeX.Core
|
|||
new EncounterStatic { Species = 787, Level = 60, Shiny = Shiny.Never, Ability = 1, Location = 140, IV3 = true, }, // Tapu Bulu
|
||||
new EncounterStatic { Species = 788, Level = 60, Shiny = Shiny.Never, Ability = 1, Location = 180, IV3 = true, }, // Tapu Fini
|
||||
};
|
||||
|
||||
internal static readonly EncounterTrade[] TradeGift_SM = // @ a\1\5\5
|
||||
{
|
||||
// Trades - 4.bin
|
||||
|
@ -184,6 +187,7 @@ namespace PKHeX.Core
|
|||
new EncounterTrade { Species = 762, Form = 0, Level = 43, Ability = 1, TID = 20679, SID = 00009, IVs = new[] {-1,-1,-1,-1,-1,31}, OTGender = 1, Gender = 1, Nature = Nature.Careful, }, // Steenee
|
||||
new EncounterTrade { Species = 663, Form = 0, Level = 59, Ability = 4, TID = 56734, SID = 00008, IVs = new[] {-1,-1,-1,31,-1,-1}, OTGender = 0, Gender = 0, Nature = Nature.Jolly, }, // Talonflame
|
||||
};
|
||||
|
||||
private static readonly EncounterStatic[] Encounter_USUM =
|
||||
{
|
||||
new EncounterStatic { Gift = true, Species = 722, Level = 05, Location = 8, }, // Rowlet
|
||||
|
@ -379,6 +383,7 @@ namespace PKHeX.Core
|
|||
new EncounterStatic { Species = 739, Level = 31, Location = 118, }, // Route 16
|
||||
new EncounterStatic { Species = 739, Level = 32, Location = 120, }, // Route 17
|
||||
};
|
||||
|
||||
internal static readonly EncounterTrade[] TradeGift_USUM =
|
||||
{
|
||||
// Trades - 4.bin
|
||||
|
@ -390,6 +395,7 @@ namespace PKHeX.Core
|
|||
new EncounterTrade { Species = 422, Form = 0, Level = 44, Ability = 2, TID = 20679, SID = 00009, IVs = new[] {-1,-1,31,-1,-1,-1}, OTGender = 1, Gender = 1, Nature = Nature.Quiet, }, // Shellos
|
||||
new EncounterTrade { Species = 128, Form = 0, Level = 59, Ability = 1, TID = 56734, SID = 00008, IVs = new[] {-1,-1,-1,31,-1,-1}, OTGender = 0, Gender = 0, Nature = Nature.Jolly, }, // Tauros
|
||||
};
|
||||
|
||||
internal static readonly string[][] TradeSM =
|
||||
{
|
||||
new string[0], // 0 - None
|
||||
|
@ -404,6 +410,7 @@ namespace PKHeX.Core
|
|||
Util.GetStringList("tradesm", "zh"), // 9
|
||||
Util.GetStringList("tradesm", "zh"), // 10
|
||||
};
|
||||
|
||||
internal static readonly string[][] TradeUSUM =
|
||||
{
|
||||
new string[0], // 0 - None
|
||||
|
@ -420,6 +427,7 @@ namespace PKHeX.Core
|
|||
};
|
||||
|
||||
private static EncounterArea[] Encounter_Pelago_SN, Encounter_Pelago_MN, Encounter_Pelago_US, Encounter_Pelago_UM;
|
||||
|
||||
private static void InitializePelagoAreas()
|
||||
{
|
||||
int[] minLevels = { 1, 11, 21, 37, 49 };
|
||||
|
@ -447,6 +455,7 @@ namespace PKHeX.Core
|
|||
speciesUU[3][3] = 309; // Houndour -> Electrike
|
||||
Encounter_Pelago_UM = GetPelagoArea(speciesUU, minLevels);
|
||||
}
|
||||
|
||||
private static EncounterArea[] GetPelagoArea(int[][] species, int[] min)
|
||||
{
|
||||
// Species that appear at a lower level than the current table show up too.
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
namespace PKHeX.Core
|
||||
using System;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Invalid Encounter Data
|
||||
|
@ -20,6 +22,6 @@
|
|||
EggEncounter = pkm.WasEgg;
|
||||
}
|
||||
|
||||
public PKM ConvertToPKM(ITrainerInfo SAV) => throw new System.NotImplementedException();
|
||||
public PKM ConvertToPKM(ITrainerInfo SAV) => throw new ArgumentException($"Cannot convert an {nameof(EncounterInvalid)} to PKM.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -21,6 +23,6 @@ namespace PKHeX.Core
|
|||
Check = check;
|
||||
}
|
||||
|
||||
public PKM ConvertToPKM(ITrainerInfo SAV) => throw new System.NotImplementedException();
|
||||
public PKM ConvertToPKM(ITrainerInfo SAV) => throw new ArgumentException($"Cannot convert an {nameof(EncounterRejected)} to PKM.");
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@ namespace PKHeX.Core
|
|||
public bool IsDexNav => AllowDexNav && DexNav;
|
||||
public EncounterSlotPermissions Clone() => (EncounterSlotPermissions)MemberwiseClone();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wild Encounter Slot data
|
||||
/// </summary>
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace PKHeX.Core
|
|||
public int Ability { get; set; }
|
||||
public int Form { get; set; }
|
||||
public virtual Shiny Shiny { get; set; } = Shiny.Random;
|
||||
public int[] Relearn { get; set; } = new int[4];
|
||||
public int[] Relearn { get; set; } = Array.Empty<int>();
|
||||
public int Gender { get; set; } = -1;
|
||||
public int EggLocation { get; set; }
|
||||
public Nature Nature { get; set; } = Nature.Random;
|
||||
|
@ -56,6 +56,7 @@ namespace PKHeX.Core
|
|||
Relearn = (int[])Relearn.Clone();
|
||||
IVs = (int[])IVs?.Clone();
|
||||
}
|
||||
|
||||
internal virtual EncounterStatic Clone()
|
||||
{
|
||||
var result = (EncounterStatic)MemberwiseClone();
|
||||
|
@ -119,14 +120,16 @@ namespace PKHeX.Core
|
|||
pk.Gender = PKX.GetGenderFromPID(Species, p.PID);
|
||||
if (pk is PK5 pk5)
|
||||
{
|
||||
pk5.IVs = new[] { 30, 30, 30, 30, 30, 30 };
|
||||
pk5.IVs = new[] {30, 30, 30, 30, 30, 30};
|
||||
pk5.NPokémon = p.NSparkle;
|
||||
pk5.OT_Name = Legal.GetG5OT_NSparkle(lang);
|
||||
pk5.TID = 00002;
|
||||
pk5.SID = 00000;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetIVs(pk);
|
||||
}
|
||||
if (Generation >= 5)
|
||||
pk.Nature = nature;
|
||||
pk.RefreshAbility(Ability >> 1);
|
||||
|
@ -160,7 +163,7 @@ namespace PKHeX.Core
|
|||
pk.HeldItem = HeldItem;
|
||||
pk.Moves = moves;
|
||||
pk.SetMaximumPPCurrent(moves);
|
||||
if (pk.Format >= 6 && Relearn != null)
|
||||
if (pk.Format >= 6 && Relearn.Length > 0)
|
||||
pk.RelearnMoves = Relearn;
|
||||
pk.OT_Friendship = pk.PersonalInfo.BaseFriendship;
|
||||
if (Fateful)
|
||||
|
@ -179,7 +182,8 @@ namespace PKHeX.Core
|
|||
|
||||
private void SanityCheckVersion(ref GameVersion version)
|
||||
{
|
||||
if (Generation == 4 && (int)version != 12)
|
||||
if (Generation != 4 || version == GameVersion.Pt)
|
||||
return;
|
||||
switch (Species)
|
||||
{
|
||||
case 491 when Location == 079: // DP Darkrai
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
namespace PKHeX.Core
|
||||
using System;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
internal class EncounterStaticShadow : EncounterStatic
|
||||
{
|
||||
public EncounterLock[][] Locks { get; internal set; } = new EncounterLock[0][];
|
||||
public EncounterLock[][] Locks { get; internal set; } = Array.Empty<EncounterLock[]>();
|
||||
public int Gauge { get; internal set; }
|
||||
public bool EReader { get; set; }
|
||||
|
||||
internal override EncounterStatic Clone()
|
||||
{
|
||||
var result = (EncounterStaticShadow)base.Clone();
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace PKHeX.Core
|
|||
var evos = table.GetValidPreEvolutions(pkm, maxLevel: 100, maxSpeciesOrigin: maxSpeciesOrigin, skipChecks: true);
|
||||
return GenerateEggs(pkm, evos, all);
|
||||
}
|
||||
|
||||
public static IEnumerable<EncounterEgg> GenerateEggs(PKM pkm, IReadOnlyList<DexLevel> vs, bool all = false)
|
||||
{
|
||||
if (NoHatchFromEgg.Contains(pkm.Species))
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace PKHeX.Core
|
|||
/// <param name="pkm">Source data to find a match for</param>
|
||||
/// <returns>
|
||||
/// Information containing the matched encounter and any parsed checks.
|
||||
/// If no clean match is found, the last checked match is returned.
|
||||
/// If no clean match is found, the last checked match is returned.
|
||||
/// If no match is found, an invalid encounter object is returned.
|
||||
/// </returns>
|
||||
public static LegalInfo FindVerifiedEncounter(PKM pkm)
|
||||
|
@ -76,8 +76,10 @@ namespace PKHeX.Core
|
|||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
info.Relearn[i] = new CheckResult(CheckIdentifier.RelearnMove);
|
||||
}
|
||||
|
||||
info.Moves = VerifyCurrentMoves.VerifyMoves(pkm, info);
|
||||
if (info.Moves.Any(z => !z.Valid) && iterator.PeekIsNext())
|
||||
|
|
|
@ -54,6 +54,7 @@ namespace PKHeX.Core
|
|||
yield return z;
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<IEncounterable> GetEncounters3(PKM pkm, LegalInfo info)
|
||||
{
|
||||
info.PIDIV = MethodFinder.Analyze(pkm);
|
||||
|
@ -74,6 +75,7 @@ namespace PKHeX.Core
|
|||
foreach (var z in deferred)
|
||||
yield return z;
|
||||
}
|
||||
|
||||
private static IEnumerable<IEncounterable> GetEncounters4(PKM pkm, LegalInfo info)
|
||||
{
|
||||
info.PIDIV = MethodFinder.Analyze(pkm);
|
||||
|
@ -178,9 +180,10 @@ namespace PKHeX.Core
|
|||
foreach (var d in deferred)
|
||||
yield return d;
|
||||
}
|
||||
|
||||
private static IEnumerable<IEncounterable> GenerateFilteredEncounters12(PKM pkm)
|
||||
{
|
||||
bool crystal = pkm.Format == 2 && pkm.Met_Location != 0 || pkm.Format >= 7 && pkm.OT_Gender == 1;
|
||||
bool crystal = (pkm.Format == 2 && pkm.Met_Location != 0) || (pkm.Format >= 7 && pkm.OT_Gender == 1);
|
||||
bool kadabra = pkm.Species == 64 && pkm is PK1 pk1
|
||||
&& (pk1.Catch_Rate == PersonalTable.RB[64].CatchRate
|
||||
|| pk1.Catch_Rate == PersonalTable.Y[64].CatchRate); // catch rate outsider, return gen1 first always
|
||||
|
@ -210,18 +213,21 @@ namespace PKHeX.Core
|
|||
foreach (var z in deferred)
|
||||
yield return z;
|
||||
}
|
||||
|
||||
private static IEnumerable<IEncounterable> GenerateRawEncounters1(PKM pkm, bool crystal)
|
||||
{
|
||||
return pkm.Gen2_NotTradeback || crystal
|
||||
? Enumerable.Empty<IEncounterable>()
|
||||
: GenerateRawEncounters12(pkm, GameVersion.RBY);
|
||||
}
|
||||
|
||||
private static IEnumerable<IEncounterable> GenerateRawEncounters2(PKM pkm, bool crystal)
|
||||
{
|
||||
return pkm.Gen1_NotTradeback
|
||||
? Enumerable.Empty<IEncounterable>()
|
||||
: GenerateRawEncounters12(pkm, crystal ? GameVersion.C : GameVersion.GSC);
|
||||
}
|
||||
|
||||
private static PeekEnumerator<IEncounterable> GetPreferredGBIterator(PKM pkm, PeekEnumerator<IEncounterable> g1i, PeekEnumerator<IEncounterable> g2i)
|
||||
{
|
||||
if (!g1i.PeekIsNext())
|
||||
|
@ -232,6 +238,7 @@ namespace PKHeX.Core
|
|||
var p2 = GetGBEncounterPriority(pkm, g2i.Current);
|
||||
return p1 > p2 ? g1i : g2i;
|
||||
}
|
||||
|
||||
private static GBEncounterPriority GetGBEncounterPriority(PKM pkm, IEncounterable Encounter)
|
||||
{
|
||||
switch (Encounter)
|
||||
|
@ -300,6 +307,7 @@ namespace PKHeX.Core
|
|||
{ yield return z; ++ctr; }
|
||||
// if (ctr != 0) yield break;
|
||||
}
|
||||
|
||||
private static IEnumerable<IEncounterable> GenerateRawEncounters4(PKM pkm, LegalInfo info)
|
||||
{
|
||||
bool wasEvent = pkm.WasEvent || pkm.WasEventEgg; // egg events?
|
||||
|
@ -323,12 +331,14 @@ namespace PKHeX.Core
|
|||
bool safari = pkm.Ball == 0x05; // never static encounters
|
||||
bool safariSport = safari || sport;
|
||||
if (!safariSport)
|
||||
foreach (var z in GetValidStaticEncounter(pkm))
|
||||
{
|
||||
if (z.Gift && pkm.Ball != 4)
|
||||
deferIncompat.Enqueue(z);
|
||||
else
|
||||
yield return z;
|
||||
foreach (var z in GetValidStaticEncounter(pkm))
|
||||
{
|
||||
if (z.Gift && pkm.Ball != 4)
|
||||
deferIncompat.Enqueue(z);
|
||||
else
|
||||
yield return z;
|
||||
}
|
||||
}
|
||||
|
||||
int species = pkm.Species;
|
||||
|
@ -366,10 +376,12 @@ namespace PKHeX.Core
|
|||
yield return z;
|
||||
|
||||
// do static encounters if they were deferred to end, spit out any possible encounters for invalid pkm
|
||||
if (safariSport)
|
||||
if (!safariSport)
|
||||
yield break;
|
||||
foreach (var z in GetValidStaticEncounter(pkm))
|
||||
yield return z;
|
||||
}
|
||||
|
||||
private static IEnumerable<IEncounterable> GenerateRawEncounters3(PKM pkm, LegalInfo info)
|
||||
{
|
||||
foreach (var z in GetValidGifts(pkm))
|
||||
|
@ -380,12 +392,14 @@ namespace PKHeX.Core
|
|||
var deferIncompat = new Queue<IEncounterable>();
|
||||
bool safari = pkm.Ball == 0x05; // never static encounters
|
||||
if (!safari)
|
||||
foreach (var z in GetValidStaticEncounter(pkm))
|
||||
{
|
||||
if (z.Gift && pkm.Ball != 4)
|
||||
deferIncompat.Enqueue(z);
|
||||
else
|
||||
yield return z;
|
||||
foreach (var z in GetValidStaticEncounter(pkm))
|
||||
{
|
||||
if (z.Gift && pkm.Ball != 4)
|
||||
deferIncompat.Enqueue(z);
|
||||
else
|
||||
yield return z;
|
||||
}
|
||||
}
|
||||
|
||||
int species = pkm.Species;
|
||||
|
@ -421,13 +435,16 @@ namespace PKHeX.Core
|
|||
info.FrameMatches = false;
|
||||
|
||||
if (pkm.Version != 15) // no eggs in C/XD
|
||||
foreach (var z in GenerateEggs(pkm))
|
||||
yield return z;
|
||||
{
|
||||
foreach (var z in GenerateEggs(pkm))
|
||||
yield return z;
|
||||
}
|
||||
|
||||
foreach (var z in deferIncompat)
|
||||
yield return z;
|
||||
// do static encounters if they were deferred to end, spit out any possible encounters for invalid pkm
|
||||
if (safari)
|
||||
if (!safari)
|
||||
yield break;
|
||||
foreach (var z in GetValidStaticEncounter(pkm))
|
||||
yield return z;
|
||||
}
|
||||
|
@ -445,6 +462,7 @@ namespace PKHeX.Core
|
|||
return type == 0;
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool IsEncounterTrade1Valid(PKM pkm, EncounterTrade t)
|
||||
{
|
||||
string ot = pkm.OT_Name;
|
||||
|
|
|
@ -130,8 +130,10 @@ namespace PKHeX.Core
|
|||
// generate possible eggs
|
||||
var eggs = GetEggs(pk, needs, version);
|
||||
if (!GameVersion.CXD.Contains(version))
|
||||
foreach (var egg in eggs)
|
||||
yield return egg;
|
||||
{
|
||||
foreach (var egg in eggs)
|
||||
yield return egg;
|
||||
}
|
||||
|
||||
// mystery gifts next
|
||||
var gifts = GetGifts(pk, needs);
|
||||
|
@ -304,7 +306,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool IsUnobtainable(this EncounterSlot slot, PKM pk)
|
||||
private static bool IsUnobtainable(this EncounterSlot slot, ITrainerID pk)
|
||||
{
|
||||
switch (slot.Generation)
|
||||
{
|
||||
|
@ -312,9 +314,8 @@ namespace PKHeX.Core
|
|||
if ((slot.Type & SlotType.Safari) != 0) // Safari Zone is unavailable in Gen 2.
|
||||
return true;
|
||||
|
||||
if ((slot.Type & SlotType.Headbutt) != 0)
|
||||
if (Encounters2.GetGSCHeadbuttAvailability(slot, pk.TID) != TreeEncounterAvailable.ValidTree) // Unreachable Headbutt Trees.
|
||||
return true;
|
||||
if ((slot.Type & SlotType.Headbutt) != 0) // Unreachable Headbutt Trees.
|
||||
return Encounters2.GetGSCHeadbuttAvailability(slot, pk.TID) != TreeEncounterAvailable.ValidTree;
|
||||
break;
|
||||
case 4:
|
||||
if (slot.Location == 193 && slot.Type == SlotType.Surf) // Johto Route 45 surfing encounter. Unreachable Water tiles.
|
||||
|
|
|
@ -14,17 +14,20 @@ namespace PKHeX.Core
|
|||
var vs = EvolutionChain.GetValidPreEvolutions(pkm, maxspeciesorigin: maxspeciesorigin);
|
||||
return GetPossible(pkm, vs, gameSource);
|
||||
}
|
||||
|
||||
public static IEnumerable<EncounterSlot> GetPossible(PKM pkm, IReadOnlyList<DexLevel> vs, GameVersion gameSource = GameVersion.Any)
|
||||
{
|
||||
var possibleAreas = GetEncounterSlots(pkm, gameSource);
|
||||
return possibleAreas.SelectMany(area => area.Slots).Where(z => vs.Any(v => v.Species == z.Species));
|
||||
}
|
||||
|
||||
private static IEnumerable<EncounterSlot> GetRawEncounterSlots(PKM pkm, int lvl, GameVersion gameSource)
|
||||
{
|
||||
int maxspeciesorigin = GetMaxSpecies(gameSource);
|
||||
var vs = EvolutionChain.GetValidPreEvolutions(pkm, maxspeciesorigin: maxspeciesorigin);
|
||||
return GetRawEncounterSlots(pkm, lvl, vs, gameSource);
|
||||
}
|
||||
|
||||
private static IEnumerable<EncounterSlot> GetRawEncounterSlots(PKM pkm, int lvl, IReadOnlyList<EvoCriteria> vs, GameVersion gameSource)
|
||||
{
|
||||
var possibleAreas = GetEncounterAreas(pkm, gameSource);
|
||||
|
@ -52,6 +55,7 @@ namespace PKHeX.Core
|
|||
|
||||
return s; // defer deferrals to the method consuming this collection
|
||||
}
|
||||
|
||||
public static IEnumerable<EncounterSlot> GetValidWildEncounters12(PKM pkm, IReadOnlyList<EvoCriteria> vs, GameVersion gameSource = GameVersion.Any)
|
||||
{
|
||||
if (gameSource == GameVersion.Any)
|
||||
|
@ -62,6 +66,7 @@ namespace PKHeX.Core
|
|||
return Enumerable.Empty<EncounterSlot>();
|
||||
return GetRawEncounterSlots(pkm, lvl, vs, gameSource);
|
||||
}
|
||||
|
||||
public static IEnumerable<EncounterSlot> GetValidWildEncounters(PKM pkm, IReadOnlyList<EvoCriteria> vs, GameVersion gameSource = GameVersion.Any)
|
||||
{
|
||||
if (gameSource == GameVersion.Any)
|
||||
|
@ -79,6 +84,7 @@ namespace PKHeX.Core
|
|||
|
||||
return s.DeferByBoolean(slot => slot.IsDeferred(species, pkm, IsSafariBall, IsSportBall, IsHidden)); // non-deferred first
|
||||
}
|
||||
|
||||
public static IEnumerable<EncounterSlot> GetValidWildEncounters(PKM pkm, GameVersion gameSource = GameVersion.Any)
|
||||
{
|
||||
if (gameSource == GameVersion.Any)
|
||||
|
@ -96,17 +102,20 @@ namespace PKHeX.Core
|
|||
|
||||
return s.DeferByBoolean(slot => slot.IsDeferred(species, pkm, IsSafariBall, IsSportBall, IsHidden)); // non-deferred first
|
||||
}
|
||||
|
||||
public static bool IsDeferred3(this EncounterSlot slot, int currentSpecies, PKM pkm, bool IsSafariBall)
|
||||
{
|
||||
return slot.IsDeferredWurmple(currentSpecies, pkm)
|
||||
|| slot.IsDeferredSafari(IsSafariBall);
|
||||
}
|
||||
|
||||
public static bool IsDeferred4(this EncounterSlot slot, int currentSpecies, PKM pkm, bool IsSafariBall, bool IsSportBall)
|
||||
{
|
||||
return slot.IsDeferredWurmple(currentSpecies, pkm)
|
||||
|| slot.IsDeferredSafari(IsSafariBall)
|
||||
|| slot.IsDeferredSport(IsSportBall);
|
||||
}
|
||||
|
||||
private static bool IsDeferred(this EncounterSlot slot, int currentSpecies, PKM pkm, bool IsSafariBall, bool IsSportBall, bool IsHidden)
|
||||
{
|
||||
return slot.IsDeferredWurmple(currentSpecies, pkm)
|
||||
|
@ -114,6 +123,7 @@ namespace PKHeX.Core
|
|||
|| slot.IsDeferredSafari(IsSafariBall)
|
||||
|| slot.IsDeferredSport(IsSportBall);
|
||||
}
|
||||
|
||||
private static bool IsDeferredWurmple(this IEncounterable slot, int currentSpecies, PKM pkm) => slot.Species == 265 && currentSpecies != 265 && !IsWurmpleEvoValid(pkm);
|
||||
private static bool IsDeferredSafari(this EncounterSlot slot, bool IsSafariBall) => IsSafariBall != ((slot.Type & SlotType.Safari) != 0);
|
||||
private static bool IsDeferredSport(this EncounterSlot slot, bool IsSportBall) => IsSportBall != ((slot.Type & SlotType.BugContest) != 0);
|
||||
|
@ -155,6 +165,7 @@ namespace PKHeX.Core
|
|||
return GetFilteredSlots6DexNav(pkm, lvl, encounterSlots, fluteBoost);
|
||||
return GetFilteredSlots67(pkm, encounterSlots);
|
||||
}
|
||||
|
||||
private static IEnumerable<EncounterSlot> GetValidEncounterSlots12(PKM pkm, EncounterArea loc, IEnumerable<DexLevel> vs, int lvl = -1, bool ignoreLevel = false)
|
||||
{
|
||||
if (lvl < 0)
|
||||
|
@ -170,6 +181,7 @@ namespace PKHeX.Core
|
|||
var encounterSlots = GetValidEncounterSlotsByEvoLevel(pkm, loc.Slots, lvl, ignoreLevel, vs);
|
||||
return GetFilteredSlots12(pkm, pkm.GenNumber, Gen1Version, encounterSlots, RBDragonair).OrderBy(slot => slot.LevelMin); // prefer lowest levels
|
||||
}
|
||||
|
||||
private static IEnumerable<EncounterSlot> GetValidEncounterSlotsByEvoLevel(PKM pkm, IEnumerable<EncounterSlot> slots, int lvl, bool ignoreLevel, IEnumerable<DexLevel> vs, int df = 0, int dn = 0)
|
||||
{
|
||||
// Get slots where pokemon can exist with respect to the evolution chain
|
||||
|
@ -183,12 +195,14 @@ namespace PKHeX.Core
|
|||
// check for any less than current level
|
||||
return slots.Where(slot => slot.LevelMin <= lvl);
|
||||
}
|
||||
|
||||
private static IEnumerable<EncounterSlot> GetFilteredSlotsByForm(PKM pkm, IEnumerable<EncounterSlot> encounterSlots)
|
||||
{
|
||||
return WildForms.Contains(pkm.Species)
|
||||
? encounterSlots.Where(slot => slot.Form == pkm.AltForm)
|
||||
: encounterSlots;
|
||||
}
|
||||
|
||||
private static IEnumerable<EncounterSlot> GetFilteredSlots67(PKM pkm, IEnumerable<EncounterSlot> encounterSlots)
|
||||
{
|
||||
int species = pkm.Species;
|
||||
|
@ -239,7 +253,7 @@ namespace PKHeX.Core
|
|||
// Filter for Form Specific
|
||||
// Pressure Slot
|
||||
if (slotMax == null)
|
||||
yield break; // yield break;
|
||||
yield break;
|
||||
|
||||
if (AlolanVariantEvolutions12.Contains(species)) // match form if same species, else form 0.
|
||||
{
|
||||
|
@ -252,10 +266,13 @@ namespace PKHeX.Core
|
|||
yield return GetPressureSlot(slotMax, pkm);
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return GetPressureSlot(slotMax, pkm);
|
||||
}
|
||||
|
||||
bool ShouldMatchSlotForm() => WildForms.Contains(species) || AlolanOriginForms.Contains(species) || FormConverter.IsTotemForm(species, form);
|
||||
}
|
||||
|
||||
private static IEnumerable<EncounterSlot> GetFilteredSlots6DexNav(PKM pkm, int lvl, IEnumerable<EncounterSlot> encounterSlots, int fluteBoost)
|
||||
{
|
||||
EncounterSlot slotMax = null;
|
||||
|
@ -290,6 +307,7 @@ namespace PKHeX.Core
|
|||
if (slotMax != null)
|
||||
yield return GetPressureSlot(slotMax, pkm);
|
||||
}
|
||||
|
||||
private static EncounterSlot GetPressureSlot(EncounterSlot s, PKM pkm)
|
||||
{
|
||||
var max = s.Clone();
|
||||
|
@ -346,6 +364,7 @@ namespace PKHeX.Core
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<EncounterSlot> GetFilteredSlots12(PKM pkm, int gen, GameVersion Gen1Version, IEnumerable<EncounterSlot> slots, bool RBDragonair)
|
||||
{
|
||||
switch (gen)
|
||||
|
@ -377,13 +396,14 @@ namespace PKHeX.Core
|
|||
|
||||
return GetEncounterTable(pkm, gameSource);
|
||||
}
|
||||
|
||||
private static IEnumerable<EncounterArea> GetEncounterAreas(PKM pkm, GameVersion gameSource = GameVersion.Any)
|
||||
{
|
||||
if (gameSource == GameVersion.Any)
|
||||
gameSource = (GameVersion)pkm.Version;
|
||||
|
||||
var slots = GetEncounterSlots(pkm, gameSource: gameSource);
|
||||
bool noMet = !pkm.HasOriginalMetLocation || pkm.Format == 2 && gameSource != GameVersion.C;
|
||||
bool noMet = !pkm.HasOriginalMetLocation || (pkm.Format == 2 && gameSource != GameVersion.C);
|
||||
return noMet ? slots : slots.Where(area => area.Location == pkm.Met_Location);
|
||||
}
|
||||
|
||||
|
@ -411,6 +431,7 @@ namespace PKHeX.Core
|
|||
var d_areas = areas.Select(area => GetValidEncounterSlots(pkm, area, vs, DexNav: true));
|
||||
return d_areas.Any(slots => slots.Any(slot => slot.Permissions.AllowDexNav && slot.Permissions.DexNav));
|
||||
}
|
||||
|
||||
internal static EncounterArea GetCaptureLocation(PKM pkm)
|
||||
{
|
||||
var vs = EvolutionChain.GetValidPreEvolutions(pkm);
|
||||
|
|
|
@ -175,7 +175,7 @@ namespace PKHeX.Core
|
|||
return false;
|
||||
if (e.Form != pkm.AltForm && !e.SkipFormCheck && !IsFormChangeable(pkm, e.Species))
|
||||
return false;
|
||||
if (e.EggLocation == 60002 && e.Relearn[0] == 0 && pkm.RelearnMoves.Any(z => z != 0)) // gen7 eevee edge case
|
||||
if (e.EggLocation == 60002 && e.Relearn.Length == 0 && pkm.RelearnMoves.Any(z => z != 0)) // gen7 eevee edge case
|
||||
return false;
|
||||
|
||||
if (e.IVs != null && (e.Generation > 2 || pkm.Format <= 2)) // 1,2->7 regenerates IVs, only check if original IVs still exist
|
||||
|
|
|
@ -12,20 +12,23 @@ namespace PKHeX.Core
|
|||
var p = EvolutionChain.GetValidPreEvolutions(pkm);
|
||||
return GetPossible(pkm, p, gameSource);
|
||||
}
|
||||
|
||||
public static IEnumerable<EncounterTrade> GetPossible(PKM pkm, IReadOnlyList<DexLevel> vs, GameVersion gameSource = GameVersion.Any)
|
||||
{
|
||||
if (gameSource == GameVersion.Any)
|
||||
gameSource = (GameVersion)pkm.Version;
|
||||
|
||||
if (pkm.VC || pkm.Format <= 2)
|
||||
return GetPossibleVC(pkm, vs, gameSource);
|
||||
return GetPossibleVC(vs, gameSource);
|
||||
return GetPossibleNonVC(pkm, vs, gameSource);
|
||||
}
|
||||
|
||||
public static IEnumerable<EncounterTrade> GetValidEncounterTrades(PKM pkm, GameVersion gameSource = GameVersion.Any)
|
||||
{
|
||||
var p = EvolutionChain.GetValidPreEvolutions(pkm);
|
||||
return GetValidEncounterTrades(pkm, p, gameSource);
|
||||
}
|
||||
|
||||
public static IEnumerable<EncounterTrade> GetValidEncounterTrades(PKM pkm, IReadOnlyList<DexLevel> p, GameVersion gameSource = GameVersion.Any)
|
||||
{
|
||||
if (GetIsFromGB(pkm))
|
||||
|
@ -38,6 +41,7 @@ namespace PKHeX.Core
|
|||
var poss = GetPossibleNonVC(pkm, p, gameSource);
|
||||
return poss.Where(z => IsEncounterTradeValid(pkm, z, lvl));
|
||||
}
|
||||
|
||||
private static IEnumerable<EncounterTrade> GetPossibleNonVC(PKM pkm, IReadOnlyList<DexLevel> p, GameVersion gameSource = GameVersion.Any)
|
||||
{
|
||||
if (gameSource == GameVersion.Any)
|
||||
|
@ -49,11 +53,13 @@ namespace PKHeX.Core
|
|||
var table = GetEncounterTradeTable(pkm);
|
||||
return table?.Where(f => p.Any(r => r.Species == f.Species)) ?? Enumerable.Empty<EncounterTrade>();
|
||||
}
|
||||
private static IEnumerable<EncounterTrade> GetPossibleVC(PKM pkm, IReadOnlyList<DexLevel> p, GameVersion gameSource = GameVersion.Any)
|
||||
|
||||
private static IEnumerable<EncounterTrade> GetPossibleVC(IReadOnlyList<DexLevel> p, GameVersion gameSource = GameVersion.Any)
|
||||
{
|
||||
var table = GetEncounterTradeTableVC(gameSource);
|
||||
return table.Where(f => p.Any(r => r.Species == f.Species));
|
||||
}
|
||||
|
||||
private static IEnumerable<EncounterTrade> GetEncounterTradeTableVC(GameVersion gameSource)
|
||||
{
|
||||
if (GameVersion.RBY.Contains(gameSource))
|
||||
|
@ -62,6 +68,7 @@ namespace PKHeX.Core
|
|||
return Encounters2.TradeGift_GSC;
|
||||
return null;
|
||||
}
|
||||
|
||||
private static IEnumerable<EncounterTrade> GetEncounterTradeTable(PKM pkm)
|
||||
{
|
||||
switch (pkm.GenNumber)
|
||||
|
@ -74,13 +81,15 @@ namespace PKHeX.Core
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static IEnumerable<EncounterTrade> GetValidEncounterTradesVC(PKM pkm, IReadOnlyList<DexLevel> p, GameVersion gameSource)
|
||||
{
|
||||
var poss = GetPossibleVC(pkm, p, gameSource);
|
||||
var poss = GetPossibleVC(p, gameSource);
|
||||
if (gameSource == GameVersion.RBY)
|
||||
return poss.Where(z => GetIsValidTradeVC1(pkm, z));
|
||||
return poss.Where(z => GetIsValidTradeVC2(pkm, z));
|
||||
}
|
||||
|
||||
private static bool GetIsValidTradeVC1(PKM pkm, EncounterTrade z)
|
||||
{
|
||||
if (z.Level > pkm.CurrentLevel) // minimum required level
|
||||
|
@ -104,6 +113,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool GetIsValidTradeVC2(PKM pkm, EncounterTrade z)
|
||||
{
|
||||
if (z.Level > pkm.CurrentLevel) // minimum required level
|
||||
|
@ -127,12 +137,17 @@ namespace PKHeX.Core
|
|||
}
|
||||
|
||||
private static bool GetIsFromGB(PKM pkm) => pkm.VC || pkm.Format <= 2;
|
||||
|
||||
private static bool IsEncounterTradeValid(PKM pkm, EncounterTrade z, int lvl)
|
||||
{
|
||||
if (z.IVs != null)
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
if (z.IVs[i] != -1 && z.IVs[i] != pkm.IVs[i])
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (z is EncounterTradePID p)
|
||||
{
|
||||
|
@ -159,16 +174,21 @@ namespace PKHeX.Core
|
|||
var loc = z.Location > 0 ? z.Location : EncounterTrade.DefaultMetLocation[z.Generation - 1];
|
||||
if (loc != pkm.Met_Location)
|
||||
return false;
|
||||
|
||||
if (pkm.Format < 5)
|
||||
{
|
||||
if (z.Level > lvl)
|
||||
return false;
|
||||
}
|
||||
else if (z.Level != lvl)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (z.Level > lvl)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (z.CurrentLevel != -1 && z.CurrentLevel > pkm.CurrentLevel)
|
||||
return false;
|
||||
|
|
|
@ -13,11 +13,13 @@ namespace PKHeX.Core
|
|||
var vs = EvolutionChain.GetValidPreEvolutions(pkm, maxSpecies);
|
||||
return GetPossible(pkm, vs);
|
||||
}
|
||||
|
||||
public static IEnumerable<MysteryGift> GetPossible(PKM pkm, IReadOnlyList<DexLevel> vs)
|
||||
{
|
||||
var table = GetTable(pkm.GenNumber);
|
||||
return table.Where(wc => vs.Any(dl => dl.Species == wc.Species));
|
||||
}
|
||||
|
||||
public static IEnumerable<MysteryGift> GetValidGifts(PKM pkm)
|
||||
{
|
||||
int gen = pkm.GenNumber;
|
||||
|
@ -32,6 +34,7 @@ namespace PKHeX.Core
|
|||
default: return Enumerable.Empty<MysteryGift>();
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<MysteryGift> GetTable(int generation)
|
||||
{
|
||||
switch (generation)
|
||||
|
@ -44,6 +47,7 @@ namespace PKHeX.Core
|
|||
default: return Enumerable.Empty<MysteryGift>();
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<MysteryGift> GetMatchingWC3(PKM pkm, IEnumerable<MysteryGift> DB)
|
||||
{
|
||||
if (DB == null)
|
||||
|
@ -65,9 +69,10 @@ namespace PKHeX.Core
|
|||
foreach (var z in validWC3)
|
||||
yield return z;
|
||||
}
|
||||
|
||||
private static IEnumerable<MysteryGift> GetMatchingPCD(PKM pkm, IEnumerable<MysteryGift> DB)
|
||||
{
|
||||
if (DB == null || pkm.IsEgg && pkm.Format != 4) // transferred
|
||||
if (DB == null || (pkm.IsEgg && pkm.Format != 4)) // transferred
|
||||
yield break;
|
||||
|
||||
if (IsRangerManaphy(pkm))
|
||||
|
@ -95,6 +100,7 @@ namespace PKHeX.Core
|
|||
foreach (var z in deferred)
|
||||
yield return z;
|
||||
}
|
||||
|
||||
private static IEnumerable<MysteryGift> GetMatchingPGF(PKM pkm, IEnumerable<MysteryGift> DB)
|
||||
{
|
||||
if (DB == null)
|
||||
|
@ -116,6 +122,7 @@ namespace PKHeX.Core
|
|||
foreach (var z in deferred)
|
||||
yield return z;
|
||||
}
|
||||
|
||||
private static IEnumerable<MysteryGift> GetMatchingWC6(PKM pkm, IEnumerable<MysteryGift> DB)
|
||||
{
|
||||
if (DB == null)
|
||||
|
@ -135,6 +142,7 @@ namespace PKHeX.Core
|
|||
foreach (var z in deferred)
|
||||
yield return z;
|
||||
}
|
||||
|
||||
private static IEnumerable<MysteryGift> GetMatchingWC7(PKM pkm, IEnumerable<MysteryGift> DB)
|
||||
{
|
||||
if (DB == null)
|
||||
|
@ -164,6 +172,7 @@ namespace PKHeX.Core
|
|||
foreach (var z in deferred)
|
||||
yield return z;
|
||||
}
|
||||
|
||||
private static bool GetIsMatchWC3(PKM pkm, WC3 wc)
|
||||
{
|
||||
// Gen3 Version MUST match.
|
||||
|
@ -206,6 +215,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool GetIsMatchPCD(PKM pkm, PK4 wc, IEnumerable<DexLevel> vs)
|
||||
{
|
||||
if (!wc.IsEgg)
|
||||
|
@ -250,6 +260,7 @@ namespace PKHeX.Core
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool GetIsMatchPGF(PKM pkm, PGF wc, IEnumerable<DexLevel> vs)
|
||||
{
|
||||
if (!wc.IsEgg)
|
||||
|
@ -275,7 +286,10 @@ namespace PKHeX.Core
|
|||
return false;
|
||||
}
|
||||
else if (wc.PIDType == 0 && pkm.IsShiny)
|
||||
{
|
||||
return false; // can't be traded away for unshiny
|
||||
}
|
||||
|
||||
if (pkm.IsEgg && !pkm.IsNative)
|
||||
return false;
|
||||
}
|
||||
|
@ -292,6 +306,7 @@ namespace PKHeX.Core
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool GetIsMatchWC6(PKM pkm, WC6 wc, IEnumerable<DexLevel> vs)
|
||||
{
|
||||
if (pkm.Egg_Location == 0) // Not Egg
|
||||
|
@ -316,7 +331,10 @@ namespace PKHeX.Core
|
|||
return false;
|
||||
}
|
||||
else if (wc.PIDType == 0 && pkm.IsShiny)
|
||||
{
|
||||
return false; // can't be traded away for unshiny
|
||||
}
|
||||
|
||||
if (pkm.IsEgg && !pkm.IsNative)
|
||||
return false;
|
||||
}
|
||||
|
@ -337,6 +355,7 @@ namespace PKHeX.Core
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool GetIsMatchWC7(PKM pkm, WC7 wc, IEnumerable<DexLevel> vs)
|
||||
{
|
||||
if (pkm.Egg_Location == 0) // Not Egg
|
||||
|
@ -359,7 +378,9 @@ namespace PKHeX.Core
|
|||
// Rockruff gift edge case; has altform 1 then evolves to altform 2
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (wc.IsEgg)
|
||||
|
@ -370,7 +391,10 @@ namespace PKHeX.Core
|
|||
return false;
|
||||
}
|
||||
else if (wc.PIDType == 0 && pkm.IsShiny)
|
||||
{
|
||||
return false; // can't be traded away for unshiny
|
||||
}
|
||||
|
||||
if (pkm.IsEgg && !pkm.IsNative)
|
||||
return false;
|
||||
}
|
||||
|
@ -412,6 +436,7 @@ namespace PKHeX.Core
|
|||
return true;
|
||||
return wc.Species != pkm.Species;
|
||||
}
|
||||
|
||||
private static bool GetIsDeferredWC7(PKM pkm, WC7 wc)
|
||||
{
|
||||
if (wc.RestrictLanguage != 0 && wc.RestrictLanguage != pkm.Language)
|
||||
|
@ -423,6 +448,7 @@ namespace PKHeX.Core
|
|||
|
||||
// Utility
|
||||
private static readonly PGT RangerManaphy = new PGT {Data = {[0] = 7, [8] = 1}};
|
||||
|
||||
private static bool IsRangerManaphy(PKM pkm)
|
||||
{
|
||||
var egg = pkm.Egg_Location;
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace PKHeX.Core
|
|||
didPeek = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the enumerator to its initial position, which is before the first element in the collection.
|
||||
/// </summary>
|
||||
|
@ -69,6 +70,7 @@ namespace PKHeX.Core
|
|||
|
||||
return peek;
|
||||
}
|
||||
|
||||
public T PeekOrDefault() => !TryFetchPeek() ? default(T) : peek;
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace PKHeX.Core
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static EncounterStatic GetSuggestedEncounterEgg(PKM pkm, int loc = -1)
|
||||
{
|
||||
int lvl = GetSuggestedEncounterEggMetLevel(pkm);
|
||||
|
@ -73,6 +74,7 @@ namespace PKHeX.Core
|
|||
Level = first.LevelMin,
|
||||
};
|
||||
}
|
||||
|
||||
private static EncounterStatic GetSuggestedEncounterStatic(EncounterStatic s, int loc = -1)
|
||||
{
|
||||
if (loc == -1)
|
||||
|
@ -143,6 +145,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the correct Transfer Met location for the origin game.
|
||||
/// </summary>
|
||||
|
|
|
@ -28,6 +28,7 @@ namespace PKHeX.Core
|
|||
Parse.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private IEncounterable _match;
|
||||
|
||||
/// <summary>Indicates whether or not the <see cref="PKM"/> originated from <see cref="GameVersion.XD"/>.</summary>
|
||||
|
@ -71,6 +72,7 @@ namespace PKHeX.Core
|
|||
|
||||
/// <summary>List of all near-matches that were rejected for a given reason.</summary>
|
||||
public List<EncounterRejected> InvalidMatches;
|
||||
|
||||
internal void Reject(CheckResult c)
|
||||
{
|
||||
(InvalidMatches ?? (InvalidMatches = new List<EncounterRejected>())).Add(new EncounterRejected(EncounterMatch, c));
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace PKHeX.Core
|
|||
{
|
||||
switch (info.EncounterMatch)
|
||||
{
|
||||
case EncounterEgg e: return VerifyEncounterEgg(pkm, e);
|
||||
case EncounterEgg _: return VerifyEncounterEgg(pkm);
|
||||
case EncounterLink l: return VerifyEncounterLink(pkm, l);
|
||||
case EncounterTrade t: return VerifyEncounterTrade(pkm, t);
|
||||
case EncounterSlot w: return VerifyEncounterWild(pkm, w);
|
||||
|
@ -38,13 +38,14 @@ namespace PKHeX.Core
|
|||
return new CheckResult(Severity.Invalid, V80, CheckIdentifier.Encounter);
|
||||
}
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterG12(PKM pkm, LegalInfo info)
|
||||
{
|
||||
var EncounterMatch = info.EncounterMatch;
|
||||
if (EncounterMatch.EggEncounter)
|
||||
{
|
||||
pkm.WasEgg = true;
|
||||
return VerifyEncounterEgg(pkm, EncounterMatch);
|
||||
return VerifyEncounterEgg(pkm);
|
||||
}
|
||||
if (EncounterMatch is EncounterSlot1 l)
|
||||
{
|
||||
|
@ -77,6 +78,7 @@ namespace PKHeX.Core
|
|||
|
||||
return new CheckResult(Severity.Valid, V68, CheckIdentifier.Encounter);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyWildEncounterCrystal(PKM pkm, EncounterSlot encounter)
|
||||
{
|
||||
switch (encounter.Type)
|
||||
|
@ -100,6 +102,7 @@ namespace PKHeX.Core
|
|||
|
||||
return new CheckResult(Severity.Valid, V68, CheckIdentifier.Encounter);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyWildEncounterCrystalHeadbutt(ITrainerID tr, EncounterSlot encounter)
|
||||
{
|
||||
var tree = Encounters2.GetGSCHeadbuttAvailability(encounter, tr.TID);
|
||||
|
@ -115,7 +118,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
|
||||
// Eggs
|
||||
private static CheckResult VerifyEncounterEgg(PKM pkm, IEncounterable egg)
|
||||
private static CheckResult VerifyEncounterEgg(PKM pkm)
|
||||
{
|
||||
pkm.WasEgg = true;
|
||||
// Check Species
|
||||
|
@ -135,10 +138,12 @@ namespace PKHeX.Core
|
|||
return new CheckResult(Severity.Invalid, V51, CheckIdentifier.Encounter);
|
||||
}
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterEgg3(PKM pkm)
|
||||
{
|
||||
return pkm.Format == 3 ? VerifyEncounterEgg3Native(pkm) : VerifyEncounterEgg3Transfer(pkm);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterEgg3Native(PKM pkm)
|
||||
{
|
||||
if (pkm.Met_Level != 0)
|
||||
|
@ -160,6 +165,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return new CheckResult(Severity.Valid, V53, CheckIdentifier.Encounter);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterEgg3Transfer(PKM pkm)
|
||||
{
|
||||
if (pkm.IsEgg)
|
||||
|
@ -175,6 +181,7 @@ namespace PKHeX.Core
|
|||
|
||||
return new CheckResult(Severity.Valid, V53, CheckIdentifier.Encounter);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterEgg4(PKM pkm)
|
||||
{
|
||||
if (pkm.Format == 4)
|
||||
|
@ -189,10 +196,12 @@ namespace PKHeX.Core
|
|||
return new CheckResult(Severity.Invalid, V61, CheckIdentifier.Encounter);
|
||||
return new CheckResult(Severity.Valid, V53, CheckIdentifier.Encounter);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterEgg5(PKM pkm)
|
||||
{
|
||||
return VerifyEncounterEggLevelLoc(pkm, 1, pkm.B2W2 ? Legal.ValidMet_B2W2 : Legal.ValidMet_BW);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterEgg6(PKM pkm)
|
||||
{
|
||||
if (pkm.AO)
|
||||
|
@ -203,6 +212,7 @@ namespace PKHeX.Core
|
|||
|
||||
return VerifyEncounterEggLevelLoc(pkm, 1, Legal.ValidMet_XY);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterEgg7(PKM pkm)
|
||||
{
|
||||
if (pkm.SM)
|
||||
|
@ -213,6 +223,7 @@ namespace PKHeX.Core
|
|||
// no other games
|
||||
return new CheckResult(Severity.Invalid, V51, CheckIdentifier.Encounter);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterEggLevelLoc(PKM pkm, int eggLevel, ICollection<int> MetLocations)
|
||||
{
|
||||
if (pkm.Met_Level != eggLevel)
|
||||
|
@ -221,6 +232,7 @@ namespace PKHeX.Core
|
|||
? new CheckResult(Severity.Valid, V53, CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Invalid, V54, CheckIdentifier.Encounter);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyUnhatchedEgg(PKM pkm, int tradeLoc)
|
||||
{
|
||||
var eggLevel = pkm.Format < 5 ? 0 : 1;
|
||||
|
@ -249,27 +261,34 @@ namespace PKHeX.Core
|
|||
}
|
||||
|
||||
if (slot.Permissions.IsNormalLead)
|
||||
{
|
||||
return slot.Permissions.Pressure
|
||||
? new CheckResult(Severity.Valid, V67, CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Valid, V68, CheckIdentifier.Encounter);
|
||||
}
|
||||
|
||||
// Decreased Level Encounters
|
||||
if (slot.Permissions.WhiteFlute)
|
||||
{
|
||||
return slot.Permissions.Pressure
|
||||
? new CheckResult(Severity.Valid, V69, CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Valid, V70, CheckIdentifier.Encounter);
|
||||
}
|
||||
|
||||
// Increased Level Encounters
|
||||
if (slot.Permissions.BlackFlute)
|
||||
{
|
||||
return slot.Permissions.Pressure
|
||||
? new CheckResult(Severity.Valid, V71, CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Valid, V72, CheckIdentifier.Encounter);
|
||||
}
|
||||
|
||||
if (slot.Permissions.Pressure)
|
||||
return new CheckResult(Severity.Valid, V67, CheckIdentifier.Encounter);
|
||||
|
||||
return new CheckResult(Severity.Valid, V73, CheckIdentifier.Encounter);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterStatic(PKM pkm, EncounterStatic s)
|
||||
{
|
||||
// Check for Unreleased Encounters / Collisions
|
||||
|
@ -301,13 +320,14 @@ namespace PKHeX.Core
|
|||
}
|
||||
if (s.EggEncounter && !pkm.IsEgg) // hatched
|
||||
{
|
||||
var hatchCheck = VerifyEncounterEgg(pkm, null);
|
||||
var hatchCheck = VerifyEncounterEgg(pkm);
|
||||
if (!hatchCheck.Valid)
|
||||
return hatchCheck;
|
||||
}
|
||||
|
||||
return new CheckResult(Severity.Valid, V75, CheckIdentifier.Encounter);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterTrade(PKM pkm, EncounterTrade trade)
|
||||
{
|
||||
if (trade.Species == pkm.Species && trade.EvolveOnTrade)
|
||||
|
@ -321,6 +341,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return new CheckResult(Severity.Valid, V76, CheckIdentifier.Encounter);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterLink(PKM pkm, EncounterLink enc)
|
||||
{
|
||||
// Should NOT be Fateful, and should be in Database
|
||||
|
@ -339,6 +360,7 @@ namespace PKHeX.Core
|
|||
? new CheckResult(Severity.Invalid, V48, CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Valid, V49, CheckIdentifier.Encounter);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterEvent(PKM pkm, MysteryGift MatchedGift)
|
||||
{
|
||||
switch (MatchedGift)
|
||||
|
@ -350,7 +372,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
if (!pkm.IsEgg && MatchedGift.IsEgg) // hatched
|
||||
{
|
||||
var hatchCheck = VerifyEncounterEgg(pkm, null);
|
||||
var hatchCheck = VerifyEncounterEgg(pkm);
|
||||
if (!hatchCheck.Valid)
|
||||
return hatchCheck;
|
||||
}
|
||||
|
|
|
@ -39,15 +39,20 @@ namespace PKHeX.Core
|
|||
public static int GetSuggestedLanguage(this MysteryGiftRestriction value)
|
||||
{
|
||||
for (int i = (int)LanguageID.Japanese; i <= (int)LanguageID.Korean; i++)
|
||||
{
|
||||
if (value.HasFlagFast((MysteryGiftRestriction)(1 << i)))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static int GetSuggestedRegion(this MysteryGiftRestriction value)
|
||||
{
|
||||
for (int i = (int)RegionID.Japan; i <= (int)RegionID.Taiwan; i++)
|
||||
{
|
||||
if (value.HasFlagFast((MysteryGiftRestriction)((int)MysteryGiftRestriction.RegionBase << i)))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace PKHeX.Core
|
|||
public static class MysteryGiftVerifier
|
||||
{
|
||||
private static readonly Dictionary<int, MysteryGiftRestriction>[] RestrictionSet = Get();
|
||||
|
||||
private static Dictionary<int, MysteryGiftRestriction>[] Get()
|
||||
{
|
||||
var s = new Dictionary<int, MysteryGiftRestriction>[PKX.Generation + 1];
|
||||
|
@ -16,6 +17,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
|
||||
private static string RestrictionSetName(int i) => $"mgrestrict{i}.pkl";
|
||||
|
||||
private static Dictionary<int, MysteryGiftRestriction> GetRestriction(int generation)
|
||||
{
|
||||
var resource = RestrictionSetName(generation);
|
||||
|
|
|
@ -66,6 +66,7 @@ namespace PKHeX.Core
|
|||
pkm.TradebackStatus = defaultTradeback;
|
||||
return res;
|
||||
}
|
||||
|
||||
private static CheckMoveResult[] ParseMovesForSmeargle(PKM pkm, int[] Moves, LegalInfo info)
|
||||
{
|
||||
if (!pkm.IsEgg)
|
||||
|
@ -78,17 +79,19 @@ namespace PKHeX.Core
|
|||
var source = new MoveParseSource { CurrentMoves = pkm.Moves, };
|
||||
return ParseMoves(pkm, source, info);
|
||||
}
|
||||
|
||||
private static CheckMoveResult[] ParseMovesIsEggPreRelearn(PKM pkm, int[] Moves, int[] SpecialMoves, EncounterEgg e)
|
||||
{
|
||||
EggInfoSource infoset = new EggInfoSource(pkm, SpecialMoves, e);
|
||||
return VerifyPreRelearnEggBase(pkm, Moves, infoset);
|
||||
}
|
||||
|
||||
private static CheckMoveResult[] ParseMovesWasEggPreRelearn(PKM pkm, int[] Moves, LegalInfo info, EncounterEgg e)
|
||||
{
|
||||
var EventEggMoves = GetSpecialMoves(info.EncounterMatch);
|
||||
// Level up moves could not be inherited if Ditto is parent,
|
||||
// that means genderless species and male only species except Nidoran and Volbeat (they breed with female nidoran and illumise) could not have level up moves as an egg
|
||||
var AllowLevelUp = pkm.PersonalInfo.Gender > 0 && pkm.PersonalInfo.Gender < 255 || Legal.MixedGenderBreeding.Contains(e.Species);
|
||||
var AllowLevelUp = (pkm.PersonalInfo.Gender > 0 && pkm.PersonalInfo.Gender < 255) || Legal.MixedGenderBreeding.Contains(e.Species);
|
||||
int BaseLevel = AllowLevelUp ? 100 : e.LevelMin;
|
||||
var LevelUp = Legal.GetBaseEggMoves(pkm, e.Species, e.Version, BaseLevel);
|
||||
|
||||
|
@ -116,15 +119,20 @@ namespace PKHeX.Core
|
|||
};
|
||||
return ParseMoves(pkm, source, info);
|
||||
}
|
||||
|
||||
private static CheckMoveResult[] ParseMovesSketch(PKM pkm, int[] Moves)
|
||||
{
|
||||
CheckMoveResult[] res = new CheckMoveResult[4];
|
||||
var res = new CheckMoveResult[4];
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
res[i] = Legal.InvalidSketch.Contains(Moves[i])
|
||||
? new CheckMoveResult(MoveSource.Unknown, pkm.Format, Severity.Invalid, V166, CheckIdentifier.Move)
|
||||
: new CheckMoveResult(MoveSource.Sketch, pkm.Format, CheckIdentifier.Move);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private static CheckMoveResult[] ParseMoves3DS(PKM pkm, int[] Moves, LegalInfo info)
|
||||
{
|
||||
info.EncounterMoves.Relearn = info.Generation >= 6 ? pkm.RelearnMoves : Array.Empty<int>();
|
||||
|
@ -134,6 +142,7 @@ namespace PKHeX.Core
|
|||
// Everything else
|
||||
return ParseMovesRelearn(pkm, Moves, info);
|
||||
}
|
||||
|
||||
private static CheckMoveResult[] ParseMovesPre3DS(PKM pkm, int[] Moves, LegalInfo info)
|
||||
{
|
||||
if (pkm.IsEgg && info.EncounterMatch is EncounterEgg egg)
|
||||
|
@ -143,12 +152,12 @@ namespace PKHeX.Core
|
|||
}
|
||||
if (info.EncounterMatch is EncounterEgg e)
|
||||
return ParseMovesWasEggPreRelearn(pkm, Moves, info, e);
|
||||
if (info.Generation <= 2 &&
|
||||
info.EncounterMatch is IGeneration g && (g.Generation == 1 || g.Generation == 2 && !Legal.AllowGen2MoveReminder(pkm))) // fixed encounter moves without relearning
|
||||
if (info.Generation <= 2 && info.EncounterMatch is IGeneration g && (g.Generation == 1 || (g.Generation == 2 && !Legal.AllowGen2MoveReminder(pkm)))) // fixed encounter moves without relearning
|
||||
return ParseMovesGenGB(pkm, Moves, info);
|
||||
|
||||
return ParseMovesSpecialMoveset(pkm, Moves, info);
|
||||
}
|
||||
|
||||
private static CheckMoveResult[] ParseMovesGenGB(PKM pkm, int[] Moves, LegalInfo info)
|
||||
{
|
||||
CheckMoveResult[] res = new CheckMoveResult[4];
|
||||
|
@ -177,6 +186,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private static CheckMoveResult[] ParseMovesSpecialMoveset(PKM pkm, int[] Moves, LegalInfo info)
|
||||
{
|
||||
var source = new MoveParseSource
|
||||
|
@ -186,12 +196,14 @@ namespace PKHeX.Core
|
|||
};
|
||||
return ParseMoves(pkm, source, info);
|
||||
}
|
||||
|
||||
private static int[] GetSpecialMoves(IEncounterable EncounterMatch)
|
||||
{
|
||||
if (EncounterMatch is IMoveset mg)
|
||||
return mg.Moves ?? Array.Empty<int>();
|
||||
return Array.Empty<int>();
|
||||
}
|
||||
|
||||
private static CheckMoveResult[] ParseMovesRelearn(PKM pkm, int[] Moves, LegalInfo info)
|
||||
{
|
||||
var source = new MoveParseSource
|
||||
|
@ -207,11 +219,14 @@ namespace PKHeX.Core
|
|||
|
||||
int[] RelearnMoves = pkm.RelearnMoves;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if ((pkm.IsEgg || res[i].Flag) && !RelearnMoves.Contains(Moves[i]))
|
||||
res[i] = new CheckMoveResult(res[i], Severity.Invalid, string.Format(V170, res[i].Comment), res[i].Identifier);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private static CheckMoveResult[] ParseMoves(PKM pkm, MoveParseSource source, LegalInfo info)
|
||||
{
|
||||
CheckMoveResult[] res = new CheckMoveResult[4];
|
||||
|
@ -255,6 +270,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private static void ParseMovesByGeneration(PKM pkm, CheckMoveResult[] res, int gen, LegalInfo info, LearnInfo learnInfo, int last)
|
||||
{
|
||||
GetHMCompatibility(pkm, res, gen, learnInfo.Source.CurrentMoves, out bool[] HMLearned, out bool KnowDefogWhirlpool);
|
||||
|
@ -283,6 +299,7 @@ namespace PKHeX.Core
|
|||
if (Legal.SpeciesEvolutionWithMove.Contains(pkm.Species))
|
||||
ParseEvolutionLevelupMove(pkm, res, learnInfo.Source.CurrentMoves, learnInfo.IncenseMoves, info);
|
||||
}
|
||||
|
||||
private static void ParseMovesByGeneration(PKM pkm, IList<CheckMoveResult> res, int gen, LegalInfo info, LearnInfo learnInfo)
|
||||
{
|
||||
var moves = learnInfo.Source.CurrentMoves;
|
||||
|
@ -332,6 +349,7 @@ namespace PKHeX.Core
|
|||
pkm.TradebackStatus = TradebackType.WasTradeback;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ParseMovesByGeneration12(PKM pkm, CheckMoveResult[] res, int[] moves, int gen, LegalInfo info, LearnInfo learnInfo)
|
||||
{
|
||||
// Mark the gen 1 exclusive moves as illegal because the pokemon also have Non tradeback egg moves.
|
||||
|
@ -350,12 +368,14 @@ namespace PKHeX.Core
|
|||
ParseEvolutionsIncompatibleMoves(pkm, res, moves, info.EncounterMoves.TMHMMoves[1]);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ParseMovesByGenerationLast(PKM pkm, CheckMoveResult[] res, int gen, LearnInfo learnInfo)
|
||||
{
|
||||
ParseEggMovesInherited(pkm, res, gen, learnInfo);
|
||||
ParseEggMoves(pkm, res, gen, learnInfo);
|
||||
ParseEggMovesRemaining(pkm, res, learnInfo);
|
||||
}
|
||||
|
||||
private static void ParseEggMovesInherited(PKM pkm, CheckMoveResult[] res, int gen, LearnInfo learnInfo)
|
||||
{
|
||||
var moves = learnInfo.Source.CurrentMoves;
|
||||
|
@ -376,12 +396,15 @@ namespace PKHeX.Core
|
|||
learnInfo.MixedGen12NonTradeback = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
res[m] = new CheckMoveResult(MoveSource.InheritLevelUp, gen, Severity.Valid, V345, CheckIdentifier.Move);
|
||||
}
|
||||
learnInfo.LevelUpEggMoves.Add(m);
|
||||
if (pkm.TradebackStatus == TradebackType.Any && pkm.GenNumber == 1)
|
||||
pkm.TradebackStatus = TradebackType.WasTradeback;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ParseEggMoves(PKM pkm, CheckMoveResult[] res, int gen, LearnInfo learnInfo)
|
||||
{
|
||||
var moves = learnInfo.Source.CurrentMoves;
|
||||
|
@ -405,7 +428,9 @@ namespace PKHeX.Core
|
|||
learnInfo.MixedGen12NonTradeback = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
res[m] = new CheckMoveResult(MoveSource.EggMove, gen, Severity.Valid, V171, CheckIdentifier.Move) { Flag = true };
|
||||
}
|
||||
|
||||
learnInfo.EggMovesLearned.Add(m);
|
||||
if (pkm.TradebackStatus == TradebackType.Any && pkm.GenNumber == 1)
|
||||
|
@ -422,13 +447,16 @@ namespace PKHeX.Core
|
|||
learnInfo.MixedGen12NonTradeback = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
res[m] = new CheckMoveResult(MoveSource.SpecialEgg, gen, Severity.Valid, V333, CheckIdentifier.Move);
|
||||
}
|
||||
}
|
||||
if (pkm.TradebackStatus == TradebackType.Any && pkm.GenNumber == 1)
|
||||
pkm.TradebackStatus = TradebackType.WasTradeback;
|
||||
learnInfo.EventEggMoves.Add(m);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ParseEggMovesRemaining(PKM pkm, CheckMoveResult[] res, LearnInfo learnInfo)
|
||||
{
|
||||
// A pokemon could have normal egg moves and regular egg moves
|
||||
|
@ -462,14 +490,17 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ParseRedYellowIncompatibleMoves(PKM pkm, IList<CheckMoveResult> res, int[] moves)
|
||||
{
|
||||
var incompatible = GetIncompatibleRBYMoves(pkm, moves);
|
||||
if (incompatible.Count == 0)
|
||||
return;
|
||||
for (int m = 0; m < 4; m++)
|
||||
{
|
||||
if (incompatible.Contains(moves[m]))
|
||||
res[m] = new CheckMoveResult(res[m], Severity.Invalid, V363, CheckIdentifier.Move);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<int> GetIncompatibleRBYMoves(PKM pkm, int[] moves)
|
||||
|
@ -555,6 +586,7 @@ namespace PKHeX.Core
|
|||
res[m] = new CheckMoveResult(res[m], Severity.Invalid, string.Format(V366, currentspecies, previousspecies), CheckIdentifier.Move);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ParseShedinjaEvolveMoves(PKM pkm, IList<CheckMoveResult> res, int[] moves)
|
||||
{
|
||||
var ShedinjaEvoMovesLearned = new List<int>();
|
||||
|
@ -605,17 +637,17 @@ namespace PKHeX.Core
|
|||
res[m] = new CheckMoveResult(res[m], Severity.Invalid, string.Format(V366, SpeciesStrings[290], SpeciesStrings[291]), CheckIdentifier.Move);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ParseEvolutionLevelupMove(PKM pkm, IList<CheckMoveResult> res, int[] moves, List<int> IncenseMovesLearned, LegalInfo info)
|
||||
{
|
||||
// Ignore if there is an invalid move or an empty move, this validation is only for 4 non-empty moves that are all valid, but invalid as a 4 combination
|
||||
// Ignore Mr. Mime and Sudowodoo from generations 1 to 3, they cant be evolved from Bonsly or Munchlax
|
||||
// Ignore if encounter species is the evolution species, the pokemon was not evolved by the player
|
||||
if (!res.All(r => r?.Valid ?? false) || moves.Any(m => m == 0) ||
|
||||
(Legal.BabyEvolutionWithMove.Contains(pkm.Species) && pkm.GenNumber <= 3) ||
|
||||
info.EncounterMatch.Species == pkm.Species)
|
||||
if (!res.All(r => r?.Valid ?? false) || moves.Any(m => m == 0) || (Legal.BabyEvolutionWithMove.Contains(pkm.Species) && pkm.GenNumber <= 3) || info.EncounterMatch.Species == pkm.Species)
|
||||
return;
|
||||
|
||||
var ValidMoves = Legal.GetValidPostEvolutionMoves(pkm, pkm.Species, info.EvoChainsAllGens, GameVersion.Any);
|
||||
|
||||
// Add the evolution moves to valid moves in case some of these moves could not be learned after evolving
|
||||
switch (pkm.Species)
|
||||
{
|
||||
|
@ -649,6 +681,7 @@ namespace PKHeX.Core
|
|||
for (int m = 0; m < 4; m++)
|
||||
res[m] = new CheckMoveResult(res[m], Severity.Invalid, string.Format(V385, SpeciesStrings[pkm.Species]), CheckIdentifier.Move);
|
||||
}
|
||||
|
||||
private static void GetHMCompatibility(PKM pkm, IReadOnlyList<CheckResult> res, int gen, IReadOnlyList<int> moves, out bool[] HMLearned, out bool KnowDefogWhirlpool)
|
||||
{
|
||||
HMLearned = new bool[4];
|
||||
|
@ -669,9 +702,11 @@ namespace PKHeX.Core
|
|||
flags[i] = IsCheckInvalid(res[i]) && source.Contains(moves[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsDefogWhirl(int move) => move == 250 || move == 432;
|
||||
private static bool IsCheckInvalid(CheckResult chk) => !(chk?.Valid ?? false);
|
||||
private static bool IsCheckValid(CheckResult chk) => chk?.Valid ?? false;
|
||||
|
||||
private static void FlagIncompatibleTransferHMs(CheckMoveResult[] res, int[] moves, int gen, bool[] HMLearned, bool KnowDefogWhirlpool)
|
||||
{
|
||||
// After all the moves from the generations 3 and 4,
|
||||
|
@ -682,15 +717,21 @@ namespace PKHeX.Core
|
|||
{
|
||||
int invalidCount = moves.Where((m, i) => IsDefogWhirl(m) && IsCheckValid(res[i])).Count();
|
||||
if (invalidCount == 2) // can't know both at the same time
|
||||
{
|
||||
for (int i = 0; i < 4; i++) // flag both moves
|
||||
{
|
||||
if (IsDefogWhirl(moves[i]))
|
||||
res[i] = new CheckMoveResult(res[i], Severity.Invalid, V338, CheckIdentifier.Move);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Flag moves that are only legal when learned from a past-gen HM source
|
||||
for (int i = 0; i < HMLearned.Length; i++)
|
||||
{
|
||||
if (HMLearned[i] && IsCheckValid(res[i]))
|
||||
res[i] = new CheckMoveResult(res[i], Severity.Invalid, string.Format(V339, gen, gen + 1), CheckIdentifier.Move);
|
||||
}
|
||||
}
|
||||
|
||||
/* Similar to verifyRelearnEgg but in pre relearn generation is the moves what should match the expected order but only if the pokemon is inside an egg */
|
||||
|
@ -766,6 +807,7 @@ namespace PKHeX.Core
|
|||
|
||||
return res;
|
||||
}
|
||||
|
||||
private static int GetRequiredBaseMoveCount(int[] Moves, EggInfoSource infoset)
|
||||
{
|
||||
int baseCt = infoset.Base.Count;
|
||||
|
@ -796,6 +838,7 @@ namespace PKHeX.Core
|
|||
res[i] = new CheckMoveResult(res[i], Severity.Invalid, V168, res[i].Identifier);
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateGen1LevelUpMoves(PKM pkm, ValidEncounterMoves EncounterMoves, int defaultLvlG1, int generation, LegalInfo info)
|
||||
{
|
||||
switch (generation)
|
||||
|
@ -808,6 +851,7 @@ namespace PKHeX.Core
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateGen2LevelUpMoves(PKM pkm, ValidEncounterMoves EncounterMoves, int defaultLvlG2, int generation, LegalInfo info)
|
||||
{
|
||||
switch (generation)
|
||||
|
@ -820,6 +864,7 @@ namespace PKHeX.Core
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static int[] GetGenMovesCheckOrder(PKM pkm)
|
||||
{
|
||||
if (pkm.Format < 3)
|
||||
|
@ -829,6 +874,7 @@ namespace PKHeX.Core
|
|||
|
||||
return GetGenMovesOrder(pkm.Format, pkm.GenNumber);
|
||||
}
|
||||
|
||||
private static int[] GetGenMovesOrderVC(PKM pkm)
|
||||
{
|
||||
// VC case: check transfer games in reverse order (8, 7..) then past games.
|
||||
|
@ -839,12 +885,14 @@ namespace PKHeX.Core
|
|||
past.CopyTo(xfer, end);
|
||||
return xfer;
|
||||
}
|
||||
|
||||
private static int[] GetGenMovesCheckOrderGB(PKM pkm, int originalGeneration)
|
||||
{
|
||||
if (originalGeneration == 2)
|
||||
return pkm.Korean ? new[] {2} : new[] {2, 1};
|
||||
return new[] {1, 2}; // RBY
|
||||
}
|
||||
|
||||
private static int[] GetGenMovesOrder(int start, int end)
|
||||
{
|
||||
if (end < 0)
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace PKHeX.Core
|
|||
return VerifyRelearnSpecifiedMoveset(pkm, info, l.RelearnMoves);
|
||||
case MysteryGift g:
|
||||
return VerifyRelearnSpecifiedMoveset(pkm, info, g.RelearnMoves);
|
||||
case EncounterStatic s:
|
||||
case EncounterStatic s when s.Relearn.Length > 0:
|
||||
return VerifyRelearnSpecifiedMoveset(pkm, info, s.Relearn);
|
||||
case EncounterEgg e:
|
||||
return VerifyRelearnEggBase(pkm, info, e);
|
||||
|
@ -36,16 +36,18 @@ namespace PKHeX.Core
|
|||
{
|
||||
CheckResult[] res = new CheckResult[4];
|
||||
int[] RelearnMoves = pkm.RelearnMoves;
|
||||
// Get gifts that match
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
res[i] = moves[i] != RelearnMoves[i]
|
||||
? new CheckResult(Severity.Invalid, string.Format(V178, MoveStrings[moves[i]]), CheckIdentifier.RelearnMove)
|
||||
: new CheckResult(CheckIdentifier.RelearnMove);
|
||||
}
|
||||
|
||||
info.RelearnBase = moves;
|
||||
return res;
|
||||
}
|
||||
|
||||
private static CheckResult[] VerifyRelearnDexNav(PKM pkm, LegalInfo info)
|
||||
{
|
||||
CheckResult[] res = new CheckResult[4];
|
||||
|
@ -58,9 +60,11 @@ namespace PKHeX.Core
|
|||
|
||||
// All other relearn moves must be empty.
|
||||
for (int i = 1; i < 4; i++)
|
||||
{
|
||||
res[i] = RelearnMoves[i] != 0
|
||||
? new CheckResult(Severity.Invalid, V184, CheckIdentifier.RelearnMove)
|
||||
: new CheckResult(CheckIdentifier.RelearnMove);
|
||||
}
|
||||
|
||||
// Update the relearn base moves if the first relearn move is okay.
|
||||
info.RelearnBase = res[0].Valid
|
||||
|
@ -69,6 +73,7 @@ namespace PKHeX.Core
|
|||
|
||||
return res;
|
||||
}
|
||||
|
||||
private static CheckResult[] VerifyRelearnNone(PKM pkm, LegalInfo info)
|
||||
{
|
||||
CheckResult[] res = new CheckResult[4];
|
||||
|
@ -76,13 +81,16 @@ namespace PKHeX.Core
|
|||
|
||||
// No relearn moves should be present.
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
res[i] = RelearnMoves[i] != 0
|
||||
? new CheckResult(Severity.Invalid, V184, CheckIdentifier.RelearnMove)
|
||||
: new CheckResult(CheckIdentifier.RelearnMove);
|
||||
}
|
||||
|
||||
info.RelearnBase = new int[4];
|
||||
return res;
|
||||
}
|
||||
|
||||
private static CheckResult[] VerifyRelearnEggBase(PKM pkm, LegalInfo info, EncounterEgg e)
|
||||
{
|
||||
int[] RelearnMoves = pkm.RelearnMoves;
|
||||
|
@ -118,6 +126,7 @@ namespace PKHeX.Core
|
|||
info.RelearnBase = baseMoves;
|
||||
return res;
|
||||
}
|
||||
|
||||
private static void FlagBaseEggMoves(CheckResult[] res, int required, IReadOnlyList<int> baseMoves, IReadOnlyList<int> RelearnMoves)
|
||||
{
|
||||
for (int i = 0; i < required; i++)
|
||||
|
@ -130,6 +139,7 @@ namespace PKHeX.Core
|
|||
res[i] = new CheckResult(Severity.Valid, V179, CheckIdentifier.RelearnMove);
|
||||
}
|
||||
}
|
||||
|
||||
private static void FlagRelearnMovesMissing(CheckResult[] res, int required, IReadOnlyList<int> baseMoves, int start)
|
||||
{
|
||||
for (int z = start; z < required; z++)
|
||||
|
@ -139,6 +149,7 @@ namespace PKHeX.Core
|
|||
string em = string.Join(", ", GetMoveNames(baseMoves));
|
||||
res[required - 1].Comment += string.Format(Environment.NewLine + V181, em);
|
||||
}
|
||||
|
||||
private static bool FlagInvalidInheritedMoves(CheckResult[] res, int required, IReadOnlyList<int> RelearnMoves, IReadOnlyList<int> inheritMoves, IReadOnlyList<int> splitMoves)
|
||||
{
|
||||
bool splitInvalid = false;
|
||||
|
@ -157,6 +168,7 @@ namespace PKHeX.Core
|
|||
|
||||
return splitInvalid;
|
||||
}
|
||||
|
||||
private static void FlagSplitbreedMoves(CheckResult[] res, int required, EncounterEgg e, PKM pkm)
|
||||
{
|
||||
var other = e is EncounterEggSplit x ? x.OtherSpecies : Legal.GetBaseEggSpecies(pkm, 1);
|
||||
|
|
|
@ -7,107 +7,133 @@
|
|||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM.Moves"/>.
|
||||
/// </summary>
|
||||
Move,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM.RelearnMoves"/>.
|
||||
/// </summary>
|
||||
RelearnMove,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM"/>'s matched encounter information.
|
||||
/// </summary>
|
||||
Encounter,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM.IsShiny"/> status.
|
||||
/// </summary>
|
||||
Shiny,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM.EncryptionConstant"/>.
|
||||
/// </summary>
|
||||
EC,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM.PID"/>.
|
||||
/// </summary>
|
||||
PID,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM.Gender"/>.
|
||||
/// </summary>
|
||||
Gender,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM.EVs"/>.
|
||||
/// </summary>
|
||||
EVs,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM.Language"/>.
|
||||
/// </summary>
|
||||
Language,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM.Nickname"/>.
|
||||
/// </summary>
|
||||
Nickname,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM.OT_Name"/>, <see cref="PKM.TID"/>, or <see cref="PKM.SID"/>.
|
||||
/// </summary>
|
||||
Trainer,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM.IVs"/>.
|
||||
/// </summary>
|
||||
IVs,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM.Met_Level"/> or <see cref="PKM.CurrentLevel"/>.
|
||||
/// </summary>
|
||||
Level,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM.Ball"/>.
|
||||
/// </summary>
|
||||
Ball,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM"/> memory data.
|
||||
/// </summary>
|
||||
Memory,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM"/> geography data.
|
||||
/// </summary>
|
||||
Geography,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM.AltForm"/>.
|
||||
/// </summary>
|
||||
Form,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM.IsEgg"/> status.
|
||||
/// </summary>
|
||||
Egg,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM"/> miscellaneous properties.
|
||||
/// </summary>
|
||||
Misc,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM.FatefulEncounter"/>.
|
||||
/// </summary>
|
||||
Fateful,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM"/> ribbon data.
|
||||
/// </summary>
|
||||
Ribbon,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM"/> super training data.
|
||||
/// </summary>
|
||||
Training,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM.Ability"/>.
|
||||
/// </summary>
|
||||
Ability,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM"/> evolution chain relative to the matched encounter.
|
||||
/// </summary>
|
||||
Evolution,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM.Nature"/>.
|
||||
/// </summary>
|
||||
Nature,
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CheckResult"/> pertains to the <see cref="PKM"/>'s <see cref="PKM.Version"/> compatibility.
|
||||
/// <remarks>This is used for parsing checks to ensure the <see cref="PKM"/> didn't debut on a future <see cref="PKM.GenNumber"/></remarks>
|
||||
/// </summary>
|
||||
GameOrigin,
|
||||
|
||||
/// <summary>
|
||||
/// The CheckResult pertains to the <see cref="PKM.HeldItem"/>.
|
||||
/// </summary>
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace PKHeX.Core
|
|||
internal static class EncounterTimeExtension
|
||||
{
|
||||
internal static bool Contains(this EncounterTime t1, int t2) => t1 == EncounterTime.Any || (t1 & (EncounterTime)(1 << t2)) != 0;
|
||||
|
||||
internal static int RandomValidTime(this EncounterTime t1)
|
||||
{
|
||||
int val = Util.Rand.Next(1, 4);
|
||||
|
|
|
@ -14,70 +14,87 @@ namespace PKHeX.Core
|
|||
/// Default (un-assigned) encounter slot type.
|
||||
/// </summary>
|
||||
Any = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via Grass.
|
||||
/// </summary>
|
||||
Grass = 1 << 00,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via Surfing.
|
||||
/// </summary>
|
||||
Surf = 1 << 01,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via Old Rod (Fishing).
|
||||
/// </summary>
|
||||
Old_Rod = 1 << 02,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via Good Rod (Fishing).
|
||||
/// </summary>
|
||||
Good_Rod = 1 << 03,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via Super Rod (Fishing).
|
||||
/// </summary>
|
||||
Super_Rod = 1 << 04,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via Rock Smash.
|
||||
/// </summary>
|
||||
Rock_Smash = 1 << 05,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via a Horde.
|
||||
/// </summary>
|
||||
Horde = 1 << 06,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via the Friend Safari.
|
||||
/// </summary>
|
||||
FriendSafari = 1 << 07,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered through special means. Used to signify special slots for Gen2, sometimes for later follow-up).
|
||||
/// </summary>
|
||||
Special = 1 << 08,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via SOS signal.
|
||||
/// </summary>
|
||||
SOS = 1 << 09,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered in a Swarm.
|
||||
/// </summary>
|
||||
Swarm = 1 << 10,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via Headbutt.
|
||||
/// </summary>
|
||||
Headbutt = 1 << 11,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via the Poké Radar.
|
||||
/// </summary>
|
||||
Pokeradar = 1 << 12,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via a Honey Tree.
|
||||
/// </summary>
|
||||
HoneyTree = 1 << 13,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via a Hidden Grotto.
|
||||
/// </summary>
|
||||
HiddenGrotto = 1 << 14,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered via the Bug Catching Contest.
|
||||
/// </summary>
|
||||
BugContest = 1 << 15,
|
||||
|
||||
/// <summary>
|
||||
/// Slot is encountered in the Safari Zone.
|
||||
/// </summary>
|
||||
|
@ -103,10 +120,12 @@ namespace PKHeX.Core
|
|||
public static partial class Extensions
|
||||
{
|
||||
internal static bool IsSafariType(this SlotType t) => (t & SlotType.Safari) != 0;
|
||||
|
||||
internal static bool IsFishingRodType(this SlotType t)
|
||||
{
|
||||
return (t & SlotType.Old_Rod) != 0 || (t & SlotType.Good_Rod) != 0 || (t & SlotType.Super_Rod) != 0;
|
||||
}
|
||||
|
||||
internal static bool IsSweetScentType(this SlotType t)
|
||||
{
|
||||
return !(t.IsFishingRodType() || (t & SlotType.Rock_Smash) != 0);
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace PKHeX.Core
|
|||
public static class EvolutionChain
|
||||
{
|
||||
private static readonly List<EvoCriteria> NONE = new List<EvoCriteria>(0);
|
||||
|
||||
internal static IReadOnlyList<EvoCriteria>[] GetEvolutionChainsAllGens(PKM pkm, IEncounterable Encounter)
|
||||
{
|
||||
var CompleteEvoChain = GetEvolutionChain(pkm, Encounter, pkm.Species, pkm.CurrentLevel);
|
||||
|
@ -150,10 +151,13 @@ namespace PKHeX.Core
|
|||
internal static int GetEvoChainSpeciesIndex(IReadOnlyList<EvoCriteria> chain, int species)
|
||||
{
|
||||
for (int i = 0; i < chain.Count; i++)
|
||||
{
|
||||
if (chain[i].Species == species)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static List<EvoCriteria> GetEvolutionChain(PKM pkm, IEncounterable Encounter, int maxspec, int maxlevel)
|
||||
{
|
||||
var vs = GetValidPreEvolutions(pkm);
|
||||
|
@ -231,16 +235,22 @@ namespace PKHeX.Core
|
|||
if (lvl < 0)
|
||||
lvl = pkm.CurrentLevel;
|
||||
if (pkm.IsEgg && !skipChecks)
|
||||
{
|
||||
return new List<EvoCriteria>
|
||||
{
|
||||
new EvoCriteria { Species = pkm.Species, Level = lvl, MinLevel = lvl },
|
||||
};
|
||||
}
|
||||
|
||||
if (pkm.Species == 292 && lvl >= 20 && (!pkm.HasOriginalMetLocation || pkm.Met_Level + 1 <= lvl))
|
||||
{
|
||||
return new List<EvoCriteria>
|
||||
{
|
||||
new EvoCriteria { Species = 292, Level = lvl, MinLevel = 20 },
|
||||
new EvoCriteria { Species = 290, Level = lvl, MinLevel = 1 }
|
||||
};
|
||||
}
|
||||
|
||||
if (maxspeciesorigin == -1 && pkm.InhabitedGeneration(2) && pkm.Format <= 2 && pkm.GenNumber == 1)
|
||||
maxspeciesorigin = MaxSpeciesID_2;
|
||||
|
||||
|
@ -248,6 +258,7 @@ namespace PKHeX.Core
|
|||
var et = EvolutionTree.GetEvolutionTree(tree);
|
||||
return et.GetValidPreEvolutions(pkm, maxLevel: lvl, maxSpeciesOrigin: maxspeciesorigin, skipChecks: skipChecks);
|
||||
}
|
||||
|
||||
private static int GetMinLevelGeneration(PKM pkm, int generation)
|
||||
{
|
||||
if (!pkm.InhabitedGeneration(generation))
|
||||
|
|
|
@ -14,14 +14,17 @@ namespace PKHeX.Core
|
|||
{
|
||||
int matchChain = -1;
|
||||
for (int i = 0; i < Chain.Count; i++)
|
||||
{
|
||||
if (Chain[i].StageEntryMethods.Any(e => e.Species == entry.Species))
|
||||
matchChain = i;
|
||||
}
|
||||
|
||||
if (matchChain != -1)
|
||||
Chain[matchChain].StageEntryMethods.Add(entry);
|
||||
else
|
||||
Chain.Insert(0, new EvolutionStage { StageEntryMethods = new List<EvolutionMethod> {entry}});
|
||||
}
|
||||
|
||||
public void Insert(EvolutionStage evo)
|
||||
{
|
||||
Chain.Insert(0, evo);
|
||||
|
@ -71,6 +74,7 @@ namespace PKHeX.Core
|
|||
last.RequiresLvlUp = false;
|
||||
return dl;
|
||||
}
|
||||
|
||||
private static void UpdateMinValues(IReadOnlyList<EvoCriteria> dl, EvolutionMethod evo)
|
||||
{
|
||||
var last = dl[dl.Count - 1];
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
|
@ -17,7 +18,7 @@ namespace PKHeX.Core
|
|||
public bool RequiresLevelUp;
|
||||
|
||||
internal static readonly HashSet<int> TradeMethods = new HashSet<int> {5, 6, 7};
|
||||
private static readonly IReadOnlyCollection<GameVersion> NoBanlist = new GameVersion[0];
|
||||
private static readonly IReadOnlyCollection<GameVersion> NoBanlist = Array.Empty<GameVersion>();
|
||||
internal static readonly IReadOnlyCollection<GameVersion> BanSM = new[] {GameVersion.SN, GameVersion.MN};
|
||||
internal IReadOnlyCollection<GameVersion> Banlist = NoBanlist;
|
||||
|
||||
|
@ -25,8 +26,10 @@ namespace PKHeX.Core
|
|||
{
|
||||
RequiresLevelUp = false;
|
||||
if (Form > -1)
|
||||
{
|
||||
if (!skipChecks && pkm.AltForm != Form)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!skipChecks && Banlist.Contains((GameVersion)pkm.Version) && pkm.IsUntraded) // sm lacks usum kantonian evos
|
||||
return false;
|
||||
|
@ -68,7 +71,7 @@ namespace PKHeX.Core
|
|||
case 37: // Daytime on Version
|
||||
case 38: // Nighttime on Version
|
||||
// Version checks come in pairs, check for any pair match
|
||||
if ((pkm.Version & 1) != (Argument & 1) && pkm.IsUntraded || skipChecks)
|
||||
if (((pkm.Version & 1) != (Argument & 1) && pkm.IsUntraded) || skipChecks)
|
||||
return skipChecks;
|
||||
goto default;
|
||||
|
||||
|
|
|
@ -181,6 +181,7 @@ namespace PKHeX.Core
|
|||
return pkm.Species;
|
||||
return Personal.GetFormeIndex(pkm.Species, pkm.AltForm);
|
||||
}
|
||||
|
||||
private int GetIndex(EvolutionMethod evo)
|
||||
{
|
||||
int evolvesToSpecies = evo.Species;
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace PKHeX.Core
|
|||
Levels = levels.ToArray();
|
||||
Count = Moves.Length;
|
||||
}
|
||||
|
||||
public static Learnset[] GetArray(byte[] input, int maxSpecies)
|
||||
{
|
||||
var data = new Learnset[maxSpecies + 1];
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
|
@ -15,6 +14,7 @@ namespace PKHeX.Core
|
|||
public MoveParseSource Source { get; set; }
|
||||
|
||||
public readonly bool IsGen2Pkm;
|
||||
|
||||
public LearnInfo(PKM pkm)
|
||||
{
|
||||
IsGen2Pkm = pkm.Format == 2 || pkm.VC2;
|
||||
|
@ -25,6 +25,7 @@ namespace PKHeX.Core
|
|||
{
|
||||
public readonly GameVersion Game;
|
||||
public readonly int Level;
|
||||
|
||||
public LearnVersion(int lv, GameVersion game = GameVersion.Any)
|
||||
{
|
||||
Game = game;
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace PKHeX.Core
|
|||
private readonly GameVersion Version;
|
||||
private readonly PersonalTable Table;
|
||||
private readonly Learnset[] Learn;
|
||||
|
||||
public LearnLookup(PersonalTable table, Learnset[] learn, GameVersion version)
|
||||
{
|
||||
Version = version;
|
||||
|
@ -26,22 +27,26 @@ namespace PKHeX.Core
|
|||
return moves;
|
||||
return Learn[index].AddMoves(moves, max, min);
|
||||
}
|
||||
|
||||
public List<int> AddMoves(List<int> moves, int species, int form, int max, int min = 0)
|
||||
{
|
||||
int index = Table.GetFormeIndex(species, form);
|
||||
return AddMovesIndex(moves, index, max, min);
|
||||
}
|
||||
|
||||
public List<int> AddMoves1(List<int> moves, int species, int form, int max, int min)
|
||||
{
|
||||
int index = Table.GetFormeIndex(species, form);
|
||||
return AddMovesIndex1(moves, index, max, min);
|
||||
}
|
||||
|
||||
public List<int> AddMovesIndex1(List<int> moves, int index, int max, int min)
|
||||
{
|
||||
if (min == 1)
|
||||
moves.AddRange(((PersonalInfoG1)Table[index]).Moves);
|
||||
return AddMovesIndex(moves, index, max, min);
|
||||
}
|
||||
|
||||
public List<int> GetMoves(int species, int form, int min, int max)
|
||||
{
|
||||
int index = Table.GetFormeIndex(species, form);
|
||||
|
|
|
@ -9,12 +9,13 @@ namespace PKHeX.Core
|
|||
internal static int[] GetEggMoves(PKM pkm, int species, int formnum, GameVersion version)
|
||||
{
|
||||
int gen = pkm.Format <= 2 || pkm.VC ? 2 : pkm.GenNumber;
|
||||
if (!pkm.InhabitedGeneration(gen, species) || pkm.PersonalInfo.Gender == 255 && !FixedGenderFromBiGender.Contains(species))
|
||||
if (!pkm.InhabitedGeneration(gen, species) || (pkm.PersonalInfo.Gender == 255 && !FixedGenderFromBiGender.Contains(species)))
|
||||
return Array.Empty<int>();
|
||||
if (version == GameVersion.Any)
|
||||
version = (GameVersion)pkm.Version;
|
||||
return GetEggMoves(gen, species, formnum, version);
|
||||
}
|
||||
|
||||
private static int[] GetEggMoves(int gen, int species, int formnum, GameVersion version)
|
||||
{
|
||||
switch (gen)
|
||||
|
|
|
@ -77,6 +77,7 @@ namespace PKHeX.Core
|
|||
|
||||
return LearnNONE;
|
||||
}
|
||||
|
||||
private static LearnVersion GetIsLevelUp2(int species, int move, int max, int form, int min, bool korean, GameVersion ver = Any)
|
||||
{
|
||||
// No Korean Crystal
|
||||
|
@ -95,6 +96,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return LearnNONE;
|
||||
}
|
||||
|
||||
private static LearnVersion GetIsLevelUp3(int species, int move, int lvl, int form, GameVersion ver = Any)
|
||||
{
|
||||
if (species == 386)
|
||||
|
@ -116,6 +118,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return LearnNONE;
|
||||
}
|
||||
|
||||
private static LearnVersion GetIsLevelUp4(int species, int move, int lvl, int form, GameVersion ver = Any)
|
||||
{
|
||||
switch (ver)
|
||||
|
@ -140,6 +143,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return LearnNONE;
|
||||
}
|
||||
|
||||
private static LearnVersion GetIsLevelUp5(int species, int form, int move, int lvl, GameVersion ver = Any)
|
||||
{
|
||||
switch (ver)
|
||||
|
@ -156,6 +160,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return LearnNONE;
|
||||
}
|
||||
|
||||
private static LearnVersion GetIsLevelUp6(int species, int move, int lvl, int form, GameVersion ver = Any)
|
||||
{
|
||||
switch (ver)
|
||||
|
@ -173,6 +178,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return LearnNONE;
|
||||
}
|
||||
|
||||
private static LearnVersion GetIsLevelUp7(int species, int move, int form, GameVersion ver = Any)
|
||||
{
|
||||
switch (ver)
|
||||
|
@ -223,17 +229,21 @@ namespace PKHeX.Core
|
|||
return Invalid;
|
||||
}
|
||||
}
|
||||
|
||||
private static Learnset GetDeoxysLearn3(int form, GameVersion ver = Any)
|
||||
{
|
||||
if (ver == Any)
|
||||
switch (form)
|
||||
{
|
||||
case 0: return LevelUpRS[386]; // Normal
|
||||
case 1: return LevelUpFR[386]; // Attack
|
||||
case 2: return LevelUpLG[386]; // Defense
|
||||
case 3: return LevelUpE[386]; // Speed
|
||||
default: return null;
|
||||
switch (form)
|
||||
{
|
||||
case 0: return LevelUpRS[386]; // Normal
|
||||
case 1: return LevelUpFR[386]; // Attack
|
||||
case 2: return LevelUpLG[386]; // Defense
|
||||
case 3: return LevelUpE[386]; // Speed
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
var gen = ver.GetGeneration();
|
||||
if (gen != 3)
|
||||
return GetDeoxysLearn3(form);
|
||||
|
@ -263,6 +273,7 @@ namespace PKHeX.Core
|
|||
{
|
||||
return AddMovesLevelUp1(new List<int>(), ver, species, form, max, min);
|
||||
}
|
||||
|
||||
private static List<int> GetMovesLevelUp2(int species, int form, int max, int min, bool korean, bool removeNewGSCMoves, GameVersion ver = Any)
|
||||
{
|
||||
var moves = AddMovesLevelUp2(new List<int>(), ver, species, form, max, min, korean);
|
||||
|
@ -270,22 +281,27 @@ namespace PKHeX.Core
|
|||
moves.RemoveAll(m => m > MaxMoveID_1);
|
||||
return moves;
|
||||
}
|
||||
|
||||
private static List<int> GetMovesLevelUp3(int species, int form, int max, GameVersion ver = Any)
|
||||
{
|
||||
return AddMovesLevelUp3(new List<int>(), ver, species, max, form);
|
||||
}
|
||||
|
||||
private static List<int> GetMovesLevelUp4(int species, int form, int max, GameVersion ver = Any)
|
||||
{
|
||||
return AddMovesLevelUp4(new List<int>(), ver, species, max, form);
|
||||
}
|
||||
|
||||
private static List<int> GetMovesLevelUp5(int species, int form, int max, GameVersion ver = Any)
|
||||
{
|
||||
return AddMovesLevelUp5(new List<int>(), ver, species, max, form);
|
||||
}
|
||||
|
||||
private static List<int> GetMovesLevelUp6(int species, int form, int max, GameVersion ver = Any)
|
||||
{
|
||||
return AddMovesLevelUp6(new List<int>(), ver, species, max, form);
|
||||
}
|
||||
|
||||
private static List<int> GetMovesLevelUp7(int species, int form, int max, bool MoveReminder, GameVersion ver = Any)
|
||||
{
|
||||
return AddMovesLevelUp7(new List<int>(), ver, species, max, form, MoveReminder);
|
||||
|
@ -306,6 +322,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return moves;
|
||||
}
|
||||
|
||||
private static List<int> AddMovesLevelUp2(List<int> moves, GameVersion ver, int species, int form, int max, int min, bool korean)
|
||||
{
|
||||
switch (ver)
|
||||
|
@ -323,6 +340,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return moves;
|
||||
}
|
||||
|
||||
private static List<int> AddMovesLevelUp3(List<int> moves, GameVersion ver, int species, int max, int form)
|
||||
{
|
||||
if (species == 386)
|
||||
|
@ -347,6 +365,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return moves;
|
||||
}
|
||||
|
||||
private static List<int> AddMovesLevelUp4(List<int> moves, GameVersion ver, int species, int max, int form)
|
||||
{
|
||||
switch (ver)
|
||||
|
@ -367,6 +386,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return moves;
|
||||
}
|
||||
|
||||
private static List<int> AddMovesLevelUp5(List<int> moves, GameVersion ver, int species, int max, int form)
|
||||
{
|
||||
switch (ver)
|
||||
|
@ -382,6 +402,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return moves;
|
||||
}
|
||||
|
||||
private static List<int> AddMovesLevelUp6(List<int> moves, GameVersion ver, int species, int max, int form)
|
||||
{
|
||||
switch (ver)
|
||||
|
@ -397,6 +418,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return moves;
|
||||
}
|
||||
|
||||
private static List<int> AddMovesLevelUp7(List<int> moves, GameVersion ver, int species, int max, int form, bool MoveReminder)
|
||||
{
|
||||
if (MoveReminder)
|
||||
|
@ -442,6 +464,7 @@ namespace PKHeX.Core
|
|||
|
||||
return learn[index].GetEncounterMoves(level, lvl0, start);
|
||||
}
|
||||
|
||||
private static int[] GetEncounterMoves2(int species, int level, GameVersion version)
|
||||
{
|
||||
var learn = GameData.GetLearnsets(version);
|
||||
|
|
|
@ -27,35 +27,43 @@ namespace PKHeX.Core
|
|||
private static GameVersion GetIsMachine1(int species, int move)
|
||||
{
|
||||
for (int i = 0; i < Legal.TMHM_RBY.Length; i++)
|
||||
if (Legal.TMHM_RBY[i] == move)
|
||||
{
|
||||
if (PersonalTable.RB[species].TMHM[i])
|
||||
return GameVersion.RB;
|
||||
if (PersonalTable.Y[species].TMHM[i])
|
||||
return GameVersion.Y;
|
||||
}
|
||||
{
|
||||
if (Legal.TMHM_RBY[i] != move)
|
||||
continue;
|
||||
if (PersonalTable.RB[species].TMHM[i])
|
||||
return GameVersion.RB;
|
||||
if (PersonalTable.Y[species].TMHM[i])
|
||||
return GameVersion.Y;
|
||||
}
|
||||
|
||||
return Legal.NONE;
|
||||
}
|
||||
|
||||
private static GameVersion GetIsMachine2(int species, int move)
|
||||
{
|
||||
for (int i = 0; i < Legal.TMHM_GSC.Length; i++)
|
||||
{
|
||||
if (Legal.TMHM_GSC[i] == move && PersonalTable.C[species].TMHM[i])
|
||||
return GameVersion.GS;
|
||||
}
|
||||
|
||||
return Legal.NONE;
|
||||
}
|
||||
|
||||
private static GameVersion GetIsMachine3(int species, int move, int format, bool RemoveTransfer)
|
||||
{
|
||||
for (int i = 0; i < Legal.TM_3.Length; i++)
|
||||
{
|
||||
if (Legal.TM_3[i] == move && PersonalTable.E[species].TMHM[i])
|
||||
return GameVersion.Gen3;
|
||||
}
|
||||
|
||||
if (!RemoveTransfer && format <= 3)
|
||||
return GetIsMachine3HM(species, move);
|
||||
|
||||
return Legal.NONE;
|
||||
}
|
||||
|
||||
private static GameVersion GetIsMachine3HM(int species, int move)
|
||||
{
|
||||
int x = 0;
|
||||
|
@ -67,17 +75,21 @@ namespace PKHeX.Core
|
|||
}
|
||||
return Legal.NONE;
|
||||
}
|
||||
|
||||
private static GameVersion GetIsMachine4(int species, int move, int format, bool RemoveTransfer, int form)
|
||||
{
|
||||
for (int i = 0; i < Legal.TM_3.Length; i++)
|
||||
{
|
||||
if (Legal.TM_4[i] == move && PersonalTable.HGSS.GetFormeEntry(species, form).TMHM[i])
|
||||
return GameVersion.Gen4;
|
||||
}
|
||||
|
||||
if (RemoveTransfer && format > 4)
|
||||
return GetIsMachine4HMTransfer(species, move, form);
|
||||
|
||||
return GetIsMachine4HM(species, move, form);
|
||||
}
|
||||
|
||||
private static GameVersion GetIsMachine4HMTransfer(int species, int move, int form)
|
||||
{
|
||||
// The combination of both these moves is illegal, it should be checked that the pokemon only learn one
|
||||
|
@ -95,6 +107,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return Legal.NONE;
|
||||
}
|
||||
|
||||
private static GameVersion GetIsMachine4HM(int species, int move, int form)
|
||||
{
|
||||
{
|
||||
|
@ -122,6 +135,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return Legal.NONE;
|
||||
}
|
||||
|
||||
private static GameVersion GetIsMachine5(int species, int move, int form)
|
||||
{
|
||||
for (int i = 0; i < Legal.TMHM_BW.Length; i++)
|
||||
|
@ -129,6 +143,7 @@ namespace PKHeX.Core
|
|||
return PersonalTable.B2W2.GetFormeEntry(species, form).TMHM[i] ? GameVersion.Gen5 : Legal.NONE;
|
||||
return Legal.NONE;
|
||||
}
|
||||
|
||||
private static GameVersion GetIsMachine6(int species, int move, int form, GameVersion ver)
|
||||
{
|
||||
if (GameVersion.XY.Contains(ver))
|
||||
|
@ -149,6 +164,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return Legal.NONE;
|
||||
}
|
||||
|
||||
private static GameVersion GetIsMachine7(int species, int move, int form, GameVersion ver)
|
||||
{
|
||||
if (GameVersion.SM.Contains(ver) && species <= Legal.MaxSpeciesID_7)
|
||||
|
@ -201,6 +217,7 @@ namespace PKHeX.Core
|
|||
r.AddRange(Legal.TMHM_RBY.Where((_, m) => pi_rb.TMHM[m]));
|
||||
r.AddRange(Legal.TMHM_RBY.Where((_, m) => pi_y.TMHM[m]));
|
||||
}
|
||||
|
||||
private static void AddMachine2(List<int> r, int species)
|
||||
{
|
||||
int index = PersonalTable.C.GetFormeIndex(species, 0);
|
||||
|
@ -209,6 +226,7 @@ namespace PKHeX.Core
|
|||
var pi_c = PersonalTable.C[index];
|
||||
r.AddRange(Legal.TMHM_GSC.Where((_, m) => pi_c.TMHM[m]));
|
||||
}
|
||||
|
||||
private static void AddMachine3(List<int> r, int species, int format, bool RemoveTransfer)
|
||||
{
|
||||
int index = PersonalTable.E.GetFormeIndex(species, 0);
|
||||
|
@ -222,6 +240,7 @@ namespace PKHeX.Core
|
|||
else if (format > 3) //Remove HM
|
||||
r.AddRange(Legal.HM_3.Where((_, m) => pi_c.TMHM[m + 50]).Except(Legal.HM_3));
|
||||
}
|
||||
|
||||
private static void AddMachine4(List<int> r, int species, int format, bool RemoveTransfer, int form)
|
||||
{
|
||||
var pi_hgss = PersonalTable.HGSS.GetFormeEntry(species, form);
|
||||
|
@ -243,11 +262,13 @@ namespace PKHeX.Core
|
|||
r.AddRange(Legal.HM_HGSS.Where((_, m) => pi_hgss.TMHM[m + 92]));
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddMachine5(List<int> r, int species, int form)
|
||||
{
|
||||
var pi = PersonalTable.B2W2.GetFormeEntry(species, form);
|
||||
r.AddRange(Legal.TMHM_BW.Where((_, m) => pi.TMHM[m]));
|
||||
}
|
||||
|
||||
private static void AddMachine6(List<int> r, int species, int form, GameVersion ver = GameVersion.Any)
|
||||
{
|
||||
switch (ver)
|
||||
|
@ -267,6 +288,7 @@ namespace PKHeX.Core
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddMachine7(List<int> r, int species, int form, GameVersion ver = GameVersion.Any)
|
||||
{
|
||||
switch (ver)
|
||||
|
@ -287,16 +309,19 @@ namespace PKHeX.Core
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddMachine6XY(List<int> r, int species, int form)
|
||||
{
|
||||
var pi = PersonalTable.XY.GetFormeEntry(species, form);
|
||||
r.AddRange(Legal.TMHM_XY.Where((_, m) => pi.TMHM[m]));
|
||||
}
|
||||
|
||||
private static void AddMachine6AO(List<int> r, int species, int form)
|
||||
{
|
||||
var pi = PersonalTable.AO.GetFormeEntry(species, form);
|
||||
r.AddRange(Legal.TMHM_AO.Where((_, m) => pi.TMHM[m]));
|
||||
}
|
||||
|
||||
private static void AddMachineSM(List<int> r, int species, int form)
|
||||
{
|
||||
if (species > Legal.MaxSpeciesID_7)
|
||||
|
@ -304,6 +329,7 @@ namespace PKHeX.Core
|
|||
var pi = PersonalTable.SM.GetFormeEntry(species, form);
|
||||
r.AddRange(Legal.TMHM_SM.Where((_, m) => pi.TMHM[m]));
|
||||
}
|
||||
|
||||
private static void AddMachineUSUM(List<int> r, int species, int form)
|
||||
{
|
||||
var pi = PersonalTable.USUM.GetFormeEntry(species, form);
|
||||
|
|
|
@ -32,6 +32,7 @@ namespace PKHeX.Core
|
|||
return GameVersion.Stadium;
|
||||
return NONE;
|
||||
}
|
||||
|
||||
private static GameVersion GetIsTutor2(PKM pkm, int species, int move)
|
||||
{
|
||||
if (!AllowGen2Crystal(pkm))
|
||||
|
@ -44,14 +45,17 @@ namespace PKHeX.Core
|
|||
}
|
||||
return GetIsTutor1(pkm, species, move);
|
||||
}
|
||||
|
||||
private static GameVersion GetIsTutor3(int species, int move)
|
||||
{
|
||||
// E Tutors (Free)
|
||||
// E Tutors (BP)
|
||||
var info = PersonalTable.E[species];
|
||||
for (int i = 0; i < Tutor_E.Length; i++)
|
||||
{
|
||||
if (Tutor_E[i] == move && info.TypeTutors[i])
|
||||
return GameVersion.E;
|
||||
}
|
||||
|
||||
// FRLG Tutors
|
||||
// Only special tutor moves, normal tutor moves are already included in Emerald data
|
||||
|
@ -74,60 +78,90 @@ namespace PKHeX.Core
|
|||
|
||||
return NONE;
|
||||
}
|
||||
|
||||
private static GameVersion GetIsTutor4(int species, int form, int move)
|
||||
{
|
||||
var pi = PersonalTable.HGSS.GetFormeEntry(species, form);
|
||||
for (int i = 0; i < Tutors_4.Length; i++)
|
||||
{
|
||||
if (Tutors_4[i] == move && pi.TypeTutors[i])
|
||||
return GameVersion.Gen4;
|
||||
}
|
||||
|
||||
for (int i = 0; i < SpecialTutors_4.Length; i++)
|
||||
{
|
||||
if (SpecialTutors_4[i] == move && SpecialTutors_Compatibility_4[i].Any(e => e == species))
|
||||
return GameVersion.HGSS;
|
||||
}
|
||||
|
||||
return NONE;
|
||||
}
|
||||
|
||||
private static GameVersion GetIsTutor5(PKM pkm, int species, int form, bool specialTutors, int move)
|
||||
{
|
||||
var pi = PersonalTable.B2W2.GetFormeEntry(species, form);
|
||||
for (int i = 0; i < TypeTutor6.Length; i++)
|
||||
{
|
||||
if (TypeTutor6[i] == move && pi.TypeTutors[i])
|
||||
return GameVersion.Gen5;
|
||||
}
|
||||
|
||||
if (specialTutors && pkm.HasVisitedB2W2())
|
||||
{
|
||||
for (int i = 0; i < Tutors_B2W2.Length; i++)
|
||||
for (int j = 0; j < Tutors_B2W2[i].Length; j++)
|
||||
if (Tutors_B2W2[i][j] == move && pi.SpecialTutors[i][j])
|
||||
return GameVersion.B2W2;
|
||||
{
|
||||
for (int j = 0; j < Tutors_B2W2[i].Length; j++)
|
||||
{
|
||||
if (Tutors_B2W2[i][j] == move && pi.SpecialTutors[i][j])
|
||||
return GameVersion.B2W2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NONE;
|
||||
}
|
||||
|
||||
private static GameVersion GetIsTutor6(PKM pkm, int species, int form, bool specialTutors, int move)
|
||||
{
|
||||
var pi = PersonalTable.AO.GetFormeEntry(species, form);
|
||||
for (int i = 0; i < TypeTutor6.Length; i++)
|
||||
{
|
||||
if (TypeTutor6[i] == move && pi.TypeTutors[i])
|
||||
return GameVersion.Gen6;
|
||||
}
|
||||
|
||||
if (specialTutors && pkm.HasVisitedORAS())
|
||||
{
|
||||
for (int i = 0; i < Tutors_AO.Length; i++)
|
||||
for (int j = 0; j < Tutors_AO[i].Length; j++)
|
||||
if (Tutors_AO[i][j] == move && pi.SpecialTutors[i][j])
|
||||
return GameVersion.ORAS;
|
||||
{
|
||||
for (int j = 0; j < Tutors_AO[i].Length; j++)
|
||||
{
|
||||
if (Tutors_AO[i][j] == move && pi.SpecialTutors[i][j])
|
||||
return GameVersion.ORAS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NONE;
|
||||
}
|
||||
|
||||
private static GameVersion GetIsTutor7(PKM pkm, int species, int form, bool specialTutors, int move)
|
||||
{
|
||||
var pi = PersonalTable.USUM.GetFormeEntry(species, form);
|
||||
for (int i = 0; i < TypeTutor6.Length; i++)
|
||||
{
|
||||
if (TypeTutor6[i] == move && pi.TypeTutors[i])
|
||||
return GameVersion.Gen7;
|
||||
}
|
||||
|
||||
if (specialTutors && pkm.HasVisitedUSUM())
|
||||
{
|
||||
for (int i = 0; i < Tutors_USUM.Length; i++)
|
||||
{
|
||||
if (Tutors_USUM[i] == move && pi.SpecialTutors[0][i])
|
||||
return GameVersion.USUM;
|
||||
}
|
||||
}
|
||||
|
||||
return NONE;
|
||||
}
|
||||
|
@ -153,6 +187,7 @@ namespace PKHeX.Core
|
|||
if (AllowGBCartEra && format < 3 && (species == 25 || species == 26)) // Surf Pikachu via Stadium
|
||||
moves.Add(57);
|
||||
}
|
||||
|
||||
private static void AddMovesTutor2(List<int> moves, int species, int format, bool korean = false)
|
||||
{
|
||||
if (korean)
|
||||
|
@ -161,6 +196,7 @@ namespace PKHeX.Core
|
|||
moves.AddRange(Tutors_GSC.Where((_, i) => pi.TMHM[57 + i]));
|
||||
AddMovesTutor1(moves, species, format);
|
||||
}
|
||||
|
||||
private static void AddMovesTutor3(List<int> moves, int species)
|
||||
{
|
||||
// E Tutors (Free)
|
||||
|
@ -176,12 +212,14 @@ namespace PKHeX.Core
|
|||
if (species == 151)
|
||||
moves.AddRange(Tutor_3Mew);
|
||||
}
|
||||
|
||||
private static void AddMovesTutor4(List<int> moves, int species, int form)
|
||||
{
|
||||
var pi = PersonalTable.HGSS.GetFormeEntry(species, form);
|
||||
moves.AddRange(Tutors_4.Where((_, i) => pi.TypeTutors[i]));
|
||||
moves.AddRange(SpecialTutors_4.Where((_, i) => SpecialTutors_Compatibility_4[i].Any(e => e == species)));
|
||||
}
|
||||
|
||||
private static void AddMovesTutor5(List<int> moves, int species, int form, PKM pkm, bool specialTutors)
|
||||
{
|
||||
var pi = PersonalTable.B2W2[species];
|
||||
|
@ -189,6 +227,7 @@ namespace PKHeX.Core
|
|||
if (pkm.InhabitedGeneration(5) && specialTutors)
|
||||
moves.AddRange(GetTutors(PersonalTable.B2W2.GetFormeEntry(species, form), Tutors_B2W2));
|
||||
}
|
||||
|
||||
private static void AddMovesTutor6(List<int> moves, int species, int form, PKM pkm, bool specialTutors)
|
||||
{
|
||||
var pi = PersonalTable.AO[species];
|
||||
|
@ -196,6 +235,7 @@ namespace PKHeX.Core
|
|||
if (specialTutors && pkm.HasVisitedORAS())
|
||||
moves.AddRange(GetTutors(PersonalTable.AO.GetFormeEntry(species, form), Tutors_AO));
|
||||
}
|
||||
|
||||
private static void AddMovesTutor7(List<int> moves, int species, int form, PKM pkm, bool specialTutors)
|
||||
{
|
||||
var pi = PersonalTable.USUM.GetFormeEntry(species, form);
|
||||
|
@ -207,9 +247,13 @@ namespace PKHeX.Core
|
|||
private static IEnumerable<int> GetTutors(PersonalInfo pi, params int[][] tutors)
|
||||
{
|
||||
for (int i = 0; i < tutors.Length; i++)
|
||||
for (int b = 0; b < tutors[i].Length; b++)
|
||||
if (pi.SpecialTutors[i][b])
|
||||
yield return tutors[i][b];
|
||||
{
|
||||
for (int b = 0; b < tutors[i].Length; b++)
|
||||
{
|
||||
if (pi.SpecialTutors[i][b])
|
||||
yield return tutors[i][b];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static void AddSpecialTutorMoves(List<int> r, PKM pkm, int Generation, int species)
|
||||
|
|
|
@ -53,6 +53,7 @@ namespace PKHeX.Core
|
|||
|
||||
return new PIDIV {Type=PIDType.None, NoSeed=true}; // no match
|
||||
}
|
||||
|
||||
private static bool GetModifiedPIDMatch(PKM pk, uint pid, uint[] IVs, out PIDIV pidiv)
|
||||
{
|
||||
if (pk.IsShiny)
|
||||
|
@ -70,11 +71,12 @@ namespace PKHeX.Core
|
|||
|
||||
return GetPokewalkerMatch(pk, pid, out pidiv);
|
||||
}
|
||||
|
||||
private static bool GetModified8BitMatch(PKM pk, uint pid, out PIDIV pidiv)
|
||||
{
|
||||
return pk.Gen4
|
||||
? pid <= 0xFF && GetCuteCharmMatch(pk, pid, out pidiv) || GetG5MGShinyMatch(pk, pid, out pidiv)
|
||||
: GetG5MGShinyMatch(pk, pid, out pidiv) || pid <= 0xFF && GetCuteCharmMatch(pk, pid, out pidiv);
|
||||
? (pid <= 0xFF && GetCuteCharmMatch(pk, pid, out pidiv)) || GetG5MGShinyMatch(pk, pid, out pidiv)
|
||||
: GetG5MGShinyMatch(pk, pid, out pidiv) || (pid <= 0xFF && GetCuteCharmMatch(pk, pid, out pidiv));
|
||||
}
|
||||
|
||||
private static bool GetLCRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv)
|
||||
|
@ -126,6 +128,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return GetNonMatch(out pidiv);
|
||||
}
|
||||
|
||||
private static bool GetLCRNGUnownMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv)
|
||||
{
|
||||
// this is an exact copy of LCRNG 1,2,4 matching, except the PID has its halves switched (BACD, BADE, BACE)
|
||||
|
@ -176,6 +179,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return GetNonMatch(out pidiv);
|
||||
}
|
||||
|
||||
private static bool GetLCRNGRoamerMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv)
|
||||
{
|
||||
if (IVs.Skip(2).Any(iv => iv != 0) || IVs[1] > 7)
|
||||
|
@ -194,6 +198,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return GetNonMatch(out pidiv);
|
||||
}
|
||||
|
||||
private static bool GetXDRNGMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv)
|
||||
{
|
||||
var xdc = GetSeedsFromPIDEuclid(RNG.XDRNG, top, bot);
|
||||
|
@ -216,6 +221,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return GetNonMatch(out pidiv);
|
||||
}
|
||||
|
||||
private static bool GetChannelMatch(uint top, uint bot, uint[] IVs, out PIDIV pidiv, PKM pk)
|
||||
{
|
||||
var ver = pk.Version;
|
||||
|
@ -250,6 +256,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return GetNonMatch(out pidiv);
|
||||
}
|
||||
|
||||
private static bool GetMG4Match(uint pid, uint[] IVs, out PIDIV pidiv)
|
||||
{
|
||||
uint mg4Rev = RNG.ARNG.Prev(pid);
|
||||
|
@ -267,6 +274,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return GetNonMatch(out pidiv);
|
||||
}
|
||||
|
||||
private static bool GetG5MGShinyMatch(PKM pk, uint pid, out PIDIV pidiv)
|
||||
{
|
||||
var low = pid & 0xFFFF;
|
||||
|
@ -283,6 +291,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return GetNonMatch(out pidiv);
|
||||
}
|
||||
|
||||
private static bool GetCuteCharmMatch(PKM pk, uint pid, out PIDIV pidiv)
|
||||
{
|
||||
if (pid > 0xFF)
|
||||
|
@ -297,7 +306,7 @@ namespace PKHeX.Core
|
|||
var gr = getRatio();
|
||||
if (254 <= gr) // no modification for PID
|
||||
break;
|
||||
var rate = 25*(gr/25 + 1); // buffered
|
||||
var rate = 25*((gr / 25) + 1); // buffered
|
||||
var nature = pid % 25;
|
||||
if (nature + rate != pid)
|
||||
break;
|
||||
|
@ -315,6 +324,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return GetNonMatch(out pidiv);
|
||||
}
|
||||
|
||||
private static bool GetChainShinyMatch(PKM pk, uint pid, uint[] IVs, out PIDIV pidiv)
|
||||
{
|
||||
// 13 shiny bits
|
||||
|
@ -347,7 +357,7 @@ namespace PKHeX.Core
|
|||
if ((lower >> 16 & 7) != (pid & 7))
|
||||
continue;
|
||||
|
||||
var upid = ((pid & 0xFFFF) ^ pk.TID ^ pk.SID) & 0xFFF8 | (upper >> 16) & 0x7;
|
||||
var upid = (((pid & 0xFFFF) ^ pk.TID ^ pk.SID) & 0xFFF8) | ((upper >> 16) & 0x7);
|
||||
if (upid != pid >> 16)
|
||||
continue;
|
||||
|
||||
|
@ -357,6 +367,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return GetNonMatch(out pidiv);
|
||||
}
|
||||
|
||||
private static bool GetBACDMatch(PKM pk, uint pid, uint[] IVs, out PIDIV pidiv)
|
||||
{
|
||||
var bot = GetIVChunk(IVs, 0);
|
||||
|
@ -369,11 +380,11 @@ namespace PKHeX.Core
|
|||
var A = RNG.LCRNG.Prev(B);
|
||||
var low = B >> 16;
|
||||
|
||||
var PID = A & 0xFFFF0000 | low;
|
||||
var PID = (A & 0xFFFF0000) | low;
|
||||
if (PID != pid)
|
||||
{
|
||||
uint idxor = (uint)(pk.TID ^ pk.SID);
|
||||
bool isShiny = (idxor ^ PID >> 16 ^ PID & 0xFFFF) < 8;
|
||||
bool isShiny = (idxor ^ PID >> 16 ^ (PID & 0xFFFF)) < 8;
|
||||
if (!isShiny)
|
||||
{
|
||||
if (!pk.IsShiny) // check for nyx antishiny
|
||||
|
@ -412,6 +423,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return GetNonMatch(out pidiv);
|
||||
}
|
||||
|
||||
private static bool GetPokewalkerMatch(PKM pk, uint oldpid, out PIDIV pidiv)
|
||||
{
|
||||
// check surface compatibility
|
||||
|
@ -429,9 +441,10 @@ namespace PKHeX.Core
|
|||
pidiv = new PIDIV {NoSeed = true, RNG = RNG.LCRNG, Type = PIDType.Pokewalker};
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool GetColoStarterMatch(PKM pk, uint top, uint bot, uint[] IVs, out PIDIV pidiv)
|
||||
{
|
||||
if (pk.Version != 15 || pk.Species != 196 && pk.Species != 197)
|
||||
if (pk.Version != 15 || (pk.Species != 196 && pk.Species != 197))
|
||||
return GetNonMatch(out pidiv);
|
||||
|
||||
var iv1 = GetIVChunk(IVs, 0);
|
||||
|
@ -460,6 +473,7 @@ namespace PKHeX.Core
|
|||
pidiv = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the PID is a <see cref="PIDType.BACD_U_S"></see> match.
|
||||
/// </summary>
|
||||
|
@ -480,7 +494,7 @@ namespace PKHeX.Core
|
|||
// PID = PIDH << 16 | (SID ^ TID ^ PIDH)
|
||||
|
||||
var X = RNG.LCRNG.Prev(A); // unroll once as there's 3 calls instead of 2
|
||||
uint PID = X & 0xFFFF0000 | idxor ^ X >> 16;
|
||||
uint PID = (X & 0xFFFF0000) | (idxor ^ X >> 16);
|
||||
PID &= 0xFFFFFFF8;
|
||||
PID |= low & 0x7; // lowest 3 bits
|
||||
|
||||
|
@ -490,6 +504,7 @@ namespace PKHeX.Core
|
|||
type = PIDType.BACD_U_S;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the PID is a <see cref="PIDType.BACD_U_AX"></see> match.
|
||||
/// </summary>
|
||||
|
@ -519,7 +534,7 @@ namespace PKHeX.Core
|
|||
return true;
|
||||
}
|
||||
|
||||
private static PIDIV AnalyzeGB(PKM pk)
|
||||
private static PIDIV AnalyzeGB(PKM _)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
@ -532,6 +547,7 @@ namespace PKHeX.Core
|
|||
uint first = b << 16;
|
||||
return method.RecoverLower16Bits(first, second);
|
||||
}
|
||||
|
||||
private static IEnumerable<uint> GetSeedsFromIVs(RNG method, uint a, uint b)
|
||||
{
|
||||
Debug.Assert(a >> 15 == 0);
|
||||
|
@ -546,6 +562,7 @@ namespace PKHeX.Core
|
|||
yield return z ^ 0x80000000; // sister bitflip
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<uint> GetSeedsFromIVsSkip(RNG method, uint rand1, uint rand3)
|
||||
{
|
||||
Debug.Assert(rand1 >> 15 == 0);
|
||||
|
@ -560,10 +577,12 @@ namespace PKHeX.Core
|
|||
yield return z ^ 0x80000000; // sister bitflip
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<uint> GetSeedsFromPIDEuclid(RNG method, uint rand1, uint rand2)
|
||||
{
|
||||
return method.RecoverLower16BitsEuclid16(rand1 << 16, rand2 << 16);
|
||||
}
|
||||
|
||||
public static IEnumerable<uint> GetSeedsFromIVsEuclid(RNG method, uint rand1, uint rand2)
|
||||
{
|
||||
return method.RecoverLower16BitsEuclid15(rand1 << 16, rand2 << 16);
|
||||
|
@ -587,6 +606,7 @@ namespace PKHeX.Core
|
|||
r2 >> 10 & 31,
|
||||
};
|
||||
}
|
||||
|
||||
internal static int[] GetIVsInt32(uint r1, uint r2)
|
||||
{
|
||||
return new[]
|
||||
|
@ -599,6 +619,7 @@ namespace PKHeX.Core
|
|||
(int)r2 >> 10 & 31,
|
||||
};
|
||||
}
|
||||
|
||||
private static uint GetIVChunk(uint[] IVs, int start)
|
||||
{
|
||||
uint val = 0;
|
||||
|
@ -624,6 +645,7 @@ namespace PKHeX.Core
|
|||
yield return new PIDIV {OriginSeed = s, RNG = RNG.XDRNG, Type = PIDType.PokeSpot};
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsPokeSpotActivation(int slot, uint seed, out uint s)
|
||||
{
|
||||
s = seed;
|
||||
|
@ -648,6 +670,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsPokeSpotSlotValid(int slot, uint esv)
|
||||
{
|
||||
switch (slot)
|
||||
|
@ -661,6 +684,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsCompatible3(this PIDType val, IEncounterable encounter, PKM pkm)
|
||||
{
|
||||
switch (encounter)
|
||||
|
@ -692,6 +716,7 @@ namespace PKHeX.Core
|
|||
return val == PIDType.None;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsRoamerPIDIV(this PIDType val, PKM pkm)
|
||||
{
|
||||
// Roamer PIDIV is always Method 1.
|
||||
|
@ -703,12 +728,13 @@ namespace PKHeX.Core
|
|||
var IVs = pkm.IVs;
|
||||
return !(IVs.Skip(2).Any(iv => iv != 0) || IVs[1] > 7);
|
||||
}
|
||||
|
||||
public static bool IsCompatible4(this PIDType val, IEncounterable encounter, PKM pkm)
|
||||
{
|
||||
switch (encounter)
|
||||
{
|
||||
case EncounterStatic s:
|
||||
if (s == Encounters4.SpikyEaredPichu || s.Location == 233 && s.Gift) // Pokewalker
|
||||
if (s == Encounters4.SpikyEaredPichu || (s.Location == 233 && s.Gift)) // Pokewalker
|
||||
return val == PIDType.Pokewalker;
|
||||
if (s.Shiny == Shiny.Always)
|
||||
return val == PIDType.ChainShiny;
|
||||
|
@ -732,6 +758,7 @@ namespace PKHeX.Core
|
|||
return val == PIDType.None;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsG4ManaphyPIDValid(PIDType val, PKM pkm)
|
||||
{
|
||||
if (pkm.IsEgg)
|
||||
|
@ -753,15 +780,20 @@ namespace PKHeX.Core
|
|||
return (pkm.TID ^ pkm.SID ^ (shinyPID & 0xFFFF) ^ (shinyPID >> 16)) < 8; // shiny proc
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsCuteCharm4Valid(IEncounterable encounter, PKM pkm)
|
||||
{
|
||||
if (pkm.Species == 183 || pkm.Species == 184)
|
||||
{
|
||||
return !IsCuteCharmAzurillMale(pkm.PID) // recognized as not Azurill
|
||||
|| encounter.Species == 298; // encounter must be male Azurill
|
||||
|| encounter.Species == 298; // encounter must be male Azurill
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool IsCuteCharmAzurillMale(uint pid) => pid >= 0xC8 && pid <= 0xE0;
|
||||
|
||||
private static void GetCuteCharmGenderSpecies(PKM pk, uint pid, out int genderValue, out int species)
|
||||
{
|
||||
// There are some edge cases when the gender ratio changes across evolutions.
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace PKHeX.Core
|
|||
var rng = RNG.LCRNG;
|
||||
var A = rng.Next(seed);
|
||||
var B = rng.Next(A);
|
||||
var pid = B & 0xFFFF0000 | A >> 16;
|
||||
var pid = (B & 0xFFFF0000) | A >> 16;
|
||||
if (type == PIDType.Method_1_Unown || type == PIDType.Method_2_Unown || type == PIDType.Method_4_Unown)
|
||||
pk.PID = (pid >> 16) | (pid << 16); // swap halves
|
||||
else
|
||||
|
@ -34,6 +34,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
pk.IVs = IVs;
|
||||
}
|
||||
|
||||
private static void SetValuesFromSeedBACD(PKM pk, PIDType type, uint seed)
|
||||
{
|
||||
var rng = RNG.LCRNG;
|
||||
|
@ -46,7 +47,7 @@ namespace PKHeX.Core
|
|||
|
||||
if (shiny)
|
||||
{
|
||||
uint PID = X & 0xFFFF0000 | (uint)pk.SID ^ (uint)pk.TID ^ X >> 16;
|
||||
uint PID = (X & 0xFFFF0000) | ((uint)pk.SID ^ (uint)pk.TID ^ X >> 16);
|
||||
PID &= 0xFFFFFFF8;
|
||||
PID |= B >> 16 & 0x7; // lowest 3 bits
|
||||
|
||||
|
@ -55,10 +56,12 @@ namespace PKHeX.Core
|
|||
else if (type == PIDType.BACD_R_AX || type == PIDType.BACD_U_AX)
|
||||
{
|
||||
uint low = B >> 16;
|
||||
pk.PID = A & 0xFFFF0000 ^ (((uint)pk.TID ^ (uint)pk.SID ^ low) << 16) | low;
|
||||
pk.PID = ((A & 0xFFFF0000) ^ (((uint)pk.TID ^ (uint)pk.SID ^ low) << 16)) | low;
|
||||
}
|
||||
else
|
||||
pk.PID = A & 0xFFFF0000 | B >> 16;
|
||||
{
|
||||
pk.PID = (A & 0xFFFF0000) | B >> 16;
|
||||
}
|
||||
|
||||
pk.IVs = MethodFinder.GetIVsInt32(C >> 16, D >> 16);
|
||||
|
||||
|
@ -66,6 +69,7 @@ namespace PKHeX.Core
|
|||
while (antishiny && pk.IsShiny)
|
||||
pk.PID = unchecked(pk.PID + 1);
|
||||
}
|
||||
|
||||
private static void SetValuesFromSeedXDRNG(PKM pk, uint seed)
|
||||
{
|
||||
var rng = RNG.XDRNG;
|
||||
|
@ -89,9 +93,10 @@ namespace PKHeX.Core
|
|||
var D = rng.Next(C); // PID
|
||||
var E = rng.Next(D); // PID
|
||||
|
||||
pk.PID = D & 0xFFFF0000 | E >> 16;
|
||||
pk.PID = (D & 0xFFFF0000) | E >> 16;
|
||||
pk.IVs = MethodFinder.GetIVsInt32(A >> 16, B >> 16);
|
||||
}
|
||||
|
||||
private static void SetValuesFromSeedChannel(PKM pk, uint seed)
|
||||
{
|
||||
var rng = RNG.XDRNG;
|
||||
|
@ -123,6 +128,7 @@ namespace PKHeX.Core
|
|||
var method = GetGeneratorMethod(type);
|
||||
method(pk, seed);
|
||||
}
|
||||
|
||||
private static Action<PKM, uint> GetGeneratorMethod(PIDType t)
|
||||
{
|
||||
switch (t)
|
||||
|
@ -167,7 +173,7 @@ namespace PKHeX.Core
|
|||
case PIDType.G4MGAntiShiny:
|
||||
break;
|
||||
}
|
||||
return (pk, _) => { };
|
||||
return (_, __) => { };
|
||||
}
|
||||
|
||||
public static void SetRandomChainShinyPID(PKM pk, uint seed)
|
||||
|
@ -182,7 +188,7 @@ namespace PKHeX.Core
|
|||
for (int i = 0; i < 13; i++)
|
||||
lower |= (Next() & 1) << (3 + i);
|
||||
|
||||
upper = (uint)(lower ^ pk.TID ^ pk.SID) & 0xFFF8 | upper & 0x7;
|
||||
upper = ((uint)(lower ^ pk.TID ^ pk.SID) & 0xFFF8) | (upper & 0x7);
|
||||
pk.PID = upper << 16 | lower;
|
||||
pk.IVs = MethodFinder.GetIVsInt32(Next(), Next());
|
||||
}
|
||||
|
@ -199,7 +205,7 @@ namespace PKHeX.Core
|
|||
var D = rng.Next(seed); // PID
|
||||
var E = rng.Next(D); // PID
|
||||
|
||||
pk.PID = D & 0xFFFF0000 | E >> 16;
|
||||
pk.PID = (D & 0xFFFF0000) | E >> 16;
|
||||
if (!IsValidCriteria4(pk, nature, ability, gender))
|
||||
continue;
|
||||
|
||||
|
@ -222,7 +228,7 @@ namespace PKHeX.Core
|
|||
nature = 0;
|
||||
uint pid = (uint)((TID ^ SID) >> 8 ^ 0xFF) << 24; // the most significant byte of the PID is chosen so the Pokémon can never be shiny.
|
||||
// Ensure nature is set to required nature without affecting shininess
|
||||
pid += nature - pid % 25;
|
||||
pid += nature - (pid % 25);
|
||||
|
||||
// Ensure Gender is set to required gender without affecting other properties
|
||||
// If Gender is modified, modify the ability if appropriate
|
||||
|
@ -237,13 +243,13 @@ namespace PKHeX.Core
|
|||
|
||||
if (currentGender == 0) // Male
|
||||
{
|
||||
pid += (uint)(((gr - (pid & 0xFF)) / 25 + 1) * 25);
|
||||
pid += (uint)((((gr - (pid & 0xFF)) / 25) + 1) * 25);
|
||||
if ((nature & 1) != (pid & 1))
|
||||
pid += 25;
|
||||
}
|
||||
else
|
||||
{
|
||||
pid -= (uint)((((pid & 0xFF) - gr) / 25 + 1) * 25);
|
||||
pid -= (uint)(((((pid & 0xFF) - gr) / 25) + 1) * 25);
|
||||
if ((nature & 1) != (pid & 1))
|
||||
pid -= 25;
|
||||
}
|
||||
|
@ -338,6 +344,7 @@ namespace PKHeX.Core
|
|||
|
||||
return PIDType.Method_1;
|
||||
}
|
||||
|
||||
private static void SetRandomWildPID5(PKM pk, int nature, int ability, int gender, PIDType specific = PIDType.None)
|
||||
{
|
||||
var tidbit = (pk.TID ^ pk.SID) & 1;
|
||||
|
|
|
@ -8,21 +8,27 @@
|
|||
/// <summary> Method 1 Variants (H1/J/K) </summary>
|
||||
/// <remarks><see cref="RNG.LCRNG"/></remarks>
|
||||
Method_1,
|
||||
|
||||
/// <summary> Method H2 </summary>
|
||||
/// <remarks><see cref="RNG.LCRNG"/></remarks>
|
||||
Method_2,
|
||||
|
||||
/// <summary> Method H4 </summary>
|
||||
/// <remarks><see cref="RNG.LCRNG"/></remarks>
|
||||
Method_4,
|
||||
|
||||
/// <summary> Method H1_Unown (FRLG) </summary>
|
||||
/// <remarks><see cref="RNG.LCRNG"/></remarks>
|
||||
Method_1_Unown,
|
||||
|
||||
/// <summary> Method H2_Unown (FRLG) </summary>
|
||||
/// <remarks><see cref="RNG.LCRNG"/></remarks>
|
||||
Method_2_Unown,
|
||||
|
||||
/// <summary> Method H4_Unown (FRLG) </summary>
|
||||
/// <remarks><see cref="RNG.LCRNG"/></remarks>
|
||||
Method_4_Unown,
|
||||
|
||||
/// <summary> Method 1 Roamer (Gen3) </summary>
|
||||
/// <remarks><see cref="RNG.LCRNG"/></remarks>
|
||||
Method_1_Roamer,
|
||||
|
@ -32,36 +38,43 @@
|
|||
/// </summary>
|
||||
/// <remarks><see cref="RNG.LCRNG"/></remarks>
|
||||
BACD_R,
|
||||
|
||||
/// <summary>
|
||||
/// Event Reversed Order PID without Origin Seed restrictions
|
||||
/// </summary>
|
||||
/// <remarks><see cref="RNG.LCRNG"/></remarks>
|
||||
BACD_U,
|
||||
|
||||
/// <summary>
|
||||
/// Event Reversed Order PID restricted to 16bit Origin Seed, antishiny.
|
||||
/// </summary>
|
||||
/// <remarks><see cref="RNG.LCRNG"/></remarks>
|
||||
BACD_R_A,
|
||||
|
||||
/// <summary>
|
||||
/// Event Reversed Order PID without Origin Seed restrictions, antishiny.
|
||||
/// </summary>
|
||||
/// <remarks><see cref="RNG.LCRNG"/></remarks>
|
||||
BACD_U_A,
|
||||
|
||||
/// <summary>
|
||||
/// Event Reversed Order PID restricted to 16bit Origin Seed, shiny
|
||||
/// </summary>
|
||||
/// <remarks><see cref="RNG.LCRNG"/></remarks>
|
||||
BACD_R_S,
|
||||
|
||||
/// <summary>
|
||||
/// Event Reversed Order PID without Origin Seed restrictions, shiny
|
||||
/// </summary>
|
||||
/// <remarks><see cref="RNG.LCRNG"/></remarks>
|
||||
BACD_U_S,
|
||||
|
||||
/// <summary>
|
||||
/// Event Reversed Order PID restricted to 16bit Origin Seed, antishiny (nyx)
|
||||
/// </summary>
|
||||
/// <remarks><see cref="RNG.LCRNG"/></remarks>
|
||||
BACD_R_AX,
|
||||
|
||||
/// <summary>
|
||||
/// Event Reversed Order PID without Origin Seed restrictions, antishiny (nyx)
|
||||
/// </summary>
|
||||
|
@ -73,6 +86,7 @@
|
|||
/// </summary>
|
||||
/// <remarks><see cref="RNG.LCRNG"/></remarks>
|
||||
CuteCharm,
|
||||
|
||||
/// <summary>
|
||||
/// Generation 4 Chained Shiny
|
||||
/// </summary>
|
||||
|
@ -85,6 +99,7 @@
|
|||
/// </summary>
|
||||
/// <remarks><see cref="RNG.XDRNG"/></remarks>
|
||||
CXD,
|
||||
|
||||
/// <summary>
|
||||
/// Standard <see cref="GameVersion.CXD"/> PIDIV which is immediately after the RNG calls that create the TID and SID.
|
||||
/// </summary>
|
||||
|
|
|
@ -3,7 +3,7 @@ using System.Runtime.CompilerServices;
|
|||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
public class RNG
|
||||
public sealed class RNG
|
||||
{
|
||||
public static readonly RNG LCRNG = new RNG(0x41C64E6D, 0x00006073, 0xEEB9EB65, 0x0A3561A1);
|
||||
public static readonly RNG XDRNG = new RNG(0x000343FD, 0x00269EC3, 0xB9B33155, 0xA170F641);
|
||||
|
@ -59,7 +59,7 @@ namespace PKHeX.Core
|
|||
// with the current calc setup, the search loop's calculated value may be -1 (loop does subtraction)
|
||||
// since LCGs are linear (hence the name), there's no values in adjacent cells. (no collisions)
|
||||
// if we mark the prior adjacent cell, we eliminate the need to check flags twice on each loop.
|
||||
uint right = mult * i + add;
|
||||
uint right = (mult * i) + add;
|
||||
ushort val = (ushort) (right >> 16);
|
||||
|
||||
f[val] = true; v[val] = (byte)i;
|
||||
|
@ -69,9 +69,10 @@ namespace PKHeX.Core
|
|||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public uint Next(uint seed) => seed * Mult + Add;
|
||||
public uint Next(uint seed) => (seed * Mult) + Add;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public uint Prev(uint seed) => seed * rMult + rAdd;
|
||||
public uint Prev(uint seed) => (seed * rMult) + rAdd;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public uint Advance(uint seed, int frames)
|
||||
|
@ -80,6 +81,7 @@ namespace PKHeX.Core
|
|||
seed = Next(seed);
|
||||
return seed;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public uint Reverse(uint seed, int frames)
|
||||
{
|
||||
|
@ -104,6 +106,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return ivs;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal int[] GetSequentialIVsInt32(uint seed)
|
||||
{
|
||||
|
@ -130,7 +133,7 @@ namespace PKHeX.Core
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal IEnumerable<uint> RecoverLower16Bits(uint first, uint second)
|
||||
{
|
||||
uint k1 = second - first * Mult;
|
||||
uint k1 = second - (first * Mult);
|
||||
for (uint i = 0, k3 = k1; i <= 255; ++i, k3 -= k2)
|
||||
{
|
||||
ushort val = (ushort)(k3 >> 16);
|
||||
|
@ -138,6 +141,7 @@ namespace PKHeX.Core
|
|||
yield return Prev(first | i << 8 | low8[val]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the origin seeds for two 16 bit rand() calls (ignoring a rand() in between) using a meet-in-the-middle approach.
|
||||
/// </summary>
|
||||
|
@ -152,7 +156,7 @@ namespace PKHeX.Core
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal IEnumerable<uint> RecoverLower16BitsGap(uint first, uint third)
|
||||
{
|
||||
uint k1 = third - first * k0g;
|
||||
uint k1 = third - (first * k0g);
|
||||
for (uint i = 0, k3 = k1; i <= 255; ++i, k3 -= k2s)
|
||||
{
|
||||
ushort val = (ushort)(k3 >> 16);
|
||||
|
@ -160,6 +164,7 @@ namespace PKHeX.Core
|
|||
yield return Prev(first | i << 8 | g_low8[val]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the origin seeds for two successive 16 bit rand() calls using a Euclidean division approach.
|
||||
/// </summary>
|
||||
|
@ -178,6 +183,7 @@ namespace PKHeX.Core
|
|||
const long inc = 0x100000000; // 1 << 32;
|
||||
return GetPossibleSeedsEuclid(first, second, bitshift, inc);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the origin seeds for two successive 15 bit rand() calls using a Euclidean division approach.
|
||||
/// </summary>
|
||||
|
@ -201,13 +207,13 @@ namespace PKHeX.Core
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private IEnumerable<uint> GetPossibleSeedsEuclid(uint first, uint second, int bitshift, long inc)
|
||||
{
|
||||
long t = second - Mult * first - t0;
|
||||
long t = second - (Mult * first) - t0;
|
||||
long kmax = (((t1 - t) >> bitshift) << bitshift) + t;
|
||||
for (long k = t; k <= kmax; k += inc)
|
||||
{
|
||||
// compute modulo in steps for reuse in yielded value (x % Mult)
|
||||
long fix = k / Mult;
|
||||
long remainder = k - Mult * fix;
|
||||
long remainder = k - (Mult * fix);
|
||||
if (remainder >> 16 == 0)
|
||||
yield return Prev(first | (uint) fix);
|
||||
}
|
||||
|
|
|
@ -35,12 +35,14 @@
|
|||
Source = m;
|
||||
Generation = g;
|
||||
}
|
||||
|
||||
internal CheckMoveResult(MoveSource m, int g, Severity s, string c, CheckIdentifier i)
|
||||
: base(s, c, i)
|
||||
{
|
||||
Source = m;
|
||||
Generation = g;
|
||||
}
|
||||
|
||||
internal CheckMoveResult(CheckMoveResult Org, Severity s, string c, CheckIdentifier i)
|
||||
: base(s, c, i)
|
||||
{
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
public string Rating => Judgement.Description();
|
||||
internal readonly CheckIdentifier Identifier;
|
||||
|
||||
internal CheckResult(CheckIdentifier i) { Identifier = i; }
|
||||
internal CheckResult(CheckIdentifier i) => Identifier = i;
|
||||
|
||||
internal CheckResult(Severity s, string c, CheckIdentifier i)
|
||||
{
|
||||
Judgement = s;
|
||||
|
|
|
@ -13,29 +13,34 @@ namespace PKHeX.Core
|
|||
public bool GetHasEggMove(int move) => Moves.Contains(move);
|
||||
}
|
||||
|
||||
public class EggMoves2 : EggMoves
|
||||
public sealed class EggMoves2 : EggMoves
|
||||
{
|
||||
private EggMoves2(byte[] data)
|
||||
{
|
||||
Count = data.Length;
|
||||
Moves = data.Select(i => (int) i).ToArray();
|
||||
}
|
||||
|
||||
public static EggMoves[] GetArray(byte[] data, int count)
|
||||
{
|
||||
int[] ptrs = new int[count+1];
|
||||
int baseOffset = (data[1] << 8 | data[0]) - count * 2;
|
||||
int baseOffset = (data[1] << 8 | data[0]) - (count * 2);
|
||||
for (int i = 1; i < ptrs.Length; i++)
|
||||
ptrs[i] = (data[(i - 1)*2 + 1] << 8 | data[(i - 1)*2]) - baseOffset;
|
||||
{
|
||||
var ofs = (i - 1) * 2;
|
||||
ptrs[i] = (data[ofs + 1] << 8 | data[ofs]) - baseOffset;
|
||||
}
|
||||
|
||||
EggMoves[] entries = new EggMoves[count + 1];
|
||||
entries[0] = new EggMoves2(new byte[0]);
|
||||
entries[0] = new EggMoves2(Array.Empty<byte>());
|
||||
for (int i = 1; i < entries.Length; i++)
|
||||
entries[i] = new EggMoves2(data.Skip(ptrs[i]).TakeWhile(b => b != 0xFF).ToArray());
|
||||
|
||||
return entries;
|
||||
}
|
||||
}
|
||||
public class EggMoves6 : EggMoves
|
||||
|
||||
public sealed class EggMoves6 : EggMoves
|
||||
{
|
||||
private EggMoves6(byte[] data)
|
||||
{
|
||||
|
@ -48,6 +53,7 @@ namespace PKHeX.Core
|
|||
Moves[i] = br.ReadUInt16();
|
||||
}
|
||||
}
|
||||
|
||||
public static EggMoves[] GetArray(byte[][] entries)
|
||||
{
|
||||
EggMoves[] data = new EggMoves[entries.Length];
|
||||
|
@ -56,7 +62,8 @@ namespace PKHeX.Core
|
|||
return data;
|
||||
}
|
||||
}
|
||||
public class EggMoves7 : EggMoves
|
||||
|
||||
public sealed class EggMoves7 : EggMoves
|
||||
{
|
||||
private EggMoves7(byte[] data)
|
||||
{
|
||||
|
@ -71,6 +78,7 @@ namespace PKHeX.Core
|
|||
Moves[i] = br.ReadUInt16();
|
||||
}
|
||||
}
|
||||
|
||||
public static EggMoves[] GetArray(byte[][] entries)
|
||||
{
|
||||
EggMoves[] data = new EggMoves[entries.Length];
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
{
|
||||
return encounter.LevelMin <= lvl && lvl <= encounter.LevelMax;
|
||||
}
|
||||
|
||||
public static bool IsWithinRange(this IEncounterable encounter, PKM pkm)
|
||||
{
|
||||
if (!pkm.HasOriginalMetLocation)
|
||||
|
@ -30,6 +31,7 @@
|
|||
return pkm.CurrentLevel == g.Level;
|
||||
return pkm.CurrentLevel == pkm.Met_Level;
|
||||
}
|
||||
|
||||
internal static string GetEncounterTypeName(this IEncounterable Encounter) => Encounter?.Name ?? "Unknown";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
? encounter.Location
|
||||
: encounter.EggLocation;
|
||||
}
|
||||
|
||||
internal static string GetEncounterLocation(this ILocation Encounter, int gen, int version = -1)
|
||||
{
|
||||
int loc = Encounter.GetLocation();
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace PKHeX.Core
|
|||
public static partial class Extensions
|
||||
{
|
||||
public static bool CanBeReceivedBy(this IVersion ver, GameVersion game) => ver.Version.Contains(game);
|
||||
|
||||
public static GameVersion GetCompatibleVersion(this IVersion ver, GameVersion prefer)
|
||||
{
|
||||
if (ver.CanBeReceivedBy(prefer) || ver.Version <= GameVersion.Unknown)
|
||||
|
@ -20,9 +21,12 @@ namespace PKHeX.Core
|
|||
internal static void SetVersion(this IEnumerable<IVersion> arr, GameVersion game)
|
||||
{
|
||||
foreach (var z in arr)
|
||||
{
|
||||
if (z.Version <= 0)
|
||||
z.Version = game;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void SetVersion(this IEnumerable<EncounterArea> arr, GameVersion game)
|
||||
{
|
||||
foreach (var area in arr)
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
return GetMoveTypeFromG12(type);
|
||||
return type;
|
||||
}
|
||||
|
||||
private static MoveType GetMoveTypeFromG12(this MoveType type)
|
||||
{
|
||||
if (type <= MoveType.Rock)
|
||||
|
|
|
@ -5,10 +5,30 @@
|
|||
/// </summary>
|
||||
public enum Nature : byte
|
||||
{
|
||||
Hardy, Lonely, Brave, Adamant, Naughty, Bold,
|
||||
Docile, Relaxed, Impish, Lax, Timid, Hasty,
|
||||
Serious, Jolly, Naive, Modest, Mild, Quiet,
|
||||
Bashful, Rash, Calm, Gentle, Sassy, Careful,
|
||||
Hardy,
|
||||
Lonely,
|
||||
Brave,
|
||||
Adamant,
|
||||
Naughty,
|
||||
Bold,
|
||||
Docile,
|
||||
Relaxed,
|
||||
Impish,
|
||||
Lax,
|
||||
Timid,
|
||||
Hasty,
|
||||
Serious,
|
||||
Jolly,
|
||||
Naive,
|
||||
Modest,
|
||||
Mild,
|
||||
Quiet,
|
||||
Bashful,
|
||||
Rash,
|
||||
Calm,
|
||||
Gentle,
|
||||
Sassy,
|
||||
Careful,
|
||||
Quirky,
|
||||
|
||||
Random = 25,
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX.Core
|
||||
|
@ -13,10 +14,9 @@ namespace PKHeX.Core
|
|||
/// </summary>
|
||||
/// <param name="len">Length, in bytes, of the data of which to determine validity.</param>
|
||||
/// <returns>A boolean indicating whether or not the given length is valid for a mystery gift.</returns>
|
||||
public static bool IsMysteryGift(long len)
|
||||
{
|
||||
return new[] { WC6.SizeFull, WC6.Size, PGF.Size, PGT.Size, PCD.Size }.Contains((int)len);
|
||||
}
|
||||
public static bool IsMysteryGift(long len) => MGSizes.Contains((int)len);
|
||||
|
||||
private static readonly HashSet<int> MGSizes = new HashSet<int>(new[] { WC6.SizeFull, WC6.Size, PGF.Size, PGT.Size, PCD.Size });
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given data to a <see cref="MysteryGift"/>.
|
||||
|
@ -133,8 +133,8 @@ namespace PKHeX.Core
|
|||
}
|
||||
|
||||
// Search Properties
|
||||
public virtual int[] Moves { get => new int[4]; set { } }
|
||||
public virtual int[] RelearnMoves { get => new int[4]; set { } }
|
||||
public virtual int[] Moves { get => Array.Empty<int>(); set { } }
|
||||
public virtual int[] RelearnMoves { get => Array.Empty<int>(); set { } }
|
||||
public virtual int[] IVs { get => null; set { } }
|
||||
public virtual bool IsShiny => false;
|
||||
public virtual bool IsEgg { get => false; set { } }
|
||||
|
|
|
@ -305,7 +305,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
protected override bool[] MysteryGiftReceivedFlags { get => null; set { } }
|
||||
protected override MysteryGift[] MysteryGiftCards { get => new MysteryGift[0]; set { } }
|
||||
protected override MysteryGift[] MysteryGiftCards { get => Array.Empty<MysteryGift>(); set { } }
|
||||
|
||||
// Trainer Info
|
||||
public override string OT
|
||||
|
|
|
@ -23,13 +23,14 @@ namespace PKHeX.Core
|
|||
public bool Exportable { get; protected set; }
|
||||
public abstract SaveFile Clone();
|
||||
public abstract string Filter { get; }
|
||||
public byte[] Footer { protected get; set; } = new byte[0]; // .dsv
|
||||
public byte[] Header { protected get; set; } = new byte[0]; // .gci
|
||||
public byte[] Footer { protected get; set; } = Array.Empty<byte>(); // .dsv
|
||||
public byte[] Header { protected get; set; } = Array.Empty<byte>(); // .gci
|
||||
public bool Japanese { get; protected set; }
|
||||
public virtual string PlayTimeString => $"{PlayedHours}ː{PlayedMinutes:00}ː{PlayedSeconds:00}"; // not :
|
||||
public bool IndeterminateGame => Version == GameVersion.Unknown;
|
||||
public virtual bool IndeterminateSubVersion => false;
|
||||
public abstract string Extension { get; }
|
||||
|
||||
public virtual string[] PKMExtensions => PKM.Extensions.Where(f =>
|
||||
{
|
||||
int gen = f.Last() - 0x30;
|
||||
|
@ -52,6 +53,7 @@ namespace PKHeX.Core
|
|||
{
|
||||
return Write(DSV);
|
||||
}
|
||||
|
||||
protected virtual byte[] Write(bool DSV)
|
||||
{
|
||||
SetChecksums();
|
||||
|
@ -61,6 +63,7 @@ namespace PKHeX.Core
|
|||
return Header.Concat(Data).ToArray();
|
||||
return Data;
|
||||
}
|
||||
|
||||
public virtual string MiscSaveChecks() => string.Empty;
|
||||
public virtual string MiscSaveInfo() => string.Empty;
|
||||
public virtual GameVersion Version { get; protected set; }
|
||||
|
@ -117,7 +120,7 @@ namespace PKHeX.Core
|
|||
public virtual bool HasGeolocation => false;
|
||||
public bool HasPokeBlock => ORAS && !ORASDEMO;
|
||||
public bool HasEvents => EventFlags != null;
|
||||
public bool HasLink => ORAS && !ORASDEMO || XY;
|
||||
public bool HasLink => (ORAS && !ORASDEMO) || XY;
|
||||
|
||||
// Counts
|
||||
protected virtual int GiftCountMax { get; } = int.MinValue;
|
||||
|
@ -175,6 +178,7 @@ namespace PKHeX.Core
|
|||
SetBoxData(value, b, b * BoxSlotCount);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetBoxData(IList<PKM> value, int box, int index = 0)
|
||||
{
|
||||
int ofs = GetBoxOffset(box);
|
||||
|
@ -184,12 +188,14 @@ namespace PKHeX.Core
|
|||
SetStoredSlot(value[index + slot], ofs);
|
||||
}
|
||||
}
|
||||
|
||||
public PKM[] GetBoxData(int box)
|
||||
{
|
||||
var data = new PKM[BoxSlotCount];
|
||||
AddBoxData(data, box, 0);
|
||||
return data;
|
||||
}
|
||||
|
||||
private void AddBoxData(IList<PKM> data, int box, int index)
|
||||
{
|
||||
int ofs = GetBoxOffset(box);
|
||||
|
@ -232,6 +238,7 @@ namespace PKHeX.Core
|
|||
SetPartySlot(newParty[i], GetPartyOffset(i));
|
||||
}
|
||||
}
|
||||
|
||||
public IList<PKM> BattleBoxData
|
||||
{
|
||||
get
|
||||
|
@ -242,7 +249,7 @@ namespace PKHeX.Core
|
|||
PKM[] data = new PKM[6];
|
||||
for (int i = 0; i < data.Length; i++)
|
||||
{
|
||||
data[i] = GetStoredSlot(BattleBox + SIZE_STORED * i);
|
||||
data[i] = GetStoredSlot(BattleBox + (SIZE_STORED * i));
|
||||
data[i].Locked = BattleBoxLocked;
|
||||
if (data[i].Species != 0)
|
||||
continue;
|
||||
|
@ -276,6 +283,7 @@ namespace PKHeX.Core
|
|||
SetEventFlag(i, value[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> All Event Constant values for the savegame </summary>
|
||||
public ushort[] EventConsts
|
||||
{
|
||||
|
@ -286,7 +294,7 @@ namespace PKHeX.Core
|
|||
|
||||
ushort[] Constants = new ushort[EventConstMax];
|
||||
for (int i = 0; i < Constants.Length; i++)
|
||||
Constants[i] = BitConverter.ToUInt16(Data, EventConst + i * 2);
|
||||
Constants[i] = BitConverter.ToUInt16(Data, EventConst + (i * 2));
|
||||
return Constants;
|
||||
}
|
||||
set
|
||||
|
@ -297,9 +305,10 @@ namespace PKHeX.Core
|
|||
return;
|
||||
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
BitConverter.GetBytes(value[i]).CopyTo(Data, EventConst + i * 2);
|
||||
BitConverter.GetBytes(value[i]).CopyTo(Data, EventConst + (i * 2));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="bool"/> status of a desired Event Flag
|
||||
/// </summary>
|
||||
|
@ -324,6 +333,7 @@ namespace PKHeX.Core
|
|||
throw new ArgumentException($"Event Flag to set ({flagNumber}) is greater than max ({EventFlagMax}).");
|
||||
SetFlag(EventFlag + (flagNumber >> 3), flagNumber & 7, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="bool"/> status of the Flag at the specified offset and index.
|
||||
/// </summary>
|
||||
|
@ -335,6 +345,7 @@ namespace PKHeX.Core
|
|||
bitIndex &= 7; // ensure bit access is 0-7
|
||||
return (Data[offset] >> bitIndex & 1) != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the <see cref="bool"/> status of the Flag at the specified offset and index.
|
||||
/// </summary>
|
||||
|
@ -365,6 +376,7 @@ namespace PKHeX.Core
|
|||
// Mystery Gift
|
||||
protected virtual bool[] MysteryGiftReceivedFlags { get => null; set { } }
|
||||
protected virtual MysteryGift[] MysteryGiftCards { get => null; set { } }
|
||||
|
||||
public virtual MysteryGiftAlbum GiftAlbum
|
||||
{
|
||||
get => new MysteryGiftAlbum
|
||||
|
@ -405,6 +417,7 @@ namespace PKHeX.Core
|
|||
public int SlotCount => BoxCount * BoxSlotCount;
|
||||
public virtual int PartyCount { get; protected set; }
|
||||
public virtual int MultiplayerSpriteID { get => 0; set { } }
|
||||
|
||||
public bool IsPartyAllEggs(params int[] except)
|
||||
{
|
||||
if (!HasParty)
|
||||
|
@ -446,6 +459,7 @@ namespace PKHeX.Core
|
|||
public virtual int CurrentBox { get => 0; set { } }
|
||||
protected int[] LockedSlots = Array.Empty<int>();
|
||||
protected int[] TeamSlots = Array.Empty<int>();
|
||||
|
||||
public bool MoveBox(int box, int insertBeforeBox)
|
||||
{
|
||||
if (box == insertBeforeBox) // no movement required
|
||||
|
@ -484,6 +498,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool SwapBox(int box1, int box2)
|
||||
{
|
||||
if (box1 == box2) // no movement required
|
||||
|
@ -514,10 +529,11 @@ namespace PKHeX.Core
|
|||
SetBoxWallpaper(box2, b1w);
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool IsBoxAbleToMove(int box)
|
||||
{
|
||||
int min = BoxSlotCount * box;
|
||||
int max = BoxSlotCount * box + BoxSlotCount;
|
||||
int max = min + BoxSlotCount;
|
||||
if (LockedSlots.Any(slot => min <= slot && slot < max)) // locked slot within box
|
||||
return false;
|
||||
if (TeamSlots.Any(slot => min <= slot && slot < max)) // team slot within box
|
||||
|
@ -526,6 +542,7 @@ namespace PKHeX.Core
|
|||
}
|
||||
|
||||
protected virtual int GetBoxWallpaperOffset(int box) => -1;
|
||||
|
||||
public virtual int GetBoxWallpaper(int box)
|
||||
{
|
||||
int offset = GetBoxWallpaperOffset(box);
|
||||
|
@ -533,6 +550,7 @@ namespace PKHeX.Core
|
|||
return box;
|
||||
return Data[offset];
|
||||
}
|
||||
|
||||
public virtual void SetBoxWallpaper(int box, int value)
|
||||
{
|
||||
int offset = GetBoxWallpaperOffset(box);
|
||||
|
@ -551,12 +569,15 @@ namespace PKHeX.Core
|
|||
|
||||
public PKM GetPartySlotAtIndex(int index) => GetPartySlot(GetPartyOffset(index));
|
||||
public PKM GetBoxSlotAtIndex(int box, int slot) => GetStoredSlot(GetBoxSlotOffset(box, slot));
|
||||
|
||||
public PKM GetBoxSlotAtIndex(int index)
|
||||
{
|
||||
GetBoxSlotFromIndex(index, out int box, out int slot);
|
||||
return GetBoxSlotAtIndex(box, slot);
|
||||
}
|
||||
public int GetBoxSlotOffset(int box, int slot) => GetBoxOffset(box) + slot * SIZE_STORED;
|
||||
|
||||
public int GetBoxSlotOffset(int box, int slot) => GetBoxOffset(box) + (slot * SIZE_STORED);
|
||||
|
||||
public int GetBoxSlotOffset(int index)
|
||||
{
|
||||
GetBoxSlotFromIndex(index, out int box, out int slot);
|
||||
|
@ -568,10 +589,12 @@ namespace PKHeX.Core
|
|||
public void SetPartySlotAtIndex(PKM pkm, int index, bool? trade = null, bool? dex = null) => SetPartySlot(pkm, GetPartyOffset(index), trade, dex);
|
||||
|
||||
public virtual PKM GetPartySlot(int offset) => GetPKM(DecryptPKM(GetData(offset, SIZE_PARTY)));
|
||||
|
||||
public virtual PKM GetStoredSlot(int offset)
|
||||
{
|
||||
return GetPKM(DecryptPKM(GetData(offset, SIZE_STORED)));
|
||||
}
|
||||
|
||||
public void SetPartySlot(PKM pkm, int offset, bool? trade = null, bool? dex = null)
|
||||
{
|
||||
if (pkm == null) return;
|
||||
|
@ -594,18 +617,24 @@ namespace PKHeX.Core
|
|||
PartyCount = i + 1;
|
||||
}
|
||||
else if (PartyCount > i)
|
||||
{
|
||||
PartyCount = i;
|
||||
}
|
||||
|
||||
SetData(pkm.EncryptedPartyData, offset);
|
||||
Edited = true;
|
||||
}
|
||||
|
||||
private int GetPartyIndex(int offset)
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
if (GetPartyOffset(i) == offset)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public virtual void SetStoredSlot(PKM pkm, int offset, bool? trade = null, bool? dex = null)
|
||||
{
|
||||
if (pkm == null) return;
|
||||
|
@ -619,6 +648,7 @@ namespace PKHeX.Core
|
|||
SetData(pkm.EncryptedBoxData, offset);
|
||||
Edited = true;
|
||||
}
|
||||
|
||||
public void DeletePartySlot(int slot)
|
||||
{
|
||||
if (PartyCount <= slot) // beyond party range (or empty data already present)
|
||||
|
@ -633,11 +663,14 @@ namespace PKHeX.Core
|
|||
SetStoredSlot(BlankPKM, GetPartyOffset(5), false, false);
|
||||
PartyCount--;
|
||||
}
|
||||
|
||||
public virtual bool IsSlotLocked(int box, int slot) => false;
|
||||
|
||||
public bool IsAnySlotLockedInBox(int BoxStart, int BoxEnd)
|
||||
{
|
||||
return LockedSlots.Any(slot => BoxStart*BoxSlotCount <= slot && slot < (BoxEnd + 1)*BoxSlotCount);
|
||||
}
|
||||
|
||||
public virtual bool IsSlotInBattleTeam(int box, int slot) => false;
|
||||
|
||||
public void SortBoxes(int BoxStart = 0, int BoxEnd = -1, Func<IEnumerable<PKM>, IEnumerable<PKM>> sortMethod = null, bool reverse = false)
|
||||
|
@ -655,6 +688,7 @@ namespace PKHeX.Core
|
|||
Sorted.CopyTo(BD, start);
|
||||
BoxData = BD;
|
||||
}
|
||||
|
||||
public void ClearBoxes(int BoxStart = 0, int BoxEnd = -1, Func<PKM, bool> deleteCriteria = null)
|
||||
{
|
||||
if (BoxEnd < 0)
|
||||
|
@ -671,7 +705,7 @@ namespace PKHeX.Core
|
|||
{
|
||||
if (IsSlotLocked(i, p))
|
||||
continue;
|
||||
var ofs = offset + SIZE_STORED * p;
|
||||
var ofs = offset + (SIZE_STORED * p);
|
||||
if (deleteCriteria != null)
|
||||
{
|
||||
var pk = GetStoredSlot(ofs);
|
||||
|
@ -683,24 +717,29 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ModifyBoxes(Action<PKM> action, int BoxStart = 0, int BoxEnd = -1)
|
||||
{
|
||||
if (BoxEnd < 0)
|
||||
BoxEnd = BoxCount - 1;
|
||||
var BD = BoxData;
|
||||
for (int b = BoxStart; b <= BoxEnd; b++)
|
||||
for (int s = 0; s < BoxSlotCount; s++)
|
||||
{
|
||||
if (IsSlotLocked(b, s))
|
||||
continue;
|
||||
var index = b * BoxSlotCount + s;
|
||||
action(BD[index]);
|
||||
for (int s = 0; s < BoxSlotCount; s++)
|
||||
{
|
||||
if (IsSlotLocked(b, s))
|
||||
continue;
|
||||
var index = (b * BoxSlotCount) + s;
|
||||
action(BD[index]);
|
||||
}
|
||||
}
|
||||
|
||||
BoxData = BD;
|
||||
}
|
||||
|
||||
public byte[] PCBinary => BoxData.SelectMany(pk => pk.EncryptedBoxData).ToArray();
|
||||
public byte[] GetBoxBinary(int box) => BoxData.Skip(box*BoxSlotCount).Take(BoxSlotCount).SelectMany(pk => pk.EncryptedBoxData).ToArray();
|
||||
|
||||
public bool SetPCBinary(byte[] data)
|
||||
{
|
||||
if (LockedSlots.Length != 0)
|
||||
|
@ -714,6 +753,7 @@ namespace PKHeX.Core
|
|||
BoxData = BD;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool SetBoxBinary(byte[] data, int box)
|
||||
{
|
||||
int start = box * BoxSlotCount;
|
||||
|
@ -739,6 +779,7 @@ namespace PKHeX.Core
|
|||
pkm.SetStats(pkm.GetStats(pkm.PersonalInfo));
|
||||
pkm.Stat_Level = pkm.CurrentLevel;
|
||||
}
|
||||
|
||||
protected virtual void SetPKM(PKM pkm) { }
|
||||
protected virtual void SetDex(PKM pkm) { }
|
||||
public virtual bool GetSeen(int species) => false;
|
||||
|
@ -756,12 +797,15 @@ namespace PKHeX.Core
|
|||
Buffer.BlockCopy(Data, Offset, data, 0, Length);
|
||||
return data;
|
||||
}
|
||||
|
||||
public void SetData(byte[] input, int Offset)
|
||||
{
|
||||
input.CopyTo(Data, Offset);
|
||||
Edited = true;
|
||||
}
|
||||
|
||||
public bool IsRangeEmpty(int Offset, int Length) => IsRangeAll(Offset, Length, 0);
|
||||
|
||||
public bool IsRangeAll(int Offset, int Length, int value)
|
||||
{
|
||||
for (int i = Offset; i < Offset + Length; i++)
|
||||
|
@ -769,6 +813,7 @@ namespace PKHeX.Core
|
|||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual bool IsPKMPresent(int Offset) => PKX.IsPKMPresent(Data, Offset);
|
||||
|
||||
public abstract string GetString(int Offset, int Length);
|
||||
|
|
|
@ -456,43 +456,48 @@ namespace PKHeX.Core
|
|||
public static SaveFile GetVariantSAV(byte[] data)
|
||||
{
|
||||
// Pre-check for header/footer signatures
|
||||
SaveFile sav;
|
||||
byte[] header = new byte[0], footer = new byte[0];
|
||||
byte[] header = Array.Empty<byte>(), footer = Array.Empty<byte>();
|
||||
CheckHeaderFooter(ref data, ref header, ref footer);
|
||||
var sav = GetVariantSAVInternal(data);
|
||||
if (sav == null)
|
||||
return null;
|
||||
sav.Header = header;
|
||||
sav.Footer = footer;
|
||||
return sav;
|
||||
}
|
||||
|
||||
private static SaveFile GetVariantSAVInternal(byte[] data)
|
||||
{
|
||||
switch (GetSAVGeneration(data))
|
||||
{
|
||||
// Main Games
|
||||
case GameVersion.Gen1: sav = new SAV1(data); break;
|
||||
case GameVersion.Gen2: sav = new SAV2(data); break;
|
||||
case GameVersion.Gen3: sav = new SAV3(data); break;
|
||||
case GameVersion.Gen4: sav = new SAV4(data); break;
|
||||
case GameVersion.Gen5: sav = new SAV5(data); break;
|
||||
case GameVersion.Gen6: sav = new SAV6(data); break;
|
||||
case GameVersion.Gen7: sav = new SAV7(data); break;
|
||||
case GameVersion.Gen1: return new SAV1(data);
|
||||
case GameVersion.Gen2: return new SAV2(data);
|
||||
case GameVersion.Gen3: return new SAV3(data);
|
||||
case GameVersion.Gen4: return new SAV4(data);
|
||||
case GameVersion.Gen5: return new SAV5(data);
|
||||
case GameVersion.Gen6: return new SAV6(data);
|
||||
case GameVersion.Gen7: return new SAV7(data);
|
||||
|
||||
// Side Games
|
||||
case GameVersion.COLO: sav = new SAV3Colosseum(data); break;
|
||||
case GameVersion.XD: sav = new SAV3XD(data); break;
|
||||
case GameVersion.RSBOX: sav = new SAV3RSBox(data); break;
|
||||
case GameVersion.BATREV: sav = new SAV4BR(data); break;
|
||||
case GameVersion.COLO: return new SAV3Colosseum(data);
|
||||
case GameVersion.XD: return new SAV3XD(data);
|
||||
case GameVersion.RSBOX: return new SAV3RSBox(data);
|
||||
case GameVersion.BATREV: return new SAV4BR(data);
|
||||
|
||||
// Bulk Storage
|
||||
case GameVersion.USUM: sav = Bank7.GetBank7(data); break;
|
||||
case GameVersion.USUM: return Bank7.GetBank7(data);
|
||||
|
||||
// No pattern matched
|
||||
default: return null;
|
||||
}
|
||||
sav.Header = header;
|
||||
sav.Footer = footer;
|
||||
return sav;
|
||||
}
|
||||
|
||||
public static SaveFile GetVariantSAV(SAV3GCMemoryCard MC)
|
||||
{
|
||||
// Pre-check for header/footer signatures
|
||||
SaveFile sav;
|
||||
byte[] header = new byte[0], footer = new byte[0];
|
||||
byte[] header = Array.Empty<byte>(), footer = Array.Empty<byte>();
|
||||
byte[] data = MC.SelectedSaveData;
|
||||
CheckHeaderFooter(ref data, ref header, ref footer);
|
||||
|
||||
|
|
|
@ -142,7 +142,7 @@ namespace PKHeX.WinForms.Controls
|
|||
|
||||
public void SetPKMFormatMode(int Format)
|
||||
{
|
||||
byte[] extraBytes = new byte[0];
|
||||
byte[] extraBytes = Array.Empty<byte>();
|
||||
switch (Format)
|
||||
{
|
||||
case 1:
|
||||
|
@ -288,8 +288,6 @@ namespace PKHeX.WinForms.Controls
|
|||
var index = WinFormsUtil.GetIndex(c);
|
||||
c.DataSource = new BindingSource(MoveDataAllowed, null);
|
||||
c.SelectedValue = index;
|
||||
if (c.Visible)
|
||||
c.SelectionLength = 0; // flicker hack
|
||||
}
|
||||
|
||||
public void UpdateUnicode(string[] symbols)
|
||||
|
|
|
@ -62,6 +62,7 @@ namespace PKHeX.WinForms.Controls
|
|||
Parent = FindForm(),
|
||||
};
|
||||
}
|
||||
|
||||
private int GetSlot(PictureBox sender) => SlotPictureBoxes.IndexOf(WinFormsUtil.GetUnderlyingControl(sender) as PictureBox);
|
||||
public int GetSlotOffset(int box, int slot) => GetOffset(slot, box);
|
||||
public int GetSlotOffset(int slot) => GetSlotOffset(CurrentBox, slot);
|
||||
|
@ -72,23 +73,28 @@ namespace PKHeX.WinForms.Controls
|
|||
get => CB_BoxSelect.Enabled;
|
||||
set => CB_BoxSelect.Enabled = CB_BoxSelect.Visible = B_BoxLeft.Visible = B_BoxRight.Visible = value;
|
||||
}
|
||||
|
||||
public bool ControlsEnabled
|
||||
{
|
||||
get => CB_BoxSelect.Enabled;
|
||||
set => CB_BoxSelect.Enabled = B_BoxLeft.Enabled = B_BoxRight.Enabled = value;
|
||||
}
|
||||
|
||||
public int CurrentBox
|
||||
{
|
||||
get => CB_BoxSelect.SelectedIndex;
|
||||
set => CB_BoxSelect.SelectedIndex = value;
|
||||
}
|
||||
|
||||
public string CurrentBoxName => CB_BoxSelect.Text;
|
||||
|
||||
public int GetOffset(int slot, int box)
|
||||
{
|
||||
if (box < 0)
|
||||
box = CurrentBox;
|
||||
return SAV.GetBoxOffset(box) + slot * SAV.SIZE_STORED;
|
||||
return SAV.GetBoxOffset(box) + (slot * SAV.SIZE_STORED);
|
||||
}
|
||||
|
||||
public void Setup(SlotChangeManager m)
|
||||
{
|
||||
M = m;
|
||||
|
@ -96,6 +102,7 @@ namespace PKHeX.WinForms.Controls
|
|||
FlagIllegal = M.SE.FlagIllegal;
|
||||
Reset();
|
||||
}
|
||||
|
||||
public void SetSlotFiller(PKM p, int box = -1, int slot = -1, PictureBox pb = null)
|
||||
{
|
||||
if (pb == null)
|
||||
|
@ -147,6 +154,7 @@ namespace PKHeX.WinForms.Controls
|
|||
CB_BoxSelect.Items.Add($"Box {i+1}");
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetSlots()
|
||||
{
|
||||
int box = CurrentBox;
|
||||
|
@ -161,12 +169,13 @@ namespace PKHeX.WinForms.Controls
|
|||
{
|
||||
var pb = SlotPictureBoxes[i];
|
||||
if (i < SAV.BoxSlotCount)
|
||||
GetSlotFiller(boxoffset + SAV.SIZE_STORED * i, pb, box, i);
|
||||
GetSlotFiller(boxoffset + (SAV.SIZE_STORED * i), pb, box, i);
|
||||
else
|
||||
pb.Visible = false;
|
||||
pb.BackgroundImage = slot == i ? M?.ColorizedColor : null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool SaveBoxBinary()
|
||||
{
|
||||
DialogResult dr = WinFormsUtil.Prompt(MessageBoxButtons.YesNoCancel,
|
||||
|
@ -192,6 +201,7 @@ namespace PKHeX.WinForms.Controls
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void ClearEvents()
|
||||
{
|
||||
B_BoxRight.Click -= ClickBoxRight;
|
||||
|
@ -204,6 +214,7 @@ namespace PKHeX.WinForms.Controls
|
|||
ResetBoxNames();
|
||||
ResetSlots();
|
||||
}
|
||||
|
||||
private void GetBox(object sender, EventArgs e)
|
||||
{
|
||||
if (SAV.CurrentBox != CurrentBox)
|
||||
|
@ -211,16 +222,21 @@ namespace PKHeX.WinForms.Controls
|
|||
ResetSlots();
|
||||
M?.RefreshHoverSlot(this);
|
||||
}
|
||||
|
||||
private void ClickBoxLeft(object sender, EventArgs e) => MoveLeft(ModifierKeys == Keys.Control);
|
||||
|
||||
public void MoveLeft(bool max = false)
|
||||
{
|
||||
CurrentBox = max ? 0 : (CurrentBox + SAV.BoxCount - 1) % SAV.BoxCount;
|
||||
}
|
||||
|
||||
private void ClickBoxRight(object sender, EventArgs e) => MoveRight(ModifierKeys == Keys.Control);
|
||||
|
||||
public void MoveRight(bool max = false)
|
||||
{
|
||||
CurrentBox = max ? SAV.BoxCount - 1 : (CurrentBox + 1) % SAV.BoxCount;
|
||||
}
|
||||
|
||||
private void GetSlotFiller(int offset, PictureBox pb, int box = -1, int slot = -1)
|
||||
{
|
||||
if (!SAV.IsPKMPresent(offset))
|
||||
|
|
|
@ -44,6 +44,7 @@ namespace PKHeX.WinForms.Controls
|
|||
IsPartyFormat = type.IsParty(SAV.Generation)
|
||||
};
|
||||
}
|
||||
|
||||
public IList<PictureBox> SlotPictureBoxes { get; }
|
||||
public int GetSlot(PictureBox sender) => SlotPictureBoxes.IndexOf(WinFormsUtil.GetUnderlyingControl(sender) as PictureBox);
|
||||
public int ViewIndex { get; set; } = -1;
|
||||
|
@ -57,6 +58,7 @@ namespace PKHeX.WinForms.Controls
|
|||
ReloadSlots();
|
||||
}
|
||||
}
|
||||
|
||||
public void ReloadSlots()
|
||||
{
|
||||
UpdateBoxViewers(all: true);
|
||||
|
@ -110,6 +112,7 @@ namespace PKHeX.WinForms.Controls
|
|||
SL_Extra.ViewIndex = -2;
|
||||
M.OtherSlots.Add(SL_Extra);
|
||||
}
|
||||
|
||||
private void InitializeDragDrop(Control pb)
|
||||
{
|
||||
pb.MouseEnter += M.MouseEnter;
|
||||
|
@ -129,6 +132,7 @@ namespace PKHeX.WinForms.Controls
|
|||
|
||||
/// <summary>Occurs when the Control Collection requests a cloning operation to the current box.</summary>
|
||||
public event EventHandler RequestCloneData;
|
||||
|
||||
/// <summary>Occurs when the Control Collection requests a save to be reloaded.</summary>
|
||||
public event EventHandler RequestReloadSave;
|
||||
|
||||
|
@ -154,7 +158,7 @@ namespace PKHeX.WinForms.Controls
|
|||
if (slot < (int)SlotIndex.BattleBox) // Party Slot
|
||||
return SAV.GetPartyOffset(slot - (int)SlotIndex.Party);
|
||||
if (slot < (int)SlotIndex.Daycare) // Battle Box Slot
|
||||
return SAV.BattleBox + (slot - (int)SlotIndex.BattleBox) * SAV.SIZE_STORED;
|
||||
return SAV.BattleBox + ((slot - (int)SlotIndex.BattleBox) * SAV.SIZE_STORED);
|
||||
return SAV.GetDaycareSlotOffset(SAV.DaycareIndex, slot - (int)SlotIndex.Daycare);
|
||||
}
|
||||
|
||||
|
@ -164,6 +168,7 @@ namespace PKHeX.WinForms.Controls
|
|||
Box.CurrentBox = viewBox;
|
||||
return mainBox;
|
||||
}
|
||||
|
||||
public void UpdateBoxViewers(bool all = false)
|
||||
{
|
||||
foreach (var v in M.Boxes.Where(v => v.CurrentBox == Box.CurrentBox || all))
|
||||
|
@ -172,6 +177,7 @@ namespace PKHeX.WinForms.Controls
|
|||
v.ResetSlots();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetPKMBoxes()
|
||||
{
|
||||
if (SAV.HasBox)
|
||||
|
@ -183,6 +189,7 @@ namespace PKHeX.WinForms.Controls
|
|||
if (M?.ColorizedSlot >= (int)SlotIndex.Party && M.ColorizedSlot < SlotPictureBoxes.Count)
|
||||
SlotPictureBoxes[M.ColorizedSlot].BackgroundImage = M.ColorizedColor;
|
||||
}
|
||||
|
||||
private void ResetNonBoxSlots()
|
||||
{
|
||||
ResetParty();
|
||||
|
@ -190,12 +197,14 @@ namespace PKHeX.WinForms.Controls
|
|||
ResetDaycare();
|
||||
ResetMiscSlots();
|
||||
}
|
||||
|
||||
private void ResetMiscSlots()
|
||||
{
|
||||
var slots = SL_Extra.SlotPictureBoxes;
|
||||
for (int i = 0; i < SL_Extra.SlotCount; i++)
|
||||
GetSlotFiller(SL_Extra.GetSlotOffset(i), slots[i]);
|
||||
}
|
||||
|
||||
private void ResetParty()
|
||||
{
|
||||
if (!SAV.HasParty)
|
||||
|
@ -204,18 +213,20 @@ namespace PKHeX.WinForms.Controls
|
|||
for (int i = 0; i < 6; i++)
|
||||
GetSlotFiller(SAV.GetPartyOffset(i), SlotPictureBoxes[i + (int)SlotIndex.Party]);
|
||||
}
|
||||
|
||||
private void ResetBattleBox()
|
||||
{
|
||||
if (!SAV.HasBattleBox)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
GetSlotFiller(SAV.BattleBox + SAV.SIZE_STORED * i, SlotPictureBoxes[i + (int)SlotIndex.BattleBox]);
|
||||
GetSlotFiller(SAV.BattleBox + (SAV.SIZE_STORED * i), SlotPictureBoxes[i + (int)SlotIndex.BattleBox]);
|
||||
}
|
||||
|
||||
private readonly Label[] L_SlotOccupied;
|
||||
private readonly TextBox[] TB_SlotEXP;
|
||||
private readonly Label[] L_SlotEXP;
|
||||
|
||||
private void ResetDaycare()
|
||||
{
|
||||
if (!SAV.HasDaycare)
|
||||
|
@ -231,7 +242,9 @@ namespace PKHeX.WinForms.Controls
|
|||
bool? occ = SAV.IsDaycareOccupied(SAV.DaycareIndex, i);
|
||||
L_SlotOccupied[i].Visible = occ != null;
|
||||
if (occ == true) // If Occupied
|
||||
{
|
||||
L_SlotOccupied[i].Text = $"{i + 1}: ✓";
|
||||
}
|
||||
else
|
||||
{
|
||||
L_SlotOccupied[i].Text = $"{i + 1}: ✘";
|
||||
|
@ -251,6 +264,7 @@ namespace PKHeX.WinForms.Controls
|
|||
}
|
||||
L_DaycareSeed.Visible = TB_RNGSeed.Visible = seed != null;
|
||||
}
|
||||
|
||||
public void SetParty()
|
||||
{
|
||||
// Refresh slots
|
||||
|
@ -271,6 +285,7 @@ namespace PKHeX.WinForms.Controls
|
|||
SlotPictureBoxes[i + (int)SlotIndex.BattleBox].Image = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void ClickUndo()
|
||||
{
|
||||
if (UndoStack.Count == 0)
|
||||
|
@ -290,6 +305,7 @@ namespace PKHeX.WinForms.Controls
|
|||
UndoSlotChange(change);
|
||||
M.SetColor(change.Box, change.Slot, Resources.slotSet);
|
||||
}
|
||||
|
||||
public void ClickRedo()
|
||||
{
|
||||
if (RedoStack.Count == 0)
|
||||
|
@ -309,6 +325,7 @@ namespace PKHeX.WinForms.Controls
|
|||
UndoSlotChange(change);
|
||||
M.SetColor(change.Box, change.Slot, Resources.slotSet);
|
||||
}
|
||||
|
||||
public void SetClonesToBox(PKM pk)
|
||||
{
|
||||
if (WinFormsUtil.Prompt(MessageBoxButtons.YesNo, string.Format(MsgSaveBoxCloneFromTabs, Box.CurrentBoxName)) != DialogResult.Yes)
|
||||
|
@ -320,6 +337,7 @@ namespace PKHeX.WinForms.Controls
|
|||
|
||||
UpdateBoxViewers();
|
||||
}
|
||||
|
||||
private int SetClonesToCurrentBox(PKM pk, int box)
|
||||
{
|
||||
int slotSkipped = 0;
|
||||
|
@ -333,6 +351,7 @@ namespace PKHeX.WinForms.Controls
|
|||
|
||||
return slotSkipped;
|
||||
}
|
||||
|
||||
public void ClickSlot(object sender, EventArgs e)
|
||||
{
|
||||
switch (ModifierKeys)
|
||||
|
@ -364,6 +383,7 @@ namespace PKHeX.WinForms.Controls
|
|||
|
||||
SystemSounds.Asterisk.Play();
|
||||
}
|
||||
|
||||
private void GetSlotFiller(int offset, PictureBox pb)
|
||||
{
|
||||
if (!SAV.IsPKMPresent(offset))
|
||||
|
@ -408,6 +428,7 @@ namespace PKHeX.WinForms.Controls
|
|||
var pt = Tab_Box.PointToScreen(new Point(0, 0));
|
||||
SortMenu.Show(pt);
|
||||
}
|
||||
|
||||
public void ClearAll(Func<PKM, bool> criteria)
|
||||
{
|
||||
if (!CanManipulateRegion(0, SAV.BoxCount - 1, MsgSaveBoxClearAll, MsgSaveBoxClearAllFailBattle))
|
||||
|
@ -415,6 +436,7 @@ namespace PKHeX.WinForms.Controls
|
|||
SAV.ClearBoxes(deleteCriteria: criteria);
|
||||
FinishBoxManipulation(MsgSaveBoxClearAllSuccess, true);
|
||||
}
|
||||
|
||||
public void ClearCurrent(Func<PKM, bool> criteria)
|
||||
{
|
||||
if (!CanManipulateRegion(Box.CurrentBox, Box.CurrentBox, MsgSaveBoxClearCurrent, MsgSaveBoxClearCurrentFailBattle))
|
||||
|
@ -422,6 +444,7 @@ namespace PKHeX.WinForms.Controls
|
|||
SAV.ClearBoxes(Box.CurrentBox, Box.CurrentBox, criteria);
|
||||
FinishBoxManipulation(MsgSaveBoxClearCurrentSuccess, false);
|
||||
}
|
||||
|
||||
public void SortAll(Func<IEnumerable<PKM>, IEnumerable<PKM>> sorter, bool reverse)
|
||||
{
|
||||
if (!CanManipulateRegion(0, SAV.BoxCount - 1, MsgSaveBoxSortAll, MsgSaveBoxSortAllFailBattle))
|
||||
|
@ -429,6 +452,7 @@ namespace PKHeX.WinForms.Controls
|
|||
SAV.SortBoxes(sortMethod: sorter, reverse: reverse);
|
||||
FinishBoxManipulation(MsgSaveBoxSortAllSuccess, true);
|
||||
}
|
||||
|
||||
public void SortCurrent(Func<IEnumerable<PKM>, IEnumerable<PKM>> sorter, bool reverse)
|
||||
{
|
||||
if (!CanManipulateRegion(Box.CurrentBox, Box.CurrentBox, MsgSaveBoxSortCurrent, MsgSaveBoxSortCurrentFailBattle))
|
||||
|
@ -436,18 +460,21 @@ namespace PKHeX.WinForms.Controls
|
|||
SAV.SortBoxes(Box.CurrentBox, Box.CurrentBox, sorter, reverse: reverse);
|
||||
FinishBoxManipulation(MsgSaveBoxSortCurrentSuccess, false);
|
||||
}
|
||||
|
||||
public void ModifyAll(Action<PKM> action)
|
||||
{
|
||||
SAV.ModifyBoxes(action);
|
||||
FinishBoxManipulation(null, true);
|
||||
SystemSounds.Asterisk.Play();
|
||||
}
|
||||
|
||||
public void ModifyCurrent(Action<PKM> action)
|
||||
{
|
||||
SAV.ModifyBoxes(action, Box.CurrentBox, Box.CurrentBox);
|
||||
FinishBoxManipulation(null, true);
|
||||
SystemSounds.Asterisk.Play();
|
||||
}
|
||||
|
||||
private void FinishBoxManipulation(string message, bool all)
|
||||
{
|
||||
SetPKMBoxes();
|
||||
|
@ -455,6 +482,7 @@ namespace PKHeX.WinForms.Controls
|
|||
if (message != null)
|
||||
WinFormsUtil.Alert(message);
|
||||
}
|
||||
|
||||
private bool CanManipulateRegion(int start, int end, string prompt, string fail)
|
||||
{
|
||||
if (prompt != null && WinFormsUtil.Prompt(MessageBoxButtons.YesNo, prompt) != DialogResult.Yes)
|
||||
|
@ -492,12 +520,14 @@ namespace PKHeX.WinForms.Controls
|
|||
{ var z = M.Boxes[1].ParentForm; z.CenterToForm(ParentForm); z.BringToFront(); return; }
|
||||
new SAV_BoxViewer(this, M).Show();
|
||||
}
|
||||
|
||||
private void ClickClone(object sender, EventArgs e)
|
||||
{
|
||||
if (GetSlot((PictureBox)sender) >= 0)
|
||||
return; // only perform action if cloning to boxes
|
||||
RequestCloneData?.Invoke(sender, e);
|
||||
}
|
||||
|
||||
private void UpdateSaveSlot(object sender, EventArgs e)
|
||||
{
|
||||
if (SAV.Version != GameVersion.BATREV)
|
||||
|
@ -507,6 +537,7 @@ namespace PKHeX.WinForms.Controls
|
|||
SetPKMBoxes();
|
||||
UpdateBoxViewers(true);
|
||||
}
|
||||
|
||||
private void UpdateStringSeed(object sender, EventArgs e)
|
||||
{
|
||||
if (!FieldsLoaded)
|
||||
|
@ -552,6 +583,7 @@ namespace PKHeX.WinForms.Controls
|
|||
SAV.Edited = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void SwitchDaycare(object sender, EventArgs e)
|
||||
{
|
||||
if (!SAV.HasTwoDaycares)
|
||||
|
@ -562,6 +594,7 @@ namespace PKHeX.WinForms.Controls
|
|||
SAV.DaycareIndex ^= 1;
|
||||
ResetDaycare();
|
||||
}
|
||||
|
||||
private void B_SaveBoxBin_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (!SAV.HasBox)
|
||||
|
@ -583,11 +616,13 @@ namespace PKHeX.WinForms.Controls
|
|||
private void B_Roamer_Click(object sender, EventArgs e) => new SAV_Roamer3(SAV).ShowDialog();
|
||||
private void B_OpenApricorn_Click(object sender, EventArgs e) => new SAV_Apricorn(SAV).ShowDialog();
|
||||
private void B_CGearSkin_Click(object sender, EventArgs e) => new SAV_CGearSkin(SAV).ShowDialog();
|
||||
|
||||
private void B_OpenEventFlags_Click(object sender, EventArgs e)
|
||||
{
|
||||
var form = SAV.Generation == 1 ? new SAV_EventReset1(SAV) as Form : new SAV_EventFlags(SAV);
|
||||
form.ShowDialog();
|
||||
}
|
||||
|
||||
private void B_OpenBoxLayout_Click(object sender, EventArgs e)
|
||||
{
|
||||
new SAV_BoxLayout(SAV, Box.CurrentBox).ShowDialog();
|
||||
|
@ -595,6 +630,7 @@ namespace PKHeX.WinForms.Controls
|
|||
Box.ResetSlots(); // refresh box background
|
||||
UpdateBoxViewers(all: true); // update subviewers
|
||||
}
|
||||
|
||||
private void B_OpenTrainerInfo_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (SAV.Generation < 6)
|
||||
|
@ -604,12 +640,14 @@ namespace PKHeX.WinForms.Controls
|
|||
else if (SAV is SAV7)
|
||||
new SAV_Trainer7(SAV).ShowDialog();
|
||||
}
|
||||
|
||||
private void B_OpenOPowers_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (SAV.Generation != 6)
|
||||
return;
|
||||
new SAV_OPower((SAV6)SAV).ShowDialog();
|
||||
}
|
||||
|
||||
private void B_OpenFriendSafari_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (!SAV.XY)
|
||||
|
@ -636,11 +674,13 @@ namespace PKHeX.WinForms.Controls
|
|||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void B_OpenPokedex_Click(object sender, EventArgs e)
|
||||
{
|
||||
var editor = GetPokeDexEditor(SAV);
|
||||
editor?.ShowDialog();
|
||||
}
|
||||
|
||||
private void B_OpenMiscEditor_Click(object sender, EventArgs e)
|
||||
{
|
||||
switch (SAV.Generation)
|
||||
|
@ -650,6 +690,7 @@ namespace PKHeX.WinForms.Controls
|
|||
case 5: new SAV_Misc5(SAV).ShowDialog(); break;
|
||||
}
|
||||
}
|
||||
|
||||
private void B_OpenRTCEditor_Click(object sender, EventArgs e)
|
||||
{
|
||||
switch (SAV.Generation)
|
||||
|
@ -660,6 +701,7 @@ namespace PKHeX.WinForms.Controls
|
|||
new SAV_RTC3(SAV).ShowDialog(); break;
|
||||
}
|
||||
}
|
||||
|
||||
private void B_OpenHoneyTreeEditor_Click(object sender, EventArgs e)
|
||||
{
|
||||
switch (SAV.Version)
|
||||
|
@ -669,6 +711,7 @@ namespace PKHeX.WinForms.Controls
|
|||
new SAV_HoneyTree(SAV).ShowDialog(); break;
|
||||
}
|
||||
}
|
||||
|
||||
private void B_OUTPasserby_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (SAV.Generation != 6)
|
||||
|
@ -678,6 +721,7 @@ namespace PKHeX.WinForms.Controls
|
|||
var result = PSS6.GetPSSParse((SAV6)SAV);
|
||||
Clipboard.SetText(string.Join(Environment.NewLine, result));
|
||||
}
|
||||
|
||||
private void B_OUTHallofFame_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (SAV.Generation == 6)
|
||||
|
@ -685,6 +729,7 @@ namespace PKHeX.WinForms.Controls
|
|||
else if (SAV is SAV7)
|
||||
new SAV_HallOfFame7(SAV).ShowDialog();
|
||||
}
|
||||
|
||||
private void B_JPEG_Click(object sender, EventArgs e)
|
||||
{
|
||||
byte[] jpeg = SAV.JPEGData;
|
||||
|
@ -695,6 +740,7 @@ namespace PKHeX.WinForms.Controls
|
|||
if (sfd.ShowDialog() != DialogResult.OK) return;
|
||||
File.WriteAllBytes(sfd.FileName, jpeg);
|
||||
}
|
||||
|
||||
private void ClickVerifyCHK(object sender, EventArgs e)
|
||||
{
|
||||
if (SAV.Edited) { WinFormsUtil.Alert(MsgSaveChecksumFailEdited); return; }
|
||||
|
@ -716,6 +762,7 @@ namespace PKHeX.WinForms.Controls
|
|||
noSetb = GetPKMSetOverride();
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool? GetPKMSetOverride()
|
||||
{
|
||||
var yn = ModifyPKM ? MsgYes : MsgNo;
|
||||
|
@ -726,6 +773,7 @@ namespace PKHeX.WinForms.Controls
|
|||
string.Format(MsgSaveBoxImportModifyCurrent, yn));
|
||||
return noSet == DialogResult.Yes || noSet == DialogResult.No ? (bool?)false : null;
|
||||
}
|
||||
|
||||
private static bool IsFolderPath(out string path)
|
||||
{
|
||||
FolderBrowserDialog fbd = new FolderBrowserDialog();
|
||||
|
@ -739,6 +787,7 @@ namespace PKHeX.WinForms.Controls
|
|||
ValidateChildren();
|
||||
return WinFormsUtil.SaveSAVDialog(SAV, SAV.CurrentBox);
|
||||
}
|
||||
|
||||
public bool ExportBackup()
|
||||
{
|
||||
if (!SAV.Exportable)
|
||||
|
@ -753,7 +802,9 @@ namespace PKHeX.WinForms.Controls
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsPCBoxBin(int length) => PKX.IsPKM(length / SAV.SlotCount) || PKX.IsPKM(length / SAV.BoxSlotCount);
|
||||
|
||||
public bool OpenPCBoxBin(byte[] input, out string c)
|
||||
{
|
||||
if (SAV.PCBinary.Length == input.Length)
|
||||
|
@ -783,6 +834,7 @@ namespace PKHeX.WinForms.Controls
|
|||
UpdateBoxViewers();
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool OpenBattleVideo(BattleVideo b, out string c)
|
||||
{
|
||||
if (b == null || SAV.Generation != b.Generation)
|
||||
|
@ -807,7 +859,7 @@ namespace PKHeX.WinForms.Controls
|
|||
{
|
||||
if (SAV.IsSlotLocked(Box.CurrentBox, i))
|
||||
{ slotSkipped++; continue; }
|
||||
SAV.SetStoredSlot(data[i], offset + i * SAV.SIZE_STORED, noSetb);
|
||||
SAV.SetStoredSlot(data[i], offset + (i * SAV.SIZE_STORED), noSetb);
|
||||
}
|
||||
|
||||
SetPKMBoxes();
|
||||
|
@ -817,6 +869,7 @@ namespace PKHeX.WinForms.Controls
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool DumpBoxes(out string result, string path = null, bool separate = false)
|
||||
{
|
||||
if (path == null && !IsFolderPath(out path))
|
||||
|
@ -830,6 +883,7 @@ namespace PKHeX.WinForms.Controls
|
|||
SAV.DumpBoxes(path, out result, separate);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool DumpBox(out string result, string path = null)
|
||||
{
|
||||
if (path == null && !IsFolderPath(out path))
|
||||
|
@ -843,6 +897,7 @@ namespace PKHeX.WinForms.Controls
|
|||
SAV.DumpBox(path, out result, Box.CurrentBox);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool LoadBoxes(out string result, string path = null)
|
||||
{
|
||||
result = string.Empty;
|
||||
|
@ -887,6 +942,7 @@ namespace PKHeX.WinForms.Controls
|
|||
FieldsLoaded = true;
|
||||
return WindowTranslationRequired;
|
||||
}
|
||||
|
||||
private void ToggleViewReset()
|
||||
{
|
||||
// Close subforms that are save dependent
|
||||
|
@ -900,6 +956,7 @@ namespace PKHeX.WinForms.Controls
|
|||
M.SetColor(-1, -1, null);
|
||||
SortMenu.ToggleVisibility();
|
||||
}
|
||||
|
||||
private bool ToggleViewBox(SaveFile sav)
|
||||
{
|
||||
if (!sav.HasBox)
|
||||
|
@ -920,6 +977,7 @@ namespace PKHeX.WinForms.Controls
|
|||
tabBoxMulti.TabPages.Insert(0, Tab_Box);
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ToggleViewParty(SaveFile sav, int BoxTab)
|
||||
{
|
||||
if (!sav.HasParty)
|
||||
|
@ -939,6 +997,7 @@ namespace PKHeX.WinForms.Controls
|
|||
tabBoxMulti.TabPages.Insert(index + 1, Tab_PartyBattle);
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ToggleViewDaycare(SaveFile sav, int BoxTab, int PartyTab)
|
||||
{
|
||||
if (!sav.HasDaycare)
|
||||
|
@ -960,6 +1019,7 @@ namespace PKHeX.WinForms.Controls
|
|||
tabBoxMulti.TabPages.Insert(index + 1, Tab_Other);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ToggleViewSubEditors(SaveFile sav)
|
||||
{
|
||||
if (!sav.Exportable || sav is BulkStorage)
|
||||
|
@ -1007,6 +1067,7 @@ namespace PKHeX.WinForms.Controls
|
|||
foreach (Control c in FLP_SAVtools.Controls.OfType<Control>())
|
||||
c.Visible = c.Enabled;
|
||||
}
|
||||
|
||||
private void ToggleViewMisc(SaveFile sav)
|
||||
{
|
||||
// Generational Interface
|
||||
|
@ -1081,6 +1142,7 @@ namespace PKHeX.WinForms.Controls
|
|||
catch { }
|
||||
WinFormsUtil.Alert(MsgSimulatorExportBattleBox);
|
||||
}
|
||||
|
||||
public void ClickShowdownExportCurrentBox(object sender, EventArgs e)
|
||||
{
|
||||
if (!SAV.HasBox)
|
||||
|
@ -1105,11 +1167,13 @@ namespace PKHeX.WinForms.Controls
|
|||
new SAV_Underground(SAV).ShowDialog(); break;
|
||||
}
|
||||
}
|
||||
|
||||
private void B_FestivalPlaza_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (SAV is SAV7)
|
||||
new SAV_FestivalPlaza(SAV).ShowDialog();
|
||||
}
|
||||
|
||||
private void B_MailBox_Click(object sender, EventArgs e)
|
||||
{
|
||||
new SAV_MailBox(SAV).ShowDialog();
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace PKHeX.WinForms
|
|||
public partial class TrashEditor : Form
|
||||
{
|
||||
private readonly SaveFile SAV;
|
||||
|
||||
public TrashEditor(TextBoxBase TB_NN, byte[] raw, SaveFile sav)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
@ -52,6 +53,7 @@ namespace PKHeX.WinForms
|
|||
private bool editing;
|
||||
private readonly bool bigendian;
|
||||
private void B_Cancel_Click(object sender, EventArgs e) => Close();
|
||||
|
||||
private void B_Save_Click(object sender, EventArgs e)
|
||||
{
|
||||
FinalString = TB_Text.Text;
|
||||
|
@ -77,6 +79,7 @@ namespace PKHeX.WinForms
|
|||
FLP_Characters.Controls.Add(l);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddTrashEditing(int count)
|
||||
{
|
||||
FLP_Hex.Visible = true;
|
||||
|
@ -87,7 +90,7 @@ namespace PKHeX.WinForms
|
|||
{
|
||||
var l = GetLabel($"${i:X2}");
|
||||
l.Font = courier;
|
||||
var n = GetNUD(hex: true, min: 0, max: 255);
|
||||
var n = GetNUD(min: 0, max: 255, hex: true);
|
||||
n.Click += (s, e) =>
|
||||
{
|
||||
switch (ModifierKeys)
|
||||
|
@ -126,6 +129,7 @@ namespace PKHeX.WinForms
|
|||
TB_Text.Text = str;
|
||||
editing = false;
|
||||
}
|
||||
|
||||
private void UpdateString(object sender, EventArgs e)
|
||||
{
|
||||
if (editing)
|
||||
|
@ -138,6 +142,7 @@ namespace PKHeX.WinForms
|
|||
Bytes[i].Value = Raw[i];
|
||||
editing = false;
|
||||
}
|
||||
|
||||
private void B_ApplyTrash_Click(object sender, EventArgs e)
|
||||
{
|
||||
string species = PKX.GetSpeciesNameGeneration(WinFormsUtil.GetIndex(CB_Species),
|
||||
|
@ -162,18 +167,21 @@ namespace PKHeX.WinForms
|
|||
for (int i = current.Length; i < data.Length; i++)
|
||||
Bytes[i].Value = data[i];
|
||||
}
|
||||
|
||||
private void B_ClearTrash_Click(object sender, EventArgs e)
|
||||
{
|
||||
byte[] current = SetString(TB_Text.Text);
|
||||
for (int i = current.Length; i < Bytes.Count; i++)
|
||||
Bytes[i].Value = 0;
|
||||
}
|
||||
|
||||
private byte[] SetString(string text)
|
||||
{
|
||||
return SAV is SAV2 s && s.Korean
|
||||
? StringConverter.SetString2KOR(text, Raw.Length)
|
||||
: StringConverter.SetString(text, SAV.Generation, SAV.Japanese, bigendian, Raw.Length, SAV.Language);
|
||||
}
|
||||
|
||||
private string GetString()
|
||||
{
|
||||
return SAV is SAV2 s && s.Korean
|
||||
|
@ -183,6 +191,7 @@ namespace PKHeX.WinForms
|
|||
|
||||
// Helpers
|
||||
private static Label GetLabel(string str) => new Label {Text = str, AutoSize = true};
|
||||
|
||||
private static NumericUpDown GetNUD(int min, int max, bool hex) => new NumericUpDown
|
||||
{
|
||||
Maximum = max,
|
||||
|
@ -203,6 +212,7 @@ namespace PKHeX.WinForms
|
|||
default: return Array.Empty<ushort>();
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly ushort[] chars67 =
|
||||
{
|
||||
0xE081, 0xE082, 0xE083, 0xE084, 0xE085, 0xE086, 0xE087, 0xE08D,
|
||||
|
|
|
@ -184,7 +184,7 @@ namespace PKHeX.WinForms
|
|||
// Data from Box: Delete from save file
|
||||
int box = pk.Box-1;
|
||||
int slot = pk.Slot-1;
|
||||
int offset = SAV.GetBoxOffset(box) + slot*SAV.SIZE_STORED;
|
||||
int offset = SAV.GetBoxOffset(box) + (slot *SAV.SIZE_STORED);
|
||||
PKM pkSAV = SAV.GetStoredSlot(offset);
|
||||
|
||||
if (!pkSAV.DecryptedBoxData.SequenceEqual(pk.DecryptedBoxData)) // data still exists in SAV, unmodified
|
||||
|
@ -239,7 +239,7 @@ namespace PKHeX.WinForms
|
|||
slotColor = Properties.Resources.slotSet;
|
||||
if ((SCR_Box.Maximum+1)*6 < Results.Count)
|
||||
SCR_Box.Maximum++;
|
||||
SCR_Box.Value = Math.Max(0, SCR_Box.Maximum - PKXBOXES.Length/6 + 1);
|
||||
SCR_Box.Value = Math.Max(0, SCR_Box.Maximum - (PKXBOXES.Length/6) + 1);
|
||||
FillPKXBoxes(SCR_Box.Value);
|
||||
WinFormsUtil.Alert(MsgDBAddFromTabsSuccess);
|
||||
}
|
||||
|
@ -320,8 +320,7 @@ namespace PKHeX.WinForms
|
|||
|
||||
private void GenerateDBReport(object sender, EventArgs e)
|
||||
{
|
||||
if (WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MsgDBCreateReportPrompt, MsgDBCreateReportWarning)
|
||||
!= DialogResult.Yes)
|
||||
if (WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MsgDBCreateReportPrompt, MsgDBCreateReportWarning) != DialogResult.Yes)
|
||||
return;
|
||||
|
||||
ReportGrid reportGrid = new ReportGrid();
|
||||
|
@ -352,8 +351,10 @@ namespace PKHeX.WinForms
|
|||
var sav = SaveUtil.GetVariantSAV(file);
|
||||
var path = EXTERNAL_SAV + new FileInfo(file).Name;
|
||||
if (sav.HasBox)
|
||||
{
|
||||
foreach (var pk in sav.BoxData)
|
||||
addPKM(pk);
|
||||
}
|
||||
|
||||
void addPKM(PKM pk)
|
||||
{
|
||||
|
@ -658,7 +659,7 @@ namespace PKHeX.WinForms
|
|||
return;
|
||||
}
|
||||
int begin = start*RES_MIN;
|
||||
int end = Math.Min(RES_MAX, Results.Count - start*RES_MIN);
|
||||
int end = Math.Min(RES_MAX, Results.Count - begin);
|
||||
for (int i = 0; i < end; i++)
|
||||
PKXBOXES[i].Image = Results[i + begin].Sprite();
|
||||
for (int i = end; i < RES_MAX; i++)
|
||||
|
@ -666,8 +667,8 @@ namespace PKHeX.WinForms
|
|||
|
||||
for (int i = 0; i < RES_MAX; i++)
|
||||
PKXBOXES[i].BackgroundImage = Properties.Resources.slotTrans;
|
||||
if (slotSelected != -1 && slotSelected >= RES_MIN * start && slotSelected < RES_MIN * start + RES_MAX)
|
||||
PKXBOXES[slotSelected - start * RES_MIN].BackgroundImage = slotColor ?? Properties.Resources.slotView;
|
||||
if (slotSelected != -1 && slotSelected >= begin && slotSelected < begin + RES_MAX)
|
||||
PKXBOXES[slotSelected - begin].BackgroundImage = slotColor ?? Properties.Resources.slotView;
|
||||
}
|
||||
|
||||
// Misc Update Methods
|
||||
|
@ -696,9 +697,15 @@ namespace PKHeX.WinForms
|
|||
|
||||
private void Menu_SearchAdvanced_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (!Menu_SearchAdvanced.Checked)
|
||||
{ Size = MinimumSize; RTB_Instructions.Clear(); }
|
||||
else Size = MaximumSize;
|
||||
if (Menu_SearchAdvanced.Checked)
|
||||
{
|
||||
Size = MaximumSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
Size = MinimumSize;
|
||||
RTB_Instructions.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void Menu_Exit_Click(object sender, EventArgs e) => Close();
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace PKHeX.WinForms
|
|||
{
|
||||
private readonly SaveFile Origin;
|
||||
private readonly SAV3 SAV;
|
||||
|
||||
public SAV_Misc3(SaveFile sav)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
@ -34,7 +35,7 @@ namespace PKHeX.WinForms
|
|||
|
||||
if (SAV.FRLG)
|
||||
{
|
||||
TB_OTName.Text = StringConverter.GetString3(SAV.Data, SAV.GetBlockOffset(4) + 0xBCC, 8, SAV.Japanese);
|
||||
TB_OTName.Text = SAV.GetString(SAV.GetBlockOffset(4) + 0xBCC, 8);
|
||||
ComboBox[] cba = { CB_TCM1, CB_TCM2, CB_TCM3, CB_TCM4, CB_TCM5, CB_TCM6 };
|
||||
int[] HoennListMixed = {
|
||||
277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,
|
||||
|
@ -64,6 +65,7 @@ namespace PKHeX.WinForms
|
|||
NUD_BP.Value = Math.Min(NUD_BP.Maximum, SAV.BP);
|
||||
NUD_Coins.Value = Math.Min(NUD_Coins.Maximum, SAV.Coin);
|
||||
}
|
||||
|
||||
private void B_Save_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (tabControl1.Controls.Contains(TAB_Joyful))
|
||||
|
@ -75,7 +77,7 @@ namespace PKHeX.WinForms
|
|||
if (SAV.FRLG)
|
||||
{
|
||||
SAV.SetData(SAV.SetString(TB_OTName.Text, TB_OTName.MaxLength), SAV.GetBlockOffset(4) + 0xBCC);
|
||||
ComboBox[] cba = new[] { CB_TCM1, CB_TCM2, CB_TCM3, CB_TCM4, CB_TCM5, CB_TCM6 };
|
||||
ComboBox[] cba = { CB_TCM1, CB_TCM2, CB_TCM3, CB_TCM4, CB_TCM5, CB_TCM6 };
|
||||
int ofsTCM = SAV.GetBlockOffset(2) + 0x106;
|
||||
for (int i = 0; i < cba.Length; i++)
|
||||
BitConverter.GetBytes((ushort)(int)cba[i].SelectedValue).CopyTo(SAV.Data, ofsTCM + (i << 1));
|
||||
|
@ -87,10 +89,8 @@ namespace PKHeX.WinForms
|
|||
Origin.SetData(SAV.Data, 0);
|
||||
Close();
|
||||
}
|
||||
private void B_Cancel_Click(object sender, EventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
private void B_Cancel_Click(object sender, EventArgs e) => Close();
|
||||
|
||||
#region Joyful
|
||||
private int JUMPS_IN_ROW, JUMPS_SCORE, JUMPS_5_IN_ROW;
|
||||
|
@ -249,6 +249,7 @@ namespace PKHeX.WinForms
|
|||
private string[][] BFT;
|
||||
private int[][] BFV;
|
||||
private string[] BFN;
|
||||
|
||||
private void ChangeStat1(object sender, EventArgs e)
|
||||
{
|
||||
if (loading) return;
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace PKHeX.WinForms
|
|||
public sealed partial class SAV_BoxViewer : Form
|
||||
{
|
||||
private readonly SAVEditor parent;
|
||||
|
||||
public SAV_BoxViewer(SAVEditor p, SlotChangeManager m)
|
||||
{
|
||||
parent = p;
|
||||
|
@ -35,6 +36,7 @@ namespace PKHeX.WinForms
|
|||
foreach (PictureBox pb in Box.SlotPictureBoxes)
|
||||
pb.ContextMenuStrip = parent.SlotPictureBoxes[0].ContextMenuStrip;
|
||||
}
|
||||
|
||||
public int CurrentBox => Box.CurrentBox;
|
||||
private void PB_BoxSwap_Click(object sender, EventArgs e) => Box.CurrentBox = parent.SwapBoxesViewer(Box.CurrentBox);
|
||||
public void SetPKMBoxes() => Box.ResetSlots();
|
||||
|
|
Loading…
Add table
Reference in a new issue