From d5ae6764aa0cd9b02d41fdde3b006a7bb970a7b4 Mon Sep 17 00:00:00 2001 From: Kurt Date: Sun, 13 Mar 2022 19:24:08 -0700 Subject: [PATCH] Stackalloc IVs for template->pkm fill --- PKHeX.Core/Legality/Core.cs | 4 +-- .../EncounterStatic/EncounterStatic.cs | 2 +- .../EncounterTrade/EncounterTrade.cs | 2 +- .../EncounterTrade/EncounterTrade2.cs | 2 +- .../Verifiers/IndividualValueVerifier.cs | 9 ++--- PKHeX.Core/MysteryGifts/MysteryGift.cs | 2 ++ PKHeX.Core/MysteryGifts/PCD.cs | 2 ++ PKHeX.Core/MysteryGifts/PGF.cs | 17 ++++++++-- PKHeX.Core/MysteryGifts/PGT.cs | 6 ++++ PKHeX.Core/MysteryGifts/WA8.cs | 29 +++++++++++++--- PKHeX.Core/MysteryGifts/WB7.cs | 29 +++++++++++++--- PKHeX.Core/MysteryGifts/WB8.cs | 29 +++++++++++++--- PKHeX.Core/MysteryGifts/WC3.cs | 1 + PKHeX.Core/MysteryGifts/WC6.cs | 33 +++++++++++++++---- PKHeX.Core/MysteryGifts/WC7.cs | 29 +++++++++++++--- PKHeX.Core/MysteryGifts/WC8.cs | 29 +++++++++++++--- PKHeX.Core/PKM/PKM.cs | 12 +++++++ PKHeX.Core/Util/ArrayUtil.cs | 10 ++++++ 18 files changed, 204 insertions(+), 43 deletions(-) diff --git a/PKHeX.Core/Legality/Core.cs b/PKHeX.Core/Legality/Core.cs index 54a27b3e2..5d715d34f 100644 --- a/PKHeX.Core/Legality/Core.cs +++ b/PKHeX.Core/Legality/Core.cs @@ -248,7 +248,7 @@ internal static bool IsMovesetRestricted(this PKM pkm, int gen) _ => generation >= 6 ? 12 : 10, }; - public static bool GetIsFixedIVSequenceValidSkipRand(IReadOnlyList IVs, PKM pkm, int max = 31) + public static bool GetIsFixedIVSequenceValidSkipRand(ReadOnlySpan IVs, PKM pkm, int max = 31) { for (int i = 0; i < 6; i++) { @@ -260,7 +260,7 @@ public static bool GetIsFixedIVSequenceValidSkipRand(IReadOnlyList IVs, PKM return true; } - public static bool GetIsFixedIVSequenceValidNoRand(IReadOnlyList IVs, PKM pkm) + public static bool GetIsFixedIVSequenceValidNoRand(ReadOnlySpan IVs, PKM pkm) { for (int i = 0; i < 6; i++) { diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic.cs index 9e3220548..a4cadeda6 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic.cs @@ -253,7 +253,7 @@ private bool IsMatchIVs(PKM pkm) if (Generation <= 2 && pkm.Format > 2) return true; // IVs are regenerated on VC transfer upward - return Legal.GetIsFixedIVSequenceValidSkipRand(IVs, pkm); + return Legal.GetIsFixedIVSequenceValidSkipRand((int[])IVs, pkm); } protected virtual bool IsMatchForm(PKM pkm, DexLevel evo) diff --git a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade.cs b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade.cs index 9568e8462..cde65bc7d 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade.cs @@ -182,7 +182,7 @@ public virtual bool IsMatchExact(PKM pkm, DexLevel evo) { if (IVs.Count != 0) { - if (!Legal.GetIsFixedIVSequenceValidSkipRand(IVs, pkm)) + if (!Legal.GetIsFixedIVSequenceValidSkipRand((int[])IVs, pkm)) return false; } diff --git a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade2.cs b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade2.cs index 90535f554..f042944c5 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade2.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade2.cs @@ -27,7 +27,7 @@ public override bool IsMatchExact(PKM pkm, DexLevel dl) { if (Gender >= 0 && Gender != pkm.Gender) return false; - if (IVs.Count != 0 && !Legal.GetIsFixedIVSequenceValidNoRand(IVs, pkm)) + if (IVs.Count != 0 && !Legal.GetIsFixedIVSequenceValidNoRand((int[])IVs, pkm)) return false; if (pkm.Format == 2 && pkm.Met_Location is not (0 or 126)) return false; diff --git a/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs b/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs index a830c2730..e980ac75d 100644 --- a/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/IndividualValueVerifier.cs @@ -42,11 +42,12 @@ private static bool AllIVsEqual(PKM pkm, int hpiv) private void VerifyIVsMystery(LegalityAnalysis data, MysteryGift g) { - var IVs = g.IVs; - if (IVs.Length == 0) - return; + if (!g.HasFixedIVs) + return; // PID/IV style instead of fixed IVs. - var ivflag = Array.Find(IVs, iv => (byte)(iv - 0xFC) < 3); + Span IVs = stackalloc int[6]; + g.GetIVs(IVs); + var ivflag = IVs.Find(iv => (byte)(iv - 0xFC) < 3); if (ivflag == 0) // Random IVs { bool valid = Legal.GetIsFixedIVSequenceValidSkipRand(IVs, data.pkm); diff --git a/PKHeX.Core/MysteryGifts/MysteryGift.cs b/PKHeX.Core/MysteryGifts/MysteryGift.cs index 57cba7af4..500393d96 100644 --- a/PKHeX.Core/MysteryGifts/MysteryGift.cs +++ b/PKHeX.Core/MysteryGifts/MysteryGift.cs @@ -134,6 +134,8 @@ public virtual GameVersion Version public virtual IReadOnlyList Moves { get => Array.Empty(); set { } } public virtual IReadOnlyList Relearn { get => Array.Empty(); set { } } public virtual int[] IVs { get => Array.Empty(); set { } } + public virtual bool HasFixedIVs => true; + public virtual void GetIVs(Span value) { } public virtual bool IsShiny => false; public virtual Shiny Shiny diff --git a/PKHeX.Core/MysteryGifts/PCD.cs b/PKHeX.Core/MysteryGifts/PCD.cs index e6db67deb..1e329683b 100644 --- a/PKHeX.Core/MysteryGifts/PCD.cs +++ b/PKHeX.Core/MysteryGifts/PCD.cs @@ -88,6 +88,8 @@ public override string CardTitle public override int SID { get => Gift.SID; set => Gift.SID = value; } public override string OT_Name { get => Gift.OT_Name; set => Gift.OT_Name = value; } public override AbilityPermission Ability => Gift.Ability; + public override bool HasFixedIVs => Gift.HasFixedIVs; + public override void GetIVs(Span value) => Gift.GetIVs(value); // ILocation overrides public override int Location { get => IsEgg ? 0 : Gift.EggLocation + 3000; set { } } diff --git a/PKHeX.Core/MysteryGifts/PGF.cs b/PKHeX.Core/MysteryGifts/PGF.cs index 4471a7fc5..4832d1972 100644 --- a/PKHeX.Core/MysteryGifts/PGF.cs +++ b/PKHeX.Core/MysteryGifts/PGF.cs @@ -155,6 +155,18 @@ public override int[] IVs } } + public override void GetIVs(Span value) + { + if (value.Length != 6) + return; + value[0] = IV_HP; + value[1] = IV_ATK; + value[2] = IV_DEF; + value[3] = IV_SPE; + value[4] = IV_SPA; + value[5] = IV_SPD; + } + public bool IsNicknamed => Nickname.Length > 0; public override bool IsShiny => PIDType == 2; public override int Location { get => MetLocation; set => MetLocation = (ushort)value; } @@ -339,9 +351,10 @@ private void SetPID(PKM pk, int av) private void SetIVs(PKM pk) { Span finalIVs = stackalloc int[6]; + GetIVs(finalIVs); var rnd = Util.Rand; - for (int i = 0; i < IVs.Length; i++) - finalIVs[i] = IVs[i] == 0xFF ? rnd.Next(32) : IVs[i]; + for (int i = 0; i < finalIVs.Length; i++) + finalIVs[i] = finalIVs[i] == 0xFF ? rnd.Next(32) : finalIVs[i]; pk.SetIVs(finalIVs); } diff --git a/PKHeX.Core/MysteryGifts/PGT.cs b/PKHeX.Core/MysteryGifts/PGT.cs index 314107743..2f3f8c302 100644 --- a/PKHeX.Core/MysteryGifts/PGT.cs +++ b/PKHeX.Core/MysteryGifts/PGT.cs @@ -119,6 +119,12 @@ private void EncryptPK() public override string OT_Name { get => PK.OT_Name; set => PK.OT_Name = value; } public override int Location { get => PK.Met_Location; set => PK.Met_Location = value; } public override int EggLocation { get => PK.Egg_Location; set => PK.Egg_Location = value; } + public override bool HasFixedIVs => PK.IV32 != 0; + public override void GetIVs(Span value) + { + if (HasFixedIVs) + PK.GetIVs(value); + } public override PKM ConvertToPKM(ITrainerInfo sav, EncounterCriteria criteria) { diff --git a/PKHeX.Core/MysteryGifts/WA8.cs b/PKHeX.Core/MysteryGifts/WA8.cs index 6f34dc744..189e12ca4 100644 --- a/PKHeX.Core/MysteryGifts/WA8.cs +++ b/PKHeX.Core/MysteryGifts/WA8.cs @@ -254,6 +254,18 @@ public override int[] IVs } } + public override void GetIVs(Span value) + { + if (value.Length != 6) + return; + value[0] = IV_HP; + value[1] = IV_ATK; + value[2] = IV_DEF; + value[3] = IV_SPE; + value[4] = IV_SPA; + value[5] = IV_SPD; + } + public int[] EVs { get => new[] { EV_HP, EV_ATK, EV_DEF, EV_SPE, EV_SPA, EV_SPD }; @@ -541,20 +553,27 @@ private void SetPID(PKM pk) private void SetIVs(PKM pk) { Span finalIVs = stackalloc int[6]; - var ivflag = Array.Find(IVs, iv => (byte)(iv - 0xFC) < 3); + GetIVs(finalIVs); + var ivflag = finalIVs.Find(iv => (byte)(iv - 0xFC) < 3); var rng = Util.Rand; if (ivflag == 0) // Random IVs { - for (int i = 0; i < 6; i++) - finalIVs[i] = IVs[i] > 31 ? rng.Next(32) : IVs[i]; + for (int i = 0; i < finalIVs.Length; i++) + { + if (finalIVs[i] > 31) + finalIVs[i] = rng.Next(32); + } } else // 1/2/3 perfect IVs { int IVCount = ivflag - 0xFB; do { finalIVs[rng.Next(6)] = 31; } while (finalIVs.Count(31) < IVCount); - for (int i = 0; i < 6; i++) - finalIVs[i] = finalIVs[i] == 31 ? 31 : rng.Next(32); + for (int i = 0; i < finalIVs.Length; i++) + { + if (finalIVs[i] != 31) + finalIVs[i] = rng.Next(32); + } } pk.SetIVs(finalIVs); } diff --git a/PKHeX.Core/MysteryGifts/WB7.cs b/PKHeX.Core/MysteryGifts/WB7.cs index 95c59d7dd..5fca3ad78 100644 --- a/PKHeX.Core/MysteryGifts/WB7.cs +++ b/PKHeX.Core/MysteryGifts/WB7.cs @@ -244,6 +244,18 @@ public override int[] IVs } } + public override void GetIVs(Span value) + { + if (value.Length != 6) + return; + value[0] = IV_HP; + value[1] = IV_ATK; + value[2] = IV_DEF; + value[3] = IV_SPE; + value[4] = IV_SPA; + value[5] = IV_SPD; + } + public bool GetIsNicknamed(int language) => Data[GetNicknameOffset(language)] != 0; private static int GetLanguageIndex(int language) @@ -469,20 +481,27 @@ private void SetPID(PKM pk) private void SetIVs(PKM pk) { Span finalIVs = stackalloc int[6]; - var ivflag = Array.Find(IVs, iv => (byte)(iv - 0xFC) < 3); + GetIVs(finalIVs); + var ivflag = finalIVs.Find(iv => (byte)(iv - 0xFC) < 3); var rng = Util.Rand; if (ivflag == 0) // Random IVs { - for (int i = 0; i < 6; i++) - finalIVs[i] = IVs[i] > 31 ? rng.Next(32) : IVs[i]; + for (int i = 0; i < finalIVs.Length; i++) + { + if (finalIVs[i] > 31) + finalIVs[i] = rng.Next(32); + } } else // 1/2/3 perfect IVs { int IVCount = ivflag - 0xFB; do { finalIVs[rng.Next(6)] = 31; } while (finalIVs.Count(31) < IVCount); - for (int i = 0; i < 6; i++) - finalIVs[i] = finalIVs[i] == 31 ? 31 : rng.Next(32); + for (int i = 0; i < finalIVs.Length; i++) + { + if (finalIVs[i] != 31) + finalIVs[i] = rng.Next(32); + } } pk.SetIVs(finalIVs); } diff --git a/PKHeX.Core/MysteryGifts/WB8.cs b/PKHeX.Core/MysteryGifts/WB8.cs index f321fe355..d045406f2 100644 --- a/PKHeX.Core/MysteryGifts/WB8.cs +++ b/PKHeX.Core/MysteryGifts/WB8.cs @@ -249,6 +249,18 @@ public override int[] IVs } } + public override void GetIVs(Span value) + { + if (value.Length != 6) + return; + value[0] = IV_HP; + value[1] = IV_ATK; + value[2] = IV_DEF; + value[3] = IV_SPE; + value[4] = IV_SPA; + value[5] = IV_SPD; + } + public int[] EVs { get => new[] { EV_HP, EV_ATK, EV_DEF, EV_SPE, EV_SPA, EV_SPD }; @@ -537,20 +549,27 @@ private void SetPID(PKM pk) private void SetIVs(PKM pk) { Span finalIVs = stackalloc int[6]; - var ivflag = Array.Find(IVs, iv => (byte)(iv - 0xFC) < 3); + GetIVs(finalIVs); + var ivflag = finalIVs.Find(iv => (byte)(iv - 0xFC) < 3); var rng = Util.Rand; if (ivflag == 0) // Random IVs { - for (int i = 0; i < 6; i++) - finalIVs[i] = IVs[i] > 31 ? rng.Next(32) : IVs[i]; + for (int i = 0; i < finalIVs.Length; i++) + { + if (finalIVs[i] > 31) + finalIVs[i] = rng.Next(32); + } } else // 1/2/3 perfect IVs { int IVCount = ivflag - 0xFB; do { finalIVs[rng.Next(6)] = 31; } while (finalIVs.Count(31) < IVCount); - for (int i = 0; i < 6; i++) - finalIVs[i] = finalIVs[i] == 31 ? 31 : rng.Next(32); + for (int i = 0; i < finalIVs.Length; i++) + { + if (finalIVs[i] != 31) + finalIVs[i] = rng.Next(32); + } } pk.SetIVs(finalIVs); } diff --git a/PKHeX.Core/MysteryGifts/WC3.cs b/PKHeX.Core/MysteryGifts/WC3.cs index 93e6da6b3..1a0d0f9ce 100644 --- a/PKHeX.Core/MysteryGifts/WC3.cs +++ b/PKHeX.Core/MysteryGifts/WC3.cs @@ -40,6 +40,7 @@ public sealed class WC3 : MysteryGift, IRibbonSetEvent3, ILangNicknamedTemplate public override byte Level { get; set; } public override int Ball { get; set; } = 4; public override bool IsShiny => Shiny == Shiny.Always; + public override bool HasFixedIVs => false; public bool RibbonEarth { get; set; } public bool RibbonNational { get; set; } public bool RibbonCountry { get; set; } diff --git a/PKHeX.Core/MysteryGifts/WC6.cs b/PKHeX.Core/MysteryGifts/WC6.cs index 585aec149..ab1e3d076 100644 --- a/PKHeX.Core/MysteryGifts/WC6.cs +++ b/PKHeX.Core/MysteryGifts/WC6.cs @@ -473,23 +473,42 @@ private void SetPID(PKM pk) } } + public override void GetIVs(Span value) + { + if (value.Length != 6) + return; + value[0] = IV_HP; + value[1] = IV_ATK; + value[2] = IV_DEF; + value[3] = IV_SPE; + value[4] = IV_SPA; + value[5] = IV_SPD; + } + private void SetIVs(PKM pk) { Span finalIVs = stackalloc int[6]; - var ivflag = Array.Find(IVs, iv => (byte)(iv - 0xFC) < 3); - var rnd = Util.Rand; + GetIVs(finalIVs); + var ivflag = finalIVs.Find(iv => (byte)(iv - 0xFC) < 3); + var rng = Util.Rand; if (ivflag == 0) // Random IVs { - for (int i = 0; i < 6; i++) - finalIVs[i] = IVs[i] > 31 ? rnd.Next(32) : IVs[i]; + for (int i = 0; i < finalIVs.Length; i++) + { + if (finalIVs[i] > 31) + finalIVs[i] = rng.Next(32); + } } else // 1/2/3 perfect IVs { int IVCount = ivflag - 0xFB; - do { finalIVs[rnd.Next(6)] = 31; } + do { finalIVs[rng.Next(6)] = 31; } while (finalIVs.Count(31) < IVCount); - for (int i = 0; i < 6; i++) - finalIVs[i] = finalIVs[i] == 31 ? 31 : rnd.Next(32); + for (int i = 0; i < finalIVs.Length; i++) + { + if (finalIVs[i] != 31) + finalIVs[i] = rng.Next(32); + } } pk.SetIVs(finalIVs); } diff --git a/PKHeX.Core/MysteryGifts/WC7.cs b/PKHeX.Core/MysteryGifts/WC7.cs index 7cb5527b0..86e8bbe27 100644 --- a/PKHeX.Core/MysteryGifts/WC7.cs +++ b/PKHeX.Core/MysteryGifts/WC7.cs @@ -295,6 +295,18 @@ public override int[] IVs } } + public override void GetIVs(Span value) + { + if (value.Length != 6) + return; + value[0] = IV_HP; + value[1] = IV_ATK; + value[2] = IV_DEF; + value[3] = IV_SPE; + value[4] = IV_SPA; + value[5] = IV_SPD; + } + public int[] EVs { get => new[] { EV_HP, EV_ATK, EV_DEF, EV_SPE, EV_SPA, EV_SPD }; @@ -507,20 +519,27 @@ private void SetPID(PKM pk) private void SetIVs(PKM pk) { Span finalIVs = stackalloc int[6]; - var ivflag = Array.Find(IVs, iv => (byte)(iv - 0xFC) < 3); + GetIVs(finalIVs); + var ivflag = finalIVs.Find(iv => (byte)(iv - 0xFC) < 3); var rng = Util.Rand; if (ivflag == 0) // Random IVs { - for (int i = 0; i < 6; i++) - finalIVs[i] = IVs[i] > 31 ? rng.Next(32) : IVs[i]; + for (int i = 0; i < finalIVs.Length; i++) + { + if (finalIVs[i] > 31) + finalIVs[i] = rng.Next(32); + } } else // 1/2/3 perfect IVs { int IVCount = ivflag - 0xFB; do { finalIVs[rng.Next(6)] = 31; } while (finalIVs.Count(31) < IVCount); - for (int i = 0; i < 6; i++) - finalIVs[i] = finalIVs[i] == 31 ? 31 : rng.Next(32); + for (int i = 0; i < finalIVs.Length; i++) + { + if (finalIVs[i] != 31) + finalIVs[i] = rng.Next(32); + } } pk.SetIVs(finalIVs); } diff --git a/PKHeX.Core/MysteryGifts/WC8.cs b/PKHeX.Core/MysteryGifts/WC8.cs index 66fac4f45..65f30adb2 100644 --- a/PKHeX.Core/MysteryGifts/WC8.cs +++ b/PKHeX.Core/MysteryGifts/WC8.cs @@ -241,6 +241,18 @@ public override int[] IVs } } + public override void GetIVs(Span value) + { + if (value.Length != 6) + return; + value[0] = IV_HP; + value[1] = IV_ATK; + value[2] = IV_DEF; + value[3] = IV_SPE; + value[4] = IV_SPA; + value[5] = IV_SPD; + } + public int[] EVs { get => new[] { EV_HP, EV_ATK, EV_DEF, EV_SPE, EV_SPA, EV_SPD }; @@ -540,20 +552,27 @@ private void SetPID(PKM pk) private void SetIVs(PKM pk) { Span finalIVs = stackalloc int[6]; - var ivflag = Array.Find(IVs, iv => (byte)(iv - 0xFC) < 3); + GetIVs(finalIVs); + var ivflag = finalIVs.Find(iv => (byte)(iv - 0xFC) < 3); var rng = Util.Rand; if (ivflag == 0) // Random IVs { - for (int i = 0; i < 6; i++) - finalIVs[i] = IVs[i] > 31 ? rng.Next(32) : IVs[i]; + for (int i = 0; i < finalIVs.Length; i++) + { + if (finalIVs[i] > 31) + finalIVs[i] = rng.Next(32); + } } else // 1/2/3 perfect IVs { int IVCount = ivflag - 0xFB; do { finalIVs[rng.Next(6)] = 31; } while (finalIVs.Count(31) < IVCount); - for (int i = 0; i < 6; i++) - finalIVs[i] = finalIVs[i] == 31 ? 31 : rng.Next(32); + for (int i = 0; i < finalIVs.Length; i++) + { + if (finalIVs[i] != 31) + finalIVs[i] = rng.Next(32); + } } pk.SetIVs(finalIVs); } diff --git a/PKHeX.Core/PKM/PKM.cs b/PKHeX.Core/PKM/PKM.cs index 0bd2a92fc..c5bcad616 100644 --- a/PKHeX.Core/PKM/PKM.cs +++ b/PKHeX.Core/PKM/PKM.cs @@ -376,6 +376,18 @@ public int[] IVs set => SetIVs(value); } + public void GetIVs(Span value) + { + if (value.Length != 6) + return; + value[0] = IV_HP; + value[1] = IV_ATK; + value[2] = IV_DEF; + value[3] = IV_SPE; + value[4] = IV_SPA; + value[5] = IV_SPD; + } + public void SetIVs(ReadOnlySpan value) { if (value.Length != 6) diff --git a/PKHeX.Core/Util/ArrayUtil.cs b/PKHeX.Core/Util/ArrayUtil.cs index afdccc28e..a89adc919 100644 --- a/PKHeX.Core/Util/ArrayUtil.cs +++ b/PKHeX.Core/Util/ArrayUtil.cs @@ -23,6 +23,16 @@ public static bool IsRangeEmpty(this ReadOnlySpan data, byte value = 0) return ((ReadOnlySpan)data).Count(value); } + public static T Find(this Span data, Func value) where T : unmanaged + { + foreach (var x in data) + { + if (value(x)) + return x; + } + return default; + } + public static int Count(this ReadOnlySpan data, T value) where T : IEquatable { int count = 0;