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,78 +6,116 @@ namespace PKHeX
{
public partial class LegalityAnalysis
{
private readonly PK6 pk6;
private object EncounterMatch;
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 };
private PKM pkm;
private readonly List<CheckResult> Parse = new List<CheckResult>();
public bool Valid = true;
public bool SecondaryChecked;
public int[] RelearnBase;
public LegalityCheck[] vMoves = new LegalityCheck[4];
public LegalityCheck[] vRelearn = new LegalityCheck[4];
private object EncounterMatch;
private Type EncounterType;
private List<MysteryGift> EventGiftMatch;
private CheckResult Encounter, History;
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 VerboseReport => getVerboseLegalityReport();
public bool Native => pkm.GenNumber == pkm.Format;
public LegalityAnalysis(PKM pk)
{
if (!(pk is PK6))
return;
pk6 = (PK6) pk;
try
{
updateRelearnLegality();
updateMoveLegality();
updateChecks();
getLegalityReport();
switch (pk.Format)
{
case 6: parsePK6(pk); break;
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; }
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(); }
catch { for (int i = 0; i < 4; i++) vRelearn[i] = new LegalityCheck(Severity.Invalid, "Internal error."); }
SecondaryChecked = false;
catch { for (int i = 0; i < 4; i++) vRelearn[i] = new CheckResult(Severity.Invalid, "Internal error.", CheckIdentifier.RelearnMove); }
// SecondaryChecked = false;
}
public void updateMoveLegality()
private void updateMoveLegality()
{
try { vMoves = verifyMoves(); }
catch { for (int i = 0; i < 4; i++) vMoves[i] = new LegalityCheck(Severity.Invalid, "Internal error."); }
SecondaryChecked = false;
catch { for (int i = 0; i < 4; i++) vMoves[i] = new CheckResult(Severity.Invalid, "Internal error.", CheckIdentifier.Move); }
// SecondaryChecked = false;
}
private void updateChecks()
{
Encounter = verifyEncounter();
EncounterType = EncounterMatch?.GetType();
ECPID = verifyECPID();
Nickname = verifyNickname();
IDs = verifyID();
IVs = verifyIVs();
EVs = verifyEVs();
Level = verifyLevel();
Ribbons = verifyRibbons();
Ability = verifyAbility();
Ball = verifyBall();
History = verifyHistory();
OTMemory = verifyOTMemory();
HTMemory = verifyHTMemory();
Region = verifyRegion();
Form = verifyForm();
Misc = verifyMisc();
Gender = verifyGender();
SecondaryChecked = true;
verifyECPID();
verifyNickname();
verifyID();
verifyIVs();
verifyEVs();
verifyLevel();
verifyRibbons();
verifyAbility();
verifyBall();
verifyOTMemory();
verifyHTMemory();
verifyRegion();
verifyForm();
verifyMisc();
verifyGender();
// SecondaryChecked = true;
}
private string getLegalityReport()
{
if (pk6 == null || !pk6.Gen6)
return "Analysis only available for Pokémon that originate from X/Y & OR/AS.";
if (!Parsed)
return "Analysis not available for this Pokémon.";
var chks = Checks;
string r = "";
for (int i = 0; i < 4; i++)
if (!vMoves[i].Valid)
@ -86,19 +124,18 @@ namespace PKHeX
if (!vRelearn[i].Valid)
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!";
Valid = false;
// 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();
}
private string getVerboseLegalityReport()
{
string r = getLegalityReport() + Environment.NewLine;
if (pk6 == null)
if (pkm == null)
return r;
r += "===" + Environment.NewLine + Environment.NewLine;
int rl = r.Length;
@ -112,9 +149,8 @@ namespace PKHeX
if (rl != r.Length) // move info added, break for next section
r += Environment.NewLine;
var chks = Checks;
r += chks.Where(chk => chk != null && chk.Valid && chk.Comment != "Valid").OrderBy(chk => chk.Judgement) // Fishy sorted to top
r += Parse.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}");
return r.TrimEnd();
}
@ -123,15 +159,17 @@ namespace PKHeX
{
if (RelearnBase == null)
return new int[4];
if (pkm.GenNumber < 6)
return new int[4];
if (!pk6.WasEgg)
if (!pkm.WasEgg)
return RelearnBase;
List<int> window = new List<int>(RelearnBase);
for (int i = 0; i < 4; i++)
if (!vMoves[i].Valid || vMoves[i].Flag)
window.Add(pk6.Moves[i]);
window.Add(pkm.Moves[i]);
if (window.Count < 4)
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 EncounterStatic[] getSpecial(GameVersion Game)
{
if (Game == GameVersion.X || Game == GameVersion.Y)
return Encounter_XY.Where(s => s.Version == GameVersion.Any || s.Version == Game).ToArray();
// else if (Game == GameVersion.AS || Game == GameVersion.OR)
return Encounter_AO.Where(s => s.Version == GameVersion.Any || s.Version == Game).ToArray();
EncounterStatic[] table = null;
switch (Game)
{
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)
{
@ -42,6 +55,7 @@ namespace PKHeX
static Legal() // Setup
{
#region Gen6: XY & ORAS
StaticX = getSpecial(GameVersion.X);
StaticY = getSpecial(GameVersion.Y);
StaticA = getSpecial(GameVersion.AS);
@ -92,28 +106,30 @@ namespace PKHeX
for (int i = 0; i < slotct; i++)
area.Slots[i].AllowDexNav = area.Slots[i].Type != SlotType.Rock_Smash;
}
#endregion
}
internal static IEnumerable<int> getValidMoves(PK6 pk6)
{ return getValidMoves(pk6, -1, LVL: true, Relearn: false, Tutor: true, Machine: true); }
internal static IEnumerable<int> getValidRelearn(PK6 pk6, int skipOption)
internal static IEnumerable<int> getValidMoves(PKM pkm)
{ return getValidMoves(pkm, -1, 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(pk6, skipOption);
r.AddRange(getLVLMoves(species, 1, pk6.AltForm));
r.AddRange(getEggMoves(species, pk6.Species == 678 ? pk6.AltForm : 0));
r.AddRange(getLVLMoves(species, 100, pk6.AltForm));
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));
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 (pk6.XY)
if (pkm.XY)
return LevelUpXY[species].getMoves(1);
// if (pk6.Version == 26 || pk6.Version == 27)
return LevelUpAO[species].getMoves(1);
if (pkm.AO)
return LevelUpAO[species].getMoves(1);
return null;
}
if (gameSource == 0) // XY
return LevelUpXY[species].getMoves(1);
@ -121,89 +137,89 @@ namespace PKHeX
return LevelUpAO[species].getMoves(1);
}
internal static IEnumerable<WC6> getValidWC6s(PK6 pk6)
internal static IEnumerable<MysteryGift> getValidWC6s(PKM pkm)
{
var vs = getValidPreEvolutions(pk6).ToArray();
List<WC6> validWC6 = new List<WC6>();
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 (pk6.Egg_Location == 0) // Not Egg
if (pkm.Egg_Location == 0) // Not Egg
{
if (wc.CardID != pk6.SID) continue;
if (wc.TID != pk6.TID) continue;
if (wc.OT != pk6.OT_Name) continue;
if (wc.OTGender != pk6.OT_Gender) continue;
if (wc.PIDType == 0 && pk6.PID != wc.PID) continue;
if (wc.PIDType == 2 && !pk6.IsShiny) continue;
if (wc.PIDType == 3 && pk6.IsShiny) continue;
if (wc.OriginGame != 0 && wc.OriginGame != pk6.Version) continue;
if (wc.EncryptionConstant != 0 && wc.EncryptionConstant != pk6.EncryptionConstant) continue;
if (wc.Language != 0 && wc.Language != pk6.Language) continue;
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 != pk6.AltForm && vs.All(dl => !FormChange.Contains(dl.Species))) continue;
if (wc.MetLocation != pk6.Met_Location) continue;
if (wc.EggLocation != pk6.Egg_Location) continue;
if (wc.Level != pk6.Met_Level) continue;
if (wc.Pokéball != pk6.Ball) continue;
if (wc.OTGender < 3 && wc.OTGender != pk6.OT_Gender) continue;
if (wc.Nature != 0xFF && wc.Nature != pk6.Nature) continue;
if (wc.Gender != 3 && wc.Gender != pk6.Gender) 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 > pk6.CNT_Cool) continue;
if (wc.CNT_Beauty > pk6.CNT_Beauty) continue;
if (wc.CNT_Cute > pk6.CNT_Cute) continue;
if (wc.CNT_Smart > pk6.CNT_Smart) continue;
if (wc.CNT_Tough > pk6.CNT_Tough) continue;
if (wc.CNT_Sheen > pk6.CNT_Sheen) 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(pk6.RelearnMoves)) continue; // Defer to relearn legality
// if (wc.OT.Length > 0 && pk6.CurrentHandler != 1) continue; // Defer to ownership legality
// if (wc.OT.Length > 0 && pk6.OT_Friendship != PKX.getBaseFriendship(pk6.Species)) continue; // Friendship
// if (wc.Level > pk6.CurrentLevel) continue; // Defer to level legality
// 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 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>();
foreach (var area in getEncounterAreas(pk6))
s.AddRange(getValidEncounterSlots(pk6, area, DexNav: pk6.AO));
foreach (var area in getEncounterAreas(pkm))
s.AddRange(getValidEncounterSlots(pkm, area, DexNav: pkm.AO));
return s.Any() ? s.ToArray() : null;
}
internal static EncounterStatic getValidStaticEncounter(PK6 pk6)
internal static EncounterStatic getValidStaticEncounter(PKM pkm)
{
// Get possible encounters
IEnumerable<EncounterStatic> poss = getStaticEncounters(pk6);
// Back Check against pk6
IEnumerable<EncounterStatic> poss = getStaticEncounters(pkm);
// Back Check against pkm
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;
if (e.EggLocation != pk6.Egg_Location)
if (e.EggLocation != pkm.Egg_Location)
continue;
if (e.Location != 0 && e.Location != pk6.Met_Location)
if (e.Location != 0 && e.Location != pkm.Met_Location)
continue;
if (e.Gender != -1 && e.Gender != pk6.Gender)
if (e.Gender != -1 && e.Gender != pkm.Gender)
continue;
if (e.Level != pk6.Met_Level)
if (e.Level != pkm.Met_Level)
continue;
// Defer to EC/PID check
// if (e.Shiny != null && e.Shiny != pk6.IsShiny)
// if (e.Shiny != null && e.Shiny != pkm.IsShiny)
// continue;
// Defer ball check to later
// if (e.Gift && pk6.Ball != 4) // PokéBall
// if (e.Gift && pkm.Ball != 4) // PokéBall
// continue;
// Passes all checks, valid encounter
@ -211,119 +227,118 @@ namespace PKHeX
}
return null;
}
internal static EncounterTrade getValidIngameTrade(PK6 pk6)
internal static EncounterTrade getValidIngameTrade(PKM pkm)
{
if (!pk6.WasIngameTrade)
if (!pkm.WasIngameTrade)
return null;
int lang = pk6.Language;
int lang = pkm.Language;
if (lang == 0)
return null;
// Get valid pre-evolutions
IEnumerable<DexLevel> p = getValidPreEvolutions(pk6);
IEnumerable<DexLevel> p = getValidPreEvolutions(pkm);
EncounterTrade z = null;
if (pk6.XY)
if (pkm.XY)
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));
if (z == null)
return null;
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;
if (z.Shiny ^ pk6.IsShiny) // Are PIDs static?
if (z.Shiny ^ pkm.IsShiny) // Are PIDs static?
return null;
if (z.TID != pk6.TID)
if (z.TID != pkm.TID)
return null;
if (z.SID != pk6.SID)
if (z.SID != pkm.SID)
return null;
if (z.Location != pk6.Met_Location)
if (z.Location != pkm.Met_Location)
return null;
if (z.Level != pk6.Met_Level)
if (z.Level != pkm.Met_Level)
return null;
if (z.Nature != Nature.Random && (int)z.Nature != pk6.Nature)
if (z.Nature != Nature.Random && (int)z.Nature != pkm.Nature)
return null;
if (z.Gender != pk6.Gender)
if (z.Gender != pkm.Gender)
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 z;
}
internal static EncounterSlot[] getValidFriendSafari(PK6 pk6)
internal static EncounterSlot[] getValidFriendSafari(PKM pkm)
{
if (!pk6.XY)
if (!pkm.XY)
return null;
if (pk6.Met_Location != 148) // Friend Safari
if (pkm.Met_Location != 148) // Friend Safari
return null;
if (pk6.Met_Level != 30)
if (pkm.Met_Level != 30)
return null;
IEnumerable<DexLevel> vs = getValidPreEvolutions(pk6);
IEnumerable<DexLevel> vs = getValidPreEvolutions(pkm);
List<EncounterSlot> slots = new List<EncounterSlot>();
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,
LevelMin = 30,
LevelMax = 30,
Form = 0,
Type = SlotType.FriendSafari,
};
slots.Add(slot);
});
}
return slots.Any() ? slots.ToArray() : null;
}
internal static bool getDexNavValid(PK6 pk6)
internal static bool getDexNavValid(PKM pkm)
{
IEnumerable<EncounterArea> locs = getDexNavAreas(pk6);
return locs.Select(loc => getValidEncounterSlots(pk6, loc, DexNav: true)).Any(slots => slots.Any(slot => slot.AllowDexNav && slot.DexNav));
IEnumerable<EncounterArea> locs = getDexNavAreas(pkm);
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;
if (pk6.Egg_Location != 0)
if (pkm.Egg_Location != 0)
return false;
if (pk6.XY && pk6.Met_Location == 44)
return Fossils.Contains(getBaseSpecies(pk6));
if (pk6.AO && pk6.Met_Location == 190)
return Fossils.Contains(getBaseSpecies(pk6));
if (pkm.XY && pkm.Met_Location == 44)
return Fossils.Contains(getBaseSpecies(pkm));
if (pkm.AO && pkm.Met_Location == 190)
return Fossils.Contains(getBaseSpecies(pkm));
return false;
}
internal static bool getEvolutionValid(PK6 pk6)
internal static bool getEvolutionValid(PKM pkm)
{
var curr = getValidPreEvolutions(pk6);
var poss = getValidPreEvolutions(pk6, 100);
var curr = getValidPreEvolutions(pkm);
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();
}
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};
for (int i = 0; i < Evolves.Length; i++)
if (Evolves[i].Evos.Any(pk => pk.Species == species))
res.Add(i);
for (int i = -1; i < 2; i++)
res.Add(getBaseSpecies(pk6, i));
res.Add(getBaseSpecies(pkm, i));
return res.Distinct();
}
@ -363,45 +378,45 @@ namespace PKHeX
}
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 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;
if (pk6.Species == 242 && pk6.CurrentLevel < 3) // Never Cleffa
if (pkm.Species == 242 && pkm.CurrentLevel < 3) // Never Cleffa
return 113;
DexLevel[] evos = Evolves[pk6.Species].Evos;
DexLevel[] evos = Evolves[pkm.Species].Evos;
switch (skipOption)
{
case -1: return pk6.Species;
case 1: return evos.Length <= 1 ? pk6.Species : evos[evos.Length - 2].Species;
default: return evos.Length <= 0 ? pk6.Species : evos.Last().Species;
case -1: return pkm.Species;
case 1: return evos.Length <= 1 ? pkm.Species : evos[evos.Length - 2].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;
if (!alpha && pk6.Version != 27)
bool alpha = pkm.Version == 26;
if (!alpha && pkm.Version != 27)
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)
{
@ -409,41 +424,41 @@ namespace PKHeX
int ind_AO = PersonalTable.AO.getFormeIndex(species, formnum);
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
return getSlots(pk6, SlotsX);
return getSlots(pkm, SlotsX);
case 25: // Y
return getSlots(pk6, SlotsY);
return getSlots(pkm, SlotsY);
case 26: // AS
return getSlots(pk6, SlotsA);
return getSlots(pkm, SlotsA);
case 27: // OR
return getSlots(pk6, SlotsO);
return getSlots(pkm, SlotsO);
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
return getStatic(pk6, StaticX);
return getStatic(pkm, StaticX);
case 25: // Y
return getStatic(pk6, StaticY);
return getStatic(pkm, StaticY);
case 26: // AS
return getStatic(pk6, StaticA);
return getStatic(pkm, StaticA);
case 27: // OR
return getStatic(pk6, StaticO);
return getStatic(pkm, StaticO);
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 dexnavBoost = 30;
@ -452,36 +467,36 @@ namespace PKHeX
List<EncounterSlot> slotdata = new List<EncounterSlot>();
// Get Valid levels
IEnumerable<DexLevel> vs = getValidPreEvolutions(pk6);
IEnumerable<DexLevel> vs = getValidPreEvolutions(pkm);
// 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));
// 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();
// Pressure Slot
EncounterSlot slotMax = encounterSlots.OrderByDescending(slot => slot.LevelMax).FirstOrDefault();
if (slotMax != null)
slotMax = new EncounterSlot(slotMax) { Pressure = true, Form = pk6.AltForm };
slotMax = new EncounterSlot(slotMax) { Pressure = true, Form = pkm.AltForm };
if (!DexNav)
{
// Filter for Form Specific
slotdata.AddRange(WildForms.Contains(pk6.Species)
? encounterSlots.Where(slot => slot.Form == pk6.AltForm)
slotdata.AddRange(WildForms.Contains(pkm.Species)
? encounterSlots.Where(slot => slot.Form == pkm.AltForm)
: encounterSlots);
if (slotMax != null)
slotdata.Add(slotMax);
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)
eslots.Add(slotMax);
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 };
if (slot.LevelMin > lvl)
@ -494,9 +509,9 @@ namespace PKHeX
}
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>();
foreach (var loc in tables)
{
@ -508,21 +523,21 @@ namespace PKHeX
}
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)
lvl = pk6.CurrentLevel;
if (pk6.Species == 292 && pk6.Met_Level + 1 <= lvl && lvl >= 20)
lvl = pkm.CurrentLevel;
if (pkm.Species == 292 && pkm.Met_Level + 1 <= lvl && lvl >= 20)
return new List<DexLevel>
{
new DexLevel { Species = 292, Level = lvl },
new DexLevel { Species = 290, Level = lvl-1 }
};
var evos = Evolves[pk6.Species].Evos;
List<DexLevel> dl = new List<DexLevel> { new DexLevel { Species = pk6.Species, Level = lvl } };
var evos = Evolves[pkm.Species].Evos;
List<DexLevel> dl = new List<DexLevel> { new DexLevel { Species = pkm.Species, Level = lvl } };
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});
else break;
if (evo.Level > 2) // Level Up (from previous level)
@ -530,37 +545,37 @@ namespace PKHeX
}
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));
}
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 };
int species = pk6.Species;
int lvl = pk6.CurrentLevel;
bool ORASTutors = Version == -1 || pk6.AO || !pk6.IsUntraded;
int species = pkm.Species;
int lvl = pkm.CurrentLevel;
bool ORASTutors = Version == -1 || pkm.AO || !pkm.IsUntraded;
if (FormChangeMoves.Contains(species)) // Deoxys & Shaymin & Giratina (others don't have extra but whatever)
{
int formcount = PersonalTable.AO[species].FormeCount;
for (int i = 0; i < formcount; i++)
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();
}
r.AddRange(getMoves(species, lvl, pk6.AltForm, ORASTutors, Version, LVL, Tutor, Machine));
IEnumerable<DexLevel> vs = getValidPreEvolutions(pk6);
r.AddRange(getMoves(species, lvl, pkm.AltForm, ORASTutors, Version, LVL, Tutor, Machine));
IEnumerable<DexLevel> vs = getValidPreEvolutions(pkm);
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
r.Add(RotomMoves[pk6.AltForm]);
r.Add(RotomMoves[pkm.AltForm]);
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();
}
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 const int Struggle = 165;
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[] LightBall = {25, 26, 172};
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
566, 567, 696, 697, 698, 699 // Fossil Only obtain
};
internal static readonly int[] WurmpleFamily =
internal static readonly int[] WurmpleEvolutions =
{
266, 267, // Silcoon Beautifly
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
};
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.");
}
int wIndex = Array.IndexOf(Legal.WurmpleFamily, Util.getIndex(CB_Species));
int wIndex = Array.IndexOf(Legal.WurmpleEvolutions, Util.getIndex(CB_Species));
if (wIndex < 0)
{
TB_EC.Text = Util.rnd32().ToString("X8");
@ -2774,6 +2774,11 @@ namespace PKHeX
private void showLegality(PKM pk, bool tabs, bool verbose)
{
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)
updateLegality(la);
Util.Alert(verbose ? la.VerboseReport : la.Report);
@ -2782,11 +2787,15 @@ namespace PKHeX
{
if (!fieldsLoaded)
return;
if (!(pkm is PK6))
Legality = la ?? new LegalityAnalysis(pkm);
if (!Legality.Parsed || !Legality.Native || HaX)
{
PB_Legal.Visible = false;
return;
Legality = la ?? new LegalityAnalysis((PK6) pkm);
}
PB_Legal.Visible = true;
PB_Legal.Image = Legality.Valid ? Properties.Resources.valid : Properties.Resources.warn;
PB_Legal.Visible = pkm.Gen6 /*&& pkm is PK6*/ && !HaX;
// Refresh Move Legality
for (int i = 0; i < 4; i++)
@ -3378,12 +3387,7 @@ namespace PKHeX
if (pk.Species == 0 || !pk.ChecksumValid)
{ SystemSounds.Asterisk.Play(); return; }
if (typeof (PK6) != pk.GetType())
{
Util.Alert($"Checking legality of {pk.GetType().Name} files is not supported.");
return;
}
showLegality(pk as PK6, slot < 0, ModifierKeys == Keys.Control);
showLegality(pk, slot < 0, ModifierKeys == Keys.Control);
}
private void updateSaveSlot(object sender, EventArgs e)
{
@ -3715,7 +3719,7 @@ namespace PKHeX
}
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?",
$"Currently viewing daycare {SAV.DaycareIndex + 1}."))
// If ORAS, alter the daycare offset via toggle.

View file

@ -1,5 +1,4 @@
using System;
using System.Linq;
using System.Linq;
namespace PKHeX
{
@ -90,10 +89,15 @@ namespace PKHeX
// Search Properties
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 IsEgg { get { return false; } 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 Gen6 => Format == 6;
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 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 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); } }
@ -79,7 +79,7 @@ namespace PKHeX
get { return PKX.TrimFromFFFF(Encoding.Unicode.GetString(Data, 0x4A, 0x10)); }
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 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); } }
// Unused 0x5D 0x5E 0x5F
public override string CardTitle
@ -174,7 +174,7 @@ namespace PKHeX
AltForm = Form,
Version = OriginGame == 0 ? new[] {20, 21, 22, 23}[Util.rnd32() & 0x3] : OriginGame,
Language = Language == 0 ? SAV.Language : Language,
Ball = Pokéball,
Ball = Ball,
Move1 = Move1,
Move2 = Move2,
Move3 = Move3,

View file

@ -12,7 +12,17 @@ namespace PKHeX
{
internal const int Size = 0x358; // 856
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)
{
Data = (byte[])(data?.Clone() ?? new byte[Size]);
@ -25,6 +35,7 @@ namespace PKHeX
Array.Copy(Data, PGT.Size, Information, 0, Information.Length);
}
public readonly PGT Gift;
public override object Content => Gift.PK;
public readonly byte[] Information;
public override bool GiftUsed { get { return Gift.GiftUsed; } set { Gift.GiftUsed = value; } }
@ -65,6 +76,16 @@ namespace PKHeX
{
internal const int Size = 0x104; // 260
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
{
@ -86,6 +107,7 @@ namespace PKHeX
public override string CardTitle { get { return "Raw Gift (PGT)"; } set { } }
public override int CardID { get { return -1; } set { } }
public override bool GiftUsed { get { return false; } set { } }
public override object Content => PK;
public PGT(byte[] data = null)
{

View file

@ -107,7 +107,7 @@ namespace PKHeX
public uint EncryptionConstant {
get { return BitConverter.ToUInt32(Data, 0x70); }
set { BitConverter.GetBytes(value).CopyTo(Data, 0x70); } }
public int Pokéball {
public override int Ball {
get { return Data[0x76]; }
set { Data[0x76] = (byte)value; } }
public override int HeldItem {
@ -174,7 +174,7 @@ namespace PKHeX
public string OT {
get { return Util.TrimFromZero(Encoding.Unicode.GetString(Data, 0xB6, 0x1A)); }
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 uint PID {
get { return BitConverter.ToUInt32(Data, 0xD4); }
@ -223,7 +223,7 @@ namespace PKHeX
{
get { return new[] {Move1, Move2, Move3, Move4}; }
}
public int[] RelearnMoves
public override int[] RelearnMoves
{
get { return new[] { RelearnMove1, RelearnMove2, RelearnMove3, RelearnMove4 }; }
set
@ -254,7 +254,7 @@ namespace PKHeX
EncryptionConstant = EncryptionConstant == 0 ? Util.rnd32() : EncryptionConstant,
Version = OriginGame == 0 ? SAV.Game : OriginGame,
Language = Language == 0 ? SAV.Language : Language,
Ball = Pokéball,
Ball = Ball,
Country = SAV.Country,
Region = SAV.SubRegion,
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 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; } }
// 0xCE unknown
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_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 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); } }
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); }
}
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 TrainingBag { get { return Data[0x17]; } set { Data[0x17] = (byte)value; } }
public override uint PID
@ -274,8 +274,8 @@ namespace PKHeX
get { return BitConverter.ToUInt16(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 bool SecretSuperTrainingComplete { get { return (Data[0x72] & 2) == 2; } set { Data[0x72] = (byte)((Data[0x72] & ~2) | (value ? 2 : 0)); } }
public override bool SecretSuperTrainingUnlocked { get { return (Data[0x72] & 1) == 1; } set { Data[0x72] = (byte)((Data[0x72] & ~1) | (value ? 1 : 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; } }
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)); } }
@ -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 EncounterType { get { return Data[0xDE]; } set { Data[0xDE] = (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 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 Country { get { return Data[0xE0]; } set { Data[0xE0] = (byte)value; } }
public override int Region { get { return Data[0xE1]; } set { Data[0xE1] = (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; } }
#endregion
#region Battle Stats
@ -410,7 +410,6 @@ namespace PKHeX
public override int PSV => (int)((PID >> 16 ^ PID & 0xFFFF) >> 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;
// Complex Generated Attributes
@ -624,11 +623,11 @@ namespace PKHeX
}
// Legality Properties
public bool WasLink => Met_Location == 30011;
public bool WasEgg => Legal.EggLocations.Contains(Egg_Location);
public 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 bool WasTradedEgg => Egg_Location == 30002;
public bool WasIngameTrade => Met_Location == 30001;
public override bool WasLink => Met_Location == 30011;
public override bool WasEgg => Legal.EggLocations.Contains(Egg_Location);
public override bool WasEvent => Met_Location > 40000 && Met_Location < 50000 || FatefulEncounter && Species != 386;
public override bool WasEventEgg => ((Egg_Location > 40000 && Egg_Location < 50000) || (FatefulEncounter && Egg_Location == 30002)) && Met_Level == 1;
public override bool WasTradedEgg => Egg_Location == 30002;
public override bool WasIngameTrade => Met_Location == 30001;
}
}

View file

@ -67,7 +67,7 @@ namespace PKHeX
set { BitConverter.GetBytes(value).CopyTo(Data, 0x10); }
}
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 TrainingBag { get { return Data[0x17]; } set { Data[0x17] = (byte)value; } }
public override uint PID
@ -282,8 +282,8 @@ namespace PKHeX
get { return BitConverter.ToUInt16(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 bool SecretSuperTrainingComplete { get { return (Data[0x72] & 2) == 2; } set { Data[0x72] = (byte)((Data[0x72] & ~2) | (value ? 2 : 0)); } }
public override bool SecretSuperTrainingUnlocked { get { return (Data[0x72] & 1) == 1; } set { Data[0x72] = (byte)((Data[0x72] & ~1) | (value ? 1 : 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; } }
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)); } }
@ -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 EncounterType { get { return Data[0xDE]; } set { Data[0xDE] = (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 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 Country { get { return Data[0xE0]; } set { Data[0xE0] = (byte)value; } }
public override int Region { get { return Data[0xE1]; } set { Data[0xE1] = (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; } }
#endregion
#region Battle Stats
@ -418,7 +418,6 @@ namespace PKHeX
public override int PSV => (int)((PID >> 16 ^ PID & 0xFFFF) >> 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;
// Complex Generated Attributes
@ -632,11 +631,11 @@ namespace PKHeX
}
// Legality Properties
public bool WasLink => Met_Location == 30011;
public bool WasEgg => Legal.EggLocations.Contains(Egg_Location);
public 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 bool WasTradedEgg => Egg_Location == 30002;
public bool WasIngameTrade => Met_Location == 30001;
public override bool WasLink => Met_Location == 30011;
public override bool WasEgg => Legal.EggLocations.Contains(Egg_Location);
public override bool WasEvent => Met_Location > 40000 && Met_Location < 50000 || FatefulEncounter && Species != 386;
public override bool WasEventEgg => ((Egg_Location > 40000 && Egg_Location < 50000) || (FatefulEncounter && Egg_Location == 30002)) && Met_Level == 1;
public override bool WasTradedEgg => Egg_Location == 30002;
public override bool WasIngameTrade => Met_Location == 30001;
}
}

View file

@ -152,6 +152,10 @@ namespace PKHeX
public virtual int Geo5_Country { get; set; }
public virtual byte Enjoyment { 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>
/// 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
public abstract bool getGenderIsValid();
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 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 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); } }
// 0x1E-0x1F Unknown
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
return Convert.ChangeType(value, type);
}
internal static bool? getBooleanState(object obj, string prop)
{
return obj.GetType().HasProperty(prop) ? GetValue(obj, prop) as bool? : null;
}
}
}