mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-23 04:23:12 +00:00
Misc tweaks
Add xmldoc Simplify some casts Demote priority of Gen2 event yielding Remove old EncounterMatchUtil code Repoint DateTime.Now to console specific date provider stubs
This commit is contained in:
parent
c7aa497e73
commit
b536388d0d
71 changed files with 376 additions and 212 deletions
|
@ -30,12 +30,12 @@ public sealed class QRPK7 : IEncounterInfo
|
||||||
public int Move3_PPUps => Data[0xA];
|
public int Move3_PPUps => Data[0xA];
|
||||||
public int Move4_PPUps => Data[0xB];
|
public int Move4_PPUps => Data[0xB];
|
||||||
public uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0xC)); set => WriteUInt32LittleEndian(Data.AsSpan(0xC), value); }
|
public uint IV32 { get => ReadUInt32LittleEndian(Data.AsSpan(0xC)); set => WriteUInt32LittleEndian(Data.AsSpan(0xC), value); }
|
||||||
public int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 00)) | (uint)((value > 31 ? 31 : value) << 00)); }
|
public int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | (uint)((value > 31 ? 31 : value) << 00); }
|
||||||
public int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 05)) | (uint)((value > 31 ? 31 : value) << 05)); }
|
public int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | (uint)((value > 31 ? 31 : value) << 05); }
|
||||||
public int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 10)) | (uint)((value > 31 ? 31 : value) << 10)); }
|
public int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | (uint)((value > 31 ? 31 : value) << 10); }
|
||||||
public int IV_SPE { get => (int)(IV32 >> 15) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 15)) | (uint)((value > 31 ? 31 : value) << 15)); }
|
public int IV_SPE { get => (int)(IV32 >> 15) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 15)) | (uint)((value > 31 ? 31 : value) << 15); }
|
||||||
public int IV_SPA { get => (int)(IV32 >> 20) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 20)) | (uint)((value > 31 ? 31 : value) << 20)); }
|
public int IV_SPA { get => (int)(IV32 >> 20) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 20)) | (uint)((value > 31 ? 31 : value) << 20); }
|
||||||
public int IV_SPD { get => (int)(IV32 >> 25) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 25)) | (uint)((value > 31 ? 31 : value) << 25)); }
|
public int IV_SPD { get => (int)(IV32 >> 25) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 25)) | (uint)((value > 31 ? 31 : value) << 25); }
|
||||||
public uint PID => ReadUInt32LittleEndian(Data.AsSpan(0x10));
|
public uint PID => ReadUInt32LittleEndian(Data.AsSpan(0x10));
|
||||||
public ushort Species => ReadUInt16LittleEndian(Data.AsSpan(0x14));
|
public ushort Species => ReadUInt16LittleEndian(Data.AsSpan(0x14));
|
||||||
public ushort HeldItem => ReadUInt16LittleEndian(Data.AsSpan(0x16));
|
public ushort HeldItem => ReadUInt16LittleEndian(Data.AsSpan(0x16));
|
||||||
|
|
|
@ -135,9 +135,9 @@ public sealed class GameDataSource
|
||||||
{
|
{
|
||||||
var languages = new List<ComboItem>(LanguageList);
|
var languages = new List<ComboItem>(LanguageList);
|
||||||
if (gen == 3)
|
if (gen == 3)
|
||||||
languages.RemoveAll(l => l.Value >= (int)LanguageID.Korean);
|
languages.RemoveAll(static l => l.Value >= (int)LanguageID.Korean);
|
||||||
else if (gen < 7)
|
else if (gen < 7)
|
||||||
languages.RemoveAll(l => l.Value > (int)LanguageID.Korean);
|
languages.RemoveAll(static l => l.Value > (int)LanguageID.Korean);
|
||||||
return languages;
|
return languages;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -273,22 +273,33 @@ public sealed class MetDataSource
|
||||||
BD or SP => Partition2(MetGen8b, IsMetLocation8BDSP),
|
BD or SP => Partition2(MetGen8b, IsMetLocation8BDSP),
|
||||||
PLA => Partition2(MetGen8a, IsMetLocation8LA),
|
PLA => Partition2(MetGen8a, IsMetLocation8LA),
|
||||||
SL or VL => Partition2(MetGen9, IsMetLocation9SV),
|
SL or VL => Partition2(MetGen9, IsMetLocation9SV),
|
||||||
_ => new List<ComboItem>(GetLocationListModified(version, context)),
|
_ => GetLocationListModified(version, context),
|
||||||
};
|
};
|
||||||
|
|
||||||
static IReadOnlyList<ComboItem> Partition1(IReadOnlyList<ComboItem> list, Func<ushort, bool> criteria)
|
static ComboItem[] Partition1(List<ComboItem> list, Func<ushort, bool> criteria)
|
||||||
{
|
{
|
||||||
|
var span = CollectionsMarshal.AsSpan(list);
|
||||||
var result = new ComboItem[list.Count];
|
var result = new ComboItem[list.Count];
|
||||||
return GetOrderedList(list, result, criteria);
|
ReorderList(span, result, criteria);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static IReadOnlyList<ComboItem> GetOrderedList(IReadOnlyList<ComboItem> list, ComboItem[] result,
|
static ComboItem[] Partition2(List<ComboItem> list, Func<ushort, bool> criteria, int keepFirst = 3)
|
||||||
Func<ushort, bool> criteria, int start = 0)
|
{
|
||||||
|
var span = CollectionsMarshal.AsSpan(list);
|
||||||
|
var result = new ComboItem[span.Length];
|
||||||
|
for (int i = 0; i < keepFirst; i++)
|
||||||
|
result[i] = list[i];
|
||||||
|
ReorderList(span, result, criteria, keepFirst);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ReorderList(Span<ComboItem> list, Span<ComboItem> result, Func<ushort, bool> criteria, int start = 0)
|
||||||
{
|
{
|
||||||
// store values that match criteria at the next available position of the array
|
// store values that match criteria at the next available position of the array
|
||||||
// store non-matches starting at the end. reverse before returning
|
// store non-matches starting at the end. reverse before returning
|
||||||
int end = list.Count - 1;
|
int end = list.Length - 1;
|
||||||
for (var index = start; index < list.Count; index++)
|
for (var index = start; index < list.Length; index++)
|
||||||
{
|
{
|
||||||
var item = list[index];
|
var item = list[index];
|
||||||
if (criteria((ushort)item.Value))
|
if (criteria((ushort)item.Value))
|
||||||
|
@ -297,18 +308,8 @@ public sealed class MetDataSource
|
||||||
result[end--] = item;
|
result[end--] = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
// since the non-matches are reversed in order, we swap them back since we know where they end up at.
|
// since the non-matches are reversed in order, we reverse that section.
|
||||||
Array.Reverse(result, start, list.Count - start);
|
result[start..].Reverse();
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static IReadOnlyList<ComboItem> Partition2(IReadOnlyList<ComboItem> list, Func<ushort, bool> criteria,
|
|
||||||
int keepFirst = 3)
|
|
||||||
{
|
|
||||||
var result = new ComboItem[list.Count];
|
|
||||||
for (int i = 0; i < keepFirst; i++)
|
|
||||||
result[i] = list[i];
|
|
||||||
return GetOrderedList(list, result, criteria, keepFirst);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace PKHeX.Core;
|
||||||
public static class LocationsHOME
|
public static class LocationsHOME
|
||||||
{
|
{
|
||||||
// 60000 - (version - PLA)
|
// 60000 - (version - PLA)
|
||||||
private const int RemapCount = 5;
|
private const int RemapCount = 5; // Count of future game version IDs that can transfer back into SW/SH.
|
||||||
public const ushort SHVL = 59996; // VL traded to (SW)SH
|
public const ushort SHVL = 59996; // VL traded to (SW)SH
|
||||||
public const ushort SWSL = 59997; // SL traded to SW(SH)
|
public const ushort SWSL = 59997; // SL traded to SW(SH)
|
||||||
public const ushort SHSP = 59998; // SP traded to (SW)SH
|
public const ushort SHSP = 59998; // SP traded to (SW)SH
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Buffers;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
|
@ -59,7 +60,13 @@ public static class BulkGenerator
|
||||||
template.Form = form;
|
template.Form = form;
|
||||||
template.Gender = template.GetSaneGender();
|
template.Gender = template.GetSaneGender();
|
||||||
|
|
||||||
var f = EncounterMovesetGenerator.GeneratePKMs(template, tr, template.Moves).FirstOrDefault();
|
var moves = ArrayPool<ushort>.Shared.Rent(4);
|
||||||
|
var memory = moves.AsMemory(0, 4);
|
||||||
|
var span = memory.Span;
|
||||||
|
template.GetMoves(span);
|
||||||
|
var f = EncounterMovesetGenerator.GeneratePKMs(template, tr, memory).FirstOrDefault();
|
||||||
|
span.Clear();
|
||||||
|
ArrayPool<ushort>.Shared.Return(moves);
|
||||||
if (f == null)
|
if (f == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
|
|
@ -167,23 +167,23 @@ public static class EncounterFinder
|
||||||
LearnVerifier.Verify(info.Moves, pk, info.EncounterMatch, info.EvoChainsAllGens);
|
LearnVerifier.Verify(info.Moves, pk, info.EncounterMatch, info.EvoChainsAllGens);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetHintWhyNotFound(PKM pk, int gen)
|
private static string GetHintWhyNotFound(PKM pk, int generation)
|
||||||
{
|
{
|
||||||
if (WasGiftEgg(pk, gen, (ushort)pk.Egg_Location))
|
if (WasGiftEgg(pk, generation, (ushort)pk.Egg_Location))
|
||||||
return LEncGift;
|
return LEncGift;
|
||||||
if (WasEventEgg(pk, gen))
|
if (WasEventEgg(pk, generation))
|
||||||
return LEncGiftEggEvent;
|
return LEncGiftEggEvent;
|
||||||
if (WasEvent(pk, gen))
|
if (WasEvent(pk, generation))
|
||||||
return LEncGiftNotFound;
|
return LEncGiftNotFound;
|
||||||
return LEncInvalid;
|
return LEncInvalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool WasGiftEgg(PKM pk, int gen, ushort loc) => !pk.FatefulEncounter && gen switch
|
private static bool WasGiftEgg(PKM pk, int generation, ushort eggLocation) => !pk.FatefulEncounter && generation switch
|
||||||
{
|
{
|
||||||
3 => pk.IsEgg && (byte)pk.Met_Location == 253, // Gift Egg, indistinguishable from normal eggs after hatch
|
3 => pk.IsEgg && (byte)pk.Met_Location == 253, // Gift Egg, indistinguishable from normal eggs after hatch
|
||||||
4 => (uint)(loc - 2009) <= (2014 - 2009) || (pk.Format != 4 && (loc == Locations.Faraway4 && pk.HGSS)),
|
4 => eggLocation - 2009u <= (2014 - 2009) || (pk.Format != 4 && (eggLocation == Locations.Faraway4 && pk.HGSS)),
|
||||||
5 => loc is Locations.Breeder5,
|
5 => eggLocation is Locations.Breeder5,
|
||||||
_ => loc is Locations.Breeder6,
|
_ => eggLocation is Locations.Breeder6,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static bool WasEventEgg(PKM pk, int gen) => gen switch
|
private static bool WasEventEgg(PKM pk, int gen) => gen switch
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find possible encounters for <see cref="GameVersion.Gen1"/> encounters.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterPossible1(EvoCriteria[] Chain, EncounterTypeGroup Flags, GameVersion Version) : IEnumerator<IEncounterable>
|
public record struct EncounterPossible1(EvoCriteria[] Chain, EncounterTypeGroup Flags, GameVersion Version) : IEnumerator<IEncounterable>
|
||||||
{
|
{
|
||||||
public IEncounterable Current { get; private set; }
|
public IEncounterable Current { get; private set; }
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find possible encounters for <see cref="GameVersion.Gen2"/> encounters.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterPossible2(EvoCriteria[] Chain, EncounterTypeGroup Flags, GameVersion Version, PKM Entity) : IEnumerator<IEncounterable>
|
public record struct EncounterPossible2(EvoCriteria[] Chain, EncounterTypeGroup Flags, GameVersion Version, PKM Entity) : IEnumerator<IEncounterable>
|
||||||
{
|
{
|
||||||
public IEncounterable Current { get; private set; }
|
public IEncounterable Current { get; private set; }
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find possible encounters for <see cref="GameVersion.Gen3"/> encounters.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterPossible3(EvoCriteria[] Chain, EncounterTypeGroup Flags, GameVersion Version) : IEnumerator<IEncounterable>
|
public record struct EncounterPossible3(EvoCriteria[] Chain, EncounterTypeGroup Flags, GameVersion Version) : IEnumerator<IEncounterable>
|
||||||
{
|
{
|
||||||
public IEncounterable Current { get; private set; }
|
public IEncounterable Current { get; private set; }
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find possible encounters for <see cref="GameVersion.CXD"/> encounters.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterPossible3GC(EvoCriteria[] Chain, EncounterTypeGroup Flags) : IEnumerator<IEncounterable>
|
public record struct EncounterPossible3GC(EvoCriteria[] Chain, EncounterTypeGroup Flags) : IEnumerator<IEncounterable>
|
||||||
{
|
{
|
||||||
public IEncounterable Current { get; private set; }
|
public IEncounterable Current { get; private set; }
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find possible encounters for <see cref="GameVersion.Gen4"/> encounters.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterPossible4(EvoCriteria[] Chain, EncounterTypeGroup Flags, GameVersion Version) : IEnumerator<IEncounterable>
|
public record struct EncounterPossible4(EvoCriteria[] Chain, EncounterTypeGroup Flags, GameVersion Version) : IEnumerator<IEncounterable>
|
||||||
{
|
{
|
||||||
public IEncounterable Current { get; private set; }
|
public IEncounterable Current { get; private set; }
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find possible encounters for <see cref="GameVersion.Gen5"/> encounters.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterPossible5(EvoCriteria[] Chain, EncounterTypeGroup Flags, GameVersion Version) : IEnumerator<IEncounterable>
|
public record struct EncounterPossible5(EvoCriteria[] Chain, EncounterTypeGroup Flags, GameVersion Version) : IEnumerator<IEncounterable>
|
||||||
{
|
{
|
||||||
public IEncounterable Current { get; private set; }
|
public IEncounterable Current { get; private set; }
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find possible encounters for <see cref="GameVersion.Gen6"/> encounters.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterPossible6(EvoCriteria[] Chain, EncounterTypeGroup Flags, GameVersion Version) : IEnumerator<IEncounterable>
|
public record struct EncounterPossible6(EvoCriteria[] Chain, EncounterTypeGroup Flags, GameVersion Version) : IEnumerator<IEncounterable>
|
||||||
{
|
{
|
||||||
public IEncounterable Current { get; private set; }
|
public IEncounterable Current { get; private set; }
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find possible encounters for <see cref="GameVersion.Gen7"/> encounters.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterPossible7(EvoCriteria[] Chain, EncounterTypeGroup Flags, GameVersion Version) : IEnumerator<IEncounterable>
|
public record struct EncounterPossible7(EvoCriteria[] Chain, EncounterTypeGroup Flags, GameVersion Version) : IEnumerator<IEncounterable>
|
||||||
{
|
{
|
||||||
public IEncounterable Current { get; private set; }
|
public IEncounterable Current { get; private set; }
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find possible encounters for <see cref="GameVersion.GG"/> encounters.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterPossible7GG(EvoCriteria[] Chain, EncounterTypeGroup Flags, GameVersion Version) : IEnumerator<IEncounterable>
|
public record struct EncounterPossible7GG(EvoCriteria[] Chain, EncounterTypeGroup Flags, GameVersion Version) : IEnumerator<IEncounterable>
|
||||||
{
|
{
|
||||||
public IEncounterable Current { get; private set; }
|
public IEncounterable Current { get; private set; }
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find possible encounters for <see cref="GameVersion.GO"/> encounters from LGP/E's GO Park.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterPossible7GO(EvoCriteria[] Chain, EncounterTypeGroup Flags) : IEnumerator<IEncounterable>
|
public record struct EncounterPossible7GO(EvoCriteria[] Chain, EncounterTypeGroup Flags) : IEnumerator<IEncounterable>
|
||||||
{
|
{
|
||||||
public IEncounterable Current { get; private set; }
|
public IEncounterable Current { get; private set; }
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find possible encounters for <see cref="GameVersion.SWSH"/> encounters.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterPossible8(EvoCriteria[] Chain, EncounterTypeGroup Flags, GameVersion Version) : IEnumerator<IEncounterable>
|
public record struct EncounterPossible8(EvoCriteria[] Chain, EncounterTypeGroup Flags, GameVersion Version) : IEnumerator<IEncounterable>
|
||||||
{
|
{
|
||||||
public IEncounterable Current { get; private set; }
|
public IEncounterable Current { get; private set; }
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find possible encounters for <see cref="GameVersion.GO"/> encounters.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterPossible8GO(EvoCriteria[] Chain, EncounterTypeGroup Flags) : IEnumerator<IEncounterable>
|
public record struct EncounterPossible8GO(EvoCriteria[] Chain, EncounterTypeGroup Flags) : IEnumerator<IEncounterable>
|
||||||
{
|
{
|
||||||
public IEncounterable Current { get; private set; }
|
public IEncounterable Current { get; private set; }
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find possible encounters for <see cref="GameVersion.PLA"/> encounters.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterPossible8a(EvoCriteria[] Chain, EncounterTypeGroup Flags) : IEnumerator<IEncounterable>
|
public record struct EncounterPossible8a(EvoCriteria[] Chain, EncounterTypeGroup Flags) : IEnumerator<IEncounterable>
|
||||||
{
|
{
|
||||||
public IEncounterable Current { get; private set; }
|
public IEncounterable Current { get; private set; }
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find possible encounters for <see cref="GameVersion.BDSP"/> encounters.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterPossible8b(EvoCriteria[] Chain, EncounterTypeGroup Flags, GameVersion Version) : IEnumerator<IEncounterable>
|
public record struct EncounterPossible8b(EvoCriteria[] Chain, EncounterTypeGroup Flags, GameVersion Version) : IEnumerator<IEncounterable>
|
||||||
{
|
{
|
||||||
public IEncounterable Current { get; private set; }
|
public IEncounterable Current { get; private set; }
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find possible encounters for <see cref="GameVersion.SV"/> encounters.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterPossible9(EvoCriteria[] Chain, EncounterTypeGroup Flags, GameVersion Version) : IEnumerator<IEncounterable>
|
public record struct EncounterPossible9(EvoCriteria[] Chain, EncounterTypeGroup Flags, GameVersion Version) : IEnumerator<IEncounterable>
|
||||||
{
|
{
|
||||||
public IEncounterable Current { get; private set; }
|
public IEncounterable Current { get; private set; }
|
||||||
|
|
|
@ -5,6 +5,9 @@ using System.Diagnostics;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find potentially matched encounters for <see cref="GameVersion.BDSP"/> encounters while in the <see cref="PK8"/> format.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterEnumerator8bSWSH(PKM Entity, EvoCriteria[] Chain, GameVersion Version) : IEnumerator<MatchedEncounter<IEncounterable>>
|
public record struct EncounterEnumerator8bSWSH(PKM Entity, EvoCriteria[] Chain, GameVersion Version) : IEnumerator<MatchedEncounter<IEncounterable>>
|
||||||
{
|
{
|
||||||
private IEncounterable? Deferred;
|
private IEncounterable? Deferred;
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find potentially matched encounters for <see cref="GameVersion.SV"/> encounters while in the <see cref="PK8"/> format.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterEnumerator9SWSH(PKM Entity, EvoCriteria[] Chain, GameVersion Version) : IEnumerator<MatchedEncounter<IEncounterable>>
|
public record struct EncounterEnumerator9SWSH(PKM Entity, EvoCriteria[] Chain, GameVersion Version) : IEnumerator<MatchedEncounter<IEncounterable>>
|
||||||
{
|
{
|
||||||
private IEncounterable? Deferred;
|
private IEncounterable? Deferred;
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find potentially matched encounters for <see cref="GameVersion.Gen1"/>.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterEnumerator1(PKM Entity, EvoCriteria[] Chain) : IEnumerator<MatchedEncounter<IEncounterable>>
|
public record struct EncounterEnumerator1(PKM Entity, EvoCriteria[] Chain) : IEnumerator<MatchedEncounter<IEncounterable>>
|
||||||
{
|
{
|
||||||
private IEncounterable? Deferred;
|
private IEncounterable? Deferred;
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find potentially matched encounters for <see cref="GameVersion.Gen2"/>.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterEnumerator2 : IEnumerator<MatchedEncounter<IEncounterable>>
|
public record struct EncounterEnumerator2 : IEnumerator<MatchedEncounter<IEncounterable>>
|
||||||
{
|
{
|
||||||
private IEncounterable? Deferred;
|
private IEncounterable? Deferred;
|
||||||
|
@ -79,25 +82,7 @@ public record struct EncounterEnumerator2 : IEnumerator<MatchedEncounter<IEncoun
|
||||||
case YieldState.Start:
|
case YieldState.Start:
|
||||||
if (Chain.Length == 0)
|
if (Chain.Length == 0)
|
||||||
break;
|
break;
|
||||||
goto case YieldState.EventStart;
|
State = YieldState.Trade; goto case YieldState.Trade;
|
||||||
|
|
||||||
case YieldState.EventStart:
|
|
||||||
if (Entity.Korean)
|
|
||||||
{ State = YieldState.Trade; goto case YieldState.Trade; }
|
|
||||||
if (ParseSettings.AllowGBVirtualConsole3DS)
|
|
||||||
{ State = YieldState.EventVC; goto case YieldState.EventVC; }
|
|
||||||
if (ParseSettings.AllowGBEraEvents)
|
|
||||||
{ State = YieldState.EventGB; goto case YieldState.EventGB; }
|
|
||||||
throw new InvalidOperationException("No events allowed");
|
|
||||||
case YieldState.EventVC:
|
|
||||||
State = YieldState.Trade;
|
|
||||||
if (IsMatch(Encounters2.CelebiVC))
|
|
||||||
return SetCurrent(Encounters2.CelebiVC);
|
|
||||||
goto case YieldState.Trade;
|
|
||||||
case YieldState.EventGB:
|
|
||||||
if (TryGetNext(Encounters2GBEra.StaticEventsGB))
|
|
||||||
return true;
|
|
||||||
Index = 0; State = YieldState.Trade; goto case YieldState.Trade;
|
|
||||||
|
|
||||||
case YieldState.Trade:
|
case YieldState.Trade:
|
||||||
if (TryGetNext(Encounters2.TradeGift_GSC))
|
if (TryGetNext(Encounters2.TradeGift_GSC))
|
||||||
|
@ -170,7 +155,25 @@ public record struct EncounterEnumerator2 : IEnumerator<MatchedEncounter<IEncoun
|
||||||
return true;
|
return true;
|
||||||
Index = 0; goto case YieldState.SlotEnd;
|
Index = 0; goto case YieldState.SlotEnd;
|
||||||
case YieldState.SlotEnd:
|
case YieldState.SlotEnd:
|
||||||
|
goto case YieldState.EventStart;
|
||||||
|
|
||||||
|
case YieldState.EventStart:
|
||||||
|
if (Entity.Korean)
|
||||||
|
{ State = YieldState.Fallback; goto case YieldState.Fallback; }
|
||||||
|
if (ParseSettings.AllowGBVirtualConsole3DS)
|
||||||
|
{ State = YieldState.EventVC; goto case YieldState.EventVC; }
|
||||||
|
if (ParseSettings.AllowGBEraEvents)
|
||||||
|
{ State = YieldState.EventGB; goto case YieldState.EventGB; }
|
||||||
|
throw new InvalidOperationException("No events allowed");
|
||||||
|
case YieldState.EventVC:
|
||||||
|
State = YieldState.Fallback;
|
||||||
|
if (IsMatch(Encounters2.CelebiVC))
|
||||||
|
return SetCurrent(Encounters2.CelebiVC);
|
||||||
goto case YieldState.Fallback;
|
goto case YieldState.Fallback;
|
||||||
|
case YieldState.EventGB:
|
||||||
|
if (TryGetNext(Encounters2GBEra.StaticEventsGB))
|
||||||
|
return true;
|
||||||
|
State = YieldState.Fallback; goto case YieldState.Fallback;
|
||||||
|
|
||||||
case YieldState.Fallback:
|
case YieldState.Fallback:
|
||||||
State = YieldState.End;
|
State = YieldState.End;
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find potentially matched encounters for <see cref="GameVersion.Gen3"/>.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterEnumerator3(PKM Entity, EvoCriteria[] Chain, GameVersion Version) : IEnumerator<MatchedEncounter<IEncounterable>>
|
public record struct EncounterEnumerator3(PKM Entity, EvoCriteria[] Chain, GameVersion Version) : IEnumerator<MatchedEncounter<IEncounterable>>
|
||||||
{
|
{
|
||||||
private IEncounterable? Deferred;
|
private IEncounterable? Deferred;
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find potentially matched encounters for <see cref="GameVersion.CXD"/>.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterEnumerator3GC(PKM Entity, EvoCriteria[] Chain) : IEnumerator<MatchedEncounter<IEncounterable>>
|
public record struct EncounterEnumerator3GC(PKM Entity, EvoCriteria[] Chain) : IEnumerator<MatchedEncounter<IEncounterable>>
|
||||||
{
|
{
|
||||||
private IEncounterable? Deferred;
|
private IEncounterable? Deferred;
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find potentially matched encounters for <see cref="GameVersion.Gen4"/>.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterEnumerator4(PKM Entity, EvoCriteria[] Chain, GameVersion Version) : IEnumerator<MatchedEncounter<IEncounterable>>
|
public record struct EncounterEnumerator4(PKM Entity, EvoCriteria[] Chain, GameVersion Version) : IEnumerator<MatchedEncounter<IEncounterable>>
|
||||||
{
|
{
|
||||||
private IEncounterable? Deferred;
|
private IEncounterable? Deferred;
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find potentially matched encounters for <see cref="GameVersion.Gen5"/>.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterEnumerator5(PKM Entity, EvoCriteria[] Chain, GameVersion Version) : IEnumerator<MatchedEncounter<IEncounterable>>
|
public record struct EncounterEnumerator5(PKM Entity, EvoCriteria[] Chain, GameVersion Version) : IEnumerator<MatchedEncounter<IEncounterable>>
|
||||||
{
|
{
|
||||||
private IEncounterable? Deferred;
|
private IEncounterable? Deferred;
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find potentially matched encounters for <see cref="GameVersion.Gen6"/>.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterEnumerator6(PKM Entity, EvoCriteria[] Chain, GameVersion Version) : IEnumerator<MatchedEncounter<IEncounterable>>
|
public record struct EncounterEnumerator6(PKM Entity, EvoCriteria[] Chain, GameVersion Version) : IEnumerator<MatchedEncounter<IEncounterable>>
|
||||||
{
|
{
|
||||||
private IEncounterable? Deferred;
|
private IEncounterable? Deferred;
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find potentially matched encounters for <see cref="GameVersion.Gen7"/>.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterEnumerator7(PKM Entity, EvoCriteria[] Chain, GameVersion Version) : IEnumerator<MatchedEncounter<IEncounterable>>
|
public record struct EncounterEnumerator7(PKM Entity, EvoCriteria[] Chain, GameVersion Version) : IEnumerator<MatchedEncounter<IEncounterable>>
|
||||||
{
|
{
|
||||||
private IEncounterable? Deferred;
|
private IEncounterable? Deferred;
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find potentially matched encounters for <see cref="GameVersion.GG"/>.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterEnumerator7GG(PKM Entity, EvoCriteria[] Chain, GameVersion Version) : IEnumerator<MatchedEncounter<IEncounterable>>
|
public record struct EncounterEnumerator7GG(PKM Entity, EvoCriteria[] Chain, GameVersion Version) : IEnumerator<MatchedEncounter<IEncounterable>>
|
||||||
{
|
{
|
||||||
private IEncounterable? Deferred;
|
private IEncounterable? Deferred;
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find potentially matched encounters for <see cref="GameVersion.GG"/> encounters from GO Park.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterEnumerator7GO(PKM Entity, EvoCriteria[] Chain) : IEnumerator<MatchedEncounter<IEncounterable>>
|
public record struct EncounterEnumerator7GO(PKM Entity, EvoCriteria[] Chain) : IEnumerator<MatchedEncounter<IEncounterable>>
|
||||||
{
|
{
|
||||||
private IEncounterable? Deferred;
|
private IEncounterable? Deferred;
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find potentially matched encounters for <see cref="GameVersion.SWSH"/>.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterEnumerator8(PKM Entity, EvoCriteria[] Chain, GameVersion Version) : IEnumerator<MatchedEncounter<IEncounterable>>
|
public record struct EncounterEnumerator8(PKM Entity, EvoCriteria[] Chain, GameVersion Version) : IEnumerator<MatchedEncounter<IEncounterable>>
|
||||||
{
|
{
|
||||||
private IEncounterable? Deferred;
|
private IEncounterable? Deferred;
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find potentially matched encounters for <see cref="GameVersion.GO"/>.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterEnumerator8GO(PKM Entity, EvoCriteria[] Chain) : IEnumerator<MatchedEncounter<IEncounterable>>
|
public record struct EncounterEnumerator8GO(PKM Entity, EvoCriteria[] Chain) : IEnumerator<MatchedEncounter<IEncounterable>>
|
||||||
{
|
{
|
||||||
private IEncounterable? Deferred;
|
private IEncounterable? Deferred;
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find potentially matched encounters for <see cref="GameVersion.PLA"/>.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterEnumerator8a(PKM Entity, EvoCriteria[] Chain) : IEnumerator<MatchedEncounter<IEncounterable>>
|
public record struct EncounterEnumerator8a(PKM Entity, EvoCriteria[] Chain) : IEnumerator<MatchedEncounter<IEncounterable>>
|
||||||
{
|
{
|
||||||
private IEncounterable? Deferred;
|
private IEncounterable? Deferred;
|
||||||
|
|
|
@ -5,6 +5,9 @@ using System.Diagnostics;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find potentially matched encounters for <see cref="GameVersion.BDSP"/>.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterEnumerator8b(PKM Entity, EvoCriteria[] Chain, GameVersion Version) : IEnumerator<MatchedEncounter<IEncounterable>>
|
public record struct EncounterEnumerator8b(PKM Entity, EvoCriteria[] Chain, GameVersion Version) : IEnumerator<MatchedEncounter<IEncounterable>>
|
||||||
{
|
{
|
||||||
private IEncounterable? Deferred;
|
private IEncounterable? Deferred;
|
||||||
|
|
|
@ -4,6 +4,9 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Iterates to find potentially matched encounters for <see cref="GameVersion.SV"/>.
|
||||||
|
/// </summary>
|
||||||
public record struct EncounterEnumerator9(PKM Entity, EvoCriteria[] Chain, GameVersion Version) : IEnumerator<MatchedEncounter<IEncounterable>>
|
public record struct EncounterEnumerator9(PKM Entity, EvoCriteria[] Chain, GameVersion Version) : IEnumerator<MatchedEncounter<IEncounterable>>
|
||||||
{
|
{
|
||||||
private IEncounterable? Deferred;
|
private IEncounterable? Deferred;
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tuple of matched encounter info.
|
||||||
|
/// </summary>
|
||||||
|
public readonly record struct MatchedEncounter<T>(T Encounter, EncounterMatchRating Rating);
|
|
@ -1,6 +1,3 @@
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -23,58 +20,3 @@ public enum EncounterMatchRating : ushort
|
||||||
/// <summary> Unused -- only used as an initial "max" value that anything else will be more suitable of a match. </summary>
|
/// <summary> Unused -- only used as an initial "max" value that anything else will be more suitable of a match. </summary>
|
||||||
MaxNotMatch,
|
MaxNotMatch,
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly record struct MatchedEncounter<T>(T Encounter, EncounterMatchRating Rating);
|
|
||||||
|
|
||||||
public static class EncounterMatchUtil
|
|
||||||
{
|
|
||||||
public static EncounterEnumerator<T> Enumerate<T>(this IReadOnlyList<T> encounters, EvoCriteria[] chain, PKM pk)
|
|
||||||
where T : IEncounterMatch, IEncounterable
|
|
||||||
{
|
|
||||||
return new EncounterEnumerator<T>(encounters, chain, pk);
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct EncounterEnumerator<T> : IEnumerator<MatchedEncounter<T>> where T : IEncounterMatch, IEncounterable
|
|
||||||
{
|
|
||||||
private readonly IReadOnlyList<T> _encounters;
|
|
||||||
private readonly EvoCriteria[] _chain;
|
|
||||||
private int _index = 0;
|
|
||||||
private readonly PKM _pk;
|
|
||||||
|
|
||||||
public EncounterEnumerator(IReadOnlyList<T> encounters, EvoCriteria[] chain, PKM pk)
|
|
||||||
{
|
|
||||||
_encounters = encounters;
|
|
||||||
_chain = chain;
|
|
||||||
_pk = pk;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MatchedEncounter<T> Current { get; private set; } = default!;
|
|
||||||
readonly object IEnumerator.Current => Current;
|
|
||||||
|
|
||||||
public bool MoveNext()
|
|
||||||
{
|
|
||||||
for (; _index < _encounters.Count;)
|
|
||||||
{
|
|
||||||
var enc = _encounters[_index++];
|
|
||||||
foreach (var evo in _chain)
|
|
||||||
{
|
|
||||||
if (enc.Species != evo.Species)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var exact = enc.IsMatchExact(_pk, evo);
|
|
||||||
if (!exact)
|
|
||||||
break;
|
|
||||||
|
|
||||||
Current = new(enc, enc.GetMatchRating(_pk));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reset() => _index = 0;
|
|
||||||
public readonly void Dispose() { }
|
|
||||||
public readonly IEnumerator<MatchedEncounter<T>> GetEnumerator() => this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -20,7 +20,14 @@ public interface IMagnetStatic
|
||||||
/// <summary> Count of slots in the parent area that can be yielded by <see cref="Ability.MagnetPull"/> </summary>
|
/// <summary> Count of slots in the parent area that can be yielded by <see cref="Ability.MagnetPull"/> </summary>
|
||||||
byte MagnetPullCount { get; }
|
byte MagnetPullCount { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates if the slot can be yielded by <see cref="Ability.Static"/>.
|
||||||
|
/// </summary>
|
||||||
bool IsStaticSlot => StaticCount != 0 && StaticIndex != byte.MaxValue;
|
bool IsStaticSlot => StaticCount != 0 && StaticIndex != byte.MaxValue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates if the slot can be yielded by <see cref="Ability.MagnetPull"/>.
|
||||||
|
/// </summary>
|
||||||
bool IsMagnetSlot => MagnetPullCount != 0 && MagnetPullIndex != byte.MaxValue;
|
bool IsMagnetSlot => MagnetPullCount != 0 && MagnetPullIndex != byte.MaxValue;
|
||||||
|
|
||||||
bool IsMatchStatic(int index, int count) => index == StaticIndex && count == StaticCount;
|
bool IsMatchStatic(int index, int count) => index == StaticIndex && count == StaticCount;
|
||||||
|
|
|
@ -12,7 +12,7 @@ public static class EggHatchLocation5
|
||||||
|
|
||||||
public static bool IsValidMet5(int location, GameVersion game)
|
public static bool IsValidMet5(int location, GameVersion game)
|
||||||
{
|
{
|
||||||
var shift = (uint)((int)game - (int)W);
|
var shift = (uint)(game - W);
|
||||||
if (shift >= 4)
|
if (shift >= 4)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,12 @@ public static class MoveBreed4
|
||||||
if (count == -1)
|
if (count == -1)
|
||||||
count = moves.Length;
|
count = moves.Length;
|
||||||
|
|
||||||
var learn = GameData.GetLearnSource(version);
|
var learnset = version switch
|
||||||
var learnset = learn.GetLearnset(species, 0);
|
{
|
||||||
|
HG or SS => LearnSource4HGSS.Instance.GetLearnset(species, 0),
|
||||||
|
D or P => LearnSource4DP.Instance.GetLearnset(species, 0),
|
||||||
|
_ => LearnSource4Pt.Instance.GetLearnset(species, 0),
|
||||||
|
};
|
||||||
var table = version switch
|
var table = version switch
|
||||||
{
|
{
|
||||||
HG or SS => PersonalTable.HGSS,
|
HG or SS => PersonalTable.HGSS,
|
||||||
|
|
|
@ -22,8 +22,11 @@ public static class MoveBreed5
|
||||||
if (count == -1)
|
if (count == -1)
|
||||||
count = moves.Length;
|
count = moves.Length;
|
||||||
|
|
||||||
var learn = GameData.GetLearnSource(version);
|
var learnset = version switch
|
||||||
var learnset = learn.GetLearnset(species, 0);
|
{
|
||||||
|
GameVersion.B or GameVersion.W => LearnSource5BW.Instance.GetLearnset(species, 0),
|
||||||
|
_ => LearnSource5B2W2.Instance.GetLearnset(species, 0),
|
||||||
|
};
|
||||||
IPersonalInfoTM pi = version switch
|
IPersonalInfoTM pi = version switch
|
||||||
{
|
{
|
||||||
GameVersion.B or GameVersion.W => PersonalTable.BW[species],
|
GameVersion.B or GameVersion.W => PersonalTable.BW[species],
|
||||||
|
|
|
@ -9,6 +9,16 @@ public static class Tera9RNG
|
||||||
{
|
{
|
||||||
private const uint TeraTypeCount = 18;
|
private const uint TeraTypeCount = 18;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the <see cref="ITeraType.TeraTypeOriginal"/> matches the specification of the <see cref="gem"/> value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="seed">Seed used to generate the Tera Type</param>
|
||||||
|
/// <param name="gem">Encounter specified Gem Type</param>
|
||||||
|
/// <param name="species">Encounter Species</param>
|
||||||
|
/// <param name="form">Encounter Form</param>
|
||||||
|
/// <param name="original">Original Tera Type from the Entity</param>
|
||||||
|
/// <returns>True if the Tera Type matches the RNG and specification</returns>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
||||||
public static bool IsMatchTeraType(in uint seed, in GemType gem, in ushort species, in byte form, in byte original)
|
public static bool IsMatchTeraType(in uint seed, in GemType gem, in ushort species, in byte form, in byte original)
|
||||||
{
|
{
|
||||||
if (gem.IsSpecified(out var type))
|
if (gem.IsSpecified(out var type))
|
||||||
|
@ -43,6 +53,14 @@ public static class Tera9RNG
|
||||||
throw new ArgumentOutOfRangeException(nameof(gem), gem, null);
|
throw new ArgumentOutOfRangeException(nameof(gem), gem, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the expected Tera Type from the Personal Info and RNG seed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="seed">Seed used to generate the Tera Type</param>
|
||||||
|
/// <param name="gem">Encounter specified Gem Type</param>
|
||||||
|
/// <param name="species">Encounter Species</param>
|
||||||
|
/// <param name="form">Encounter Form</param>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException"></exception>
|
||||||
public static byte GetTeraType(in ulong seed, GemType gem, in ushort species, in byte form)
|
public static byte GetTeraType(in ulong seed, GemType gem, in ushort species, in byte form)
|
||||||
{
|
{
|
||||||
if (gem.IsSpecified(out var type))
|
if (gem.IsSpecified(out var type))
|
||||||
|
@ -61,6 +79,9 @@ public static class Tera9RNG
|
||||||
throw new ArgumentOutOfRangeException(nameof(gem), gem, null);
|
throw new ArgumentOutOfRangeException(nameof(gem), gem, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the original Tera Type matches either of the Personal Info types.
|
||||||
|
/// </summary>
|
||||||
private static bool IsMatchType(IPersonalType pi, in byte original) => original == pi.Type1 || original == pi.Type2;
|
private static bool IsMatchType(IPersonalType pi, in byte original) => original == pi.Type1 || original == pi.Type2;
|
||||||
|
|
||||||
public static bool IsMatchTeraTypePersonalEgg(in ushort species, in byte form, in byte original) =>
|
public static bool IsMatchTeraTypePersonalEgg(in ushort species, in byte form, in byte original) =>
|
||||||
|
@ -68,7 +89,16 @@ public static class Tera9RNG
|
||||||
? IsMatchTeraTypePersonalAnyForm(species, original)
|
? IsMatchTeraTypePersonalAnyForm(species, original)
|
||||||
: IsMatchTeraTypePersonal(species, form, original);
|
: IsMatchTeraTypePersonal(species, form, original);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IsMatchType"/>
|
||||||
public static bool IsMatchTeraTypePersonal(in ushort species, in byte form, in byte original) => IsMatchType(PersonalTable.SV[species, form], original);
|
public static bool IsMatchTeraTypePersonal(in ushort species, in byte form, in byte original) => IsMatchType(PersonalTable.SV[species, form], original);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the original Tera Type matches any of the Personal Info types for any form it may change into.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Only enter this method if it is permitted to change into all forms.</remarks>
|
||||||
|
/// <param name="species">Encounter Species</param>
|
||||||
|
/// <param name="original">Entity's original Tera Type</param>
|
||||||
|
/// <returns>True if the Tera Type matches any of the Personal Info types</returns>
|
||||||
public static bool IsMatchTeraTypePersonalAnyForm(in ushort species, in byte original)
|
public static bool IsMatchTeraTypePersonalAnyForm(in ushort species, in byte original)
|
||||||
{
|
{
|
||||||
var pt = PersonalTable.SV;
|
var pt = PersonalTable.SV;
|
||||||
|
@ -85,18 +115,27 @@ public static class Tera9RNG
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the original Tera Type matches the Personal Info type for the specified form.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Used for HOME imports into <see cref="GameVersion.SV"/>.</remarks>
|
||||||
|
/// <param name="pi">Arrival Personal Info</param>
|
||||||
|
/// <param name="original">Entity's original Tera Type</param>
|
||||||
|
/// <returns>True if the Tera Type matches the expected Personal Info type</returns>
|
||||||
private static bool IsMatchTeraTypeImport(PersonalInfo9SV pi, in byte original)
|
private static bool IsMatchTeraTypeImport(PersonalInfo9SV pi, in byte original)
|
||||||
{
|
{
|
||||||
var import = TeraTypeUtil.GetTeraTypeImport(pi.Type1, pi.Type2);
|
var import = TeraTypeUtil.GetTeraTypeImport(pi.Type1, pi.Type2);
|
||||||
return (MoveType)original == import;
|
return (MoveType)original == import;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IsMatchTeraTypeImport"/>
|
||||||
public static bool IsMatchTeraTypePersonalImport(in ushort species, in byte form, in byte original)
|
public static bool IsMatchTeraTypePersonalImport(in ushort species, in byte form, in byte original)
|
||||||
{
|
{
|
||||||
var pi = PersonalTable.SV[species, form];
|
var pi = PersonalTable.SV[species, form];
|
||||||
return IsMatchTeraTypeImport(pi, original);
|
return IsMatchTeraTypeImport(pi, original);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IsMatchTeraTypeImport"/>
|
||||||
public static bool IsMatchTeraTypePersonalAnyFormImport(in ushort species, in byte original)
|
public static bool IsMatchTeraTypePersonalAnyFormImport(in ushort species, in byte original)
|
||||||
{
|
{
|
||||||
var pt = PersonalTable.SV;
|
var pt = PersonalTable.SV;
|
||||||
|
@ -113,12 +152,29 @@ public static class Tera9RNG
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the expected Tera Type from the Personal Info and pivot.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="species">Encounter Species</param>
|
||||||
|
/// <param name="form">Encounter Form</param>
|
||||||
|
/// <param name="pivot">Random pivot to determine which Personal Info type to use</param>
|
||||||
|
/// <returns>Expected Tera Type</returns>
|
||||||
public static byte GetTeraTypeFromPersonal(in ushort species, in byte form, in ulong pivot)
|
public static byte GetTeraTypeFromPersonal(in ushort species, in byte form, in ulong pivot)
|
||||||
{
|
{
|
||||||
var pi = PersonalTable.SV[species, form];
|
var pi = PersonalTable.SV[species, form];
|
||||||
return pivot == 0 ? pi.Type1 : pi.Type2;
|
return pivot == 0 ? pi.Type1 : pi.Type2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares the Raid Seed to the possible raid bounds to see if the encounter can originate from that seed.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>A given raid seed might yield a different encounter or star count, hence why we need to check.</remarks>
|
||||||
|
/// <param name="seed">Random seed used to generate the raid.</param>
|
||||||
|
/// <param name="stars">Difficulty rating.</param>
|
||||||
|
/// <param name="raidRate">Random weight of the raid to be used in the comparison with the game specific min rates.</param>
|
||||||
|
/// <param name="randRateMinScarlet">Total weight of all Scarlet raids prior to this encounter.</param>
|
||||||
|
/// <param name="randRateMinViolet">Total weight of all Violet raids prior to this encounter.</param>
|
||||||
|
/// <returns>True if the raid seed can generate the encounter.</returns>
|
||||||
public static bool IsMatchStarChoice(in uint seed, in byte stars, in byte raidRate, in short randRateMinScarlet, in short randRateMinViolet)
|
public static bool IsMatchStarChoice(in uint seed, in byte stars, in byte raidRate, in short randRateMinScarlet, in short randRateMinViolet)
|
||||||
{
|
{
|
||||||
// When determining a raid, the game takes the u32 seed and does two rand calls.
|
// When determining a raid, the game takes the u32 seed and does two rand calls.
|
||||||
|
|
|
@ -77,13 +77,14 @@ public sealed class LegalInfo : IGeneration
|
||||||
StoreMetadata(pk.Generation);
|
StoreMetadata(pk.Generation);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void StoreMetadata(int gen)
|
/// <summary>
|
||||||
|
/// We can call this method at the start for any Gen3+ encounter iteration.
|
||||||
|
/// Additionally, We need to call this for each Gen1/2 encounter as Version is not stored for those origins.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="generation">Encounter generation</param>
|
||||||
|
internal void StoreMetadata(int generation) => Generation = generation switch
|
||||||
{
|
{
|
||||||
// We can call this method at the start for any Gen3+ encounter iteration.
|
-1 when Entity is PK9 { IsUnhatchedEgg: true } => 9,
|
||||||
// We need to call this for each Gen1/2 encounter as Version is not stored for those origins.
|
_ => generation,
|
||||||
Generation = gen;
|
};
|
||||||
|
|
||||||
if (gen == -1 && Entity is PK9 { IsUnhatchedEgg: true })
|
|
||||||
Generation = 9;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,7 +185,7 @@ public sealed class PGF : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I
|
||||||
|
|
||||||
var rnd = Util.Rand;
|
var rnd = Util.Rand;
|
||||||
|
|
||||||
var dt = DateTime.Now;
|
var dt = EncounterDate.GetDateNDS();
|
||||||
if (Day == 0)
|
if (Day == 0)
|
||||||
{
|
{
|
||||||
Day = (byte)dt.Day;
|
Day = (byte)dt.Day;
|
||||||
|
@ -202,7 +202,7 @@ public sealed class PGF : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I
|
||||||
Met_Level = currentLevel,
|
Met_Level = currentLevel,
|
||||||
Nature = Nature != -1 ? Nature : rnd.Next(25),
|
Nature = Nature != -1 ? Nature : rnd.Next(25),
|
||||||
Form = Form,
|
Form = Form,
|
||||||
Version = OriginGame == 0 ? tr.Game : OriginGame,
|
Version = GetVersion(tr, rnd),
|
||||||
Language = Language == 0 ? tr.Language : Language,
|
Language = Language == 0 ? tr.Language : Language,
|
||||||
Ball = Ball,
|
Ball = Ball,
|
||||||
Move1 = Move1,
|
Move1 = Move1,
|
||||||
|
@ -241,8 +241,6 @@ public sealed class PGF : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I
|
||||||
|
|
||||||
FatefulEncounter = true,
|
FatefulEncounter = true,
|
||||||
};
|
};
|
||||||
if (tr.Generation > 5 && OriginGame == 0) // Gen6+, give random gen5 game
|
|
||||||
pk.Version = (int)GameVersion.W + rnd.Next(4);
|
|
||||||
|
|
||||||
if (Move1 == 0) // No moves defined
|
if (Move1 == 0) // No moves defined
|
||||||
{
|
{
|
||||||
|
@ -285,6 +283,23 @@ public sealed class PGF : DataMysteryGift, IRibbonSetEvent3, IRibbonSetEvent4, I
|
||||||
return pk;
|
return pk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int GetVersion(ITrainerInfo tr, Random rnd)
|
||||||
|
{
|
||||||
|
if (OriginGame != 0)
|
||||||
|
return OriginGame;
|
||||||
|
if (tr.Generation <= 5)
|
||||||
|
return tr.Game;
|
||||||
|
// Gen6+, give random gen5 game
|
||||||
|
var bias = rnd.Next(4);
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
var ver = (int)GameVersion.W + ((bias + i) % 4);
|
||||||
|
if (CanBeReceivedByVersion(ver))
|
||||||
|
return ver;
|
||||||
|
}
|
||||||
|
return (int)GameVersion.W; // should never hit this for any distributed card
|
||||||
|
}
|
||||||
|
|
||||||
private void SetEggMetDetails(PK5 pk)
|
private void SetEggMetDetails(PK5 pk)
|
||||||
{
|
{
|
||||||
pk.IsEgg = true;
|
pk.IsEgg = true;
|
||||||
|
|
|
@ -17,7 +17,7 @@ public sealed class WC6Full
|
||||||
Data = data;
|
Data = data;
|
||||||
var wc6 = data.AsSpan(GiftStart).ToArray();
|
var wc6 = data.AsSpan(GiftStart).ToArray();
|
||||||
Gift = new WC6(wc6);
|
Gift = new WC6(wc6);
|
||||||
var now = DateTime.Now;
|
var now = EncounterDate.GetDate3DS();
|
||||||
Gift.RawDate = WC6.SetDate((uint)now.Year, (uint)now.Month, (uint)now.Day);
|
Gift.RawDate = WC6.SetDate((uint)now.Year, (uint)now.Month, (uint)now.Day);
|
||||||
|
|
||||||
Gift.RestrictVersion = RestrictVersion;
|
Gift.RestrictVersion = RestrictVersion;
|
||||||
|
@ -30,7 +30,7 @@ public sealed class WC6Full
|
||||||
var countgift = data.Length / WC6.Size;
|
var countgift = data.Length / WC6.Size;
|
||||||
var result = new WC6[countfull + countgift];
|
var result = new WC6[countfull + countgift];
|
||||||
|
|
||||||
var now = DateTime.Now;
|
var now = EncounterDate.GetDate3DS();
|
||||||
for (int i = 0; i < countfull; i++)
|
for (int i = 0; i < countfull; i++)
|
||||||
result[i] = ReadWC6(WC6Full, i * Size, now);
|
result[i] = ReadWC6(WC6Full, i * Size, now);
|
||||||
for (int i = 0; i < countgift; i++)
|
for (int i = 0; i < countgift; i++)
|
||||||
|
@ -39,7 +39,7 @@ public sealed class WC6Full
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static WC6 ReadWC6(ReadOnlySpan<byte> data, int ofs, DateTime date)
|
private static WC6 ReadWC6(ReadOnlySpan<byte> data, int ofs, DateOnly date)
|
||||||
{
|
{
|
||||||
var slice = data.Slice(ofs + GiftStart, WC6.Size).ToArray();
|
var slice = data.Slice(ofs + GiftStart, WC6.Size).ToArray();
|
||||||
return new WC6(slice)
|
return new WC6(slice)
|
||||||
|
|
|
@ -17,7 +17,7 @@ public sealed class WC7Full
|
||||||
Data = data;
|
Data = data;
|
||||||
var wc7 = data.AsSpan(GiftStart).ToArray();
|
var wc7 = data.AsSpan(GiftStart).ToArray();
|
||||||
Gift = new WC7(wc7);
|
Gift = new WC7(wc7);
|
||||||
var now = DateTime.Now;
|
var now = EncounterDate.GetDate3DS();
|
||||||
Gift.RawDate = WC7.SetDate((uint)now.Year, (uint)now.Month, (uint)now.Day);
|
Gift.RawDate = WC7.SetDate((uint)now.Year, (uint)now.Month, (uint)now.Day);
|
||||||
|
|
||||||
Gift.RestrictVersion = RestrictVersion;
|
Gift.RestrictVersion = RestrictVersion;
|
||||||
|
@ -30,7 +30,7 @@ public sealed class WC7Full
|
||||||
var countgift = data.Length / WC7.Size;
|
var countgift = data.Length / WC7.Size;
|
||||||
var result = new WC7[countfull + countgift];
|
var result = new WC7[countfull + countgift];
|
||||||
|
|
||||||
var now = DateTime.Now;
|
var now = EncounterDate.GetDate3DS();
|
||||||
for (int i = 0; i < countfull; i++)
|
for (int i = 0; i < countfull; i++)
|
||||||
result[i] = ReadWC7(wc7Full, i * Size, now);
|
result[i] = ReadWC7(wc7Full, i * Size, now);
|
||||||
for (int i = 0; i < countgift; i++)
|
for (int i = 0; i < countgift; i++)
|
||||||
|
@ -39,7 +39,7 @@ public sealed class WC7Full
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static WC7 ReadWC7(ReadOnlySpan<byte> data, int ofs, DateTime date)
|
private static WC7 ReadWC7(ReadOnlySpan<byte> data, int ofs, DateOnly date)
|
||||||
{
|
{
|
||||||
var slice = data.Slice(ofs + GiftStart, WC7.Size).ToArray();
|
var slice = data.Slice(ofs + GiftStart, WC7.Size).ToArray();
|
||||||
return new WC7(slice)
|
return new WC7(slice)
|
||||||
|
|
|
@ -7,12 +7,22 @@ namespace PKHeX.Core;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ITrainerID32 : ITrainerID16
|
public interface ITrainerID32 : ITrainerID16
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 32-bit Trainer ID (0-4294967295)
|
||||||
|
/// </summary>
|
||||||
uint ID32 { get; set; }
|
uint ID32 { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 16-bit Secret ID (0-65535)
|
||||||
|
/// </summary>
|
||||||
ushort SID16 { get; set; }
|
ushort SID16 { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ITrainerID16 : ITrainerID
|
public interface ITrainerID16 : ITrainerID
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 16-bit Trainer ID (0-65535)
|
||||||
|
/// </summary>
|
||||||
ushort TID16 { get; set; }
|
ushort TID16 { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,10 +38,13 @@ public static class ITrainerID32Extensions
|
||||||
public static bool IsShiny(this ITrainerID32 tr, uint pid, int gen = 7)
|
public static bool IsShiny(this ITrainerID32 tr, uint pid, int gen = 7)
|
||||||
{
|
{
|
||||||
var xor = GetShinyXor(tr, pid);
|
var xor = GetShinyXor(tr, pid);
|
||||||
var threshold = (gen >= 7 ? 16 : 8);
|
var threshold = (gen >= 7 ? ShinyXorThreshold7 : ShinyXorThreshold36);
|
||||||
return xor < threshold;
|
return xor < threshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private const int ShinyXorThreshold36 = 8; // 1:8192
|
||||||
|
private const int ShinyXorThreshold7 = 16; // 1:4096
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates the <see cref="pid"/> and <see cref="ITrainerID32.ID32"/> xor.
|
/// Calculates the <see cref="pid"/> and <see cref="ITrainerID32.ID32"/> xor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -455,7 +455,7 @@ public abstract class PKM : ISpeciesForm, ITrainerID32, IGeneration, IShiny, ILa
|
||||||
Move2 = value.Move2;
|
Move2 = value.Move2;
|
||||||
Move3 = value.Move3;
|
Move3 = value.Move3;
|
||||||
Move4 = value.Move4;
|
Move4 = value.Move4;
|
||||||
this.SetMaximumPPCurrent(Moves);
|
this.SetMaximumPPCurrent(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetMoves(ReadOnlySpan<ushort> value)
|
public void SetMoves(ReadOnlySpan<ushort> value)
|
||||||
|
@ -464,7 +464,7 @@ public abstract class PKM : ISpeciesForm, ITrainerID32, IGeneration, IShiny, ILa
|
||||||
Move2 = value.Length > 1 ? value[1] : default;
|
Move2 = value.Length > 1 ? value[1] : default;
|
||||||
Move3 = value.Length > 2 ? value[2] : default;
|
Move3 = value.Length > 2 ? value[2] : default;
|
||||||
Move4 = value.Length > 3 ? value[3] : default;
|
Move4 = value.Length > 3 ? value[3] : default;
|
||||||
this.SetMaximumPPCurrent(Moves);
|
this.SetMaximumPPCurrent(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ushort[] RelearnMoves
|
public ushort[] RelearnMoves
|
||||||
|
|
|
@ -275,8 +275,8 @@ public abstract class SAV4 : SaveFile, IEventFlag37
|
||||||
{
|
{
|
||||||
var pk4 = (PK4)pk;
|
var pk4 = (PK4)pk;
|
||||||
// Apply to this Save File
|
// Apply to this Save File
|
||||||
DateTime Date = DateTime.Now;
|
var now = EncounterDate.GetDateNDS();
|
||||||
if (pk4.Trade(OT, ID32, Gender, Date.Day, Date.Month, Date.Year))
|
if (pk4.Trade(OT, ID32, Gender, now.Day, now.Month, now.Year))
|
||||||
pk.RefreshChecksum();
|
pk.RefreshChecksum();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -244,8 +244,8 @@ public sealed class SAV4BR : SaveFile
|
||||||
{
|
{
|
||||||
var pk4 = (BK4)pk;
|
var pk4 = (BK4)pk;
|
||||||
// Apply to this Save File
|
// Apply to this Save File
|
||||||
DateTime Date = DateTime.Now;
|
var now = EncounterDate.GetDateNDS();
|
||||||
if (pk4.Trade(OT, ID32, Gender, Date.Day, Date.Month, Date.Year))
|
if (pk4.Trade(OT, ID32, Gender, now.Day, now.Month, now.Year))
|
||||||
pk.RefreshChecksum();
|
pk.RefreshChecksum();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -115,8 +115,8 @@ public abstract class SAV5 : SaveFile, ISaveBlock5BW, IEventFlag37
|
||||||
{
|
{
|
||||||
var pk5 = (PK5)pk;
|
var pk5 = (PK5)pk;
|
||||||
// Apply to this Save File
|
// Apply to this Save File
|
||||||
DateTime Date = DateTime.Now;
|
var now = EncounterDate.GetDateNDS();
|
||||||
if (pk5.Trade(OT, ID32, Gender, Date.Day, Date.Month, Date.Year))
|
if (pk5.Trade(OT, ID32, Gender, now.Day, now.Month, now.Year))
|
||||||
pk.RefreshChecksum();
|
pk.RefreshChecksum();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -111,8 +111,8 @@ public abstract class SAV6 : SAV_BEEF, ITrainerStatRecord, ISaveBlock6Core, IReg
|
||||||
PK6 pk6 = (PK6)pk;
|
PK6 pk6 = (PK6)pk;
|
||||||
// Apply to this Save File
|
// Apply to this Save File
|
||||||
int CT = pk6.CurrentHandler;
|
int CT = pk6.CurrentHandler;
|
||||||
DateTime Date = DateTime.Now;
|
var now = EncounterDate.GetDate3DS();
|
||||||
pk6.Trade(this, Date.Day, Date.Month, Date.Year);
|
pk6.Trade(this, now.Day, now.Month, now.Year);
|
||||||
if (CT != pk6.CurrentHandler) // Logic updated Friendship
|
if (CT != pk6.CurrentHandler) // Logic updated Friendship
|
||||||
{
|
{
|
||||||
// Copy over the Friendship Value only under certain circumstances
|
// Copy over the Friendship Value only under certain circumstances
|
||||||
|
|
|
@ -175,8 +175,8 @@ public abstract class SAV7 : SAV_BEEF, ITrainerStatRecord, ISaveBlock7Main, IReg
|
||||||
PK7 pk7 = (PK7)pk;
|
PK7 pk7 = (PK7)pk;
|
||||||
// Apply to this Save File
|
// Apply to this Save File
|
||||||
int CT = pk7.CurrentHandler;
|
int CT = pk7.CurrentHandler;
|
||||||
DateTime Date = DateTime.Now;
|
var now = EncounterDate.GetDate3DS();
|
||||||
pk7.Trade(this, Date.Day, Date.Month, Date.Year);
|
pk7.Trade(this, now.Day, now.Month, now.Year);
|
||||||
if (CT != pk7.CurrentHandler) // Logic updated Friendship
|
if (CT != pk7.CurrentHandler) // Logic updated Friendship
|
||||||
{
|
{
|
||||||
// Copy over the Friendship Value only under certain circumstances
|
// Copy over the Friendship Value only under certain circumstances
|
||||||
|
|
|
@ -93,8 +93,8 @@ public sealed class SAV7b : SAV_BEEF, ISaveBlock7b, IGameSync, IEventFlagArray
|
||||||
{
|
{
|
||||||
var pb7 = (PB7)pk;
|
var pb7 = (PB7)pk;
|
||||||
// Apply to this Save File
|
// Apply to this Save File
|
||||||
var Date = DateTime.Now;
|
var now = EncounterDate.GetDateSwitch();
|
||||||
pb7.Trade(this, Date.Day, Date.Month, Date.Year);
|
pb7.Trade(this, now.Day, now.Month, now.Year);
|
||||||
pb7.RefreshChecksum();
|
pb7.RefreshChecksum();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -309,8 +309,8 @@ public sealed class SAV8BS : SaveFile, ISaveFileRevision, ITrainerStatRecord, IE
|
||||||
{
|
{
|
||||||
var pb8 = (PB8)pk;
|
var pb8 = (PB8)pk;
|
||||||
// Apply to this Save File
|
// Apply to this Save File
|
||||||
DateTime Date = DateTime.Now;
|
var now = EncounterDate.GetDateSwitch();
|
||||||
pb8.Trade(this, Date.Day, Date.Month, Date.Year);
|
pb8.Trade(this, now.Day, now.Month, now.Year);
|
||||||
|
|
||||||
pb8.RefreshChecksum();
|
pb8.RefreshChecksum();
|
||||||
AddCountAcquired(pb8);
|
AddCountAcquired(pb8);
|
||||||
|
|
|
@ -195,8 +195,8 @@ public sealed class SAV8SWSH : SaveFile, ISaveBlock8SWSH, ITrainerStatRecord, IS
|
||||||
{
|
{
|
||||||
PK8 pk8 = (PK8)pk;
|
PK8 pk8 = (PK8)pk;
|
||||||
// Apply to this Save File
|
// Apply to this Save File
|
||||||
DateTime Date = DateTime.Now;
|
var now = EncounterDate.GetDateSwitch();
|
||||||
pk8.Trade(this, Date.Day, Date.Month, Date.Year);
|
pk8.Trade(this, now.Day, now.Month, now.Year);
|
||||||
|
|
||||||
if (FormArgumentUtil.IsFormArgumentTypeDatePair(pk8.Species, pk8.Form))
|
if (FormArgumentUtil.IsFormArgumentTypeDatePair(pk8.Species, pk8.Form))
|
||||||
{
|
{
|
||||||
|
|
|
@ -164,8 +164,8 @@ public sealed class SAV9SV : SaveFile, ISaveBlock9Main, ISCBlockArray, ISaveFile
|
||||||
{
|
{
|
||||||
PK9 pk9 = (PK9)pk;
|
PK9 pk9 = (PK9)pk;
|
||||||
// Apply to this Save File
|
// Apply to this Save File
|
||||||
DateTime Date = DateTime.Now;
|
var now = EncounterDate.GetDateSwitch();
|
||||||
pk9.Trade(this, Date.Day, Date.Month, Date.Year);
|
pk9.Trade(this, now.Day, now.Month, now.Year);
|
||||||
|
|
||||||
if (FormArgumentUtil.IsFormArgumentTypeDatePair(pk9.Species, pk9.Form))
|
if (FormArgumentUtil.IsFormArgumentTypeDatePair(pk9.Species, pk9.Form))
|
||||||
{
|
{
|
||||||
|
|
|
@ -63,12 +63,12 @@ public sealed class Roamer3 : IContestStats
|
||||||
public bool Active { get => Data[Offset + 0x13] == 1; set => Data[Offset + 0x13] = value ? (byte)1 : (byte)0; }
|
public bool Active { get => Data[Offset + 0x13] == 1; set => Data[Offset + 0x13] = value ? (byte)1 : (byte)0; }
|
||||||
|
|
||||||
// Derived Properties
|
// Derived Properties
|
||||||
private int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 00)) | (uint)((value > 31 ? 31 : value) << 00)); }
|
private int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | (uint)((value > 31 ? 31 : value) << 00); }
|
||||||
private int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 05)) | (uint)((value > 31 ? 31 : value) << 05)); }
|
private int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | (uint)((value > 31 ? 31 : value) << 05); }
|
||||||
private int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 10)) | (uint)((value > 31 ? 31 : value) << 10)); }
|
private int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | (uint)((value > 31 ? 31 : value) << 10); }
|
||||||
private int IV_SPE { get => (int)(IV32 >> 15) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 15)) | (uint)((value > 31 ? 31 : value) << 15)); }
|
private int IV_SPE { get => (int)(IV32 >> 15) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 15)) | (uint)((value > 31 ? 31 : value) << 15); }
|
||||||
private int IV_SPA { get => (int)(IV32 >> 20) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 20)) | (uint)((value > 31 ? 31 : value) << 20)); }
|
private int IV_SPA { get => (int)(IV32 >> 20) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 20)) | (uint)((value > 31 ? 31 : value) << 20); }
|
||||||
private int IV_SPD { get => (int)(IV32 >> 25) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 25)) | (uint)((value > 31 ? 31 : value) << 25)); }
|
private int IV_SPD { get => (int)(IV32 >> 25) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 25)) | (uint)((value > 31 ? 31 : value) << 25); }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Roamer's IVs.
|
/// Roamer's IVs.
|
||||||
|
|
|
@ -28,12 +28,12 @@ public sealed class Roamer4
|
||||||
// 0x13 alignment, unused
|
// 0x13 alignment, unused
|
||||||
|
|
||||||
// Derived Properties
|
// Derived Properties
|
||||||
private int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 00)) | (uint)((value > 31 ? 31 : value) << 00)); }
|
private int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | (uint)((value > 31 ? 31 : value) << 00); }
|
||||||
private int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 05)) | (uint)((value > 31 ? 31 : value) << 05)); }
|
private int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | (uint)((value > 31 ? 31 : value) << 05); }
|
||||||
private int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 10)) | (uint)((value > 31 ? 31 : value) << 10)); }
|
private int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | (uint)((value > 31 ? 31 : value) << 10); }
|
||||||
private int IV_SPE { get => (int)(IV32 >> 15) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 15)) | (uint)((value > 31 ? 31 : value) << 15)); }
|
private int IV_SPE { get => (int)(IV32 >> 15) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 15)) | (uint)((value > 31 ? 31 : value) << 15); }
|
||||||
private int IV_SPA { get => (int)(IV32 >> 20) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 20)) | (uint)((value > 31 ? 31 : value) << 20)); }
|
private int IV_SPA { get => (int)(IV32 >> 20) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 20)) | (uint)((value > 31 ? 31 : value) << 20); }
|
||||||
private int IV_SPD { get => (int)(IV32 >> 25) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 25)) | (uint)((value > 31 ? 31 : value) << 25)); }
|
private int IV_SPD { get => (int)(IV32 >> 25) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 25)) | (uint)((value > 31 ? 31 : value) << 25); }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Roamer's IVs.
|
/// Roamer's IVs.
|
||||||
|
|
|
@ -39,7 +39,7 @@ public sealed class Daycare5 : SaveBlock<SAV5>
|
||||||
private int GetDaycareEXPOffset(int slot) => GetDaycareSlotOffset(slot) + 4 + PokeCrypto.SIZE_5PARTY;
|
private int GetDaycareEXPOffset(int slot) => GetDaycareSlotOffset(slot) + 4 + PokeCrypto.SIZE_5PARTY;
|
||||||
|
|
||||||
public bool? IsOccupied(int slot) => ReadUInt32LittleEndian(Data.AsSpan(GetDaycareSlotOffset(slot))) == 1;
|
public bool? IsOccupied(int slot) => ReadUInt32LittleEndian(Data.AsSpan(GetDaycareSlotOffset(slot))) == 1;
|
||||||
public void SetOccupied(int slot, bool occupied) => WriteUInt32LittleEndian(Data.AsSpan(GetDaycareSlotOffset(slot)), (uint)(occupied ? 1 : 0));
|
public void SetOccupied(int slot, bool occupied) => WriteUInt32LittleEndian(Data.AsSpan(GetDaycareSlotOffset(slot)), occupied ? 1u : 0);
|
||||||
|
|
||||||
public uint? GetEXP(int slot) => ReadUInt32LittleEndian(Data.AsSpan(GetDaycareEXPOffset(slot)));
|
public uint? GetEXP(int slot) => ReadUInt32LittleEndian(Data.AsSpan(GetDaycareEXPOffset(slot)));
|
||||||
public void SetEXP(int slot, uint EXP) => WriteUInt32LittleEndian(Data.AsSpan(GetDaycareEXPOffset(slot)), EXP);
|
public void SetEXP(int slot, uint EXP) => WriteUInt32LittleEndian(Data.AsSpan(GetDaycareEXPOffset(slot)), EXP);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using System;
|
using System;
|
||||||
using static System.Buffers.Binary.BinaryPrimitives;
|
using static System.Buffers.Binary.BinaryPrimitives;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
@ -50,7 +50,7 @@ public sealed class EntreeForest
|
||||||
{
|
{
|
||||||
var slots = new EntreeSlot[TotalSlots];
|
var slots = new EntreeSlot[TotalSlots];
|
||||||
for (int i = 0; i < slots.Length; i++)
|
for (int i = 0; i < slots.Length; i++)
|
||||||
slots[i] = new EntreeSlot(Data, i * 4) { Area = GetSlotArea(i) };
|
slots[i] = new EntreeSlot(Data.AsMemory(i * EntreeSlot.SIZE, EntreeSlot.SIZE)) { Area = GetSlotArea(i) };
|
||||||
return slots;
|
return slots;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,6 +116,6 @@ public sealed class EntreeForest
|
||||||
0 => EntreeForestArea.Center,
|
0 => EntreeForestArea.Center,
|
||||||
1 => EntreeForestArea.Left,
|
1 => EntreeForestArea.Left,
|
||||||
2 => EntreeForestArea.Right,
|
2 => EntreeForestArea.Right,
|
||||||
_ => throw new ArgumentOutOfRangeException(),
|
_ => throw new ArgumentOutOfRangeException(nameof(index)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ public sealed class EntreeSlot : ISpeciesForm
|
||||||
public ushort Species // bits 0-10
|
public ushort Species // bits 0-10
|
||||||
{
|
{
|
||||||
get => (ushort)((RawValue & 0x3FF) >> 0);
|
get => (ushort)((RawValue & 0x3FF) >> 0);
|
||||||
set => RawValue = (RawValue & 0xFFFF_F800) | ((uint)(value & 0x3FF) << 0);
|
set => RawValue = (RawValue & 0xFFFF_F800) | ((value & 0x3FFu) << 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -23,7 +23,7 @@ public sealed class EntreeSlot : ISpeciesForm
|
||||||
public ushort Move // bits 11-20
|
public ushort Move // bits 11-20
|
||||||
{
|
{
|
||||||
get => (ushort)((RawValue & 0x001F_F800) >> 11);
|
get => (ushort)((RawValue & 0x001F_F800) >> 11);
|
||||||
set => RawValue = (RawValue & 0xFFE0_07FF) | ((uint)(value & 0x3FF) << 11);
|
set => RawValue = (RawValue & 0xFFE0_07FF) | ((value & 0x3FFu) << 11);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -41,7 +41,7 @@ public sealed class EntreeSlot : ISpeciesForm
|
||||||
public byte Form // bits 23-27
|
public byte Form // bits 23-27
|
||||||
{
|
{
|
||||||
get => (byte)((RawValue & 0x0F80_0000) >> 23);
|
get => (byte)((RawValue & 0x0F80_0000) >> 23);
|
||||||
set => RawValue = (RawValue & 0xF07F_FFFF) | ((uint)(value & 0x1F) << 23);
|
set => RawValue = (RawValue & 0xF07F_FFFF) | ((value & 0x1Fu) << 23);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -62,25 +62,29 @@ public sealed class EntreeSlot : ISpeciesForm
|
||||||
set => RawValue = ((RawValue << 3) >> 3) | (uint)((value & 0x7) << 29);
|
set => RawValue = ((RawValue << 3) >> 3) | (uint)((value & 0x7) << 29);
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly byte[] Data;
|
private Memory<byte> Data { get; }
|
||||||
private readonly int Offset;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Raw Data Value
|
/// Raw Data Value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public uint RawValue
|
public uint RawValue
|
||||||
{
|
{
|
||||||
get => ReadUInt32LittleEndian(Data.AsSpan(Offset));
|
get => ReadUInt32LittleEndian(Data.Span);
|
||||||
set => WriteUInt32LittleEndian(Data.AsSpan(Offset), value);
|
set => WriteUInt32LittleEndian(Data.Span, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Resets the raw data value to 0.
|
||||||
|
/// </summary>
|
||||||
public void Delete() => RawValue = 0;
|
public void Delete() => RawValue = 0;
|
||||||
|
|
||||||
|
public const int SIZE = 4;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates which area the slot data originated from.
|
||||||
|
/// Extra metadata for the slot which is not stored in the raw data.
|
||||||
|
/// </summary>
|
||||||
public EntreeForestArea Area { get; init; }
|
public EntreeForestArea Area { get; init; }
|
||||||
|
|
||||||
public EntreeSlot(byte[] data, int ofs)
|
public EntreeSlot(Memory<byte> data) => Data = data;
|
||||||
{
|
|
||||||
Data = data;
|
|
||||||
Offset = ofs;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,12 +29,12 @@ public sealed class Roamer5
|
||||||
public byte Unk13 { get => Data[0x13]; set => Data[0x13] = value; } // likely just alignment
|
public byte Unk13 { get => Data[0x13]; set => Data[0x13] = value; } // likely just alignment
|
||||||
|
|
||||||
// Derived Properties
|
// Derived Properties
|
||||||
private int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 00)) | (uint)((value > 31 ? 31 : value) << 00)); }
|
private int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | (uint)((value > 31 ? 31 : value) << 00); }
|
||||||
private int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 05)) | (uint)((value > 31 ? 31 : value) << 05)); }
|
private int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | (uint)((value > 31 ? 31 : value) << 05); }
|
||||||
private int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 10)) | (uint)((value > 31 ? 31 : value) << 10)); }
|
private int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | (uint)((value > 31 ? 31 : value) << 10); }
|
||||||
private int IV_SPE { get => (int)(IV32 >> 15) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 15)) | (uint)((value > 31 ? 31 : value) << 15)); }
|
private int IV_SPE { get => (int)(IV32 >> 15) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 15)) | (uint)((value > 31 ? 31 : value) << 15); }
|
||||||
private int IV_SPA { get => (int)(IV32 >> 20) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 20)) | (uint)((value > 31 ? 31 : value) << 20)); }
|
private int IV_SPA { get => (int)(IV32 >> 20) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 20)) | (uint)((value > 31 ? 31 : value) << 20); }
|
||||||
private int IV_SPD { get => (int)(IV32 >> 25) & 0x1F; set => IV32 = (uint)((IV32 & ~(0x1F << 25)) | (uint)((value > 31 ? 31 : value) << 25)); }
|
private int IV_SPD { get => (int)(IV32 >> 25) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 25)) | (uint)((value > 31 ? 31 : value) << 25); }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Roamer's IVs.
|
/// Roamer's IVs.
|
||||||
|
|
|
@ -5,7 +5,7 @@ namespace PKHeX.Core;
|
||||||
|
|
||||||
public sealed class Puff6 : SaveBlock<SAV6>
|
public sealed class Puff6 : SaveBlock<SAV6>
|
||||||
{
|
{
|
||||||
private const int MaxPuffID = 26; // Supreme Winter Poké Puff
|
private const byte MaxPuffID = 26; // Supreme Winter Poké Puff
|
||||||
private const int PuffSlots = 100;
|
private const int PuffSlots = 100;
|
||||||
|
|
||||||
public Puff6(SAV6 SAV, int offset) : base(SAV) => Offset = offset;
|
public Puff6(SAV6 SAV, int offset) : base(SAV) => Offset = offset;
|
||||||
|
@ -21,37 +21,41 @@ public sealed class Puff6 : SaveBlock<SAV6>
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
Array.Clear(Data, Offset, PuffSlots);
|
var puffs = GetPuffs();
|
||||||
|
puffs.Clear();
|
||||||
// Set the first few default Puffs
|
// Set the first few default Puffs
|
||||||
Data[Offset + 0] = 1;
|
puffs[0] = 1;
|
||||||
Data[Offset + 1] = 2;
|
puffs[1] = 2;
|
||||||
Data[Offset + 2] = 3;
|
puffs[2] = 3;
|
||||||
Data[Offset + 3] = 4;
|
puffs[3] = 4;
|
||||||
Data[Offset + 4] = 5;
|
puffs[4] = 5;
|
||||||
PuffCount = 5;
|
PuffCount = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MaxCheat(bool special = false)
|
public void MaxCheat(bool special = false)
|
||||||
{
|
{
|
||||||
var rnd = Util.Rand;
|
var rnd = Util.Rand;
|
||||||
|
var puffs = GetPuffs();
|
||||||
if (special)
|
if (special)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < PuffSlots; i++)
|
foreach (ref var puff in puffs)
|
||||||
Data[Offset + i] = (byte)(21 + rnd.Next(2)); // Supreme Wish or Honor
|
puff = (byte)(21 + rnd.Next(2)); // Supreme Wish or Honor
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int i = 0; i < PuffSlots; i++)
|
int i = 0;
|
||||||
Data[Offset + i] = (byte)((i % MaxPuffID) + 1);
|
foreach (ref var puff in puffs)
|
||||||
rnd.Shuffle(Data.AsSpan(Offset, PuffSlots));
|
puff = (byte)((i++ % MaxPuffID) + 1);
|
||||||
|
rnd.Shuffle(puffs);
|
||||||
}
|
}
|
||||||
PuffCount = PuffSlots;
|
PuffCount = PuffSlots;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Sort(bool reverse = false)
|
public void Sort(bool reverse = false)
|
||||||
{
|
{
|
||||||
Array.Sort(Data, Offset, PuffCount);
|
var puffs = GetPuffs();
|
||||||
|
puffs.Sort();
|
||||||
if (reverse)
|
if (reverse)
|
||||||
Array.Reverse(Data, Offset, PuffCount);
|
puffs.Reverse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1121,16 +1121,19 @@ public sealed class PokedexSave8a
|
||||||
if (hash == 0xCBF29CE484222645)
|
if (hash == 0xCBF29CE484222645)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return (int)(uint)SaveFile.Accessor.GetBlockValue((uint)(hash & 0xFFFFFFFF));
|
return (int)(uint)SaveFile.Accessor.GetBlockValue(GetSaveBlockKey(hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static uint GetSaveBlockKey(ulong hash) => (uint)hash; // truncate to 32-bit
|
||||||
|
|
||||||
private int GetSpeciesQuestState(ulong hash)
|
private int GetSpeciesQuestState(ulong hash)
|
||||||
{
|
{
|
||||||
if (hash is 0xC0EA47549AB5F3D9 or 0xCBF29CE484222645)
|
if (hash is 0xC0EA47549AB5F3D9 or 0xCBF29CE484222645)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// These are single-byte blocks, but type is "object"...
|
// These are single-byte blocks, but type is "object"...
|
||||||
return SaveFile.Accessor.GetBlock((uint)(hash & 0xFFFFFFFF)).Data[0];
|
var key = GetSaveBlockKey(hash);
|
||||||
|
return SaveFile.Accessor.GetBlock(key).Data[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsAnyTaskTriggered(ushort species, PokedexResearchTaskType8a which, MoveType moveType, int move, PokedexTimeOfDay8a timeOfDay)
|
public static bool IsAnyTaskTriggered(ushort species, PokedexResearchTaskType8a which, MoveType moveType, int move, PokedexTimeOfDay8a timeOfDay)
|
||||||
|
|
|
@ -40,8 +40,8 @@ public sealed class PokedexSaveData
|
||||||
public bool IsPokedexCompleted(PokedexType8a which) => (GlobalData.Flags & (which < PokedexType8a.Count ? (1 << (int)which) : 1)) != 0;
|
public bool IsPokedexCompleted(PokedexType8a which) => (GlobalData.Flags & (which < PokedexType8a.Count ? (1 << (int)which) : 1)) != 0;
|
||||||
public bool IsPokedexPerfect(PokedexType8a which) => (GlobalData.Flags & ((which < PokedexType8a.Count ? (1 << (int)which) : 1) << 6)) != 0;
|
public bool IsPokedexPerfect(PokedexType8a which) => (GlobalData.Flags & ((which < PokedexType8a.Count ? (1 << (int)which) : 1) << 6)) != 0;
|
||||||
|
|
||||||
public void SetPokedexCompleted(PokedexType8a which) => GlobalData.Flags |= (uint)(which < PokedexType8a.Count ? (1 << (int)which) : 1);
|
public void SetPokedexCompleted(PokedexType8a which) => GlobalData.Flags |= which < PokedexType8a.Count ? (1u << (int)which) : 1;
|
||||||
public void SetPokedexPerfect(PokedexType8a which) => GlobalData.Flags |= (uint)((which < PokedexType8a.Count ? (1 << (int)which) : 1) << 6);
|
public void SetPokedexPerfect(PokedexType8a which) => GlobalData.Flags |= (which < PokedexType8a.Count ? (1u << (int)which) : 1) << 6;
|
||||||
|
|
||||||
public PokedexSaveResearchEntry GetResearchEntry(ushort species) => ResearchEntries[species];
|
public PokedexSaveResearchEntry GetResearchEntry(ushort species) => ResearchEntries[species];
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,9 @@ public sealed class Zukan4 : ZukanBase<SAV4>
|
||||||
const int brSize = 0x40;
|
const int brSize = 0x40;
|
||||||
if (species == (int)Species.Deoxys)
|
if (species == (int)Species.Deoxys)
|
||||||
{
|
{
|
||||||
uint val = (uint)(Data[0x4 + (1 * brSize) - 1] | (Data[0x4 + (2 * brSize) - 1] << 8));
|
var br1 = Data[0x4 + (1 * brSize) - 1];
|
||||||
|
var br2 = Data[0x4 + (2 * brSize) - 1];
|
||||||
|
uint val = (uint)(br1 | (br2 << 8));
|
||||||
return GetDexFormValues(val, 4, 4);
|
return GetDexFormValues(val, 4, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue