Refactor Legality engine

Beginnings of multi-generational support; removed all references to PK6
(child) and changed to PKM (abstract parent).

The core portion still needs revision to not be hard-coded for XY/ORAS
info tables.
This commit is contained in:
Kaphotics 2016-10-23 12:48:49 -07:00
parent e3d7a7ebce
commit 0fec576831
17 changed files with 1241 additions and 869 deletions

View file

@ -6,77 +6,115 @@ namespace PKHeX
{ {
public partial class LegalityAnalysis public partial class LegalityAnalysis
{ {
private readonly PK6 pk6; private PKM pkm;
private object EncounterMatch; private readonly List<CheckResult> Parse = new List<CheckResult>();
private List<WC6> CardMatch;
private Type EncounterType;
private LegalityCheck ECPID, Nickname, IDs, IVs, EVs, Encounter, Level, Ribbons, Ability, Ball, History, OTMemory, HTMemory, Region, Form, Misc, Gender;
private LegalityCheck[] Checks => new[] { Encounter, Level, Form, Ball, Ability, Ribbons, ECPID, Nickname, IVs, EVs, IDs, History, OTMemory, HTMemory, Region, Misc, Gender };
public bool Valid = true; private object EncounterMatch;
public bool SecondaryChecked; private Type EncounterType;
public int[] RelearnBase; private List<MysteryGift> EventGiftMatch;
public LegalityCheck[] vMoves = new LegalityCheck[4]; private CheckResult Encounter, History;
public LegalityCheck[] vRelearn = new LegalityCheck[4]; private int[] RelearnBase;
// private bool SecondaryChecked;
public readonly bool Parsed;
public readonly bool Valid;
public CheckResult[] vMoves = new CheckResult[4];
public CheckResult[] vRelearn = new CheckResult[4];
public string Report => getLegalityReport(); public string Report => getLegalityReport();
public string VerboseReport => getVerboseLegalityReport(); public string VerboseReport => getVerboseLegalityReport();
public bool Native => pkm.GenNumber == pkm.Format;
public LegalityAnalysis(PKM pk) public LegalityAnalysis(PKM pk)
{ {
if (!(pk is PK6))
return;
pk6 = (PK6) pk;
try try
{ {
updateRelearnLegality(); switch (pk.Format)
updateMoveLegality(); {
updateChecks(); case 6: parsePK6(pk); break;
getLegalityReport(); case 7: parsePK7(pk); break;
default: return;
}
Valid = Parse.Any() && Parse.All(chk => chk.Valid);
if (vMoves.Any(m => m.Valid != true))
Valid = false;
else if (vRelearn.Any(m => m.Valid != true))
Valid = false;
} }
catch { Valid = false; } catch { Valid = false; }
Parsed = true;
} }
public void updateRelearnLegality() private void AddLine(Severity s, string c, CheckIdentifier i)
{
AddLine(new CheckResult(s, c, i));
}
private void AddLine(CheckResult chk)
{
Parse.Add(chk);
}
private void parsePK6(PKM pk)
{
if (!(pk is PK6))
return;
pkm = pk;
updateRelearnLegality();
updateMoveLegality();
updateChecks();
getLegalityReport();
}
private void parsePK7(PKM pk)
{
if (!(pk is PK7))
return;
pkm = pk;
updateRelearnLegality();
updateMoveLegality();
updateChecks();
getLegalityReport();
}
private void updateRelearnLegality()
{ {
try { vRelearn = verifyRelearn(); } try { vRelearn = verifyRelearn(); }
catch { for (int i = 0; i < 4; i++) vRelearn[i] = new LegalityCheck(Severity.Invalid, "Internal error."); } catch { for (int i = 0; i < 4; i++) vRelearn[i] = new CheckResult(Severity.Invalid, "Internal error.", CheckIdentifier.RelearnMove); }
SecondaryChecked = false; // SecondaryChecked = false;
} }
public void updateMoveLegality() private void updateMoveLegality()
{ {
try { vMoves = verifyMoves(); } try { vMoves = verifyMoves(); }
catch { for (int i = 0; i < 4; i++) vMoves[i] = new LegalityCheck(Severity.Invalid, "Internal error."); } catch { for (int i = 0; i < 4; i++) vMoves[i] = new CheckResult(Severity.Invalid, "Internal error.", CheckIdentifier.Move); }
SecondaryChecked = false; // SecondaryChecked = false;
} }
private void updateChecks() private void updateChecks()
{ {
Encounter = verifyEncounter(); Encounter = verifyEncounter();
EncounterType = EncounterMatch?.GetType(); EncounterType = EncounterMatch?.GetType();
ECPID = verifyECPID();
Nickname = verifyNickname();
IDs = verifyID();
IVs = verifyIVs();
EVs = verifyEVs();
Level = verifyLevel();
Ribbons = verifyRibbons();
Ability = verifyAbility();
Ball = verifyBall();
History = verifyHistory(); History = verifyHistory();
OTMemory = verifyOTMemory();
HTMemory = verifyHTMemory(); verifyECPID();
Region = verifyRegion(); verifyNickname();
Form = verifyForm(); verifyID();
Misc = verifyMisc(); verifyIVs();
Gender = verifyGender(); verifyEVs();
SecondaryChecked = true; verifyLevel();
verifyRibbons();
verifyAbility();
verifyBall();
verifyOTMemory();
verifyHTMemory();
verifyRegion();
verifyForm();
verifyMisc();
verifyGender();
// SecondaryChecked = true;
} }
private string getLegalityReport() private string getLegalityReport()
{ {
if (pk6 == null || !pk6.Gen6) if (!Parsed)
return "Analysis only available for Pokémon that originate from X/Y & OR/AS."; return "Analysis not available for this Pokémon.";
var chks = Checks;
string r = ""; string r = "";
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
@ -86,19 +124,18 @@ namespace PKHeX
if (!vRelearn[i].Valid) if (!vRelearn[i].Valid)
r += $"{vRelearn[i].Judgement} Relearn Move {i + 1}: {vRelearn[i].Comment}" + Environment.NewLine; r += $"{vRelearn[i].Judgement} Relearn Move {i + 1}: {vRelearn[i].Comment}" + Environment.NewLine;
if (r.Length == 0 && chks.All(chk => chk.Valid)) if (r.Length == 0 && Parse.All(chk => chk.Valid))
return "Legal!"; return "Legal!";
Valid = false;
// Build result string... // Build result string...
r += chks.Where(chk => !chk.Valid).Aggregate("", (current, chk) => current + $"{chk.Judgement}: {chk.Comment}{Environment.NewLine}"); r += Parse.Where(chk => !chk.Valid).Aggregate("", (current, chk) => current + $"{chk.Judgement}: {chk.Comment}{Environment.NewLine}");
return r.TrimEnd(); return r.TrimEnd();
} }
private string getVerboseLegalityReport() private string getVerboseLegalityReport()
{ {
string r = getLegalityReport() + Environment.NewLine; string r = getLegalityReport() + Environment.NewLine;
if (pk6 == null) if (pkm == null)
return r; return r;
r += "===" + Environment.NewLine + Environment.NewLine; r += "===" + Environment.NewLine + Environment.NewLine;
int rl = r.Length; int rl = r.Length;
@ -113,8 +150,7 @@ namespace PKHeX
if (rl != r.Length) // move info added, break for next section if (rl != r.Length) // move info added, break for next section
r += Environment.NewLine; r += Environment.NewLine;
var chks = Checks; r += Parse.Where(chk => chk != null && chk.Valid && chk.Comment != "Valid").OrderBy(chk => chk.Judgement) // Fishy sorted to top
r += chks.Where(chk => chk != null && chk.Valid && chk.Comment != "Valid").OrderBy(chk => chk.Judgement) // Fishy sorted to top
.Aggregate("", (current, chk) => current + $"{chk.Judgement}: {chk.Comment}{Environment.NewLine}"); .Aggregate("", (current, chk) => current + $"{chk.Judgement}: {chk.Comment}{Environment.NewLine}");
return r.TrimEnd(); return r.TrimEnd();
} }
@ -123,15 +159,17 @@ namespace PKHeX
{ {
if (RelearnBase == null) if (RelearnBase == null)
return new int[4]; return new int[4];
if (pkm.GenNumber < 6)
return new int[4];
if (!pk6.WasEgg) if (!pkm.WasEgg)
return RelearnBase; return RelearnBase;
List<int> window = new List<int>(RelearnBase); List<int> window = new List<int>(RelearnBase);
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
if (!vMoves[i].Valid || vMoves[i].Flag) if (!vMoves[i].Valid || vMoves[i].Flag)
window.Add(pk6.Moves[i]); window.Add(pkm.Moves[i]);
if (window.Count < 4) if (window.Count < 4)
window.AddRange(new int[4 - window.Count]); window.AddRange(new int[4 - window.Count]);

File diff suppressed because it is too large Load diff

View file

@ -24,10 +24,23 @@ namespace PKHeX
private static readonly EncounterStatic[] StaticO; private static readonly EncounterStatic[] StaticO;
private static EncounterStatic[] getSpecial(GameVersion Game) private static EncounterStatic[] getSpecial(GameVersion Game)
{ {
if (Game == GameVersion.X || Game == GameVersion.Y) EncounterStatic[] table = null;
return Encounter_XY.Where(s => s.Version == GameVersion.Any || s.Version == Game).ToArray(); switch (Game)
// else if (Game == GameVersion.AS || Game == GameVersion.OR) {
return Encounter_AO.Where(s => s.Version == GameVersion.Any || s.Version == Game).ToArray(); case GameVersion.X:
case GameVersion.Y:
table = Encounter_XY;
break;
case GameVersion.AS:
case GameVersion.OR:
table = Encounter_AO;
break;
case GameVersion.SN:
case GameVersion.MN:
table = Encounter_SM;
break;
}
return table?.Where(s => s.Version == GameVersion.Any || s.Version == Game).ToArray();
} }
private static EncounterArea[] addXYAltTiles(EncounterArea[] GameSlots, EncounterArea[] SpecialSlots) private static EncounterArea[] addXYAltTiles(EncounterArea[] GameSlots, EncounterArea[] SpecialSlots)
{ {
@ -42,6 +55,7 @@ namespace PKHeX
static Legal() // Setup static Legal() // Setup
{ {
#region Gen6: XY & ORAS
StaticX = getSpecial(GameVersion.X); StaticX = getSpecial(GameVersion.X);
StaticY = getSpecial(GameVersion.Y); StaticY = getSpecial(GameVersion.Y);
StaticA = getSpecial(GameVersion.AS); StaticA = getSpecial(GameVersion.AS);
@ -92,28 +106,30 @@ namespace PKHeX
for (int i = 0; i < slotct; i++) for (int i = 0; i < slotct; i++)
area.Slots[i].AllowDexNav = area.Slots[i].Type != SlotType.Rock_Smash; area.Slots[i].AllowDexNav = area.Slots[i].Type != SlotType.Rock_Smash;
} }
#endregion
} }
internal static IEnumerable<int> getValidMoves(PK6 pk6) internal static IEnumerable<int> getValidMoves(PKM pkm)
{ return getValidMoves(pk6, -1, LVL: true, Relearn: false, Tutor: true, Machine: true); } { return getValidMoves(pkm, -1, LVL: true, Relearn: false, Tutor: true, Machine: true); }
internal static IEnumerable<int> getValidRelearn(PK6 pk6, int skipOption) internal static IEnumerable<int> getValidRelearn(PKM pkm, int skipOption)
{ {
List<int> r = new List<int> { 0 }; List<int> r = new List<int> { 0 };
int species = getBaseSpecies(pk6, skipOption); int species = getBaseSpecies(pkm, skipOption);
r.AddRange(getLVLMoves(species, 1, pk6.AltForm)); r.AddRange(getLVLMoves(species, 1, pkm.AltForm));
r.AddRange(getEggMoves(species, pk6.Species == 678 ? pk6.AltForm : 0)); r.AddRange(getEggMoves(species, pkm.Species == 678 ? pkm.AltForm : 0));
r.AddRange(getLVLMoves(species, 100, pk6.AltForm)); r.AddRange(getLVLMoves(species, 100, pkm.AltForm));
return r.Distinct(); return r.Distinct();
} }
internal static IEnumerable<int> getBaseEggMoves(PK6 pk6, int skipOption, int gameSource) internal static IEnumerable<int> getBaseEggMoves(PKM pkm, int skipOption, int gameSource)
{ {
int species = getBaseSpecies(pk6, skipOption); int species = getBaseSpecies(pkm, skipOption);
if (gameSource == -1) if (gameSource == -1)
{ {
if (pk6.XY) if (pkm.XY)
return LevelUpXY[species].getMoves(1); return LevelUpXY[species].getMoves(1);
// if (pk6.Version == 26 || pk6.Version == 27) if (pkm.AO)
return LevelUpAO[species].getMoves(1); return LevelUpAO[species].getMoves(1);
return null;
} }
if (gameSource == 0) // XY if (gameSource == 0) // XY
return LevelUpXY[species].getMoves(1); return LevelUpXY[species].getMoves(1);
@ -121,89 +137,89 @@ namespace PKHeX
return LevelUpAO[species].getMoves(1); return LevelUpAO[species].getMoves(1);
} }
internal static IEnumerable<WC6> getValidWC6s(PK6 pk6) internal static IEnumerable<MysteryGift> getValidWC6s(PKM pkm)
{ {
var vs = getValidPreEvolutions(pk6).ToArray(); var vs = getValidPreEvolutions(pkm).ToArray();
List<WC6> validWC6 = new List<WC6>(); List<MysteryGift> validWC6 = new List<MysteryGift>();
foreach (WC6 wc in WC6DB.Where(wc => vs.Any(dl => dl.Species == wc.Species))) foreach (WC6 wc in WC6DB.Where(wc => vs.Any(dl => dl.Species == wc.Species)))
{ {
if (pk6.Egg_Location == 0) // Not Egg if (pkm.Egg_Location == 0) // Not Egg
{ {
if (wc.CardID != pk6.SID) continue; if (wc.CardID != pkm.SID) continue;
if (wc.TID != pk6.TID) continue; if (wc.TID != pkm.TID) continue;
if (wc.OT != pk6.OT_Name) continue; if (wc.OT != pkm.OT_Name) continue;
if (wc.OTGender != pk6.OT_Gender) continue; if (wc.OTGender != pkm.OT_Gender) continue;
if (wc.PIDType == 0 && pk6.PID != wc.PID) continue; if (wc.PIDType == 0 && pkm.PID != wc.PID) continue;
if (wc.PIDType == 2 && !pk6.IsShiny) continue; if (wc.PIDType == 2 && !pkm.IsShiny) continue;
if (wc.PIDType == 3 && pk6.IsShiny) continue; if (wc.PIDType == 3 && pkm.IsShiny) continue;
if (wc.OriginGame != 0 && wc.OriginGame != pk6.Version) continue; if (wc.OriginGame != 0 && wc.OriginGame != pkm.Version) continue;
if (wc.EncryptionConstant != 0 && wc.EncryptionConstant != pk6.EncryptionConstant) continue; if (wc.EncryptionConstant != 0 && wc.EncryptionConstant != pkm.EncryptionConstant) continue;
if (wc.Language != 0 && wc.Language != pk6.Language) continue; if (wc.Language != 0 && wc.Language != pkm.Language) continue;
} }
if (wc.Form != pk6.AltForm && vs.All(dl => !FormChange.Contains(dl.Species))) continue; if (wc.Form != pkm.AltForm && vs.All(dl => !FormChange.Contains(dl.Species))) continue;
if (wc.MetLocation != pk6.Met_Location) continue; if (wc.MetLocation != pkm.Met_Location) continue;
if (wc.EggLocation != pk6.Egg_Location) continue; if (wc.EggLocation != pkm.Egg_Location) continue;
if (wc.Level != pk6.Met_Level) continue; if (wc.Level != pkm.Met_Level) continue;
if (wc.Pokéball != pk6.Ball) continue; if (wc.Ball != pkm.Ball) continue;
if (wc.OTGender < 3 && wc.OTGender != pk6.OT_Gender) continue; if (wc.OTGender < 3 && wc.OTGender != pkm.OT_Gender) continue;
if (wc.Nature != 0xFF && wc.Nature != pk6.Nature) continue; if (wc.Nature != 0xFF && wc.Nature != pkm.Nature) continue;
if (wc.Gender != 3 && wc.Gender != pk6.Gender) continue; if (wc.Gender != 3 && wc.Gender != pkm.Gender) continue;
if (wc.CNT_Cool > pk6.CNT_Cool) continue; if (wc.CNT_Cool > pkm.CNT_Cool) continue;
if (wc.CNT_Beauty > pk6.CNT_Beauty) continue; if (wc.CNT_Beauty > pkm.CNT_Beauty) continue;
if (wc.CNT_Cute > pk6.CNT_Cute) continue; if (wc.CNT_Cute > pkm.CNT_Cute) continue;
if (wc.CNT_Smart > pk6.CNT_Smart) continue; if (wc.CNT_Smart > pkm.CNT_Smart) continue;
if (wc.CNT_Tough > pk6.CNT_Tough) continue; if (wc.CNT_Tough > pkm.CNT_Tough) continue;
if (wc.CNT_Sheen > pk6.CNT_Sheen) 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. // Some checks are best performed separately as they are caused by users screwing up valid data.
// if (!wc.RelearnMoves.SequenceEqual(pk6.RelearnMoves)) continue; // Defer to relearn legality // if (!wc.RelearnMoves.SequenceEqual(pkm.RelearnMoves)) continue; // Defer to relearn legality
// if (wc.OT.Length > 0 && pk6.CurrentHandler != 1) continue; // Defer to ownership legality // if (wc.OT.Length > 0 && pkm.CurrentHandler != 1) continue; // Defer to ownership legality
// if (wc.OT.Length > 0 && pk6.OT_Friendship != PKX.getBaseFriendship(pk6.Species)) continue; // Friendship // if (wc.OT.Length > 0 && pkm.OT_Friendship != PKX.getBaseFriendship(pkm.Species)) continue; // Friendship
// if (wc.Level > pk6.CurrentLevel) continue; // Defer to level legality // if (wc.Level > pkm.CurrentLevel) continue; // Defer to level legality
// RIBBONS: Defer to ribbon legality // RIBBONS: Defer to ribbon legality
validWC6.Add(wc); validWC6.Add(wc);
} }
return validWC6; return validWC6;
} }
internal static EncounterLink getValidLinkGifts(PK6 pk6) internal static EncounterLink getValidLinkGifts(PKM pkm)
{ {
return LinkGifts.FirstOrDefault(g => g.Species == pk6.Species && g.Level == pk6.Met_Level); return LinkGifts.FirstOrDefault(g => g.Species == pkm.Species && g.Level == pkm.Met_Level);
} }
internal static EncounterSlot[] getValidWildEncounters(PK6 pk6) internal static EncounterSlot[] getValidWildEncounters(PKM pkm)
{ {
List<EncounterSlot> s = new List<EncounterSlot>(); List<EncounterSlot> s = new List<EncounterSlot>();
foreach (var area in getEncounterAreas(pk6)) foreach (var area in getEncounterAreas(pkm))
s.AddRange(getValidEncounterSlots(pk6, area, DexNav: pk6.AO)); s.AddRange(getValidEncounterSlots(pkm, area, DexNav: pkm.AO));
return s.Any() ? s.ToArray() : null; return s.Any() ? s.ToArray() : null;
} }
internal static EncounterStatic getValidStaticEncounter(PK6 pk6) internal static EncounterStatic getValidStaticEncounter(PKM pkm)
{ {
// Get possible encounters // Get possible encounters
IEnumerable<EncounterStatic> poss = getStaticEncounters(pk6); IEnumerable<EncounterStatic> poss = getStaticEncounters(pkm);
// Back Check against pk6 // Back Check against pkm
foreach (EncounterStatic e in poss) foreach (EncounterStatic e in poss)
{ {
if (e.Nature != Nature.Random && pk6.Nature != (int)e.Nature) if (e.Nature != Nature.Random && pkm.Nature != (int)e.Nature)
continue; continue;
if (e.EggLocation != pk6.Egg_Location) if (e.EggLocation != pkm.Egg_Location)
continue; continue;
if (e.Location != 0 && e.Location != pk6.Met_Location) if (e.Location != 0 && e.Location != pkm.Met_Location)
continue; continue;
if (e.Gender != -1 && e.Gender != pk6.Gender) if (e.Gender != -1 && e.Gender != pkm.Gender)
continue; continue;
if (e.Level != pk6.Met_Level) if (e.Level != pkm.Met_Level)
continue; continue;
// Defer to EC/PID check // Defer to EC/PID check
// if (e.Shiny != null && e.Shiny != pk6.IsShiny) // if (e.Shiny != null && e.Shiny != pkm.IsShiny)
// continue; // continue;
// Defer ball check to later // Defer ball check to later
// if (e.Gift && pk6.Ball != 4) // PokéBall // if (e.Gift && pkm.Ball != 4) // PokéBall
// continue; // continue;
// Passes all checks, valid encounter // Passes all checks, valid encounter
@ -211,119 +227,118 @@ namespace PKHeX
} }
return null; return null;
} }
internal static EncounterTrade getValidIngameTrade(PK6 pk6) internal static EncounterTrade getValidIngameTrade(PKM pkm)
{ {
if (!pk6.WasIngameTrade) if (!pkm.WasIngameTrade)
return null; return null;
int lang = pk6.Language; int lang = pkm.Language;
if (lang == 0) if (lang == 0)
return null; return null;
// Get valid pre-evolutions // Get valid pre-evolutions
IEnumerable<DexLevel> p = getValidPreEvolutions(pk6); IEnumerable<DexLevel> p = getValidPreEvolutions(pkm);
EncounterTrade z = null; EncounterTrade z = null;
if (pk6.XY) if (pkm.XY)
z = lang == 6 ? null : TradeGift_XY.FirstOrDefault(f => p.Any(r => r.Species == f.Species)); z = lang == 6 ? null : TradeGift_XY.FirstOrDefault(f => p.Any(r => r.Species == f.Species));
if (pk6.AO) if (pkm.AO)
z = lang == 6 ? null : TradeGift_AO.FirstOrDefault(f => p.Any(r => r.Species == f.Species)); z = lang == 6 ? null : TradeGift_AO.FirstOrDefault(f => p.Any(r => r.Species == f.Species));
if (z == null) if (z == null)
return null; return null;
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
if (z.IVs[i] != -1 && z.IVs[i] != pk6.IVs[i]) if (z.IVs[i] != -1 && z.IVs[i] != pkm.IVs[i])
return null; return null;
if (z.Shiny ^ pk6.IsShiny) // Are PIDs static? if (z.Shiny ^ pkm.IsShiny) // Are PIDs static?
return null; return null;
if (z.TID != pk6.TID) if (z.TID != pkm.TID)
return null; return null;
if (z.SID != pk6.SID) if (z.SID != pkm.SID)
return null; return null;
if (z.Location != pk6.Met_Location) if (z.Location != pkm.Met_Location)
return null; return null;
if (z.Level != pk6.Met_Level) if (z.Level != pkm.Met_Level)
return null; return null;
if (z.Nature != Nature.Random && (int)z.Nature != pk6.Nature) if (z.Nature != Nature.Random && (int)z.Nature != pkm.Nature)
return null; return null;
if (z.Gender != pk6.Gender) if (z.Gender != pkm.Gender)
return null; return null;
// if (z.Ability == 4 ^ pk6.AbilityNumber == 4) // defer to Ability // if (z.Ability == 4 ^ pkm.AbilityNumber == 4) // defer to Ability
// return null; // return null;
return z; return z;
} }
internal static EncounterSlot[] getValidFriendSafari(PK6 pk6) internal static EncounterSlot[] getValidFriendSafari(PKM pkm)
{ {
if (!pk6.XY) if (!pkm.XY)
return null; return null;
if (pk6.Met_Location != 148) // Friend Safari if (pkm.Met_Location != 148) // Friend Safari
return null; return null;
if (pk6.Met_Level != 30) if (pkm.Met_Level != 30)
return null; return null;
IEnumerable<DexLevel> vs = getValidPreEvolutions(pk6); IEnumerable<DexLevel> vs = getValidPreEvolutions(pkm);
List<EncounterSlot> slots = new List<EncounterSlot>(); List<EncounterSlot> slots = new List<EncounterSlot>();
foreach (DexLevel d in vs.Where(d => FriendSafari.Contains(d.Species) && d.Level >= 30)) foreach (DexLevel d in vs.Where(d => FriendSafari.Contains(d.Species) && d.Level >= 30))
{ {
var slot = new EncounterSlot slots.Add(new EncounterSlot
{ {
Species = d.Species, Species = d.Species,
LevelMin = 30, LevelMin = 30,
LevelMax = 30, LevelMax = 30,
Form = 0, Form = 0,
Type = SlotType.FriendSafari, Type = SlotType.FriendSafari,
}; });
slots.Add(slot);
} }
return slots.Any() ? slots.ToArray() : null; return slots.Any() ? slots.ToArray() : null;
} }
internal static bool getDexNavValid(PK6 pk6) internal static bool getDexNavValid(PKM pkm)
{ {
IEnumerable<EncounterArea> locs = getDexNavAreas(pk6); IEnumerable<EncounterArea> locs = getDexNavAreas(pkm);
return locs.Select(loc => getValidEncounterSlots(pk6, loc, DexNav: true)).Any(slots => slots.Any(slot => slot.AllowDexNav && slot.DexNav)); return locs.Select(loc => getValidEncounterSlots(pkm, loc, DexNav: true)).Any(slots => slots.Any(slot => slot.AllowDexNav && slot.DexNav));
} }
internal static bool getHasEvolved(PK6 pk6) internal static bool getHasEvolved(PKM pkm)
{ {
return getValidPreEvolutions(pk6).Count() > 1; return getValidPreEvolutions(pkm).Count() > 1;
} }
internal static bool getHasTradeEvolved(PK6 pk6) internal static bool getHasTradeEvolved(PKM pkm)
{ {
return Evolves[pk6.Species].Evos.Any(evo => evo.Level == 1); // 1: Trade, 0: Item, >=2: Levelup return Evolves[pkm.Species].Evos.Any(evo => evo.Level == 1); // 1: Trade, 0: Item, >=2: Levelup
} }
internal static bool getIsFossil(PK6 pk6) internal static bool getIsFossil(PKM pkm)
{ {
if (pk6.Met_Level != 20) if (pkm.Met_Level != 20)
return false; return false;
if (pk6.Egg_Location != 0) if (pkm.Egg_Location != 0)
return false; return false;
if (pk6.XY && pk6.Met_Location == 44) if (pkm.XY && pkm.Met_Location == 44)
return Fossils.Contains(getBaseSpecies(pk6)); return Fossils.Contains(getBaseSpecies(pkm));
if (pk6.AO && pk6.Met_Location == 190) if (pkm.AO && pkm.Met_Location == 190)
return Fossils.Contains(getBaseSpecies(pk6)); return Fossils.Contains(getBaseSpecies(pkm));
return false; return false;
} }
internal static bool getEvolutionValid(PK6 pk6) internal static bool getEvolutionValid(PKM pkm)
{ {
var curr = getValidPreEvolutions(pk6); var curr = getValidPreEvolutions(pkm);
var poss = getValidPreEvolutions(pk6, 100); var poss = getValidPreEvolutions(pkm, 100);
if (SplitBreed.Contains(getBaseSpecies(pk6, 1))) if (SplitBreed.Contains(getBaseSpecies(pkm, 1)))
return curr.Count() >= poss.Count() - 1; return curr.Count() >= poss.Count() - 1;
return curr.Count() >= poss.Count(); return curr.Count() >= poss.Count();
} }
internal static IEnumerable<int> getLineage(PK6 pk6) internal static IEnumerable<int> getLineage(PKM pkm)
{ {
int species = pk6.Species; int species = pkm.Species;
List<int> res = new List<int>{species}; List<int> res = new List<int>{species};
for (int i = 0; i < Evolves.Length; i++) for (int i = 0; i < Evolves.Length; i++)
if (Evolves[i].Evos.Any(pk => pk.Species == species)) if (Evolves[i].Evos.Any(pk => pk.Species == species))
res.Add(i); res.Add(i);
for (int i = -1; i < 2; i++) for (int i = -1; i < 2; i++)
res.Add(getBaseSpecies(pk6, i)); res.Add(getBaseSpecies(pkm, i));
return res.Distinct(); return res.Distinct();
} }
@ -363,45 +378,45 @@ namespace PKHeX
} }
return false; return false;
} }
internal static bool getCanLearnMachineMove(PK6 pk6, int move, int version = -1) internal static bool getCanLearnMachineMove(PKM pkm, int move, int version = -1)
{ {
return getValidMoves(pk6, version, Machine: true).Contains(move); return getValidMoves(pkm, version, Machine: true).Contains(move);
} }
internal static bool getCanRelearnMove(PK6 pk6, int move, int version = -1) internal static bool getCanRelearnMove(PKM pkm, int move, int version = -1)
{ {
return getValidMoves(pk6, version, LVL: true, Relearn: true).Contains(move); return getValidMoves(pkm, version, LVL: true, Relearn: true).Contains(move);
} }
internal static bool getCanLearnMove(PK6 pk6, int move, int version = -1) internal static bool getCanLearnMove(PKM pkm, int move, int version = -1)
{ {
return getValidMoves(pk6, version, Tutor: true, Machine: true).Contains(move); return getValidMoves(pkm, version, Tutor: true, Machine: true).Contains(move);
} }
internal static bool getCanKnowMove(PK6 pk6, int move, int version = -1) internal static bool getCanKnowMove(PKM pkm, int move, int version = -1)
{ {
if (pk6.Species == 235 && !InvalidSketch.Contains(move)) if (pkm.Species == 235 && !InvalidSketch.Contains(move))
return true; return true;
return getValidMoves(pk6, Version: version, LVL: true, Relearn: true, Tutor: true, Machine: true).Contains(move); return getValidMoves(pkm, Version: version, LVL: true, Relearn: true, Tutor: true, Machine: true).Contains(move);
} }
private static int getBaseSpecies(PK6 pk6, int skipOption = 0) private static int getBaseSpecies(PKM pkm, int skipOption = 0)
{ {
if (pk6.Species == 292) if (pkm.Species == 292)
return 290; return 290;
if (pk6.Species == 242 && pk6.CurrentLevel < 3) // Never Cleffa if (pkm.Species == 242 && pkm.CurrentLevel < 3) // Never Cleffa
return 113; return 113;
DexLevel[] evos = Evolves[pk6.Species].Evos; DexLevel[] evos = Evolves[pkm.Species].Evos;
switch (skipOption) switch (skipOption)
{ {
case -1: return pk6.Species; case -1: return pkm.Species;
case 1: return evos.Length <= 1 ? pk6.Species : evos[evos.Length - 2].Species; case 1: return evos.Length <= 1 ? pkm.Species : evos[evos.Length - 2].Species;
default: return evos.Length <= 0 ? pk6.Species : evos.Last().Species; default: return evos.Length <= 0 ? pkm.Species : evos.Last().Species;
} }
} }
private static IEnumerable<EncounterArea> getDexNavAreas(PK6 pk6) private static IEnumerable<EncounterArea> getDexNavAreas(PKM pkm)
{ {
bool alpha = pk6.Version == 26; bool alpha = pkm.Version == 26;
if (!alpha && pk6.Version != 27) if (!alpha && pkm.Version != 27)
return new EncounterArea[0]; return new EncounterArea[0];
return (alpha ? SlotsA : SlotsO).Where(l => l.Location == pk6.Met_Location); return (alpha ? SlotsA : SlotsO).Where(l => l.Location == pkm.Met_Location);
} }
private static IEnumerable<int> getLVLMoves(int species, int lvl, int formnum) private static IEnumerable<int> getLVLMoves(int species, int lvl, int formnum)
{ {
@ -409,41 +424,41 @@ namespace PKHeX
int ind_AO = PersonalTable.AO.getFormeIndex(species, formnum); int ind_AO = PersonalTable.AO.getFormeIndex(species, formnum);
return LevelUpXY[ind_XY].getMoves(lvl).Concat(LevelUpAO[ind_AO].getMoves(lvl)); return LevelUpXY[ind_XY].getMoves(lvl).Concat(LevelUpAO[ind_AO].getMoves(lvl));
} }
private static IEnumerable<EncounterArea> getEncounterSlots(PK6 pk6) private static IEnumerable<EncounterArea> getEncounterSlots(PKM pkm)
{ {
switch (pk6.Version) switch (pkm.Version)
{ {
case 24: // X case 24: // X
return getSlots(pk6, SlotsX); return getSlots(pkm, SlotsX);
case 25: // Y case 25: // Y
return getSlots(pk6, SlotsY); return getSlots(pkm, SlotsY);
case 26: // AS case 26: // AS
return getSlots(pk6, SlotsA); return getSlots(pkm, SlotsA);
case 27: // OR case 27: // OR
return getSlots(pk6, SlotsO); return getSlots(pkm, SlotsO);
default: return new List<EncounterArea>(); default: return new List<EncounterArea>();
} }
} }
private static IEnumerable<EncounterStatic> getStaticEncounters(PK6 pk6) private static IEnumerable<EncounterStatic> getStaticEncounters(PKM pkm)
{ {
switch (pk6.Version) switch (pkm.Version)
{ {
case 24: // X case 24: // X
return getStatic(pk6, StaticX); return getStatic(pkm, StaticX);
case 25: // Y case 25: // Y
return getStatic(pk6, StaticY); return getStatic(pkm, StaticY);
case 26: // AS case 26: // AS
return getStatic(pk6, StaticA); return getStatic(pkm, StaticA);
case 27: // OR case 27: // OR
return getStatic(pk6, StaticO); return getStatic(pkm, StaticO);
default: return new List<EncounterStatic>(); default: return new List<EncounterStatic>();
} }
} }
private static IEnumerable<EncounterArea> getEncounterAreas(PK6 pk6) private static IEnumerable<EncounterArea> getEncounterAreas(PKM pkm)
{ {
return getEncounterSlots(pk6).Where(l => l.Location == pk6.Met_Location); return getEncounterSlots(pkm).Where(l => l.Location == pkm.Met_Location);
} }
private static IEnumerable<EncounterSlot> getValidEncounterSlots(PK6 pk6, EncounterArea loc, bool DexNav) private static IEnumerable<EncounterSlot> getValidEncounterSlots(PKM pkm, EncounterArea loc, bool DexNav)
{ {
const int fluteBoost = 4; const int fluteBoost = 4;
const int dexnavBoost = 30; const int dexnavBoost = 30;
@ -452,36 +467,36 @@ namespace PKHeX
List<EncounterSlot> slotdata = new List<EncounterSlot>(); List<EncounterSlot> slotdata = new List<EncounterSlot>();
// Get Valid levels // Get Valid levels
IEnumerable<DexLevel> vs = getValidPreEvolutions(pk6); IEnumerable<DexLevel> vs = getValidPreEvolutions(pkm);
// Get slots where pokemon can exist // Get slots where pokemon can exist
IEnumerable<EncounterSlot> slots = loc.Slots.Where(slot => vs.Any(evo => evo.Species == slot.Species && evo.Level >= slot.LevelMin - df)); IEnumerable<EncounterSlot> slots = loc.Slots.Where(slot => vs.Any(evo => evo.Species == slot.Species && evo.Level >= slot.LevelMin - df));
// Filter for Met Level // Filter for Met Level
int lvl = pk6.Met_Level; int lvl = pkm.Met_Level;
var encounterSlots = slots.Where(slot => slot.LevelMin - df <= lvl && lvl <= slot.LevelMax + (slot.AllowDexNav ? dn : df)).ToList(); var encounterSlots = slots.Where(slot => slot.LevelMin - df <= lvl && lvl <= slot.LevelMax + (slot.AllowDexNav ? dn : df)).ToList();
// Pressure Slot // Pressure Slot
EncounterSlot slotMax = encounterSlots.OrderByDescending(slot => slot.LevelMax).FirstOrDefault(); EncounterSlot slotMax = encounterSlots.OrderByDescending(slot => slot.LevelMax).FirstOrDefault();
if (slotMax != null) if (slotMax != null)
slotMax = new EncounterSlot(slotMax) { Pressure = true, Form = pk6.AltForm }; slotMax = new EncounterSlot(slotMax) { Pressure = true, Form = pkm.AltForm };
if (!DexNav) if (!DexNav)
{ {
// Filter for Form Specific // Filter for Form Specific
slotdata.AddRange(WildForms.Contains(pk6.Species) slotdata.AddRange(WildForms.Contains(pkm.Species)
? encounterSlots.Where(slot => slot.Form == pk6.AltForm) ? encounterSlots.Where(slot => slot.Form == pkm.AltForm)
: encounterSlots); : encounterSlots);
if (slotMax != null) if (slotMax != null)
slotdata.Add(slotMax); slotdata.Add(slotMax);
return slotdata; return slotdata;
} }
List<EncounterSlot> eslots = encounterSlots.Where(slot => !WildForms.Contains(pk6.Species) || slot.Form == pk6.AltForm).ToList(); List<EncounterSlot> eslots = encounterSlots.Where(slot => !WildForms.Contains(pkm.Species) || slot.Form == pkm.AltForm).ToList();
if (slotMax != null) if (slotMax != null)
eslots.Add(slotMax); eslots.Add(slotMax);
foreach (EncounterSlot s in eslots) foreach (EncounterSlot s in eslots)
{ {
bool nav = s.AllowDexNav && (pk6.RelearnMove1 != 0 || pk6.AbilityNumber == 4); bool nav = s.AllowDexNav && (pkm.RelearnMove1 != 0 || pkm.AbilityNumber == 4);
EncounterSlot slot = new EncounterSlot(s) { DexNav = nav }; EncounterSlot slot = new EncounterSlot(s) { DexNav = nav };
if (slot.LevelMin > lvl) if (slot.LevelMin > lvl)
@ -494,9 +509,9 @@ namespace PKHeX
} }
return slotdata; return slotdata;
} }
private static IEnumerable<EncounterArea> getSlots(PK6 pk6, IEnumerable<EncounterArea> tables) private static IEnumerable<EncounterArea> getSlots(PKM pkm, IEnumerable<EncounterArea> tables)
{ {
IEnumerable<DexLevel> vs = getValidPreEvolutions(pk6); IEnumerable<DexLevel> vs = getValidPreEvolutions(pkm);
List<EncounterArea> slotLocations = new List<EncounterArea>(); List<EncounterArea> slotLocations = new List<EncounterArea>();
foreach (var loc in tables) foreach (var loc in tables)
{ {
@ -508,21 +523,21 @@ namespace PKHeX
} }
return slotLocations; return slotLocations;
} }
private static IEnumerable<DexLevel> getValidPreEvolutions(PK6 pk6, int lvl = -1) private static IEnumerable<DexLevel> getValidPreEvolutions(PKM pkm, int lvl = -1)
{ {
if (lvl < 0) if (lvl < 0)
lvl = pk6.CurrentLevel; lvl = pkm.CurrentLevel;
if (pk6.Species == 292 && pk6.Met_Level + 1 <= lvl && lvl >= 20) if (pkm.Species == 292 && pkm.Met_Level + 1 <= lvl && lvl >= 20)
return new List<DexLevel> return new List<DexLevel>
{ {
new DexLevel { Species = 292, Level = lvl }, new DexLevel { Species = 292, Level = lvl },
new DexLevel { Species = 290, Level = lvl-1 } new DexLevel { Species = 290, Level = lvl-1 }
}; };
var evos = Evolves[pk6.Species].Evos; var evos = Evolves[pkm.Species].Evos;
List<DexLevel> dl = new List<DexLevel> { new DexLevel { Species = pk6.Species, Level = lvl } }; List<DexLevel> dl = new List<DexLevel> { new DexLevel { Species = pkm.Species, Level = lvl } };
foreach (DexLevel evo in evos) foreach (DexLevel evo in evos)
{ {
if (lvl >= pk6.Met_Level && lvl >= evo.Level) if (lvl >= pkm.Met_Level && lvl >= evo.Level)
dl.Add(new DexLevel {Species = evo.Species, Level = lvl}); dl.Add(new DexLevel {Species = evo.Species, Level = lvl});
else break; else break;
if (evo.Level > 2) // Level Up (from previous level) if (evo.Level > 2) // Level Up (from previous level)
@ -530,37 +545,37 @@ namespace PKHeX
} }
return dl; return dl;
} }
private static IEnumerable<EncounterStatic> getStatic(PK6 pk6, IEnumerable<EncounterStatic> table) private static IEnumerable<EncounterStatic> getStatic(PKM pkm, IEnumerable<EncounterStatic> table)
{ {
IEnumerable<DexLevel> dl = getValidPreEvolutions(pk6); IEnumerable<DexLevel> dl = getValidPreEvolutions(pkm);
return table.Where(e => dl.Any(d => d.Species == e.Species)); return table.Where(e => dl.Any(d => d.Species == e.Species));
} }
private static IEnumerable<int> getValidMoves(PK6 pk6, int Version, bool LVL = false, bool Relearn = false, bool Tutor = false, bool Machine = false) private static IEnumerable<int> getValidMoves(PKM pkm, int Version, bool LVL = false, bool Relearn = false, bool Tutor = false, bool Machine = false)
{ {
List<int> r = new List<int> { 0 }; List<int> r = new List<int> { 0 };
int species = pk6.Species; int species = pkm.Species;
int lvl = pk6.CurrentLevel; int lvl = pkm.CurrentLevel;
bool ORASTutors = Version == -1 || pk6.AO || !pk6.IsUntraded; bool ORASTutors = Version == -1 || pkm.AO || !pkm.IsUntraded;
if (FormChangeMoves.Contains(species)) // Deoxys & Shaymin & Giratina (others don't have extra but whatever) if (FormChangeMoves.Contains(species)) // Deoxys & Shaymin & Giratina (others don't have extra but whatever)
{ {
int formcount = PersonalTable.AO[species].FormeCount; int formcount = PersonalTable.AO[species].FormeCount;
for (int i = 0; i < formcount; i++) for (int i = 0; i < formcount; i++)
r.AddRange(getMoves(species, lvl, i, ORASTutors, Version, LVL, Tutor, Machine)); r.AddRange(getMoves(species, lvl, i, ORASTutors, Version, LVL, Tutor, Machine));
if (Relearn) r.AddRange(pk6.RelearnMoves); if (Relearn) r.AddRange(pkm.RelearnMoves);
return r.Distinct().ToArray(); return r.Distinct().ToArray();
} }
r.AddRange(getMoves(species, lvl, pk6.AltForm, ORASTutors, Version, LVL, Tutor, Machine)); r.AddRange(getMoves(species, lvl, pkm.AltForm, ORASTutors, Version, LVL, Tutor, Machine));
IEnumerable<DexLevel> vs = getValidPreEvolutions(pk6); IEnumerable<DexLevel> vs = getValidPreEvolutions(pkm);
foreach (DexLevel evo in vs) foreach (DexLevel evo in vs)
r.AddRange(getMoves(evo.Species, evo.Level, pk6.AltForm, ORASTutors, Version, LVL, Tutor, Machine)); r.AddRange(getMoves(evo.Species, evo.Level, pkm.AltForm, ORASTutors, Version, LVL, Tutor, Machine));
if (species == 479) // Rotom if (species == 479) // Rotom
r.Add(RotomMoves[pk6.AltForm]); r.Add(RotomMoves[pkm.AltForm]);
if (species == 25) // Pikachu if (species == 25) // Pikachu
r.Add(PikachuMoves[pk6.AltForm]); r.Add(PikachuMoves[pkm.AltForm]);
if (Relearn) r.AddRange(pk6.RelearnMoves); if (Relearn) r.AddRange(pkm.RelearnMoves);
return r.Distinct().ToArray(); 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(int species, int lvl, int form, bool ORASTutors, int Version, bool LVL, bool Tutor, bool Machine)

View file

@ -312,7 +312,13 @@ namespace PKHeX
internal static readonly int[] Gen4EncounterTypes = { 1, 2, 4, 5, 7, 9, 10, 12, 23, 24 }; internal static readonly int[] Gen4EncounterTypes = { 1, 2, 4, 5, 7, 9, 10, 12, 23, 24 };
internal const int Struggle = 165; internal const int Struggle = 165;
internal const int Chatter = 448; internal const int Chatter = 448;
internal static readonly int[] InvalidSketch = {Struggle, Chatter}; internal static readonly int[] InvalidSketch =
{
// Regular Moves
Struggle, Chatter
// Z-Moves
};
internal static readonly int[] EggLocations = {60002, 30002}; internal static readonly int[] EggLocations = {60002, 30002};
internal static readonly int[] LightBall = {25, 26, 172}; internal static readonly int[] LightBall = {25, 26, 172};
internal static readonly int[] Fossils = {138, 140, 142, 345, 347, 408, 410, 564, 566, 696, 698}; internal static readonly int[] Fossils = {138, 140, 142, 345, 347, 408, 410, 564, 566, 696, 698};
@ -861,7 +867,7 @@ namespace PKHeX
497, 500, 503, //3 497, 500, 503, //3
566, 567, 696, 697, 698, 699 // Fossil Only obtain 566, 567, 696, 697, 698, 699 // Fossil Only obtain
}; };
internal static readonly int[] WurmpleFamily = internal static readonly int[] WurmpleEvolutions =
{ {
266, 267, // Silcoon Beautifly 266, 267, // Silcoon Beautifly
268, 269, // Cascoon Dustox 268, 269, // Cascoon Dustox

View file

@ -37,5 +37,10 @@ namespace PKHeX
776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 798, 799, 800, 801, 802, 803, 804, 805, 806, 836 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 798, 799, 800, 801, 802, 803, 804, 805, 806, 836
}; };
internal static readonly ushort[] HeldItems_SM = new ushort[1].Concat(Pouch_Items_SM).Concat(Pouch_Berries_SM).Concat(Pouch_Medicine_SM).Concat(Pouch_ZCrystal_SM).ToArray(); internal static readonly ushort[] HeldItems_SM = new ushort[1].Concat(Pouch_Items_SM).Concat(Pouch_Berries_SM).Concat(Pouch_Medicine_SM).Concat(Pouch_ZCrystal_SM).ToArray();
private static readonly EncounterStatic[] Encounter_SM =
{
};
} }
} }

