mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-09-09 01:16:13 -05:00
Add pokeblock slot filtering
since there's 300 calls to rand to shuffle, I wouldn't be surprised if there are vblanks messing up the frames judging from my data 6 years ago (wow, still wrong, just look at the frame offsets) http://www.smogon.com/forums/threads/past-gen-rng-research.61090/page-35#post-4021415 looks like it happens quite erratically. may have to just override this to return true for all gen3 safari mons as it's entirely unpredictable.
This commit is contained in:
@@ -185,6 +185,18 @@ private static IEnumerable<Frame> FilterNatureSync(IEnumerable<SeedInfo> seeds,
|
||||
foreach (var seed in seeds)
|
||||
{
|
||||
var s = seed.Seed;
|
||||
|
||||
if (info.Safari3)
|
||||
{
|
||||
// successful pokeblock activation
|
||||
bool result = IsValidPokeBlockNature(s, info.Nature, out uint blockSeed);
|
||||
if (result)
|
||||
yield return info.GetFrame(blockSeed, seed.Charm3 ? LeadRequired.CuteCharm : LeadRequired.None);
|
||||
|
||||
// if no pokeblocks present (or failed call), fall out of the safari specific code and generate via the other scenarios
|
||||
s = info.RNG.Prev(s); // wasted RNG call
|
||||
}
|
||||
|
||||
var rand = s >> 16;
|
||||
bool sync = info.AllowLeads && !seed.Charm3 && (info.DPPt ? rand >> 15 : rand & 1) == 0;
|
||||
bool reg = (info.DPPt ? rand / 0xA3E : rand % 25) == info.Nature;
|
||||
@@ -209,6 +221,60 @@ private static IEnumerable<Frame> FilterNatureSync(IEnumerable<SeedInfo> seeds,
|
||||
}
|
||||
}
|
||||
}
|
||||
private static bool IsValidPokeBlockNature(uint seed, uint nature, out uint natureOrigin)
|
||||
{
|
||||
if (nature % 6 == 0) // neutral
|
||||
{
|
||||
natureOrigin = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// unroll the RNG to a stack of seeds
|
||||
var stack = new Stack<uint>();
|
||||
for (uint i = 0; i < 25; i++)
|
||||
for (uint j = 1 + i; j < 25; j++)
|
||||
stack.Push(seed = RNG.LCRNG.Prev(seed));
|
||||
|
||||
natureOrigin = RNG.LCRNG.Prev(stack.Peek());
|
||||
if (natureOrigin >> 16 % 100 >= 80) // failed proc
|
||||
return false;
|
||||
|
||||
// init natures
|
||||
uint[] natures = new uint[25];
|
||||
for (uint i = 0; i < 25; i++)
|
||||
natures[i] = i;
|
||||
|
||||
// shuffle nature list
|
||||
for (uint i = 0; i < 25; i++)
|
||||
for (uint j = 1 + i; j < 25; j++)
|
||||
{
|
||||
var s = stack.Pop();
|
||||
if ((s >> 16 & 1) == 0)
|
||||
continue; // only swap if 1
|
||||
|
||||
var temp = natures[i];
|
||||
natures[i] = natures[j];
|
||||
natures[j] = temp;
|
||||
}
|
||||
|
||||
var likes = Pokeblock.GetLikedBlockFlavor(nature);
|
||||
// best case scenario is a perfect flavored pokeblock for the nature.
|
||||
// has liked flavor, and all other non-disliked flavors are present.
|
||||
// is it possible to skip this step?
|
||||
for (int i = 0; i < 25; i++)
|
||||
{
|
||||
var n = natures[i];
|
||||
if (n == nature)
|
||||
break;
|
||||
|
||||
var nl = Pokeblock.GetLikedBlockFlavor(natures[i]);
|
||||
if (nl == likes) // next random nature likes the same block as the desired nature
|
||||
return false; // current nature is chosen instead, fail!
|
||||
}
|
||||
// unroll once more to hit the level calc (origin with respect for beginning the nature calcs)
|
||||
natureOrigin = RNG.LCRNG.Prev(natureOrigin);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Filters the input <see cref="SeedInfo"/> according to a Cute Charm frame generation pattern.
|
||||
|
||||
@@ -10,6 +10,8 @@ public class FrameGenerator
|
||||
public readonly bool AllowLeads;
|
||||
public readonly FrameType FrameType = FrameType.None;
|
||||
public readonly RNG RNG;
|
||||
public readonly bool Safari3;
|
||||
|
||||
public Frame GetFrame(uint seed, LeadRequired lead) => new Frame(seed, FrameType, RNG, lead);
|
||||
public Frame GetFrame(uint seed, LeadRequired lead, uint esv) => new Frame(seed, FrameType, RNG, lead) {ESV = esv};
|
||||
|
||||
@@ -33,6 +35,7 @@ public FrameGenerator(PIDIV pidiv, PKM pk)
|
||||
DPPt = false;
|
||||
FrameType = FrameType.MethodH;
|
||||
RNG = pidiv.RNG;
|
||||
Safari3 = pk.Ball == 5;
|
||||
|
||||
if (ver != GameVersion.E)
|
||||
return;
|
||||
|
||||
16
PKHeX.Core/Legality/RNG/Frame/Pokeblock.cs
Normal file
16
PKHeX.Core/Legality/RNG/Frame/Pokeblock.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
public static class Pokeblock
|
||||
{
|
||||
public static Flavor GetLikedBlockFlavor(uint nature) => (Flavor)(nature/5);
|
||||
public static Flavor GetDislikedBlockFlavor(uint nature) => (Flavor)(nature%5);
|
||||
public enum Flavor
|
||||
{
|
||||
Spicy,
|
||||
Sour,
|
||||
Sweet,
|
||||
Dry,
|
||||
Bitter,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user