mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-23 20:43:07 +00:00
260 lines
10 KiB
C#
260 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;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|