View file

@ -2113,7 +2113,7 @@ namespace PKHeX
Util.Alert("EC should match PID."); Util.Alert("EC should match PID.");
} }
int wIndex = Array.IndexOf(Legal.WurmpleFamily, Util.getIndex(CB_Species)); int wIndex = Array.IndexOf(Legal.WurmpleEvolutions, Util.getIndex(CB_Species));
if (wIndex < 0) if (wIndex < 0)
{ {
TB_EC.Text = Util.rnd32().ToString("X8"); TB_EC.Text = Util.rnd32().ToString("X8");
@ -2774,6 +2774,11 @@ namespace PKHeX
private void showLegality(PKM pk, bool tabs, bool verbose) private void showLegality(PKM pk, bool tabs, bool verbose)
{ {
LegalityAnalysis la = new LegalityAnalysis(pk); LegalityAnalysis la = new LegalityAnalysis(pk);
if (!la.Native)
{
Util.Alert($"Checking legality of PK{pk.Format} files that originated from Gen{pk.GenNumber} is not supported.");
return;
}
if (tabs) if (tabs)
updateLegality(la); updateLegality(la);
Util.Alert(verbose ? la.VerboseReport : la.Report); Util.Alert(verbose ? la.VerboseReport : la.Report);
@ -2782,11 +2787,15 @@ namespace PKHeX
{ {
if (!fieldsLoaded) if (!fieldsLoaded)
return; return;
if (!(pkm is PK6)) Legality = la ?? new LegalityAnalysis(pkm);
if (!Legality.Parsed || !Legality.Native || HaX)
{
PB_Legal.Visible = false;
return; return;
Legality = la ?? new LegalityAnalysis((PK6) pkm); }
PB_Legal.Visible = true;
PB_Legal.Image = Legality.Valid ? Properties.Resources.valid : Properties.Resources.warn; PB_Legal.Image = Legality.Valid ? Properties.Resources.valid : Properties.Resources.warn;
PB_Legal.Visible = pkm.Gen6 /*&& pkm is PK6*/ && !HaX;
// Refresh Move Legality // Refresh Move Legality
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
@ -3378,12 +3387,7 @@ namespace PKHeX
if (pk.Species == 0 || !pk.ChecksumValid) if (pk.Species == 0 || !pk.ChecksumValid)
{ SystemSounds.Asterisk.Play(); return; } { SystemSounds.Asterisk.Play(); return; }
if (typeof (PK6) != pk.GetType()) showLegality(pk, slot < 0, ModifierKeys == Keys.Control);
{
Util.Alert($"Checking legality of {pk.GetType().Name} files is not supported.");
return;
}
showLegality(pk as PK6, slot < 0, ModifierKeys == Keys.Control);
} }
private void updateSaveSlot(object sender, EventArgs e) private void updateSaveSlot(object sender, EventArgs e)
{ {
@ -3715,7 +3719,7 @@ namespace PKHeX
} }
private void switchDaycare(object sender, EventArgs e) private void switchDaycare(object sender, EventArgs e)
{ {
if (!SAV.ORAS) return; if (!SAV.HasTwoDaycares) return;
if (DialogResult.Yes == Util.Prompt(MessageBoxButtons.YesNo, "Would you like to switch the view to the other Daycare?", if (DialogResult.Yes == Util.Prompt(MessageBoxButtons.YesNo, "Would you like to switch the view to the other Daycare?",
$"Currently viewing daycare {SAV.DaycareIndex + 1}.")) $"Currently viewing daycare {SAV.DaycareIndex + 1}."))
// If ORAS, alter the daycare offset via toggle. // If ORAS, alter the daycare offset via toggle.

View file

@ -1,5 +1,4 @@
using System; using System.Linq;
using System.Linq;
namespace PKHeX namespace PKHeX
{ {
@ -90,10 +89,15 @@ namespace PKHeX
// Search Properties // Search Properties
public virtual int Species { get { return -1; } set { } } public virtual int Species { get { return -1; } set { } }
public virtual int[] Moves => new int[0]; public virtual int[] Moves => new int[4];
public virtual int[] RelearnMoves { get { return new int[4]; } set { } }
public virtual bool IsShiny => false; public virtual bool IsShiny => false;
public virtual bool IsEgg { get { return false; } set { } } public virtual bool IsEgg { get { return false; } set { } }
public virtual int HeldItem { get { return -1; } set { } } public virtual int HeldItem { get { return -1; } set { } }
public virtual object Content => this;
public abstract int Level { get; set; }
public abstract int Ball { get; set; }
public bool Gen7 => Format == 7; public bool Gen7 => Format == 7;
public bool Gen6 => Format == 6; public bool Gen6 => Format == 6;
public bool Gen5 => Format == 5; public bool Gen5 => Format == 5;

View file

@ -40,7 +40,7 @@ namespace PKHeX
public bool RibbonChampionWorld { get { return (RIB1 & (1 << 6)) == 1 << 6; } set { RIB1 = (byte)(RIB1 & ~(1 << 6) | (value ? 1 << 6 : 0)); } } // World Champ Ribbon public bool RibbonChampionWorld { get { return (RIB1 & (1 << 6)) == 1 << 6; } set { RIB1 = (byte)(RIB1 & ~(1 << 6) | (value ? 1 << 6 : 0)); } } // World Champ Ribbon
public bool RIB1_7 { get { return (RIB1 & (1 << 7)) == 1 << 7; } set { RIB1 = (byte)(RIB1 & ~(1 << 7) | (value ? 1 << 7 : 0)); } } // Empty public bool RIB1_7 { get { return (RIB1 & (1 << 7)) == 1 << 7; } set { RIB1 = (byte)(RIB1 & ~(1 << 7) | (value ? 1 << 7 : 0)); } } // Empty
public int Pokéball { get { return Data[0x0E]; } set { Data[0x0E] = (byte)value; } } public override int Ball { get { return Data[0x0E]; } set { Data[0x0E] = (byte)value; } }
public override int HeldItem { get { return BitConverter.ToUInt16(Data, 0x10); } set { BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x10); } } public override int HeldItem { get { return BitConverter.ToUInt16(Data, 0x10); } set { BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x10); } }
public int Move1 { get { return BitConverter.ToUInt16(Data, 0x12); } set { BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x12); } } public int Move1 { get { return BitConverter.ToUInt16(Data, 0x12); } set { BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x12); } }
public int Move2 { get { return BitConverter.ToUInt16(Data, 0x14); } set { BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x14); } } public int Move2 { get { return BitConverter.ToUInt16(Data, 0x14); } set { BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x14); } }
@ -79,7 +79,7 @@ namespace PKHeX
get { return PKX.TrimFromFFFF(Encoding.Unicode.GetString(Data, 0x4A, 0x10)); } get { return PKX.TrimFromFFFF(Encoding.Unicode.GetString(Data, 0x4A, 0x10)); }
set { Encoding.Unicode.GetBytes(value.PadRight(0x08, (char)0xFFFF)).CopyTo(Data, 0x4A); } } set { Encoding.Unicode.GetBytes(value.PadRight(0x08, (char)0xFFFF)).CopyTo(Data, 0x4A); } }
public int OTGender { get { return Data[0x5A]; } set { Data[0x5A] = (byte)value; } } public int OTGender { get { return Data[0x5A]; } set { Data[0x5A] = (byte)value; } }
public int Level { get { return Data[0x5B]; } set { Data[0x5C] = (byte)value; } } public override int Level { get { return Data[0x5B]; } set { Data[0x5C] = (byte)value; } }
public override bool IsEgg { get { return Data[0x5C] == 1; } set { Data[0x5C] = (byte)(value ? 1 : 0); } } public override bool IsEgg { get { return Data[0x5C] == 1; } set { Data[0x5C] = (byte)(value ? 1 : 0); } }
// Unused 0x5D 0x5E 0x5F // Unused 0x5D 0x5E 0x5F
public override string CardTitle public override string CardTitle
@ -174,7 +174,7 @@ namespace PKHeX
AltForm = Form, AltForm = Form,
Version = OriginGame == 0 ? new[] {20, 21, 22, 23}[Util.rnd32() & 0x3] : OriginGame, Version = OriginGame == 0 ? new[] {20, 21, 22, 23}[Util.rnd32() & 0x3] : OriginGame,
Language = Language == 0 ? SAV.Language : Language, Language = Language == 0 ? SAV.Language : Language,
Ball = Pokéball, Ball = Ball,
Move1 = Move1, Move1 = Move1,
Move2 = Move2, Move2 = Move2,
Move3 = Move3, Move3 = Move3,

