mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-08-17 13:57:25 -05:00
encdb->pa8: source shiny roll count from save file
This commit is contained in:
@@ -160,7 +160,7 @@ private static byte GetInitialDynamaxLevel(Xoroshiro128Plus rand, int rank)
|
||||
return (byte)(baseValue + boost);
|
||||
}
|
||||
|
||||
public override void GenerateSeed64(PKM pk, ulong seed)
|
||||
public override void GenerateSeed64(PKM pk, ITrainerInfo tr, ulong seed)
|
||||
{
|
||||
var (_, noShiny) = IsPossibleSeed(pk, seed, false);
|
||||
var param = GetParam();
|
||||
|
||||
@@ -253,7 +253,7 @@ public bool Verify(PKM pk, ulong seed, bool forceNoShiny = false)
|
||||
return RaidRNG.Verify(pk, seed, iv, param, forceNoShiny: forceNoShiny);
|
||||
}
|
||||
|
||||
public virtual void GenerateSeed64(PKM pk, ulong seed)
|
||||
public virtual void GenerateSeed64(PKM pk, ITrainerInfo tr, ulong seed)
|
||||
{
|
||||
var criteria = EncounterCriteria.Unrestricted;
|
||||
var pk8 = (PK8)pk;
|
||||
|
||||
@@ -56,7 +56,7 @@ public PA8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
|
||||
OriginalTrainerFriendship = pi.BaseFriendship,
|
||||
Nickname = SpeciesName.GetSpeciesNameGeneration(Species, language, Generation),
|
||||
};
|
||||
SetPINGA(pk, criteria, pi);
|
||||
SetPINGA(pk, tr, criteria, pi);
|
||||
pk.Scale = pk.HeightScalar;
|
||||
pk.ResetHeight();
|
||||
pk.ResetWeight();
|
||||
@@ -65,9 +65,10 @@ public PA8 ConvertToPKM(ITrainerInfo tr, EncounterCriteria criteria)
|
||||
return pk;
|
||||
}
|
||||
|
||||
private void SetPINGA(PA8 pk, in EncounterCriteria criteria, PersonalInfo8LA pi)
|
||||
private void SetPINGA(PA8 pk, ITrainerInfo tr, in EncounterCriteria criteria, PersonalInfo8LA pi)
|
||||
{
|
||||
var para = GetParams(pi);
|
||||
var rollCount = GetRollCount(Type, tr);
|
||||
var para = GetParams(pi, rollCount);
|
||||
bool checkLevel = criteria.IsSpecifiedLevelRange() && this.IsLevelWithinRange(criteria);
|
||||
while (true)
|
||||
{
|
||||
@@ -84,22 +85,23 @@ private void SetPINGA(PA8 pk, in EncounterCriteria criteria, PersonalInfo8LA pi)
|
||||
}
|
||||
}
|
||||
|
||||
public void GenerateSeed64(PKM pk, ulong seed)
|
||||
public void GenerateSeed64(PKM pk, ITrainerInfo tr, ulong seed)
|
||||
{
|
||||
if (pk is not PA8 pa8)
|
||||
throw new ArgumentException($"{nameof(pk)} must be a {nameof(PA8)} instance.", nameof(pk));
|
||||
var criteria = EncounterCriteria.Unrestricted;
|
||||
var pi = PersonalTable.LA.GetFormEntry(Species, Form);
|
||||
var para = GetParams(pi);
|
||||
var rollCount = GetRollCount(Type, tr);
|
||||
var para = GetParams(pi, rollCount);
|
||||
_ = Overworld8aRNG.ApplyDetails(pa8, criteria, para, HasAlphaMove);
|
||||
}
|
||||
|
||||
private OverworldParam8a GetParams(PersonalInfo8LA pi) => new()
|
||||
private OverworldParam8a GetParams(PersonalInfo8LA pi, byte rollCount) => new()
|
||||
{
|
||||
Shiny = Shiny,
|
||||
IsAlpha = IsAlpha,
|
||||
FlawlessIVs = FlawlessIVCount,
|
||||
RollCount = GetRollCount(Type),
|
||||
RollCount = rollCount,
|
||||
GenderRatio = Gender switch
|
||||
{
|
||||
Gender.Male => PersonalInfo.RatioMagicMale,
|
||||
@@ -111,12 +113,21 @@ private OverworldParam8a GetParams(PersonalInfo8LA pi) => new()
|
||||
// hardcoded 7 to assume max dex progress + shiny charm.
|
||||
private const int MaxRollCount = 7;
|
||||
|
||||
private static byte GetRollCount(SlotType8a type) => (byte)(MaxRollCount + type switch
|
||||
private byte GetRollCount(SlotType8a type, ITrainerInfo tr) => (byte)(GetRollCountBase(tr, Species) + GetRollCountBoost(type));
|
||||
|
||||
private static byte GetRollCountBoost(SlotType8a type) => type switch
|
||||
{
|
||||
SlotType8a.MassOutbreakMassive => 12,
|
||||
SlotType8a.MassOutbreakRegular => 25,
|
||||
_ => 0,
|
||||
});
|
||||
};
|
||||
|
||||
private int GetRollCountBase(ITrainerInfo tr, ushort species)
|
||||
{
|
||||
if (tr is not ITrainerInfo8a la)
|
||||
return MaxRollCount;
|
||||
return la.GetShinyRolls(species);
|
||||
}
|
||||
|
||||
private void SetEncounterMoves(PA8 pk, byte level)
|
||||
{
|
||||
@@ -246,7 +257,8 @@ public SeedCorrelationResult TryGetSeed(PKM pk, out ulong seed)
|
||||
{
|
||||
// Check if it matches any single-roll seed.
|
||||
var pi = PersonalTable.LA[Species, Form];
|
||||
var param = GetParams(pi) with { RollCount = 1 };
|
||||
var rollCount = (byte)(1 + GetRollCountBoost(Type));
|
||||
var param = GetParams(pi, rollCount);
|
||||
var solver = new XoroMachineSkip(pk.EncryptionConstant, pk.PID);
|
||||
foreach (var s in solver)
|
||||
{
|
||||
|
||||
@@ -118,7 +118,7 @@ private void Finalize(PA8 pk, ulong slotSeed)
|
||||
SetEncounterMoves(pk, pk.MetLevel);
|
||||
}
|
||||
|
||||
public void GenerateSeed64(PKM pk, ulong seed)
|
||||
public void GenerateSeed64(PKM pk, ITrainerInfo tr, ulong seed)
|
||||
{
|
||||
var pa8 = (PA8)pk;
|
||||
var criteria = EncounterCriteria.Unrestricted;
|
||||
|
||||
@@ -9,5 +9,5 @@ public interface IGenerateSeed64
|
||||
/// Generates the <see cref="PKM"/> from the seed.
|
||||
/// </summary>
|
||||
/// <remarks>Be sure the <see cref="pk"/> is un-converted and matches its original type.</remarks>
|
||||
void GenerateSeed64(PKM pk, ulong seed);
|
||||
void GenerateSeed64(PKM pk, ITrainerInfo tr, ulong seed);
|
||||
}
|
||||
|
||||
@@ -284,7 +284,7 @@ private static bool TryGetMatch<T>(in SearchContext<T> ctx, uint seed, byte natu
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the magic number that that allows any lead to be used, enabling the generation target to require or not require a synchronize lead.
|
||||
/// Represents the magic number that allows any lead to be used, enabling the generation target to require or not require a synchronize lead.
|
||||
/// </summary>
|
||||
private const Nature LeadSyncAllowed = Nature.Random;
|
||||
|
||||
|
||||
@@ -137,3 +137,15 @@ private static bool IsMatchVersion(ITrainerInfo tr, PKM pk)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save File specific interface for trainer objects to expose information about how many shiny rolls a species may be generated with.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Currently only useful for <see cref="GameVersion.PLA"/> which ties Pokédex progress to shiny rolls.
|
||||
/// By implementing this interface, a generated Pokémon can be generated more plausibly, and the save file can quickly inform.
|
||||
/// </remarks>
|
||||
public interface ITrainerInfo8a
|
||||
{
|
||||
byte GetShinyRolls(ushort species);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace PKHeX.Core;
|
||||
/// <summary>
|
||||
/// Generation 8 <see cref="SaveFile"/> object for <see cref="GameVersion.PLA"/> games.
|
||||
/// </summary>
|
||||
public sealed class SAV8LA : SaveFile, ISaveBlock8LA, ISCBlockArray, ISaveFileRevision, IBoxDetailName, IBoxDetailWallpaper
|
||||
public sealed class SAV8LA : SaveFile, ISaveBlock8LA, ISCBlockArray, ISaveFileRevision, IBoxDetailName, IBoxDetailWallpaper, ITrainerInfo8a
|
||||
{
|
||||
protected internal override string ShortSummary => $"{OT} ({Version}) - {LastSaved.DisplayValue}";
|
||||
public override string Extension => string.Empty;
|
||||
@@ -136,6 +136,33 @@ protected override SAV8LA CloneInternal()
|
||||
protected override Span<byte> PartyBuffer => PartyInfo.Data;
|
||||
|
||||
public override bool HasPokeDex => true;
|
||||
|
||||
public byte GetShinyRolls(ushort species)
|
||||
{
|
||||
// Level 10: +1
|
||||
// Perfect: +2
|
||||
// Shiny Charm: +3
|
||||
|
||||
var dex = PokedexSave;
|
||||
byte rolls = HasKeyItem(632) ? (byte)(1 + 3) : (byte)1;
|
||||
if (!dex.IsComplete(species))
|
||||
return rolls;
|
||||
if (!dex.IsPerfect(species))
|
||||
return (byte)(rolls + 1);
|
||||
return (byte)(rolls + 3);
|
||||
}
|
||||
|
||||
private bool HasKeyItem(ushort item)
|
||||
{
|
||||
var span = Accessor.GetBlock(SaveBlockAccessor8LA.KItemKey).Data;
|
||||
// Look for (u16 632, u16 1) after reinterpreting as u32, respecting endianness as Little Endian
|
||||
var cast = System.Runtime.InteropServices.MemoryMarshal.Cast<byte, uint>(span);
|
||||
var seek = (uint)(item | (1 << 16)); // 0x00010278
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
seek = System.Buffers.Binary.BinaryPrimitives.ReverseEndianness(seek);
|
||||
return cast.Contains(seek);
|
||||
}
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
Box = 0;
|
||||
|
||||
@@ -8,7 +8,7 @@ public sealed record InventoryItem8a : InventoryItem, IItemFavorite
|
||||
public const int SIZE = 0x10;
|
||||
|
||||
public override string ToString() => $"{Index:000} x{Count}";
|
||||
public bool IsFavorite { get; set; }
|
||||
public bool IsFavorite { get; set; } // favorites stored separately, this is just a fake property mirror
|
||||
|
||||
public override void Clear()
|
||||
{
|
||||
@@ -23,7 +23,7 @@ public static InventoryItem8a Read(ReadOnlySpan<byte> data) => new()
|
||||
|
||||
public void Write(Span<byte> data)
|
||||
{
|
||||
// Index is not saved.
|
||||
// Favorite is saved separately.
|
||||
WriteUInt16LittleEndian(data, (ushort)Index);
|
||||
WriteUInt16LittleEndian(data[2..], (ushort)Count);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user