2016-03-12 17:16:41 +00:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
2016-03-11 04:36:32 +00:00
namespace PKHeX
{
public enum Severity
{
Indeterminate = - 2 ,
Invalid = - 1 ,
Fishy = 0 ,
Valid = 1 ,
NotImplemented = 2 ,
}
2016-10-23 19:48:49 +00:00
public enum CheckIdentifier
{
Move ,
RelearnMove ,
Encounter ,
History ,
ECPID ,
Shiny ,
EC ,
PID ,
Gender ,
EVs ,
Language ,
Trainer ,
IVs ,
None ,
Level ,
Ball ,
Memory ,
Geography ,
Form ,
Egg ,
Misc ,
Fateful ,
Ribbon ,
Training ,
Ability
}
public class CheckResult
2016-03-11 04:36:32 +00:00
{
2016-03-12 03:43:40 +00:00
public Severity Judgement = Severity . Valid ;
2016-04-07 01:13:43 +00:00
public string Comment = "Valid" ;
2016-03-11 04:36:32 +00:00
public bool Valid = > Judgement > = Severity . Fishy ;
2016-03-25 07:10:11 +00:00
public bool Flag ;
2016-10-23 19:48:49 +00:00
public readonly CheckIdentifier Identifier ;
2016-03-11 04:36:32 +00:00
2016-10-23 19:48:49 +00:00
public CheckResult ( CheckIdentifier i ) { }
public CheckResult ( Severity s , string c , CheckIdentifier i )
2016-03-11 04:36:32 +00:00
{
Judgement = s ;
Comment = c ;
2016-10-23 19:48:49 +00:00
Identifier = i ;
2016-03-11 04:36:32 +00:00
}
2016-03-14 03:19:04 +00:00
}
public partial class LegalityAnalysis
{
2016-10-23 19:48:49 +00:00
private void verifyGender ( )
2016-07-04 01:36:04 +00:00
{
2016-10-29 06:41:22 +00:00
if ( pkm . PersonalInfo . Gender = = 255 & & pkm . Gender ! = 2 )
2016-10-23 19:48:49 +00:00
{
AddLine ( Severity . Invalid , "Genderless Pokémon should not have a gender." , CheckIdentifier . Gender ) ;
// return;
}
2016-07-04 01:36:04 +00:00
}
2016-10-23 19:48:49 +00:00
private void verifyECPID ( )
2016-03-11 04:36:32 +00:00
{
2016-10-23 19:48:49 +00:00
if ( pkm . EncryptionConstant = = 0 )
AddLine ( Severity . Fishy , "Encryption Constant is not set." , CheckIdentifier . EC ) ;
if ( pkm . PID = = 0 )
AddLine ( Severity . Fishy , "PID is not set." , CheckIdentifier . PID ) ;
2016-03-11 04:36:32 +00:00
2016-10-23 19:48:49 +00:00
if ( pkm . GenNumber > = 6 & & pkm . PID = = pkm . EncryptionConstant )
AddLine ( Severity . Fishy , "Encryption Constant matches PID." , CheckIdentifier . PID ) ;
2016-03-11 04:36:32 +00:00
2016-06-20 04:22:43 +00:00
if ( EncounterType = = typeof ( EncounterStatic ) )
{
var enc = ( EncounterStatic ) EncounterMatch ;
2016-10-23 19:48:49 +00:00
if ( enc . Shiny ! = null & & ( bool ) enc . Shiny ^ pkm . IsShiny )
{
AddLine ( Severity . Invalid , $"Encounter {(enc.Shiny == true ? " must be " : " cannot be ")} shiny." , CheckIdentifier . Shiny ) ;
return ;
}
2016-06-20 04:22:43 +00:00
}
2016-10-23 19:48:49 +00:00
int wIndex = Array . IndexOf ( Legal . WurmpleEvolutions , pkm . Species ) ;
if ( pkm . GenNumber > = 6 )
2016-04-08 00:56:39 +00:00
{
2016-04-21 07:28:40 +00:00
// Wurmple -> Silcoon/Cascoon
if ( wIndex > - 1 )
{
// Check if Wurmple was the origin (only Egg and Wild Encounter)
2016-10-23 19:48:49 +00:00
if ( pkm . WasEgg | | ( EncounterType = = typeof ( EncounterSlot [ ] ) & & ( EncounterMatch as EncounterSlot [ ] ) . All ( slot = > slot . Species = = 265 ) ) )
if ( ( pkm . EncryptionConstant > > 16 ) % 10 / 5 ! = wIndex / 2 )
{
AddLine ( Severity . Invalid , "Wurmple evolution Encryption Constant mismatch." , CheckIdentifier . EC ) ;
return ;
}
}
else if ( pkm . Species = = 265 )
{
AddLine ( Severity . Valid , "Wurmple Evolution: " + ( ( pkm . EncryptionConstant > > 16 ) % 10 / 5 = = 0 ? "Silcoon" : "Cascoon" ) , CheckIdentifier . EC ) ;
}
int xor = pkm . TSV ^ pkm . PSV ;
if ( xor < 16 & & xor > = 8 & & ( pkm . PID ^ 0x80000000 ) = = pkm . EncryptionConstant )
{
AddLine ( Severity . Fishy , "Encryption Constant matches shinyxored PID." , CheckIdentifier . EC ) ;
return ;
2016-04-21 07:28:40 +00:00
}
2016-04-08 00:56:39 +00:00
}
2016-03-11 04:36:32 +00:00
2016-10-23 19:48:49 +00:00
if ( pkm . Format < 6 )
return ;
if ( pkm . GenNumber > = 6 )
return ;
2016-03-11 04:36:32 +00:00
// When transferred to Generation 6, the Encryption Constant is copied from the PID.
// The PID is then checked to see if it becomes shiny with the new Shiny rules (>>4 instead of >>3)
// If the PID is nonshiny->shiny, the top bit is flipped.
// Check to see if the PID and EC are properly configured.
2016-10-23 19:48:49 +00:00
bool xorPID = ( ( pkm . TID ^ pkm . SID ^ ( int ) ( pkm . PID & 0xFFFF ) ^ ( int ) ( pkm . PID > > 16 ) ) & 0x7 ) = = 8 ;
2016-03-11 04:36:32 +00:00
bool valid = xorPID
2016-10-23 19:48:49 +00:00
? pkm . EncryptionConstant = = ( pkm . PID ^ 0x8000000 )
: pkm . EncryptionConstant = = pkm . PID ;
2016-03-11 04:36:32 +00:00
if ( ! valid )
2016-10-23 19:48:49 +00:00
{
AddLine ( Severity . Invalid ,
xorPID
? "PID should be equal to EC [with top bit flipped]!"
: "PID should be equal to EC!" , CheckIdentifier . ECPID ) ;
}
2016-03-11 04:36:32 +00:00
}
2016-10-23 19:48:49 +00:00
private void verifyNickname ( )
2016-03-11 04:36:32 +00:00
{
// If the Pokémon is not nicknamed, it should match one of the language strings.
2016-10-23 19:48:49 +00:00
if ( pkm . Nickname . Length = = 0 )
{
AddLine ( Severity . Invalid , "Nickname is empty." , CheckIdentifier . EVs ) ;
return ;
}
if ( pkm . Species > PKX . SpeciesLang [ 0 ] . Length )
{
AddLine ( Severity . Indeterminate , "Species index invalid for Nickname comparison." , CheckIdentifier . EVs ) ;
return ;
}
2016-03-20 01:06:02 +00:00
if ( ! Encounter . Valid )
2016-10-23 19:48:49 +00:00
return ;
if ( pkm . Format < = 6 & & pkm . Language > 8 )
{
AddLine ( Severity . Indeterminate , "Language ID > 8." , CheckIdentifier . Language ) ;
return ;
}
2016-11-09 16:23:47 +00:00
if ( pkm . Format < = 7 & & pkm . Language > 10 )
2016-10-23 19:48:49 +00:00
{
2016-11-09 16:23:47 +00:00
AddLine ( Severity . Indeterminate , "Language ID > 10." , CheckIdentifier . Language ) ;
2016-10-23 19:48:49 +00:00
return ;
}
2016-03-28 05:05:51 +00:00
if ( EncounterType = = typeof ( EncounterTrade ) )
2016-03-27 00:23:53 +00:00
{
string [ ] validOT = new string [ 0 ] ;
int index = - 1 ;
2016-10-23 19:48:49 +00:00
if ( pkm . XY )
2016-03-27 00:23:53 +00:00
{
2016-10-23 19:48:49 +00:00
validOT = Legal . TradeXY [ pkm . Language ] ;
2016-03-27 00:23:53 +00:00
index = Array . IndexOf ( Legal . TradeGift_XY , EncounterMatch ) ;
}
2016-10-23 19:48:49 +00:00
else if ( pkm . AO )
2016-03-27 00:23:53 +00:00
{
2016-10-23 19:48:49 +00:00
validOT = Legal . TradeAO [ pkm . Language ] ;
2016-03-27 00:23:53 +00:00
index = Array . IndexOf ( Legal . TradeGift_AO , EncounterMatch ) ;
}
2016-11-11 03:29:00 +00:00
else if ( pkm . SM )
{
// TODO
AddLine ( Severity . Valid , "Ingame Trade for Sun/Moon un-implemented." , CheckIdentifier . EVs ) ;
return ;
}
2016-10-23 19:48:49 +00:00
2016-03-27 00:23:53 +00:00
if ( validOT . Length = = 0 )
2016-10-23 19:48:49 +00:00
{
AddLine ( Severity . Indeterminate , "Ingame Trade invalid version?" , CheckIdentifier . Trainer ) ;
return ;
}
if ( index = = - 1 | | validOT . Length < index * 2 )
{
AddLine ( Severity . Indeterminate , "Ingame Trade invalid lookup?" , CheckIdentifier . Trainer ) ;
return ;
}
2016-03-27 00:23:53 +00:00
string nick = validOT [ index ] ;
string OT = validOT [ validOT . Length / 2 + index ] ;
2016-10-23 19:48:49 +00:00
if ( nick ! = pkm . Nickname )
AddLine ( Severity . Fishy , "Ingame Trade nickname has been altered." , CheckIdentifier . EVs ) ;
else if ( OT ! = pkm . OT_Name )
AddLine ( Severity . Invalid , "Ingame Trade OT has been altered." , CheckIdentifier . Trainer ) ;
else
AddLine ( Severity . Valid , "Ingame Trade OT/Nickname have not been altered." , CheckIdentifier . EVs ) ;
2016-03-27 00:23:53 +00:00
2016-10-23 19:48:49 +00:00
return ;
2016-03-27 00:23:53 +00:00
}
2016-03-20 01:06:02 +00:00
2016-10-23 19:48:49 +00:00
if ( pkm . IsEgg )
2016-03-16 04:15:40 +00:00
{
2016-11-11 03:29:00 +00:00
if ( ! pkm . IsNicknamed & & ( pkm . Format ! = 7 ) )
2016-10-23 19:48:49 +00:00
AddLine ( Severity . Invalid , "Eggs must be nicknamed." , CheckIdentifier . EVs ) ;
else if ( PKX . SpeciesLang [ pkm . Language ] [ 0 ] ! = pkm . Nickname )
AddLine ( Severity . Invalid , "Egg name does not match language Egg name." , CheckIdentifier . EVs ) ;
else
AddLine ( Severity . Valid , "Egg matches language Egg name." , CheckIdentifier . EVs ) ;
return ;
2016-03-16 04:15:40 +00:00
}
2016-10-23 19:48:49 +00:00
string nickname = pkm . Nickname . Replace ( "'" , "’ " ) ;
if ( pkm . IsNicknamed )
2016-03-11 04:36:32 +00:00
{
2016-03-20 01:06:02 +00:00
for ( int i = 0 ; i < PKX . SpeciesLang . Length ; i + + )
{
string [ ] lang = PKX . SpeciesLang [ i ] ;
int index = Array . IndexOf ( lang , nickname ) ;
if ( index < 0 )
continue ;
2016-10-23 19:48:49 +00:00
AddLine ( Severity . Fishy , index = = pkm . Species & & i ! = pkm . Language
? "Nickname matches another species name (+language)."
: "Nickname flagged, matches species name." , CheckIdentifier . EVs ) ;
return ;
2016-03-20 01:06:02 +00:00
}
2016-10-23 19:48:49 +00:00
AddLine ( Severity . Valid , "Nickname does not match another species name." , CheckIdentifier . EVs ) ;
return ;
2016-03-16 01:56:18 +00:00
}
2016-10-23 19:48:49 +00:00
2016-03-16 01:56:18 +00:00
// else
{
2016-07-11 05:22:55 +00:00
// Can't have another language name if it hasn't evolved or wasn't a language-traded egg.
2016-10-23 19:48:49 +00:00
bool match = ( pkm . WasTradedEgg | | Legal . getHasEvolved ( pkm ) ) & & PKX . SpeciesLang . Any ( lang = > lang [ pkm . Species ] = = nickname )
| | PKX . SpeciesLang [ pkm . Language ] [ pkm . Species ] = = nickname ;
if ( ! match )
AddLine ( Severity . Invalid , "Nickname does not match species name." , CheckIdentifier . EVs ) ;
else
AddLine ( Severity . Valid , "Nickname matches species name." , CheckIdentifier . EVs ) ;
// return;
2016-03-11 04:36:32 +00:00
}
}
2016-10-23 19:48:49 +00:00
private void verifyEVs ( )
2016-03-11 04:36:32 +00:00
{
2016-10-23 19:48:49 +00:00
var evs = pkm . EVs ;
2016-03-14 03:19:04 +00:00
int sum = evs . Sum ( ) ;
2016-10-23 19:48:49 +00:00
if ( pkm . IsEgg & & sum > 0 )
AddLine ( Severity . Invalid , "Eggs cannot receive EVs." , CheckIdentifier . EVs ) ;
else if ( sum = = 0 & & pkm . Stat_Level - pkm . Met_Level > 0 )
AddLine ( Severity . Fishy , "All EVs are zero, but leveled above Met Level." , CheckIdentifier . EVs ) ;
else if ( sum = = 508 )
AddLine ( Severity . Fishy , "2 EVs remaining." , CheckIdentifier . EVs ) ;
else if ( sum > 510 )
AddLine ( Severity . Invalid , "EV total cannot be above 510." , CheckIdentifier . EVs ) ;
else if ( pkm . Format > = 6 & & evs . Any ( ev = > ev > 252 ) )
AddLine ( Severity . Invalid , "EVs cannot go above 252." , CheckIdentifier . EVs ) ;
else if ( evs . All ( ev = > pkm . EVs [ 0 ] = = ev ) & & evs [ 0 ] ! = 0 )
AddLine ( Severity . Fishy , "EVs are all equal." , CheckIdentifier . EVs ) ;
2016-03-11 04:36:32 +00:00
}
2016-10-23 19:48:49 +00:00
private void verifyIVs ( )
2016-03-11 04:36:32 +00:00
{
2016-10-23 19:48:49 +00:00
if ( EncounterType = = typeof ( EncounterStatic ) & & ( EncounterMatch as EncounterStatic ) ? . IV3 = = true )
{
if ( pkm . IVs . Count ( iv = > iv = = 31 ) < 3 )
{
AddLine ( Severity . Invalid , "Should have at least 3 IVs = 31." , CheckIdentifier . IVs ) ;
return ;
}
}
if ( pkm . IVs . Sum ( ) = = 0 )
AddLine ( Severity . Fishy , "All IVs are zero." , CheckIdentifier . IVs ) ;
else if ( pkm . IVs [ 0 ] < 30 & & pkm . IVs . All ( iv = > pkm . IVs [ 0 ] = = iv ) )
AddLine ( Severity . Fishy , "All IVs are equal." , CheckIdentifier . IVs ) ;
2016-03-11 04:36:32 +00:00
}
2016-10-23 19:48:49 +00:00
private void verifyID ( )
2016-03-11 04:36:32 +00:00
{
2016-04-08 05:27:36 +00:00
if ( EncounterType = = typeof ( EncounterTrade ) )
2016-10-23 19:48:49 +00:00
return ; // Already matches Encounter Trade information
if ( pkm . TID = = 0 & & pkm . SID = = 0 )
AddLine ( Severity . Fishy , "TID and SID are zero." , CheckIdentifier . Trainer ) ;
else if ( pkm . TID = = pkm . SID )
AddLine ( Severity . Fishy , "TID and SID are equal." , CheckIdentifier . Trainer ) ;
else if ( pkm . TID = = 0 )
AddLine ( Severity . Fishy , "TID is zero." , CheckIdentifier . Trainer ) ;
else if ( pkm . SID = = 0 )
AddLine ( Severity . Fishy , "SID is zero." , CheckIdentifier . Trainer ) ;
2016-03-11 04:36:32 +00:00
}
2016-11-11 10:31:50 +00:00
private void verifyHyperTraining ( )
{
if ( pkm . Format < 7 )
return ; // No Hyper Training before Gen VII
var IVs = new [ ] { pkm . IV_HP , pkm . IV_ATK , pkm . IV_DEF , pkm . IV_SPA , pkm . IV_SPD , pkm . IV_SPE } ;
var HTs = new [ ] { pkm . HT_HP , pkm . HT_ATK , pkm . HT_DEF , pkm . HT_SPA , pkm . HT_SPD , pkm . HT_SPE } ;
2016-11-11 11:23:38 +00:00
if ( HTs . Any ( ht = > ht ) & & pkm . CurrentLevel ! = 100 )
AddLine ( Severity . Invalid , "Can't Hyper Train a pokemon that isn't level 100." , CheckIdentifier . IVs ) ;
2016-11-11 10:31:50 +00:00
if ( IVs . All ( iv = > iv = = 31 ) & & HTs . Any ( ht = > ht ) )
AddLine ( Severity . Invalid , "Can't Hyper Train a pokemon with perfect IVs." , CheckIdentifier . IVs ) ;
else
{
for ( int i = 0 ; i < 6 ; i + + ) // Check individual IVs
{
if ( ( IVs [ i ] = = 31 ) & & HTs [ i ] )
AddLine ( Severity . Invalid , "Can't Hyper Train a perfect IV." , CheckIdentifier . IVs ) ;
}
}
}
2016-10-23 19:48:49 +00:00
private CheckResult verifyEncounter ( )
2016-03-12 03:43:40 +00:00
{
2016-11-08 16:43:57 +00:00
if ( pkm . GenNumber < 6 )
2016-10-23 19:48:49 +00:00
return new CheckResult ( Severity . NotImplemented , "Not Implemented." , CheckIdentifier . Encounter ) ;
2016-03-12 03:43:40 +00:00
2016-10-23 19:48:49 +00:00
if ( pkm . WasLink )
2016-03-12 03:43:40 +00:00
{
2016-03-16 05:04:04 +00:00
// Should NOT be Fateful, and should be in Database
2016-03-24 00:57:22 +00:00
EncounterLink enc = EncounterMatch as EncounterLink ;
if ( enc = = null )
2016-10-23 19:48:49 +00:00
return new CheckResult ( Severity . Invalid , "Invalid Link Gift: unable to find matching gift." , CheckIdentifier . Encounter ) ;
2016-03-24 00:57:22 +00:00
2016-10-23 19:48:49 +00:00
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 ) ;
2016-11-13 19:48:07 +00:00
if ( pkm . SM & & ! enc . SM )
return new CheckResult ( Severity . Invalid , "Invalid Link Gift: can't obtain in SM." , CheckIdentifier . Encounter ) ;
2016-04-03 23:56:57 +00:00
2016-10-23 19:48:49 +00:00
if ( enc . Shiny ! = null & & ( bool ) enc . Shiny ^ pkm . IsShiny )
return new CheckResult ( Severity . Invalid , "Shiny Link gift mismatch." , CheckIdentifier . Encounter ) ;
2016-03-24 00:57:22 +00:00
2016-10-23 19:48:49 +00:00
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 ) ;
2016-03-12 03:43:40 +00:00
}
2016-11-13 17:37:28 +00:00
2016-10-23 19:48:49 +00:00
if ( pkm . WasEvent | | pkm . WasEventEgg )
2016-03-12 03:43:40 +00:00
{
2016-10-23 19:48:49 +00:00
MysteryGift MatchedGift = EncounterMatch as MysteryGift ;
2016-11-13 17:37:28 +00:00
if ( MatchedGift ! = null )
return new CheckResult ( Severity . Valid , $"Matches #{MatchedGift.CardID.ToString(" 0000 ")} ({MatchedGift.CardTitle})" , CheckIdentifier . Encounter ) ;
2016-03-12 03:43:40 +00:00
}
2016-03-23 02:47:13 +00:00
2016-11-11 01:39:38 +00:00
EncounterMatch = Legal . getValidStaticEncounter ( pkm ) ;
if ( EncounterMatch ! = null )
{
// Re-parse relearn moves
var s = ( EncounterStatic ) EncounterMatch ;
2016-11-17 06:16:28 +00:00
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 ) ;
}
2016-11-11 01:39:38 +00:00
}
2016-03-23 02:47:13 +00:00
EncounterMatch = null ; // Reset object
2016-10-23 19:48:49 +00:00
if ( pkm . WasEgg )
2016-03-12 03:43:40 +00:00
{
// Check Hatch Locations
2016-10-23 19:48:49 +00:00
if ( pkm . Met_Level ! = 1 )
return new CheckResult ( Severity . Invalid , "Invalid met level, expected 1." , CheckIdentifier . Encounter ) ;
2016-04-15 07:39:19 +00:00
// Check species
2016-10-23 19:48:49 +00:00
if ( Legal . NoHatchFromEgg . Contains ( pkm . Species ) )
return new CheckResult ( Severity . Invalid , "Species cannot be hatched from an egg." , CheckIdentifier . Encounter ) ;
if ( pkm . IsEgg )
2016-03-12 17:16:41 +00:00
{
2016-10-23 19:48:49 +00:00
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 ) ;
2016-03-12 17:16:41 +00:00
}
2016-10-23 19:48:49 +00:00
if ( pkm . XY )
2016-03-12 03:43:40 +00:00
{
2016-10-23 19:48:49 +00:00
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 ) ;
2016-03-12 03:43:40 +00:00
}
2016-10-23 19:48:49 +00:00
if ( pkm . AO )
2016-03-12 03:43:40 +00:00
{
2016-10-23 19:48:49 +00:00
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 ) ;
2016-03-12 03:43:40 +00:00
}
2016-11-09 05:43:22 +00:00
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 ) ;
}
2016-10-23 19:48:49 +00:00
return new CheckResult ( Severity . Invalid , "Invalid location for hatched egg." , CheckIdentifier . Encounter ) ;
2016-03-12 03:43:40 +00:00
}
2016-10-23 19:48:49 +00:00
if ( Legal . getIsFossil ( pkm ) )
2016-03-17 02:15:49 +00:00
{
2016-10-23 19:48:49 +00:00
return pkm . AbilityNumber ! = 4
? new CheckResult ( Severity . Valid , "Valid revived fossil." , CheckIdentifier . Encounter )
: new CheckResult ( Severity . Invalid , "Hidden ability on revived fossil." , CheckIdentifier . Encounter ) ;
2016-03-17 02:15:49 +00:00
}
2016-10-23 19:48:49 +00:00
EncounterMatch = Legal . getValidFriendSafari ( pkm ) ;
2016-03-23 05:31:30 +00:00
if ( EncounterMatch ! = null )
2016-03-16 01:35:40 +00:00
{
2016-10-23 19:48:49 +00:00
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 ) ;
2016-03-16 01:35:40 +00:00
}
2016-03-23 02:47:13 +00:00
2016-10-23 19:48:49 +00:00
EncounterMatch = Legal . getValidWildEncounters ( pkm ) ;
2016-03-23 02:47:13 +00:00
if ( EncounterMatch ! = null )
2016-03-13 23:42:03 +00:00
{
2016-04-21 02:47:40 +00:00
EncounterSlot [ ] enc = ( EncounterSlot [ ] ) EncounterMatch ;
if ( enc . Any ( slot = > slot . Normal ) )
return enc . All ( slot = > slot . Pressure )
2016-10-23 19:48:49 +00:00
? new CheckResult ( Severity . Valid , "Valid encounter at location (Pressure/Hustle/Vital Spirit)." , CheckIdentifier . Encounter )
: new CheckResult ( Severity . Valid , "Valid encounter at location." , CheckIdentifier . Encounter ) ;
2016-04-21 02:47:40 +00:00
// Decreased Level Encounters
if ( enc . Any ( slot = > slot . WhiteFlute ) )
return enc . All ( slot = > slot . Pressure )
2016-10-23 19:48:49 +00:00
? 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 ) ;
2016-04-21 02:47:40 +00:00
// Increased Level Encounters
if ( enc . Any ( slot = > slot . BlackFlute ) )
return enc . All ( slot = > slot . Pressure )
2016-10-23 19:48:49 +00:00
? 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 ) ;
2016-04-21 02:47:40 +00:00
if ( enc . Any ( slot = > slot . Pressure ) )
2016-10-23 19:48:49 +00:00
return new CheckResult ( Severity . Valid , "Valid encounter at location (Pressure/Hustle/Vital Spirit)." , CheckIdentifier . Encounter ) ;
2016-04-21 02:47:40 +00:00
2016-10-23 19:48:49 +00:00
return new CheckResult ( Severity . Valid , "Valid encounter at location (DexNav)." , CheckIdentifier . Encounter ) ;
2016-03-13 23:42:03 +00:00
}
2016-10-23 19:48:49 +00:00
EncounterMatch = Legal . getValidIngameTrade ( pkm ) ;
2016-03-23 02:47:13 +00:00
if ( EncounterMatch ! = null )
2016-10-23 19:48:49 +00:00
return new CheckResult ( Severity . Valid , "Valid ingame trade." , CheckIdentifier . Encounter ) ;
2016-11-13 17:37:28 +00:00
if ( pkm . WasEvent | | pkm . WasEventEgg )
return new CheckResult ( Severity . Invalid , "Unable to match to a Mystery Gift in the database." , CheckIdentifier . Encounter ) ;
2016-11-17 15:55:28 +00:00
return new CheckResult ( Severity . Invalid , "Unknown encounter." , CheckIdentifier . Encounter ) ;
2016-03-12 03:43:40 +00:00
}
2016-10-23 19:48:49 +00:00
private void verifyLevel ( )
2016-03-19 05:49:21 +00:00
{
2016-10-23 19:48:49 +00:00
MysteryGift MatchedGift = EncounterMatch as MysteryGift ;
if ( MatchedGift ! = null & & MatchedGift . Level ! = pkm . Met_Level )
{
2016-11-13 23:40:34 +00:00
if ( ! ( MatchedGift is WC7 ) | | ( ( WC7 ) MatchedGift ) . MetLevel ! = pkm . Met_Level )
{
AddLine ( new CheckResult ( Severity . Invalid , "Met Level does not match Wonder Card level." , CheckIdentifier . Level ) ) ;
return ;
}
2016-10-23 19:48:49 +00:00
}
int lvl = pkm . CurrentLevel ;
if ( lvl > 1 & & pkm . IsEgg )
AddLine ( Severity . Invalid , "Current level for an egg is invalid." , CheckIdentifier . Level ) ;
else if ( lvl < pkm . Met_Level )
AddLine ( Severity . Invalid , "Current level is below met level." , CheckIdentifier . Level ) ;
else if ( ( pkm . WasEgg | | EncounterMatch = = null ) & & ! Legal . getEvolutionValid ( pkm ) & & pkm . Species ! = 350 )
AddLine ( Severity . Invalid , "Level is below evolution requirements." , CheckIdentifier . Level ) ;
else if ( lvl > pkm . Met_Level & & lvl > 1 & & lvl ! = 100 & & pkm . EXP = = PKX . getEXP ( pkm . Stat_Level , pkm . Species ) )
AddLine ( Severity . Fishy , "Current experience matches level threshold." , CheckIdentifier . Level ) ;
else
AddLine ( Severity . Valid , "Current level is not below met level." , CheckIdentifier . Level ) ;
2016-03-19 05:49:21 +00:00
}
2016-11-08 16:43:57 +00:00
private void verifyMedals ( )
{
if ( pkm . Format < 6 )
return ;
// Training Medals
var TrainNames = ReflectUtil . getPropertiesStartWithPrefix ( pkm . GetType ( ) , "SuperTrain" ) . ToArray ( ) ;
var TrainCount = TrainNames . Count ( MissionName = > ReflectUtil . GetValue ( pkm , MissionName ) as bool? = = true ) ;
if ( pkm . IsEgg & & TrainCount > 0 )
{ AddLine ( Severity . Invalid , "Super Training missions on Egg." , CheckIdentifier . Training ) ; }
else if ( TrainCount > 0 & & pkm . GenNumber ! = 6 )
{ AddLine ( Severity . Invalid , "Distribution Super Training missions are not available in game." , CheckIdentifier . Training ) ; }
else if ( TrainCount = = 30 ^ pkm . SecretSuperTrainingComplete )
{ AddLine ( Severity . Invalid , "Super Training complete flag mismatch." , CheckIdentifier . Training ) ; }
// Distribution Training Medals
var DistNames = ReflectUtil . getPropertiesStartWithPrefix ( pkm . GetType ( ) , "DistSuperTrain" ) ;
var DistCount = DistNames . Count ( MissionName = > ReflectUtil . GetValue ( pkm , MissionName ) as bool? = = true ) ;
if ( pkm . IsEgg & & DistCount > 0 )
{ AddLine ( Severity . Invalid , "Distribution Super Training missions on Egg." , CheckIdentifier . Training ) ; }
else if ( DistCount > 0 & & pkm . GenNumber ! = 6 )
{ AddLine ( Severity . Invalid , "Distribution Super Training missions are not available in game." , CheckIdentifier . Training ) ; }
else if ( DistCount > 0 )
{ AddLine ( Severity . Fishy , "Distribution Super Training missions are not released." , CheckIdentifier . Training ) ; }
}
2016-10-23 19:48:49 +00:00
private void verifyRibbons ( )
2016-03-20 22:20:11 +00:00
{
if ( ! Encounter . Valid )
2016-10-23 19:48:49 +00:00
return ;
2016-09-17 19:21:23 +00:00
2016-03-20 22:20:11 +00:00
List < string > missingRibbons = new List < string > ( ) ;
List < string > invalidRibbons = new List < string > ( ) ;
2016-09-03 15:10:22 +00:00
2016-10-23 19:48:49 +00:00
if ( pkm . IsEgg )
2016-09-03 15:10:22 +00:00
{
2016-10-23 19:48:49 +00:00
var RibbonNames = ReflectUtil . getPropertiesStartWithPrefix ( pkm . GetType ( ) , "Ribbon" ) ;
foreach ( object RibbonValue in RibbonNames . Select ( RibbonName = > ReflectUtil . GetValue ( pkm , RibbonName ) ) )
2016-09-03 15:10:22 +00:00
{
2016-10-23 19:48:49 +00:00
if ( RibbonValue as bool? = = true ) // Boolean
{ AddLine ( Severity . Invalid , "Eggs should not have ribbons." , CheckIdentifier . Ribbon ) ; return ; }
if ( ( RibbonValue as int? ) > 0 ) // Count
{ AddLine ( Severity . Invalid , "Eggs should not have ribbons." , CheckIdentifier . Ribbon ) ; return ; }
2016-09-03 15:10:22 +00:00
}
2016-10-23 19:48:49 +00:00
return ;
2016-09-03 15:10:22 +00:00
}
2016-03-20 22:20:11 +00:00
// Check Event Ribbons
2016-10-23 19:48:49 +00:00
var RibbonData = ReflectUtil . getPropertiesStartWithPrefix ( pkm . GetType ( ) , "Ribbon" ) ;
MysteryGift MatchedGift = EncounterMatch as MysteryGift ;
string [ ] EventRib =
2016-03-20 22:20:11 +00:00
{
2016-10-23 19:48:49 +00:00
"RibbonCountry" , "RibbonNational" , "RibbonEarth" , "RibbonWorld" , "RibbonClassic" ,
"RibbonPremier" , "RibbonEvent" , "RibbonBirthday" , "RibbonSpecial" , "RibbonSouvenir" ,
"RibbonWishing" , "RibbonChampionBattle" , "RibbonChampionRegional" , "RibbonChampionNational" , "RibbonChampionWorld"
2016-03-20 22:20:11 +00:00
} ;
2016-10-23 19:48:49 +00:00
if ( MatchedGift ! = null ) // Wonder Card
2016-03-20 22:20:11 +00:00
{
2016-10-23 19:48:49 +00:00
var mgRibbons = ReflectUtil . getPropertiesStartWithPrefix ( MatchedGift . Content . GetType ( ) , "Ribbon" ) ;
var commonRibbons = mgRibbons . Intersect ( RibbonData ) . ToArray ( ) ;
foreach ( string r in commonRibbons )
2016-03-20 22:20:11 +00:00
{
2016-10-23 19:48:49 +00:00
bool? pk = ReflectUtil . getBooleanState ( pkm , r ) ;
bool? mg = ReflectUtil . getBooleanState ( MatchedGift , r ) ;
if ( pk ! = mg ) // Mismatch
{
if ( pk ? ? false )
missingRibbons . Add ( r ) ;
else
invalidRibbons . Add ( r ) ;
}
}
2016-03-20 22:20:11 +00:00
}
2016-03-28 05:05:51 +00:00
else if ( EncounterType = = typeof ( EncounterLink ) )
2016-03-23 02:47:13 +00:00
{
// No Event Ribbons except Classic (unless otherwise specified, ie not for Demo)
for ( int i = 0 ; i < EventRib . Length ; i + + )
2016-10-23 19:48:49 +00:00
{
if ( i = = 4 )
continue ;
if ( ReflectUtil . getBooleanState ( pkm , EventRib [ i ] ) = = true )
2016-03-23 02:47:13 +00:00
invalidRibbons . Add ( EventRibName [ i ] ) ;
2016-10-23 19:48:49 +00:00
}
2016-03-23 02:47:13 +00:00
2016-10-23 19:48:49 +00:00
bool classic = ReflectUtil . getBooleanState ( pkm , EventRib [ 4 ] ) = = true ;
if ( classic ^ ( ( EncounterLink ) EncounterMatch ) . Classic )
( classic ? invalidRibbons : missingRibbons ) . Add ( EventRibName [ 4 ] ) ;
2016-03-23 02:47:13 +00:00
}
2016-11-13 17:37:28 +00:00
else if ( EncounterType = = typeof ( EncounterStatic ) )
{
// No Event Ribbons except Wishing (which is only for Magearna)
for ( int i = 0 ; i < EventRib . Length ; i + + )
{
if ( i = = 10 )
continue ;
if ( ReflectUtil . getBooleanState ( pkm , EventRib [ i ] ) = = true )
invalidRibbons . Add ( EventRibName [ i ] ) ;
}
bool wishing = ReflectUtil . getBooleanState ( pkm , EventRib [ 10 ] ) = = true ;
if ( wishing ^ ( ( EncounterStatic ) EncounterMatch ) . RibbonWishing )
( wishing ? invalidRibbons : missingRibbons ) . Add ( EventRibName [ 10 ] ) ;
}
2016-03-23 02:47:13 +00:00
else // No ribbons
2016-03-20 22:20:11 +00:00
{
for ( int i = 0 ; i < EventRib . Length ; i + + )
2016-10-23 19:48:49 +00:00
if ( ReflectUtil . getBooleanState ( pkm , EventRib [ i ] ) = = true )
2016-03-20 22:20:11 +00:00
invalidRibbons . Add ( EventRibName [ i ] ) ;
}
2016-10-23 19:48:49 +00:00
// Unobtainable ribbons for Gen Origin
if ( pkm . GenNumber > 3 )
{
if ( ReflectUtil . getBooleanState ( pkm , "RibbonChampionG3Hoenn" ) = = true )
invalidRibbons . Add ( "GBA Champion" ) ; // RSE HoF
if ( ReflectUtil . getBooleanState ( pkm , "RibbonChampionG3Hoenn" ) = = true )
invalidRibbons . Add ( "RibbonArtist" ) ; // RSE Master Rank Portrait
if ( ReflectUtil . getBooleanState ( pkm , "RibbonChampionG3Hoenn" ) = = true )
invalidRibbons . Add ( "GBA Champion" ) ; // RSE HoF
}
if ( pkm . GenNumber > 4 )
{
if ( ReflectUtil . getBooleanState ( pkm , "RibbonChampionSinnoh" ) = = true )
invalidRibbons . Add ( "Sinnoh Champ" ) ; // DPPt HoF
if ( ReflectUtil . getBooleanState ( pkm , "RibbonLegend" ) = = true )
invalidRibbons . Add ( "Legend" ) ; // HGSS Defeat Red @ Mt.Silver
}
if ( pkm . Format > = 6 & & pkm . GenNumber > = 6 )
{
if ( ReflectUtil . getBooleanState ( pkm , "RibbonCountMemoryContest" ) = = true )
invalidRibbons . Add ( "Contest Memory" ) ; // Gen3/4 Contest
if ( ReflectUtil . getBooleanState ( pkm , "RibbonCountMemoryBattle" ) = = true )
invalidRibbons . Add ( "Battle Memory" ) ; // Gen3/4 Battle
}
if ( ReflectUtil . getBooleanState ( pkm , "RibbonRecord" ) = = true )
2016-03-20 22:20:11 +00:00
invalidRibbons . Add ( "Record" ) ; // Unobtainable
if ( missingRibbons . Count + invalidRibbons . Count = = 0 )
2016-09-03 15:10:22 +00:00
{
2016-11-08 16:43:57 +00:00
AddLine ( Severity . Valid , "All ribbons accounted for." , CheckIdentifier . Ribbon ) ;
2016-10-23 19:48:49 +00:00
return ;
2016-09-03 15:10:22 +00:00
}
2016-03-20 22:20:11 +00:00
string [ ] result = new string [ 2 ] ;
if ( missingRibbons . Count > 0 )
result [ 0 ] = "Missing Ribbons: " + string . Join ( ", " , missingRibbons ) ;
if ( invalidRibbons . Count > 0 )
result [ 1 ] = "Invalid Ribbons: " + string . Join ( ", " , invalidRibbons ) ;
2016-10-23 19:48:49 +00:00
AddLine ( Severity . Invalid , string . Join ( Environment . NewLine , result . Where ( s = > ! string . IsNullOrEmpty ( s ) ) ) , CheckIdentifier . Ribbon ) ;
2016-03-20 22:20:11 +00:00
}
2016-10-23 19:48:49 +00:00
private void verifyAbility ( )
2016-03-21 15:01:08 +00:00
{
2016-10-29 06:41:22 +00:00
int [ ] abilities = pkm . PersonalInfo . Abilities ;
2016-10-23 19:48:49 +00:00
int abilval = Array . IndexOf ( abilities , pkm . Ability ) ;
2016-03-21 15:01:08 +00:00
if ( abilval < 0 )
2016-10-23 19:48:49 +00:00
{
AddLine ( Severity . Invalid , "Ability is not valid for species/form." , CheckIdentifier . Ability ) ;
return ;
}
2016-03-21 15:01:08 +00:00
2016-03-23 02:47:13 +00:00
if ( EncounterMatch ! = null )
{
2016-10-23 19:48:49 +00:00
// Check Hidden Ability Mismatches
if ( pkm . GenNumber > = 5 )
2016-03-31 02:55:27 +00:00
{
2016-10-23 19:48:49 +00:00
if ( EncounterType = = typeof ( EncounterStatic ) )
if ( pkm . AbilityNumber = = 4 ^ ( ( EncounterStatic ) EncounterMatch ) . Ability = = 4 )
{
AddLine ( Severity . Invalid , "Hidden Ability mismatch for static encounter." , CheckIdentifier . Ability ) ;
}
if ( EncounterType = = typeof ( EncounterTrade ) )
if ( pkm . AbilityNumber = = 4 ^ ( ( EncounterTrade ) EncounterMatch ) . Ability = = 4 )
{
AddLine ( Severity . Invalid , "Hidden Ability mismatch for ingame trade." , CheckIdentifier . Ability ) ;
return ;
}
2016-11-13 20:01:52 +00:00
if ( EncounterType = = typeof ( EncounterLink ) )
if ( pkm . AbilityNumber ! = ( ( EncounterLink ) EncounterMatch ) . Ability )
{
AddLine ( Severity . Invalid , "Ability mismatch for Link Gift." , CheckIdentifier . Ability ) ;
return ;
}
2016-10-23 19:48:49 +00:00
}
if ( pkm . GenNumber = = 6 )
{
if ( EncounterType = = typeof ( EncounterSlot [ ] ) & & pkm . AbilityNumber = = 4 )
{
var slots = ( EncounterSlot [ ] ) EncounterMatch ;
bool valid = slots . Any ( slot = > slot . DexNav | |
slot . Type = = SlotType . FriendSafari | |
slot . Type = = SlotType . Horde ) ;
2016-03-31 02:55:27 +00:00
2016-10-23 19:48:49 +00:00
if ( ! valid )
{
AddLine ( Severity . Invalid , "Hidden Ability on non-horde/friend safari wild encounter." , CheckIdentifier . Ability ) ;
2016-11-23 01:04:53 +00:00
return ;
}
}
}
if ( pkm . GenNumber = = 7 )
{
if ( EncounterType = = typeof ( EncounterSlot [ ] ) & & pkm . AbilityNumber = = 4 )
{
var slots = ( EncounterSlot [ ] ) EncounterMatch ;
bool valid = slots . Any ( slot = > slot . Type = = SlotType . SOS ) ;
if ( ! valid )
{
AddLine ( Severity . Invalid , "Hidden Ability on non-SOS wild encounter." , CheckIdentifier . Ability ) ;
2016-10-23 19:48:49 +00:00
return ;
}
}
2016-03-31 02:55:27 +00:00
}
2016-03-23 02:47:13 +00:00
}
2016-03-22 04:50:39 +00:00
2016-10-23 19:48:49 +00:00
if ( pkm . GenNumber > = 6 & & abilities [ pkm . AbilityNumber > > 1 ] ! = pkm . Ability )
AddLine ( Severity . Invalid , "Ability does not match ability number." , CheckIdentifier . Ability ) ;
else if ( pkm . GenNumber < = 5 & & pkm . Version ! = ( int ) GameVersion . CXD & & abilities [ 0 ] ! = abilities [ 1 ] & & pkm . PIDAbility ! = abilval )
AddLine ( Severity . Invalid , "Ability does not match PID." , CheckIdentifier . Ability ) ;
else
AddLine ( Severity . Valid , "Ability matches ability number." , CheckIdentifier . Ability ) ;
2016-03-21 15:01:08 +00:00
}
2016-10-23 19:48:49 +00:00
private void verifyBall ( )
2016-03-21 15:01:08 +00:00
{
2016-10-23 19:48:49 +00:00
if ( pkm . GenNumber < 6 )
return ; // not implemented
2016-03-23 02:47:13 +00:00
if ( ! Encounter . Valid )
2016-10-23 19:48:49 +00:00
return ;
2016-11-09 07:37:53 +00:00
if ( EncounterIsMysteryGift )
2016-10-23 19:48:49 +00:00
{
if ( pkm . Ball ! = ( ( MysteryGift ) EncounterMatch ) . Ball )
AddLine ( Severity . Invalid , "Ball does not match specified Mystery Gift Ball." , CheckIdentifier . Ball ) ;
else
AddLine ( Severity . Valid , "Ball matches Mystery Gift." , CheckIdentifier . Ball ) ;
return ;
}
if ( EncounterType = = typeof ( EncounterLink ) )
{
if ( ( ( EncounterLink ) EncounterMatch ) . Ball ! = pkm . Ball )
AddLine ( Severity . Invalid , "Incorrect ball on Link gift." , CheckIdentifier . Ball ) ;
else
AddLine ( Severity . Valid , "Correct ball on Link gift." , CheckIdentifier . Ball ) ;
return ;
}
if ( EncounterType = = typeof ( EncounterTrade ) )
{
if ( pkm . Ball ! = 4 ) // Pokeball
AddLine ( Severity . Invalid , "Incorrect ball on ingame trade encounter." , CheckIdentifier . Ball ) ;
else
AddLine ( Severity . Valid , "Correct ball on ingame trade encounter." , CheckIdentifier . Ball ) ;
return ;
}
2016-03-29 05:30:23 +00:00
if ( EncounterType = = typeof ( EncounterStatic ) )
2016-04-21 03:46:18 +00:00
{
EncounterStatic enc = EncounterMatch as EncounterStatic ;
2016-10-23 19:48:49 +00:00
if ( enc ? . Gift ? ? false )
2016-03-28 05:05:51 +00:00
{
2016-10-23 19:48:49 +00:00
if ( enc . Ball ! = pkm . Ball ) // Pokéball by default
AddLine ( Severity . Invalid , "Incorrect ball on ingame gift." , CheckIdentifier . Ball ) ;
2016-11-08 16:43:57 +00:00
else
2016-10-23 19:48:49 +00:00
AddLine ( Severity . Valid , "Correct ball on ingame gift." , CheckIdentifier . Ball ) ;
2016-03-28 05:05:51 +00:00
2016-10-23 19:48:49 +00:00
return ;
2016-03-28 05:05:51 +00:00
}
2016-10-23 19:48:49 +00:00
2016-11-08 16:43:57 +00:00
if ( Legal . getWildBalls ( pkm ) . Contains ( pkm . Ball ) )
2016-10-23 19:48:49 +00:00
AddLine ( Severity . Valid , "Correct ball on ingame static encounter." , CheckIdentifier . Ball ) ;
2016-11-08 16:43:57 +00:00
else
AddLine ( Severity . Invalid , "Incorrect ball on ingame static encounter." , CheckIdentifier . Ball ) ;
2016-10-23 19:48:49 +00:00
return ;
}
if ( EncounterType = = typeof ( EncounterSlot [ ] ) )
{
2016-11-08 16:43:57 +00:00
if ( Legal . getWildBalls ( pkm ) . Contains ( pkm . Ball ) )
2016-10-23 19:48:49 +00:00
AddLine ( Severity . Valid , "Correct ball on ingame encounter." , CheckIdentifier . Ball ) ;
2016-11-08 16:43:57 +00:00
else
AddLine ( Severity . Invalid , "Incorrect ball on ingame encounter." , CheckIdentifier . Ball ) ;
2016-10-23 19:48:49 +00:00
return ;
}
if ( pkm . WasEgg )
{
if ( pkm . GenNumber < 6 ) // No inheriting Balls
{
if ( pkm . Ball ! = 0x04 )
AddLine ( Severity . Invalid , "Ball should be Pokéball." , CheckIdentifier . Ball ) ;
return ;
}
if ( pkm . Ball = = 0x01 ) // Master Ball
{ AddLine ( Severity . Invalid , "Master Ball on egg origin." , CheckIdentifier . Ball ) ; return ; }
if ( pkm . Ball = = 0x10 ) // Cherish Ball
{ AddLine ( Severity . Invalid , "Cherish Ball on non-event." , CheckIdentifier . Ball ) ; return ; }
2016-11-13 17:49:44 +00:00
if ( pkm . Ball = = 0x04 ) // Poké Ball
{ AddLine ( Severity . Valid , "Standard Poké Ball." , CheckIdentifier . Ball ) ; return ; }
2016-10-23 19:48:49 +00:00
2016-11-11 05:10:28 +00:00
switch ( pkm . GenNumber )
2016-03-28 05:05:51 +00:00
{
2016-11-11 05:10:28 +00:00
case 6 : // Gen6 Inheritance Rules
verifyEggBallGen6 ( ) ;
return ;
case 7 : // Gen7 Inheritance Rules
verifyEggBallGen7 ( ) ;
return ;
2016-03-28 05:05:51 +00:00
}
2016-11-11 05:10:28 +00:00
}
2016-03-28 05:05:51 +00:00
2016-11-11 05:10:28 +00:00
if ( pkm . Ball = = 0x04 ) // Poké Ball
{
AddLine ( Severity . Valid , "Standard Poké Ball." , CheckIdentifier . Ball ) ;
return ;
}
2016-10-23 19:48:49 +00:00
2016-11-11 05:10:28 +00:00
AddLine ( Severity . Invalid , "No ball check satisfied, assuming illegal." , CheckIdentifier . Ball ) ;
}
private void verifyEggBallGen6 ( )
{
if ( pkm . Gender = = 2 ) // Genderless
{
if ( pkm . Ball ! = 0x04 ) // Must be Pokéball as ball can only pass via mother (not Ditto!)
AddLine ( Severity . Invalid , "Non-Pokéball on genderless egg." , CheckIdentifier . Ball ) ;
else
AddLine ( Severity . Valid , "Pokéball on genderless egg." , CheckIdentifier . Ball ) ;
2016-03-28 05:05:51 +00:00
2016-11-11 05:10:28 +00:00
return ;
}
if ( Legal . BreedMaleOnly . Contains ( pkm . Species ) )
{
if ( pkm . Ball ! = 0x04 ) // Must be Pokéball as ball can only pass via mother (not Ditto!)
AddLine ( Severity . Invalid , "Non-Pokéball on Male-Only egg." , CheckIdentifier . Ball ) ;
else
AddLine ( Severity . Valid , "Pokéball on Male-Only egg." , CheckIdentifier . Ball ) ;
2016-03-27 03:52:06 +00:00
2016-11-11 05:10:28 +00:00
return ;
}
2016-10-23 19:48:49 +00:00
2016-11-11 05:10:28 +00:00
if ( pkm . Ball = = 0x05 ) // Safari Ball
{
if ( Legal . getLineage ( pkm ) . All ( e = > ! Legal . Inherit_Safari . Contains ( e ) ) )
AddLine ( Severity . Invalid , "Safari Ball not possible for species." , CheckIdentifier . Ball ) ;
else if ( pkm . AbilityNumber = = 4 )
AddLine ( Severity . Invalid , "Safari Ball with Hidden Ability." , CheckIdentifier . Ball ) ;
else
AddLine ( Severity . Valid , "Safari Ball possible for species." , CheckIdentifier . Ball ) ;
2016-10-23 19:48:49 +00:00
2016-11-11 05:10:28 +00:00
return ;
}
if ( 0x10 < pkm . Ball & & pkm . Ball < 0x18 ) // Apricorn Ball
{
if ( Legal . getLineage ( pkm ) . All ( e = > ! Legal . Inherit_Apricorn . Contains ( e ) ) )
AddLine ( Severity . Invalid , "Apricorn Ball not possible for species." , CheckIdentifier . Ball ) ;
if ( pkm . AbilityNumber = = 4 )
AddLine ( Severity . Invalid , "Apricorn Ball with Hidden Ability." , CheckIdentifier . Ball ) ;
else
AddLine ( Severity . Valid , "Apricorn Ball possible for species." , CheckIdentifier . Ball ) ;
2016-03-22 04:31:06 +00:00
2016-11-11 05:10:28 +00:00
return ;
}
if ( pkm . Ball = = 0x18 ) // Sport Ball
{
if ( Legal . getLineage ( pkm ) . All ( e = > ! Legal . Inherit_Sport . Contains ( e ) ) )
AddLine ( Severity . Invalid , "Sport Ball not possible for species." , CheckIdentifier . Ball ) ;
else if ( pkm . AbilityNumber = = 4 )
AddLine ( Severity . Invalid , "Sport Ball with Hidden Ability." , CheckIdentifier . Ball ) ;
else
AddLine ( Severity . Valid , "Sport Ball possible for species." , CheckIdentifier . Ball ) ;
2016-03-23 02:47:13 +00:00
2016-11-11 05:10:28 +00:00
return ;
}
if ( pkm . Ball = = 0x19 ) // Dream Ball
{
if ( Legal . getLineage ( pkm ) . All ( e = > ! Legal . Inherit_Dream . Contains ( e ) ) )
AddLine ( Severity . Invalid , "Dream Ball not possible for species." , CheckIdentifier . Ball ) ;
else
AddLine ( Severity . Valid , "Dream Ball possible for species." , CheckIdentifier . Ball ) ;
2016-10-23 19:48:49 +00:00
2016-11-11 05:10:28 +00:00
return ;
}
if ( 0x0D < = pkm . Ball & & pkm . Ball < = 0x0F )
{
if ( Legal . Ban_Gen4Ball . Contains ( pkm . Species ) )
AddLine ( Severity . Invalid , "Unobtainable capture for Gen4 Ball." , CheckIdentifier . Ball ) ;
else
AddLine ( Severity . Valid , "Obtainable capture for Gen4 Ball." , CheckIdentifier . Ball ) ;
return ;
2016-03-29 05:30:23 +00:00
}
2016-11-11 05:10:28 +00:00
if ( 0x02 < = pkm . Ball & & pkm . Ball < = 0x0C ) // Don't worry, Ball # 0x05 was already checked.
{
if ( Legal . Ban_Gen3Ball . Contains ( pkm . Species ) )
2016-11-12 05:23:33 +00:00
AddLine ( Severity . Invalid , "Unobtainable capture for Gen3 Ball." , CheckIdentifier . Ball ) ;
2016-11-11 05:10:28 +00:00
else if ( pkm . AbilityNumber = = 4 & & 152 < = pkm . Species & & pkm . Species < = 160 )
AddLine ( Severity . Invalid , "Ball not possible for species with hidden ability." , CheckIdentifier . Ball ) ;
else
2016-11-12 05:23:33 +00:00
AddLine ( Severity . Valid , "Obtainable capture for Gen3 Ball." , CheckIdentifier . Ball ) ;
2016-03-21 15:01:08 +00:00
2016-11-11 05:10:28 +00:00
return ;
}
if ( pkm . Species > 650 & & pkm . Species ! = 700 ) // Sylveon
{
if ( ! Legal . getWildBalls ( pkm ) . Contains ( pkm . Ball ) )
AddLine ( Severity . Invalid , "Unobtainable ball for Kalos origin." , CheckIdentifier . Ball ) ;
else
AddLine ( Severity . Valid , "Obtainable ball for Kalos origin." , CheckIdentifier . Ball ) ;
return ;
}
2016-11-12 14:52:40 +00:00
AddLine ( Severity . Invalid , pkm . Ball > = 26
? "Ball unobtainable in origin generation."
: "No ball check satisfied, assuming illegal." , CheckIdentifier . Ball ) ;
2016-03-21 15:01:08 +00:00
}
2016-11-11 05:10:28 +00:00
private void verifyEggBallGen7 ( )
{
2016-11-12 05:23:33 +00:00
var Lineage = Legal . getLineage ( pkm ) . ToArray ( ) ;
if ( pkm . Ball = = 0x05 ) // Safari Ball
{
if ( Lineage . Any ( e = > Legal . Inherit_Safari . Contains ( e ) ) )
AddLine ( Severity . Valid , "Safari Ball possible from Female parent." , CheckIdentifier . Ball ) ;
else if ( Lineage . Any ( e = > Legal . Inherit_SafariMale . Contains ( e ) ) )
AddLine ( Severity . Valid , "Safari Ball possible from Male parent." , CheckIdentifier . Ball ) ;
else
AddLine ( Severity . Invalid , "Safari Ball not possible for species." , CheckIdentifier . Ball ) ;
if ( pkm . AbilityNumber = = 4 )
AddLine ( Severity . Invalid , "Safari Ball with Hidden Ability." , CheckIdentifier . Ball ) ;
return ;
}
if ( 0x10 < pkm . Ball & & pkm . Ball < 0x18 ) // Apricorn Ball
{
2016-11-14 06:24:29 +00:00
if ( ( pkm . Species > 731 & & pkm . Species < = 785 ) | | Lineage . Any ( e = > Legal . PastGenAlolanNatives . Contains ( e ) ) )
2016-11-12 05:23:33 +00:00
{
AddLine ( Severity . Valid , "Apricorn Ball possible for species." , CheckIdentifier . Ball ) ;
return ;
}
if ( Lineage . Any ( e = > Legal . PastGenAlolanScans . Contains ( e ) ) )
{
AddLine ( Severity . Valid , "Apricorn Ball possible for species." , CheckIdentifier . Ball ) ;
if ( pkm . AbilityNumber = = 4 )
AddLine ( Severity . Invalid , "Apricorn Ball with Hidden Ability." , CheckIdentifier . Ball ) ;
}
if ( Lineage . Any ( e = > Legal . Inherit_Apricorn . Contains ( e ) ) )
{
AddLine ( Severity . Valid , "Apricorn Ball possible for species." , CheckIdentifier . Ball ) ;
if ( pkm . AbilityNumber = = 4 )
AddLine ( Severity . Invalid , "Apricorn Ball with Hidden Ability." , CheckIdentifier . Ball ) ;
}
else
AddLine ( Severity . Invalid , "Apricorn Ball not possible for species." , CheckIdentifier . Ball ) ;
return ;
}
if ( pkm . Ball = = 0x18 ) // Sport Ball
{
if ( Lineage . All ( e = > ! Legal . Inherit_Sport . Contains ( e ) ) )
AddLine ( Severity . Invalid , "Sport Ball not possible for species." , CheckIdentifier . Ball ) ;
else
AddLine ( Severity . Valid , "Sport Ball possible for species." , CheckIdentifier . Ball ) ;
if ( pkm . AbilityNumber = = 4 )
AddLine ( Severity . Invalid , "Sport Ball with Hidden Ability." , CheckIdentifier . Ball ) ;
return ;
}
if ( pkm . Ball = = 0x19 ) // Dream Ball
{
if ( Lineage . Any ( e = > Legal . Inherit_Dream . Contains ( e ) ) )
AddLine ( Severity . Valid , "Dream Ball inheritance possible from Female species." , CheckIdentifier . Ball ) ;
else if ( Lineage . Any ( e = > Legal . InheritDreamMale . Contains ( e ) ) )
{
if ( pkm . AbilityNumber ! = 4 )
AddLine ( Severity . Valid , "Dream Ball inheritance possible from Male/Genderless species." , CheckIdentifier . Ball ) ;
else
AddLine ( Severity . Invalid , "Dream Ball not possible for species." , CheckIdentifier . Ball ) ;
}
else
AddLine ( Severity . Invalid , "Dream Ball not possible for species." , CheckIdentifier . Ball ) ;
return ;
}
if ( 0x0D < = pkm . Ball & & pkm . Ball < = 0x0F )
{
if ( Legal . Ban_Gen4Ball . Contains ( pkm . Species ) )
{
if ( ! Legal . Ban_Gen4Ball_AllowG7 . Contains ( pkm . Species ) )
AddLine ( Severity . Invalid , "Unobtainable capture for Gen4 Ball." , CheckIdentifier . Ball ) ;
else if ( pkm . AbilityNumber = = 4 )
AddLine ( Severity . Invalid , "Ball not possible for species with hidden ability." , CheckIdentifier . Ball ) ;
else
AddLine ( Severity . Valid , "Obtainable capture for Gen4 Ball." , CheckIdentifier . Ball ) ;
}
else
AddLine ( Severity . Valid , "Obtainable capture for Gen4 Ball." , CheckIdentifier . Ball ) ;
return ;
}
if ( 0x02 < = pkm . Ball & & pkm . Ball < = 0x0C ) // Don't worry, Ball # 0x05 was already checked.
{
if ( Legal . Ban_Gen3Ball_AllowG7 . Contains ( pkm . Species ) )
{
if ( pkm . AbilityNumber = = 4 )
AddLine ( Severity . Invalid , "Ball not possible for species with hidden ability." , CheckIdentifier . Ball ) ;
else
AddLine ( Severity . Valid , "Obtainable capture for Gen3Ball." , CheckIdentifier . Ball ) ;
}
else if ( Legal . Ban_Gen3Ball . Contains ( pkm . Species ) )
AddLine ( Severity . Invalid , "Unobtainable capture for Gen3 Ball." , CheckIdentifier . Ball ) ;
else if ( pkm . AbilityNumber = = 4 & & 152 < = pkm . Species & & pkm . Species < = 160 )
AddLine ( Severity . Invalid , "Ball not possible for species with hidden ability." , CheckIdentifier . Ball ) ;
else
AddLine ( Severity . Valid , "Obtainable capture for Gen3Ball." , CheckIdentifier . Ball ) ;
return ;
}
2016-11-12 14:52:40 +00:00
if ( pkm . Ball = = 26 )
{
2016-11-14 06:24:29 +00:00
if ( ( pkm . Species > 731 & & pkm . Species < = 785 ) | | Lineage . Any ( e = > Legal . PastGenAlolanNatives . Contains ( e ) ) )
2016-11-12 14:52:40 +00:00
{
AddLine ( Severity . Valid , "Beast Ball possible for species." , CheckIdentifier . Ball ) ;
return ;
}
if ( Lineage . Any ( e = > Legal . PastGenAlolanScans . Contains ( e ) ) )
{
AddLine ( Severity . Valid , "Scanned Beast Ball possible for species." , CheckIdentifier . Ball ) ;
if ( pkm . AbilityNumber = = 4 )
AddLine ( Severity . Invalid , "Scanned Beast Ball with Hidden Ability." , CheckIdentifier . Ball ) ;
return ;
}
// next statement catches all new alolans
}
if ( pkm . Species > 721 )
2016-11-11 05:10:28 +00:00
{
if ( ! Legal . getWildBalls ( pkm ) . Contains ( pkm . Ball ) )
AddLine ( Severity . Invalid , "Unobtainable ball for Alola origin." , CheckIdentifier . Ball ) ;
else
AddLine ( Severity . Valid , "Obtainable ball for Alola origin." , CheckIdentifier . Ball ) ;
return ;
}
2016-11-12 14:52:40 +00:00
AddLine ( Severity . Invalid , pkm . Ball > 26
? "Ball unobtainable in origin generation."
: "No ball check satisfied, assuming illegal." , CheckIdentifier . Ball ) ;
2016-11-11 05:10:28 +00:00
}
2016-10-23 19:48:49 +00:00
private CheckResult verifyHistory ( )
2016-03-22 04:31:06 +00:00
{
2016-03-23 02:47:13 +00:00
if ( ! Encounter . Valid )
2016-10-23 19:48:49 +00:00
return new CheckResult ( Severity . Valid , "Skipped History check due to other check being invalid." , CheckIdentifier . History ) ;
if ( pkm . GenNumber < 6 )
return new CheckResult ( Severity . Valid , "No History Block to check." , CheckIdentifier . History ) ;
2016-03-23 02:47:13 +00:00
2016-03-23 05:49:46 +00:00
WC6 MatchedWC6 = EncounterMatch as WC6 ;
2016-03-22 04:31:06 +00:00
if ( MatchedWC6 ? . OT . Length > 0 ) // Has Event OT -- null propagation yields false if MatchedWC6=null
{
2016-10-29 06:41:22 +00:00
if ( pkm . OT_Friendship ! = pkm . PersonalInfo . BaseFriendship )
2016-10-23 19:48:49 +00:00
return new CheckResult ( Severity . Invalid , "Event OT Friendship does not match base friendship." , CheckIdentifier . History ) ;
if ( pkm . OT_Affection ! = 0 )
return new CheckResult ( Severity . Invalid , "Event OT Affection should be zero." , CheckIdentifier . History ) ;
if ( pkm . CurrentHandler ! = 1 )
return new CheckResult ( Severity . Invalid , "Current handler should not be Event OT." , CheckIdentifier . History ) ;
}
2016-11-17 17:12:17 +00:00
if ( pkm . Format = = 7 )
2016-11-11 03:29:00 +00:00
{
// TODO
return new CheckResult ( Severity . Valid , "S/M History Block check skipped." , CheckIdentifier . History ) ;
}
2016-10-23 19:48:49 +00:00
if ( ! pkm . WasEvent & & ! ( pkm . WasLink & & ( EncounterMatch as EncounterLink ) ? . OT = = false ) & & ( pkm . HT_Name . Length = = 0 | | pkm . Geo1_Country = = 0 ) ) // Is not Traded
{
if ( pkm . HT_Name . Length ! = 0 )
return new CheckResult ( Severity . Invalid , "GeoLocation Memory -- HT Name present but has no previous Country." , CheckIdentifier . History ) ;
if ( pkm . Geo1_Country ! = 0 )
return new CheckResult ( Severity . Invalid , "GeoLocation Memory -- Previous country of residence but no Handling Trainer." , CheckIdentifier . History ) ;
if ( pkm . HT_Memory ! = 0 )
return new CheckResult ( Severity . Invalid , "Memory -- Handling Trainer memory present but no Handling Trainer." , CheckIdentifier . History ) ;
if ( pkm . CurrentHandler ! = 0 ) // Badly edited; PKHeX doesn't trip this.
return new CheckResult ( Severity . Invalid , "Untraded -- Current handler should not be the Handling Trainer." , CheckIdentifier . History ) ;
if ( pkm . HT_Friendship ! = 0 )
return new CheckResult ( Severity . Invalid , "Untraded -- Handling Trainer Friendship should be zero." , CheckIdentifier . History ) ;
if ( pkm . HT_Affection ! = 0 )
return new CheckResult ( Severity . Invalid , "Untraded -- Handling Trainer Affection should be zero." , CheckIdentifier . History ) ;
if ( pkm . XY & & pkm . CNTs . Any ( stat = > stat > 0 ) )
return new CheckResult ( Severity . Invalid , "Untraded -- Contest stats on XY should be zero." , CheckIdentifier . History ) ;
2016-03-22 04:31:06 +00:00
// We know it is untraded (HT is empty), if it must be trade evolved flag it.
2016-10-23 19:48:49 +00:00
if ( Legal . getHasTradeEvolved ( pkm ) & & ( EncounterMatch as EncounterSlot [ ] ) ? . Any ( slot = > slot . Species = = pkm . Species ) ! = true )
2016-03-22 04:31:06 +00:00
{
2016-10-23 19:48:49 +00:00
if ( pkm . Species ! = 350 ) // Milotic
return new CheckResult ( Severity . Invalid , "Untraded -- requires a trade evolution." , CheckIdentifier . History ) ;
if ( pkm . CNT_Beauty < 170 ) // Beauty Contest Stat Requirement
return new CheckResult ( Severity . Invalid , "Untraded -- Beauty is not high enough for Levelup Evolution." , CheckIdentifier . History ) ;
if ( pkm . CurrentLevel = = 1 )
return new CheckResult ( Severity . Invalid , "Untraded -- Beauty is high enough but still Level 1." , CheckIdentifier . History ) ;
2016-03-22 04:31:06 +00:00
}
}
else // Is Traded
{
2016-11-10 16:14:54 +00:00
if ( pkm . HT_Memory = = 0 & & pkm . Format = = 6 )
2016-10-23 19:48:49 +00:00
return new CheckResult ( Severity . Invalid , "Memory -- missing Handling Trainer Memory." , CheckIdentifier . History ) ;
2016-03-22 04:31:06 +00:00
}
2016-03-31 01:53:34 +00:00
2016-10-23 19:48:49 +00:00
// Memory ChecksResult
if ( pkm . IsEgg )
2016-03-31 01:53:34 +00:00
{
2016-10-23 19:48:49 +00:00
if ( pkm . HT_Memory ! = 0 )
return new CheckResult ( Severity . Invalid , "Memory -- has Handling Trainer Memory." , CheckIdentifier . History ) ;
if ( pkm . OT_Memory ! = 0 )
return new CheckResult ( Severity . Invalid , "Memory -- has Original Trainer Memory." , CheckIdentifier . History ) ;
2016-03-31 01:53:34 +00:00
}
else if ( EncounterType ! = typeof ( WC6 ) )
{
2016-10-23 19:48:49 +00:00
if ( pkm . OT_Memory = = 0 ^ ! pkm . Gen6 )
return new CheckResult ( Severity . Invalid , "Memory -- missing Original Trainer Memory." , CheckIdentifier . History ) ;
2016-11-11 06:11:53 +00:00
if ( pkm . GenNumber < 6 & & pkm . OT_Affection ! = 0 )
2016-10-23 19:48:49 +00:00
return new CheckResult ( Severity . Invalid , "OT Affection should be zero." , CheckIdentifier . History ) ;
2016-03-31 01:53:34 +00:00
}
2016-03-22 04:31:06 +00:00
// Unimplemented: Ingame Trade Memories
2016-10-23 19:48:49 +00:00
return new CheckResult ( Severity . Valid , "History is valid." , CheckIdentifier . History ) ;
2016-03-22 04:31:06 +00:00
}
2016-10-23 19:48:49 +00:00
private CheckResult verifyCommonMemory ( int handler )
2016-05-07 06:16:35 +00:00
{
int m = 0 ;
2016-05-09 23:09:40 +00:00
int t = 0 ;
2016-05-07 06:16:35 +00:00
string resultPrefix = "" ;
switch ( handler )
{
case 0 :
2016-10-23 19:48:49 +00:00
m = pkm . OT_Memory ;
t = pkm . OT_TextVar ;
2016-05-07 06:16:35 +00:00
resultPrefix = "OT " ;
break ;
case 1 :
2016-10-23 19:48:49 +00:00
m = pkm . HT_Memory ;
t = pkm . HT_TextVar ;
2016-05-07 06:16:35 +00:00
resultPrefix = "HT " ;
break ;
}
int matchingMoveMemory = Array . IndexOf ( Legal . MoveSpecificMemories [ 0 ] , m ) ;
2016-10-23 19:48:49 +00:00
if ( matchingMoveMemory ! = - 1 & & pkm . Species ! = 235 & & ! Legal . getCanLearnMachineMove ( pkm , Legal . MoveSpecificMemories [ 1 ] [ matchingMoveMemory ] ) )
2016-05-07 06:16:35 +00:00
{
2016-10-23 19:48:49 +00:00
return new CheckResult ( Severity . Invalid , resultPrefix + "Memory: Species cannot learn this move." , CheckIdentifier . Memory ) ;
2016-05-07 06:16:35 +00:00
}
2016-05-09 23:09:40 +00:00
if ( m = = 6 & & ! Legal . LocationsWithPKCenter [ 0 ] . Contains ( t ) )
{
2016-10-23 19:48:49 +00:00
return new CheckResult ( Severity . Invalid , resultPrefix + "Memory: Location doesn't have a Pokemon Center." , CheckIdentifier . Memory ) ;
2016-05-09 23:09:40 +00:00
}
2016-05-10 01:19:31 +00:00
if ( m = = 21 ) // {0} saw {2} carrying {1} on its back. {4} that {3}.
{
2016-05-10 02:24:18 +00:00
if ( ! Legal . getCanLearnMachineMove ( new PK6 { Species = t , EXP = PKX . getEXP ( 100 , t ) } , 19 ) )
2016-10-23 19:48:49 +00:00
return new CheckResult ( Severity . Invalid , resultPrefix + "Memory: Argument Species cannot learn Fly." , CheckIdentifier . Memory ) ;
2016-05-10 01:19:31 +00:00
}
2016-11-09 06:10:32 +00:00
if ( ( m = = 16 | | m = = 48 ) & & ( t = = 0 | | ! Legal . getCanKnowMove ( pkm , t , GameVersion . Any ) ) )
2016-05-10 16:06:52 +00:00
{
2016-10-23 19:48:49 +00:00
return new CheckResult ( Severity . Invalid , resultPrefix + "Memory: Species cannot know this move." , CheckIdentifier . Memory ) ;
2016-05-10 16:06:52 +00:00
}
2016-11-09 06:10:32 +00:00
if ( m = = 49 & & ( t = = 0 | | ! Legal . getCanRelearnMove ( pkm , t , GameVersion . Any ) ) ) // {0} was able to remember {2} at {1}'s instruction. {4} that {3}.
2016-05-11 23:37:51 +00:00
{
2016-10-23 19:48:49 +00:00
return new CheckResult ( Severity . Invalid , resultPrefix + "Memory: Species cannot relearn this move." , CheckIdentifier . Memory ) ;
2016-05-11 23:37:51 +00:00
}
2016-10-23 19:48:49 +00:00
return new CheckResult ( Severity . Valid , resultPrefix + "Memory is valid." , CheckIdentifier . Memory ) ;
2016-05-07 06:16:35 +00:00
}
2016-10-23 19:48:49 +00:00
private void verifyOTMemory ( )
2016-05-06 03:05:22 +00:00
{
if ( ! History . Valid )
2016-10-23 19:48:49 +00:00
return ;
if ( pkm . GenNumber < 6 )
return ;
2016-05-06 03:05:22 +00:00
if ( EncounterType = = typeof ( EncounterTrade ) )
{
2016-10-23 19:48:49 +00:00
AddLine ( Severity . Valid , "OT Memory (Ingame Trade) is valid." , CheckIdentifier . Memory ) ;
return ;
2016-05-06 03:05:22 +00:00
}
if ( EncounterType = = typeof ( WC6 ) )
{
2016-06-20 04:29:38 +00:00
WC6 MatchedWC6 = EncounterMatch as WC6 ;
2016-10-23 19:48:49 +00:00
if ( pkm . OT_Memory ! = MatchedWC6 . OT_Memory )
AddLine ( Severity . Invalid , "Event " + ( MatchedWC6 . OT_Memory = = 0 ? "should not have an OT Memory" : "OT Memory should be index " + MatchedWC6 . OT_Memory ) + "." , CheckIdentifier . Memory ) ;
if ( pkm . OT_Intensity ! = MatchedWC6 . OT_Intensity )
AddLine ( Severity . Invalid , "Event " + ( MatchedWC6 . OT_Intensity = = 0 ? "should not have an OT Memory Intensity value" : "OT Memory Intensity should be index " + MatchedWC6 . OT_Intensity ) + "." , CheckIdentifier . Memory ) ;
if ( pkm . OT_TextVar ! = MatchedWC6 . OT_TextVar )
AddLine ( Severity . Invalid , "Event " + ( MatchedWC6 . OT_TextVar = = 0 ? "should not have an OT Memory TextVar value" : "OT Memory TextVar should be index " + MatchedWC6 . OT_TextVar ) + "." , CheckIdentifier . Memory ) ;
if ( pkm . OT_Feeling ! = MatchedWC6 . OT_Feeling )
AddLine ( Severity . Invalid , "Event " + ( MatchedWC6 . OT_Feeling = = 0 ? "should not have an OT Memory Feeling value" : "OT Memory Feeling should be index " + MatchedWC6 . OT_Feeling ) + "." , CheckIdentifier . Memory ) ;
2016-05-06 03:05:22 +00:00
}
2016-10-23 19:48:49 +00:00
switch ( pkm . OT_Memory )
2016-05-06 03:05:22 +00:00
{
2016-05-25 05:20:19 +00:00
case 2 : // {0} hatched from an Egg and saw {1} for the first time at... {2}. {4} that {3}.
2016-10-23 19:48:49 +00:00
if ( ! pkm . WasEgg & & pkm . Egg_Location ! = 60004 )
AddLine ( Severity . Invalid , "OT Memory: OT did not hatch this." , CheckIdentifier . Memory ) ;
break ;
2016-05-06 03:05:22 +00:00
case 4 : // {0} became {1}’ s friend when it arrived via Link Trade at... {2}. {4} that {3}.
2016-10-23 19:48:49 +00:00
AddLine ( Severity . Invalid , "OT Memory: Link Trade is not a valid first memory." , CheckIdentifier . Memory ) ;
return ;
2016-05-09 23:09:40 +00:00
case 6 : // {0} went to the Pokémon Center in {2} with {1} and had its tired body healed there. {4} that {3}.
2016-10-23 19:48:49 +00:00
int matchingOriginGame = Array . IndexOf ( Legal . LocationsWithPKCenter [ 0 ] , pkm . OT_TextVar ) ;
2016-05-10 00:51:35 +00:00
if ( matchingOriginGame ! = - 1 )
{
int gameID = Legal . LocationsWithPKCenter [ 1 ] [ matchingOriginGame ] ;
2016-10-23 19:48:49 +00:00
if ( pkm . XY & & gameID ! = 0 | | pkm . AO & & gameID ! = 1 )
AddLine ( Severity . Invalid , "OT Memory: Location doesn't exist on Origin Game region." , CheckIdentifier . Memory ) ;
2016-05-10 00:51:35 +00:00
}
2016-10-23 19:48:49 +00:00
AddLine ( verifyCommonMemory ( 0 ) ) ;
return ;
2016-05-06 03:35:18 +00:00
case 14 :
2016-11-09 06:10:32 +00:00
if ( ! Legal . getCanBeCaptured ( pkm . OT_TextVar , pkm . GenNumber , ( GameVersion ) pkm . Version ) )
2016-10-23 19:48:49 +00:00
AddLine ( Severity . Invalid , "OT Memory: Captured Species can not be captured in game." , CheckIdentifier . Memory ) ;
else
AddLine ( Severity . Valid , "OT Memory: Captured Species can be captured in game." , CheckIdentifier . Memory ) ;
return ;
2016-05-06 03:05:22 +00:00
}
2016-10-23 19:48:49 +00:00
if ( pkm . XY & & Legal . Memory_NotXY . Contains ( pkm . OT_Memory ) )
AddLine ( Severity . Invalid , "OT Memory: OR/AS exclusive memory on X/Y origin." , CheckIdentifier . Memory ) ;
if ( pkm . AO & & Legal . Memory_NotAO . Contains ( pkm . OT_Memory ) )
AddLine ( Severity . Invalid , "OT Memory: X/Y exclusive memory on OR/AS origin." , CheckIdentifier . Memory ) ;
2016-05-06 03:05:22 +00:00
2016-10-23 19:48:49 +00:00
AddLine ( verifyCommonMemory ( 0 ) ) ;
2016-05-06 03:05:22 +00:00
}
2016-10-23 19:48:49 +00:00
private void verifyHTMemory ( )
2016-05-06 03:05:22 +00:00
{
2016-10-23 19:48:49 +00:00
if ( pkm . Format < 6 )
return ;
2016-05-06 03:05:22 +00:00
if ( ! History . Valid )
2016-10-23 19:48:49 +00:00
return ;
2016-05-06 03:05:22 +00:00
2016-10-23 19:48:49 +00:00
switch ( pkm . HT_Memory )
2016-05-06 03:05:22 +00:00
{
case 1 : // {0} met {1} at... {2}. {1} threw a Poké Ball at it, and they started to travel together. {4} that {3}.
2016-10-23 19:48:49 +00:00
AddLine ( Severity . Invalid , "HT Memory: Handling Trainer did not capture this." , CheckIdentifier . Memory ) ; return ;
2016-05-06 03:05:22 +00:00
case 2 : // {0} hatched from an Egg and saw {1} for the first time at... {2}. {4} that {3}.
2016-10-23 19:48:49 +00:00
AddLine ( Severity . Invalid , "HT Memory: Handling Trainer did not hatch this." , CheckIdentifier . Memory ) ; return ;
2016-05-06 03:35:18 +00:00
case 14 :
2016-10-24 05:03:19 +00:00
if ( ! Legal . getCanBeCaptured ( pkm . HT_TextVar , pkm . GenNumber ) )
2016-10-23 19:48:49 +00:00
AddLine ( Severity . Invalid , "HT Memory: Captured Species can not be captured in game." , CheckIdentifier . Memory ) ;
else
AddLine ( Severity . Valid , "HT Memory: Captured Species can be captured in game." , CheckIdentifier . Memory ) ;
return ;
2016-05-06 03:05:22 +00:00
}
2016-10-23 19:48:49 +00:00
AddLine ( verifyCommonMemory ( 1 ) ) ;
2016-05-06 03:05:22 +00:00
}
2016-10-23 19:48:49 +00:00
private void verifyRegion ( )
2016-05-11 23:20:31 +00:00
{
2016-10-23 19:48:49 +00:00
if ( pkm . Format < 6 )
return ;
bool pass ;
switch ( pkm . ConsoleRegion )
2016-05-11 23:20:31 +00:00
{
2016-05-12 04:18:05 +00:00
case 0 : // Japan
2016-10-23 19:48:49 +00:00
pass = pkm . Country = = 1 ;
2016-05-11 23:20:31 +00:00
break ;
2016-05-12 04:18:05 +00:00
case 1 : // Americas
2016-10-23 19:48:49 +00:00
pass = 8 < = pkm . Country & & pkm . Country < = 52 | | new [ ] { 153 , 156 , 168 , 174 , 186 } . Contains ( pkm . Country ) ;
2016-05-11 23:20:31 +00:00
break ;
2016-05-12 04:18:05 +00:00
case 2 : // Europe
2016-10-23 19:48:49 +00:00
pass = 64 < = pkm . Country & & pkm . Country < = 127 | | new [ ] { 169 , 184 , 185 } . Contains ( pkm . Country ) ;
2016-05-11 23:20:31 +00:00
break ;
2016-05-12 04:18:05 +00:00
case 4 : // China
2016-10-23 19:48:49 +00:00
pass = pkm . Country = = 144 | | pkm . Country = = 160 ;
2016-05-11 23:20:31 +00:00
break ;
2016-05-12 04:18:05 +00:00
case 5 : // Korea
2016-10-23 19:48:49 +00:00
pass = pkm . Country = = 136 ;
2016-05-11 23:20:31 +00:00
break ;
2016-05-12 04:18:05 +00:00
case 6 : // Taiwan
2016-10-23 19:48:49 +00:00
pass = pkm . Country = = 128 ;
2016-05-11 23:20:31 +00:00
break ;
2016-10-23 19:48:49 +00:00
default :
AddLine ( new CheckResult ( Severity . Invalid , "Invalid Console Region." , CheckIdentifier . Geography ) ) ;
return ;
2016-05-11 23:20:31 +00:00
}
2016-10-23 19:48:49 +00:00
if ( ! pass )
AddLine ( Severity . Invalid , "Geolocation: Country is not in 3DS region." , CheckIdentifier . Geography ) ;
else
AddLine ( Severity . Valid , "Geolocation: Country is in 3DS region." , CheckIdentifier . Geography ) ;
2016-05-11 23:20:31 +00:00
}
2016-10-23 19:48:49 +00:00
private void verifyForm ( )
2016-04-14 10:17:03 +00:00
{
if ( ! Encounter . Valid )
2016-10-23 19:48:49 +00:00
return ;
2016-04-14 10:17:03 +00:00
2016-10-23 19:48:49 +00:00
if ( pkm . Format < 4 )
return ;
2016-11-09 05:43:22 +00:00
if ( pkm . AltForm > pkm . PersonalInfo . FormeCount )
{
2016-11-14 15:33:39 +00:00
bool valid = false ;
int species = pkm . Species ;
if ( species = = 201 ) // Unown
{
if ( pkm . GenNumber = = 2 & & pkm . AltForm < 26 ) // A-Z
valid = true ;
else if ( pkm . GenNumber > = 3 & & pkm . AltForm > = 28 ) // A-Z?!
valid = true ;
}
if ( species = = 414 & & pkm . AltForm < 3 ) // Wormadam base form kept
valid = true ;
if ( ( species = = 664 | | species = = 665 ) & & pkm . AltForm < 18 ) // Vivillon Pre-evolutions
valid = true ;
if ( ! valid ) // ignore list
{ AddLine ( Severity . Invalid , $"Form Count is out of range. Expected <= {pkm.PersonalInfo.FormeCount}, got {pkm.AltForm}" , CheckIdentifier . Form ) ; return ; }
2016-11-09 05:43:22 +00:00
}
2016-10-23 19:48:49 +00:00
switch ( pkm . Species )
2016-04-14 10:17:03 +00:00
{
2016-11-14 02:25:33 +00:00
case 25 : // Pikachu
2016-10-23 19:48:49 +00:00
if ( pkm . Format = = 6 & & pkm . AltForm ! = 0 ^ EncounterType = = typeof ( EncounterStatic ) )
{
if ( EncounterType = = typeof ( EncounterStatic ) )
AddLine ( Severity . Invalid , "Cosplay Pikachu cannot have the default form." , CheckIdentifier . Form ) ;
else
AddLine ( Severity . Invalid , "Only Cosplay Pikachu can have this form." , CheckIdentifier . Form ) ;
return ;
}
2016-11-09 07:37:53 +00:00
if ( pkm . Format = = 7 & & pkm . AltForm ! = 0 ^ EncounterIsMysteryGift )
2016-10-23 19:48:49 +00:00
{
2016-11-14 02:25:33 +00:00
var gift = EncounterMatch as WC7 ;
2016-10-23 19:48:49 +00:00
if ( gift ! = null & & gift . Form ! = pkm . AltForm )
{
AddLine ( Severity . Invalid , "Event Pikachu cannot have the default form." , CheckIdentifier . Form ) ;
return ;
}
}
2016-04-23 21:16:12 +00:00
break ;
2016-11-14 02:25:33 +00:00
case 658 : // Greninja
2016-11-09 05:43:22 +00:00
if ( pkm . AltForm > 1 ) // Ash Battle Bond active
{
AddLine ( Severity . Invalid , "Form cannot exist outside of a battle." , CheckIdentifier . Form ) ;
return ;
}
break ;
2016-11-14 02:25:33 +00:00
case 664 : // Scatterbug
case 665 : // Spewpa
2016-10-23 19:48:49 +00:00
if ( pkm . AltForm > 17 ) // Fancy & Pokéball
{
AddLine ( Severity . Invalid , "Event Vivillon pattern on pre-evolution." , CheckIdentifier . Form ) ;
return ;
}
2016-04-14 10:17:03 +00:00
break ;
2016-11-14 02:25:33 +00:00
case 666 : // Vivillon
2016-10-23 19:48:49 +00:00
if ( pkm . AltForm > 17 ) // Fancy & Pokéball
{
2016-11-09 07:37:53 +00:00
if ( ! EncounterIsMysteryGift )
2016-10-23 19:48:49 +00:00
AddLine ( Severity . Invalid , "Invalid Vivillon pattern." , CheckIdentifier . Form ) ;
else
AddLine ( Severity . Valid , "Valid Vivillon pattern." , CheckIdentifier . Form ) ;
return ;
}
2016-04-14 10:17:03 +00:00
break ;
2016-11-14 02:25:33 +00:00
case 670 : // Floette
2016-10-23 19:48:49 +00:00
if ( pkm . AltForm = = 5 ) // Eternal Flower -- Never Released
{
2016-11-09 07:37:53 +00:00
if ( ! EncounterIsMysteryGift )
2016-10-23 19:48:49 +00:00
AddLine ( Severity . Invalid , "Invalid Eternal Flower encounter." , CheckIdentifier . Form ) ;
else
AddLine ( Severity . Valid , "Valid Eternal Flower encounter." , CheckIdentifier . Form ) ;
return ;
}
2016-04-14 10:17:03 +00:00
break ;
2016-11-14 02:25:33 +00:00
case 718 : // Zygarde
2016-11-09 05:43:22 +00:00
if ( pkm . AltForm > = 4 )
{
AddLine ( Severity . Invalid , "Form cannot exist outside of a battle." , CheckIdentifier . Form ) ;
return ;
}
break ;
2016-11-14 02:25:33 +00:00
case 774 : // Minior
if ( pkm . AltForm < 7 )
2016-11-09 05:43:22 +00:00
{
AddLine ( Severity . Invalid , "Form cannot exist outside of a battle." , CheckIdentifier . Form ) ;
return ;
}
break ;
2016-04-14 10:17:03 +00:00
}
2016-11-14 02:19:09 +00:00
2016-11-14 05:54:11 +00:00
if ( pkm . Format > = 7 & & pkm . GenNumber < 7 & & pkm . AltForm ! = 0 & & Legal . AlolanOriginForms . Contains ( pkm . Species ) )
2016-11-14 02:19:09 +00:00
{ AddLine ( Severity . Invalid , "Form cannot be obtained for pre-Alola generation games." , CheckIdentifier . Form ) ; return ; }
2016-10-23 19:48:49 +00:00
if ( pkm . AltForm > 0 & & new [ ] { Legal . BattleForms , Legal . BattleMegas , Legal . BattlePrimals } . Any ( arr = > arr . Contains ( pkm . Species ) ) )
{ AddLine ( Severity . Invalid , "Form cannot exist outside of a battle." , CheckIdentifier . Form ) ; return ; }
2016-04-14 10:17:03 +00:00
2016-10-23 19:48:49 +00:00
AddLine ( Severity . Valid , "Form is Valid." , CheckIdentifier . Form ) ;
2016-04-14 10:17:03 +00:00
}
2016-10-23 19:48:49 +00:00
private void verifyMisc ( )
2016-04-22 02:32:22 +00:00
{
2016-10-23 19:48:49 +00:00
if ( pkm . IsEgg )
2016-09-03 15:10:22 +00:00
{
2016-10-23 19:48:49 +00:00
if ( new [ ] { pkm . Move1_PPUps , pkm . Move2_PPUps , pkm . Move3_PPUps , pkm . Move4_PPUps } . Any ( ppup = > ppup > 0 ) )
{ AddLine ( Severity . Invalid , "Cannot apply PP Ups to an Egg." , CheckIdentifier . Misc ) ; return ; }
if ( pkm . CNTs . Any ( stat = > stat > 0 ) )
{ AddLine ( Severity . Invalid , "Cannot increase Contest Stats of an Egg." , CheckIdentifier . Misc ) ; return ; }
2016-09-03 15:10:22 +00:00
}
2016-11-09 07:37:53 +00:00
if ( Encounter . Valid & & EncounterIsMysteryGift ^ pkm . FatefulEncounter )
2016-04-22 02:32:22 +00:00
{
2016-11-13 17:37:28 +00:00
if ( EncounterType = = typeof ( EncounterStatic ) )
{
var enc = EncounterMatch as EncounterStatic ;
if ( enc . Fateful )
AddLine ( Severity . Valid , "Special ingame Fateful Encounter." , CheckIdentifier . Fateful ) ;
return ;
}
AddLine ( Severity . Invalid , "Fateful Encounter should " + ( pkm . FatefulEncounter ? "not " : "" ) + "be checked." , CheckIdentifier . Fateful ) ;
return ;
2016-04-22 02:32:22 +00:00
}
2016-11-13 17:37:28 +00:00
AddLine ( Severity . Valid , "Fateful Encounter is Valid." , CheckIdentifier . Fateful ) ;
2016-04-22 02:32:22 +00:00
}
2016-10-23 19:48:49 +00:00
private CheckResult [ ] verifyMoves ( )
2016-03-12 17:16:41 +00:00
{
2016-10-23 19:48:49 +00:00
int [ ] Moves = pkm . Moves ;
CheckResult [ ] res = new CheckResult [ 4 ] ;
2016-03-12 17:16:41 +00:00
for ( int i = 0 ; i < 4 ; i + + )
2016-10-23 19:48:49 +00:00
res [ i ] = new CheckResult ( CheckIdentifier . Move ) ;
2016-11-08 16:43:57 +00:00
if ( pkm . GenNumber < 6 )
2016-03-12 17:16:41 +00:00
return res ;
2016-10-23 19:48:49 +00:00
var validMoves = Legal . getValidMoves ( pkm ) . ToArray ( ) ;
if ( pkm . Species = = 235 ) // Smeargle
2016-03-12 17:16:41 +00:00
{
for ( int i = 0 ; i < 4 ; i + + )
res [ i ] = Legal . InvalidSketch . Contains ( Moves [ i ] )
2016-10-23 19:48:49 +00:00
? new CheckResult ( Severity . Invalid , "Invalid Sketch move." , CheckIdentifier . Move )
: new CheckResult ( CheckIdentifier . Move ) ;
2016-03-12 17:16:41 +00:00
}
2016-10-23 19:48:49 +00:00
else if ( EventGiftMatch ? . Count > 1 ) // Multiple possible Mystery Gifts matched
2016-04-16 18:35:16 +00:00
{
2016-10-23 19:48:49 +00:00
int [ ] RelearnMoves = pkm . RelearnMoves ;
foreach ( MysteryGift mg in EventGiftMatch )
2016-04-16 18:35:16 +00:00
{
for ( int i = 0 ; i < 4 ; i + + )
{
if ( Moves [ i ] = = Legal . Struggle )
2016-10-23 19:48:49 +00:00
res [ i ] = new CheckResult ( Severity . Invalid , "Invalid Move: Struggle." , CheckIdentifier . Move ) ;
2016-04-16 18:35:16 +00:00
else if ( validMoves . Contains ( Moves [ i ] ) )
2016-10-23 19:48:49 +00:00
res [ i ] = new CheckResult ( Severity . Valid , Moves [ i ] = = 0 ? "Empty" : "Level-up." , CheckIdentifier . Move ) ;
2016-04-16 18:35:16 +00:00
else if ( RelearnMoves . Contains ( Moves [ i ] ) )
2016-10-23 19:48:49 +00:00
res [ i ] = new CheckResult ( Severity . Valid , Moves [ i ] = = 0 ? "Empty" : "Relearn Move." , CheckIdentifier . Move ) { Flag = true } ;
else if ( mg . Moves . Contains ( Moves [ i ] ) )
res [ i ] = new CheckResult ( Severity . Valid , "Wonder Card Non-Relearn Move." , CheckIdentifier . Move ) ;
2016-04-16 18:35:16 +00:00
else
2016-10-23 19:48:49 +00:00
res [ i ] = new CheckResult ( Severity . Invalid , "Invalid Move." , CheckIdentifier . Move ) ;
2016-04-16 18:35:16 +00:00
}
2016-07-04 23:06:07 +00:00
if ( res . Any ( r = > ! r . Valid ) )
continue ;
2016-10-23 19:48:49 +00:00
EncounterMatch = mg ;
RelearnBase = mg . RelearnMoves ;
2016-07-04 23:06:07 +00:00
break ;
2016-04-16 18:35:16 +00:00
}
}
2016-03-12 17:16:41 +00:00
else
{
2016-10-23 19:48:49 +00:00
int [ ] RelearnMoves = pkm . RelearnMoves ;
MysteryGift MatchedGift = EncounterMatch as MysteryGift ;
int [ ] GiftMoves = MatchedGift ? . Moves ? ? new int [ 0 ] ;
2016-03-12 17:16:41 +00:00
for ( int i = 0 ; i < 4 ; i + + )
{
if ( Moves [ i ] = = Legal . Struggle )
2016-10-23 19:48:49 +00:00
res [ i ] = new CheckResult ( Severity . Invalid , "Invalid Move: Struggle." , CheckIdentifier . Move ) ;
2016-03-12 17:16:41 +00:00
else if ( validMoves . Contains ( Moves [ i ] ) )
2016-10-23 19:48:49 +00:00
res [ i ] = new CheckResult ( Severity . Valid , Moves [ i ] = = 0 ? "Empty" : "Level-up." , CheckIdentifier . Move ) ;
2016-03-12 17:16:41 +00:00
else if ( RelearnMoves . Contains ( Moves [ i ] ) )
2016-10-23 19:48:49 +00:00
res [ i ] = new CheckResult ( Severity . Valid , Moves [ i ] = = 0 ? "Empty" : "Relearn Move." , CheckIdentifier . Move ) { Flag = true } ;
else if ( GiftMoves . Contains ( Moves [ i ] ) )
res [ i ] = new CheckResult ( Severity . Valid , "Wonder Card Non-Relearn Move." , CheckIdentifier . Move ) ;
2016-03-12 17:16:41 +00:00
else
2016-10-23 19:48:49 +00:00
res [ i ] = new CheckResult ( Severity . Invalid , "Invalid Move." , CheckIdentifier . Move ) ;
2016-03-12 17:16:41 +00:00
}
}
2016-10-23 19:48:49 +00:00
if ( Moves [ 0 ] = = 0 ) // None
res [ 0 ] = new CheckResult ( Severity . Invalid , "Invalid Move." , CheckIdentifier . Move ) ;
2016-03-12 17:16:41 +00:00
2016-10-23 19:48:49 +00:00
if ( pkm . Species = = 647 ) // Keldeo
if ( pkm . AltForm = = 1 ^ pkm . Moves . Contains ( 548 ) )
res [ Math . Max ( Array . IndexOf ( pkm . Moves , 548 ) , 0 ) ] = new CheckResult ( Severity . Invalid , "Secret Sword / Resolute Keldeo Mismatch." , CheckIdentifier . Move ) ;
2016-03-15 06:54:13 +00:00
2016-03-15 06:26:51 +00:00
// Duplicate Moves Check
for ( int i = 0 ; i < 4 ; i + + )
if ( Moves . Count ( m = > m ! = 0 & & m = = Moves [ i ] ) > 1 )
2016-10-23 19:48:49 +00:00
res [ i ] = new CheckResult ( Severity . Invalid , "Duplicate Move." , CheckIdentifier . Move ) ;
2016-03-15 06:26:51 +00:00
2016-03-12 17:16:41 +00:00
return res ;
}
2016-10-23 19:48:49 +00:00
private CheckResult [ ] verifyRelearn ( )
2016-03-12 17:16:41 +00:00
{
2016-03-29 05:30:23 +00:00
RelearnBase = null ;
2016-10-23 19:48:49 +00:00
CheckResult [ ] res = new CheckResult [ 4 ] ;
2016-03-23 02:47:13 +00:00
2016-10-23 19:48:49 +00:00
int [ ] Moves = pkm . RelearnMoves ;
if ( pkm . GenNumber < 6 )
2016-03-12 17:16:41 +00:00
goto noRelearn ;
2016-10-24 05:03:19 +00:00
2016-10-23 19:48:49 +00:00
if ( pkm . WasLink )
2016-03-12 17:16:41 +00:00
{
2016-10-23 19:48:49 +00:00
var Link = Legal . getValidLinkGifts ( pkm ) ;
2016-03-23 05:49:46 +00:00
if ( Link = = null )
2016-03-23 02:47:13 +00:00
{
for ( int i = 0 ; i < 4 ; i + + )
2016-10-23 19:48:49 +00:00
res [ i ] = new CheckResult ( CheckIdentifier . RelearnMove ) ;
2016-03-23 02:47:13 +00:00
return res ;
}
2016-03-23 05:49:46 +00:00
EncounterMatch = Link ;
2016-03-23 02:47:13 +00:00
int [ ] moves = ( ( EncounterLink ) EncounterMatch ) . RelearnMoves ;
2016-03-25 07:10:11 +00:00
RelearnBase = moves ;
2016-03-12 17:16:41 +00:00
for ( int i = 0 ; i < 4 ; i + + )
res [ i ] = moves [ i ] ! = Moves [ i ]
2016-10-23 19:48:49 +00:00
? new CheckResult ( Severity . Invalid , $"Expected: {movelist[moves[i]]}." , CheckIdentifier . RelearnMove )
: new CheckResult ( CheckIdentifier . RelearnMove ) ;
2016-03-12 17:16:41 +00:00
return res ;
}
2016-10-23 19:48:49 +00:00
if ( pkm . WasEvent | | pkm . WasEventEgg )
2016-03-12 17:16:41 +00:00
{
// Get WC6's that match
2016-10-24 05:03:19 +00:00
EventGiftMatch = new List < MysteryGift > ( Legal . getValidGifts ( pkm ) ) ;
2016-10-23 19:48:49 +00:00
foreach ( MysteryGift mg in EventGiftMatch . ToArray ( ) )
2016-03-12 17:16:41 +00:00
{
2016-10-23 19:48:49 +00:00
int [ ] moves = mg . RelearnMoves ;
2016-03-12 17:16:41 +00:00
for ( int i = 0 ; i < 4 ; i + + )
res [ i ] = moves [ i ] ! = Moves [ i ]
2016-10-23 19:48:49 +00:00
? new CheckResult ( Severity . Invalid , $"Expected ID: {movelist[moves[i]]}." , CheckIdentifier . RelearnMove )
: new CheckResult ( Severity . Valid , $"Matched {mg.CardID}" , CheckIdentifier . RelearnMove ) ;
2016-04-16 18:35:16 +00:00
if ( res . Any ( r = > ! r . Valid ) )
2016-10-23 19:48:49 +00:00
EventGiftMatch . Remove ( mg ) ;
2016-03-12 17:16:41 +00:00
}
2016-10-23 19:48:49 +00:00
if ( EventGiftMatch . Count > 1 )
2016-04-16 18:35:16 +00:00
return res ;
2016-10-23 19:48:49 +00:00
if ( EventGiftMatch . Count = = 1 )
{ EncounterMatch = EventGiftMatch [ 0 ] ; RelearnBase = EventGiftMatch [ 0 ] . RelearnMoves ; return res ; }
2016-04-16 18:35:16 +00:00
2016-03-28 05:05:51 +00:00
EncounterMatch = EncounterType = null ;
2016-03-12 17:16:41 +00:00
goto noRelearn ; // No WC match
}
2016-10-23 19:48:49 +00:00
if ( pkm . WasEgg & & ! Legal . NoHatchFromEgg . Contains ( pkm . Species ) )
2016-03-12 17:16:41 +00:00
{
2016-10-24 05:03:19 +00:00
GameVersion [ ] Games = { GameVersion . XY } ;
switch ( pkm . GenNumber )
{
case 6 :
Games = new [ ] { GameVersion . XY , GameVersion . ORAS } ;
break ;
case 7 :
Games = new [ ] { GameVersion . SM } ;
break ;
}
2016-10-23 19:48:49 +00:00
bool checkAllGames = pkm . WasTradedEgg ;
bool splitBreed = Legal . SplitBreed . Contains ( pkm . Species ) ;
2016-03-12 17:16:41 +00:00
2016-11-12 14:10:44 +00:00
int iterate = ( checkAllGames ? Games . Length : 1 ) * ( splitBreed ? 2 : 1 ) ;
2016-03-12 17:16:41 +00:00
for ( int i = 0 ; i < iterate ; i + + )
{
int gameSource = ! checkAllGames ? - 1 : i % iterate / ( splitBreed ? 2 : 1 ) ;
int skipOption = splitBreed & & iterate / 2 < = i ? 1 : 0 ;
2016-10-24 05:03:19 +00:00
GameVersion ver = gameSource = = - 1 ? GameVersion . Any : Games [ gameSource ] ;
2016-03-12 17:16:41 +00:00
2016-03-12 22:07:57 +00:00
// Obtain level1 moves
2016-10-24 05:03:19 +00:00
List < int > baseMoves = new List < int > ( Legal . getBaseEggMoves ( pkm , skipOption , ver ) ) ;
2016-03-12 18:35:17 +00:00
int baseCt = baseMoves . Count ;
if ( baseCt > 4 ) baseCt = 4 ;
2016-03-12 22:07:57 +00:00
2016-03-12 17:16:41 +00:00
// Obtain Nonstandard moves
2016-10-23 19:48:49 +00:00
var relearnMoves = Legal . getValidRelearn ( pkm , skipOption ) . ToArray ( ) ;
var relearn = pkm . RelearnMoves . Where ( move = > move ! = 0
2016-03-12 22:07:57 +00:00
& & ( ! baseMoves . Contains ( move ) | | relearnMoves . Contains ( move ) )
) . ToArray ( ) ;
2016-03-12 17:16:41 +00:00
int relearnCt = relearn . Length ;
2016-03-12 22:07:57 +00:00
2016-03-12 18:35:17 +00:00
// Get Move Window
List < int > window = new List < int > ( baseMoves ) ;
window . AddRange ( relearn ) ;
int [ ] moves = window . Skip ( baseCt + relearnCt - 4 ) . Take ( 4 ) . ToArray ( ) ;
2016-03-12 17:16:41 +00:00
Array . Resize ( ref moves , 4 ) ;
2016-11-08 16:43:57 +00:00
int reqBase ;
int unique = baseMoves . Concat ( relearn ) . Distinct ( ) . Count ( ) ;
2016-03-12 18:35:17 +00:00
if ( relearnCt = = 4 )
2016-11-08 16:43:57 +00:00
reqBase = 0 ;
2016-03-12 18:35:17 +00:00
else if ( baseCt + relearnCt > 4 )
2016-11-08 16:43:57 +00:00
reqBase = 4 - relearnCt ;
2016-03-12 18:35:17 +00:00
else
2016-11-08 16:43:57 +00:00
reqBase = baseCt ;
if ( pkm . RelearnMoves . Where ( m = > m ! = 0 ) . Count ( ) < Math . Min ( 4 , baseMoves . Count ) )
reqBase = Math . Min ( 4 , unique ) ;
2016-03-12 17:16:41 +00:00
// Movepool finalized! Check validity.
2016-10-23 19:48:49 +00:00
int [ ] rl = pkm . RelearnMoves ;
2016-04-07 01:13:43 +00:00
string em = string . Join ( ", " , baseMoves . Select ( r = > r > = movelist . Length ? "ERROR" : movelist [ r ] ) ) ;
2016-03-25 07:10:11 +00:00
RelearnBase = baseMoves . ToArray ( ) ;
2016-03-12 17:16:41 +00:00
// Base Egg Move
2016-11-08 16:43:57 +00:00
for ( int j = 0 ; j < reqBase ; j + + )
2016-04-07 01:13:43 +00:00
{
if ( baseMoves . Contains ( rl [ j ] ) )
2016-10-23 19:48:49 +00:00
res [ j ] = new CheckResult ( Severity . Valid , "Base egg move." , CheckIdentifier . RelearnMove ) ;
2016-04-07 01:13:43 +00:00
else
{
2016-10-23 19:48:49 +00:00
res [ j ] = new CheckResult ( Severity . Invalid , "Base egg move missing." , CheckIdentifier . RelearnMove ) ;
2016-11-08 16:43:57 +00:00
for ( int f = j + 1 ; f < reqBase ; f + + )
2016-10-23 19:48:49 +00:00
res [ f ] = new CheckResult ( Severity . Invalid , "Base egg move missing." , CheckIdentifier . RelearnMove ) ;
2016-11-08 16:43:57 +00:00
res [ reqBase - 1 ] . Comment + = $"{Environment.NewLine}Expected the following Relearn Moves: {em}." ;
2016-04-07 01:13:43 +00:00
break ;
}
}
2016-03-12 17:16:41 +00:00
// Non-Base
2016-10-23 19:48:49 +00:00
if ( Legal . LightBall . Contains ( pkm . Species ) )
2016-03-12 22:07:57 +00:00
relearnMoves = relearnMoves . Concat ( new [ ] { 344 } ) . ToArray ( ) ;
2016-11-08 16:43:57 +00:00
for ( int j = reqBase ; j < 4 ; j + + )
2016-03-12 17:16:41 +00:00
res [ j ] = ! relearnMoves . Contains ( rl [ j ] )
2016-10-23 19:48:49 +00:00
? new CheckResult ( Severity . Invalid , "Not an expected relearn move." , CheckIdentifier . RelearnMove )
: new CheckResult ( Severity . Valid , rl [ j ] = = 0 ? "Empty" : "Relearn move." , CheckIdentifier . RelearnMove ) ;
2016-03-12 17:16:41 +00:00
if ( res . All ( r = > r . Valid ) )
break ;
}
return res ;
}
if ( Moves [ 0 ] ! = 0 ) // DexNav only?
{
// Check DexNav
2016-10-23 19:48:49 +00:00
if ( ! Legal . getDexNavValid ( pkm ) )
2016-03-12 17:16:41 +00:00
goto noRelearn ;
2016-10-23 19:48:49 +00:00
res [ 0 ] = ! Legal . getValidRelearn ( pkm , 0 ) . Contains ( Moves [ 0 ] )
? new CheckResult ( Severity . Invalid , "Not an expected DexNav move." , CheckIdentifier . RelearnMove )
: new CheckResult ( CheckIdentifier . RelearnMove ) ;
2016-03-12 17:16:41 +00:00
for ( int i = 1 ; i < 4 ; i + + )
res [ i ] = Moves [ i ] ! = 0
2016-10-23 19:48:49 +00:00
? new CheckResult ( Severity . Invalid , "Expected no Relearn Move in slot." , CheckIdentifier . RelearnMove )
: new CheckResult ( CheckIdentifier . RelearnMove ) ;
2016-03-12 17:16:41 +00:00
2016-03-25 07:10:11 +00:00
if ( res [ 0 ] . Valid )
RelearnBase = new [ ] { Moves [ 0 ] , 0 , 0 , 0 } ;
2016-03-12 17:16:41 +00:00
return res ;
}
// Should have no relearn moves.
noRelearn :
for ( int i = 0 ; i < 4 ; i + + )
res [ i ] = Moves [ i ] ! = 0
2016-10-23 19:48:49 +00:00
? new CheckResult ( Severity . Invalid , "Expected no Relearn Moves." , CheckIdentifier . RelearnMove )
: new CheckResult ( CheckIdentifier . RelearnMove ) ;
2016-03-12 17:16:41 +00:00
return res ;
}
2016-03-23 02:47:13 +00:00
2016-08-08 20:11:02 +00:00
internal static string [ ] movelist = Util . getMovesList ( "en" ) ;
2016-03-26 03:39:31 +00:00
private static readonly string [ ] EventRibName =
2016-03-23 02:47:13 +00:00
{
"Country" , "National" , "Earth" , "World" , "Classic" ,
"Premier" , "Event" , "Birthday" , "Special" , "Souvenir" ,
"Wishing" , "Battle Champ" , "Regional Champ" , "National Champ" , "World Champ"
} ;
2016-03-11 04:36:32 +00:00
}
}