View file

@ -12,6 +12,16 @@ namespace PKHeX
{ {
internal const int Size = 0x358; // 856 internal const int Size = 0x358; // 856
public override int Format => 4; public override int Format => 4;
public override int Level
{
get { return Gift.Level; }
set { Gift.Level = value; }
}
public override int Ball
{
get { return Gift.Ball; }
set { Gift.Ball = value; }
}
public PCD(byte[] data = null) public PCD(byte[] data = null)
{ {
@ -25,6 +35,7 @@ namespace PKHeX
Array.Copy(Data, PGT.Size, Information, 0, Information.Length); Array.Copy(Data, PGT.Size, Information, 0, Information.Length);
} }
public readonly PGT Gift; public readonly PGT Gift;
public override object Content => Gift.PK;
public readonly byte[] Information; public readonly byte[] Information;
public override bool GiftUsed { get { return Gift.GiftUsed; } set { Gift.GiftUsed = value; } } public override bool GiftUsed { get { return Gift.GiftUsed; } set { Gift.GiftUsed = value; } }
@ -65,6 +76,16 @@ namespace PKHeX
{ {
internal const int Size = 0x104; // 260 internal const int Size = 0x104; // 260
public override int Format => 4; public override int Format => 4;
public override int Level
{
get { return IsPokémon ? PK.Met_Level : 0; }
set { if (IsPokémon) PK.Met_Level = value; }
}
public override int Ball
{
get { return IsPokémon ? PK.Ball : 0; }
set { if (IsPokémon) PK.Ball = value; }
}
private enum GiftType private enum GiftType
{ {
@ -86,6 +107,7 @@ namespace PKHeX
public override string CardTitle { get { return "Raw Gift (PGT)"; } set { } } public override string CardTitle { get { return "Raw Gift (PGT)"; } set { } }
public override int CardID { get { return -1; } set { } } public override int CardID { get { return -1; } set { } }
public override bool GiftUsed { get { return false; } set { } } public override bool GiftUsed { get { return false; } set { } }
public override object Content => PK;
public PGT(byte[] data = null) public PGT(byte[] data = null)
{ {

View file

@ -107,7 +107,7 @@ namespace PKHeX
public uint EncryptionConstant { public uint EncryptionConstant {
get { return BitConverter.ToUInt32(Data, 0x70); } get { return BitConverter.ToUInt32(Data, 0x70); }
set { BitConverter.GetBytes(value).CopyTo(Data, 0x70); } } set { BitConverter.GetBytes(value).CopyTo(Data, 0x70); } }
public int Pokéball { public override int Ball {
get { return Data[0x76]; } get { return Data[0x76]; }
set { Data[0x76] = (byte)value; } } set { Data[0x76] = (byte)value; } }
public override int HeldItem { public override int HeldItem {
@ -174,7 +174,7 @@ namespace PKHeX
public string OT { public string OT {
get { return Util.TrimFromZero(Encoding.Unicode.GetString(Data, 0xB6, 0x1A)); } get { return Util.TrimFromZero(Encoding.Unicode.GetString(Data, 0xB6, 0x1A)); }
set { Encoding.Unicode.GetBytes(value.PadRight(value.Length + 1, '\0')).CopyTo(Data, 0xB6); } } set { Encoding.Unicode.GetBytes(value.PadRight(value.Length + 1, '\0')).CopyTo(Data, 0xB6); } }
public int Level { get { return Data[0xD0]; } set { Data[0xD0] = (byte)value; } } public override int Level { get { return Data[0xD0]; } set { Data[0xD0] = (byte)value; } }
public override bool IsEgg { get { return Data[0xD1] == 1; } set { Data[0xD1] = (byte)(value ? 1 : 0); } } public override bool IsEgg { get { return Data[0xD1] == 1; } set { Data[0xD1] = (byte)(value ? 1 : 0); } }
public uint PID { public uint PID {
get { return BitConverter.ToUInt32(Data, 0xD4); } get { return BitConverter.ToUInt32(Data, 0xD4); }
@ -223,7 +223,7 @@ namespace PKHeX
{ {
get { return new[] {Move1, Move2, Move3, Move4}; } get { return new[] {Move1, Move2, Move3, Move4}; }
} }
public int[] RelearnMoves public override int[] RelearnMoves
{ {
get { return new[] { RelearnMove1, RelearnMove2, RelearnMove3, RelearnMove4 }; } get { return new[] { RelearnMove1, RelearnMove2, RelearnMove3, RelearnMove4 }; }
set set
@ -254,7 +254,7 @@ namespace PKHeX
EncryptionConstant = EncryptionConstant == 0 ? Util.rnd32() : EncryptionConstant, EncryptionConstant = EncryptionConstant == 0 ? Util.rnd32() : EncryptionConstant,
Version = OriginGame == 0 ? SAV.Game : OriginGame, Version = OriginGame == 0 ? SAV.Game : OriginGame,
Language = Language == 0 ? SAV.Language : Language, Language = Language == 0 ? SAV.Language : Language,
Ball = Pokéball, Ball = Ball,
Country = SAV.Country, Country = SAV.Country,
Region = SAV.SubRegion, Region = SAV.SubRegion,
ConsoleRegion = SAV.ConsoleRegion, ConsoleRegion = SAV.ConsoleRegion,

View file

@ -166,7 +166,7 @@ namespace PKHeX
public override int PKRS_Strain { get { return Data[0xCA] & 0xF; } set { Data[0xCA] = (byte)(value & 0xF); } } public override int PKRS_Strain { get { return Data[0xCA] & 0xF; } set { Data[0xCA] = (byte)(value & 0xF); } }
public override bool IsEgg { get { return Data[0xCB] == 1; } set { Data[0xCB] = (byte)(value ? 1 : 0); } } public override bool IsEgg { get { return Data[0xCB] == 1; } set { Data[0xCB] = (byte)(value ? 1 : 0); } }
public int AbilityNumber { get { return Data[0xCC]; } set { Data[0xCC] = (byte)(value & 1); } } public override int AbilityNumber { get { return Data[0xCC]; } set { Data[0xCC] = (byte)(value & 1); } }
public override bool Valid { get { return Data[0xCD] == 0; } set { if (value) Data[0xCD] = 0; } } public override bool Valid { get { return Data[0xCD] == 0; } set { if (value) Data[0xCD] = 0; } }
// 0xCE unknown // 0xCE unknown
public override byte MarkByte { get { return Data[0xCF]; } protected set { Data[0xCF] = value; } } public override byte MarkByte { get { return Data[0xCF]; } protected set { Data[0xCF] = value; } }

View file

@ -118,7 +118,7 @@ namespace PKHeX
public override int IV_SPA { get { return (int)(IV32 >> 20) & 0x1F; } set { IV32 = (uint)((IV32 & ~(0x1F << 20)) | (uint)((value > 31 ? 31 : value) << 20)); } } public override int IV_SPA { get { return (int)(IV32 >> 20) & 0x1F; } set { IV32 = (uint)((IV32 & ~(0x1F << 20)) | (uint)((value > 31 ? 31 : value) << 20)); } }
public override int IV_SPD { get { return (int)(IV32 >> 25) & 0x1F; } set { IV32 = (uint)((IV32 & ~(0x1F << 25)) | (uint)((value > 31 ? 31 : value) << 25)); } } public override int IV_SPD { get { return (int)(IV32 >> 25) & 0x1F; } set { IV32 = (uint)((IV32 & ~(0x1F << 25)) | (uint)((value > 31 ? 31 : value) << 25)); } }
public override bool IsEgg { get { return ((IV32 >> 30) & 1) == 1; } set { IV32 = (uint)((IV32 & ~0x40000000) | (uint)(value ? 0x40000000 : 0)); } } public override bool IsEgg { get { return ((IV32 >> 30) & 1) == 1; } set { IV32 = (uint)((IV32 & ~0x40000000) | (uint)(value ? 0x40000000 : 0)); } }
public int AbilityNumber { get { return (int)((IV32 >> 31) & 1); } set { IV32 = (IV32 & 0x7FFFFFFF) | (value == 1 ? 0x80000000 : 0); } } public override int AbilityNumber { get { return (int)((IV32 >> 31) & 1); } set { IV32 = (IV32 & 0x7FFFFFFF) | (value == 1 ? 0x80000000 : 0); } }
private uint RIB0 { get { return BitConverter.ToUInt32(Data, 0x4C); } set { BitConverter.GetBytes(value).CopyTo(Data, 0x4C); } } private uint RIB0 { get { return BitConverter.ToUInt32(Data, 0x4C); } set { BitConverter.GetBytes(value).CopyTo(Data, 0x4C); } }
public int RibbonCountG3Cool { get { return (int)(RIB0 >> 00) & 7; } set { RIB0 = (uint)((RIB0 & ~(7 << 00)) | (uint)(value & 7) << 00); } } public int RibbonCountG3Cool { get { return (int)(RIB0 >> 00) & 7; } set { RIB0 = (uint)((RIB0 & ~(7 << 00)) | (uint)(value & 7) << 00); } }

View file

@ -67,7 +67,7 @@ namespace PKHeX
set { BitConverter.GetBytes(value).CopyTo(Data, 0x10); } set { BitConverter.GetBytes(value).CopyTo(Data, 0x10); }
} }
public override int Ability { get { return Data[0x14]; } set { Data[0x14] = (byte)value; } } public override int Ability { get { return Data[0x14]; } set { Data[0x14] = (byte)value; } }
public int AbilityNumber { get { return Data[0x15]; } set { Data[0x15] = (byte)value; } } public override int AbilityNumber { get { return Data[0x15]; } set { Data[0x15] = (byte)value; } }
public int TrainingBagHits { get { return Data[0x16]; } set { Data[0x16] = (byte)value; } } public int TrainingBagHits { get { return Data[0x16]; } set { Data[0x16] = (byte)value; } }
public int TrainingBag { get { return Data[0x17]; } set { Data[0x17] = (byte)value; } } public int TrainingBag { get { return Data[0x17]; } set { Data[0x17] = (byte)value; } }
public override uint PID public override uint PID
@ -274,8 +274,8 @@ namespace PKHeX
get { return BitConverter.ToUInt16(Data, 0x70); } get { return BitConverter.ToUInt16(Data, 0x70); }
set { BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x70); } set { BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x70); }
} }
public bool SecretSuperTrainingUnlocked { get { return (Data[0x72] & 1) == 1; } set { Data[0x72] = (byte)((Data[0x72] & ~1) | (value ? 1 : 0)); } } public override bool SecretSuperTrainingUnlocked { get { return (Data[0x72] & 1) == 1; } set { Data[0x72] = (byte)((Data[0x72] & ~1) | (value ? 1 : 0)); } }
public bool SecretSuperTrainingComplete { get { return (Data[0x72] & 2) == 2; } set { Data[0x72] = (byte)((Data[0x72] & ~2) | (value ? 2 : 0)); } } public override bool SecretSuperTrainingComplete { get { return (Data[0x72] & 2) == 2; } set { Data[0x72] = (byte)((Data[0x72] & ~2) | (value ? 2 : 0)); } }
public byte _0x73 { get { return Data[0x73]; } set { Data[0x73] = value; } } public byte _0x73 { get { return Data[0x73]; } set { Data[0x73] = value; } }
private uint IV32 { get { return BitConverter.ToUInt32(Data, 0x74); } set { BitConverter.GetBytes(value).CopyTo(Data, 0x74); } } private uint IV32 { get { return BitConverter.ToUInt32(Data, 0x74); } set { BitConverter.GetBytes(value).CopyTo(Data, 0x74); } }
public override int IV_HP { get { return (int)(IV32 >> 00) & 0x1F; } set { IV32 = (uint)((IV32 & ~(0x1F << 00)) | (uint)((value > 31 ? 31 : value) << 00)); } } public override int IV_HP { get { return (int)(IV32 >> 00) & 0x1F; } set { IV32 = (uint)((IV32 & ~(0x1F << 00)) | (uint)((value > 31 ? 31 : value) << 00)); } }
@ -381,9 +381,9 @@ namespace PKHeX
public override int OT_Gender { get { return Data[0xDD] >> 7; } set { Data[0xDD] = (byte)((Data[0xDD] & ~0x80) | (value << 7)); } } public override int OT_Gender { get { return Data[0xDD] >> 7; } set { Data[0xDD] = (byte)((Data[0xDD] & ~0x80) | (value << 7)); } }
public override int EncounterType { get { return Data[0xDE]; } set { Data[0xDE] = (byte)value; } } public override int EncounterType { get { return Data[0xDE]; } set { Data[0xDE] = (byte)value; } }
public override int Version { get { return Data[0xDF]; } set { Data[0xDF] = (byte)value; } } public override int Version { get { return Data[0xDF]; } set { Data[0xDF] = (byte)value; } }
public int Country { get { return Data[0xE0]; } set { Data[0xE0] = (byte)value; } } public override int Country { get { return Data[0xE0]; } set { Data[0xE0] = (byte)value; } }
public int Region { get { return Data[0xE1]; } set { Data[0xE1] = (byte)value; } } public override int Region { get { return Data[0xE1]; } set { Data[0xE1] = (byte)value; } }
public int ConsoleRegion { get { return Data[0xE2]; } set { Data[0xE2] = (byte)value; } } public override int ConsoleRegion { get { return Data[0xE2]; } set { Data[0xE2] = (byte)value; } }
public override int Language { get { return Data[0xE3]; } set { Data[0xE3] = (byte)value; } } public override int Language { get { return Data[0xE3]; } set { Data[0xE3] = (byte)value; } }
#endregion #endregion
#region Battle Stats #region Battle Stats
@ -410,7 +410,6 @@ namespace PKHeX
public override int PSV => (int)((PID >> 16 ^ PID & 0xFFFF) >> 4); public override int PSV => (int)((PID >> 16 ^ PID & 0xFFFF) >> 4);
public override int TSV => (TID ^ SID) >> 4; public override int TSV => (TID ^ SID) >> 4;
public bool IsUntraded => string.IsNullOrWhiteSpace(HT_Name);
public bool IsUntradedEvent6 => Geo1_Country == 0 && Geo1_Region == 0 && Met_Location / 10000 == 4 && Gen6; public bool IsUntradedEvent6 => Geo1_Country == 0 && Geo1_Region == 0 && Met_Location / 10000 == 4 && Gen6;
// Complex Generated Attributes // Complex Generated Attributes
@ -624,11 +623,11 @@ namespace PKHeX
} }
// Legality Properties // Legality Properties
public bool WasLink => Met_Location == 30011; public override bool WasLink => Met_Location == 30011;
public bool WasEgg => Legal.EggLocations.Contains(Egg_Location); public override bool WasEgg => Legal.EggLocations.Contains(Egg_Location);
public bool WasEvent => Met_Location > 40000 && Met_Location < 50000 || FatefulEncounter && Species != 386; public override bool WasEvent => Met_Location > 40000 && Met_Location < 50000 || FatefulEncounter && Species != 386;
public bool WasEventEgg => ((Egg_Location > 40000 && Egg_Location < 50000) || (FatefulEncounter && Egg_Location == 30002)) && Met_Level == 1; public override bool WasEventEgg => ((Egg_Location > 40000 && Egg_Location < 50000) || (FatefulEncounter && Egg_Location == 30002)) && Met_Level == 1;
public bool WasTradedEgg => Egg_Location == 30002; public override bool WasTradedEgg => Egg_Location == 30002;
public bool WasIngameTrade => Met_Location == 30001; public override bool WasIngameTrade => Met_Location == 30001;
} }
} }

View file

@ -67,7 +67,7 @@ namespace PKHeX
set { BitConverter.GetBytes(value).CopyTo(Data, 0x10); } set { BitConverter.GetBytes(value).CopyTo(Data, 0x10); }
} }
public override int Ability { get { return Data[0x14]; } set { Data[0x14] = (byte)value; } } public override int Ability { get { return Data[0x14]; } set { Data[0x14] = (byte)value; } }
public int AbilityNumber { get { return Data[0x15]; } set { Data[0x15] = (byte)value; } } public override int AbilityNumber { get { return Data[0x15]; } set { Data[0x15] = (byte)value; } }
public int TrainingBagHits { get { return Data[0x16]; } set { Data[0x16] = (byte)value; } } public int TrainingBagHits { get { return Data[0x16]; } set { Data[0x16] = (byte)value; } }
public int TrainingBag { get { return Data[0x17]; } set { Data[0x17] = (byte)value; } } public int TrainingBag { get { return Data[0x17]; } set { Data[0x17] = (byte)value; } }
public override uint PID public override uint PID
@ -282,8 +282,8 @@ namespace PKHeX
get { return BitConverter.ToUInt16(Data, 0x70); } get { return BitConverter.ToUInt16(Data, 0x70); }
set { BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x70); } set { BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x70); }
} }
public bool SecretSuperTrainingUnlocked { get { return (Data[0x72] & 1) == 1; } set { Data[0x72] = (byte)((Data[0x72] & ~1) | (value ? 1 : 0)); } } public override bool SecretSuperTrainingUnlocked { get { return (Data[0x72] & 1) == 1; } set { Data[0x72] = (byte)((Data[0x72] & ~1) | (value ? 1 : 0)); } }
public bool SecretSuperTrainingComplete { get { return (Data[0x72] & 2) == 2; } set { Data[0x72] = (byte)((Data[0x72] & ~2) | (value ? 2 : 0)); } } public override bool SecretSuperTrainingComplete { get { return (Data[0x72] & 2) == 2; } set { Data[0x72] = (byte)((Data[0x72] & ~2) | (value ? 2 : 0)); } }
public byte _0x73 { get { return Data[0x73]; } set { Data[0x73] = value; } } public byte _0x73 { get { return Data[0x73]; } set { Data[0x73] = value; } }
private uint IV32 { get { return BitConverter.ToUInt32(Data, 0x74); } set { BitConverter.GetBytes(value).CopyTo(Data, 0x74); } } private uint IV32 { get { return BitConverter.ToUInt32(Data, 0x74); } set { BitConverter.GetBytes(value).CopyTo(Data, 0x74); } }
public override int IV_HP { get { return (int)(IV32 >> 00) & 0x1F; } set { IV32 = (uint)((IV32 & ~(0x1F << 00)) | (uint)((value > 31 ? 31 : value) << 00)); } } public override int IV_HP { get { return (int)(IV32 >> 00) & 0x1F; } set { IV32 = (uint)((IV32 & ~(0x1F << 00)) | (uint)((value > 31 ? 31 : value) << 00)); } }
@ -389,9 +389,9 @@ namespace PKHeX
public override int OT_Gender { get { return Data[0xDD] >> 7; } set { Data[0xDD] = (byte)((Data[0xDD] & ~0x80) | (value << 7)); } } public override int OT_Gender { get { return Data[0xDD] >> 7; } set { Data[0xDD] = (byte)((Data[0xDD] & ~0x80) | (value << 7)); } }
public override int EncounterType { get { return Data[0xDE]; } set { Data[0xDE] = (byte)value; } } public override int EncounterType { get { return Data[0xDE]; } set { Data[0xDE] = (byte)value; } }
public override int Version { get { return Data[0xDF]; } set { Data[0xDF] = (byte)value; } } public override int Version { get { return Data[0xDF]; } set { Data[0xDF] = (byte)value; } }
public int Country { get { return Data[0xE0]; } set { Data[0xE0] = (byte)value; } } public override int Country { get { return Data[0xE0]; } set { Data[0xE0] = (byte)value; } }
public int Region { get { return Data[0xE1]; } set { Data[0xE1] = (byte)value; } } public override int Region { get { return Data[0xE1]; } set { Data[0xE1] = (byte)value; } }
public int ConsoleRegion { get { return Data[0xE2]; } set { Data[0xE2] = (byte)value; } } public override int ConsoleRegion { get { return Data[0xE2]; } set { Data[0xE2] = (byte)value; } }
public override int Language { get { return Data[0xE3]; } set { Data[0xE3] = (byte)value; } } public override int Language { get { return Data[0xE3]; } set { Data[0xE3] = (byte)value; } }
#endregion #endregion
#region Battle Stats #region Battle Stats
@ -418,7 +418,6 @@ namespace PKHeX
public override int PSV => (int)((PID >> 16 ^ PID & 0xFFFF) >> 4); public override int PSV => (int)((PID >> 16 ^ PID & 0xFFFF) >> 4);
public override int TSV => (TID ^ SID) >> 4; public override int TSV => (TID ^ SID) >> 4;
public bool IsUntraded => string.IsNullOrWhiteSpace(HT_Name);
public bool IsUntradedEvent6 => Geo1_Country == 0 && Geo1_Region == 0 && Met_Location / 10000 == 4 && Gen6; public bool IsUntradedEvent6 => Geo1_Country == 0 && Geo1_Region == 0 && Met_Location / 10000 == 4 && Gen6;
// Complex Generated Attributes // Complex Generated Attributes
@ -632,11 +631,11 @@ namespace PKHeX
} }
// Legality Properties // Legality Properties
public bool WasLink => Met_Location == 30011; public override bool WasLink => Met_Location == 30011;
public bool WasEgg => Legal.EggLocations.Contains(Egg_Location); public override bool WasEgg => Legal.EggLocations.Contains(Egg_Location);
public bool WasEvent => Met_Location > 40000 && Met_Location < 50000 || FatefulEncounter && Species != 386; public override bool WasEvent => Met_Location > 40000 && Met_Location < 50000 || FatefulEncounter && Species != 386;
public bool WasEventEgg => ((Egg_Location > 40000 && Egg_Location < 50000) || (FatefulEncounter && Egg_Location == 30002)) && Met_Level == 1; public override bool WasEventEgg => ((Egg_Location > 40000 && Egg_Location < 50000) || (FatefulEncounter && Egg_Location == 30002)) && Met_Level == 1;
public bool WasTradedEgg => Egg_Location == 30002; public override bool WasTradedEgg => Egg_Location == 30002;
public bool WasIngameTrade => Met_Location == 30001; public override bool WasIngameTrade => Met_Location == 30001;
} }
} }

View file

@ -152,6 +152,10 @@ namespace PKHeX
public virtual int Geo5_Country { get; set; } public virtual int Geo5_Country { get; set; }
public virtual byte Enjoyment { get; set; } public virtual byte Enjoyment { get; set; }
public virtual byte Fullness { get; set; } public virtual byte Fullness { get; set; }
public virtual int AbilityNumber { get; set; }
public virtual int Country { get; set; }
public virtual int Region { get; set; }
public virtual int ConsoleRegion { get; set; }
/// <summary> /// <summary>
/// The date the Pokémon was met. /// The date the Pokémon was met.
@ -377,6 +381,17 @@ namespace PKHeX
} }
} }
// Legality Extensions
public virtual bool WasLink => false;
public virtual bool WasEgg => Egg_Location > 0;
public virtual bool WasEvent => Met_Location > 40000 && Met_Location < 50000 || FatefulEncounter;
public virtual bool WasEventEgg => ((Egg_Location > 40000 && Egg_Location < 50000) || (FatefulEncounter && Egg_Location > 0)) && Met_Level == 1;
public virtual bool WasTradedEgg => Egg_Location == 30002;
public virtual bool WasIngameTrade => Met_Location == 30001;
public virtual bool IsUntraded => string.IsNullOrWhiteSpace(HT_Name);
public virtual bool SecretSuperTrainingUnlocked { get { return false; } set { } }
public virtual bool SecretSuperTrainingComplete { get { return false; } set { } }
// Methods // Methods
public abstract bool getGenderIsValid(); public abstract bool getGenderIsValid();
public void RefreshChecksum() { Checksum = CalculateChecksum(); } public void RefreshChecksum() { Checksum = CalculateChecksum(); }

