2018-06-24 05:00:01 +00:00
|
|
|
|
using System;
|
|
|
|
|
using static PKHeX.Core.LegalityCheckStrings;
|
2021-01-11 02:15:33 +00:00
|
|
|
|
using static PKHeX.Core.Species;
|
2018-06-24 05:00:01 +00:00
|
|
|
|
|
|
|
|
|
namespace PKHeX.Core
|
|
|
|
|
{
|
2018-07-02 02:17:37 +00:00
|
|
|
|
/// <summary>
|
2020-12-11 04:42:30 +00:00
|
|
|
|
/// Verifies the <see cref="PKM.Form"/> value.
|
2018-07-02 02:17:37 +00:00
|
|
|
|
/// </summary>
|
|
|
|
|
public sealed class FormVerifier : Verifier
|
2018-06-24 05:00:01 +00:00
|
|
|
|
{
|
|
|
|
|
protected override CheckIdentifier Identifier => CheckIdentifier.Form;
|
|
|
|
|
|
|
|
|
|
public override void Verify(LegalityAnalysis data)
|
|
|
|
|
{
|
|
|
|
|
var pkm = data.pkm;
|
|
|
|
|
if (pkm.Format < 4)
|
|
|
|
|
return; // no forms exist
|
2018-06-30 22:01:16 +00:00
|
|
|
|
var result = VerifyForm(data);
|
|
|
|
|
data.AddLine(result);
|
2020-01-11 00:33:40 +00:00
|
|
|
|
|
|
|
|
|
if (pkm is IFormArgument f)
|
2021-02-09 04:26:53 +00:00
|
|
|
|
data.AddLine(VerifyFormArgument(data, f));
|
2018-06-30 22:01:16 +00:00
|
|
|
|
}
|
2018-06-24 05:00:01 +00:00
|
|
|
|
|
2018-09-01 21:11:12 +00:00
|
|
|
|
private CheckResult VALID => GetValid(LFormValid);
|
2018-07-27 02:34:27 +00:00
|
|
|
|
|
2018-06-30 22:01:16 +00:00
|
|
|
|
private CheckResult VerifyForm(LegalityAnalysis data)
|
|
|
|
|
{
|
|
|
|
|
var pkm = data.pkm;
|
2018-06-24 05:00:01 +00:00
|
|
|
|
var PersonalInfo = data.PersonalInfo;
|
|
|
|
|
|
2020-12-11 04:42:30 +00:00
|
|
|
|
int count = PersonalInfo.FormCount;
|
|
|
|
|
var form = pkm.Form;
|
2020-01-17 03:23:29 +00:00
|
|
|
|
if (count <= 1 && form == 0)
|
2018-06-30 22:01:16 +00:00
|
|
|
|
return VALID; // no forms to check
|
|
|
|
|
|
2020-01-17 03:23:29 +00:00
|
|
|
|
var species = pkm.Species;
|
2021-01-02 01:08:49 +00:00
|
|
|
|
var enc = data.EncounterMatch;
|
2018-06-30 22:01:16 +00:00
|
|
|
|
var Info = data.Info;
|
2018-06-24 05:00:01 +00:00
|
|
|
|
|
2020-12-11 04:42:30 +00:00
|
|
|
|
if (!PersonalInfo.IsFormWithinRange(form) && !FormInfo.IsValidOutOfBoundsForm(species, form, Info.Generation))
|
2020-01-17 03:23:29 +00:00
|
|
|
|
return GetInvalid(string.Format(LFormInvalidRange, count - 1, form));
|
2018-06-24 05:00:01 +00:00
|
|
|
|
|
2021-01-11 02:15:33 +00:00
|
|
|
|
switch ((Species)species)
|
2018-06-24 05:00:01 +00:00
|
|
|
|
{
|
2021-01-11 02:15:33 +00:00
|
|
|
|
case Pikachu when Info.Generation == 6: // Cosplay
|
2022-03-26 21:53:15 +00:00
|
|
|
|
bool isStatic = enc is EncounterStatic6;
|
2021-01-11 02:15:33 +00:00
|
|
|
|
bool validCosplay = form == (isStatic ? enc.Form : 0);
|
|
|
|
|
if (!validCosplay)
|
2018-09-01 21:11:12 +00:00
|
|
|
|
return GetInvalid(isStatic ? LFormPikachuCosplayInvalid : LFormPikachuCosplay);
|
2018-06-24 05:00:01 +00:00
|
|
|
|
break;
|
2018-06-30 22:01:16 +00:00
|
|
|
|
|
2021-08-23 23:46:03 +00:00
|
|
|
|
case Pikachu when form is not 0 && ParseSettings.ActiveTrainer is SAV7b {Version:GameVersion.GE}:
|
|
|
|
|
case Eevee when form is not 0 && ParseSettings.ActiveTrainer is SAV7b {Version:GameVersion.GP}:
|
|
|
|
|
return GetInvalid(LFormBattle);
|
|
|
|
|
|
2021-01-11 02:15:33 +00:00
|
|
|
|
case Pikachu when Info.Generation >= 7: // Cap
|
2021-01-27 00:23:26 +00:00
|
|
|
|
bool validCap = form == (enc is EncounterInvalid or EncounterEgg ? 0 : enc.Form);
|
2021-01-02 01:08:49 +00:00
|
|
|
|
if (!validCap)
|
2018-06-24 05:00:01 +00:00
|
|
|
|
{
|
2021-01-02 01:08:49 +00:00
|
|
|
|
bool gift = enc is MysteryGift g && g.Form != form;
|
2018-09-01 21:11:12 +00:00
|
|
|
|
var msg = gift ? LFormPikachuEventInvalid : LFormInvalidGame;
|
2018-06-30 22:01:16 +00:00
|
|
|
|
return GetInvalid(msg);
|
2018-06-24 05:00:01 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2021-01-11 02:15:33 +00:00
|
|
|
|
case Unown when Info.Generation == 2 && form >= 26:
|
2020-01-17 03:23:29 +00:00
|
|
|
|
return GetInvalid(string.Format(LFormInvalidRange, "Z", form == 26 ? "!" : "?"));
|
2022-05-31 04:43:52 +00:00
|
|
|
|
case Dialga or Palkia or Giratina or Arceus when form > 0 && pkm is PA8: // can change forms with key items
|
2022-02-05 01:35:15 +00:00
|
|
|
|
break;
|
2021-01-11 02:15:33 +00:00
|
|
|
|
case Giratina when form == 1 ^ pkm.HeldItem == 112: // Giratina, Origin form only with Griseous Orb
|
2018-09-01 21:11:12 +00:00
|
|
|
|
return GetInvalid(LFormItemInvalid);
|
2018-06-30 22:01:16 +00:00
|
|
|
|
|
2021-01-11 02:15:33 +00:00
|
|
|
|
case Arceus:
|
2018-06-24 05:00:01 +00:00
|
|
|
|
{
|
2020-01-17 03:23:29 +00:00
|
|
|
|
int arceus = GetArceusFormFromHeldItem(pkm.HeldItem, pkm.Format);
|
|
|
|
|
return arceus != form ? GetInvalid(LFormItemInvalid) : GetValid(LFormItem);
|
2018-06-24 05:00:01 +00:00
|
|
|
|
}
|
2021-04-19 04:22:58 +00:00
|
|
|
|
case Keldeo when enc.Generation != 5 || pkm.Format >= 8:
|
2021-01-11 02:15:33 +00:00
|
|
|
|
// can mismatch in gen5 via BW tutor and transfer up
|
|
|
|
|
// can mismatch in gen8+ as the form activates in battle when knowing the move; outside of battle can be either state.
|
2021-04-19 04:22:58 +00:00
|
|
|
|
// Generation 8 patched out the mismatch; always forced to match moves.
|
2021-01-11 02:15:33 +00:00
|
|
|
|
bool hasSword = pkm.HasMove((int) Move.SecretSword);
|
|
|
|
|
bool isSword = pkm.Form == 1;
|
|
|
|
|
if (isSword != hasSword)
|
|
|
|
|
return GetInvalid(LMoveKeldeoMismatch);
|
2018-06-24 05:00:01 +00:00
|
|
|
|
break;
|
2021-01-11 02:15:33 +00:00
|
|
|
|
case Genesect:
|
2018-06-24 05:00:01 +00:00
|
|
|
|
{
|
2020-01-17 03:23:29 +00:00
|
|
|
|
int genesect = GetGenesectFormFromHeldItem(pkm.HeldItem);
|
|
|
|
|
return genesect != form ? GetInvalid(LFormItemInvalid) : GetValid(LFormItem);
|
2018-06-24 05:00:01 +00:00
|
|
|
|
}
|
2021-01-11 02:15:33 +00:00
|
|
|
|
case Greninja:
|
2020-01-17 03:23:29 +00:00
|
|
|
|
if (form > 1) // Ash Battle Bond active
|
2018-09-01 21:11:12 +00:00
|
|
|
|
return GetInvalid(LFormBattle);
|
2021-01-02 01:08:49 +00:00
|
|
|
|
if (form != 0 && enc is not MysteryGift) // Formes are not breedable, MysteryGift already checked
|
2020-01-17 03:23:29 +00:00
|
|
|
|
return GetInvalid(string.Format(LFormInvalidRange, 0, form));
|
2018-06-24 05:00:01 +00:00
|
|
|
|
break;
|
2018-06-30 22:01:16 +00:00
|
|
|
|
|
2021-01-11 02:15:33 +00:00
|
|
|
|
case Scatterbug or Spewpa:
|
2021-08-20 01:59:24 +00:00
|
|
|
|
if (form > Vivillon3DS.MaxWildFormID) // Fancy & Pokéball
|
2018-09-01 21:11:12 +00:00
|
|
|
|
return GetInvalid(LFormVivillonEventPre);
|
2020-12-22 01:12:39 +00:00
|
|
|
|
if (pkm is not IRegionOrigin tr)
|
2020-07-31 18:17:31 +00:00
|
|
|
|
break;
|
2021-08-02 15:57:21 +00:00
|
|
|
|
if (!Vivillon3DS.IsPatternValid(form, tr.ConsoleRegion))
|
|
|
|
|
return GetInvalid(LFormVivillonInvalid);
|
2021-08-03 02:43:57 +00:00
|
|
|
|
if (!Vivillon3DS.IsPatternNative(form, tr.Country, tr.Region))
|
2021-08-02 15:57:21 +00:00
|
|
|
|
data.AddLine(Get(LFormVivillonNonNative, Severity.Fishy));
|
2018-06-24 05:00:01 +00:00
|
|
|
|
break;
|
2021-01-11 02:15:33 +00:00
|
|
|
|
case Vivillon:
|
2021-08-20 01:59:24 +00:00
|
|
|
|
if (form > Vivillon3DS.MaxWildFormID) // Fancy & Pokéball
|
2018-06-24 05:00:01 +00:00
|
|
|
|
{
|
2021-01-02 01:08:49 +00:00
|
|
|
|
if (enc is not MysteryGift)
|
2018-09-01 21:11:12 +00:00
|
|
|
|
return GetInvalid(LFormVivillonInvalid);
|
|
|
|
|
return GetValid(LFormVivillon);
|
2018-06-24 05:00:01 +00:00
|
|
|
|
}
|
2021-01-11 02:15:33 +00:00
|
|
|
|
if (pkm is not IRegionOrigin trv)
|
2020-07-31 18:17:31 +00:00
|
|
|
|
break;
|
2021-08-02 15:57:21 +00:00
|
|
|
|
if (!Vivillon3DS.IsPatternValid(form, trv.ConsoleRegion))
|
|
|
|
|
return GetInvalid(LFormVivillonInvalid);
|
2021-08-03 02:43:57 +00:00
|
|
|
|
if (!Vivillon3DS.IsPatternNative(form, trv.Country, trv.Region))
|
2021-08-02 15:57:21 +00:00
|
|
|
|
data.AddLine(Get(LFormVivillonNonNative, Severity.Fishy));
|
2018-06-24 05:00:01 +00:00
|
|
|
|
break;
|
|
|
|
|
|
2021-01-11 02:15:33 +00:00
|
|
|
|
case Floette when form == 5: // Floette Eternal Flower -- Never Released
|
2021-01-02 01:08:49 +00:00
|
|
|
|
if (enc is not MysteryGift)
|
2018-09-01 21:11:12 +00:00
|
|
|
|
return GetInvalid(LFormEternalInvalid);
|
|
|
|
|
return GetValid(LFormEternal);
|
2021-01-11 02:15:33 +00:00
|
|
|
|
case Meowstic when form != pkm.Gender:
|
2018-09-01 21:11:12 +00:00
|
|
|
|
return GetInvalid(LGenderInvalidNone);
|
2018-06-30 22:01:16 +00:00
|
|
|
|
|
2021-01-11 02:15:33 +00:00
|
|
|
|
case Silvally:
|
2018-06-30 22:01:16 +00:00
|
|
|
|
{
|
2020-01-17 03:23:29 +00:00
|
|
|
|
int silvally = GetSilvallyFormFromHeldItem(pkm.HeldItem);
|
|
|
|
|
return silvally != form ? GetInvalid(LFormItemInvalid) : GetValid(LFormItem);
|
2018-06-30 22:01:16 +00:00
|
|
|
|
}
|
2018-06-24 05:00:01 +00:00
|
|
|
|
|
2021-01-11 02:15:33 +00:00
|
|
|
|
// Form doesn't exist in SM; cannot originate from that game.
|
2021-09-06 22:38:32 +00:00
|
|
|
|
case Rockruff when enc.Generation == 7 && form == 1 && pkm.SM:
|
2021-01-11 02:15:33 +00:00
|
|
|
|
case Lycanroc when enc.Generation == 7 && form == 2 && pkm.SM:
|
2018-09-01 21:11:12 +00:00
|
|
|
|
return GetInvalid(LFormInvalidGame);
|
2018-06-24 05:00:01 +00:00
|
|
|
|
|
2020-02-08 23:08:12 +00:00
|
|
|
|
// Toxel encounters have already been checked for the nature-specific evolution criteria.
|
2021-01-11 02:15:33 +00:00
|
|
|
|
case Toxtricity when enc.Species == (int)Toxtricity:
|
2020-02-08 23:08:12 +00:00
|
|
|
|
{
|
|
|
|
|
// The game enforces the Nature for Toxtricity encounters too!
|
2020-12-11 04:42:30 +00:00
|
|
|
|
if (pkm.Form != EvolutionMethod.GetAmpLowKeyResult(pkm.Nature))
|
2020-02-08 23:08:12 +00:00
|
|
|
|
return GetInvalid(LFormInvalidNature);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-24 05:00:01 +00:00
|
|
|
|
// Impossible Egg forms
|
2021-01-11 02:15:33 +00:00
|
|
|
|
case Rotom when pkm.IsEgg && form != 0:
|
|
|
|
|
case Furfrou when pkm.IsEgg && form != 0:
|
2018-09-01 21:11:12 +00:00
|
|
|
|
return GetInvalid(LEggSpecies);
|
2018-06-24 05:00:01 +00:00
|
|
|
|
|
|
|
|
|
// Party Only Forms
|
2021-01-11 02:15:33 +00:00
|
|
|
|
case Shaymin:
|
|
|
|
|
case Furfrou:
|
|
|
|
|
case Hoopa:
|
Track a PKM's Box,Slot,StorageFlags,Identifier metadata separately (#3222)
* Track a PKM's Box,Slot,StorageFlags,Identifier metadata separately
Don't store within the object, track the slot origin data separately.
Batch editing now pre-filters if using Box/Slot/Identifier logic; split up mods/filters as they're starting to get pretty hefty.
- Requesting a Box Data report now shows all slots in the save file (party, misc)
- Can now exclude backup saves from database search via toggle (separate from settings preventing load entirely)
- Replace some linq usages with direct code
* Remove WasLink virtual in PKM
Inline any logic, since we now have encounter objects to indicate matching, rather than the proto-legality logic checking properties of a PKM.
* Use Fateful to directly check gen5 mysterygift origins
No other encounter types in gen5 apply Fateful
* Simplify double ball comparison
Used to be separate for deferral cases, now no longer needed to be separate.
* Grab move/relearn reference and update locally
Fix relearn move identifier
* Inline defog HM transfer preference check
HasMove is faster than getting moves & checking contains. Skips allocation by setting values directly.
* Extract more met location metadata checks: WasBredEgg
* Replace Console.Write* with Debug.Write*
There's no console output UI, so don't include them in release builds.
* Inline WasGiftEgg, WasEvent, and WasEventEgg logic
Adios legality tags that aren't entirely correct for the specific format. Just put the computations in EncounterFinder.
2021-06-23 03:23:48 +00:00
|
|
|
|
if (form != 0 && data.SlotOrigin is not SlotOrigin.Party && pkm.Format <= 6) // has form but stored in box
|
2018-09-01 21:11:12 +00:00
|
|
|
|
return GetInvalid(LFormParty);
|
2018-06-24 05:00:01 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-25 16:15:16 +00:00
|
|
|
|
var format = pkm.Format;
|
2020-12-11 04:42:30 +00:00
|
|
|
|
if (FormInfo.IsBattleOnlyForm(species, form, format))
|
2020-10-25 16:15:16 +00:00
|
|
|
|
return GetInvalid(LFormBattle);
|
|
|
|
|
|
2020-01-17 03:23:29 +00:00
|
|
|
|
if (form == 0)
|
|
|
|
|
return VALID;
|
|
|
|
|
|
2020-12-11 04:42:30 +00:00
|
|
|
|
// everything below here is not Form 0, so it has a form.
|
2020-01-17 03:23:29 +00:00
|
|
|
|
if (format >= 7 && Info.Generation < 7)
|
2018-06-24 05:00:01 +00:00
|
|
|
|
{
|
2021-01-11 02:15:33 +00:00
|
|
|
|
if (species == 25 || Legal.AlolanOriginForms.Contains(species) || Legal.AlolanVariantEvolutions12.Contains(enc.Species))
|
2018-09-01 21:11:12 +00:00
|
|
|
|
return GetInvalid(LFormInvalidGame);
|
2018-06-24 05:00:01 +00:00
|
|
|
|
}
|
2020-01-17 03:23:29 +00:00
|
|
|
|
if (format >= 8 && Info.Generation < 8)
|
2019-09-23 23:56:47 +00:00
|
|
|
|
{
|
2021-01-11 02:15:33 +00:00
|
|
|
|
var orig = enc.Species;
|
2020-02-14 04:00:41 +00:00
|
|
|
|
if (Legal.GalarOriginForms.Contains(species) || Legal.GalarVariantFormEvolutions.Contains(orig))
|
2020-02-14 01:05:06 +00:00
|
|
|
|
{
|
2021-01-11 02:15:33 +00:00
|
|
|
|
if (species == (int)Meowth && enc.Form != 2)
|
2020-02-14 01:05:06 +00:00
|
|
|
|
{
|
|
|
|
|
// We're okay here. There's also Alolan Meowth...
|
|
|
|
|
}
|
2021-01-11 02:15:33 +00:00
|
|
|
|
else if (((Species)orig is MrMime or MimeJr) && pkm.CurrentLevel > enc.LevelMin && Info.Generation >= 4)
|
2020-02-14 04:00:41 +00:00
|
|
|
|
{
|
|
|
|
|
// We're okay with a Mime Jr. that has evolved via level up.
|
|
|
|
|
}
|
2021-01-02 01:08:49 +00:00
|
|
|
|
else if (enc.Version != GameVersion.GO)
|
2020-02-14 01:05:06 +00:00
|
|
|
|
{
|
|
|
|
|
return GetInvalid(LFormInvalidGame);
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-09-23 23:56:47 +00:00
|
|
|
|
}
|
2018-06-24 05:00:01 +00:00
|
|
|
|
|
2018-06-30 22:01:16 +00:00
|
|
|
|
return VALID;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-02 21:11:51 +00:00
|
|
|
|
private static readonly ushort[] Arceus_PlateIDs = { 303, 306, 304, 305, 309, 308, 310, 313, 298, 299, 301, 300, 307, 302, 311, 312, 644 };
|
|
|
|
|
private static readonly ushort[] Arceus_ZCrystal = { 782, 785, 783, 784, 788, 787, 789, 792, 777, 778, 780, 779, 786, 781, 790, 791, 793 };
|
|
|
|
|
|
2022-05-07 18:47:01 +00:00
|
|
|
|
public static int GetArceusFormFromHeldItem(int item, int format) => item switch
|
2018-06-30 22:01:16 +00:00
|
|
|
|
{
|
2022-05-07 18:47:01 +00:00
|
|
|
|
>= 777 and <= 793 => GetArceusFormFromZCrystal(item),
|
|
|
|
|
>= 298 and <= 313 or 644 => GetArceusFormFromPlate(item, format),
|
|
|
|
|
_ => 0,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
private static int GetArceusFormFromZCrystal(int item)
|
|
|
|
|
{
|
|
|
|
|
return Array.IndexOf(Arceus_ZCrystal, (ushort)item) + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static int GetArceusFormFromPlate(int item, int format)
|
|
|
|
|
{
|
|
|
|
|
int form = Array.IndexOf(Arceus_PlateIDs, (ushort)item) + 1;
|
|
|
|
|
if (format != 4) // No need to consider Curse type
|
|
|
|
|
return form;
|
|
|
|
|
if (form < 9)
|
|
|
|
|
return form;
|
|
|
|
|
return form + 1; // ??? type Form shifts everything by 1
|
2018-06-30 22:01:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-08 05:34:25 +00:00
|
|
|
|
public static int GetSilvallyFormFromHeldItem(int item)
|
2018-06-30 22:01:16 +00:00
|
|
|
|
{
|
2021-05-29 22:31:47 +00:00
|
|
|
|
if (item is >= 904 and <= 920)
|
2018-06-30 22:01:16 +00:00
|
|
|
|
return item - 903;
|
|
|
|
|
return 0;
|
2018-06-24 05:00:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-02-08 05:34:25 +00:00
|
|
|
|
public static int GetGenesectFormFromHeldItem(int item)
|
2018-06-30 22:01:16 +00:00
|
|
|
|
{
|
2021-05-29 22:31:47 +00:00
|
|
|
|
if (item is >= 116 and <= 119)
|
2018-06-30 22:01:16 +00:00
|
|
|
|
return item - 115;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2018-06-24 05:00:01 +00:00
|
|
|
|
|
2021-02-09 04:26:53 +00:00
|
|
|
|
private CheckResult VerifyFormArgument(LegalityAnalysis data, IFormArgument f)
|
2020-01-11 00:33:40 +00:00
|
|
|
|
{
|
|
|
|
|
var pkm = data.pkm;
|
2021-01-11 02:15:33 +00:00
|
|
|
|
var enc = data.EncounterMatch;
|
2021-02-09 04:26:53 +00:00
|
|
|
|
var arg = f.FormArgument;
|
|
|
|
|
|
|
|
|
|
var unusedMask = pkm.Format == 6 ? 0xFFFF_FF00 : 0xFF00_0000;
|
|
|
|
|
if ((arg & unusedMask) != 0)
|
|
|
|
|
return GetInvalid(LFormArgumentHigh);
|
2021-02-06 00:52:46 +00:00
|
|
|
|
|
2021-01-11 02:15:33 +00:00
|
|
|
|
return (Species)pkm.Species switch
|
2020-01-11 00:33:40 +00:00
|
|
|
|
{
|
2021-02-17 05:22:20 +00:00
|
|
|
|
// Transfer Edge Cases -- Bank wipes the form but keeps old FormArgument value.
|
|
|
|
|
Furfrou when pkm.Format == 7 && pkm.Form == 0 &&
|
|
|
|
|
((enc.Generation == 6 && f.FormArgument <= byte.MaxValue) || IsFormArgumentDayCounterValid(f, 5, true))
|
|
|
|
|
=> GetValid(LFormArgumentValid),
|
|
|
|
|
|
2021-02-09 07:18:45 +00:00
|
|
|
|
Furfrou when pkm.Form != 0 => !IsFormArgumentDayCounterValid(f, 5, true) ? GetInvalid(LFormArgumentInvalid) :GetValid(LFormArgumentValid),
|
2021-02-09 04:26:53 +00:00
|
|
|
|
Hoopa when pkm.Form == 1 => !IsFormArgumentDayCounterValid(f, 3) ? GetInvalid(LFormArgumentInvalid) : GetValid(LFormArgumentValid),
|
2021-01-11 02:15:33 +00:00
|
|
|
|
Yamask when pkm.Form == 1 => arg switch
|
|
|
|
|
{
|
|
|
|
|
not 0 when pkm.IsEgg => GetInvalid(LFormArgumentNotAllowed),
|
|
|
|
|
> 9_999 => GetInvalid(LFormArgumentHigh),
|
2021-08-20 20:49:20 +00:00
|
|
|
|
_ => GetValid(LFormArgumentValid),
|
2021-01-11 02:15:33 +00:00
|
|
|
|
},
|
|
|
|
|
Runerigus when enc.Species == (int)Runerigus => arg switch
|
|
|
|
|
{
|
|
|
|
|
not 0 => GetInvalid(LFormArgumentNotAllowed),
|
2021-08-20 20:49:20 +00:00
|
|
|
|
_ => GetValid(LFormArgumentValid),
|
2021-01-11 02:15:33 +00:00
|
|
|
|
},
|
|
|
|
|
Runerigus => arg switch // From Yamask-1
|
|
|
|
|
{
|
|
|
|
|
< 49 => GetInvalid(LFormArgumentLow),
|
|
|
|
|
> 9_999 => GetInvalid(LFormArgumentHigh),
|
2021-08-20 20:49:20 +00:00
|
|
|
|
_ => GetValid(LFormArgumentValid),
|
2021-01-11 02:15:33 +00:00
|
|
|
|
},
|
|
|
|
|
Alcremie when enc.Species == (int)Alcremie => arg switch
|
|
|
|
|
{
|
|
|
|
|
not 0 => GetInvalid(LFormArgumentNotAllowed),
|
2021-08-20 20:49:20 +00:00
|
|
|
|
_ => GetValid(LFormArgumentValid),
|
2021-01-11 02:15:33 +00:00
|
|
|
|
},
|
|
|
|
|
Alcremie => arg switch // From Milcery
|
|
|
|
|
{
|
|
|
|
|
> (uint) AlcremieDecoration.Ribbon => GetInvalid(LFormArgumentHigh),
|
2021-08-20 20:49:20 +00:00
|
|
|
|
_ => GetValid(LFormArgumentValid),
|
2022-02-05 01:35:15 +00:00
|
|
|
|
},
|
|
|
|
|
Overqwil when enc.Species == (int)Overqwil => arg switch
|
|
|
|
|
{
|
|
|
|
|
not 0 => GetInvalid(LFormArgumentNotAllowed),
|
|
|
|
|
_ => GetValid(LFormArgumentValid),
|
|
|
|
|
},
|
|
|
|
|
Wyrdeer when enc.Species == (int)Wyrdeer => arg switch
|
|
|
|
|
{
|
|
|
|
|
not 0 => GetInvalid(LFormArgumentNotAllowed),
|
|
|
|
|
_ => GetValid(LFormArgumentValid),
|
|
|
|
|
},
|
|
|
|
|
Basculegion when enc.Species == (int)Basculegion => arg switch
|
|
|
|
|
{
|
|
|
|
|
not 0 => GetInvalid(LFormArgumentNotAllowed),
|
|
|
|
|
_ => GetValid(LFormArgumentValid),
|
|
|
|
|
},
|
|
|
|
|
Basculin when pkm.Form is 2 => arg switch
|
|
|
|
|
{
|
|
|
|
|
not 0 when pkm.IsEgg => GetInvalid(LFormArgumentNotAllowed),
|
|
|
|
|
> 9_999 => GetInvalid(LFormArgumentHigh),
|
|
|
|
|
_ => GetValid(LFormArgumentValid),
|
|
|
|
|
},
|
|
|
|
|
Qwilfish when pkm.Form is 1 => arg switch
|
|
|
|
|
{
|
|
|
|
|
not 0 when pkm.IsEgg => GetInvalid(LFormArgumentNotAllowed),
|
2022-05-31 04:43:52 +00:00
|
|
|
|
not 0 when pkm.CurrentLevel < 25 => GetInvalid(LFormArgumentHigh),
|
2022-02-05 01:35:15 +00:00
|
|
|
|
> 9_999 => GetInvalid(LFormArgumentHigh),
|
|
|
|
|
_ => GetValid(LFormArgumentValid),
|
|
|
|
|
},
|
2022-05-31 04:43:52 +00:00
|
|
|
|
Stantler when pkm is PA8 || pkm.HasVisitedLA(data.Info.EvoChainsAllGens.Gen8a) => arg switch
|
2022-02-05 01:35:15 +00:00
|
|
|
|
{
|
|
|
|
|
not 0 when pkm.IsEgg => GetInvalid(LFormArgumentNotAllowed),
|
2022-05-31 04:43:52 +00:00
|
|
|
|
not 0 when pkm.CurrentLevel < 31 => GetInvalid(LFormArgumentHigh),
|
2022-02-05 01:35:15 +00:00
|
|
|
|
> 9_999 => GetInvalid(LFormArgumentHigh),
|
|
|
|
|
_ => GetValid(LFormArgumentValid),
|
|
|
|
|
},
|
|
|
|
|
Wyrdeer => arg switch // From Stantler
|
|
|
|
|
{
|
|
|
|
|
< 20 => GetInvalid(LFormArgumentLow),
|
|
|
|
|
> 9_999 => GetInvalid(LFormArgumentHigh),
|
|
|
|
|
_ => GetValid(LFormArgumentValid),
|
|
|
|
|
},
|
|
|
|
|
Overqwil => arg switch // From Qwilfish-1
|
|
|
|
|
{
|
|
|
|
|
< 20 => GetInvalid(LFormArgumentLow),
|
|
|
|
|
> 9_999 => GetInvalid(LFormArgumentHigh),
|
|
|
|
|
_ => GetValid(LFormArgumentValid),
|
|
|
|
|
},
|
|
|
|
|
Basculegion => arg switch // From Basculin-2
|
|
|
|
|
{
|
|
|
|
|
< 294 => GetInvalid(LFormArgumentLow),
|
|
|
|
|
> 9_999 => GetInvalid(LFormArgumentHigh),
|
|
|
|
|
_ => GetValid(LFormArgumentValid),
|
2021-01-11 02:15:33 +00:00
|
|
|
|
},
|
2021-02-09 04:26:53 +00:00
|
|
|
|
_ => VerifyFormArgumentNone(pkm, f),
|
2021-01-11 02:15:33 +00:00
|
|
|
|
};
|
2020-01-11 00:33:40 +00:00
|
|
|
|
}
|
2021-02-06 01:25:13 +00:00
|
|
|
|
|
2021-02-09 04:26:53 +00:00
|
|
|
|
private CheckResult VerifyFormArgumentNone(PKM pkm, IFormArgument f)
|
2021-02-06 01:25:13 +00:00
|
|
|
|
{
|
2021-02-09 04:26:53 +00:00
|
|
|
|
if (pkm is not PK6 pk6)
|
2021-02-09 07:18:45 +00:00
|
|
|
|
{
|
|
|
|
|
if (f.FormArgument != 0)
|
|
|
|
|
{
|
|
|
|
|
if (pkm.Species == (int)Furfrou && pkm.Form == 0 && (f.FormArgument & ~0xFF_00_00u) == 0)
|
|
|
|
|
return GetValid(LFormArgumentValid);
|
|
|
|
|
return GetInvalid(LFormArgumentNotAllowed);
|
|
|
|
|
}
|
2021-02-09 04:26:53 +00:00
|
|
|
|
return GetValid(LFormArgumentValid);
|
2021-02-09 07:18:45 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (f.FormArgument != 0)
|
|
|
|
|
{
|
|
|
|
|
if (pkm.Species == (int)Furfrou && pkm.Form == 0 && (f.FormArgument & ~0xFFu) == 0)
|
|
|
|
|
return GetValid(LFormArgumentValid);
|
|
|
|
|
return GetInvalid(LFormArgumentNotAllowed);
|
|
|
|
|
}
|
2021-02-09 04:26:53 +00:00
|
|
|
|
|
|
|
|
|
// Stored separately from main form argument value
|
|
|
|
|
if (pk6.FormArgumentRemain != 0)
|
|
|
|
|
return GetInvalid(LFormArgumentNotAllowed);
|
|
|
|
|
if (pk6.FormArgumentElapsed != 0)
|
|
|
|
|
return GetInvalid(LFormArgumentNotAllowed);
|
|
|
|
|
|
|
|
|
|
return GetValid(LFormArgumentValid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static bool IsFormArgumentDayCounterValid(IFormArgument f, uint maxSeed, bool canRefresh = false)
|
|
|
|
|
{
|
|
|
|
|
var remain = f.FormArgumentRemain;
|
|
|
|
|
var elapsed = f.FormArgumentElapsed;
|
|
|
|
|
var maxElapsed = f.FormArgumentMaximum;
|
2021-02-06 01:25:13 +00:00
|
|
|
|
if (canRefresh)
|
|
|
|
|
{
|
2021-02-09 04:26:53 +00:00
|
|
|
|
if (maxElapsed < elapsed)
|
|
|
|
|
return false;
|
|
|
|
|
|
2021-02-06 01:25:13 +00:00
|
|
|
|
if (remain + elapsed < maxSeed)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2021-02-09 04:26:53 +00:00
|
|
|
|
if (maxElapsed != 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
2021-02-06 01:25:13 +00:00
|
|
|
|
if (remain + elapsed != maxSeed)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (remain > maxSeed)
|
|
|
|
|
return false;
|
|
|
|
|
return remain != 0;
|
|
|
|
|
}
|
2018-06-24 05:00:01 +00:00
|
|
|
|
}
|
|
|
|
|
}
|