mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-10 06:34:19 +00:00
Misc tweaks
ShowdownSet: Fix indentation, use explicit const ItemStorage8BDSP: Rename GetAll->GetAllHeld to match others EncounterLearn: Guard against >4 length enumerables, use explicit versions for S/V EggMoves: Read u16[] directly rather than manually SaveFinder: simplify expression SAV_Database: extract func SAV_Encounters: use RoM to match Moveset generator
This commit is contained in:
parent
d56eb0e3c4
commit
424cbcff21
9 changed files with 62 additions and 58 deletions
|
@ -373,7 +373,7 @@ public sealed class ShowdownSet : IBattleTemplate
|
|||
result.Add($"Ability: {Strings.Ability[Ability]}");
|
||||
if (Context == EntityContext.Gen9 && TeraType != MoveType.Any)
|
||||
{
|
||||
if ((uint)TeraType <= (int)MoveType.Fairy)
|
||||
if ((uint)TeraType <= TeraTypeUtil.MaxType) // Fairy
|
||||
result.Add($"Tera Type: {Strings.Types[(int)TeraType]}");
|
||||
else if ((uint)TeraType == TeraTypeUtil.Stellar)
|
||||
result.Add($"Tera Type: {Strings.Types[TeraTypeUtil.StellarTypeDisplayStringIndex]}");
|
||||
|
@ -740,7 +740,7 @@ public sealed class ShowdownSet : IBattleTemplate
|
|||
return type;
|
||||
|
||||
if (type[0] == '(' && type[^1] == ')')
|
||||
return type[1..^1].Trim();
|
||||
return type[1..^1].Trim();
|
||||
if (type[0] == '[' && type[^1] == ']')
|
||||
return type[1..^1].Trim();
|
||||
|
||||
|
|
|
@ -155,7 +155,7 @@ public sealed class ItemStorage8BDSP : IItemStorage
|
|||
InventoryType.Berries, InventoryType.Balls, InventoryType.BattleItems, InventoryType.Treasure,
|
||||
];
|
||||
|
||||
public static ushort[] GetAll() => [..Pouch_Regular_BS, ..Pouch_Ball_BS, ..Pouch_Battle_BS, ..Pouch_Berries_BS, ..Pouch_TMHM_BS, ..Pouch_Medicine_BS, ..Pouch_Treasure_BS];
|
||||
public static ushort[] GetAllHeld() => [..Pouch_Regular_BS, ..Pouch_Ball_BS, ..Pouch_Battle_BS, ..Pouch_Berries_BS, ..Pouch_TMHM_BS, ..Pouch_Medicine_BS, ..Pouch_Treasure_BS];
|
||||
|
||||
public static InventoryType GetInventoryPouch(ushort itemIndex)
|
||||
{
|
||||
|
|
|
@ -150,7 +150,7 @@ public static class Legal
|
|||
internal static readonly ushort[] HeldItems_USUM = ItemStorage7USUM.GetAllHeld();
|
||||
internal static readonly ushort[] HeldItems_GG = [];
|
||||
internal static readonly ushort[] HeldItems_SWSH = ItemStorage8SWSH.GetAllHeld();
|
||||
internal static readonly ushort[] HeldItems_BS = ItemStorage8BDSP.GetAll();
|
||||
internal static readonly ushort[] HeldItems_BS = ItemStorage8BDSP.GetAllHeld();
|
||||
internal static readonly ushort[] HeldItems_LA = [];
|
||||
internal static readonly ushort[] HeldItems_SV = ItemStorage9SV.GetAllHeld();
|
||||
|
||||
|
|
|
@ -48,41 +48,44 @@ public static class EncounterLearn
|
|||
if (speciesID <= 0)
|
||||
return [];
|
||||
|
||||
var allMoves = moves.ToList();
|
||||
var span = new ushort[allMoves.Count];
|
||||
for (int i = 0; i < span.Length; i++)
|
||||
const int maxMoves = 4;
|
||||
Span<ushort> span = stackalloc ushort[maxMoves];
|
||||
int ctr = 0;
|
||||
foreach (var move in moves)
|
||||
{
|
||||
var move = allMoves[i];
|
||||
var index = StringUtil.FindIndexIgnoreCase(str.movelist, move);
|
||||
if (index <= 0)
|
||||
return [];
|
||||
span[i] = (ushort)index;
|
||||
span[ctr++] = (ushort)index;
|
||||
if (ctr >= span.Length)
|
||||
break;
|
||||
}
|
||||
var moveset = span[..ctr].ToArray();
|
||||
|
||||
return GetLearn((ushort)speciesID, span, form);
|
||||
return GetLearn((ushort)speciesID, moveset, form);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all encounters where a <see cref="species"/> can learn all input <see cref="moves"/>.
|
||||
/// </summary>
|
||||
public static IEnumerable<IEncounterable> GetLearn(ushort species, ushort[] moves, byte form = 0)
|
||||
public static IEnumerable<IEncounterable> GetLearn(ushort species, ReadOnlyMemory<ushort> moves, byte form = 0)
|
||||
{
|
||||
if (species == 0)
|
||||
return [];
|
||||
if (moves.AsSpan().Contains<ushort>(0))
|
||||
if (moves.Span.Contains<ushort>(0))
|
||||
return [];
|
||||
|
||||
var vers = GameUtil.GameVersions;
|
||||
return GetLearnInternal(species, form, moves, vers);
|
||||
}
|
||||
|
||||
private static IEnumerable<IEncounterable> GetLearnInternal(ushort species, byte form, ushort[] moves, GameVersion[] vers)
|
||||
private static IEnumerable<IEncounterable> GetLearnInternal(ushort species, byte form, ReadOnlyMemory<ushort> moves, GameVersion[] vers)
|
||||
{
|
||||
bool iterated = false;
|
||||
if (PersonalTable.SV.IsPresentInGame(species, form))
|
||||
{
|
||||
var blank = new PK9 { Species = species, Form = form };
|
||||
var encs = EncounterMovesetGenerator.GenerateEncounters(blank, moves, vers);
|
||||
var encs = EncounterMovesetGenerator.GenerateEncounters(blank, moves, GameVersion.SL, GameVersion.VL);
|
||||
foreach (var enc in encs)
|
||||
yield return enc;
|
||||
}
|
||||
|
@ -92,7 +95,6 @@ public static class EncounterLearn
|
|||
var encs = EncounterMovesetGenerator.GenerateEncounters(blank, moves, GameVersion.PLA);
|
||||
foreach (var enc in encs)
|
||||
yield return enc;
|
||||
iterated = true;
|
||||
}
|
||||
if (PersonalTable.BDSP.IsPresentInGame(species, form))
|
||||
{
|
||||
|
@ -100,7 +102,6 @@ public static class EncounterLearn
|
|||
var encs = EncounterMovesetGenerator.GenerateEncounters(blank, moves, GameVersion.BD, GameVersion.SP);
|
||||
foreach (var enc in encs)
|
||||
yield return enc;
|
||||
iterated = true;
|
||||
}
|
||||
if (PersonalTable.SWSH.IsPresentInGame(species, form))
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using static System.Buffers.Binary.BinaryPrimitives;
|
||||
|
||||
namespace PKHeX.Core;
|
||||
|
@ -73,10 +74,9 @@ public sealed class EggMoves6 : EggMoves
|
|||
continue;
|
||||
}
|
||||
|
||||
var moves = new ushort[count];
|
||||
var span = data[2..];
|
||||
for (int j = 0; j < moves.Length; j++)
|
||||
moves[j] = ReadUInt16LittleEndian(span[(j * 2)..]);
|
||||
var moves = MemoryMarshal.Cast<byte, ushort>(data).Slice(1, count).ToArray();
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
ReverseEndianness(moves, moves);
|
||||
result[i] = new EggMoves6(moves);
|
||||
}
|
||||
return result;
|
||||
|
@ -91,6 +91,7 @@ public sealed class EggMoves7 : EggMoves
|
|||
/// <summary>
|
||||
/// Points to the index where form data is, within the parent Egg Move object array.
|
||||
/// </summary>
|
||||
/// <remarks>This value is the same for all form entries for a given species.</remarks>
|
||||
public readonly ushort FormTableIndex;
|
||||
|
||||
private EggMoves7(ushort[] moves, ushort formIndex = 0) : base(moves) => FormTableIndex = formIndex;
|
||||
|
@ -114,10 +115,9 @@ public sealed class EggMoves7 : EggMoves
|
|||
continue;
|
||||
}
|
||||
|
||||
var moves = new ushort[count];
|
||||
var span = data[4..];
|
||||
for (int j = 0; j < moves.Length; j++)
|
||||
moves[j] = ReadUInt16LittleEndian(span[(j * 2)..]);
|
||||
var moves = MemoryMarshal.Cast<byte, ushort>(data).Slice(2, count).ToArray();
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
ReverseEndianness(moves, moves);
|
||||
result[i] = new EggMoves7(moves, formIndex);
|
||||
}
|
||||
return result;
|
||||
|
@ -130,17 +130,23 @@ internal static class EggMovesExtensions
|
|||
{
|
||||
if (species >= table.Length)
|
||||
return [];
|
||||
|
||||
var entry = table[species];
|
||||
if (form == 0 || species >= entry.FormTableIndex)
|
||||
|
||||
// Sanity check species in the event it is out of range.
|
||||
var baseIndex = entry.FormTableIndex;
|
||||
if (species > baseIndex)
|
||||
return [];
|
||||
|
||||
if (form == 0)
|
||||
return entry.Moves;
|
||||
|
||||
// Sanity check form in the event it is out of range.
|
||||
var baseIndex = entry.FormTableIndex;
|
||||
var index = baseIndex + form - 1;
|
||||
if ((uint)index >= table.Length)
|
||||
// Jump to the associated form's entry within the table.
|
||||
var index = form - 1u + baseIndex;
|
||||
if (index >= table.Length)
|
||||
return [];
|
||||
entry = table[index];
|
||||
|
||||
// Double-check that the entry is still associated to the species.
|
||||
if (entry.FormTableIndex != baseIndex)
|
||||
return [];
|
||||
|
||||
|
@ -165,9 +171,9 @@ public static class EggMoves9
|
|||
result[i] = empty;
|
||||
continue;
|
||||
}
|
||||
var moves = new ushort[data.Length >> 1];
|
||||
for (int j = 0; j < data.Length; j+=2)
|
||||
moves[j >> 1] = ReadUInt16LittleEndian(data[j..]);
|
||||
var moves = MemoryMarshal.Cast<byte, ushort>(data).ToArray();
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
ReverseEndianness(moves, moves);
|
||||
result[i] = moves;
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -165,20 +165,17 @@ public static class SaveFinder
|
|||
/// <inheritdoc cref="GetSaveFiles"/>
|
||||
public static IEnumerable<SaveFile> DetectSaveFiles() => GetSaveFiles(Environment.GetLogicalDrives(), true, CustomBackupPaths, true);
|
||||
|
||||
/// <inheritdoc cref="TryDetectSaveFile(out SaveFile?)"/>
|
||||
/// <returns>
|
||||
/// True if a valid save file was found, false otherwise.
|
||||
/// </returns>
|
||||
/// <inheritdoc cref="FindMostRecentSaveFile(IReadOnlyList{string},string[])"/>
|
||||
public static bool TryDetectSaveFile([NotNullWhen(true)] out SaveFile? sav) => TryDetectSaveFile(Environment.GetLogicalDrives(), out sav);
|
||||
|
||||
/// <inheritdoc cref="TryDetectSaveFile(out SaveFile)"/>
|
||||
public static bool TryDetectSaveFile(IReadOnlyList<string> drives, [NotNullWhen(true)] out SaveFile? sav)
|
||||
{
|
||||
var result = FindMostRecentSaveFile(drives, CustomBackupPaths);
|
||||
if (result == null)
|
||||
{
|
||||
sav = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
var path = result.Metadata.FilePath!;
|
||||
sav = result;
|
||||
sav = FindMostRecentSaveFile(drives, CustomBackupPaths);
|
||||
var path = sav?.Metadata.FilePath;
|
||||
return File.Exists(path);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -402,18 +402,9 @@ public partial class SAV_Database : Form
|
|||
|
||||
if (Main.Settings.EntityDb.FilterUnavailableSpecies)
|
||||
{
|
||||
static bool IsPresentInGameSV(ISpeciesForm pk) => pk is PK9 || PersonalTable.SV.IsPresentInGame(pk.Species, pk.Form);
|
||||
static bool IsPresentInGameSWSH(ISpeciesForm pk) => pk is PK8 || PersonalTable.SWSH.IsPresentInGame(pk.Species, pk.Form);
|
||||
static bool IsPresentInGameBDSP(ISpeciesForm pk) => pk is PB8 || PersonalTable.BDSP.IsPresentInGame(pk.Species, pk.Form);
|
||||
static bool IsPresentInGamePLA(ISpeciesForm pk) => pk is PA8 || PersonalTable.LA.IsPresentInGame(pk.Species, pk.Form);
|
||||
if (sav is SAV9SV)
|
||||
result.RemoveAll(z => !IsPresentInGameSV(z.Entity));
|
||||
else if (sav is SAV8SWSH)
|
||||
result.RemoveAll(z => !IsPresentInGameSWSH(z.Entity));
|
||||
else if (sav is SAV8BS)
|
||||
result.RemoveAll(z => !IsPresentInGameBDSP(z.Entity));
|
||||
else if (sav is SAV8LA)
|
||||
result.RemoveAll(z => !IsPresentInGamePLA(z.Entity));
|
||||
var filter = GetFilterForSaveFile(sav);
|
||||
if (filter != null)
|
||||
result.RemoveAll(z => !filter(z.Entity));
|
||||
}
|
||||
|
||||
var sort = Main.Settings.EntityDb.InitialSortMode;
|
||||
|
@ -426,6 +417,15 @@ public partial class SAV_Database : Form
|
|||
return result;
|
||||
}
|
||||
|
||||
private static Func<PKM, bool>? GetFilterForSaveFile(SaveFile sav) => sav switch
|
||||
{
|
||||
SAV8SWSH => static pk => pk is PK9 || PersonalTable.SV.IsPresentInGame(pk.Species, pk.Form),
|
||||
SAV8BS => static pk => pk is PK8 || PersonalTable.SWSH.IsPresentInGame(pk.Species, pk.Form),
|
||||
SAV8LA => static pk => pk is PB8 || PersonalTable.BDSP.IsPresentInGame(pk.Species, pk.Form),
|
||||
SAV9SV => static pk => pk is PA8 || PersonalTable.LA.IsPresentInGame(pk.Species, pk.Form),
|
||||
_ => null,
|
||||
};
|
||||
|
||||
private static void TryAddPKMsFromSaveFilePath(ConcurrentBag<SlotCache> dbTemp, string file)
|
||||
{
|
||||
var sav = SaveUtil.GetVariantSAV(file);
|
||||
|
|
|
@ -299,7 +299,7 @@ public partial class SAV_Encounters : Form
|
|||
yield return i;
|
||||
}
|
||||
|
||||
private IEnumerable<IEncounterInfo> GetAllSpeciesFormEncounters(IEnumerable<ushort> species, IPersonalTable pt, IReadOnlyList<GameVersion> versions, ushort[] moves, PKM pk, CancellationToken token)
|
||||
private IEnumerable<IEncounterInfo> GetAllSpeciesFormEncounters(IEnumerable<ushort> species, IPersonalTable pt, IReadOnlyList<GameVersion> versions, ReadOnlyMemory<ushort> moves, PKM pk, CancellationToken token)
|
||||
{
|
||||
foreach (var s in species)
|
||||
{
|
||||
|
@ -339,7 +339,7 @@ public partial class SAV_Encounters : Form
|
|||
public int GetHashCode(T obj) => RuntimeHelpers.GetHashCode(obj);
|
||||
}
|
||||
|
||||
private IEnumerable<IEncounterInfo> GetEncounters(ushort species, byte form, ushort[] moves, PKM pk, IReadOnlyList<GameVersion> vers)
|
||||
private IEnumerable<IEncounterInfo> GetEncounters(ushort species, byte form, ReadOnlyMemory<ushort> moves, PKM pk, IReadOnlyList<GameVersion> vers)
|
||||
{
|
||||
pk.Species = species;
|
||||
pk.Form = form;
|
||||
|
|
|
@ -54,7 +54,7 @@ public class ShowdownSetTests
|
|||
public void SimGetVivillonPostcardSV(byte form)
|
||||
{
|
||||
var pk9 = new PK9 { Species = (int)Species.Vivillon, Form = form };
|
||||
ushort[] moves = [];
|
||||
var moves = ReadOnlyMemory<ushort>.Empty;
|
||||
var encounters = EncounterMovesetGenerator.GenerateEncounters(pk9, moves, GameVersion.SL);
|
||||
encounters.OfType<EncounterSlot9>().Should().NotBeEmpty();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue