mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-03-21 17:48:28 -05:00
Misc tweaks
Add rejections for shiny criteria for gen8+ generators Unrelated: use recent c# lang feature for settings property field
This commit is contained in:
parent
ca6fbf024c
commit
3ad376be44
|
|
@ -126,6 +126,12 @@ public EncounterCriteria()
|
|||
/// <returns>><see langword="true"/> if an Ability is specified; otherwise, <see langword="false"/>.</returns>
|
||||
public bool IsSpecifiedAbility() => Ability != Any12H;
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the shiny value is explicitly specified rather than set to random.
|
||||
/// </summary>
|
||||
/// <returns>><see langword="true"/> if a Shiny is specified; otherwise, <see langword="false"/>.</returns>
|
||||
public bool IsSpecifiedShiny() => Shiny != Shiny.Random;
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether all IVs are specified in the criteria.
|
||||
/// </summary>
|
||||
|
|
@ -183,6 +189,20 @@ public int GetCountSpecifiedIVs() => Convert.ToInt32(IV_HP != RandomIV)
|
|||
_ => throw new ArgumentOutOfRangeException(nameof(ability), ability, null),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified shiny properties satisfy the shiny criteria based on the current <see cref="Shiny"/> setting.
|
||||
/// </summary>
|
||||
/// <returns>><see langword="true"/> if the index satisfies the shiny criteria; otherwise, <see langword="false"/>.</returns>
|
||||
public bool IsSatisfiedShiny(uint xor, uint cmp) => Shiny switch
|
||||
{
|
||||
Shiny.Random => true,
|
||||
Shiny.Never => xor > cmp, // not shiny
|
||||
Shiny.AlwaysSquare => xor == 0, // square shiny
|
||||
Shiny.AlwaysStar => xor < cmp && xor != 0, // star shiny
|
||||
Shiny.Always => xor < cmp, // shiny
|
||||
_ => false, // shouldn't be set
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified Nature satisfies the criteria.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -57,6 +57,10 @@ protected override void SetPINGA(PK8 pk, in EncounterCriteria criteria, Personal
|
|||
{
|
||||
Span<int> iv = stackalloc int[6];
|
||||
|
||||
// Honor a shiny request only at the end; generate as never-shiny to avoid shiny PID rejection in main RNG method.
|
||||
var isShinyRequested = criteria.Shiny.IsShiny();
|
||||
var iterCriteria = criteria with { Shiny = ShinyMethod };
|
||||
|
||||
int ctr = 0;
|
||||
var rand = new Xoroshiro128Plus(Util.Rand.Rand64());
|
||||
var param = GetParam(pi);
|
||||
|
|
@ -64,21 +68,22 @@ protected override void SetPINGA(PK8 pk, in EncounterCriteria criteria, Personal
|
|||
const int max = 100_000;
|
||||
do
|
||||
{
|
||||
if (TryApply(pk, seed = rand.Next(), iv, param, criteria))
|
||||
if (TryApply(pk, seed = rand.Next(), iv, param, iterCriteria))
|
||||
break;
|
||||
} while (++ctr < max);
|
||||
|
||||
if (ctr == max) // fail
|
||||
{
|
||||
if (!TryApply(pk, seed = rand.Next(), iv, param, criteria.WithoutIVs()))
|
||||
iterCriteria = iterCriteria.WithoutIVs();
|
||||
if (!TryApply(pk, seed = rand.Next(), iv, param, iterCriteria))
|
||||
{
|
||||
var tmp = EncounterCriteria.Unrestricted with { Shiny = ShinyMethod };
|
||||
while (!TryApply(pk, seed = rand.Next(), iv, param, tmp)) { }
|
||||
iterCriteria = EncounterCriteria.Unrestricted with { Shiny = ShinyMethod };
|
||||
while (!TryApply(pk, seed = rand.Next(), iv, param, iterCriteria)) { }
|
||||
}
|
||||
}
|
||||
|
||||
FinishCorrelation(pk, seed);
|
||||
if (criteria.Shiny.IsShiny())
|
||||
if (isShinyRequested)
|
||||
pk.PID = ShinyUtil.GetShinyPID(pk.TID16, pk.SID16, pk.PID, ShinyXor);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,10 +36,10 @@ public static bool GenerateData(PA9 pk, in GenerateParam9a enc, in EncounterCrit
|
|||
{
|
||||
var rand = new Xoroshiro128Plus(seed);
|
||||
pk.EncryptionConstant = (uint)rand.NextInt(uint.MaxValue);
|
||||
pk.PID = GetAdaptedPID(ref rand, pk, enc);
|
||||
|
||||
if (enc.Shiny is Shiny.Random && criteria.Shiny.IsShiny() != pk.IsShiny)
|
||||
var pid = GetAdaptedPID(ref rand, pk, enc);
|
||||
if (enc.Shiny is Shiny.Random && criteria.IsSpecifiedShiny() && !criteria.IsSatisfiedShiny(ShinyUtil.GetShinyXor(pid, pk.ID32), 16))
|
||||
return false;
|
||||
pk.PID = pid;
|
||||
|
||||
Span<int> ivs = [UNSET, UNSET, UNSET, UNSET, UNSET, UNSET];
|
||||
if (enc.IVs.IsSpecified)
|
||||
|
|
|
|||
|
|
@ -55,7 +55,8 @@ private static bool TryApplyFromSeed(PK8 pk, in EncounterCriteria criteria, Shin
|
|||
if (shiny == Shiny.AlwaysStar && type != Shiny.AlwaysStar)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (shiny is Shiny.Random && criteria.IsSpecifiedShiny() && !criteria.IsSatisfiedShiny(GetShinyXor(pid, pk.ID32), 16))
|
||||
return false;
|
||||
pk.PID = pid;
|
||||
|
||||
// IVs
|
||||
|
|
|
|||
|
|
@ -160,6 +160,8 @@ public static bool TryApply(PK8 pk, ulong seed, Span<int> ivs, in GenerateParam8
|
|||
|
||||
var trID = (uint)rng.NextInt();
|
||||
var pid = (uint)rng.NextInt();
|
||||
|
||||
// Battle
|
||||
var xor = GetShinyXor(pid, trID);
|
||||
bool isShiny = xor < 16;
|
||||
if (isShiny && param.Shiny == Shiny.Never)
|
||||
|
|
@ -167,9 +169,8 @@ public static bool TryApply(PK8 pk, ulong seed, Span<int> ivs, in GenerateParam8
|
|||
ForceShinyState(false, ref pid, trID, 0);
|
||||
isShiny = false;
|
||||
}
|
||||
if (param.Shiny is Shiny.Random && isShiny != criteria.Shiny.IsShiny())
|
||||
return false;
|
||||
|
||||
// Captured
|
||||
if (isShiny)
|
||||
{
|
||||
if (!GetIsShiny6(pk.ID32, pid))
|
||||
|
|
@ -181,6 +182,8 @@ public static bool TryApply(PK8 pk, ulong seed, Span<int> ivs, in GenerateParam8
|
|||
pid ^= 0x1000_0000;
|
||||
}
|
||||
|
||||
if (param.Shiny is Shiny.Random && criteria.IsSpecifiedShiny() && !criteria.IsSatisfiedShiny(GetShinyXor(pid, pk.ID32), 16))
|
||||
return false;
|
||||
pk.PID = pid;
|
||||
|
||||
const int UNSET = -1;
|
||||
|
|
|
|||
|
|
@ -129,6 +129,8 @@ public static bool TryApplyFromSeed(PA8 pk, in EncounterCriteria criteria, in Ov
|
|||
if (para.Shiny == Shiny.AlwaysStar && type != Shiny.AlwaysStar)
|
||||
return false;
|
||||
}
|
||||
if (para.Shiny is Shiny.Random && criteria.IsSpecifiedShiny() && !criteria.IsSatisfiedShiny(GetShinyXor(pid, pk.ID32), 16))
|
||||
return false;
|
||||
pk.PID = pid;
|
||||
|
||||
Span<int> ivs = [UNSET, UNSET, UNSET, UNSET, UNSET, UNSET];
|
||||
|
|
|
|||
|
|
@ -65,6 +65,8 @@ public static bool TryApplyFromSeed(PB8 pk, in EncounterCriteria criteria, Shiny
|
|||
if (shiny == Shiny.AlwaysStar && type != Shiny.AlwaysStar)
|
||||
return false;
|
||||
}
|
||||
if (shiny is Shiny.Random && criteria.IsSpecifiedShiny() && !criteria.IsSatisfiedShiny(GetShinyXor(pid, pk.ID32), 16))
|
||||
return false;
|
||||
pk.PID = pid;
|
||||
|
||||
// Check IVs: Create flawless IVs at random indexes, then the random IVs for not flawless.
|
||||
|
|
|
|||
|
|
@ -65,6 +65,8 @@ public static bool TryApplyFromSeed(PB8 pk, in EncounterCriteria criteria, Shiny
|
|||
if (shiny == Shiny.AlwaysStar && type != Shiny.AlwaysStar)
|
||||
return false;
|
||||
}
|
||||
if (shiny is Shiny.Random && criteria.IsSpecifiedShiny() && !criteria.IsSatisfiedShiny(GetShinyXor(pid, pk.ID32), 16))
|
||||
return false;
|
||||
pk.PID = pid;
|
||||
|
||||
// Check IVs: Create flawless IVs at random indexes, then the random IVs for not flawless.
|
||||
|
|
|
|||
|
|
@ -62,10 +62,10 @@ public static bool GenerateData(PK9 pk, in GenerateParam9 enc, in EncounterCrite
|
|||
{
|
||||
var rand = new Xoroshiro128Plus(seed);
|
||||
pk.EncryptionConstant = (uint)rand.NextInt(uint.MaxValue);
|
||||
pk.PID = GetAdaptedPID(ref rand, pk, enc);
|
||||
|
||||
if (enc.Shiny is Shiny.Random && criteria.Shiny.IsShiny() != pk.IsShiny)
|
||||
var pid = GetAdaptedPID(ref rand, pk, enc);
|
||||
if (enc.Shiny is Shiny.Random && criteria.IsSpecifiedShiny() && !criteria.IsSatisfiedShiny(GetShinyXor(pid, pk.ID32), 16))
|
||||
return false;
|
||||
pk.PID = pid;
|
||||
|
||||
const int UNSET = -1;
|
||||
const int MAX = 31;
|
||||
|
|
|
|||
|
|
@ -39,15 +39,14 @@ public sealed class StartupSettings : IStartupSettings
|
|||
public List<string> RecentlyLoaded { get; set; } = new(DefaultMaxRecent);
|
||||
|
||||
private const int DefaultMaxRecent = 10;
|
||||
private uint MaxRecentCount = DefaultMaxRecent;
|
||||
|
||||
[LocalizedDescription("Amount of recently loaded save files to remember.")]
|
||||
public uint RecentlyLoadedMaxCount
|
||||
{
|
||||
get => MaxRecentCount;
|
||||
get;
|
||||
// Sanity check to not let the user foot-gun themselves a slow recall time.
|
||||
set => MaxRecentCount = Math.Clamp(value, 1, 1000);
|
||||
}
|
||||
set => field = Math.Clamp(value, 1, 1000);
|
||||
} = DefaultMaxRecent;
|
||||
|
||||
// Don't let invalid values slip into the startup version.
|
||||
|
||||
|
|
@ -89,7 +88,7 @@ public void LoadSaveFile(string path)
|
|||
{
|
||||
var recent = RecentlyLoaded;
|
||||
// Remove from list if already present.
|
||||
if (!recent.Remove(path) && recent.Count >= MaxRecentCount)
|
||||
if (!recent.Remove(path) && recent.Count >= RecentlyLoadedMaxCount)
|
||||
recent.RemoveAt(recent.Count - 1);
|
||||
recent.Insert(0, path);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user