mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-23 20:43:07 +00:00
Add gen4 lead frame finding variants
can use level call or not at all (fixed slot) still untested, assumed same call order as gen3.
This commit is contained in:
parent
48242109fd
commit
40ec87fc9d
3 changed files with 114 additions and 21 deletions
|
@ -2,16 +2,29 @@
|
||||||
{
|
{
|
||||||
public class Frame
|
public class Frame
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Ending seed value for the frame (prior to nature call).
|
||||||
|
/// </summary>
|
||||||
public readonly uint Seed;
|
public readonly uint Seed;
|
||||||
public readonly LeadRequired Lead;
|
public readonly LeadRequired Lead;
|
||||||
|
|
||||||
private readonly FrameType FrameType;
|
private readonly FrameType FrameType;
|
||||||
private readonly RNG RNG;
|
private readonly RNG RNG;
|
||||||
|
|
||||||
public uint RandLevel { get; set; }
|
/// <summary>
|
||||||
public uint RandESV { get; set; }
|
/// Starting seed for the frame (to generate the frame).
|
||||||
|
/// </summary>
|
||||||
public uint OriginSeed { get; set; }
|
public uint OriginSeed { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// RNG Call Value for the Level Calc
|
||||||
|
/// </summary>
|
||||||
|
public uint RandLevel { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// RNG Call Value for the Encounter Slot Calc
|
||||||
|
/// </summary>
|
||||||
|
public uint RandESV { get; set; }
|
||||||
|
|
||||||
public bool LevelSlotModified => Lead.IsLevelOrSlotModified();
|
public bool LevelSlotModified => Lead.IsLevelOrSlotModified();
|
||||||
|
|
||||||
public Frame(uint seed, FrameType type, RNG rng, LeadRequired lead)
|
public Frame(uint seed, FrameType type, RNG rng, LeadRequired lead)
|
||||||
|
@ -30,6 +43,13 @@
|
||||||
/// <returns>Slot number for this frame & lead value.</returns>
|
/// <returns>Slot number for this frame & lead value.</returns>
|
||||||
public bool IsSlotCompatibile(EncounterSlot slot, PKM pkm)
|
public bool IsSlotCompatibile(EncounterSlot slot, PKM pkm)
|
||||||
{
|
{
|
||||||
|
bool usesLevel = !slot.FixedLevel;
|
||||||
|
if (FrameType != FrameType.MethodH)
|
||||||
|
{
|
||||||
|
if (Lead.HasFlag(LeadRequired.UsesLevelCall) != usesLevel)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Level is before Nature, but usually isn't varied. Check ESV calc first.
|
// Level is before Nature, but usually isn't varied. Check ESV calc first.
|
||||||
int s = GetSlot(slot);
|
int s = GetSlot(slot);
|
||||||
if (s != slot.SlotNumber)
|
if (s != slot.SlotNumber)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace PKHeX.Core
|
namespace PKHeX.Core
|
||||||
{
|
{
|
||||||
|
@ -13,10 +14,10 @@ namespace PKHeX.Core
|
||||||
public static IEnumerable<Frame> GetFrames(PIDIV pidiv, PKM pk)
|
public static IEnumerable<Frame> GetFrames(PIDIV pidiv, PKM pk)
|
||||||
{
|
{
|
||||||
if (pidiv.RNG == null)
|
if (pidiv.RNG == null)
|
||||||
yield break;
|
return Enumerable.Empty<Frame>();
|
||||||
FrameGenerator info = new FrameGenerator(pidiv, pk);
|
FrameGenerator info = new FrameGenerator(pidiv, pk);
|
||||||
if (info.FrameType == FrameType.None)
|
if (info.FrameType == FrameType.None)
|
||||||
yield break;
|
return Enumerable.Empty<Frame>();
|
||||||
|
|
||||||
info.Nature = pk.EncryptionConstant % 25;
|
info.Nature = pk.EncryptionConstant % 25;
|
||||||
|
|
||||||
|
@ -30,8 +31,9 @@ namespace PKHeX.Core
|
||||||
: FilterNatureSync(seeds, pidiv, info);
|
: FilterNatureSync(seeds, pidiv, info);
|
||||||
|
|
||||||
var refined = RefineFrames(frames, info);
|
var refined = RefineFrames(frames, info);
|
||||||
foreach (var z in refined)
|
if (pk.Gen4 && pidiv.Type == PIDType.CuteCharm) // only permit cute charm successful frames
|
||||||
yield return z;
|
return refined.Where(z => (z.Lead & ~LeadRequired.UsesLevelCall) == LeadRequired.CuteCharm);
|
||||||
|
return refined;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<Frame> RefineFrames(IEnumerable<Frame> frames, FrameGenerator info)
|
private static IEnumerable<Frame> RefineFrames(IEnumerable<Frame> frames, FrameGenerator info)
|
||||||
|
@ -105,6 +107,8 @@ namespace PKHeX.Core
|
||||||
lead = cc ? LeadRequired.CuteCharm : LeadRequired.CuteCharmFail;
|
lead = cc ? LeadRequired.CuteCharm : LeadRequired.CuteCharmFail;
|
||||||
yield return info.GetFrame(prev2, lead, p2, p1, prev3);
|
yield return info.GetFrame(prev2, lead, p2, p1, prev3);
|
||||||
}
|
}
|
||||||
|
if (f.Lead == LeadRequired.CuteCharm)
|
||||||
|
yield break;
|
||||||
|
|
||||||
// Pressure, Hustle, Vital Spirit = Force Maximum Level from slot
|
// Pressure, Hustle, Vital Spirit = Force Maximum Level from slot
|
||||||
// -2 ESV
|
// -2 ESV
|
||||||
|
@ -149,10 +153,16 @@ namespace PKHeX.Core
|
||||||
// Current Seed of the frame is the ESV.
|
// Current Seed of the frame is the ESV.
|
||||||
var rand = f.Seed >> 16;
|
var rand = f.Seed >> 16;
|
||||||
f.RandESV = rand;
|
f.RandESV = rand;
|
||||||
f.RandLevel = rand;
|
f.RandLevel = rand; // unused
|
||||||
f.OriginSeed = info.RNG.Prev(f.Seed);
|
f.OriginSeed = info.RNG.Prev(f.Seed);
|
||||||
yield return f;
|
yield return f;
|
||||||
|
|
||||||
|
// Create a copy for level; shift ESV and origin back
|
||||||
|
var esv = f.OriginSeed;
|
||||||
|
var origin = info.RNG.Prev(f.OriginSeed);
|
||||||
|
var withLevel = info.GetFrame(f.Seed, f.Lead | LeadRequired.UsesLevelCall, esv, f.RandLevel, origin);
|
||||||
|
yield return withLevel;
|
||||||
|
|
||||||
if (f.Lead != LeadRequired.None)
|
if (f.Lead != LeadRequired.None)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -161,20 +171,82 @@ namespace PKHeX.Core
|
||||||
}
|
}
|
||||||
foreach (var f in list)
|
foreach (var f in list)
|
||||||
{
|
{
|
||||||
// Level Modifiers between ESV and Nature
|
var leadframes = GenerateLeadSpecificFrames4(f, info);
|
||||||
var prev = info.RNG.Prev(f.Seed);
|
foreach (var frame in leadframes)
|
||||||
var p3 = info.RNG.Prev(prev);
|
yield return frame;
|
||||||
var p16 = prev >> 16;
|
|
||||||
|
|
||||||
yield return info.GetFrame(prev, LeadRequired.IntimidateKeenEye, p16, p3);
|
|
||||||
yield return info.GetFrame(prev, LeadRequired.PressureHustleSpirit, p16, p3);
|
|
||||||
|
|
||||||
// Slot Modifiers before ESV
|
|
||||||
var force = (info.DPPt ? p16 >> 15 : p16 & 1) == 1;
|
|
||||||
var rand = f.Seed >> 16;
|
|
||||||
yield return info.GetFrame(prev, force ? LeadRequired.StaticMagnet : LeadRequired.StaticMagnetFail, rand, p3);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private static IEnumerable<Frame> GenerateLeadSpecificFrames4(Frame f, FrameGenerator info)
|
||||||
|
{
|
||||||
|
LeadRequired lead;
|
||||||
|
var prev0 = f.Seed; // 0
|
||||||
|
var prev1 = info.RNG.Prev(f.Seed); // -1
|
||||||
|
var prev2 = info.RNG.Prev(prev1); // -2
|
||||||
|
var prev3 = info.RNG.Prev(prev2); // -3
|
||||||
|
|
||||||
|
// Rand call raw values
|
||||||
|
var p0 = prev0 >> 16;
|
||||||
|
var p1 = prev1 >> 16;
|
||||||
|
var p2 = prev2 >> 16;
|
||||||
|
|
||||||
|
// Cute Charm
|
||||||
|
// -2 ESV
|
||||||
|
// -1 Level (Optional)
|
||||||
|
// 0 CC Proc (Random() % 3 != 0)
|
||||||
|
// 1 Nature
|
||||||
|
if (info.Gendered)
|
||||||
|
{
|
||||||
|
bool cc = p0 % 3 != 0;
|
||||||
|
if (f.Lead == LeadRequired.CuteCharm) // 100% required for frame base
|
||||||
|
{
|
||||||
|
if (!cc) yield break;
|
||||||
|
yield return info.GetFrame(prev2, LeadRequired.CuteCharm, p1, p1, prev2);
|
||||||
|
yield return info.GetFrame(prev2, LeadRequired.CuteCharm | LeadRequired.UsesLevelCall, p2, p1, prev3);
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
lead = cc ? LeadRequired.CuteCharm : LeadRequired.CuteCharmFail;
|
||||||
|
yield return info.GetFrame(prev2, lead, p1, p1, prev2);
|
||||||
|
yield return info.GetFrame(prev2, lead | LeadRequired.UsesLevelCall, p2, p1, prev3);
|
||||||
|
}
|
||||||
|
if (f.Lead == LeadRequired.CuteCharm)
|
||||||
|
yield break;
|
||||||
|
|
||||||
|
// Pressure, Hustle, Vital Spirit = Force Maximum Level from slot
|
||||||
|
// -2 ESV
|
||||||
|
// -1 Level (Optional)
|
||||||
|
// 0 LevelMax proc (Random() & 1)
|
||||||
|
// 1 Nature
|
||||||
|
bool max = p0 % 2 == 1;
|
||||||
|
lead = max ? LeadRequired.PressureHustleSpirit : LeadRequired.PressureHustleSpiritFail;
|
||||||
|
yield return info.GetFrame(prev2, lead, p1, p1, prev2);
|
||||||
|
yield return info.GetFrame(prev2, lead | LeadRequired.UsesLevelCall, p2, p1, prev3);
|
||||||
|
|
||||||
|
// Keen Eye, Intimidate
|
||||||
|
// -2 ESV
|
||||||
|
// -1 Level (Optional)
|
||||||
|
// 0 Level Adequate Check !(Random() % 2 == 1) rejects -- rand%2==1 is adequate
|
||||||
|
// 1 Nature
|
||||||
|
// Note: if this check fails, the encounter generation routine is aborted.
|
||||||
|
if (max) // same result as above, no need to recalculate
|
||||||
|
{
|
||||||
|
lead = LeadRequired.IntimidateKeenEye;
|
||||||
|
yield return info.GetFrame(prev2, lead, p1, p1, prev2);
|
||||||
|
yield return info.GetFrame(prev2, lead | LeadRequired.UsesLevelCall, p2, p1, prev3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Static or Magnet Pull
|
||||||
|
// -2 SlotProc (Random % 2 == 0)
|
||||||
|
// -1 ESV (select slot)
|
||||||
|
// 0 Level (Optional)
|
||||||
|
// 1 Nature
|
||||||
|
var force1 = (info.DPPt ? p1 >> 15 : p1 & 1) == 1;
|
||||||
|
lead = force1 ? LeadRequired.StaticMagnet : LeadRequired.StaticMagnetFail;
|
||||||
|
yield return info.GetFrame(prev2, lead, p0, p0, prev3);
|
||||||
|
|
||||||
|
var force2 = (info.DPPt ? p2 >> 15 : p2 & 1) == 1;
|
||||||
|
lead = (force2 ? LeadRequired.StaticMagnet : LeadRequired.StaticMagnetFail) | LeadRequired.UsesLevelCall;
|
||||||
|
yield return info.GetFrame(prev2, lead, p1, p0, prev3);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Filters the input <see cref="SeedInfo"/> according to a Nature Lock frame generation pattern.
|
/// Filters the input <see cref="SeedInfo"/> according to a Nature Lock frame generation pattern.
|
||||||
|
|
|
@ -17,7 +17,8 @@ namespace PKHeX.Core
|
||||||
PressureHustleSpirit = 1 << 4,
|
PressureHustleSpirit = 1 << 4,
|
||||||
SuctionCups = 1 << 5,
|
SuctionCups = 1 << 5,
|
||||||
|
|
||||||
NoLevelCall = 1 << 6,
|
// Compatibility Flags
|
||||||
|
UsesLevelCall = 1 << 6,
|
||||||
Fail = 1 << 7,
|
Fail = 1 << 7,
|
||||||
|
|
||||||
CuteCharmFail = CuteCharm | Fail,
|
CuteCharmFail = CuteCharm | Fail,
|
||||||
|
@ -25,7 +26,7 @@ namespace PKHeX.Core
|
||||||
StaticMagnetFail = StaticMagnet | Fail,
|
StaticMagnetFail = StaticMagnet | Fail,
|
||||||
PressureHustleSpiritFail = PressureHustleSpirit | Fail,
|
PressureHustleSpiritFail = PressureHustleSpirit | Fail,
|
||||||
|
|
||||||
AllFlags = NoLevelCall | Fail,
|
AllFlags = UsesLevelCall | Fail,
|
||||||
NoFlags = ~AllFlags,
|
NoFlags = ~AllFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue