mirror of
https://github.com/kwsch/PKHeX
synced 2025-02-25 20:07:09 +00:00
Fix legality issues (#1055)
* Added method getBaseEggSpecies to get the base species when the pokemon was an egg, is needed because for format 1 pokemon with egg origin every time getBaseSpecies is called is returning the gen 1 base species obtaining invalid eggmoves and base egg moves Also getBaseEggSpecies was using Evolves1 when format = 1 even when asking for a gen2 egg base species, returning Pikachu egg moves (empty list) instead of Pichu egg moves * Fix ability checking for generation 3 pokemon, likea de Seadra from Issue #1011 pkm.AbilityNumber have a value assuming PID match ability like a generation 4 pokemon but the validation should be ignored if is a generation 3 pokemon with only one ability in generation 3 Also changed the validation for ingame trades with fixed abilities to check only with generation 3 abilities in the case the species has two abilities generation 3, if only one was possible any PID should be valid with the generation 3 ability Encounter Trades Also the check for evolution was wrong, the most evolved species is the first in the evochain, not the last * Fix evolution chains for gen 3 pokemon in format 4 * Fix ability for generation 3 trades. Ability could not change if there were 2 abilities in generation 3, that means it is irrelevant if the pokemon evolved in gen 4-5, the ability number must match the encounter
This commit is contained in:
parent
2f59710eee
commit
0af983547d
2 changed files with 40 additions and 19 deletions
|
@ -1242,8 +1242,9 @@ namespace PKHeX.Core
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EncounterMatch != null)
|
if (EncounterMatch != null && (!pkm.Gen3 || pkm.Format ==3))
|
||||||
{
|
{
|
||||||
|
// Gen 3 transfered to 4 could change ability, defer to verifyAbilityPreCapsule
|
||||||
// Check Ability Mismatches
|
// Check Ability Mismatches
|
||||||
int? EncounterAbility = (EncounterMatch as EncounterStatic)?.Ability ??
|
int? EncounterAbility = (EncounterMatch as EncounterStatic)?.Ability ??
|
||||||
(EncounterMatch as EncounterTrade)?.Ability ??
|
(EncounterMatch as EncounterTrade)?.Ability ??
|
||||||
|
@ -1262,23 +1263,24 @@ namespace PKHeX.Core
|
||||||
case 7: verifyAbility7(abilities); break;
|
case 7: verifyAbility7(abilities); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var AbilityMatchPID = true;
|
||||||
if (3 <= pkm.Format && pkm.Format <= 5) // 3-5
|
if (3 <= pkm.Format && pkm.Format <= 5) // 3-5
|
||||||
verifyAbilityPreCapsule(abilities, abilval);
|
AbilityMatchPID = verifyAbilityPreCapsule(abilities, abilval);
|
||||||
|
|
||||||
if (3 <= pkm.GenNumber && pkm.GenNumber <= 4 && pkm.AbilityNumber == 4)
|
if (3 <= pkm.GenNumber && pkm.GenNumber <= 4 && pkm.AbilityNumber == 4)
|
||||||
AddLine(Severity.Invalid, V112, CheckIdentifier.Ability);
|
AddLine(Severity.Invalid, V112, CheckIdentifier.Ability);
|
||||||
else if (abilities[pkm.AbilityNumber >> 1] != pkm.Ability)
|
else if (AbilityMatchPID && abilities[pkm.AbilityNumber >> 1] != pkm.Ability)
|
||||||
AddLine(Severity.Invalid, V114, CheckIdentifier.Ability);
|
AddLine(Severity.Invalid, V114, CheckIdentifier.Ability);
|
||||||
else
|
else
|
||||||
AddLine(Severity.Valid, V115, CheckIdentifier.Ability);
|
AddLine(Severity.Valid, V115, CheckIdentifier.Ability);
|
||||||
}
|
}
|
||||||
private void verifyAbilityPreCapsule(int[] abilities, int abilval)
|
private bool verifyAbilityPreCapsule(int[] abilities, int abilval)
|
||||||
{
|
{
|
||||||
if (pkm.Version == (int)GameVersion.CXD)
|
if (pkm.Version == (int)GameVersion.CXD)
|
||||||
{
|
{
|
||||||
// TODO for GameCube analysis
|
// TODO for GameCube analysis
|
||||||
AddLine(Severity.Valid, V115, CheckIdentifier.Ability);
|
AddLine(Severity.Valid, V115, CheckIdentifier.Ability);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var abilities_count = abilities.Distinct().Count();
|
var abilities_count = abilities.Distinct().Count();
|
||||||
|
@ -1288,7 +1290,7 @@ namespace PKHeX.Core
|
||||||
// gen3Species will be zero for pokemon with illegal gen 3 encounters, like Infernape with gen 3 "origin"
|
// gen3Species will be zero for pokemon with illegal gen 3 encounters, like Infernape with gen 3 "origin"
|
||||||
// Do not check for gen 3 pokemon that has evolved into gen 4 species,
|
// Do not check for gen 3 pokemon that has evolved into gen 4 species,
|
||||||
// those have evolved in generation 4 or 5 and ability must match PID, not need to check gen 3 data
|
// those have evolved in generation 4 or 5 and ability must match PID, not need to check gen 3 data
|
||||||
var gen3Species = EvoChainsAllGens[3].LastOrDefault()?.Species ?? 0;
|
var gen3Species = EvoChainsAllGens[3].FirstOrDefault()?.Species ?? 0;
|
||||||
if (gen3Species > 0)
|
if (gen3Species > 0)
|
||||||
AbilityMatchPID = verifyAbilityGen3Transfer(abilities, abilval, gen3Species, abilities_count);
|
AbilityMatchPID = verifyAbilityGen3Transfer(abilities, abilval, gen3Species, abilities_count);
|
||||||
}
|
}
|
||||||
|
@ -1296,6 +1298,7 @@ namespace PKHeX.Core
|
||||||
// Gen 4,5 pokemon or gen 3 pokemon evolved in gen 4,5 games, ability must match PID
|
// Gen 4,5 pokemon or gen 3 pokemon evolved in gen 4,5 games, ability must match PID
|
||||||
if (AbilityMatchPID && pkm.AbilityNumber != 1 << abilval)
|
if (AbilityMatchPID && pkm.AbilityNumber != 1 << abilval)
|
||||||
AddLine(Severity.Invalid, V113, CheckIdentifier.Ability);
|
AddLine(Severity.Invalid, V113, CheckIdentifier.Ability);
|
||||||
|
return AbilityMatchPID;
|
||||||
}
|
}
|
||||||
private bool verifyAbilityGen3Transfer(int[] abilities, int abilval, int Species_g3, int abilities_count)
|
private bool verifyAbilityGen3Transfer(int[] abilities, int abilval, int Species_g3, int abilities_count)
|
||||||
{
|
{
|
||||||
|
@ -1305,11 +1308,17 @@ namespace PKHeX.Core
|
||||||
var abilities_g3 = PersonalTable.E.getAbilities(Species_g3, pkm.AltForm).Where(a => a != 0).Distinct().ToArray();
|
var abilities_g3 = PersonalTable.E.getAbilities(Species_g3, pkm.AltForm).Where(a => a != 0).Distinct().ToArray();
|
||||||
if (abilities_g3.Length == 2)
|
if (abilities_g3.Length == 2)
|
||||||
{
|
{
|
||||||
|
int? EncounterAbility = (EncounterMatch as EncounterTrade)?.Ability ?? null;
|
||||||
|
// If there were two abilities in generation 3 then ability match PID in gen 3 (is impossible not to do it) and will be the same ability if evolved in gen 4-5
|
||||||
|
if (EncounterAbility != null && EncounterAbility != 0 && pkm.AbilityNumber != EncounterAbility)
|
||||||
|
{
|
||||||
|
AddLine(Severity.Invalid, V223, CheckIdentifier.Ability);
|
||||||
|
}
|
||||||
// Shadow Colloseum pokemon could habe any PID without maching PID if has 2 abilities in generation 3
|
// Shadow Colloseum pokemon could habe any PID without maching PID if has 2 abilities in generation 3
|
||||||
// For non-GC, it has 2 abilities in gen 3, must match PID
|
// For non-GC, it has 2 abilities in gen 3, must match PID
|
||||||
return pkm.Version != (int)GameVersion.CXD;
|
return pkm.Version != (int)GameVersion.CXD;
|
||||||
}
|
}
|
||||||
var Species_g45 = Math.Max(EvoChainsAllGens[4].LastOrDefault()?.Species ?? 0, pkm.Format == 5 ? EvoChainsAllGens[5].LastOrDefault()?.Species ?? 0 : 0);
|
var Species_g45 = Math.Max(EvoChainsAllGens[4].FirstOrDefault()?.Species ?? 0, pkm.Format == 5 ? EvoChainsAllGens[5].FirstOrDefault()?.Species ?? 0 : 0);
|
||||||
if (Species_g45 > Species_g3)
|
if (Species_g45 > Species_g3)
|
||||||
// it have evolved in gen 4 or 5 games, ability must match PID
|
// it have evolved in gen 4 or 5 games, ability must match PID
|
||||||
return true;
|
return true;
|
||||||
|
@ -2402,7 +2411,9 @@ namespace PKHeX.Core
|
||||||
encounters.AddRange(EventGiftMatch.Where(x => (x as IMoveset)?.Moves != null));
|
encounters.AddRange(EventGiftMatch.Where(x => (x as IMoveset)?.Moves != null));
|
||||||
if (null != EncounterStaticMatch)
|
if (null != EncounterStaticMatch)
|
||||||
encounters.AddRange(EncounterStaticMatch.Where(x => (x as IMoveset)?.Moves != null));
|
encounters.AddRange(EncounterStaticMatch.Where(x => (x as IMoveset)?.Moves != null));
|
||||||
if (null != (EncounterMatch as IMoveset)?.Moves)
|
if (null != (EncounterMatch as EncounterTrade))
|
||||||
|
encounters.Add(EncounterMatch);
|
||||||
|
else if (null != (EncounterMatch as IMoveset)?.Moves)
|
||||||
encounters.Add(EncounterMatch);
|
encounters.Add(EncounterMatch);
|
||||||
|
|
||||||
if (!pkm.IsEgg)
|
if (!pkm.IsEgg)
|
||||||
|
@ -2576,7 +2587,7 @@ namespace PKHeX.Core
|
||||||
{
|
{
|
||||||
for (int i = 0; i <= splitctr; i++)
|
for (int i = 0; i <= splitctr; i++)
|
||||||
{
|
{
|
||||||
var baseSpecies = Legal.getBaseSpecies(pkm, i);
|
var baseSpecies = Legal.getBaseEggSpecies(pkm, i);
|
||||||
if (baseSpecies != pkm.Species)
|
if (baseSpecies != pkm.Species)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -958,7 +958,7 @@ namespace PKHeX.Core
|
||||||
}
|
}
|
||||||
internal static IEnumerable<int> getBaseEggMoves(PKM pkm, int skipOption, GameVersion gameSource, int lvl)
|
internal static IEnumerable<int> getBaseEggMoves(PKM pkm, int skipOption, GameVersion gameSource, int lvl)
|
||||||
{
|
{
|
||||||
int species = getBaseSpecies(pkm, skipOption);
|
int species = getBaseEggSpecies(pkm, skipOption);
|
||||||
|
|
||||||
if (gameSource == GameVersion.Any)
|
if (gameSource == GameVersion.Any)
|
||||||
gameSource = (GameVersion) pkm.Version;
|
gameSource = (GameVersion) pkm.Version;
|
||||||
|
@ -1049,7 +1049,7 @@ namespace PKHeX.Core
|
||||||
}
|
}
|
||||||
internal static IEnumerable<int> getEggMoves(PKM pkm, int skipOption, GameVersion Version)
|
internal static IEnumerable<int> getEggMoves(PKM pkm, int skipOption, GameVersion Version)
|
||||||
{
|
{
|
||||||
return getEggMoves(pkm, getBaseSpecies(pkm, skipOption), 0, Version);
|
return getEggMoves(pkm, getBaseEggSpecies(pkm, skipOption), 0, Version);
|
||||||
}
|
}
|
||||||
internal static IEnumerable<EncounterStatic> getG3SpecialEggEncounter(PKM pkm)
|
internal static IEnumerable<EncounterStatic> getG3SpecialEggEncounter(PKM pkm)
|
||||||
{
|
{
|
||||||
|
@ -1606,7 +1606,7 @@ namespace PKHeX.Core
|
||||||
if (t != null && t.TID != 0)
|
if (t != null && t.TID != 0)
|
||||||
return new GBEncounterData(pkm, 2, t); // gen2 trade
|
return new GBEncounterData(pkm, 2, t); // gen2 trade
|
||||||
if (WasEgg && new[] { sm, em, tm }.Min(a => a) >= 5)
|
if (WasEgg && new[] { sm, em, tm }.Min(a => a) >= 5)
|
||||||
return new GBEncounterData(getBaseSpecies(pkm, maxSpeciesOrigin: MaxSpeciesID_2)); // gen2 egg
|
return new GBEncounterData(getBaseEggSpecies(pkm)); // gen2 egg
|
||||||
}
|
}
|
||||||
if (em <= sm && em <= tm)
|
if (em <= sm && em <= tm)
|
||||||
return new GBEncounterData(pkm, gen, e.Where(slot => slot.Species == em).OrderBy(slot => slot.LevelMin).First());
|
return new GBEncounterData(pkm, gen, e.Where(slot => slot.Species == em).OrderBy(slot => slot.LevelMin).First());
|
||||||
|
@ -1697,7 +1697,11 @@ namespace PKHeX.Core
|
||||||
// Generation Specific Fetching
|
// Generation Specific Fetching
|
||||||
private static EvolutionTree getEvolutionTable(PKM pkm)
|
private static EvolutionTree getEvolutionTable(PKM pkm)
|
||||||
{
|
{
|
||||||
switch (pkm.Format)
|
return getEvolutionTable(pkm.Format);
|
||||||
|
}
|
||||||
|
private static EvolutionTree getEvolutionTable(int generation)
|
||||||
|
{
|
||||||
|
switch (generation)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
return Evolves1;
|
return Evolves1;
|
||||||
|
@ -2283,15 +2287,21 @@ namespace PKHeX.Core
|
||||||
return true;
|
return true;
|
||||||
return getValidMoves(pkm, version, getValidPreEvolutions(pkm).ToArray(), generation, LVL: true, Relearn: true, Tutor: true, Machine: true).Contains(move);
|
return getValidMoves(pkm, version, getValidPreEvolutions(pkm).ToArray(), generation, LVL: true, Relearn: true, Tutor: true, Machine: true).Contains(move);
|
||||||
}
|
}
|
||||||
|
internal static int getBaseEggSpecies(PKM pkm, int skipOption = 0)
|
||||||
internal static int getBaseSpecies(PKM pkm, int skipOption = 0, int maxSpeciesOrigin = -1)
|
{
|
||||||
|
if (pkm.Format == 1)
|
||||||
|
return getBaseSpecies(pkm, skipOption : skipOption, generation : 2);
|
||||||
|
return getBaseSpecies(pkm, skipOption);
|
||||||
|
}
|
||||||
|
internal static int getBaseSpecies(PKM pkm, int skipOption = 0, int generation = -1)
|
||||||
{
|
{
|
||||||
if (pkm.Species == 292)
|
if (pkm.Species == 292)
|
||||||
return 290;
|
return 290;
|
||||||
if (pkm.Species == 242 && pkm.CurrentLevel < 3) // Never Cleffa
|
if (pkm.Species == 242 && pkm.CurrentLevel < 3) // Never Cleffa
|
||||||
return 113;
|
return 113;
|
||||||
|
|
||||||
var table = getEvolutionTable(pkm);
|
var table = generation != -1 ? getEvolutionTable(generation): getEvolutionTable(pkm);
|
||||||
|
int maxSpeciesOrigin = generation != -1 ? getMaxSpeciesOrigin(generation) : - 1;
|
||||||
var evos = table.getValidPreEvolutions(pkm, 100, maxSpeciesOrigin: maxSpeciesOrigin, skipChecks:true).ToArray();
|
var evos = table.getValidPreEvolutions(pkm, 100, maxSpeciesOrigin: maxSpeciesOrigin, skipChecks:true).ToArray();
|
||||||
|
|
||||||
switch (skipOption)
|
switch (skipOption)
|
||||||
|
@ -2350,7 +2360,7 @@ namespace PKHeX.Core
|
||||||
if (pkm.Format <= 2)
|
if (pkm.Format <= 2)
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
if (!pkm.HasOriginalMetLocation)
|
if (!pkm.HasOriginalMetLocation && generation != pkm.GenNumber)
|
||||||
return pkm.Met_Level;
|
return pkm.Met_Level;
|
||||||
|
|
||||||
if (pkm.GenNumber <= 3)
|
if (pkm.GenNumber <= 3)
|
||||||
|
@ -2392,7 +2402,7 @@ namespace PKHeX.Core
|
||||||
continue;
|
continue;
|
||||||
if ((pkm.Gen2 || pkm.VC2) && 3 <= gen && gen <= 6)
|
if ((pkm.Gen2 || pkm.VC2) && 3 <= gen && gen <= 6)
|
||||||
continue;
|
continue;
|
||||||
if (!pkm.HasOriginalMetLocation && pkm.Format > 2 && gen <= 4 && lvl > pkm.Met_Level)
|
if (!pkm.HasOriginalMetLocation && pkm.Format > 2 && gen < pkm.Format && gen <= 4 && lvl > pkm.Met_Level)
|
||||||
{
|
{
|
||||||
// Met location was lost at this point but it also means the pokemon existed in generations 1 to 4 with maximum level equals to met level
|
// Met location was lost at this point but it also means the pokemon existed in generations 1 to 4 with maximum level equals to met level
|
||||||
lvl = pkm.Met_Level;
|
lvl = pkm.Met_Level;
|
||||||
|
@ -2430,7 +2440,7 @@ namespace PKHeX.Core
|
||||||
//Remove previous evolutions bellow transfer level
|
//Remove previous evolutions bellow transfer level
|
||||||
//For example a gen3 charizar in format 7 with current level 36 and met level 36
|
//For example a gen3 charizar in format 7 with current level 36 and met level 36
|
||||||
//chain level for charmander is 35, is bellow met level
|
//chain level for charmander is 35, is bellow met level
|
||||||
GensEvoChains[gen] = GensEvoChains[gen].Where(e => e.Level >= lvl).ToArray();
|
GensEvoChains[gen] = GensEvoChains[gen].Where(e => e.Level >= getMinLevelGeneration(pkm,gen)).ToArray();
|
||||||
}
|
}
|
||||||
return GensEvoChains;
|
return GensEvoChains;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue