PKHeX/PKHeX.Core/Legality/Verifiers/MarkingVerifier.cs
Kurt 325f75e3d3 Gen12 strings: span instead of runtime dictionary
More performant byte->str performance (no longer needing to hash byte and fetch bucket), unmeasured str->byte performance, but it is the same implementation as Gen3 which is not a bottleneck.
Reduces the dll size by 80KB, and RAM usage by an unmeasured (likely similar amount). Better startup speeds since multiple dictionaries do not need to be allocated and created.

Moves Gen1 trainer names (0x5D) to Transporter class, and remove Korean entry (not legally obtainable since there's only Gen2 Korean games and Gen2 Korean VC cannot trade with international).

Hard verify Gen1 trainer name for language, since 0x5D is the ROM transfer language. Nickname can still be from any of the connected games.

This refactor makes it easier to use a different charmap for byte<->str for Boxes (see #4027) and the language differences. We have a master table that "works" for all text name entry, but localizations differ for some glyphs accessible in the box naming UI.
2023-10-25 16:34:11 -07:00

82 lines
2.3 KiB
C#

using static PKHeX.Core.LegalityCheckStrings;
using static PKHeX.Core.CheckIdentifier;
namespace PKHeX.Core;
/// <summary>
/// Verifies the <see cref="PKM.MarkValue"/>.
/// </summary>
public sealed class MarkingVerifier : Verifier
{
protected override CheckIdentifier Identifier => Marking;
public override void Verify(LegalityAnalysis data)
{
var pk = data.Entity;
VerifyFavoriteMark(data, pk);
VerifyMarkValue(data, pk);
}
private void VerifyFavoriteMark(LegalityAnalysis data, PKM pk)
{
// Can only be toggled on in LGP/E, and is retained via transfer to HOME and into other games.
if (pk is IFavorite { IsFavorite: true } && !data.Info.EvoChainsAllGens.HasVisitedLGPE)
data.AddLine(GetInvalid(LFavoriteMarkingUnavailable));
}
private void VerifyMarkValue(LegalityAnalysis data, PKM pk)
{
var mv = pk.MarkValue;
if (mv == 0)
return;
// Eggs can have markings applied.
//if (pk.IsEgg)
//{
// data.AddLine(GetInvalid(LMarkValueShouldBeZero));
// return;
//}
switch (pk.Format)
{
case <= 2:
return;
case <= 6:
VerifyMarkValueSingle(data, pk, mv);
return;
default:
VerifyMarkValueDual(data, pk, mv);
return;
}
}
private const int Single4 = 0b_1111;
private const int Single6 = 0b_111111;
private const int Dual6 = 0b_1111_1111_1111;
private void VerifyMarkValueDual(LegalityAnalysis data, PKM pk, int mv)
{
if (mv > Dual6)
data.AddLine(GetInvalid(LMarkValueUnusedBitsPresent));
var count = pk.MarkingCount;
for (int i = 0; i < count; i++)
{
var value = pk.GetMarking(i);
if (value is not (0 or 1 or 2))
data.AddLine(GetInvalid(string.Format(LMarkValueOutOfRange_0, i)));
}
}
private void VerifyMarkValueSingle(LegalityAnalysis data, PKM pk, int mv)
{
if (!IsMarkValueValid3456(pk, mv))
data.AddLine(GetInvalid(LMarkValueUnusedBitsPresent));
}
private static bool IsMarkValueValid3456(PKM pk, int value)
{
var max = pk.Format is 3 ? Single4 : Single6;
return value <= max;
}
}