Stackalloc IVs for template->pkm fill

This commit is contained in:
Kurt 2022-03-13 19:24:08 -07:00
parent 8f8726ac5e
commit d5ae6764aa
18 changed files with 204 additions and 43 deletions

View file

@ -248,7 +248,7 @@ namespace PKHeX.Core
_ => generation >= 6 ? 12 : 10,
};
public static bool GetIsFixedIVSequenceValidSkipRand(IReadOnlyList<int> IVs, PKM pkm, int max = 31)
public static bool GetIsFixedIVSequenceValidSkipRand(ReadOnlySpan<int> IVs, PKM pkm, int max = 31)
{
for (int i = 0; i < 6; i++)
{
@ -260,7 +260,7 @@ namespace PKHeX.Core
return true;
}
public static bool GetIsFixedIVSequenceValidNoRand(IReadOnlyList<int> IVs, PKM pkm)
public static bool GetIsFixedIVSequenceValidNoRand(ReadOnlySpan<int> IVs, PKM pkm)
{
for (int i = 0; i < 6; i++)
{

View file

@ -253,7 +253,7 @@ namespace PKHeX.Core
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)

View file

@ -182,7 +182,7 @@ namespace PKHeX.Core
{
if (IVs.Count != 0)
{
if (!Legal.GetIsFixedIVSequenceValidSkipRand(IVs, pkm))
if (!Legal.GetIsFixedIVSequenceValidSkipRand((int[])IVs, pkm))
return false;
}

View file

@ -27,7 +27,7 @@ namespace PKHeX.Core
{
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;

View file

@ -42,11 +42,12 @@ namespace PKHeX.Core
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<int> 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);

View file

@ -134,6 +134,8 @@ namespace PKHeX.Core
public virtual IReadOnlyList<int> Moves { get => Array.Empty<int>(); set { } }
public virtual IReadOnlyList<int> Relearn { get => Array.Empty<int>(); set { } }
public virtual int[] IVs { get => Array.Empty<int>(); set { } }
public virtual bool HasFixedIVs => true;
public virtual void GetIVs(Span<int> value) { }
public virtual bool IsShiny => false;
public virtual Shiny Shiny

View file

@ -88,6 +88,8 @@ namespace PKHeX.Core
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<int> value) => Gift.GetIVs(value);
// ILocation overrides
public override int Location { get => IsEgg ? 0 : Gift.EggLocation + 3000; set { } }

View file

@ -155,6 +155,18 @@ namespace PKHeX.Core
}
}
public override void GetIVs(Span<int> 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 @@ namespace PKHeX.Core
private void SetIVs(PKM pk)
{
Span<int> 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);
}

View file

@ -119,6 +119,12 @@ namespace PKHeX.Core
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<int> value)
{
if (HasFixedIVs)
PK.GetIVs(value);
}
public override PKM ConvertToPKM(ITrainerInfo sav, EncounterCriteria criteria)
{

View file

@ -254,6 +254,18 @@ namespace PKHeX.Core
}
}
public override void GetIVs(Span<int> 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 @@ namespace PKHeX.Core
private void SetIVs(PKM pk)
{
Span<int> 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);
}

View file

@ -244,6 +244,18 @@ namespace PKHeX.Core
}
}
public override void GetIVs(Span<int> 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 @@ namespace PKHeX.Core
private void SetIVs(PKM pk)
{
Span<int> 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);
}

View file

@ -249,6 +249,18 @@ namespace PKHeX.Core
}
}
public override void GetIVs(Span<int> 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 @@ namespace PKHeX.Core
private void SetIVs(PKM pk)
{
Span<int> 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);
}

View file

@ -40,6 +40,7 @@ namespace PKHeX.Core
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; }

View file

@ -473,23 +473,42 @@ namespace PKHeX.Core
}
}
public override void GetIVs(Span<int> 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<int> 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);
}

View file

@ -295,6 +295,18 @@ namespace PKHeX.Core
}
}
public override void GetIVs(Span<int> 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 @@ namespace PKHeX.Core
private void SetIVs(PKM pk)
{
Span<int> 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);
}

View file

@ -241,6 +241,18 @@ namespace PKHeX.Core
}
}
public override void GetIVs(Span<int> 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 @@ namespace PKHeX.Core
private void SetIVs(PKM pk)
{
Span<int> 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);
}

View file

@ -376,6 +376,18 @@ namespace PKHeX.Core
set => SetIVs(value);
}
public void GetIVs(Span<int> 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<int> value)
{
if (value.Length != 6)

View file

@ -23,6 +23,16 @@ namespace PKHeX.Core
return ((ReadOnlySpan<T>)data).Count(value);
}
public static T Find<T>(this Span<T> data, Func<T, bool> value) where T : unmanaged
{
foreach (var x in data)
{
if (value(x))
return x;
}
return default;
}
public static int Count<T>(this ReadOnlySpan<T> data, T value) where T : IEquatable<T>
{
int count = 0;