mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-05-20 20:58:30 -05:00
Reduce allocations of default valid/invalid
Condense some expressions, make some comments/params clear and consistent.
This commit is contained in:
parent
535b63f613
commit
a159da0abf
|
|
@ -12,6 +12,8 @@ public EncounterSlot5(EncounterArea5 area, int species, int form, int min, int m
|
|||
{
|
||||
}
|
||||
|
||||
public bool IsHiddenGrotto() => Area.Type == SlotType.HiddenGrotto;
|
||||
|
||||
protected override HiddenAbilityPermission IsHiddenAbilitySlot() => Area.Type == SlotType.HiddenGrotto ? HiddenAbilityPermission.Always : HiddenAbilityPermission.Never;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ private CheckResult VerifyAbility(LegalityAnalysis data)
|
|||
|
||||
// Check ability is possible (within bounds)
|
||||
int ability = pkm.Ability;
|
||||
int abilval = pi.GetAbilityIndex(ability);
|
||||
if (abilval < 0)
|
||||
int abilIndex = pi.GetAbilityIndex(ability);
|
||||
if (abilIndex < 0)
|
||||
return GetInvalid(LAbilityUnexpected);
|
||||
|
||||
var abilities = pi.Abilities;
|
||||
|
|
@ -43,12 +43,12 @@ private CheckResult VerifyAbility(LegalityAnalysis data)
|
|||
// Check AbilityNumber is a single set bit
|
||||
var num = pkm.AbilityNumber;
|
||||
if (!(num != 0 && (num & (num - 1)) == 0)) // not [!zero, and power of 2]
|
||||
return GetInvalid(LAbilityMismatchFlag);
|
||||
return INVALID;
|
||||
|
||||
// Check AbilityNumber points to ability
|
||||
int an = num >> 1;
|
||||
if (an >= abilities.Count || abilities[an] != ability)
|
||||
return GetInvalid(LAbilityMismatchFlag);
|
||||
return INVALID;
|
||||
|
||||
// Check AbilityNumber for transfers without unique abilities
|
||||
int gen = data.Info.Generation;
|
||||
|
|
@ -60,9 +60,9 @@ private CheckResult VerifyAbility(LegalityAnalysis data)
|
|||
{
|
||||
// Check if any pre-evolution could have it flipped.
|
||||
var evos = data.Info.EvoChainsAllGens[6];
|
||||
var pt = GameData.GetPersonal(GameUtil.GetVersion(pkm.Format));
|
||||
var pt = GameData.GetPersonal(GameUtil.GetVersion(format));
|
||||
if (!GetWasDual(evos, pt, pkm))
|
||||
return GetInvalid(LAbilityMismatchFlag);
|
||||
return INVALID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -85,9 +85,9 @@ private CheckResult VerifyAbility(LegalityAnalysis data)
|
|||
return VerifyAbilityMG(data, g, abilities);
|
||||
|
||||
if (format < 6)
|
||||
return VerifyAbility345(data, enc, abilities, abilval);
|
||||
return VerifyAbility345(data, enc, abilities, abilIndex);
|
||||
|
||||
return VerifyAbility(data, abilities, abilval);
|
||||
return VerifyAbility(data, abilities, abilIndex);
|
||||
}
|
||||
|
||||
private static bool GetWasDual(IReadOnlyList<EvoCriteria> evos, PersonalTable pt, ISpeciesForm pk)
|
||||
|
|
@ -106,7 +106,7 @@ private static bool GetWasDual(IReadOnlyList<EvoCriteria> evos, PersonalTable pt
|
|||
return false;
|
||||
}
|
||||
|
||||
private CheckResult VerifyAbility(LegalityAnalysis data, IReadOnlyList<int> abilities, int abilnum)
|
||||
private CheckResult VerifyAbility(LegalityAnalysis data, IReadOnlyList<int> abilities, int abilIndex)
|
||||
{
|
||||
var enc = data.EncounterMatch;
|
||||
var eabil = GetEncounterFixedAbilityNumber(enc);
|
||||
|
|
@ -115,10 +115,10 @@ private CheckResult VerifyAbility(LegalityAnalysis data, IReadOnlyList<int> abil
|
|||
if ((data.pkm.AbilityNumber == 4) != (eabil == 4))
|
||||
return GetInvalid(LAbilityHiddenFail);
|
||||
if (eabil > 0)
|
||||
return VerifyFixedAbility(data, abilities, AbilityState.CanMismatch, eabil, abilnum);
|
||||
return VerifyFixedAbility(data, abilities, AbilityState.CanMismatch, eabil, abilIndex);
|
||||
}
|
||||
|
||||
var gen = data.Info.Generation;
|
||||
var gen = enc.Generation;
|
||||
return gen switch
|
||||
{
|
||||
5 => VerifyAbility5(data, enc, abilities),
|
||||
|
|
@ -129,7 +129,7 @@ private CheckResult VerifyAbility(LegalityAnalysis data, IReadOnlyList<int> abil
|
|||
};
|
||||
}
|
||||
|
||||
private CheckResult VerifyAbility345(LegalityAnalysis data, IEncounterTemplate enc, IReadOnlyList<int> abilities, int abilnum)
|
||||
private CheckResult VerifyAbility345(LegalityAnalysis data, IEncounterTemplate enc, IReadOnlyList<int> abilities, int abilIndex)
|
||||
{
|
||||
var pkm = data.pkm;
|
||||
int format = pkm.Format;
|
||||
|
|
@ -137,44 +137,46 @@ private CheckResult VerifyAbility345(LegalityAnalysis data, IEncounterTemplate e
|
|||
if (format is (3 or 4 or 5) && abilities[0] != abilities[1]) // 3-4/5 and have 2 distinct abilities now
|
||||
state = VerifyAbilityPreCapsule(data, abilities);
|
||||
|
||||
int eabil = GetEncounterFixedAbilityNumber(enc);
|
||||
if (eabil >= 0)
|
||||
int encounterAbility = GetEncounterFixedAbilityNumber(enc);
|
||||
if (encounterAbility >= 0)
|
||||
{
|
||||
if ((pkm.AbilityNumber == 4) != (eabil == 4))
|
||||
if ((pkm.AbilityNumber == 4) != (encounterAbility == 4))
|
||||
return GetInvalid(LAbilityHiddenFail);
|
||||
if (eabil > 0)
|
||||
return VerifyFixedAbility(data, abilities, state, eabil, abilnum);
|
||||
if (encounterAbility > 0)
|
||||
return VerifyFixedAbility(data, abilities, state, encounterAbility, abilIndex);
|
||||
}
|
||||
|
||||
int gen = data.Info.Generation;
|
||||
int gen = enc.Generation;
|
||||
if (gen == 5)
|
||||
return VerifyAbility5(data, enc, abilities);
|
||||
|
||||
return CheckMatch(pkm, abilities, gen, state);
|
||||
}
|
||||
|
||||
private CheckResult VerifyFixedAbility(LegalityAnalysis data, IReadOnlyList<int> abilities, AbilityState state, int EncounterAbility, int abilval)
|
||||
private CheckResult VerifyFixedAbility(LegalityAnalysis data, IReadOnlyList<int> abilities, AbilityState state, int encounterAbility, int abilIndex)
|
||||
{
|
||||
var pkm = data.pkm;
|
||||
if (data.Info.EncounterMatch.Generation >= 6)
|
||||
var enc = data.Info.EncounterMatch;
|
||||
if (enc.Generation >= 6)
|
||||
{
|
||||
if (IsAbilityCapsuleModified(pkm, abilities, EncounterAbility))
|
||||
if (IsAbilityCapsuleModified(pkm, abilities, encounterAbility))
|
||||
return GetValid(LAbilityCapsuleUsed);
|
||||
if (pkm.AbilityNumber != EncounterAbility)
|
||||
if (pkm.AbilityNumber != encounterAbility)
|
||||
return INVALID;
|
||||
return VALID;
|
||||
}
|
||||
|
||||
if ((pkm.AbilityNumber == 4) != (EncounterAbility == 4))
|
||||
if ((pkm.AbilityNumber == 4) != (encounterAbility == 4))
|
||||
return GetInvalid(LAbilityHiddenFail);
|
||||
|
||||
if (data.EncounterMatch.Species != pkm.Species && state != AbilityState.CanMismatch) // evolved
|
||||
bool hasEvolved = enc.Species != pkm.Species;
|
||||
if (hasEvolved && state != AbilityState.CanMismatch)
|
||||
{
|
||||
// Evolving in Gen3 does not mutate the ability bit, so any mismatched abilities will stay mismatched.
|
||||
if (pkm.Gen3)
|
||||
if (enc.Generation == 3)
|
||||
{
|
||||
if (EncounterAbility == 1 << abilval)
|
||||
return GetValid(LAbilityFlag);
|
||||
if (encounterAbility == 1 << abilIndex)
|
||||
return VALID;
|
||||
|
||||
// If it is in a future game and does not match the fixed ability, then it must match the PID.
|
||||
if (pkm.Format != 3)
|
||||
|
|
@ -184,19 +186,19 @@ private CheckResult VerifyFixedAbility(LegalityAnalysis data, IReadOnlyList<int>
|
|||
return INVALID;
|
||||
}
|
||||
|
||||
return CheckMatch(pkm, abilities, data.Info.Generation, AbilityState.MustMatch);
|
||||
return CheckMatch(pkm, abilities, enc.Generation, AbilityState.MustMatch);
|
||||
}
|
||||
|
||||
if (EncounterAbility == 1 << abilval)
|
||||
return GetValid(LAbilityFlag);
|
||||
|
||||
if (pkm.AbilityNumber == EncounterAbility)
|
||||
if (encounterAbility == 1 << abilIndex)
|
||||
return VALID;
|
||||
|
||||
if (state == AbilityState.CanMismatch || EncounterAbility == 0)
|
||||
return CheckMatch(pkm, abilities, data.Info.Generation, AbilityState.MustMatch);
|
||||
if (pkm.AbilityNumber == encounterAbility)
|
||||
return VALID;
|
||||
|
||||
if (IsAbilityCapsuleModified(pkm, abilities, EncounterAbility))
|
||||
if (state == AbilityState.CanMismatch || encounterAbility == 0)
|
||||
return CheckMatch(pkm, abilities, enc.Generation, AbilityState.MustMatch);
|
||||
|
||||
if (IsAbilityCapsuleModified(pkm, abilities, encounterAbility))
|
||||
return GetValid(LAbilityCapsuleUsed);
|
||||
|
||||
return INVALID;
|
||||
|
|
@ -204,25 +206,34 @@ private CheckResult VerifyFixedAbility(LegalityAnalysis data, IReadOnlyList<int>
|
|||
|
||||
private AbilityState VerifyAbilityPreCapsule(LegalityAnalysis data, IReadOnlyList<int> abilities)
|
||||
{
|
||||
var pkm = data.pkm;
|
||||
// CXD pokemon can have any ability without matching PID
|
||||
if (pkm.Version == (int)GameVersion.CXD && pkm.Format == 3)
|
||||
return AbilityState.CanMismatch;
|
||||
|
||||
// Gen3 native or Gen4/5 origin
|
||||
if (pkm.Format == 3 || data.Info.Generation != 3)
|
||||
var info = data.Info;
|
||||
// Gen4/5 origin
|
||||
if (info.Generation != 3)
|
||||
return AbilityState.MustMatch;
|
||||
|
||||
// Gen3 origin... a lot of edge cases to check.
|
||||
var pkm = data.pkm;
|
||||
var format = pkm.Format;
|
||||
// CXD pokemon can have any ability without matching PID
|
||||
if (format == 3)
|
||||
{
|
||||
if (pkm.Version == (int)GameVersion.CXD)
|
||||
return AbilityState.CanMismatch;
|
||||
return AbilityState.MustMatch;
|
||||
}
|
||||
|
||||
// Evovled in Gen4/5
|
||||
if (pkm.Species > Legal.MaxSpeciesID_3)
|
||||
return AbilityState.MustMatch;
|
||||
|
||||
// If the species could not exist in Gen3, must match.
|
||||
if (data.Info.EvoChainsAllGens[3].Count == 0)
|
||||
var g3 = info.EvoChainsAllGens[3];
|
||||
if (g3.Count == 0)
|
||||
return AbilityState.MustMatch;
|
||||
|
||||
// Fall through when gen3 pkm transferred to gen4/5
|
||||
return VerifyAbilityGen3Transfer(data, abilities, data.Info.EvoChainsAllGens[3][0].Species);
|
||||
var maxGen3Species = g3[0].Species;
|
||||
return VerifyAbilityGen3Transfer(data, abilities, maxGen3Species);
|
||||
}
|
||||
|
||||
private AbilityState VerifyAbilityGen3Transfer(LegalityAnalysis data, IReadOnlyList<int> abilities, int maxGen3Species)
|
||||
|
|
@ -292,7 +303,7 @@ private CheckResult VerifyAbilityMG(LegalityAnalysis data, MysteryGift g, IReadO
|
|||
return GetValid(LAbilityCapsuleUsed);
|
||||
}
|
||||
|
||||
return GetInvalid(pkm.Format < 6 ? LAbilityMismatchPID : LAbilityMismatchFlag);
|
||||
return pkm.Format < 6 ? GetInvalid(LAbilityMismatchPID) : INVALID;
|
||||
}
|
||||
|
||||
private CheckResult VerifyAbilityPCD(LegalityAnalysis data, IReadOnlyList<int> abilities, PCD pcd)
|
||||
|
|
@ -305,7 +316,7 @@ private CheckResult VerifyAbilityPCD(LegalityAnalysis data, IReadOnlyList<int> a
|
|||
{
|
||||
// Gen3-5 transfer with same ability -> 1st ability that matches
|
||||
if (pkm.AbilityNumber == 1)
|
||||
return GetValid(LAbilityFlag);
|
||||
return VALID;
|
||||
return CheckMatch(pkm, abilities, 4, AbilityState.MustMatch); // evolved, must match
|
||||
}
|
||||
if (pkm.AbilityNumber < 4) // Ability Capsule can change between 1/2
|
||||
|
|
@ -322,23 +333,14 @@ private CheckResult VerifyAbilityPCD(LegalityAnalysis data, IReadOnlyList<int> a
|
|||
private CheckResult VerifyAbility5(LegalityAnalysis data, IEncounterTemplate enc, IReadOnlyList<int> abilities)
|
||||
{
|
||||
var pkm = data.pkm;
|
||||
switch (enc)
|
||||
{
|
||||
case EncounterSlot w:
|
||||
// Hidden Abilities for Wild Encounters are only available at a Hidden Grotto
|
||||
bool grotto = w.Area.Type == SlotType.HiddenGrotto;
|
||||
if (pkm.AbilityNumber == 4 ^ grotto)
|
||||
return GetInvalid(grotto ? LAbilityMismatchGrotto : LAbilityHiddenFail);
|
||||
break;
|
||||
|
||||
case EncounterEgg e when pkm.AbilityNumber == 4:
|
||||
// Hidden Abilities for some are unbreedable or unreleased
|
||||
if (AbilityBreedLegality.BanHidden5.Contains(e.Species))
|
||||
return GetInvalid(LAbilityHiddenUnavailable);
|
||||
break;
|
||||
}
|
||||
var state = pkm.Format == 5 ? AbilityState.MustMatch : AbilityState.CanMismatch;
|
||||
return CheckMatch(data.pkm, abilities, 5, state);
|
||||
// Eggs and Encounter Slots are not yet checked for Hidden Ability potential.
|
||||
return enc switch
|
||||
{
|
||||
EncounterSlot5 w when pkm.AbilityNumber == 4 != w.IsHiddenGrotto() => GetInvalid(w.IsHiddenGrotto() ? LAbilityMismatchGrotto : LAbilityHiddenFail),
|
||||
EncounterEgg e when pkm.AbilityNumber == 4 && AbilityBreedLegality.BanHidden5.Contains(e.Species) => GetInvalid(LAbilityHiddenUnavailable),
|
||||
_ => CheckMatch(data.pkm, abilities, 5, pkm.Format == 5 ? AbilityState.MustMatch : AbilityState.CanMismatch)
|
||||
};
|
||||
}
|
||||
|
||||
private CheckResult VerifyAbility6(LegalityAnalysis data, IEncounterTemplate enc)
|
||||
|
|
@ -347,32 +349,31 @@ private CheckResult VerifyAbility6(LegalityAnalysis data, IEncounterTemplate enc
|
|||
if (pkm.AbilityNumber != 4)
|
||||
return VALID;
|
||||
|
||||
// hidden abilities
|
||||
if (enc is EncounterSlot slot)
|
||||
// Eggs and Encounter Slots are not yet checked for Hidden Ability potential.
|
||||
return enc switch
|
||||
{
|
||||
bool valid = slot is EncounterSlot6AO {CanDexNav: true} || slot.Area.Type is SlotType.FriendSafari or SlotType.Horde;
|
||||
if (!valid)
|
||||
return GetInvalid(LAbilityMismatchHordeSafari);
|
||||
}
|
||||
if (AbilityBreedLegality.BanHidden6.Contains(enc.Species | (enc.Form << 11)))
|
||||
return GetInvalid(LAbilityHiddenUnavailable);
|
||||
EncounterSlot6XY slot when slot.Area.Type is SlotType.FriendSafari or SlotType.Horde => VALID,
|
||||
EncounterSlot6AO slot when slot.Area.Type is SlotType.Horde => VALID,
|
||||
EncounterSlot6AO {CanDexNav: true} => VALID,
|
||||
EncounterSlot => GetInvalid(LAbilityMismatchHordeSafari),
|
||||
|
||||
return VALID;
|
||||
EncounterEgg egg when AbilityBreedLegality.BanHidden6.Contains(egg.Species | (egg.Form << 11)) => GetInvalid(LAbilityHiddenUnavailable),
|
||||
_ => VALID
|
||||
};
|
||||
}
|
||||
|
||||
private CheckResult VerifyAbility7(LegalityAnalysis data, IEncounterTemplate enc)
|
||||
{
|
||||
var pkm = data.pkm;
|
||||
if (enc is EncounterSlot slot && pkm.AbilityNumber == 4)
|
||||
{
|
||||
bool valid = slot.Area.Type == SlotType.SOS;
|
||||
if (!valid)
|
||||
return GetInvalid(LAbilityMismatchSOS);
|
||||
}
|
||||
if (AbilityBreedLegality.BanHidden7.Contains(enc.Species | (enc.Form << 11)) && pkm.AbilityNumber == 4)
|
||||
return GetInvalid(LAbilityHiddenUnavailable);
|
||||
if (pkm.AbilityNumber != 4)
|
||||
return VALID;
|
||||
|
||||
return VALID;
|
||||
return enc switch
|
||||
{
|
||||
EncounterSlot7 slot when slot.Area.Type != SlotType.SOS => GetInvalid(LAbilityMismatchSOS),
|
||||
EncounterEgg egg when AbilityBreedLegality.BanHidden7.Contains(egg.Species | (egg.Form << 11)) => GetInvalid(LAbilityHiddenUnavailable),
|
||||
_ => VALID
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -423,6 +424,7 @@ private CheckResult CheckMatch(PKM pkm, IReadOnlyList<int> abilities, int gen, A
|
|||
|
||||
private CheckResult GetPIDAbilityMatch(PKM pkm, IReadOnlyList<int> abilities)
|
||||
{
|
||||
// Ability Number bits are already verified as clean.
|
||||
var abil = abilities[pkm.AbilityNumber >> 1];
|
||||
if (abil != pkm.Ability)
|
||||
return GetInvalid(LAbilityMismatchPID);
|
||||
|
|
@ -431,13 +433,13 @@ private CheckResult GetPIDAbilityMatch(PKM pkm, IReadOnlyList<int> abilities)
|
|||
}
|
||||
|
||||
// Ability Capsule can change between 1/2
|
||||
private static bool IsAbilityCapsuleModified(PKM pkm, IReadOnlyList<int> abilities, int EncounterAbility)
|
||||
private static bool IsAbilityCapsuleModified(PKM pkm, IReadOnlyList<int> abilities, int encounterAbility)
|
||||
{
|
||||
if (!CanAbilityCapsule(pkm.Format, abilities))
|
||||
return false;
|
||||
if (pkm.AbilityNumber == 4)
|
||||
return false; // Cannot alter to hidden ability.
|
||||
if (EncounterAbility == 4)
|
||||
if (encounterAbility == 4)
|
||||
return false; // Cannot alter from hidden ability.
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user