mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-23 20:43:07 +00:00
d47bb1d297
With the new version of Visual Studio bringing C# 12, we can revise our logic for better readability as well as use new methods/APIs introduced in the .NET 8.0 BCL.
228 lines
11 KiB
C#
228 lines
11 KiB
C#
using System;
|
|
using static PKHeX.Core.Ball;
|
|
using static PKHeX.Core.Species;
|
|
using static PKHeX.Core.BallInheritanceResult;
|
|
|
|
namespace PKHeX.Core;
|
|
|
|
/// <summary>
|
|
/// Ball Inheritance Permissions for <see cref="EntityContext.Gen7"/> games.
|
|
/// </summary>
|
|
public sealed class BallContext7 : IBallContext
|
|
{
|
|
public static readonly BallContext7 Instance = new();
|
|
|
|
public bool CanBreedWithBall(ushort species, byte form, Ball ball)
|
|
{
|
|
// Eagerly return true for the most common case
|
|
if (ball is Poke)
|
|
return true;
|
|
|
|
if (species >= Permit.Length)
|
|
return false;
|
|
var permitBit = GetPermitBit(ball);
|
|
if (permitBit == BallType.None)
|
|
return false;
|
|
|
|
var permit = Permit[species];
|
|
if ((permit & (1 << (byte)permitBit)) == 0)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
public BallInheritanceResult CanBreedWithBall(ushort species, byte form, Ball ball, PKM pk)
|
|
{
|
|
// Eagerly return true for the most common case
|
|
if (ball is Poke)
|
|
return Valid;
|
|
|
|
if (species >= Permit.Length)
|
|
return Invalid;
|
|
var permitBit = GetPermitBit(ball);
|
|
if (permitBit == BallType.None)
|
|
return Invalid;
|
|
|
|
var permit = Permit[species];
|
|
if ((permit & (1 << (byte)permitBit)) == 0)
|
|
return Invalid;
|
|
|
|
if (!BallContextHOME.IsAbilityPatchPossible(pk.Format, species) && !IsAbilityAllowed(species, form, pk, permitBit))
|
|
return BadAbility;
|
|
return Valid;
|
|
}
|
|
|
|
private static bool IsAbilityAllowed(ushort species, byte form, PKM pk, BallType permitBit) => permitBit switch
|
|
{
|
|
BallType.Gen3 => IsNotHidden(pk.AbilityNumber) || !IsBannedHiddenGen3(species),
|
|
BallType.Gen4 => IsNotHidden(pk.AbilityNumber) || !IsBannedHiddenGen4(species),
|
|
BallType.Safari => IsNotHidden(pk.AbilityNumber) || !IsBannedHiddenSafari(species),
|
|
BallType.Apricorn => IsNotHidden(pk.AbilityNumber) || !IsBannedHiddenApricorn(species, form),
|
|
BallType.Beast => IsNotHidden(pk.AbilityNumber) || !IsBannedHiddenBeast(species, form),
|
|
_ => true,
|
|
};
|
|
|
|
private static bool IsBannedHiddenBeast(ushort species, byte form) => species switch
|
|
{
|
|
(int)Voltorb => true,
|
|
(int)Flabébé => form == 3, // Flabébé-Blue
|
|
_ => false,
|
|
};
|
|
|
|
private static bool IsBannedHiddenApricorn(ushort species, byte form) => species switch
|
|
{
|
|
(int)NidoranF => true,
|
|
(int)NidoranM => true,
|
|
(int)Voltorb => true,
|
|
(int)Bronzor => true,
|
|
(int)Flabébé => form == 3, // Flabébé-Blue
|
|
_ => false,
|
|
};
|
|
|
|
private static bool IsBannedHiddenSafari(ushort species) => species switch
|
|
{
|
|
(int)NidoranF => true,
|
|
(int)NidoranM => true,
|
|
(int)Volbeat => true,
|
|
(int)Illumise => true,
|
|
(int)Magnemite => true,
|
|
(int)Voltorb => true,
|
|
(int)Kangaskhan => true,
|
|
(int)Tauros => true,
|
|
(int)Ditto => true,
|
|
(int)Miltank => true,
|
|
(int)Beldum => true,
|
|
(int)Bronzor => true,
|
|
(int)Happiny => true,
|
|
(int)Tyrogue => true,
|
|
(int)Staryu => true,
|
|
(int)Lunatone => true,
|
|
(int)Solrock => true,
|
|
(int)Rotom => true,
|
|
(int)Klink => true,
|
|
(int)Golett => true,
|
|
_ => false,
|
|
};
|
|
|
|
private static bool IsNotHidden(int pkAbilityNumber) => pkAbilityNumber != 4;
|
|
|
|
private static bool IsBannedHiddenGen4(ushort species) => species switch
|
|
{
|
|
(int)Chikorita => true,
|
|
(int)Cyndaquil => true,
|
|
(int)Totodile => true,
|
|
(int)Treecko => true,
|
|
(int)Torchic => true,
|
|
(int)Mudkip => true,
|
|
(int)Turtwig => true,
|
|
(int)Chimchar => true,
|
|
(int)Piplup => true,
|
|
(int)Snivy => true,
|
|
(int)Tepig => true,
|
|
(int)Oshawott => true,
|
|
|
|
// Fossil Only obtain
|
|
(int)Archen => true,
|
|
(int)Tyrunt => true,
|
|
(int)Amaura => true,
|
|
_ => false,
|
|
};
|
|
|
|
private static bool IsBannedHiddenGen3(ushort species) => species switch
|
|
{
|
|
// Fossil Only obtain
|
|
(int)Archen => true,
|
|
(int)Tyrunt => true,
|
|
(int)Amaura => true,
|
|
_ => false,
|
|
};
|
|
|
|
private static BallType GetPermitBit(Ball ball) => ball switch
|
|
{
|
|
Ultra => BallType.Gen3,
|
|
Great => BallType.Gen3,
|
|
Poke => BallType.Gen3,
|
|
Safari => BallType.Safari,
|
|
|
|
Net => BallType.Gen3,
|
|
Dive => BallType.Gen3,
|
|
Nest => BallType.Gen3,
|
|
Repeat => BallType.Gen3,
|
|
Timer => BallType.Gen3,
|
|
Luxury => BallType.Gen3,
|
|
Premier => BallType.Gen3,
|
|
|
|
Dusk => BallType.Gen4,
|
|
Heal => BallType.Gen4,
|
|
Quick => BallType.Gen4,
|
|
|
|
Fast => BallType.Apricorn,
|
|
Level => BallType.Apricorn,
|
|
Lure => BallType.Apricorn,
|
|
Heavy => BallType.Apricorn,
|
|
Love => BallType.Apricorn,
|
|
Friend => BallType.Apricorn,
|
|
Moon => BallType.Apricorn,
|
|
|
|
Sport => BallType.Sport,
|
|
Dream => BallType.Dream,
|
|
Beast => BallType.Beast,
|
|
_ => BallType.None,
|
|
};
|
|
|
|
public static ReadOnlySpan<byte> Permit =>
|
|
[
|
|
0x00, 0x6B, 0x03, 0x03, 0x6B, 0x03, 0x03, 0x6B, 0x03, 0x03, 0x7B, 0x03, 0x03, 0x7B, 0x03, 0x03, 0x6F, 0x03, 0x03, 0x6F, // 000-019
|
|
0x03, 0x6F, 0x03, 0x6F, 0x03, 0x03, 0x03, 0x6F, 0x03, 0x2F, 0x03, 0x03, 0x2F, 0x03, 0x03, 0x03, 0x03, 0x6B, 0x03, 0x4B, // 020-039
|
|
0x03, 0x6F, 0x03, 0x2F, 0x03, 0x03, 0x7F, 0x03, 0x3F, 0x03, 0x6F, 0x03, 0x6B, 0x03, 0x6F, 0x03, 0x6B, 0x03, 0x6B, 0x03, // 040-059
|
|
0x6F, 0x03, 0x03, 0x6F, 0x03, 0x03, 0x6F, 0x03, 0x03, 0x6F, 0x03, 0x03, 0x6B, 0x03, 0x6F, 0x03, 0x03, 0x2F, 0x03, 0x6F, // 060-079
|
|
0x03, 0x6F, 0x03, 0x2F, 0x2F, 0x03, 0x6B, 0x03, 0x6F, 0x03, 0x6B, 0x03, 0x6F, 0x03, 0x03, 0x6F, 0x6F, 0x03, 0x2F, 0x03, // 080-099
|
|
0x6F, 0x03, 0x6F, 0x03, 0x6F, 0x03, 0x03, 0x03, 0x6F, 0x2F, 0x03, 0x6F, 0x03, 0x6F, 0x2F, 0x6F, 0x6B, 0x03, 0x6F, 0x03, // 100-119
|
|
0x6B, 0x03, 0x6F, 0x7F, 0x03, 0x03, 0x03, 0x7F, 0x6F, 0x6F, 0x03, 0x6F, 0x00, 0x6B, 0x03, 0x03, 0x03, 0x23, 0x23, 0x03, // 120-139
|
|
0x23, 0x03, 0x23, 0x6B, 0x00, 0x00, 0x00, 0x6F, 0x03, 0x03, 0x00, 0x00, 0x4B, 0x03, 0x03, 0x4B, 0x03, 0x03, 0x4B, 0x03, // 140-159
|
|
0x03, 0x2F, 0x03, 0x6F, 0x03, 0x6F, 0x03, 0x6F, 0x03, 0x03, 0x6B, 0x03, 0x6F, 0x6F, 0x6F, 0x6B, 0x03, 0x6F, 0x03, 0x6F, // 160-179
|
|
0x03, 0x03, 0x03, 0x6F, 0x03, 0x6B, 0x03, 0x2F, 0x03, 0x07, 0x6F, 0x2F, 0x03, 0x6F, 0x6F, 0x03, 0x03, 0x03, 0x6F, 0x03, // 180-199
|
|
0x6F, 0x00, 0x2F, 0x2F, 0x6F, 0x03, 0x6B, 0x2F, 0x03, 0x6F, 0x03, 0x2B, 0x4B, 0x2F, 0x6F, 0x6B, 0x2F, 0x03, 0x6B, 0x03, // 200-219
|
|
0x6B, 0x03, 0x6B, 0x6F, 0x03, 0x6B, 0x6B, 0x6B, 0x6F, 0x03, 0x03, 0x2F, 0x03, 0x03, 0x2F, 0x6F, 0x23, 0x03, 0x6B, 0x6F, // 220-239
|
|
0x6F, 0x6F, 0x03, 0x00, 0x00, 0x00, 0x6F, 0x03, 0x03, 0x00, 0x00, 0x00, 0x6B, 0x03, 0x03, 0x6B, 0x03, 0x03, 0x6B, 0x03, // 240-259
|
|
0x03, 0x2B, 0x03, 0x2F, 0x07, 0x3B, 0x03, 0x03, 0x03, 0x03, 0x6F, 0x03, 0x03, 0x6F, 0x03, 0x03, 0x6B, 0x03, 0x6B, 0x03, // 260-279
|
|
0x6B, 0x03, 0x03, 0x6F, 0x03, 0x2F, 0x03, 0x6F, 0x03, 0x03, 0x33, 0x03, 0x03, 0x2B, 0x03, 0x03, 0x6B, 0x03, 0x6F, 0x6F, // 280-299
|
|
0x23, 0x03, 0x6B, 0x6B, 0x6F, 0x07, 0x03, 0x6F, 0x03, 0x6F, 0x03, 0x2B, 0x2B, 0x37, 0x37, 0x6F, 0x2F, 0x03, 0x6F, 0x03, // 300-319
|
|
0x6B, 0x03, 0x2B, 0x03, 0x6F, 0x6B, 0x03, 0x6F, 0x6F, 0x03, 0x03, 0x27, 0x03, 0x6B, 0x03, 0x27, 0x27, 0x27, 0x27, 0x6F, // 320-339
|
|
0x03, 0x6F, 0x03, 0x6B, 0x03, 0x23, 0x03, 0x23, 0x03, 0x6B, 0x03, 0x6B, 0x6F, 0x6F, 0x03, 0x27, 0x03, 0x6F, 0x2F, 0x6B, // 340-359
|
|
0x2F, 0x6B, 0x03, 0x6F, 0x03, 0x03, 0x6B, 0x03, 0x03, 0x6B, 0x6B, 0x6F, 0x03, 0x03, 0x6F, 0x03, 0x03, 0x00, 0x00, 0x00, // 360-379
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x03, 0x03, 0x6B, 0x03, 0x03, 0x6B, 0x03, 0x03, 0x6F, 0x03, 0x03, 0x2F, // 380-399
|
|
0x03, 0x3B, 0x03, 0x6F, 0x03, 0x03, 0x6F, 0x03, 0x23, 0x03, 0x23, 0x03, 0x2B, 0x03, 0x03, 0x3B, 0x03, 0x27, 0x6F, 0x03, // 400-419
|
|
0x2B, 0x03, 0x6B, 0x03, 0x03, 0x6B, 0x03, 0x6B, 0x03, 0x03, 0x03, 0x23, 0x03, 0x2F, 0x23, 0x03, 0x2F, 0x03, 0x6B, 0x6F, // 420-439
|
|
0x6F, 0x2B, 0x23, 0x6F, 0x03, 0x03, 0x6B, 0x6F, 0x03, 0x6F, 0x03, 0x6F, 0x03, 0x27, 0x03, 0x2F, 0x6B, 0x03, 0x6B, 0x6B, // 440-459
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x6B, // 460-479
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4B, 0x03, 0x03, 0x4B, 0x03, // 480-499
|
|
0x03, 0x4B, 0x03, 0x03, 0x03, 0x03, 0x4B, 0x03, 0x03, 0x03, 0x03, 0x23, 0x03, 0x23, 0x03, 0x23, 0x03, 0x23, 0x03, 0x23, // 500-519
|
|
0x03, 0x03, 0x03, 0x03, 0x6B, 0x03, 0x03, 0x03, 0x03, 0x23, 0x03, 0x6B, 0x6B, 0x03, 0x03, 0x23, 0x03, 0x03, 0x23, 0x23, // 520-539
|
|
0x4B, 0x03, 0x03, 0x6B, 0x03, 0x03, 0x6B, 0x03, 0x6B, 0x03, 0x6B, 0x6B, 0x03, 0x03, 0x03, 0x03, 0x23, 0x6B, 0x03, 0x6B, // 540-559
|
|
0x03, 0x6B, 0x03, 0x03, 0x23, 0x03, 0x00, 0x03, 0x4B, 0x03, 0x4B, 0x03, 0x4B, 0x03, 0x6B, 0x03, 0x03, 0x6B, 0x03, 0x03, // 560-579
|
|
0x6B, 0x03, 0x6B, 0x03, 0x03, 0x03, 0x03, 0x6B, 0x23, 0x03, 0x03, 0x03, 0x4B, 0x03, 0x6B, 0x23, 0x03, 0x03, 0x03, 0x6B, // 580-599
|
|
0x03, 0x03, 0x4B, 0x03, 0x03, 0x6B, 0x03, 0x4B, 0x03, 0x03, 0x6B, 0x03, 0x03, 0x03, 0x03, 0x03, 0x23, 0x03, 0x6B, 0x4B, // 600-619
|
|
0x03, 0x6B, 0x6B, 0x03, 0x6B, 0x03, 0x03, 0x4B, 0x03, 0x4B, 0x03, 0x23, 0x23, 0x4B, 0x03, 0x03, 0x4B, 0x03, 0x00, 0x00, // 620-639
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4B, 0x03, 0x03, 0x4B, 0x03, 0x03, 0x4B, 0x03, 0x03, 0x03, // 640-659
|
|
0x03, 0x4B, 0x03, 0x4B, 0x4B, 0x03, 0x03, 0x4B, 0x03, 0x4B, 0x03, 0x03, 0x03, 0x03, 0x4B, 0x03, 0x4B, 0x03, 0x03, 0x4B, // 660-679
|
|
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x4B, 0x03, 0x4B, 0x03, 0x4B, 0x03, 0x4B, 0x03, 0x4B, 0x03, 0x00, 0x03, 0x00, 0x03, // 680-699
|
|
0x03, 0x4B, 0x4B, 0x4B, 0x4B, 0x03, 0x03, 0x4B, 0x4B, 0x03, 0x03, 0x03, 0x03, 0x03, 0x4B, 0x03, 0x00, 0x00, 0x00, 0x00, // 700-719
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4B, 0x43, 0x43, 0x4B, 0x43, 0x4B, 0x43, 0x43, 0x4B, // 720-739
|
|
0x43, 0x4B, 0x4B, 0x43, 0x4B, 0x43, 0x4B, 0x4B, 0x43, 0x4B, 0x43, 0x4B, 0x43, 0x4B, 0x43, 0x4B, 0x43, 0x4B, 0x43, 0x4B, // 740-759
|
|
0x43, 0x4B, 0x43, 0x43, 0x4B, 0x4B, 0x4B, 0x4B, 0x43, 0x4B, 0x43, 0x4B, 0x00, 0x00, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, // 760-779
|
|
0x4B, 0x4B, 0x4B, 0x43, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 780-799
|
|
];
|
|
|
|
private enum BallType : byte
|
|
{
|
|
Gen3 = 0,
|
|
Gen4 = 1,
|
|
Safari = 2,
|
|
Apricorn = 3,
|
|
Sport = 4,
|
|
Dream = 5,
|
|
Beast = 6,
|
|
|
|
None = 9,
|
|
}
|
|
}
|