View file

@ -66,7 +66,7 @@ namespace PKHeX
public bool UnusedFlag3 { get { return (XDPKMFLAGS & (1 << 3)) == 1 << 3; } set { XDPKMFLAGS = XDPKMFLAGS & ~(1 << 3) | (value ? 1 << 3 : 0); } } public bool UnusedFlag3 { get { return (XDPKMFLAGS & (1 << 3)) == 1 << 3; } set { XDPKMFLAGS = XDPKMFLAGS & ~(1 << 3) | (value ? 1 << 3 : 0); } }
public bool BlockTrades { get { return (XDPKMFLAGS & (1 << 4)) == 1 << 4; } set { XDPKMFLAGS = XDPKMFLAGS & ~(1 << 4) | (value ? 1 << 4 : 0); } } public bool BlockTrades { get { return (XDPKMFLAGS & (1 << 4)) == 1 << 4; } set { XDPKMFLAGS = XDPKMFLAGS & ~(1 << 4) | (value ? 1 << 4 : 0); } }
public override bool Valid { get { return (XDPKMFLAGS & (1 << 5)) == 0; } set { XDPKMFLAGS = XDPKMFLAGS & ~(1 << 5) | (value ? 0 : 1 << 5); } } // invalid flag public override bool Valid { get { return (XDPKMFLAGS & (1 << 5)) == 0; } set { XDPKMFLAGS = XDPKMFLAGS & ~(1 << 5) | (value ? 0 : 1 << 5); } } // invalid flag
public int AbilityNumber { get { return (XDPKMFLAGS >> 6) & 1; } set { XDPKMFLAGS = XDPKMFLAGS & ~(1 << 6) | (value << 6); } } public override int AbilityNumber { get { return (XDPKMFLAGS >> 6) & 1; } set { XDPKMFLAGS = XDPKMFLAGS & ~(1 << 6) | (value << 6); } }
public override bool IsEgg { get { return (XDPKMFLAGS & (1 << 7)) == 1 << 7; } set { XDPKMFLAGS = XDPKMFLAGS & ~(1 << 7) | (value ? 1 << 7 : 0); } } public override bool IsEgg { get { return (XDPKMFLAGS & (1 << 7)) == 1 << 7; } set { XDPKMFLAGS = XDPKMFLAGS & ~(1 << 7) | (value ? 1 << 7 : 0); } }
// 0x1E-0x1F Unknown // 0x1E-0x1F Unknown
public override uint EXP { get { return BigEndian.ToUInt32(Data, 0x20); } set { BigEndian.GetBytes(value).CopyTo(Data, 0x20); } } public override uint EXP { get { return BigEndian.ToUInt32(Data, 0x20); } set { BigEndian.GetBytes(value).CopyTo(Data, 0x20); } }

View file

@ -57,5 +57,9 @@ namespace PKHeX
// Convert.ChangeType is suitable for most things // Convert.ChangeType is suitable for most things
return Convert.ChangeType(value, type); return Convert.ChangeType(value, type);
} }
internal static bool? getBooleanState(object obj, string prop)
{
return obj.GetType().HasProperty(prop) ? GetValue(obj, prop) as bool? : null;
}
} }
} }