mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-15 00:37:11 +00:00
e29cf2a903
Checks.cs initially started out small, but over the years it has grown to handle multiple types of checks. With all these checks next to eachother, it's hard to see the overall groups. Splitting them up (potentially further?) allows for more focused maintenance & understanding. Not sure if I'm happy with the overall bandaids used (checks no longer done within LegalityAnalysis so variable repointing is excessively used), but I'm happier the way it is now compared to the huge Checks.cs
127 lines
4.8 KiB
C#
127 lines
4.8 KiB
C#
using System;
|
|
using static PKHeX.Core.LegalityCheckStrings;
|
|
|
|
namespace PKHeX.Core
|
|
{
|
|
public class PIDVerifier : Verifier
|
|
{
|
|
protected override CheckIdentifier Identifier => CheckIdentifier.PID;
|
|
|
|
public override void Verify(LegalityAnalysis data)
|
|
{
|
|
var pkm = data.pkm;
|
|
if (pkm.Format >= 6)
|
|
VerifyEC(data);
|
|
|
|
var EncounterMatch = data.EncounterMatch;
|
|
if (EncounterMatch.Species == 265)
|
|
VerifyECPIDWurmple(data);
|
|
|
|
if (pkm.PID == 0)
|
|
data.AddLine(Get(V207, Severity.Fishy));
|
|
|
|
var Info = data.Info;
|
|
if ((Info.Generation >= 6 || Info.Generation < 3 && pkm.Format >= 7) && pkm.PID == pkm.EncryptionConstant)
|
|
data.AddLine(GetInvalid(V208)); // better to flag than 1:2^32 odds since RNG is not feasible to yield match
|
|
|
|
VerifyShiny(data);
|
|
}
|
|
|
|
private void VerifyShiny(LegalityAnalysis data)
|
|
{
|
|
var pkm = data.pkm;
|
|
var Info = data.Info;
|
|
|
|
switch (data.EncounterMatch)
|
|
{
|
|
case EncounterStatic s:
|
|
if (!s.Shiny.IsValid(pkm))
|
|
data.AddLine(GetInvalid(V209, CheckIdentifier.Shiny));
|
|
|
|
// gen5 correlation
|
|
if (Info.Generation != 5)
|
|
break;
|
|
if (s.Location == 75) // Entree Forest
|
|
break;
|
|
if (s.Gift || s.Roaming || s.Ability != 4)
|
|
break;
|
|
if (s is EncounterStaticPID p && p.NSparkle)
|
|
break;
|
|
VerifyG5PID_IDCorrelation(data);
|
|
break;
|
|
|
|
case EncounterSlot w:
|
|
if (pkm.IsShiny && w.Type == SlotType.HiddenGrotto)
|
|
data.AddLine(GetInvalid(V221, CheckIdentifier.Shiny));
|
|
if (Info.Generation == 5 && w.Type != SlotType.HiddenGrotto)
|
|
VerifyG5PID_IDCorrelation(data);
|
|
break;
|
|
|
|
case PCD d: // fixed PID
|
|
if (d.Gift.PK.PID != 1 && pkm.EncryptionConstant != d.Gift.PK.PID)
|
|
data.AddLine(GetInvalid(V410, CheckIdentifier.Shiny));
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void VerifyG5PID_IDCorrelation(LegalityAnalysis data)
|
|
{
|
|
var pkm = data.pkm;
|
|
var pid = pkm.EncryptionConstant;
|
|
var result = (pid & 1) ^ (pid >> 31) ^ (pkm.TID & 1) ^ (pkm.SID & 1);
|
|
if (result != 0)
|
|
data.AddLine(GetInvalid(V411));
|
|
}
|
|
private void VerifyECPIDWurmple(LegalityAnalysis data)
|
|
{
|
|
var pkm = data.pkm;
|
|
uint evoVal = PKX.GetWurmpleEvoVal(pkm.EncryptionConstant);
|
|
|
|
if (pkm.Species == 265)
|
|
{
|
|
var spec = evoVal == 0 ? LegalityAnalysis.SpeciesStrings[267] : LegalityAnalysis.SpeciesStrings[269];
|
|
var msg = string.Format(V212, spec);
|
|
data.AddLine(GetValid(msg, CheckIdentifier.EC));
|
|
}
|
|
else if (evoVal != Array.IndexOf(Legal.WurmpleEvolutions, pkm.Species) / 2)
|
|
{
|
|
data.AddLine(GetInvalid(V210, CheckIdentifier.EC));
|
|
}
|
|
}
|
|
private void VerifyEC(LegalityAnalysis data)
|
|
{
|
|
var pkm = data.pkm;
|
|
var Info = data.Info;
|
|
|
|
if (pkm.EncryptionConstant == 0)
|
|
data.AddLine(Get(V201, Severity.Fishy, CheckIdentifier.EC));
|
|
if (3 <= Info.Generation && Info.Generation <= 5)
|
|
VerifyTransferEC(data);
|
|
else
|
|
{
|
|
int xor = pkm.TSV ^ pkm.PSV;
|
|
if (xor < 16 && xor >= 8 && (pkm.PID ^ 0x80000000) == pkm.EncryptionConstant)
|
|
data.AddLine(Get(V211, Severity.Fishy, CheckIdentifier.EC));
|
|
}
|
|
}
|
|
private void VerifyTransferEC(LegalityAnalysis data)
|
|
{
|
|
var pkm = data.pkm;
|
|
// 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.
|
|
bool xorPID = ((pkm.TID ^ pkm.SID ^ (int)(pkm.PID & 0xFFFF) ^ (int)(pkm.PID >> 16)) & ~0x7) == 8;
|
|
bool valid = xorPID
|
|
? pkm.EncryptionConstant == (pkm.PID ^ 0x80000000)
|
|
: pkm.EncryptionConstant == pkm.PID;
|
|
|
|
if (valid)
|
|
return;
|
|
|
|
var msg = xorPID ? V215 : V216;
|
|
data.AddLine(GetInvalid(msg, CheckIdentifier.EC));
|
|
}
|
|
}
|
|
}
|