Reduce allocation in methodfinder IV set

This commit is contained in:
Kurt
2022-03-13 19:39:38 -07:00
parent d5ae6764aa
commit d95ba482f3
8 changed files with 33 additions and 36 deletions

View File

@@ -1,4 +1,6 @@
namespace PKHeX.Core
using System;
namespace PKHeX.Core
{
public static class HiddenPowerApplicator
{
@@ -9,9 +11,10 @@ public static class HiddenPowerApplicator
/// <param name="hiddenPowerType">Desired Hidden Power typing.</param>
public static void SetHiddenPower(this PKM pk, int hiddenPowerType)
{
var IVs = pk.IVs;
Span<int> IVs = stackalloc int[6];
pk.GetIVs(IVs);
HiddenPower.SetIVsForType(hiddenPowerType, IVs, pk.Format);
pk.IVs = IVs;
pk.SetIVs(IVs);
}
/// <summary>

View File

@@ -40,7 +40,9 @@ public static void SetMarkings(this PKM pk)
if (pk.Format <= 3)
return; // no markings (gen3 only has 4; can't mark stats intelligently
pk.SetMarkings(pk.IVs);
Span<int> IVs = stackalloc int[6];
pk.GetIVs(IVs);
pk.SetMarkings(IVs);
}
/// <summary>

View File

@@ -174,7 +174,7 @@ public static void ApplySetDetails(this PKM pk, IBattleTemplate Set)
pk.ApplyHeldItem(Set.HeldItem, Set.Format);
pk.CurrentLevel = Set.Level;
pk.CurrentFriendship = Set.Friendship;
pk.IVs = Set.IVs;
pk.SetIVs(Set.IVs);
if (pk is GBPKM gb)
{

View File

@@ -166,7 +166,7 @@ private void SetEncounterMoves(PKM pk, GameVersion version, int level)
protected void SetIVs(PKM pk)
{
if (IVs.Count != 0)
pk.SetRandomIVs(IVs, FlawlessIVCount);
pk.SetRandomIVs((int[])IVs, FlawlessIVCount);
else if (FlawlessIVCount > 0)
pk.SetRandomIVs(flawless: FlawlessIVCount);
}

View File

@@ -151,7 +151,7 @@ protected virtual void SetPINGA(PKM pk, EncounterCriteria criteria)
protected void SetIVs(PKM pk)
{
if (IVs.Count != 0)
pk.SetRandomIVs(IVs, 0);
pk.SetRandomIVs((int[])IVs, 0);
else
pk.SetRandomIVs(flawless: 3);
}

View File

@@ -722,33 +722,18 @@ private static bool IVsMatch(uint r1, uint r2, ReadOnlySpan<uint> IVs)
/// <summary>
/// Generates IVs from 2 RNG calls using 15 bits of each to generate 6 IVs (5bits each).
/// </summary>
/// <param name="result">Result storage</param>
/// <param name="r1">First rand frame</param>
/// <param name="r2">Second rand frame</param>
/// <returns>Array of 6 IVs</returns>
internal static uint[] GetIVs(uint r1, uint r2)
internal static void GetIVsInt32(Span<int> result, uint r1, uint r2)
{
return new[]
{
r1 & 31,
r1 >> 5 & 31,
r1 >> 10 & 31,
r2 & 31,
r2 >> 5 & 31,
r2 >> 10 & 31,
};
}
internal static int[] GetIVsInt32(uint r1, uint r2)
{
return new[]
{
(int)r1 & 31,
(int)r1 >> 5 & 31,
(int)r1 >> 10 & 31,
(int)r2 & 31,
(int)r2 >> 5 & 31,
(int)r2 >> 10 & 31,
};
result[5] = (int)r2 >> 10 & 31;
result[4] = (int)r2 >> 5 & 31;
result[3] = (int)r2 & 31;
result[2] = (int)r1 >> 10 & 31;
result[1] = (int)r1 >> 5 & 31;
result[0] = (int)r1 & 31;
}
private static uint GetIVChunk(ReadOnlySpan<uint> IVs, int start)

View File

@@ -32,7 +32,8 @@ private static void SetValuesFromSeedLCRNG(PKM pk, PIDType type, uint seed)
if (skipIV2Frame) // VBlank skip between IVs
D = rng.Next(D);
var IVs = MethodFinder.GetIVsInt32(C >> 16, D >> 16);
Span<int> IVs = stackalloc int[6];
MethodFinder.GetIVsInt32(IVs, C >> 16, D >> 16);
if (type == PIDType.Method_1_Roamer)
{
// Only store lowest 8 bits of IV data; zero out the other bits.
@@ -40,7 +41,7 @@ private static void SetValuesFromSeedLCRNG(PKM pk, PIDType type, uint seed)
for (int i = 2; i < 6; i++)
IVs[i] = 0;
}
pk.IVs = IVs;
pk.SetIVs(IVs);
}
private static void SetValuesFromSeedBACD(PKM pk, PIDType type, uint seed)
@@ -71,7 +72,9 @@ private static void SetValuesFromSeedBACD(PKM pk, PIDType type, uint seed)
pk.PID = (A & 0xFFFF0000) | B >> 16;
}
pk.IVs = MethodFinder.GetIVsInt32(C >> 16, D >> 16);
Span<int> IVs = stackalloc int[6];
MethodFinder.GetIVsInt32(IVs, C >> 16, D >> 16);
pk.SetIVs(IVs);
bool antishiny = type is PIDType.BACD_R_A or PIDType.BACD_U_A;
while (antishiny && pk.IsShiny)
@@ -101,7 +104,9 @@ private static void SetValuesFromSeedXDRNG(PKM pk, uint seed)
var E = rng.Next(D); // PID
pk.PID = (D & 0xFFFF0000) | E >> 16;
pk.IVs = MethodFinder.GetIVsInt32(A >> 16, B >> 16);
Span<int> IVs = stackalloc int[6];
MethodFinder.GetIVsInt32(IVs, A >> 16, B >> 16);
pk.SetIVs(IVs);
}
public static void SetValuesFromSeedXDRNG_EReader(PKM pk, uint seed)
@@ -207,7 +212,9 @@ public static void SetRandomChainShinyPID(PKM pk, uint seed)
upper = ((uint)(lower ^ pk.TID ^ pk.SID) & 0xFFF8) | (upper & 0x7);
pk.PID = upper << 16 | lower;
pk.IVs = MethodFinder.GetIVsInt32(Next(), Next());
Span<int> IVs = stackalloc int[6];
MethodFinder.GetIVsInt32(IVs, Next(), Next());
pk.SetIVs(IVs);
}
public static void SetRandomPokeSpotPID(PKM pk, int nature, int gender, int ability, int slot)

View File

@@ -972,7 +972,7 @@ public int[] SetRandomIVsGO(int minIV = 0, int maxIV = 15)
/// <param name="template">IV template to generate from</param>
/// <param name="flawless">Count of flawless IVs to set. If none provided, a count will be detected.</param>
/// <returns>Randomized IVs if desired.</returns>
public int[] SetRandomIVs(IReadOnlyList<int> template, int? flawless = null)
public int[] SetRandomIVs(ReadOnlySpan<int> template, int? flawless = null)
{
int count = flawless ?? GetFlawlessIVCount();
int[] ivs = new int[6];