From 3b4661d40da1ccde0e03e7b37d86a3bacce1ba56 Mon Sep 17 00:00:00 2001 From: Kurt Date: Sat, 28 Jun 2025 12:32:45 -0500 Subject: [PATCH] Revise dmax adv shiny PID generating to match game --- .../Templates/Gen8/EncounterStatic8N.cs | 4 +- .../Templates/Gen8/EncounterStatic8Nest.cs | 11 +++-- .../Templates/Gen8/EncounterStatic8U.cs | 44 ++++++++++++++++++- 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8N.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8N.cs index 6b1cc5a7d..75619e6da 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8N.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8N.cs @@ -24,13 +24,13 @@ public sealed record EncounterStatic8N : EncounterStatic8Nest public override byte LevelMin => LevelCaps[MinRank * 2]; public override byte LevelMax => LevelCaps[(MaxRank * 2) + 1]; - public EncounterStatic8N(byte nestIndex, byte minRank, byte maxRank, byte val, [ConstantExpected] GameVersion game) : base(game) + public EncounterStatic8N(byte nestIndex, byte minRank, byte maxRank, byte flawless, [ConstantExpected] GameVersion game) : base(game) { NestIndex = nestIndex; MinRank = minRank; MaxRank = maxRank; DynamaxLevel = (byte)(MinRank + 1u); - FlawlessIVCount = val; + FlawlessIVCount = flawless; } public static EncounterStatic8N Read(ReadOnlySpan data, [ConstantExpected] GameVersion game) => new(data[6], data[7], data[8], data[9], game) diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8Nest.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8Nest.cs index 42dc6819e..163790946 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8Nest.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8Nest.cs @@ -92,7 +92,7 @@ public PK8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria) protected virtual ushort GetLocation() => Location; - private void SetPINGA(PK8 pk, in EncounterCriteria criteria, PersonalInfo8SWSH pi) + protected virtual void SetPINGA(PK8 pk, in EncounterCriteria criteria, PersonalInfo8SWSH pi) { bool requestShiny = criteria.Shiny.IsShiny(); bool checkShiny = requestShiny && Shiny != Shiny.Never; @@ -115,7 +115,10 @@ private void SetPINGA(PK8 pk, in EncounterCriteria criteria, PersonalInfo8SWSH p if (ctr == max) // fail { if (!TryApply(pk, seed = rand.Next(), iv, param, criteria.WithoutIVs())) - while (!TryApply(pk, seed = rand.Next(), iv, param, EncounterCriteria.Unrestricted)) { } + { + var tmp = EncounterCriteria.Unrestricted; + while (!TryApply(pk, seed = rand.Next(), iv, param, tmp)) { } + } } FinishCorrelation(pk, seed); @@ -125,7 +128,7 @@ private void SetPINGA(PK8 pk, in EncounterCriteria criteria, PersonalInfo8SWSH p protected GenerateParam8 GetParam() => GetParam(Info); - protected GenerateParam8 GetParam(PersonalInfo8SWSH pi) + private GenerateParam8 GetParam(PersonalInfo8SWSH pi) { var ratio = RemapGenderToParam(Gender, pi); return new GenerateParam8(Species, ratio, FlawlessIVCount, Ability, Shiny, Nature.Random, IVs); @@ -271,7 +274,7 @@ protected virtual bool TryApply(PK8 pk, ulong seed, Span iv, in GeneratePar return RaidRNG.TryApply(pk, seed, iv, param, criteria); } - private static byte RemapGenderToParam(byte gender, PersonalInfo8SWSH pi) => gender switch + protected static byte RemapGenderToParam(byte gender, PersonalInfo8SWSH pi) => gender switch { 0 => PersonalInfo.RatioMagicMale, 1 => PersonalInfo.RatioMagicFemale, diff --git a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8U.cs b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8U.cs index 86b3bd08d..9bec76922 100644 --- a/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8U.cs +++ b/PKHeX.Core/Legality/Encounters/Templates/Gen8/EncounterStatic8U.cs @@ -48,11 +48,53 @@ protected override void SetTrainerName(ReadOnlySpan name, PK8 pk) base.SetTrainerName(name, pk); } + // These raids are always generated as Never-Shiny, and only at the choice screen are they possibly set shiny. + private const Shiny ShinyMethod = Shiny.Never; + private const byte ShinyXor = 1; // If forced shiny, the XOR is always 1. + + // Need to override to ensure the fallback also uses Never-Shiny. + protected override void SetPINGA(PK8 pk, in EncounterCriteria criteria, PersonalInfo8SWSH pi) + { + Span iv = stackalloc int[6]; + + int ctr = 0; + var rand = new Xoroshiro128Plus(Util.Rand.Rand64()); + var param = GetParam(pi); + ulong seed; + const int max = 100_000; + do + { + if (TryApply(pk, seed = rand.Next(), iv, param, criteria)) + break; + } while (++ctr < max); + + if (ctr == max) // fail + { + if (!TryApply(pk, seed = rand.Next(), iv, param, criteria.WithoutIVs())) + { + var tmp = EncounterCriteria.Unrestricted with { Shiny = ShinyMethod }; + while (!TryApply(pk, seed = rand.Next(), iv, param, tmp)) { } + } + } + + FinishCorrelation(pk, seed); + if (criteria.IsSpecifiedNature() && criteria.Nature != pk.Nature && criteria.Nature.IsMint()) + pk.StatNature = criteria.Nature; + if (criteria.Shiny.IsShiny()) + pk.PID = ShinyUtil.GetShinyPID(pk.TID16, pk.SID16, pk.PID, ShinyXor); + } + + private GenerateParam8 GetParam(PersonalInfo8SWSH pi) + { + var ratio = RemapGenderToParam(Gender, pi); + return new GenerateParam8(Species, ratio, FlawlessIVCount, Ability, ShinyMethod, Nature.Random, IVs); + } + // no downleveling, unlike all other raids protected override bool IsMatchLevel(PKM pk) => pk.MetLevel == Level; protected override bool IsMatchLocation(PKM pk) => Location == pk.MetLocation; - public bool IsShinyXorValid(ushort pkShinyXor) => pkShinyXor is > 15 or 1; + public bool IsShinyXorValid(ushort pkShinyXor) => pkShinyXor is > 15 or ShinyXor; // not shiny, or shiny with XOR=1 public bool ShouldHaveScientistTrash => Level != 70; // Level 65, not legendary/sub-legendary/ultra beast