mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-10 14:44:24 +00:00
Handle gen4 manaphy egg gift pid checks correctly
ty lincoln for bringing this to my attention and explaining the possible actions & outcomes game checks an un-updated ID32 (original recipient, different if traded hatcher), not "oops Ranger is no longer stored"
This commit is contained in:
parent
dcb72b0993
commit
a71597f3a8
2 changed files with 36 additions and 27 deletions
|
@ -334,22 +334,39 @@ public static class MethodFinder
|
|||
|
||||
private static bool GetMG4Match(Span<uint> seeds, uint pid, ReadOnlySpan<uint> IVs, out PIDIV pidiv)
|
||||
{
|
||||
uint mg4Rev = ARNG.Prev(pid);
|
||||
var currentPSV = getPSV(pid);
|
||||
pid = ARNG.Prev(pid);
|
||||
var originalPSV = getPSV(pid);
|
||||
// ARNG shiny value must be different from the original shiny
|
||||
// if we have a multi-rerolled PID, each re-roll must be from the same shiny value
|
||||
if (originalPSV == currentPSV)
|
||||
return GetNonMatch(out pidiv);
|
||||
|
||||
var count = LCRNGReversal.GetSeeds(seeds, mg4Rev << 16, mg4Rev & 0xFFFF0000);
|
||||
var mg4 = seeds[..count];
|
||||
foreach (var seed in mg4)
|
||||
// ARNG can happen at most 3 times (checked all 2^32 seeds)
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
var B = LCRNG.Next2(seed);
|
||||
var C = LCRNG.Next(B);
|
||||
var D = LCRNG.Next(C);
|
||||
if (!IVsMatch(C >> 16, D >> 16, IVs))
|
||||
continue;
|
||||
var count = LCRNGReversal.GetSeeds(seeds, pid << 16, pid & 0xFFFF0000);
|
||||
var mg4 = seeds[..count];
|
||||
foreach (var seed in mg4)
|
||||
{
|
||||
var C = LCRNG.Next3(seed);
|
||||
var D = LCRNG.Next(C);
|
||||
if (!IVsMatch(C >> 16, D >> 16, IVs))
|
||||
continue;
|
||||
|
||||
pidiv = new PIDIV(G4MGAntiShiny, seed);
|
||||
return true;
|
||||
pidiv = new PIDIV(G4MGAntiShiny, seed);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Continue checking for multi-rerolls
|
||||
pid = ARNG.Prev(pid);
|
||||
var prevPSV = getPSV(pid);
|
||||
if (prevPSV != originalPSV)
|
||||
break;
|
||||
}
|
||||
return GetNonMatch(out pidiv);
|
||||
|
||||
static uint getPSV(uint u32) => ((u32 >> 16) ^ (u32 & 0xFFFF)) >> 3;
|
||||
}
|
||||
|
||||
private static bool GetG5MGShinyMatch(PKM pk, uint pid, out PIDIV pidiv)
|
||||
|
|
|
@ -322,25 +322,17 @@ public sealed class PGT : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I
|
|||
|
||||
private static bool IsG4ManaphyPIDValid(PIDType val, PKM pk)
|
||||
{
|
||||
// Unhatched: Can't trigger ARNG, so it must always be Method 1
|
||||
if (pk.IsEgg)
|
||||
{
|
||||
if (pk.IsShiny)
|
||||
return false;
|
||||
if (val == PIDType.Method_1)
|
||||
return true;
|
||||
return val == PIDType.G4MGAntiShiny && IsAntiShinyARNG(pk);
|
||||
}
|
||||
return val == PIDType.Method_1;
|
||||
|
||||
// Hatching: Code checks if the TID/SID yield a shiny, and re-roll until not shiny.
|
||||
// However, the TID/SID reference is stale (original OT, not hatching OT), so it's fallible.
|
||||
// Hatched: Can't be shiny for an un-traded egg.
|
||||
if (val == PIDType.Method_1)
|
||||
return pk.WasTradedEgg || !pk.IsShiny; // can't be shiny on received game
|
||||
return val == PIDType.G4MGAntiShiny && (pk.WasTradedEgg || IsAntiShinyARNG(pk));
|
||||
return pk.WasTradedEgg || !pk.IsShiny;
|
||||
|
||||
static bool IsAntiShinyARNG(PKM pk)
|
||||
{
|
||||
var shinyPID = ARNG.Prev(pk.PID);
|
||||
var tmp = pk.ID32 ^ shinyPID;
|
||||
var xor = (ushort)(tmp ^ (tmp >> 16));
|
||||
return xor < 8; // shiny proc
|
||||
}
|
||||
// Hatched when the egg was shiny: PID needs to be from the ARNG.
|
||||
return val == PIDType.G4MGAntiShiny;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue