mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-23 20:43:07 +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
259 lines
10 KiB
C#
259 lines
10 KiB
C#
using System;
|
|
using System.Linq;
|
|
using static PKHeX.Core.LegalityCheckStrings;
|
|
|
|
namespace PKHeX.Core
|
|
{
|
|
public class FormVerifier : Verifier
|
|
{
|
|
protected override CheckIdentifier Identifier => CheckIdentifier.Form;
|
|
|
|
public override void Verify(LegalityAnalysis data)
|
|
{
|
|
var pkm = data.pkm;
|
|
if (pkm.Format < 4)
|
|
return; // no forms exist
|
|
|
|
var PersonalInfo = data.PersonalInfo;
|
|
var EncounterMatch = data.EncounterMatch;
|
|
var Info = data.Info;
|
|
|
|
int count = PersonalInfo.FormeCount;
|
|
if (count <= 1 && pkm.AltForm == 0)
|
|
return; // no forms to check
|
|
|
|
if (!PersonalInfo.IsFormeWithinRange(pkm.AltForm) && !FormConverter.IsValidOutOfBoundsForme(pkm.Species, pkm.AltForm, Info.Generation))
|
|
{
|
|
data.AddLine(GetInvalid(string.Format(V304, count - 1, pkm.AltForm)));
|
|
return;
|
|
}
|
|
|
|
if (EncounterMatch is EncounterSlot w && w.Type == SlotType.FriendSafari)
|
|
VerifyFormFriendSafari(data);
|
|
else if (EncounterMatch is EncounterEgg)
|
|
{
|
|
if (FormConverter.IsTotemForm(pkm.Species, pkm.AltForm))
|
|
{
|
|
data.AddLine(GetInvalid(V317));
|
|
return;
|
|
}
|
|
}
|
|
|
|
switch (pkm.Species)
|
|
{
|
|
case 25 when Info.Generation == 6: // Pikachu Cosplay
|
|
bool isStatic = EncounterMatch is EncounterStatic;
|
|
if (isStatic != (pkm.AltForm != 0))
|
|
{
|
|
string msg = isStatic ? V305 : V306;
|
|
data.AddLine(GetInvalid(msg));
|
|
return;
|
|
}
|
|
break;
|
|
case 25 when Info.Generation == 7: // Pikachu Cap
|
|
bool IsValidPikachuCap()
|
|
{
|
|
switch (EncounterMatch)
|
|
{
|
|
default: return pkm.AltForm == 0;
|
|
case WC7 wc7: return wc7.Form == pkm.AltForm;
|
|
case EncounterStatic s: return s.Form == pkm.AltForm;
|
|
}
|
|
}
|
|
|
|
if (!IsValidPikachuCap())
|
|
{
|
|
bool gift = EncounterMatch is WC7 g && g.Form != pkm.AltForm;
|
|
var msg = gift ? V307 : V317;
|
|
data.AddLine(GetInvalid(msg));
|
|
return;
|
|
}
|
|
break;
|
|
case 201 when Info.Generation == 2 && pkm.AltForm >= 26:
|
|
data.AddLine(GetInvalid(string.Format(V304, "Z", pkm.AltForm == 26 ? "!" : "?")));
|
|
break;
|
|
case 487: // Giratina
|
|
if (pkm.AltForm == 1 ^ pkm.HeldItem == 112) // Origin form only with Griseous Orb
|
|
{
|
|
data.AddLine(GetInvalid(V308));
|
|
return;
|
|
}
|
|
break;
|
|
case 493: // Arceus
|
|
{
|
|
int item = pkm.HeldItem;
|
|
int form = 0;
|
|
if (298 <= item && item <= 313 || item == 644)
|
|
form = Array.IndexOf(Legal.Arceus_Plate, item) + 1;
|
|
else if (777 <= item && item <= 793)
|
|
form = Array.IndexOf(Legal.Arceus_ZCrystal, item) + 1;
|
|
if (pkm.Format == 4 && form >= 9)
|
|
form++; // ??? type Form shifts everything by 1
|
|
|
|
if (form != pkm.AltForm)
|
|
data.AddLine(GetInvalid(V308));
|
|
else if (form != 0)
|
|
data.AddLine(GetValid(V309));
|
|
}
|
|
break;
|
|
case 647: // Keldeo
|
|
{
|
|
if (pkm.Gen5) // can mismatch in gen5 via BW tutor and transfer up
|
|
break;
|
|
int index = Array.IndexOf(pkm.Moves, 548); // Secret Sword
|
|
bool noSword = index < 0;
|
|
if (pkm.AltForm == 0 ^ noSword) // mismatch
|
|
Info.Moves[noSword ? 0 : index] = new CheckMoveResult(Info.Moves[noSword ? 0 : index], Severity.Invalid, V169, CheckIdentifier.Move);
|
|
break;
|
|
}
|
|
case 649: // Genesect
|
|
{
|
|
int item = pkm.HeldItem;
|
|
int form = 0;
|
|
if (116 <= item && item <= 119)
|
|
form = item - 115;
|
|
|
|
if (form != pkm.AltForm)
|
|
data.AddLine(GetInvalid(V308));
|
|
else
|
|
data.AddLine(GetValid(V309));
|
|
}
|
|
break;
|
|
case 658: // Greninja
|
|
if (pkm.AltForm > 1) // Ash Battle Bond active
|
|
{
|
|
data.AddLine(GetInvalid(V310));
|
|
return;
|
|
}
|
|
if (pkm.AltForm != 0 && !(EncounterMatch is MysteryGift)) // Formes are not breedable, MysteryGift already checked
|
|
{
|
|
data.AddLine(GetInvalid(string.Format(V304, 0, pkm.AltForm)));
|
|
return;
|
|
}
|
|
break;
|
|
case 664: // Scatterbug
|
|
case 665: // Spewpa
|
|
if (pkm.AltForm > 17) // Fancy & Pokéball
|
|
{
|
|
data.AddLine(GetInvalid(V311));
|
|
return;
|
|
}
|
|
if (!Legal.CheckVivillonPattern(pkm.AltForm, pkm.Country, pkm.Region))
|
|
data.AddLine(Get(V312, Severity.Fishy));
|
|
break;
|
|
case 666: // Vivillon
|
|
if (pkm.AltForm > 17) // Fancy & Pokéball
|
|
{
|
|
if (!(EncounterMatch is MysteryGift))
|
|
data.AddLine(GetInvalid(V312));
|
|
else
|
|
data.AddLine(GetValid(V313));
|
|
|
|
return;
|
|
}
|
|
if (!Legal.CheckVivillonPattern(pkm.AltForm, pkm.Country, pkm.Region))
|
|
data.AddLine(Get(V312, Severity.Fishy));
|
|
break;
|
|
case 670: // Floette
|
|
if (pkm.AltForm == 5) // Eternal Flower -- Never Released
|
|
{
|
|
if (!(EncounterMatch is MysteryGift))
|
|
data.AddLine(GetInvalid(V314));
|
|
else
|
|
data.AddLine(GetValid(V315));
|
|
|
|
return;
|
|
}
|
|
break;
|
|
case 678: // Meowstic
|
|
if (pkm.AltForm != pkm.Gender)
|
|
data.AddLine(GetInvalid(V203));
|
|
break;
|
|
case 773: // Silvally
|
|
{
|
|
int item = pkm.HeldItem;
|
|
int form = 0;
|
|
if ((904 <= item && item <= 920) || item == 644)
|
|
form = item - 903;
|
|
if (form != pkm.AltForm)
|
|
data.AddLine(GetInvalid(V308));
|
|
else if (form != 0)
|
|
data.AddLine(GetValid(V309));
|
|
break;
|
|
}
|
|
|
|
case 744 when Info.EncounterMatch.EggEncounter && pkm.AltForm == 1 && pkm.SM:
|
|
case 745 when Info.EncounterMatch.EggEncounter && pkm.AltForm == 2 && pkm.SM:
|
|
data.AddLine(GetInvalid(V317));
|
|
return;
|
|
|
|
// Impossible Egg forms
|
|
case 479 when pkm.IsEgg: // Rotom
|
|
case 676 when pkm.IsEgg: // Furfrou
|
|
if (pkm.AltForm != 0) // has form
|
|
{
|
|
data.AddLine(GetInvalid(V50));
|
|
return;
|
|
}
|
|
break;
|
|
|
|
// Party Only Forms
|
|
case 492: // Shaymin
|
|
case 676: // Furfrou
|
|
case 720: // Hoopa
|
|
if (pkm.AltForm != 0 && pkm.Box > -1 && pkm.Format <= 6) // has form but stored in box
|
|
{
|
|
data.AddLine(GetInvalid(V316));
|
|
return;
|
|
}
|
|
break;
|
|
|
|
// Battle only Forms with other legal forms allowed
|
|
case 718 when pkm.AltForm >= 4: // Zygarde Complete
|
|
case 774 when pkm.AltForm < 7: // Minior Shield
|
|
case 800 when pkm.AltForm == 3: // Ultra Necrozma
|
|
data.AddLine(GetInvalid(V310));
|
|
return;
|
|
case 800 when pkm.AltForm < 3: // Necrozma Fused forms & default
|
|
case 778 when pkm.AltForm == 2: // Totem disguise Mimikyu
|
|
data.AddLine(GetValid(V318));
|
|
return;
|
|
}
|
|
|
|
if (pkm.Format >= 7 && Info.Generation < 7 && pkm.AltForm != 0)
|
|
{
|
|
if (pkm.Species == 25 || Legal.AlolanOriginForms.Contains(pkm.Species)
|
|
|| Legal.AlolanVariantEvolutions12.Contains(data.EncounterOriginal.Species))
|
|
{ data.AddLine(GetInvalid(V317)); return; }
|
|
}
|
|
if (pkm.AltForm > 0 && new[] { Legal.BattleForms, Legal.BattleMegas, Legal.BattlePrimals }.Any(arr => arr.Contains(pkm.Species)))
|
|
{ data.AddLine(GetInvalid(V310)); return; }
|
|
|
|
data.AddLine(GetValid(V318));
|
|
}
|
|
|
|
|
|
private void VerifyFormFriendSafari(LegalityAnalysis data)
|
|
{
|
|
var pkm = data.pkm;
|
|
switch (pkm.Species)
|
|
{
|
|
case 670: // Floette
|
|
case 671: // Florges
|
|
if (!new[] { 0, 1, 3 }.Contains(pkm.AltForm)) // 0/1/3 - RBY
|
|
data.AddLine(GetInvalid(V64));
|
|
break;
|
|
case 710 when pkm.AltForm != 0: // Pumpkaboo
|
|
case 711 when pkm.AltForm != 0: // Goregeist Average
|
|
data.AddLine(GetInvalid(V6));
|
|
break;
|
|
case 423 when pkm.AltForm != 0: // Gastrodon West
|
|
data.AddLine(GetInvalid(V64));
|
|
break;
|
|
case 586 when pkm.AltForm != 0: // Sawsbuck
|
|
data.AddLine(GetInvalid(V65));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|