mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-27 14:30:56 +00:00
Legality refactoring continued
Finish removing explicit gen6 objects so that multiple generations of information can be checked. Still only supports gen6, but will be much much easier to add in other generations in the future. Tested a few pk6's and the legality checks appear to be functioning the same.
This commit is contained in:
parent
ed14ab7436
commit
a462c09743
2 changed files with 459 additions and 217 deletions
|
@ -971,7 +971,7 @@ namespace PKHeX
|
|||
return;
|
||||
|
||||
case 14:
|
||||
if (!Legal.getCanBeCaptured(pkm.OT_TextVar, pkm.Version))
|
||||
if (!Legal.getCanBeCaptured(pkm.OT_TextVar, pkm.GenNumber, pkm.Version))
|
||||
AddLine(Severity.Invalid, "OT Memory: Captured Species can not be captured in game.", CheckIdentifier.Memory);
|
||||
else
|
||||
AddLine(Severity.Valid, "OT Memory: Captured Species can be captured in game.", CheckIdentifier.Memory);
|
||||
|
@ -1001,7 +1001,7 @@ namespace PKHeX
|
|||
AddLine(Severity.Invalid, "HT Memory: Handling Trainer did not hatch this.", CheckIdentifier.Memory); return;
|
||||
|
||||
case 14:
|
||||
if (!Legal.getCanBeCaptured(pkm.HT_TextVar))
|
||||
if (!Legal.getCanBeCaptured(pkm.HT_TextVar, pkm.GenNumber))
|
||||
AddLine(Severity.Invalid, "HT Memory: Captured Species can not be captured in game.", CheckIdentifier.Memory);
|
||||
else
|
||||
AddLine(Severity.Valid, "HT Memory: Captured Species can be captured in game.", CheckIdentifier.Memory);
|
||||
|
@ -1217,6 +1217,7 @@ namespace PKHeX
|
|||
int[] Moves = pkm.RelearnMoves;
|
||||
if (pkm.GenNumber < 6)
|
||||
goto noRelearn;
|
||||
|
||||
if (pkm.WasLink)
|
||||
{
|
||||
var Link = Legal.getValidLinkGifts(pkm);
|
||||
|
@ -1239,7 +1240,7 @@ namespace PKHeX
|
|||
if (pkm.WasEvent || pkm.WasEventEgg)
|
||||
{
|
||||
// Get WC6's that match
|
||||
EventGiftMatch = new List<MysteryGift>(Legal.getValidWC6s(pkm));
|
||||
EventGiftMatch = new List<MysteryGift>(Legal.getValidGifts(pkm));
|
||||
foreach (MysteryGift mg in EventGiftMatch.ToArray())
|
||||
{
|
||||
int[] moves = mg.RelearnMoves;
|
||||
|
@ -1261,7 +1262,20 @@ namespace PKHeX
|
|||
|
||||
if (pkm.WasEgg && !Legal.NoHatchFromEgg.Contains(pkm.Species))
|
||||
{
|
||||
const int games = 2;
|
||||
int games = 1;
|
||||
GameVersion[] Games = { GameVersion.XY };
|
||||
switch (pkm.GenNumber)
|
||||
{
|
||||
case 6:
|
||||
games = 2;
|
||||
Games = new[] {GameVersion.XY, GameVersion.ORAS};
|
||||
break;
|
||||
case 7:
|
||||
games = 1;
|
||||
Games = new[] {GameVersion.SM};
|
||||
break;
|
||||
}
|
||||
|
||||
bool checkAllGames = pkm.WasTradedEgg;
|
||||
bool splitBreed = Legal.SplitBreed.Contains(pkm.Species);
|
||||
|
||||
|
@ -1270,9 +1284,10 @@ namespace PKHeX
|
|||
{
|
||||
int gameSource = !checkAllGames ? -1 : i % iterate / (splitBreed ? 2 : 1);
|
||||
int skipOption = splitBreed && iterate / 2 <= i ? 1 : 0;
|
||||
GameVersion ver = gameSource == -1 ? GameVersion.Any : Games[gameSource];
|
||||
|
||||
// Obtain level1 moves
|
||||
List<int> baseMoves = new List<int>(Legal.getBaseEggMoves(pkm, skipOption, gameSource));
|
||||
List<int> baseMoves = new List<int>(Legal.getBaseEggMoves(pkm, skipOption, ver));
|
||||
int baseCt = baseMoves.Count;
|
||||
if (baseCt > 4) baseCt = 4;
|
||||
|
||||
|
|
|
@ -5,26 +5,29 @@ namespace PKHeX
|
|||
{
|
||||
public static partial class Legal
|
||||
{
|
||||
// PKHeX master Wonder Card Database
|
||||
// Event Database(s)
|
||||
internal static WC6[] WC6DB;
|
||||
// PKHeX master personal.dat
|
||||
|
||||
// Gen 6
|
||||
private static readonly EggMoves[] EggMoveXY = EggMoves.getArray(Data.unpackMini(Properties.Resources.eggmove_xy, "xy"));
|
||||
private static readonly Learnset[] LevelUpXY = Learnset.getArray(Data.unpackMini(Properties.Resources.lvlmove_xy, "xy"));
|
||||
private static readonly EggMoves[] EggMoveAO = EggMoves.getArray(Data.unpackMini(Properties.Resources.eggmove_ao, "ao"));
|
||||
private static readonly Learnset[] LevelUpAO = Learnset.getArray(Data.unpackMini(Properties.Resources.lvlmove_ao, "ao"));
|
||||
private static readonly Evolutions[] Evolves = Evolutions.getArray(Data.unpackMini(Properties.Resources.evos_ao, "ao"));
|
||||
private static readonly EncounterArea[] SlotsA;
|
||||
private static readonly EncounterArea[] SlotsO;
|
||||
private static readonly EncounterArea[] SlotsX;
|
||||
private static readonly EncounterArea[] SlotsY;
|
||||
private static readonly EncounterStatic[] StaticX;
|
||||
private static readonly EncounterStatic[] StaticY;
|
||||
private static readonly EncounterStatic[] StaticA;
|
||||
private static readonly EncounterStatic[] StaticO;
|
||||
private static EncounterStatic[] getSpecial(GameVersion Game)
|
||||
private static readonly Evolutions[] Evolves6 = Evolutions.getArray(Data.unpackMini(Properties.Resources.evos_ao, "ao"));
|
||||
private static readonly EncounterArea[] SlotsX, SlotsY, SlotsA, SlotsO;
|
||||
private static readonly EncounterStatic[] StaticX, StaticY, StaticA, StaticO;
|
||||
|
||||
// Gen 7
|
||||
private static readonly EggMoves[] EggMoveSM = new EggMoves[0];
|
||||
private static readonly Learnset[] LevelUpSM = new Learnset[0];
|
||||
private static readonly Evolutions[] Evolves7 = new Evolutions[0];
|
||||
private static readonly EncounterArea[] SlotsSN, SlotsMN;
|
||||
private static readonly EncounterStatic[] StaticSN, StaticMN;
|
||||
|
||||
// Setup Help
|
||||
private static EncounterStatic[] getStaticEncounters(GameVersion Game)
|
||||
{
|
||||
EncounterStatic[] table = null;
|
||||
EncounterStatic[] table;
|
||||
switch (Game)
|
||||
{
|
||||
case GameVersion.X:
|
||||
|
@ -39,9 +42,47 @@ namespace PKHeX
|
|||
case GameVersion.MN:
|
||||
table = Encounter_SM;
|
||||
break;
|
||||
|
||||
default: return null;
|
||||
}
|
||||
return table?.Where(s => s.Version == GameVersion.Any || s.Version == Game).ToArray();
|
||||
}
|
||||
private static EncounterArea[] getEncounterTables(GameVersion Game)
|
||||
{
|
||||
string ident = null;
|
||||
byte[] tables = null;
|
||||
switch (Game)
|
||||
{
|
||||
case GameVersion.X:
|
||||
ident = "xy";
|
||||
tables = Properties.Resources.encounter_x;
|
||||
break;
|
||||
case GameVersion.Y:
|
||||
ident = "xy";
|
||||
tables = Properties.Resources.encounter_y;
|
||||
break;
|
||||
case GameVersion.AS:
|
||||
ident = "ao";
|
||||
tables = Properties.Resources.encounter_a;
|
||||
break;
|
||||
case GameVersion.OR:
|
||||
ident = "ao";
|
||||
tables = Properties.Resources.encounter_o;
|
||||
break;
|
||||
case GameVersion.SN:
|
||||
ident = "sm";
|
||||
// tables = Properties.Resources.encounter_sn;
|
||||
break;
|
||||
case GameVersion.MN:
|
||||
ident = "sm";
|
||||
// tables = Properties.Resources.encounter_mn;
|
||||
break;
|
||||
}
|
||||
if (ident == null)
|
||||
return null;
|
||||
|
||||
return EncounterArea.getArray(Data.unpackMini(tables, ident));
|
||||
}
|
||||
private static EncounterArea[] addXYAltTiles(EncounterArea[] GameSlots, EncounterArea[] SpecialSlots)
|
||||
{
|
||||
foreach (EncounterArea g in GameSlots)
|
||||
|
@ -52,141 +93,123 @@ namespace PKHeX
|
|||
}
|
||||
return GameSlots;
|
||||
}
|
||||
private static void MarkG6XYSlots(ref EncounterArea[] Areas)
|
||||
{
|
||||
foreach (var area in Areas)
|
||||
{
|
||||
int slotct = area.Slots.Length;
|
||||
for (int i = slotct - 15; i < slotct; i++)
|
||||
area.Slots[i].Type = SlotType.Horde;
|
||||
}
|
||||
}
|
||||
private static void MarkG6AOSlots(ref EncounterArea[] Areas)
|
||||
{
|
||||
foreach (var area in Areas)
|
||||
{
|
||||
for (int i = 32; i < 37; i++)
|
||||
area.Slots[i].Type = SlotType.Rock_Smash;
|
||||
int slotct = area.Slots.Length;
|
||||
for (int i = slotct - 15; i < slotct; i++)
|
||||
area.Slots[i].Type = SlotType.Horde;
|
||||
|
||||
for (int i = 0; i < slotct; i++)
|
||||
area.Slots[i].AllowDexNav = area.Slots[i].Type != SlotType.Rock_Smash;
|
||||
}
|
||||
}
|
||||
|
||||
static Legal() // Setup
|
||||
{
|
||||
#region Gen6: XY & ORAS
|
||||
StaticX = getSpecial(GameVersion.X);
|
||||
StaticY = getSpecial(GameVersion.Y);
|
||||
StaticA = getSpecial(GameVersion.AS);
|
||||
StaticO = getSpecial(GameVersion.OR);
|
||||
|
||||
var XSlots = EncounterArea.getArray(Data.unpackMini(Properties.Resources.encounter_x, "xy"));
|
||||
var YSlots = EncounterArea.getArray(Data.unpackMini(Properties.Resources.encounter_y, "xy"));
|
||||
|
||||
// Mark Horde Encounters
|
||||
foreach (var area in XSlots)
|
||||
// Gen 6
|
||||
{
|
||||
int slotct = area.Slots.Length;
|
||||
for (int i = slotct - 15; i < slotct; i++)
|
||||
area.Slots[i].Type = SlotType.Horde;
|
||||
StaticX = getStaticEncounters(GameVersion.X);
|
||||
StaticY = getStaticEncounters(GameVersion.Y);
|
||||
StaticA = getStaticEncounters(GameVersion.AS);
|
||||
StaticO = getStaticEncounters(GameVersion.OR);
|
||||
|
||||
var XSlots = getEncounterTables(GameVersion.X);
|
||||
var YSlots = getEncounterTables(GameVersion.Y);
|
||||
MarkG6XYSlots(ref XSlots);
|
||||
MarkG6XYSlots(ref YSlots);
|
||||
SlotsX = addXYAltTiles(XSlots, SlotsXYAlt);
|
||||
SlotsY = addXYAltTiles(YSlots, SlotsXYAlt);
|
||||
|
||||
SlotsA = getEncounterTables(GameVersion.AS);
|
||||
SlotsO = getEncounterTables(GameVersion.OR);
|
||||
MarkG6AOSlots(ref SlotsA);
|
||||
MarkG6AOSlots(ref SlotsO);
|
||||
}
|
||||
foreach (var area in YSlots)
|
||||
// Gen 7
|
||||
{
|
||||
int slotct = area.Slots.Length;
|
||||
for (int i = slotct - 15; i < slotct; i++)
|
||||
area.Slots[i].Type = SlotType.Horde;
|
||||
StaticSN = getStaticEncounters(GameVersion.SN);
|
||||
StaticMN = getStaticEncounters(GameVersion.MN);
|
||||
SlotsSN = getEncounterTables(GameVersion.SN);
|
||||
SlotsMN = getEncounterTables(GameVersion.MN);
|
||||
|
||||
// TEMP
|
||||
Evolves7 = Evolves6;
|
||||
}
|
||||
SlotsX = addXYAltTiles(XSlots, SlotsXYAlt);
|
||||
SlotsY = addXYAltTiles(YSlots, SlotsXYAlt);
|
||||
|
||||
SlotsA = EncounterArea.getArray(Data.unpackMini(Properties.Resources.encounter_a, "ao"));
|
||||
SlotsO = EncounterArea.getArray(Data.unpackMini(Properties.Resources.encounter_o, "ao"));
|
||||
|
||||
// Mark Encounters
|
||||
foreach (var area in SlotsA)
|
||||
{
|
||||
for (int i = 32; i < 37; i++)
|
||||
area.Slots[i].Type = SlotType.Rock_Smash;
|
||||
int slotct = area.Slots.Length;
|
||||
for (int i = slotct - 15; i < slotct; i++)
|
||||
area.Slots[i].Type = SlotType.Horde;
|
||||
|
||||
for (int i = 0; i < slotct; i++)
|
||||
area.Slots[i].AllowDexNav = area.Slots[i].Type != SlotType.Rock_Smash;
|
||||
}
|
||||
foreach (var area in SlotsO)
|
||||
{
|
||||
for (int i = 32; i < 37; i++)
|
||||
area.Slots[i].Type = SlotType.Rock_Smash;
|
||||
int slotct = area.Slots.Length;
|
||||
for (int i = slotct - 15; i < slotct; i++)
|
||||
area.Slots[i].Type = SlotType.Horde;
|
||||
|
||||
for (int i = 0; i < slotct; i++)
|
||||
area.Slots[i].AllowDexNav = area.Slots[i].Type != SlotType.Rock_Smash;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
// Moves
|
||||
internal static IEnumerable<int> getValidMoves(PKM pkm)
|
||||
{ return getValidMoves(pkm, -1, LVL: true, Relearn: false, Tutor: true, Machine: true); }
|
||||
{
|
||||
int version = pkm.Version;
|
||||
if (!pkm.IsUntraded)
|
||||
version = -1;
|
||||
return getValidMoves(pkm, version, LVL: true, Relearn: false, Tutor: true, Machine: true);
|
||||
}
|
||||
internal static IEnumerable<int> getValidRelearn(PKM pkm, int skipOption)
|
||||
{
|
||||
List<int> r = new List<int> { 0 };
|
||||
int species = getBaseSpecies(pkm, skipOption);
|
||||
r.AddRange(getLVLMoves(species, 1, pkm.AltForm));
|
||||
r.AddRange(getEggMoves(species, pkm.Species == 678 ? pkm.AltForm : 0));
|
||||
r.AddRange(getLVLMoves(species, 100, pkm.AltForm));
|
||||
r.AddRange(getLVLMoves(pkm, species, 1, pkm.AltForm));
|
||||
r.AddRange(getEggMoves(pkm, species, pkm.Species == 678 ? pkm.AltForm : 0));
|
||||
r.AddRange(getLVLMoves(pkm, species, 100, pkm.AltForm));
|
||||
return r.Distinct();
|
||||
}
|
||||
internal static IEnumerable<int> getBaseEggMoves(PKM pkm, int skipOption, int gameSource)
|
||||
internal static IEnumerable<int> getBaseEggMoves(PKM pkm, int skipOption, GameVersion gameSource)
|
||||
{
|
||||
int species = getBaseSpecies(pkm, skipOption);
|
||||
if (gameSource == -1)
|
||||
|
||||
if (gameSource == GameVersion.Any)
|
||||
gameSource = (GameVersion) pkm.Version;
|
||||
|
||||
switch (gameSource)
|
||||
{
|
||||
if (pkm.XY)
|
||||
return LevelUpXY[species].getMoves(1);
|
||||
if (pkm.AO)
|
||||
return LevelUpAO[species].getMoves(1);
|
||||
return null;
|
||||
case GameVersion.X:
|
||||
case GameVersion.Y:
|
||||
case GameVersion.XY:
|
||||
if (pkm.InhabitedGeneration(6))
|
||||
return LevelUpXY[species].getMoves(1);
|
||||
break;
|
||||
|
||||
case GameVersion.AS:
|
||||
case GameVersion.OR:
|
||||
case GameVersion.ORAS:
|
||||
if (pkm.InhabitedGeneration(6))
|
||||
return LevelUpAO[species].getMoves(1);
|
||||
break;
|
||||
|
||||
case GameVersion.SN:
|
||||
case GameVersion.MN:
|
||||
case GameVersion.SM:
|
||||
if (pkm.InhabitedGeneration(7))
|
||||
return LevelUpSM[species].getMoves(1);
|
||||
break;
|
||||
}
|
||||
if (gameSource == 0) // XY
|
||||
return LevelUpXY[species].getMoves(1);
|
||||
// if (gameSource == 1) // ORAS
|
||||
return LevelUpAO[species].getMoves(1);
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static IEnumerable<MysteryGift> getValidWC6s(PKM pkm)
|
||||
{
|
||||
var vs = getValidPreEvolutions(pkm).ToArray();
|
||||
List<MysteryGift> validWC6 = new List<MysteryGift>();
|
||||
|
||||
foreach (WC6 wc in WC6DB.Where(wc => vs.Any(dl => dl.Species == wc.Species)))
|
||||
{
|
||||
if (pkm.Egg_Location == 0) // Not Egg
|
||||
{
|
||||
if (wc.CardID != pkm.SID) continue;
|
||||
if (wc.TID != pkm.TID) continue;
|
||||
if (wc.OT != pkm.OT_Name) continue;
|
||||
if (wc.OTGender != pkm.OT_Gender) continue;
|
||||
if (wc.PIDType == 0 && pkm.PID != wc.PID) continue;
|
||||
if (wc.PIDType == 2 && !pkm.IsShiny) continue;
|
||||
if (wc.PIDType == 3 && pkm.IsShiny) continue;
|
||||
if (wc.OriginGame != 0 && wc.OriginGame != pkm.Version) continue;
|
||||
if (wc.EncryptionConstant != 0 && wc.EncryptionConstant != pkm.EncryptionConstant) continue;
|
||||
if (wc.Language != 0 && wc.Language != pkm.Language) continue;
|
||||
}
|
||||
if (wc.Form != pkm.AltForm && vs.All(dl => !FormChange.Contains(dl.Species))) continue;
|
||||
if (wc.MetLocation != pkm.Met_Location) continue;
|
||||
if (wc.EggLocation != pkm.Egg_Location) continue;
|
||||
if (wc.Level != pkm.Met_Level) continue;
|
||||
if (wc.Ball != pkm.Ball) continue;
|
||||
if (wc.OTGender < 3 && wc.OTGender != pkm.OT_Gender) continue;
|
||||
if (wc.Nature != 0xFF && wc.Nature != pkm.Nature) continue;
|
||||
if (wc.Gender != 3 && wc.Gender != pkm.Gender) continue;
|
||||
|
||||
if (wc.CNT_Cool > pkm.CNT_Cool) continue;
|
||||
if (wc.CNT_Beauty > pkm.CNT_Beauty) continue;
|
||||
if (wc.CNT_Cute > pkm.CNT_Cute) continue;
|
||||
if (wc.CNT_Smart > pkm.CNT_Smart) continue;
|
||||
if (wc.CNT_Tough > pkm.CNT_Tough) continue;
|
||||
if (wc.CNT_Sheen > pkm.CNT_Sheen) continue;
|
||||
|
||||
// Some checks are best performed separately as they are caused by users screwing up valid data.
|
||||
// if (!wc.RelearnMoves.SequenceEqual(pkm.RelearnMoves)) continue; // Defer to relearn legality
|
||||
// if (wc.OT.Length > 0 && pkm.CurrentHandler != 1) continue; // Defer to ownership legality
|
||||
// if (wc.OT.Length > 0 && pkm.OT_Friendship != PKX.getBaseFriendship(pkm.Species)) continue; // Friendship
|
||||
// if (wc.Level > pkm.CurrentLevel) continue; // Defer to level legality
|
||||
// RIBBONS: Defer to ribbon legality
|
||||
|
||||
validWC6.Add(wc);
|
||||
}
|
||||
return validWC6;
|
||||
}
|
||||
// Encounter
|
||||
internal static EncounterLink getValidLinkGifts(PKM pkm)
|
||||
{
|
||||
return LinkGifts.FirstOrDefault(g => g.Species == pkm.Species && g.Level == pkm.Met_Level);
|
||||
switch (pkm.GenNumber)
|
||||
{
|
||||
case 6:
|
||||
return LinkGifts6.FirstOrDefault(g => g.Species == pkm.Species && g.Level == pkm.Met_Level);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
internal static EncounterSlot[] getValidWildEncounters(PKM pkm)
|
||||
{
|
||||
|
@ -295,8 +318,83 @@ namespace PKHeX
|
|||
return slots.Any() ? slots.ToArray() : null;
|
||||
}
|
||||
|
||||
// Generation Specific Fetching
|
||||
private static Evolutions[] getEvolutionTable(PKM pkm)
|
||||
{
|
||||
switch (pkm.Format)
|
||||
{
|
||||
case 6:
|
||||
return Evolves6;
|
||||
case 7:
|
||||
return Evolves7;
|
||||
|
||||
default:
|
||||
return Evolves6;
|
||||
}
|
||||
}
|
||||
internal static IEnumerable<MysteryGift> getValidGifts(PKM pkm)
|
||||
{
|
||||
switch (pkm.GenNumber)
|
||||
{
|
||||
case 6:
|
||||
return getMatchingWC6(pkm);
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
private static IEnumerable<MysteryGift> getMatchingWC6(PKM pkm)
|
||||
{
|
||||
List<MysteryGift> validWC6 = new List<MysteryGift>();
|
||||
var vs = getValidPreEvolutions(pkm).ToArray();
|
||||
foreach (WC6 wc in WC6DB.Where(wc => vs.Any(dl => dl.Species == wc.Species)))
|
||||
{
|
||||
if (pkm.Egg_Location == 0) // Not Egg
|
||||
{
|
||||
if (wc.CardID != pkm.SID) continue;
|
||||
if (wc.TID != pkm.TID) continue;
|
||||
if (wc.OT != pkm.OT_Name) continue;
|
||||
if (wc.OTGender != pkm.OT_Gender) continue;
|
||||
if (wc.PIDType == 0 && pkm.PID != wc.PID) continue;
|
||||
if (wc.PIDType == 2 && !pkm.IsShiny) continue;
|
||||
if (wc.PIDType == 3 && pkm.IsShiny) continue;
|
||||
if (wc.OriginGame != 0 && wc.OriginGame != pkm.Version) continue;
|
||||
if (wc.EncryptionConstant != 0 && wc.EncryptionConstant != pkm.EncryptionConstant) continue;
|
||||
if (wc.Language != 0 && wc.Language != pkm.Language) continue;
|
||||
}
|
||||
if (wc.Form != pkm.AltForm && vs.All(dl => !FormChange.Contains(dl.Species))) continue;
|
||||
if (wc.MetLocation != pkm.Met_Location) continue;
|
||||
if (wc.EggLocation != pkm.Egg_Location) continue;
|
||||
if (wc.Level != pkm.Met_Level) continue;
|
||||
if (wc.Ball != pkm.Ball) continue;
|
||||
if (wc.OTGender < 3 && wc.OTGender != pkm.OT_Gender) continue;
|
||||
if (wc.Nature != 0xFF && wc.Nature != pkm.Nature) continue;
|
||||
if (wc.Gender != 3 && wc.Gender != pkm.Gender) continue;
|
||||
|
||||
if (wc.CNT_Cool > pkm.CNT_Cool) continue;
|
||||
if (wc.CNT_Beauty > pkm.CNT_Beauty) continue;
|
||||
if (wc.CNT_Cute > pkm.CNT_Cute) continue;
|
||||
if (wc.CNT_Smart > pkm.CNT_Smart) continue;
|
||||
if (wc.CNT_Tough > pkm.CNT_Tough) continue;
|
||||
if (wc.CNT_Sheen > pkm.CNT_Sheen) continue;
|
||||
|
||||
// Some checks are best performed separately as they are caused by users screwing up valid data.
|
||||
// if (!wc.RelearnMoves.SequenceEqual(pkm.RelearnMoves)) continue; // Defer to relearn legality
|
||||
// if (wc.OT.Length > 0 && pkm.CurrentHandler != 1) continue; // Defer to ownership legality
|
||||
// if (wc.OT.Length > 0 && pkm.OT_Friendship != PKX.getBaseFriendship(pkm.Species)) continue; // Friendship
|
||||
// if (wc.Level > pkm.CurrentLevel) continue; // Defer to level legality
|
||||
// RIBBONS: Defer to ribbon legality
|
||||
|
||||
validWC6.Add(wc);
|
||||
}
|
||||
return validWC6;
|
||||
}
|
||||
|
||||
internal static bool getDexNavValid(PKM pkm)
|
||||
{
|
||||
if (!pkm.AO || !pkm.InhabitedGeneration(6))
|
||||
return false;
|
||||
|
||||
IEnumerable<EncounterArea> locs = getDexNavAreas(pkm);
|
||||
return locs.Select(loc => getValidEncounterSlots(pkm, loc, DexNav: true)).Any(slots => slots.Any(slot => slot.AllowDexNav && slot.DexNav));
|
||||
}
|
||||
|
@ -306,7 +404,7 @@ namespace PKHeX
|
|||
}
|
||||
internal static bool getHasTradeEvolved(PKM pkm)
|
||||
{
|
||||
return Evolves[pkm.Species].Evos.Any(evo => evo.Level == 1); // 1: Trade, 0: Item, >=2: Levelup
|
||||
return getEvolutionTable(pkm)[pkm.Species].Evos.Any(evo => evo.Level == 1); // 1: Trade, 0: Item, >=2: Levelup
|
||||
}
|
||||
internal static bool getIsFossil(PKM pkm)
|
||||
{
|
||||
|
@ -314,6 +412,7 @@ namespace PKHeX
|
|||
return false;
|
||||
if (pkm.Egg_Location != 0)
|
||||
return false;
|
||||
|
||||
if (pkm.XY && pkm.Met_Location == 44)
|
||||
return Fossils.Contains(getBaseSpecies(pkm));
|
||||
if (pkm.AO && pkm.Met_Location == 190)
|
||||
|
@ -334,50 +433,68 @@ namespace PKHeX
|
|||
{
|
||||
int species = pkm.Species;
|
||||
List<int> res = new List<int>{species};
|
||||
for (int i = 0; i < Evolves.Length; i++)
|
||||
if (Evolves[i].Evos.Any(pk => pk.Species == species))
|
||||
var table = getEvolutionTable(pkm);
|
||||
for (int i = 0; i < table.Length; i++)
|
||||
if (table[i].Evos.Any(pk => pk.Species == species))
|
||||
res.Add(i);
|
||||
for (int i = -1; i < 2; i++)
|
||||
res.Add(getBaseSpecies(pkm, i));
|
||||
return res.Distinct();
|
||||
}
|
||||
|
||||
internal static bool getCanBeCaptured(int species, int version = -1)
|
||||
internal static bool getCanBeCaptured(int species, int gen, int version = -1)
|
||||
{
|
||||
if (version < 0 || version == (int)GameVersion.X)
|
||||
switch (gen)
|
||||
{
|
||||
if (SlotsX.Any(loc => loc.Slots.Any(slot => slot.Species == species)))
|
||||
return true;
|
||||
if (FriendSafari.Contains(species))
|
||||
return true;
|
||||
if (StaticX.Any(enc => enc.Species == species && !enc.Gift))
|
||||
return true;
|
||||
}
|
||||
if (version < 0 || version == (int)GameVersion.Y)
|
||||
{
|
||||
if (SlotsY.Any(loc => loc.Slots.Any(slot => slot.Species == species)))
|
||||
return true;
|
||||
if (FriendSafari.Contains(species))
|
||||
return true;
|
||||
if (StaticY.Any(enc => enc.Species == species && !enc.Gift))
|
||||
return true;
|
||||
}
|
||||
if (version < 0 || version == (int)GameVersion.AS)
|
||||
{
|
||||
if (SlotsA.Any(loc => loc.Slots.Any(slot => slot.Species == species)))
|
||||
return true;
|
||||
if (StaticA.Any(enc => enc.Species == species && !enc.Gift))
|
||||
return true;
|
||||
}
|
||||
if (version < 0 || version == (int)GameVersion.OR)
|
||||
{
|
||||
if (SlotsO.Any(loc => loc.Slots.Any(slot => slot.Species == species)))
|
||||
return true;
|
||||
if (StaticO.Any(enc => enc.Species == species && !enc.Gift))
|
||||
return true;
|
||||
case 6:
|
||||
switch (version)
|
||||
{
|
||||
case -1:
|
||||
return getCanBeCaptured(species, SlotsX, StaticX, XY:true)
|
||||
|| getCanBeCaptured(species, SlotsY, StaticY, XY:true)
|
||||
|| getCanBeCaptured(species, SlotsA, StaticA)
|
||||
|| getCanBeCaptured(species, SlotsO, StaticO);
|
||||
case (int)GameVersion.X:
|
||||
return getCanBeCaptured(species, SlotsX, StaticX, XY:true);
|
||||
case (int)GameVersion.Y:
|
||||
return getCanBeCaptured(species, SlotsY, StaticY, XY:true);
|
||||
case (int)GameVersion.AS:
|
||||
return getCanBeCaptured(species, SlotsA, StaticA);
|
||||
case (int)GameVersion.OR:
|
||||
return getCanBeCaptured(species, SlotsO, StaticO);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
case 7:
|
||||
switch (version)
|
||||
{
|
||||
case -1:
|
||||
return getCanBeCaptured(species, SlotsSN, StaticSN)
|
||||
|| getCanBeCaptured(species, SlotsMN, StaticMN);
|
||||
case (int)GameVersion.SN:
|
||||
return getCanBeCaptured(species, SlotsSN, StaticSN);
|
||||
case (int)GameVersion.MN:
|
||||
return getCanBeCaptured(species, SlotsMN, StaticMN);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private static bool getCanBeCaptured(int species, IEnumerable<EncounterArea> area, IEnumerable<EncounterStatic> statics, bool XY = false)
|
||||
{
|
||||
if (XY && FriendSafari.Contains(species))
|
||||
return true;
|
||||
|
||||
if (area.Any(loc => loc.Slots.Any(slot => slot.Species == species)))
|
||||
return true;
|
||||
if (statics.Any(enc => enc.Species == species && !enc.Gift))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static bool getCanLearnMachineMove(PKM pkm, int move, int version = -1)
|
||||
{
|
||||
return getValidMoves(pkm, version, Machine: true).Contains(move);
|
||||
|
@ -403,7 +520,10 @@ namespace PKHeX
|
|||
return 290;
|
||||
if (pkm.Species == 242 && pkm.CurrentLevel < 3) // Never Cleffa
|
||||
return 113;
|
||||
DexLevel[] evos = Evolves[pkm.Species].Evos;
|
||||
|
||||
Evolutions[] evotable = getEvolutionTable(pkm);
|
||||
|
||||
DexLevel[] evos = evotable[pkm.Species].Evos;
|
||||
switch (skipOption)
|
||||
{
|
||||
case -1: return pkm.Species;
|
||||
|
@ -413,29 +533,49 @@ namespace PKHeX
|
|||
}
|
||||
private static IEnumerable<EncounterArea> getDexNavAreas(PKM pkm)
|
||||
{
|
||||
bool alpha = pkm.Version == 26;
|
||||
if (!alpha && pkm.Version != 27)
|
||||
return new EncounterArea[0];
|
||||
return (alpha ? SlotsA : SlotsO).Where(l => l.Location == pkm.Met_Location);
|
||||
switch (pkm.Version)
|
||||
{
|
||||
case (int)GameVersion.AS:
|
||||
return SlotsA.Where(l => l.Location == pkm.Met_Location);
|
||||
case (int)GameVersion.OR:
|
||||
return SlotsO.Where(l => l.Location == pkm.Met_Location);
|
||||
default:
|
||||
return new EncounterArea[0];
|
||||
}
|
||||
}
|
||||
private static IEnumerable<int> getLVLMoves(int species, int lvl, int formnum)
|
||||
private static IEnumerable<int> getLVLMoves(PKM pkm, int species, int lvl, int formnum)
|
||||
{
|
||||
int ind_XY = PersonalTable.XY.getFormeIndex(species, formnum);
|
||||
int ind_AO = PersonalTable.AO.getFormeIndex(species, formnum);
|
||||
return LevelUpXY[ind_XY].getMoves(lvl).Concat(LevelUpAO[ind_AO].getMoves(lvl));
|
||||
List<int> moves = new List<int>();
|
||||
if (pkm.InhabitedGeneration(6))
|
||||
{
|
||||
int ind_XY = PersonalTable.XY.getFormeIndex(species, formnum);
|
||||
moves.AddRange(LevelUpXY[ind_XY].getMoves(lvl));
|
||||
int ind_AO = PersonalTable.AO.getFormeIndex(species, formnum);
|
||||
moves.AddRange(LevelUpAO[ind_AO].getMoves(lvl));
|
||||
}
|
||||
if (pkm.InhabitedGeneration(7))
|
||||
{
|
||||
int ind_SM = PersonalTable.SM.getFormeIndex(species, formnum);
|
||||
moves.AddRange(LevelUpSM[ind_SM].getMoves(lvl));
|
||||
}
|
||||
return moves;
|
||||
}
|
||||
private static IEnumerable<EncounterArea> getEncounterSlots(PKM pkm)
|
||||
{
|
||||
switch (pkm.Version)
|
||||
{
|
||||
case 24: // X
|
||||
case (int)GameVersion.X:
|
||||
return getSlots(pkm, SlotsX);
|
||||
case 25: // Y
|
||||
case (int)GameVersion.Y:
|
||||
return getSlots(pkm, SlotsY);
|
||||
case 26: // AS
|
||||
case (int)GameVersion.AS:
|
||||
return getSlots(pkm, SlotsA);
|
||||
case 27: // OR
|
||||
case (int)GameVersion.OR:
|
||||
return getSlots(pkm, SlotsO);
|
||||
case (int)GameVersion.SN:
|
||||
return getSlots(pkm, SlotsSN);
|
||||
case (int)GameVersion.MN:
|
||||
return getSlots(pkm, SlotsMN);
|
||||
default: return new List<EncounterArea>();
|
||||
}
|
||||
}
|
||||
|
@ -443,14 +583,18 @@ namespace PKHeX
|
|||
{
|
||||
switch (pkm.Version)
|
||||
{
|
||||
case 24: // X
|
||||
case (int)GameVersion.X:
|
||||
return getStatic(pkm, StaticX);
|
||||
case 25: // Y
|
||||
case (int)GameVersion.Y:
|
||||
return getStatic(pkm, StaticY);
|
||||
case 26: // AS
|
||||
case (int)GameVersion.AS:
|
||||
return getStatic(pkm, StaticA);
|
||||
case 27: // OR
|
||||
case (int)GameVersion.OR:
|
||||
return getStatic(pkm, StaticO);
|
||||
case (int)GameVersion.SN:
|
||||
return getStatic(pkm, StaticSN);
|
||||
case (int)GameVersion.MN:
|
||||
return getStatic(pkm, StaticMN);
|
||||
default: return new List<EncounterStatic>();
|
||||
}
|
||||
}
|
||||
|
@ -462,6 +606,7 @@ namespace PKHeX
|
|||
{
|
||||
const int fluteBoost = 4;
|
||||
const int dexnavBoost = 30;
|
||||
|
||||
int df = DexNav ? fluteBoost : 0;
|
||||
int dn = DexNav ? fluteBoost + dexnavBoost : 0;
|
||||
List<EncounterSlot> slotdata = new List<EncounterSlot>();
|
||||
|
@ -533,7 +678,8 @@ namespace PKHeX
|
|||
new DexLevel { Species = 292, Level = lvl },
|
||||
new DexLevel { Species = 290, Level = lvl-1 }
|
||||
};
|
||||
var evos = Evolves[pkm.Species].Evos;
|
||||
var table = getEvolutionTable(pkm);
|
||||
var evos = table[pkm.Species].Evos;
|
||||
List<DexLevel> dl = new List<DexLevel> { new DexLevel { Species = pkm.Species, Level = lvl } };
|
||||
foreach (DexLevel evo in evos)
|
||||
{
|
||||
|
@ -555,76 +701,157 @@ namespace PKHeX
|
|||
List<int> r = new List<int> { 0 };
|
||||
int species = pkm.Species;
|
||||
int lvl = pkm.CurrentLevel;
|
||||
bool ORASTutors = Version == -1 || pkm.AO || !pkm.IsUntraded;
|
||||
|
||||
// Special (non Type) Tutor Availability
|
||||
bool moveTutor = Version == -1 || pkm.Format != pkm.GenNumber;
|
||||
// Add extra cases where tutors
|
||||
moveTutor |= pkm.AO;
|
||||
moveTutor |= pkm.XY && !pkm.IsUntraded;
|
||||
moveTutor |= pkm.Format < 6;
|
||||
|
||||
if (FormChangeMoves.Contains(species)) // Deoxys & Shaymin & Giratina (others don't have extra but whatever)
|
||||
{
|
||||
int formcount = PersonalTable.AO[species].FormeCount;
|
||||
int formcount = pkm.PersonalInfo.FormeCount;
|
||||
for (int i = 0; i < formcount; i++)
|
||||
r.AddRange(getMoves(species, lvl, i, ORASTutors, Version, LVL, Tutor, Machine));
|
||||
r.AddRange(getMoves(pkm, species, lvl, i, moveTutor, Version, LVL, Tutor, Machine));
|
||||
if (Relearn) r.AddRange(pkm.RelearnMoves);
|
||||
return r.Distinct().ToArray();
|
||||
}
|
||||
|
||||
r.AddRange(getMoves(species, lvl, pkm.AltForm, ORASTutors, Version, LVL, Tutor, Machine));
|
||||
r.AddRange(getMoves(pkm, species, lvl, pkm.AltForm, moveTutor, Version, LVL, Tutor, Machine));
|
||||
IEnumerable<DexLevel> vs = getValidPreEvolutions(pkm);
|
||||
|
||||
foreach (DexLevel evo in vs)
|
||||
r.AddRange(getMoves(evo.Species, evo.Level, pkm.AltForm, ORASTutors, Version, LVL, Tutor, Machine));
|
||||
r.AddRange(getMoves(pkm, evo.Species, evo.Level, pkm.AltForm, moveTutor, Version, LVL, Tutor, Machine));
|
||||
|
||||
if (species == 479) // Rotom
|
||||
r.Add(RotomMoves[pkm.AltForm]);
|
||||
if (species == 25) // Pikachu
|
||||
|
||||
if (species == 25 && pkm.Format == 6) // Pikachu
|
||||
r.Add(PikachuMoves[pkm.AltForm]);
|
||||
|
||||
if (Relearn) r.AddRange(pkm.RelearnMoves);
|
||||
return r.Distinct().ToArray();
|
||||
}
|
||||
private static IEnumerable<int> getMoves(int species, int lvl, int form, bool ORASTutors, int Version, bool LVL, bool Tutor, bool Machine)
|
||||
private static IEnumerable<int> getMoves(PKM pkm, int species, int lvl, int form, bool moveTutor, int Version, bool LVL, bool Tutor, bool Machine)
|
||||
{
|
||||
List<int> r = new List<int> { 0 };
|
||||
if (Version < 0 || Version == 0)
|
||||
{
|
||||
int index = PersonalTable.XY.getFormeIndex(species, form);
|
||||
PersonalInfo pi = PersonalTable.XY.getFormeEntry(species, form);
|
||||
for (int gen = pkm.GenNumber; gen <= pkm.Format; gen++)
|
||||
r.AddRange(getMoves(pkm, species, lvl, form, moveTutor, Version, LVL, Tutor, Machine, gen));
|
||||
return r.Distinct();
|
||||
}
|
||||
private static IEnumerable<int> getMoves(PKM pkm, int species, int lvl, int form, bool moveTutor, int Version, bool LVL, bool Tutor, bool Machine, int Generation)
|
||||
{
|
||||
List<int> r = new List<int>();
|
||||
|
||||
if (LVL) r.AddRange(LevelUpXY[index].getMoves(lvl));
|
||||
if (Tutor) r.AddRange(getTutorMoves(species, form, ORASTutors));
|
||||
if (Machine) r.AddRange(TMHM_XY.Where((t, m) => pi.TMHM[m]));
|
||||
}
|
||||
if (Version < 0 || Version == 1)
|
||||
var ver = (GameVersion) Version;
|
||||
switch (Generation)
|
||||
{
|
||||
int index = PersonalTable.AO.getFormeIndex(species, form);
|
||||
PersonalInfo pi = PersonalTable.AO.getFormeEntry(species, form);
|
||||
case 6:
|
||||
switch (ver)
|
||||
{
|
||||
case GameVersion.Any: // Start at the top, hit every table
|
||||
case GameVersion.X: case GameVersion.Y: case GameVersion.XY:
|
||||
{
|
||||
int index = PersonalTable.XY.getFormeIndex(species, form);
|
||||
PersonalInfo pi = PersonalTable.XY.getFormeEntry(species, form);
|
||||
|
||||
if (LVL) r.AddRange(LevelUpAO[index].getMoves(lvl));
|
||||
if (Tutor) r.AddRange(getTutorMoves(species, form, ORASTutors));
|
||||
if (Machine) r.AddRange(TMHM_AO.Where((t, m) => pi.TMHM[m]));
|
||||
if (LVL) r.AddRange(LevelUpXY[index].getMoves(lvl));
|
||||
if (moveTutor) r.AddRange(getTutorMoves(pkm, species, form, Tutor));
|
||||
if (Machine) r.AddRange(TMHM_XY.Where((t, m) => pi.TMHM[m]));
|
||||
|
||||
if (ver == GameVersion.Any) // Fall Through
|
||||
goto case GameVersion.ORAS;
|
||||
break;
|
||||
}
|
||||
|
||||
case GameVersion.AS: case GameVersion.OR: case GameVersion.ORAS:
|
||||
{
|
||||
int index = PersonalTable.AO.getFormeIndex(species, form);
|
||||
PersonalInfo pi = PersonalTable.AO.getFormeEntry(species, form);
|
||||
|
||||
if (LVL) r.AddRange(LevelUpAO[index].getMoves(lvl));
|
||||
if (moveTutor) r.AddRange(getTutorMoves(pkm, species, form, Tutor));
|
||||
if (Machine) r.AddRange(TMHM_AO.Where((t, m) => pi.TMHM[m]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
switch (ver)
|
||||
{
|
||||
case GameVersion.Any:
|
||||
case GameVersion.SN: case GameVersion.MN: case GameVersion.SM:
|
||||
{
|
||||
int index = PersonalTable.SM.getFormeIndex(species, form);
|
||||
PersonalInfo pi = PersonalTable.SM.getFormeEntry(species, form);
|
||||
|
||||
if (LVL) r.AddRange(LevelUpSM[index].getMoves(lvl));
|
||||
if (moveTutor) r.AddRange(getTutorMoves(pkm, species, form, Tutor));
|
||||
if (Machine) r.AddRange(TMHM_SM.Where((t, m) => pi.TMHM[m]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return r;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
private static IEnumerable<int> getEggMoves(int species, int formnum)
|
||||
private static IEnumerable<int> getEggMoves(PKM pkm, int species, int formnum)
|
||||
{
|
||||
int ind_XY = PersonalTable.XY.getFormeIndex(species, formnum);
|
||||
int ind_AO = PersonalTable.AO.getFormeIndex(species, formnum);
|
||||
return EggMoveAO[ind_AO].Moves.Concat(EggMoveXY[ind_XY].Moves);
|
||||
}
|
||||
private static IEnumerable<int> getTutorMoves(int species, int formnum, bool ORASTutors)
|
||||
{
|
||||
PersonalInfo pkAO = PersonalTable.AO.getFormeEntry(species, formnum);
|
||||
switch (pkm.GenNumber)
|
||||
{
|
||||
case 6:
|
||||
int ind_XY = PersonalTable.XY.getFormeIndex(species, formnum);
|
||||
int ind_AO = PersonalTable.AO.getFormeIndex(species, formnum);
|
||||
return EggMoveAO[ind_AO].Moves.Concat(EggMoveXY[ind_XY].Moves);
|
||||
|
||||
case 7:
|
||||
int ind_SM = PersonalTable.SM.getFormeIndex(species, formnum);
|
||||
return EggMoveSM[ind_SM].Moves;
|
||||
|
||||
default:
|
||||
return new List<int>();
|
||||
}
|
||||
}
|
||||
private static IEnumerable<int> getTutorMoves(PKM pkm, int species, int form, bool Tutors)
|
||||
{
|
||||
PersonalInfo info = pkm.PersonalInfo;
|
||||
// Type Tutor
|
||||
List<int> moves = TypeTutor.Where((t, i) => pkAO.TypeTutors[i]).ToList();
|
||||
List<int> moves = TypeTutor.Where((t, i) => info.TypeTutors[i]).ToList();
|
||||
|
||||
// Varied Tutors
|
||||
if (ORASTutors)
|
||||
for (int i = 0; i < Tutors_AO.Length; i++)
|
||||
for (int b = 0; b < Tutors_AO[i].Length; b++)
|
||||
if (pkAO.SpecialTutors[i][b])
|
||||
moves.Add(Tutors_AO[i][b]);
|
||||
//if (pkm.InhabitedGeneration(5) && Tutors)
|
||||
//{
|
||||
// //PersonalInfo pi = PersonalTable.B2W2.getFormeEntry(species, form);
|
||||
// //for (int i = 0; i < Tutors_B2W2.Length; i++)
|
||||
// // for (int b = 0; b < Tutors_B2W2[i].Length; b++)
|
||||
// // if (pi.SpecialTutors[i][b])
|
||||
// // moves.Add(Tutors_B2W2[i][b]);
|
||||
//}
|
||||
if (pkm.InhabitedGeneration(6) && Tutors)
|
||||
{
|
||||
PersonalInfo pi = PersonalTable.AO.getFormeEntry(species, form);
|
||||
for (int i = 0; i < Tutors_AO.Length; i++)
|
||||
for (int b = 0; b < Tutors_AO[i].Length; b++)
|
||||
if (pi.SpecialTutors[i][b])
|
||||
moves.Add(Tutors_AO[i][b]);
|
||||
}
|
||||
//if (pkm.InhabitedGeneration(7) && Tutors)
|
||||
//{
|
||||
// //PersonalInfo pi = PersonalTable.SM.getFormeEntry(species, form);
|
||||
// //for (int i = 0; i < Tutors_SM.Length; i++)
|
||||
// // for (int b = 0; b < Tutors_SM[i].Length; b++)
|
||||
// // if (pi.SpecialTutors[i][b])
|
||||
// // moves.Add(Tutors_SM[i][b]);
|
||||
//}
|
||||
|
||||
// Keldeo - Secret Sword
|
||||
if (species == 647)
|
||||
moves.Add(548);
|
||||
return moves;
|
||||
return moves.Distinct();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue