mirror of
https://github.com/kwsch/PKHeX
synced 2025-02-17 05:48:44 +00:00
Initial Gen1 legality checks (WIP)
Have only tested pk1 format so far; there's still a few cases that are unhandled (move discrepancies between games, trade gifts, event mew, tmhm). pls no report bugs unless you are very detailed (include WHY it is wrong).
This commit is contained in:
parent
22e49928c5
commit
578f05cd2e
9 changed files with 369 additions and 202 deletions
|
@ -2837,7 +2837,9 @@ namespace PKHeX.WinForms
|
||||||
LegalityAnalysis la = new LegalityAnalysis(pk);
|
LegalityAnalysis la = new LegalityAnalysis(pk);
|
||||||
if (!la.Parsed)
|
if (!la.Parsed)
|
||||||
{
|
{
|
||||||
WinFormsUtil.Alert($"Checking legality of PK{pk.Format} files that originated from Gen{pk.GenNumber} is not supported.");
|
WinFormsUtil.Alert(pk.Format < 3
|
||||||
|
? $"Checking legality of PK{pk.Format} files is not supported."
|
||||||
|
: $"Checking legality of PK{pk.Format} files that originated from Gen{pk.GenNumber} is not supported.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (tabs)
|
if (tabs)
|
||||||
|
@ -2846,48 +2848,43 @@ namespace PKHeX.WinForms
|
||||||
}
|
}
|
||||||
private void updateLegality(LegalityAnalysis la = null, bool skipMoveRepop = false)
|
private void updateLegality(LegalityAnalysis la = null, bool skipMoveRepop = false)
|
||||||
{
|
{
|
||||||
if (pkm.GenNumber >= 6)
|
if (!fieldsLoaded)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Legality = la ?? new LegalityAnalysis(pkm);
|
||||||
|
if (!Legality.Parsed || HaX)
|
||||||
{
|
{
|
||||||
if (!fieldsLoaded)
|
PB_Legal.Visible =
|
||||||
return;
|
PB_WarnMove1.Visible = PB_WarnMove2.Visible = PB_WarnMove3.Visible = PB_WarnMove4.Visible =
|
||||||
Legality = la ?? new LegalityAnalysis(pkm);
|
|
||||||
if (!Legality.Parsed || HaX)
|
|
||||||
{
|
|
||||||
PB_Legal.Visible = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
PB_Legal.Visible = true;
|
|
||||||
|
|
||||||
PB_Legal.Image = Legality.Valid ? Resources.valid : Resources.warn;
|
|
||||||
|
|
||||||
// Refresh Move Legality
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
movePB[i].Visible = !Legality.vMoves[i].Valid && !HaX;
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
relearnPB[i].Visible = !Legality.vRelearn[i].Valid && !HaX;
|
|
||||||
|
|
||||||
if (skipMoveRepop)
|
|
||||||
return;
|
|
||||||
// Resort moves
|
|
||||||
bool tmp = fieldsLoaded;
|
|
||||||
fieldsLoaded = false;
|
|
||||||
var cb = new[] { CB_Move1, CB_Move2, CB_Move3, CB_Move4 };
|
|
||||||
var moves = Legality.AllSuggestedMovesAndRelearn;
|
|
||||||
var moveList = GameInfo.MoveDataSource.OrderByDescending(m => moves.Contains(m.Value)).ToList();
|
|
||||||
foreach (ComboBox c in cb)
|
|
||||||
{
|
|
||||||
var index = WinFormsUtil.getIndex(c);
|
|
||||||
c.DataSource = new BindingSource(moveList, null);
|
|
||||||
c.SelectedValue = index;
|
|
||||||
}
|
|
||||||
fieldsLoaded |= tmp;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PB_Legal.Visible = PB_WarnMove1.Visible = PB_WarnMove2.Visible = PB_WarnMove3.Visible = PB_WarnMove4.Visible =
|
|
||||||
PB_WarnRelearn1.Visible = PB_WarnRelearn2.Visible = PB_WarnRelearn3.Visible = PB_WarnRelearn4.Visible = false;
|
PB_WarnRelearn1.Visible = PB_WarnRelearn2.Visible = PB_WarnRelearn3.Visible = PB_WarnRelearn4.Visible = false;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PB_Legal.Visible = true;
|
||||||
|
PB_Legal.Image = Legality.Valid ? Resources.valid : Resources.warn;
|
||||||
|
|
||||||
|
// Refresh Move Legality
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
movePB[i].Visible = !Legality.vMoves[i].Valid && !HaX;
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
relearnPB[i].Visible = !Legality.vRelearn[i].Valid && !HaX && pkm.Format >= 6;
|
||||||
|
|
||||||
|
if (skipMoveRepop)
|
||||||
|
return;
|
||||||
|
// Resort moves
|
||||||
|
bool tmp = fieldsLoaded;
|
||||||
|
fieldsLoaded = false;
|
||||||
|
var cb = new[] {CB_Move1, CB_Move2, CB_Move3, CB_Move4};
|
||||||
|
var moves = Legality.AllSuggestedMovesAndRelearn;
|
||||||
|
var moveList = GameInfo.MoveDataSource.OrderByDescending(m => moves.Contains(m.Value)).ToList();
|
||||||
|
foreach (ComboBox c in cb)
|
||||||
|
{
|
||||||
|
var index = WinFormsUtil.getIndex(c);
|
||||||
|
c.DataSource = new BindingSource(moveList, null);
|
||||||
|
c.SelectedValue = index;
|
||||||
|
}
|
||||||
|
fieldsLoaded |= tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateGender()
|
private void updateGender()
|
||||||
|
|
|
@ -39,11 +39,14 @@ namespace PKHeX.Core
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
switch (pk.Format) // prior to storing GameVersion
|
||||||
|
{
|
||||||
|
case 1: parsePK1(pk); break;
|
||||||
|
}
|
||||||
switch (pk.GenNumber)
|
switch (pk.GenNumber)
|
||||||
{
|
{
|
||||||
case 6: parsePK6(pk); break;
|
case 6: parsePK6(pk); break;
|
||||||
case 7: parsePK7(pk); break;
|
case 7: parsePK7(pk); break;
|
||||||
default: return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Valid = Parsed = Parse.Any();
|
Valid = Parsed = Parse.Any();
|
||||||
|
@ -59,6 +62,8 @@ namespace PKHeX.Core
|
||||||
if (pkm.FatefulEncounter && vRelearn.Any(chk => !chk.Valid) && EncounterMatch == null)
|
if (pkm.FatefulEncounter && vRelearn.Any(chk => !chk.Valid) && EncounterMatch == null)
|
||||||
AddLine(Severity.Indeterminate, "Fateful Encounter with no matching Encounter. Has the Mystery Gift data been contributed?", CheckIdentifier.Fateful);
|
AddLine(Severity.Indeterminate, "Fateful Encounter with no matching Encounter. Has the Mystery Gift data been contributed?", CheckIdentifier.Fateful);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
catch { Valid = false; }
|
catch { Valid = false; }
|
||||||
AllSuggestedMoves = !pkm.IsOriginValid() ? new int[4] : getSuggestedMoves(true, true, true);
|
AllSuggestedMoves = !pkm.IsOriginValid() ? new int[4] : getSuggestedMoves(true, true, true);
|
||||||
|
@ -74,6 +79,19 @@ namespace PKHeX.Core
|
||||||
{
|
{
|
||||||
Parse.Add(chk);
|
Parse.Add(chk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void parsePK1(PKM pk)
|
||||||
|
{
|
||||||
|
pkm = pk;
|
||||||
|
if (!pkm.IsOriginValid())
|
||||||
|
{ AddLine(Severity.Invalid, "Species does not exist in origin game.", CheckIdentifier.None); return; }
|
||||||
|
|
||||||
|
updateEncounterChain();
|
||||||
|
updateMoveLegality();
|
||||||
|
verifyNickname();
|
||||||
|
verifyDVs();
|
||||||
|
verifyG1OT();
|
||||||
|
}
|
||||||
private void parsePK6(PKM pk)
|
private void parsePK6(PKM pk)
|
||||||
{
|
{
|
||||||
pkm = pk;
|
pkm = pk;
|
||||||
|
@ -116,6 +134,7 @@ namespace PKHeX.Core
|
||||||
EncounterMatch = EventGiftMatch.First(); // temporarily set one so that Encounter can be verified
|
EncounterMatch = EventGiftMatch.First(); // temporarily set one so that Encounter can be verified
|
||||||
|
|
||||||
Encounter = verifyEncounter();
|
Encounter = verifyEncounter();
|
||||||
|
Parse.Add(Encounter);
|
||||||
EvoChain = Legal.getEvolutionChain(pkm, EncounterMatch);
|
EvoChain = Legal.getEvolutionChain(pkm, EncounterMatch);
|
||||||
}
|
}
|
||||||
private void updateChecks()
|
private void updateChecks()
|
||||||
|
@ -160,6 +179,8 @@ namespace PKHeX.Core
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
if (!vMoves[i].Valid)
|
if (!vMoves[i].Valid)
|
||||||
r += $"{vMoves[i].Judgement} Move {i + 1}: {vMoves[i].Comment}" + Environment.NewLine;
|
r += $"{vMoves[i].Judgement} Move {i + 1}: {vMoves[i].Comment}" + Environment.NewLine;
|
||||||
|
|
||||||
|
if (pkm.Format >= 6)
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
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;
|
||||||
|
@ -186,7 +207,9 @@ namespace PKHeX.Core
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
if (vMoves[i].Valid)
|
if (vMoves[i].Valid)
|
||||||
r += $"{vMoves[i].Judgement} Move {i + 1}: {vMoves[i].Comment}" + Environment.NewLine;
|
r += $"{vMoves[i].Judgement} Move {i + 1}: {vMoves[i].Comment}" + Environment.NewLine;
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
|
if (pkm.Format >= 6)
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
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;
|
||||||
|
|
||||||
|
@ -222,8 +245,10 @@ namespace PKHeX.Core
|
||||||
}
|
}
|
||||||
public int[] getSuggestedMoves(bool tm, bool tutor, bool reminder)
|
public int[] getSuggestedMoves(bool tm, bool tutor, bool reminder)
|
||||||
{
|
{
|
||||||
if (pkm == null || pkm.GenNumber < 6 || !pkm.IsOriginValid())
|
if (pkm == null || !pkm.IsOriginValid())
|
||||||
return null;
|
return null;
|
||||||
|
if (pkm.GenNumber < 6 && pkm.Format != 1)
|
||||||
|
return new int[4];
|
||||||
return Legal.getValidMoves(pkm, EvoChain, Tutor: tutor, Machine: tm, MoveReminder: reminder).Skip(1).ToArray(); // skip move 0
|
return Legal.getValidMoves(pkm, EvoChain, Tutor: tutor, Machine: tm, MoveReminder: reminder).Skip(1).ToArray(); // skip move 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -250,10 +250,13 @@ namespace PKHeX.Core
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AddLine(Severity.Valid, "Nickname does not match another species name.", CheckIdentifier.EVs);
|
AddLine(Severity.Valid, "Nickname does not match another species name.", CheckIdentifier.EVs);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else if (pkm.Format < 3)
|
||||||
// else
|
{
|
||||||
|
// pk1/pk2 IsNicknamed getter checks for match, logic should only reach here if matches.
|
||||||
|
AddLine(Severity.Valid, "Nickname matches species name.", CheckIdentifier.EVs);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// Can't have another language name if it hasn't evolved or wasn't a language-traded egg.
|
// Can't have another language name if it hasn't evolved or wasn't a language-traded egg.
|
||||||
bool match = (pkm.WasTradedEgg || Legal.getHasEvolved(pkm)) && PKX.SpeciesLang.Any(lang => lang[pkm.Species] == nickname)
|
bool match = (pkm.WasTradedEgg || Legal.getHasEvolved(pkm)) && PKX.SpeciesLang.Any(lang => lang[pkm.Species] == nickname)
|
||||||
|
@ -263,8 +266,6 @@ namespace PKHeX.Core
|
||||||
AddLine(Severity.Invalid, "Nickname does not match species name.", CheckIdentifier.EVs);
|
AddLine(Severity.Invalid, "Nickname does not match species name.", CheckIdentifier.EVs);
|
||||||
else
|
else
|
||||||
AddLine(Severity.Valid, "Nickname matches species name.", CheckIdentifier.EVs);
|
AddLine(Severity.Valid, "Nickname matches species name.", CheckIdentifier.EVs);
|
||||||
|
|
||||||
// return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void verifyEVs()
|
private void verifyEVs()
|
||||||
|
@ -328,6 +329,10 @@ namespace PKHeX.Core
|
||||||
else if (pkm.IVs[0] < 30 && pkm.IVs.All(iv => pkm.IVs[0] == iv))
|
else if (pkm.IVs[0] < 30 && pkm.IVs.All(iv => pkm.IVs[0] == iv))
|
||||||
AddLine(Severity.Fishy, "All IVs are equal.", CheckIdentifier.IVs);
|
AddLine(Severity.Fishy, "All IVs are equal.", CheckIdentifier.IVs);
|
||||||
}
|
}
|
||||||
|
private void verifyDVs()
|
||||||
|
{
|
||||||
|
// todo
|
||||||
|
}
|
||||||
private void verifyOT()
|
private void verifyOT()
|
||||||
{
|
{
|
||||||
if (EncounterType == typeof(EncounterTrade))
|
if (EncounterType == typeof(EncounterTrade))
|
||||||
|
@ -348,19 +353,21 @@ namespace PKHeX.Core
|
||||||
AddLine(Severity.Fishy, "SID is zero.", CheckIdentifier.Trainer);
|
AddLine(Severity.Fishy, "SID is zero.", CheckIdentifier.Trainer);
|
||||||
|
|
||||||
if (pkm.VC)
|
if (pkm.VC)
|
||||||
{
|
verifyG1OT();
|
||||||
string tr = pkm.OT_Name;
|
}
|
||||||
string pk = pkm.Nickname;
|
private void verifyG1OT()
|
||||||
var langset = PKX.SpeciesLang.FirstOrDefault(s => s.Contains(pk)) ?? PKX.SpeciesLang[2];
|
{
|
||||||
int lang = Array.IndexOf(PKX.SpeciesLang, langset);
|
string tr = pkm.OT_Name;
|
||||||
|
string pk = pkm.Nickname;
|
||||||
|
var langset = PKX.SpeciesLang.FirstOrDefault(s => s.Contains(pk)) ?? PKX.SpeciesLang[2];
|
||||||
|
int lang = Array.IndexOf(PKX.SpeciesLang, langset);
|
||||||
|
|
||||||
if (tr.Length > (lang == 2 ? 7 : 5))
|
if (tr.Length > (lang == 2 ? 7 : 5))
|
||||||
AddLine(Severity.Invalid, "OT Name too long.", CheckIdentifier.Trainer);
|
AddLine(Severity.Invalid, "OT Name too long.", CheckIdentifier.Trainer);
|
||||||
if (pkm.Species == 151)
|
if (pkm.Species == 151)
|
||||||
{
|
{
|
||||||
if (tr != "GF" && tr != "ゲーフリ") // if there are more events with special OTs, may be worth refactoring
|
if (tr != "GF" && tr != "ゲーフリ") // if there are more events with special OTs, may be worth refactoring
|
||||||
AddLine(Severity.Invalid, "Incorrect event OT Name.", CheckIdentifier.Trainer);
|
AddLine(Severity.Invalid, "Incorrect event OT Name.", CheckIdentifier.Trainer);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,151 +393,183 @@ namespace PKHeX.Core
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CheckResult verifyEncounterLink()
|
||||||
|
{
|
||||||
|
// Should NOT be Fateful, and should be in Database
|
||||||
|
EncounterLink enc = EncounterMatch as EncounterLink;
|
||||||
|
if (enc == null)
|
||||||
|
return new CheckResult(Severity.Invalid, "Invalid Link Gift: unable to find matching gift.", CheckIdentifier.Encounter);
|
||||||
|
|
||||||
|
if (pkm.XY && !enc.XY)
|
||||||
|
return new CheckResult(Severity.Invalid, "Invalid Link Gift: can't obtain in XY.", CheckIdentifier.Encounter);
|
||||||
|
if (pkm.AO && !enc.ORAS)
|
||||||
|
return new CheckResult(Severity.Invalid, "Invalid Link Gift: can't obtain in ORAS.", CheckIdentifier.Encounter);
|
||||||
|
if (pkm.SM && !enc.SM)
|
||||||
|
return new CheckResult(Severity.Invalid, "Invalid Link Gift: can't obtain in SM.", CheckIdentifier.Encounter);
|
||||||
|
|
||||||
|
if (enc.Shiny != null && (bool)enc.Shiny ^ pkm.IsShiny)
|
||||||
|
return new CheckResult(Severity.Invalid, "Shiny Link gift mismatch.", CheckIdentifier.Encounter);
|
||||||
|
|
||||||
|
return pkm.FatefulEncounter
|
||||||
|
? new CheckResult(Severity.Invalid, "Invalid Link Gift: should not be Fateful Encounter.", CheckIdentifier.Encounter)
|
||||||
|
: new CheckResult(Severity.Valid, "Valid Link gift.", CheckIdentifier.Encounter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckResult verifyEncounterEvent()
|
||||||
|
{
|
||||||
|
MysteryGift MatchedGift = EncounterMatch as MysteryGift;
|
||||||
|
if (MatchedGift != null)
|
||||||
|
return new CheckResult(Severity.Valid, $"Matches #{MatchedGift.CardID:0000} ({MatchedGift.CardTitle})", CheckIdentifier.Encounter);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
private CheckResult verifyEncounterEgg()
|
||||||
|
{
|
||||||
|
// Check Hatch Locations
|
||||||
|
if (pkm.Met_Level != 1)
|
||||||
|
return new CheckResult(Severity.Invalid, "Invalid met level, expected 1.", CheckIdentifier.Encounter);
|
||||||
|
// Check species
|
||||||
|
if (Legal.NoHatchFromEgg.Contains(pkm.Species))
|
||||||
|
return new CheckResult(Severity.Invalid, "Species cannot be hatched from an egg.", CheckIdentifier.Encounter);
|
||||||
|
if (pkm.IsEgg)
|
||||||
|
{
|
||||||
|
if (pkm.Egg_Location == 30002)
|
||||||
|
return new CheckResult(Severity.Invalid, "Egg location shouldn't be 'traded' for an un-hatched egg.", CheckIdentifier.Encounter);
|
||||||
|
|
||||||
|
if (pkm.Met_Location == 30002)
|
||||||
|
return new CheckResult(Severity.Valid, "Valid traded un-hatched egg.", CheckIdentifier.Encounter);
|
||||||
|
return pkm.Met_Location == 0
|
||||||
|
? new CheckResult(Severity.Valid, "Valid un-hatched egg.", CheckIdentifier.Encounter)
|
||||||
|
: new CheckResult(Severity.Invalid, "Invalid location for un-hatched egg (expected no met location).", CheckIdentifier.Encounter);
|
||||||
|
}
|
||||||
|
if (pkm.XY)
|
||||||
|
{
|
||||||
|
if (pkm.Egg_Location == 318)
|
||||||
|
return new CheckResult(Severity.Invalid, "Invalid X/Y egg location.", CheckIdentifier.Encounter);
|
||||||
|
return Legal.ValidMet_XY.Contains(pkm.Met_Location)
|
||||||
|
? new CheckResult(Severity.Valid, "Valid X/Y hatched egg.", CheckIdentifier.Encounter)
|
||||||
|
: new CheckResult(Severity.Invalid, "Invalid X/Y location for hatched egg.", CheckIdentifier.Encounter);
|
||||||
|
}
|
||||||
|
if (pkm.AO)
|
||||||
|
{
|
||||||
|
return Legal.ValidMet_AO.Contains(pkm.Met_Location)
|
||||||
|
? new CheckResult(Severity.Valid, "Valid OR/AS hatched egg.", CheckIdentifier.Encounter)
|
||||||
|
: new CheckResult(Severity.Invalid, "Invalid OR/AS location for hatched egg.", CheckIdentifier.Encounter);
|
||||||
|
}
|
||||||
|
if (pkm.SM)
|
||||||
|
{
|
||||||
|
return Legal.ValidMet_SM.Contains(pkm.Met_Location)
|
||||||
|
? new CheckResult(Severity.Valid, "Valid S/M hatched egg.", CheckIdentifier.Encounter)
|
||||||
|
: new CheckResult(Severity.Invalid, "Invalid S/M location for hatched egg.", CheckIdentifier.Encounter);
|
||||||
|
}
|
||||||
|
return new CheckResult(Severity.Invalid, "Invalid location for hatched egg.", CheckIdentifier.Encounter);
|
||||||
|
}
|
||||||
|
private CheckResult verifyEncounterSafari()
|
||||||
|
{
|
||||||
|
if (pkm.Species == 670 || pkm.Species == 671) // Floette
|
||||||
|
if (!new[] {0, 1, 3}.Contains(pkm.AltForm)) // 0/1/3 - RBY
|
||||||
|
return new CheckResult(Severity.Invalid, "Friend Safari: Not valid color.", CheckIdentifier.Encounter);
|
||||||
|
else if (pkm.Species == 710 || pkm.Species == 711) // Pumpkaboo
|
||||||
|
if (pkm.AltForm != 1) // Average
|
||||||
|
return new CheckResult(Severity.Invalid, "Friend Safari: Not average sized.", CheckIdentifier.Encounter);
|
||||||
|
else if (pkm.Species == 586) // Sawsbuck
|
||||||
|
if (pkm.AltForm != 0)
|
||||||
|
return new CheckResult(Severity.Invalid, "Friend Safari: Not Spring form.", CheckIdentifier.Encounter);
|
||||||
|
|
||||||
|
return new CheckResult(Severity.Valid, "Valid Friend Safari encounter.", CheckIdentifier.Encounter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckResult verifyEncounterWild()
|
||||||
|
{
|
||||||
|
EncounterSlot[] enc = (EncounterSlot[])EncounterMatch;
|
||||||
|
|
||||||
|
if (enc.Any(slot => slot.Normal))
|
||||||
|
return enc.All(slot => slot.Pressure)
|
||||||
|
? new CheckResult(Severity.Valid, "Valid encounter at location (Pressure/Hustle/Vital Spirit).", CheckIdentifier.Encounter)
|
||||||
|
: new CheckResult(Severity.Valid, "Valid encounter at location.", CheckIdentifier.Encounter);
|
||||||
|
|
||||||
|
// Decreased Level Encounters
|
||||||
|
if (enc.Any(slot => slot.WhiteFlute))
|
||||||
|
return enc.All(slot => slot.Pressure)
|
||||||
|
? new CheckResult(Severity.Valid, "Valid encounter at location (White Flute & Pressure/Hustle/Vital Spirit).", CheckIdentifier.Encounter)
|
||||||
|
: new CheckResult(Severity.Valid, "Valid encounter at location (White Flute).", CheckIdentifier.Encounter);
|
||||||
|
|
||||||
|
// Increased Level Encounters
|
||||||
|
if (enc.Any(slot => slot.BlackFlute))
|
||||||
|
return enc.All(slot => slot.Pressure)
|
||||||
|
? new CheckResult(Severity.Valid, "Valid encounter at location (Black Flute & Pressure/Hustle/Vital Spirit).", CheckIdentifier.Encounter)
|
||||||
|
: new CheckResult(Severity.Valid, "Valid encounter at location (Black Flute).", CheckIdentifier.Encounter);
|
||||||
|
|
||||||
|
if (enc.Any(slot => slot.Pressure))
|
||||||
|
return new CheckResult(Severity.Valid, "Valid encounter at location (Pressure/Hustle/Vital Spirit).", CheckIdentifier.Encounter);
|
||||||
|
|
||||||
|
return new CheckResult(Severity.Valid, "Valid encounter at location (DexNav).", CheckIdentifier.Encounter);
|
||||||
|
}
|
||||||
|
private CheckResult verifyEncounterStatic()
|
||||||
|
{
|
||||||
|
// Re-parse relearn moves
|
||||||
|
var s = (EncounterStatic)EncounterMatch;
|
||||||
|
if (s.EggLocation != 60002 || vRelearn.Any(rl => !rl.Valid))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
vRelearn[i] = pkm.RelearnMoves[i] != s.Relearn[i]
|
||||||
|
? new CheckResult(Severity.Invalid, "Static encounter relearn move mismatch.", CheckIdentifier.RelearnMove)
|
||||||
|
: new CheckResult(CheckIdentifier.RelearnMove);
|
||||||
|
return new CheckResult(Severity.Valid, "Valid gift/static encounter.", CheckIdentifier.Encounter);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
private CheckResult verifyEncounter()
|
private CheckResult verifyEncounter()
|
||||||
{
|
{
|
||||||
if (pkm.GenNumber < 6)
|
if (pkm.VC || pkm.Format < 3)
|
||||||
return new CheckResult(Severity.NotImplemented, "Not Implemented.", CheckIdentifier.Encounter);
|
|
||||||
|
|
||||||
if (pkm.VC)
|
|
||||||
{
|
{
|
||||||
int baseSpecies = Legal.getBaseSpecies(pkm);
|
int baseSpecies = Legal.getBaseSpecies(pkm);
|
||||||
if ((pkm.VC1 && baseSpecies > Legal.MaxSpeciesID_1) ||
|
bool g1 = pkm.VC1 || pkm.Format == 1;
|
||||||
(pkm.VC2 && baseSpecies > Legal.MaxSpeciesID_2))
|
|
||||||
|
if ((g1 && baseSpecies > Legal.MaxSpeciesID_1) || (baseSpecies > Legal.MaxSpeciesID_2))
|
||||||
return new CheckResult(Severity.Invalid, "VC: Unobtainable species.", CheckIdentifier.Encounter);
|
return new CheckResult(Severity.Invalid, "VC: Unobtainable species.", CheckIdentifier.Encounter);
|
||||||
|
|
||||||
return verifyVCEncounter(baseSpecies);
|
if (pkm.Format > 2) // transported to 7+
|
||||||
|
Parse.Add(verifyVCEncounter(baseSpecies));
|
||||||
}
|
}
|
||||||
|
else if (pkm.GenNumber == 4)
|
||||||
if (pkm.WasLink)
|
|
||||||
{
|
{
|
||||||
// Should NOT be Fateful, and should be in Database
|
|
||||||
EncounterLink enc = EncounterMatch as EncounterLink;
|
|
||||||
if (enc == null)
|
|
||||||
return new CheckResult(Severity.Invalid, "Invalid Link Gift: unable to find matching gift.", CheckIdentifier.Encounter);
|
|
||||||
|
|
||||||
if (pkm.XY && !enc.XY)
|
|
||||||
return new CheckResult(Severity.Invalid, "Invalid Link Gift: can't obtain in XY.", CheckIdentifier.Encounter);
|
|
||||||
if (pkm.AO && !enc.ORAS)
|
|
||||||
return new CheckResult(Severity.Invalid, "Invalid Link Gift: can't obtain in ORAS.", CheckIdentifier.Encounter);
|
|
||||||
if (pkm.SM && !enc.SM)
|
|
||||||
return new CheckResult(Severity.Invalid, "Invalid Link Gift: can't obtain in SM.", CheckIdentifier.Encounter);
|
|
||||||
|
|
||||||
if (enc.Shiny != null && (bool)enc.Shiny ^ pkm.IsShiny)
|
|
||||||
return new CheckResult(Severity.Invalid, "Shiny Link gift mismatch.", CheckIdentifier.Encounter);
|
|
||||||
|
|
||||||
return pkm.FatefulEncounter
|
}
|
||||||
? new CheckResult(Severity.Invalid, "Invalid Link Gift: should not be Fateful Encounter.", CheckIdentifier.Encounter)
|
else
|
||||||
: new CheckResult(Severity.Valid, "Valid Link gift.", CheckIdentifier.Encounter);
|
{
|
||||||
|
if (pkm.WasLink)
|
||||||
|
return verifyEncounterLink();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pkm.WasEvent || pkm.WasEventEgg)
|
if (pkm.WasEvent || pkm.WasEventEgg)
|
||||||
{
|
{
|
||||||
MysteryGift MatchedGift = EncounterMatch as MysteryGift;
|
var result = verifyEncounterEvent();
|
||||||
if (MatchedGift != null)
|
if (result != null)
|
||||||
return new CheckResult(Severity.Valid, $"Matches #{MatchedGift.CardID:0000} ({MatchedGift.CardTitle})", CheckIdentifier.Encounter);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
EncounterMatch = Legal.getValidStaticEncounter(pkm);
|
EncounterMatch = Legal.getValidStaticEncounter(pkm);
|
||||||
if (EncounterMatch != null)
|
if (EncounterMatch != null)
|
||||||
{
|
{
|
||||||
// Re-parse relearn moves
|
var result = verifyEncounterStatic();
|
||||||
var s = (EncounterStatic)EncounterMatch;
|
if (result != null)
|
||||||
if (s.EggLocation != 60002 || vRelearn.Any(rl => !rl.Valid))
|
return result;
|
||||||
{
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
vRelearn[i] = pkm.RelearnMoves[i] != s.Relearn[i]
|
|
||||||
? new CheckResult(Severity.Invalid, "Static encounter relearn move mismatch.", CheckIdentifier.RelearnMove)
|
|
||||||
: new CheckResult(CheckIdentifier.RelearnMove);
|
|
||||||
return new CheckResult(Severity.Valid, "Valid gift/static encounter.", CheckIdentifier.Encounter);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EncounterMatch = null; // Reset object
|
// Reset Encounter Object, test for remaining encounters
|
||||||
|
EncounterMatch = null;
|
||||||
if (pkm.WasEgg)
|
if (pkm.WasEgg)
|
||||||
{
|
return verifyEncounterEgg();
|
||||||
// Check Hatch Locations
|
|
||||||
if (pkm.Met_Level != 1)
|
|
||||||
return new CheckResult(Severity.Invalid, "Invalid met level, expected 1.", CheckIdentifier.Encounter);
|
|
||||||
// Check species
|
|
||||||
if (Legal.NoHatchFromEgg.Contains(pkm.Species))
|
|
||||||
return new CheckResult(Severity.Invalid, "Species cannot be hatched from an egg.", CheckIdentifier.Encounter);
|
|
||||||
if (pkm.IsEgg)
|
|
||||||
{
|
|
||||||
if (pkm.Egg_Location == 30002)
|
|
||||||
return new CheckResult(Severity.Invalid, "Egg location shouldn't be 'traded' for an un-hatched egg.", CheckIdentifier.Encounter);
|
|
||||||
|
|
||||||
if (pkm.Met_Location == 30002)
|
|
||||||
return new CheckResult(Severity.Valid, "Valid traded un-hatched egg.", CheckIdentifier.Encounter);
|
|
||||||
return pkm.Met_Location == 0
|
|
||||||
? new CheckResult(Severity.Valid, "Valid un-hatched egg.", CheckIdentifier.Encounter)
|
|
||||||
: new CheckResult(Severity.Invalid, "Invalid location for un-hatched egg (expected no met location).", CheckIdentifier.Encounter);
|
|
||||||
}
|
|
||||||
if (pkm.XY)
|
|
||||||
{
|
|
||||||
if (pkm.Egg_Location == 318)
|
|
||||||
return new CheckResult(Severity.Invalid, "Invalid X/Y egg location.", CheckIdentifier.Encounter);
|
|
||||||
return Legal.ValidMet_XY.Contains(pkm.Met_Location)
|
|
||||||
? new CheckResult(Severity.Valid, "Valid X/Y hatched egg.", CheckIdentifier.Encounter)
|
|
||||||
: new CheckResult(Severity.Invalid, "Invalid X/Y location for hatched egg.", CheckIdentifier.Encounter);
|
|
||||||
}
|
|
||||||
if (pkm.AO)
|
|
||||||
{
|
|
||||||
return Legal.ValidMet_AO.Contains(pkm.Met_Location)
|
|
||||||
? new CheckResult(Severity.Valid, "Valid OR/AS hatched egg.", CheckIdentifier.Encounter)
|
|
||||||
: new CheckResult(Severity.Invalid, "Invalid OR/AS location for hatched egg.", CheckIdentifier.Encounter);
|
|
||||||
}
|
|
||||||
if (pkm.SM)
|
|
||||||
{
|
|
||||||
return Legal.ValidMet_SM.Contains(pkm.Met_Location)
|
|
||||||
? new CheckResult(Severity.Valid, "Valid S/M hatched egg.", CheckIdentifier.Encounter)
|
|
||||||
: new CheckResult(Severity.Invalid, "Invalid S/M location for hatched egg.", CheckIdentifier.Encounter);
|
|
||||||
}
|
|
||||||
return new CheckResult(Severity.Invalid, "Invalid location for hatched egg.", CheckIdentifier.Encounter);
|
|
||||||
}
|
|
||||||
|
|
||||||
EncounterMatch = Legal.getValidFriendSafari(pkm);
|
EncounterMatch = Legal.getValidFriendSafari(pkm);
|
||||||
if (EncounterMatch != null)
|
if (EncounterMatch != null)
|
||||||
{
|
return verifyEncounterSafari();
|
||||||
if (pkm.Species == 670 || pkm.Species == 671) // Floette
|
|
||||||
if (!new[] {0, 1, 3}.Contains(pkm.AltForm)) // 0/1/3 - RBY
|
|
||||||
return new CheckResult(Severity.Invalid, "Friend Safari: Not valid color.", CheckIdentifier.Encounter);
|
|
||||||
else if (pkm.Species == 710 || pkm.Species == 711) // Pumpkaboo
|
|
||||||
if (pkm.AltForm != 1) // Average
|
|
||||||
return new CheckResult(Severity.Invalid, "Friend Safari: Not average sized.", CheckIdentifier.Encounter);
|
|
||||||
else if (pkm.Species == 586) // Sawsbuck
|
|
||||||
if (pkm.AltForm != 0)
|
|
||||||
return new CheckResult(Severity.Invalid, "Friend Safari: Not Spring form.", CheckIdentifier.Encounter);
|
|
||||||
|
|
||||||
return new CheckResult(Severity.Valid, "Valid Friend Safari encounter.", CheckIdentifier.Encounter);
|
|
||||||
}
|
|
||||||
|
|
||||||
EncounterMatch = Legal.getValidWildEncounters(pkm);
|
EncounterMatch = Legal.getValidWildEncounters(pkm);
|
||||||
if (EncounterMatch != null)
|
if (EncounterMatch != null)
|
||||||
{
|
return verifyEncounterWild();
|
||||||
EncounterSlot[] enc = (EncounterSlot[])EncounterMatch;
|
|
||||||
|
|
||||||
if (enc.Any(slot => slot.Normal))
|
|
||||||
return enc.All(slot => slot.Pressure)
|
|
||||||
? new CheckResult(Severity.Valid, "Valid encounter at location (Pressure/Hustle/Vital Spirit).", CheckIdentifier.Encounter)
|
|
||||||
: new CheckResult(Severity.Valid, "Valid encounter at location.", CheckIdentifier.Encounter);
|
|
||||||
|
|
||||||
// Decreased Level Encounters
|
|
||||||
if (enc.Any(slot => slot.WhiteFlute))
|
|
||||||
return enc.All(slot => slot.Pressure)
|
|
||||||
? new CheckResult(Severity.Valid, "Valid encounter at location (White Flute & Pressure/Hustle/Vital Spirit).", CheckIdentifier.Encounter)
|
|
||||||
: new CheckResult(Severity.Valid, "Valid encounter at location (White Flute).", CheckIdentifier.Encounter);
|
|
||||||
|
|
||||||
// Increased Level Encounters
|
|
||||||
if (enc.Any(slot => slot.BlackFlute))
|
|
||||||
return enc.All(slot => slot.Pressure)
|
|
||||||
? new CheckResult(Severity.Valid, "Valid encounter at location (Black Flute & Pressure/Hustle/Vital Spirit).", CheckIdentifier.Encounter)
|
|
||||||
: new CheckResult(Severity.Valid, "Valid encounter at location (Black Flute).", CheckIdentifier.Encounter);
|
|
||||||
|
|
||||||
if (enc.Any(slot => slot.Pressure))
|
|
||||||
return new CheckResult(Severity.Valid, "Valid encounter at location (Pressure/Hustle/Vital Spirit).", CheckIdentifier.Encounter);
|
|
||||||
|
|
||||||
return new CheckResult(Severity.Valid, "Valid encounter at location (DexNav).", CheckIdentifier.Encounter);
|
|
||||||
}
|
|
||||||
EncounterMatch = Legal.getValidIngameTrade(pkm);
|
EncounterMatch = Legal.getValidIngameTrade(pkm);
|
||||||
if (EncounterMatch != null)
|
if (EncounterMatch != null)
|
||||||
return new CheckResult(Severity.Valid, "Valid ingame trade.", CheckIdentifier.Encounter);
|
return new CheckResult(Severity.Valid, "Valid ingame trade.", CheckIdentifier.Encounter);
|
||||||
|
@ -1777,9 +1816,7 @@ namespace PKHeX.Core
|
||||||
CheckResult[] res = new CheckResult[4];
|
CheckResult[] res = new CheckResult[4];
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
res[i] = new CheckResult(CheckIdentifier.Move);
|
res[i] = new CheckResult(CheckIdentifier.Move);
|
||||||
if (pkm.GenNumber < 6 || pkm.VC1)
|
|
||||||
return res;
|
|
||||||
|
|
||||||
var validMoves = Legal.getValidMoves(pkm, EvoChain).ToArray();
|
var validMoves = Legal.getValidMoves(pkm, EvoChain).ToArray();
|
||||||
if (pkm.Species == 235) // Smeargle
|
if (pkm.Species == 235) // Smeargle
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace PKHeX.Core
|
||||||
|
|
||||||
// Gen 1
|
// Gen 1
|
||||||
private static readonly Learnset[] LevelUpRB = Learnset1.getArray(Resources.lvlmove_rby);
|
private static readonly Learnset[] LevelUpRB = Learnset1.getArray(Resources.lvlmove_rby);
|
||||||
|
private static readonly Learnset[] LevelUpY = Learnset1.getArray(Resources.lvlmove_rby);
|
||||||
private static readonly EvolutionTree Evolves1;
|
private static readonly EvolutionTree Evolves1;
|
||||||
private static readonly EncounterArea[] SlotsRBY;
|
private static readonly EncounterArea[] SlotsRBY;
|
||||||
private static readonly EncounterStatic[] StaticRBY;
|
private static readonly EncounterStatic[] StaticRBY;
|
||||||
|
@ -282,12 +283,15 @@ namespace PKHeX.Core
|
||||||
continue;
|
continue;
|
||||||
if (e.EggLocation != pkm.Egg_Location)
|
if (e.EggLocation != pkm.Egg_Location)
|
||||||
continue;
|
continue;
|
||||||
if (pkm.HasOriginalMetLocation && e.Location != 0 && e.Location != pkm.Met_Location)
|
if (pkm.HasOriginalMetLocation)
|
||||||
continue;
|
{
|
||||||
|
if (e.Location != 0 && e.Location != pkm.Met_Location)
|
||||||
|
continue;
|
||||||
|
if (e.Level != pkm.Met_Level)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (e.Gender != -1 && e.Gender != pkm.Gender)
|
if (e.Gender != -1 && e.Gender != pkm.Gender)
|
||||||
continue;
|
continue;
|
||||||
if (e.Level != pkm.Met_Level)
|
|
||||||
continue;
|
|
||||||
if (e.Form != pkm.AltForm && !FormChange.Contains(pkm.Species) && !e.SkipFormCheck)
|
if (e.Form != pkm.AltForm && !FormChange.Contains(pkm.Species) && !e.SkipFormCheck)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -783,7 +787,7 @@ namespace PKHeX.Core
|
||||||
}
|
}
|
||||||
if (t is int)
|
if (t is int)
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
return t.GetType().Name;
|
return t?.GetType().Name ?? "Unknown";
|
||||||
}
|
}
|
||||||
private static IEnumerable<EncounterArea> getDexNavAreas(PKM pkm)
|
private static IEnumerable<EncounterArea> getDexNavAreas(PKM pkm)
|
||||||
{
|
{
|
||||||
|
@ -802,7 +806,8 @@ namespace PKHeX.Core
|
||||||
List<int> moves = new List<int>();
|
List<int> moves = new List<int>();
|
||||||
if (pkm.InhabitedGeneration(1))
|
if (pkm.InhabitedGeneration(1))
|
||||||
{
|
{
|
||||||
moves.AddRange(LevelUpRB[species].getMoves(lvl));
|
moves.AddRange(((PersonalInfoG1)PersonalTable.RBY[species]).Moves);
|
||||||
|
moves.AddRange(LevelUpY[species].getMoves(lvl));
|
||||||
}
|
}
|
||||||
if (pkm.InhabitedGeneration(6))
|
if (pkm.InhabitedGeneration(6))
|
||||||
{
|
{
|
||||||
|
@ -822,6 +827,7 @@ namespace PKHeX.Core
|
||||||
{
|
{
|
||||||
switch ((GameVersion)pkm.Version)
|
switch ((GameVersion)pkm.Version)
|
||||||
{
|
{
|
||||||
|
case GameVersion.RBY:
|
||||||
case GameVersion.RD: case GameVersion.BU:
|
case GameVersion.RD: case GameVersion.BU:
|
||||||
case GameVersion.GN: case GameVersion.YW:
|
case GameVersion.GN: case GameVersion.YW:
|
||||||
return getSlots(pkm, SlotsRBY, lvl);
|
return getSlots(pkm, SlotsRBY, lvl);
|
||||||
|
@ -846,6 +852,7 @@ namespace PKHeX.Core
|
||||||
{
|
{
|
||||||
switch ((GameVersion)pkm.Version)
|
switch ((GameVersion)pkm.Version)
|
||||||
{
|
{
|
||||||
|
case GameVersion.RBY:
|
||||||
case GameVersion.RD: case GameVersion.BU:
|
case GameVersion.RD: case GameVersion.BU:
|
||||||
case GameVersion.GN: case GameVersion.YW:
|
case GameVersion.GN: case GameVersion.YW:
|
||||||
return getStatic(pkm, StaticRBY, lvl);
|
return getStatic(pkm, StaticRBY, lvl);
|
||||||
|
@ -884,18 +891,31 @@ namespace PKHeX.Core
|
||||||
|
|
||||||
// Get Valid levels
|
// Get Valid levels
|
||||||
IEnumerable<DexLevel> vs = getValidPreEvolutions(pkm);
|
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) || ignoreLevel);
|
bool ignoreSlotLevel = ignoreLevel;
|
||||||
|
IEnumerable<EncounterSlot> slots = loc.Slots.Where(slot => vs.Any(evo => evo.Species == slot.Species && (ignoreSlotLevel || evo.Level >= slot.LevelMin - df)));
|
||||||
|
|
||||||
|
if (pkm.Format < 3 || pkm.VC)
|
||||||
|
return slots; // no met level or special encounter considerations
|
||||||
|
|
||||||
// Filter for Met Level
|
// Filter for Met Level
|
||||||
int lvl = pkm.Met_Level;
|
int lvl = pkm.Met_Level;
|
||||||
var encounterSlots = slots.Where(slot => slot.LevelMin - df <= lvl && lvl <= slot.LevelMax + (slot.AllowDexNav ? dn : df) || ignoreLevel).ToList();
|
int gen = pkm.GenNumber;
|
||||||
|
bool ignoreMetLevel = ignoreLevel || gen <= 4 && pkm.Format != gen;
|
||||||
|
var encounterSlots = slots.Where(slot => ignoreMetLevel || 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 = pkm.AltForm };
|
slotMax = new EncounterSlot(slotMax) { Pressure = true, Form = pkm.AltForm };
|
||||||
|
|
||||||
|
if (gen < 4)
|
||||||
|
{
|
||||||
|
if (slotMax != null)
|
||||||
|
slotdata.Add(slotMax);
|
||||||
|
return slotdata;
|
||||||
|
}
|
||||||
if (!DexNav)
|
if (!DexNav)
|
||||||
{
|
{
|
||||||
// Filter for Form Specific
|
// Filter for Form Specific
|
||||||
|
@ -1005,7 +1025,11 @@ namespace PKHeX.Core
|
||||||
private static IEnumerable<int> getMoves(PKM pkm, int species, int lvl, int form, bool moveTutor, GameVersion Version, bool LVL, bool specialTutors, bool Machine, bool MoveReminder)
|
private static IEnumerable<int> getMoves(PKM pkm, int species, int lvl, int form, bool moveTutor, GameVersion Version, bool LVL, bool specialTutors, bool Machine, bool MoveReminder)
|
||||||
{
|
{
|
||||||
List<int> r = new List<int> { 0 };
|
List<int> r = new List<int> { 0 };
|
||||||
for (int gen = pkm.GenNumber; gen <= pkm.Format; gen++)
|
int gen = pkm.GenNumber;
|
||||||
|
if (pkm.Format < 3)
|
||||||
|
gen = 1;
|
||||||
|
|
||||||
|
for (; gen <= pkm.Format; gen++)
|
||||||
r.AddRange(getMoves(pkm, species, lvl, form, moveTutor, Version, LVL, specialTutors, Machine, gen, MoveReminder));
|
r.AddRange(getMoves(pkm, species, lvl, form, moveTutor, Version, LVL, specialTutors, Machine, gen, MoveReminder));
|
||||||
return r.Distinct();
|
return r.Distinct();
|
||||||
}
|
}
|
||||||
|
@ -1016,6 +1040,17 @@ namespace PKHeX.Core
|
||||||
var ver = Version;
|
var ver = Version;
|
||||||
switch (Generation)
|
switch (Generation)
|
||||||
{
|
{
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
PersonalInfo pi = PersonalTable.RBY[species];
|
||||||
|
if (LVL)
|
||||||
|
{
|
||||||
|
r.AddRange(((PersonalInfoG1)PersonalTable.RBY[species]).Moves);
|
||||||
|
r.AddRange(LevelUpRB[species].getMoves(lvl));
|
||||||
|
}
|
||||||
|
if (Machine) r.AddRange(TMHM_RBY.Where((t, m) => pi.TMHM[m]));
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 6:
|
case 6:
|
||||||
switch (ver)
|
switch (ver)
|
||||||
{
|
{
|
||||||
|
|
|
@ -45,7 +45,67 @@ namespace PKHeX.Core
|
||||||
|
|
||||||
internal static readonly EncounterStatic[] Encounter_RBY =
|
internal static readonly EncounterStatic[] Encounter_RBY =
|
||||||
{
|
{
|
||||||
// todo
|
new EncounterStatic { Species = 001, Level = 05 }, // Bulbasaur
|
||||||
|
new EncounterStatic { Species = 004, Level = 05 }, // Charmander
|
||||||
|
new EncounterStatic { Species = 007, Level = 05 }, // Squirtle
|
||||||
|
new EncounterStatic { Species = 025, Level = 05 }, // Pikachu
|
||||||
|
|
||||||
|
// Red Game Corner
|
||||||
|
new EncounterStatic { Species = 063, Level = 09 }, // Abra
|
||||||
|
new EncounterStatic { Species = 025, Level = 08 }, // Clefairy
|
||||||
|
new EncounterStatic { Species = 025, Level = 17 }, // Nidorina
|
||||||
|
new EncounterStatic { Species = 147, Level = 18 }, // Dratini
|
||||||
|
new EncounterStatic { Species = 123, Level = 25 }, // Scyther
|
||||||
|
new EncounterStatic { Species = 137, Level = 26 }, // Porygon
|
||||||
|
|
||||||
|
// Blue(EN) / Green(JP) Game Corner
|
||||||
|
new EncounterStatic { Species = 063, Level = 06 }, // Abra
|
||||||
|
new EncounterStatic { Species = 035, Level = 12 }, // Clefairy
|
||||||
|
new EncounterStatic { Species = 030, Level = 17 }, // Nidorina
|
||||||
|
new EncounterStatic { Species = 127, Level = 20 }, // Pinsir
|
||||||
|
new EncounterStatic { Species = 147, Level = 24 }, // Dratini
|
||||||
|
new EncounterStatic { Species = 137, Level = 18 }, // Porygon
|
||||||
|
|
||||||
|
// Blue(JP) Game Corner
|
||||||
|
new EncounterStatic { Species = 063, Level = 08 }, // Abra
|
||||||
|
new EncounterStatic { Species = 025, Level = 12 }, // Pikachu
|
||||||
|
new EncounterStatic { Species = 116, Level = 18 }, // Horsea
|
||||||
|
new EncounterStatic { Species = 036, Level = 24 }, // Clefable
|
||||||
|
new EncounterStatic { Species = 148, Level = 30 }, // Dragonair
|
||||||
|
new EncounterStatic { Species = 137, Level = 22 }, // Porygon
|
||||||
|
|
||||||
|
// Yellow Game Corner
|
||||||
|
new EncounterStatic { Species = 063, Level = 15 }, // Abra
|
||||||
|
new EncounterStatic { Species = 025, Level = 18 }, // Vulpix
|
||||||
|
new EncounterStatic { Species = 025, Level = 22 }, // Wigglytuff
|
||||||
|
new EncounterStatic { Species = 123, Level = 30 }, // Scyther
|
||||||
|
new EncounterStatic { Species = 127, Level = 30 }, // Pinsir
|
||||||
|
new EncounterStatic { Species = 137, Level = 26 }, // Porygon
|
||||||
|
|
||||||
|
new EncounterStatic { Species = 129, Level = 05 }, // Magikarp
|
||||||
|
new EncounterStatic { Species = 143, Level = 30 }, // Snorlax
|
||||||
|
new EncounterStatic { Species = 106, Level = 30 }, // Hitmonlee
|
||||||
|
new EncounterStatic { Species = 107, Level = 30 }, // Hitmonchan
|
||||||
|
|
||||||
|
new EncounterStatic { Species = 131, Level = 15 }, // Lapras
|
||||||
|
new EncounterStatic { Species = 138, Level = 30 }, // Omanyte
|
||||||
|
new EncounterStatic { Species = 140, Level = 30 }, // Kabuto
|
||||||
|
new EncounterStatic { Species = 142, Level = 30 }, // Aerodactyl
|
||||||
|
|
||||||
|
|
||||||
|
new EncounterStatic { Species = 144, Level = 50 }, // Articuno
|
||||||
|
new EncounterStatic { Species = 145, Level = 50 }, // Zapdos
|
||||||
|
new EncounterStatic { Species = 146, Level = 50 }, // Moltres
|
||||||
|
|
||||||
|
new EncounterStatic { Species = 150, Level = 70 }, // Mewtwo
|
||||||
|
|
||||||
|
new EncounterStatic { Species = 133, Level = 25 }, // Eevee
|
||||||
|
|
||||||
|
// Yellow Only
|
||||||
|
new EncounterStatic { Species = 133, Level = 25 }, // Eevee (Celadon City)
|
||||||
|
new EncounterStatic { Species = 001, Level = 10 }, // Bulbasaur (Cerulean City)
|
||||||
|
new EncounterStatic { Species = 004, Level = 10 }, // Charmander (Route 24)
|
||||||
|
new EncounterStatic { Species = 007, Level = 10 }, // Squirtle (Vermillion City)
|
||||||
};
|
};
|
||||||
internal static readonly EncounterTrade[] TradeGift_RBY =
|
internal static readonly EncounterTrade[] TradeGift_RBY =
|
||||||
{
|
{
|
||||||
|
|
|
@ -259,7 +259,7 @@ namespace PKHeX.Core
|
||||||
public override int OT_Friendship { get { return 0; } set { } }
|
public override int OT_Friendship { get { return 0; } set { } }
|
||||||
public override int OT_Gender { get { return 0; } set { } }
|
public override int OT_Gender { get { return 0; } set { } }
|
||||||
public override int Ball { get { return 0; } set { } }
|
public override int Ball { get { return 0; } set { } }
|
||||||
public override int Version { get { return 0; } set { } }
|
public override int Version { get { return (int)GameVersion.RBY; } set { } }
|
||||||
public override int SID { get { return 0; } set { } }
|
public override int SID { get { return 0; } set { } }
|
||||||
public override int PKRS_Strain { get { return 0; } set { } }
|
public override int PKRS_Strain { get { return 0; } set { } }
|
||||||
public override int PKRS_Days { get { return 0; } set { } }
|
public override int PKRS_Days { get { return 0; } set { } }
|
||||||
|
|
|
@ -327,7 +327,7 @@ namespace PKHeX.Core
|
||||||
public override int Egg_Location { get { return 0; } set { } }
|
public override int Egg_Location { get { return 0; } set { } }
|
||||||
public override int OT_Friendship { get { return 0; } set { } }
|
public override int OT_Friendship { get { return 0; } set { } }
|
||||||
public override int Ball { get { return 0; } set { } }
|
public override int Ball { get { return 0; } set { } }
|
||||||
public override int Version { get { return 0; } set { } }
|
public override int Version { get { return (int)GameVersion.GSC; } set { } }
|
||||||
public override int SID { get { return 0; } set { } }
|
public override int SID { get { return 0; } set { } }
|
||||||
public override int CNT_Cool { get { return 0; } set { } }
|
public override int CNT_Cool { get { return 0; } set { } }
|
||||||
public override int CNT_Beauty { get { return 0; } set { } }
|
public override int CNT_Beauty { get { return 0; } set { } }
|
||||||
|
|
|
@ -275,7 +275,9 @@ namespace PKHeX.Core
|
||||||
public bool Gen5 => Version >= 20 && Version <= 23;
|
public bool Gen5 => Version >= 20 && Version <= 23;
|
||||||
public bool Gen4 => Version >= 7 && Version <= 12 && Version != 9;
|
public bool Gen4 => Version >= 7 && Version <= 12 && Version != 9;
|
||||||
public bool Gen3 => Version >= 1 && Version <= 5 || Version == 15;
|
public bool Gen3 => Version >= 1 && Version <= 5 || Version == 15;
|
||||||
public bool GenU => !(Gen7 || Gen6 || Gen5 || Gen4 || Gen3);
|
public bool Gen2 => Version == (int)GameVersion.GSC;
|
||||||
|
public bool Gen1 => Version == (int)GameVersion.RBY;
|
||||||
|
public bool GenU => !(Gen7 || Gen6 || Gen5 || Gen4 || Gen3 || Gen2 || Gen1);
|
||||||
public int GenNumber
|
public int GenNumber
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -286,6 +288,8 @@ namespace PKHeX.Core
|
||||||
if (Gen5) return 5;
|
if (Gen5) return 5;
|
||||||
if (Gen4) return 4;
|
if (Gen4) return 4;
|
||||||
if (Gen3) return 3;
|
if (Gen3) return 3;
|
||||||
|
if (Gen2) return Format; // 2
|
||||||
|
if (Gen1) return Format; // 1
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -405,14 +409,17 @@ namespace PKHeX.Core
|
||||||
public virtual bool WasEventEgg => ((Egg_Location > 40000 && Egg_Location < 50000) || (FatefulEncounter && Egg_Location > 0)) && Met_Level == 1;
|
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 WasTradedEgg => Egg_Location == 30002;
|
||||||
public virtual bool WasIngameTrade => Met_Location == 30001;
|
public virtual bool WasIngameTrade => Met_Location == 30001;
|
||||||
public virtual bool IsUntraded => string.IsNullOrWhiteSpace(HT_Name) && GenNumber == Format;
|
public virtual bool IsUntraded => Format >= 6 && string.IsNullOrWhiteSpace(HT_Name) && GenNumber == Format;
|
||||||
public virtual bool IsNative => GenNumber == Format;
|
public virtual bool IsNative => GenNumber == Format;
|
||||||
public virtual bool IsOriginValid()
|
public virtual bool IsOriginValid()
|
||||||
{
|
{
|
||||||
switch (GenNumber)
|
switch (Format)
|
||||||
{
|
{
|
||||||
case 1: return Species <= Legal.MaxSpeciesID_1;
|
case 1: return Species <= Legal.MaxSpeciesID_1;
|
||||||
case 2: return Species <= Legal.MaxSpeciesID_2;
|
case 2: return Species <= Legal.MaxSpeciesID_2;
|
||||||
|
}
|
||||||
|
switch (GenNumber)
|
||||||
|
{
|
||||||
case 3: return Species <= Legal.MaxSpeciesID_3;
|
case 3: return Species <= Legal.MaxSpeciesID_3;
|
||||||
case 4: return Species <= Legal.MaxSpeciesID_4;
|
case 4: return Species <= Legal.MaxSpeciesID_4;
|
||||||
case 5: return Species <= Legal.MaxSpeciesID_5;
|
case 5: return Species <= Legal.MaxSpeciesID_5;
|
||||||
|
@ -482,7 +489,7 @@ namespace PKHeX.Core
|
||||||
/// Checks if the PKM has its original met location.
|
/// Checks if the PKM has its original met location.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Returns false if the Met Location has been overwritten via generational transfer.</returns>
|
/// <returns>Returns false if the Met Location has been overwritten via generational transfer.</returns>
|
||||||
public bool HasOriginalMetLocation => !(GenNumber <= 4 && Format > 4 || VC);
|
public bool HasOriginalMetLocation => !(Format < 3 || VC || GenNumber <= 4 && Format != GenNumber);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Checks if the current <see cref="Gender"/> is valid.
|
/// Checks if the current <see cref="Gender"/> is valid.
|
||||||
|
|
|
@ -40,11 +40,11 @@ namespace PKHeX.Core
|
||||||
}
|
}
|
||||||
public override int CatchRate { get { return Data[0x08]; } set { Data[0x08] = (byte)value; } }
|
public override int CatchRate { get { return Data[0x08]; } set { Data[0x08] = (byte)value; } }
|
||||||
public override int BaseEXP { get { return Data[0x09]; } set { Data[0x09] = (byte)value; } }
|
public override int BaseEXP { get { return Data[0x09]; } set { Data[0x09] = (byte)value; } }
|
||||||
public int Move1 { get { return Data[0x0A]; } set { Data[0x0A] = (byte)value; } }
|
public int Move1 { get { return Data[0x0F]; } set { Data[0x0F] = (byte)value; } }
|
||||||
public int Move2 { get { return Data[0x0B]; } set { Data[0x0B] = (byte)value; } }
|
public int Move2 { get { return Data[0x10]; } set { Data[0x10] = (byte)value; } }
|
||||||
public int Move3 { get { return Data[0x0C]; } set { Data[0x0C] = (byte)value; } }
|
public int Move3 { get { return Data[0x12]; } set { Data[0x12] = (byte)value; } }
|
||||||
public int Move4 { get { return Data[0x0D]; } set { Data[0x0D] = (byte)value; } }
|
public int Move4 { get { return Data[0x13]; } set { Data[0x13] = (byte)value; } }
|
||||||
public override int EXPGrowth { get { return Data[0x13]; } set { Data[0x13] = (byte)value; } }
|
public override int EXPGrowth { get { return Data[0x14]; } set { Data[0x14] = (byte)value; } }
|
||||||
|
|
||||||
// EV Yields are just aliases for base stats in Gen I
|
// EV Yields are just aliases for base stats in Gen I
|
||||||
public override int EV_HP { get { return HP; } set { } }
|
public override int EV_HP { get { return HP; } set { } }
|
||||||
|
@ -64,5 +64,11 @@ namespace PKHeX.Core
|
||||||
public override int BaseFriendship { get { return 0; } set { } }
|
public override int BaseFriendship { get { return 0; } set { } }
|
||||||
public override int EscapeRate { get { return 0; } set { } }
|
public override int EscapeRate { get { return 0; } set { } }
|
||||||
public override int Color { get { return 0; } set { } }
|
public override int Color { get { return 0; } set { } }
|
||||||
|
|
||||||
|
public int[] Moves
|
||||||
|
{
|
||||||
|
get { return new[] { Move1, Move2, Move3, Move4 }; }
|
||||||
|
set { if (value?.Length != 4) return; Move1 = value[0]; Move2 = value[1]; Move3 = value[2]; Move4 = value[3]; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue