mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-10 06:34:19 +00:00
Update 21.11.19 - Brilliant Diamond & Shining Pearl (#3289)
Big thanks to @SciresM @sora10pls @Lusamine @architdate @ReignOfComputer for testing and contributing code / test cases. Can't add co-authors from the PR menu :( Builds will fail because azure pipelines not yet updated with net6.
This commit is contained in:
parent
5cff79f382
commit
723514e89c
242 changed files with 15669 additions and 763 deletions
|
@ -94,6 +94,20 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
if (enc is EncounterSlot8b { IsUnderground: true } ug)
|
||||
{
|
||||
var moves = legal.Info.Moves;
|
||||
for (int i = 0; i < moves.Length; i++)
|
||||
{
|
||||
if (!moves[i].ShouldBeInRelearnMoves())
|
||||
continue;
|
||||
|
||||
var move = legal.pkm.GetMove(i);
|
||||
if (ug.CanBeUndergroundMove(move))
|
||||
return new[] { move, 0, 0, 0 };
|
||||
}
|
||||
}
|
||||
|
||||
var encounter = EncounterSuggestion.GetSuggestedMetInfo(legal.pkm);
|
||||
if (encounter is IRelearn {Relearn: {Count: > 0} r})
|
||||
return r;
|
||||
|
|
|
@ -375,7 +375,7 @@ namespace PKHeX.Core
|
|||
{
|
||||
bool traded = origin == dest;
|
||||
var today = pk.MetDate = DateTime.Today;
|
||||
pk.Egg_Location = EncounterSuggestion.GetSuggestedEncounterEggLocationEgg(pk.Generation, traded);
|
||||
pk.Egg_Location = EncounterSuggestion.GetSuggestedEncounterEggLocationEgg(pk.Generation, origin, traded);
|
||||
pk.EggMetDate = today;
|
||||
}
|
||||
|
||||
|
|
|
@ -125,6 +125,131 @@ namespace PKHeX.Core
|
|||
};
|
||||
}
|
||||
|
||||
public sealed class EventLabelCollectionSystem
|
||||
{
|
||||
public readonly IReadOnlyList<NamedEventWork> Work;
|
||||
public readonly IReadOnlyList<NamedEventValue> Flag;
|
||||
public readonly IReadOnlyList<NamedEventValue> System;
|
||||
|
||||
public EventLabelCollectionSystem(string game, int maxFlag = int.MaxValue, int maxSystem = int.MaxValue, int maxValue = int.MaxValue)
|
||||
{
|
||||
var f = GameLanguage.GetStrings(game, GameInfo.CurrentLanguage, "flag");
|
||||
var s = GameLanguage.GetStrings(game, GameInfo.CurrentLanguage, "system");
|
||||
var c = GameLanguage.GetStrings(game, GameInfo.CurrentLanguage, "work");
|
||||
Flag = GetFlags(f, maxFlag);
|
||||
System = GetFlags(s, maxSystem);
|
||||
Work = GetValues(c, maxValue);
|
||||
}
|
||||
|
||||
private static List<NamedEventValue> GetFlags(IReadOnlyCollection<string> strings, int maxValue)
|
||||
{
|
||||
var result = new List<NamedEventValue>(strings.Count);
|
||||
var processed = new HashSet<int>();
|
||||
foreach (var s in strings)
|
||||
{
|
||||
var split = s.Split('\t');
|
||||
if (split.Length != 3)
|
||||
continue;
|
||||
|
||||
var index = TryParseHexDec(split[0]);
|
||||
if (index >= maxValue)
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
|
||||
if (processed.Contains(index))
|
||||
throw new ArgumentException("Already have an entry for this!", nameof(index));
|
||||
|
||||
var type = GetEventType(split[1]);
|
||||
var desc = split[2];
|
||||
|
||||
var item = new NamedEventValue(desc, index, type);
|
||||
result.Add(item);
|
||||
processed.Add(index);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static readonly NamedEventConst Custom = new("Custom", NamedEventConst.CustomMagicValue);
|
||||
private static readonly NamedEventConst[] Empty = { Custom };
|
||||
|
||||
private static IReadOnlyList<NamedEventWork> GetValues(IReadOnlyCollection<string> strings, int maxValue)
|
||||
{
|
||||
var result = new List<NamedEventWork>(strings.Count);
|
||||
var processed = new HashSet<int>();
|
||||
foreach (var s in strings)
|
||||
{
|
||||
var split = s.Split('\t');
|
||||
if (split.Length is not (3 or 4))
|
||||
continue;
|
||||
|
||||
var index = TryParseHexDecConst(split[0]);
|
||||
if (index >= maxValue)
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
|
||||
if (processed.Contains(index))
|
||||
throw new ArgumentException("Already have an entry for this!", nameof(index));
|
||||
|
||||
var type = GetEventType(split[1]);
|
||||
var desc = split[2];
|
||||
var predefined = split.Length is 3 ? Empty : GetPredefinedArray(split[3]);
|
||||
var item = new NamedEventWork(desc, index, type, predefined);
|
||||
result.Add(item);
|
||||
processed.Add(index);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static IReadOnlyList<NamedEventConst> GetPredefinedArray(string combined)
|
||||
{
|
||||
var result = new List<NamedEventConst> { Custom };
|
||||
var split = combined.Split(',');
|
||||
foreach (var entry in split)
|
||||
{
|
||||
var subsplit = entry.Split(':');
|
||||
var name = subsplit[1];
|
||||
var value = Convert.ToUInt16(subsplit[0]);
|
||||
result.Add(new NamedEventConst(name, value));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int TryParseHexDec(string flag)
|
||||
{
|
||||
if (!flag.StartsWith("0x"))
|
||||
return Convert.ToInt16(flag);
|
||||
flag = flag[2..];
|
||||
return Convert.ToInt16(flag, 16);
|
||||
}
|
||||
|
||||
private static int TryParseHexDecConst(string c)
|
||||
{
|
||||
if (!c.StartsWith("0x40"))
|
||||
return Convert.ToInt16(c);
|
||||
c = c[4..];
|
||||
return Convert.ToInt16(c, 16);
|
||||
}
|
||||
|
||||
private static NamedEventType GetEventType(string s) => s.Length == 0 ? 0 : GetEventType(s[0]);
|
||||
|
||||
private static NamedEventType GetEventType(char c) => c switch
|
||||
{
|
||||
'h' => NamedEventType.HiddenItem,
|
||||
'm' => NamedEventType.Misc,
|
||||
'f' => NamedEventType.FlyToggle,
|
||||
't' => NamedEventType.TrainerToggle,
|
||||
's' => NamedEventType.StoryProgress,
|
||||
|
||||
'a' => NamedEventType.Achievement,
|
||||
'+' => NamedEventType.Statistic,
|
||||
'*' => NamedEventType.UsefulFeature,
|
||||
'e' => NamedEventType.EncounterEvent,
|
||||
'g' => NamedEventType.GiftAvailable,
|
||||
'r' => NamedEventType.Rebattle,
|
||||
_ => NamedEventType.None,
|
||||
};
|
||||
}
|
||||
|
||||
public enum NamedEventType
|
||||
{
|
||||
None,
|
||||
|
|
|
@ -183,4 +183,113 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class EventWorkDiff8b : EventBlockDiff
|
||||
{
|
||||
public readonly List<int> WorkChanged = new();
|
||||
private SaveFile? S1;
|
||||
public readonly List<int> SetSystem = new();
|
||||
public readonly List<int> ClearedSystem = new();
|
||||
|
||||
public EventWorkDiff8b(string f1, string f2)
|
||||
{
|
||||
if (!SanityCheckFiles(f1, f2))
|
||||
return;
|
||||
var s1 = SaveUtil.GetVariantSAV(f1);
|
||||
var s2 = SaveUtil.GetVariantSAV(f2);
|
||||
if (s1 == null || s2 == null || s1.GetType() != s2.GetType())
|
||||
{
|
||||
Message = MsgSaveDifferentTypes;
|
||||
return;
|
||||
}
|
||||
Diff(s1, s2);
|
||||
}
|
||||
|
||||
public EventWorkDiff8b(SaveFile s1, SaveFile s2) => Diff(s1, s2);
|
||||
|
||||
protected override void Diff(SaveFile s1, SaveFile s2)
|
||||
{
|
||||
if (!SanityCheckSaveInfo(s1, s2))
|
||||
return;
|
||||
|
||||
EventWorkUtil.DiffSavesFlag(((SAV8BS)s1).Work, ((SAV8BS)s2).Work, SetFlags, ClearedFlags);
|
||||
EventWorkUtil.DiffSavesSystem(((SAV8BS)s1).Work, ((SAV8BS)s2).Work, SetSystem, ClearedSystem);
|
||||
EventWorkUtil.DiffSavesWork(((SAV8BS)s1).Work, ((SAV8BS)s2).Work, WorkChanged, WorkDiff);
|
||||
S1 = s1;
|
||||
}
|
||||
|
||||
public IReadOnlyList<string> Summarize()
|
||||
{
|
||||
if (S1 == null)
|
||||
return Array.Empty<string>();
|
||||
|
||||
var fOn = SetFlags.Select(z => new FlagSummary(z).ToString());
|
||||
var fOff = ClearedFlags.Select(z => new FlagSummary(z).ToString());
|
||||
|
||||
var sOn = SetSystem.Select(z => new FlagSummary(z).ToString());
|
||||
var sOff = ClearedSystem.Select(z => new FlagSummary(z).ToString());
|
||||
|
||||
var wt = WorkChanged.Select((z, i) => new WorkSummary(z, WorkDiff[i]).ToString());
|
||||
|
||||
var list = new List<string> { "Flags: ON", "=========" };
|
||||
list.AddRange(fOn);
|
||||
if (SetFlags.Count == 0)
|
||||
list.Add("None.");
|
||||
|
||||
list.Add("");
|
||||
list.Add("Flags: OFF");
|
||||
list.Add("==========");
|
||||
list.AddRange(fOff);
|
||||
if (ClearedFlags.Count == 0)
|
||||
list.Add("None.");
|
||||
|
||||
list.Add("System: ON");
|
||||
list.Add("=========");
|
||||
list.AddRange(sOn);
|
||||
if (SetFlags.Count == 0)
|
||||
list.Add("None.");
|
||||
|
||||
list.Add("");
|
||||
list.Add("System: OFF");
|
||||
list.Add("==========");
|
||||
list.AddRange(sOff);
|
||||
if (ClearedSystem.Count == 0)
|
||||
list.Add("None.");
|
||||
|
||||
list.Add("");
|
||||
list.Add("Work:");
|
||||
list.Add("=====");
|
||||
if (WorkChanged.Count == 0)
|
||||
list.Add("None.");
|
||||
list.AddRange(wt);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private readonly struct FlagSummary
|
||||
{
|
||||
private int Raw { get; }
|
||||
|
||||
public override string ToString() => $"{Raw:0000}\t{false}";
|
||||
|
||||
public FlagSummary(int rawIndex)
|
||||
{
|
||||
Raw = rawIndex;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly struct WorkSummary
|
||||
{
|
||||
private int Raw { get; }
|
||||
private string Text { get; }
|
||||
|
||||
public override string ToString() => $"{Raw:000}\t{Text}";
|
||||
|
||||
public WorkSummary(int rawIndex, string text)
|
||||
{
|
||||
Raw = rawIndex;
|
||||
Text = text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,14 +70,13 @@ namespace PKHeX.Core
|
|||
/// <summary>
|
||||
/// Compares a <see cref="before"/> and <see cref="after"/> <see cref="IEventWork{T}"/> object of the same type to find <see cref="EventFlag"/> changes.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of value used by <see cref="EventWork{T}"/></typeparam>
|
||||
/// <param name="before">Data before the event was triggered</param>
|
||||
/// <param name="after">Data after the event was triggered</param>
|
||||
/// <param name="on">List of flags that were turned on</param>
|
||||
/// <param name="off">List of flags that were turned off</param>
|
||||
public static void DiffSavesFlag<T>(IEventWork<T> before, IEventWork<T> after, List<int> on, List<int> off)
|
||||
public static void DiffSavesFlag(IEventFlag before, IEventFlag after, List<int> on, List<int> off)
|
||||
{
|
||||
int max = before.MaxFlag;
|
||||
int max = before.CountFlag;
|
||||
for (int i = 0; i < max; i++)
|
||||
{
|
||||
var b = before.GetFlag(i);
|
||||
|
@ -90,6 +89,28 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares a <see cref="before"/> and <see cref="after"/> <see cref="IEventWork{T}"/> object of the same type to find <see cref="EventFlag"/> changes.
|
||||
/// </summary>
|
||||
/// <param name="before">Data before the event was triggered</param>
|
||||
/// <param name="after">Data after the event was triggered</param>
|
||||
/// <param name="on">List of flags that were turned on</param>
|
||||
/// <param name="off">List of flags that were turned off</param>
|
||||
public static void DiffSavesSystem(ISystemFlag before, ISystemFlag after, List<int> on, List<int> off)
|
||||
{
|
||||
int max = before.CountSystem;
|
||||
for (int i = 0; i < max; i++)
|
||||
{
|
||||
var b = before.GetSystemFlag(i);
|
||||
var a = after.GetSystemFlag(i);
|
||||
if (b == a)
|
||||
continue;
|
||||
|
||||
var arr = a ? on : off;
|
||||
arr.Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares a <see cref="before"/> and <see cref="after"/> <see cref="IEventWork{T}"/> object of the same type to find <see cref="EventWork{T}"/> changes.
|
||||
/// </summary>
|
||||
|
@ -100,7 +121,7 @@ namespace PKHeX.Core
|
|||
/// <param name="changes">Summary of the <see cref="EventWork{T}"/> value change</param>
|
||||
public static void DiffSavesWork<T>(IEventWork<T> before, IEventWork<T> after, List<int> changed, List<string> changes)
|
||||
{
|
||||
int max = before.MaxWork;
|
||||
int max = before.CountWork;
|
||||
for (int i = 0; i < max; i++)
|
||||
{
|
||||
var b = before.GetWork(i);
|
||||
|
@ -113,4 +134,4 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,9 +11,9 @@ namespace PKHeX.Core
|
|||
{
|
||||
public readonly IList<EventVarGroup> Work;
|
||||
public readonly IList<EventVarGroup> Flag;
|
||||
public readonly IEventWork<T> Block;
|
||||
public readonly IEventVar<T> Block;
|
||||
|
||||
public SplitEventEditor(IEventWork<T> block, IEnumerable<string> work, IEnumerable<string> flag)
|
||||
public SplitEventEditor(IEventVar<T> block, IEnumerable<string> work, IEnumerable<string> flag)
|
||||
{
|
||||
Block = block;
|
||||
// load lines
|
||||
|
|
|
@ -54,6 +54,7 @@ namespace PKHeX.Core
|
|||
SAV7 sav7 => GetExtraSlots7(sav7, all),
|
||||
SAV7b lgpe => GetExtraSlots7b(lgpe),
|
||||
SAV8SWSH ss => GetExtraSlots8(ss),
|
||||
SAV8BS bs => GetExtraSlots8b(bs),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
|
@ -201,5 +202,20 @@ namespace PKHeX.Core
|
|||
|
||||
return list;
|
||||
}
|
||||
|
||||
private static List<SlotInfoMisc> GetExtraSlots8b(SAV8BS sav)
|
||||
{
|
||||
return new()
|
||||
{
|
||||
new SlotInfoMisc(sav.Data, 0, 0x96080, true) { Type = StorageSlotType.Daycare },
|
||||
new SlotInfoMisc(sav.Data, 1, 0x96080 + PokeCrypto.SIZE_8PARTY, true) { Type = StorageSlotType.Daycare },
|
||||
|
||||
new SlotInfoMisc(sav.Data, 0, 0x9A8E8 + (0 * PokeCrypto.SIZE_8PARTY), true) { Type = StorageSlotType.Misc },
|
||||
new SlotInfoMisc(sav.Data, 1, 0x9A8E8 + (1 * PokeCrypto.SIZE_8PARTY), true) { Type = StorageSlotType.Misc },
|
||||
new SlotInfoMisc(sav.Data, 2, 0x9A8E8 + (2 * PokeCrypto.SIZE_8PARTY), true) { Type = StorageSlotType.Misc },
|
||||
new SlotInfoMisc(sav.Data, 3, 0x9A8E8 + (3 * PokeCrypto.SIZE_8PARTY), true) { Type = StorageSlotType.Misc },
|
||||
new SlotInfoMisc(sav.Data, 4, 0x9A8E8 + (4 * PokeCrypto.SIZE_8PARTY), true) { Type = StorageSlotType.Misc },
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -202,6 +202,19 @@
|
|||
/// Pokémon Shield (NX)
|
||||
/// </summary>
|
||||
SH = 45,
|
||||
|
||||
// HOME = 46,
|
||||
// PLA = 47,
|
||||
|
||||
/// <summary>
|
||||
/// Pokémon Brilliant Diamond (NX)
|
||||
/// </summary>
|
||||
BD = 48,
|
||||
|
||||
/// <summary>
|
||||
/// Pokémon Shining Pearl (NX)
|
||||
/// </summary>
|
||||
SP = 49,
|
||||
#endregion
|
||||
|
||||
// The following values are not actually stored values in pkm data,
|
||||
|
@ -379,6 +392,14 @@
|
|||
/// <see cref="SH"/>
|
||||
SWSH,
|
||||
|
||||
/// <summary>
|
||||
/// Pokémon Brilliant Diamond & Shining Pearl
|
||||
/// </summary>
|
||||
/// <remarks>Used to lump data from the associated games as data assets are shared.</remarks>
|
||||
/// <see cref="BD"/>
|
||||
/// <see cref="SP"/>
|
||||
BDSP,
|
||||
|
||||
/// <summary>
|
||||
/// Generation 1 Games
|
||||
/// </summary>
|
||||
|
@ -437,6 +458,7 @@
|
|||
/// Generation 8 Games
|
||||
/// </summary>
|
||||
/// <see cref="SWSH"/>
|
||||
/// <see cref="BDSP"/>
|
||||
Gen8,
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -80,6 +80,7 @@ namespace PKHeX.Core
|
|||
var list = s.gamelist;
|
||||
var games = new byte[]
|
||||
{
|
||||
48, 49, // 8 bdsp
|
||||
44, 45, // 8 swsh
|
||||
42, 43, // 7 gg
|
||||
30, 31, // 7 sm
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace PKHeX.Core
|
|||
public readonly string[] metSM_00000, metSM_30000, metSM_40000, metSM_60000;
|
||||
public readonly string[] metGG_00000, metGG_30000, metGG_40000, metGG_60000;
|
||||
public readonly string[] metSWSH_00000, metSWSH_30000, metSWSH_40000, metSWSH_60000;
|
||||
public readonly string[] metBDSP_00000, metBDSP_30000, metBDSP_40000, metBDSP_60000;
|
||||
|
||||
// Misc
|
||||
public readonly string[] wallpapernames, puffs, walkercourses;
|
||||
|
@ -136,6 +137,11 @@ namespace PKHeX.Core
|
|||
metSWSH_40000 = Get("swsh_40000");
|
||||
metSWSH_60000 = Get("swsh_60000");
|
||||
|
||||
metBDSP_00000 = Get("bdsp_00000");
|
||||
metBDSP_30000 = Get("bdsp_30000");
|
||||
metBDSP_40000 = Get("bdsp_40000");
|
||||
metBDSP_60000 = Get("bdsp_60000");
|
||||
|
||||
Sanitize();
|
||||
|
||||
g4items = (string[])itemlist.Clone();
|
||||
|
@ -253,6 +259,7 @@ namespace PKHeX.Core
|
|||
SanitizeMetG6XY();
|
||||
SanitizeMetG7SM();
|
||||
SanitizeMetG8SWSH();
|
||||
SanitizeMetG8BDSP();
|
||||
|
||||
if (lang is "es" or "it")
|
||||
{
|
||||
|
@ -386,6 +393,50 @@ namespace PKHeX.Core
|
|||
// metSWSH_30000[17] += " (-)"; // Pokémon HOME -- duplicate with 40000's entry
|
||||
}
|
||||
|
||||
private void SanitizeMetG8BDSP()
|
||||
{
|
||||
metBDSP_30000[1] += $" ({NPC})"; // Anything from an NPC
|
||||
metBDSP_30000[2] += $" ({EggName})"; // Egg From Link Trade
|
||||
|
||||
Deduplicate(metBDSP_00000);
|
||||
Deduplicate(metBDSP_30000);
|
||||
Deduplicate(metBDSP_40000);
|
||||
Deduplicate(metBDSP_60000);
|
||||
}
|
||||
|
||||
private static void Deduplicate(string[] arr)
|
||||
{
|
||||
var counts = new Dictionary<string, int>();
|
||||
|
||||
foreach (var s in arr)
|
||||
{
|
||||
counts.TryGetValue(s, out var value);
|
||||
counts[s] = value + 1;
|
||||
}
|
||||
|
||||
#if !DEBUG
|
||||
var maxCounts = new Dictionary<string, int>(counts);
|
||||
#endif
|
||||
for (var i = arr.Length - 1; i >= 0; i--)
|
||||
{
|
||||
#if DEBUG
|
||||
arr[i] += $" ({i:00000})";
|
||||
#else
|
||||
var s = arr[i];
|
||||
var count = counts[s]--;
|
||||
if (count == 1)
|
||||
continue;
|
||||
var format = maxCounts[s] switch
|
||||
{
|
||||
>= 100 => " ({0:000})",
|
||||
>= 10 => " ({0:00})",
|
||||
_ => " ({0})",
|
||||
};
|
||||
arr[i] += string.Format(format, count);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public string[] GetItemStrings(int generation, GameVersion game = GameVersion.Any) => generation switch
|
||||
{
|
||||
0 => Array.Empty<string>(),
|
||||
|
@ -393,9 +444,29 @@ namespace PKHeX.Core
|
|||
2 => g2items,
|
||||
3 => GetItemStrings3(game),
|
||||
4 => g4items, // mail names changed 4->5
|
||||
8 when game is GameVersion.BD or GameVersion.SP or GameVersion.BDSP => GetItemStrings8b(),
|
||||
_ => itemlist,
|
||||
};
|
||||
|
||||
private string[] GetItemStrings8b()
|
||||
{
|
||||
// Item Indexes
|
||||
var clone = (string[])itemlist.Clone();
|
||||
var tm = clone[419][..2];
|
||||
for (int i = 420; i <= 427; i++)
|
||||
clone[i] = $"{tm}{i - 420 + 93}";
|
||||
|
||||
clone[618] += "(-)"; // TM93
|
||||
clone[619] += "(-)"; // TM94
|
||||
clone[620] += "(-)"; // TM95
|
||||
clone[690] += "(-)"; // TM96
|
||||
clone[691] += "(-)"; // TM97
|
||||
clone[692] += "(-)"; // TM98
|
||||
clone[693] += "(-)"; // TM99
|
||||
clone[694] += "(-)"; // TM100
|
||||
return clone;
|
||||
}
|
||||
|
||||
private string[] GetItemStrings3(GameVersion game)
|
||||
{
|
||||
switch (game)
|
||||
|
@ -487,7 +558,7 @@ namespace PKHeX.Core
|
|||
5 => GetLocationNames5(bankID),
|
||||
6 => GetLocationNames6(bankID),
|
||||
7 => GameVersion.Gen7b.Contains(version) ? GetLocationNames7GG(bankID) : GetLocationNames7(bankID),
|
||||
8 => GetLocationNames8(bankID),
|
||||
8 => GameVersion.BDSP.Contains(version) ? GetLocationNames8b(bankID) : GetLocationNames8(bankID),
|
||||
_ => Array.Empty<string>(),
|
||||
};
|
||||
|
||||
|
@ -543,5 +614,14 @@ namespace PKHeX.Core
|
|||
6 => metSWSH_60000,
|
||||
_ => Array.Empty<string>(),
|
||||
};
|
||||
|
||||
public IReadOnlyList<string> GetLocationNames8b(int bankID) => bankID switch
|
||||
{
|
||||
0 => metBDSP_00000,
|
||||
3 => metBDSP_30000,
|
||||
4 => metBDSP_40000,
|
||||
6 => metBDSP_60000,
|
||||
_ => Array.Empty<string>(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace PKHeX.Core
|
|||
private readonly List<ComboItem> MetGen7;
|
||||
private readonly List<ComboItem> MetGen7GG;
|
||||
private readonly List<ComboItem> MetGen8;
|
||||
private readonly List<ComboItem> MetGen8b;
|
||||
|
||||
private IReadOnlyList<ComboItem>? MetGen4Transfer;
|
||||
private IReadOnlyList<ComboItem>? MetGen5Transfer;
|
||||
|
@ -33,6 +34,7 @@ namespace PKHeX.Core
|
|||
MetGen7 = CreateGen7(s);
|
||||
MetGen7GG = CreateGen7GG(s);
|
||||
MetGen8 = CreateGen8(s);
|
||||
MetGen8b = CreateGen8b(s);
|
||||
}
|
||||
|
||||
private static List<ComboItem> CreateGen2(GameStrings s)
|
||||
|
@ -129,7 +131,7 @@ namespace PKHeX.Core
|
|||
private static List<ComboItem> CreateGen7GG(GameStrings s)
|
||||
{
|
||||
var locations = Util.GetCBList(s.metGG_00000, 0);
|
||||
Util.AddCBWithOffset(locations, s.metGG_60000, 60001, 60002);
|
||||
Util.AddCBWithOffset(locations, s.metGG_60000, 60001, Locations.Daycare5);
|
||||
Util.AddCBWithOffset(locations, s.metGG_30000, 30001, Locations.LinkTrade6);
|
||||
Util.AddCBWithOffset(locations, s.metGG_00000, 00000, Legal.Met_GG_0);
|
||||
Util.AddCBWithOffset(locations, s.metGG_30000, 30001, Legal.Met_GG_3);
|
||||
|
@ -141,7 +143,7 @@ namespace PKHeX.Core
|
|||
private static List<ComboItem> CreateGen8(GameStrings s)
|
||||
{
|
||||
var locations = Util.GetCBList(s.metSWSH_00000, 0);
|
||||
Util.AddCBWithOffset(locations, s.metSWSH_60000, 60001, 60002);
|
||||
Util.AddCBWithOffset(locations, s.metSWSH_60000, 60001, Locations.Daycare5);
|
||||
Util.AddCBWithOffset(locations, s.metSWSH_30000, 30001, Locations.LinkTrade6);
|
||||
Util.AddCBWithOffset(locations, s.metSWSH_00000, 00000, Legal.Met_SWSH_0);
|
||||
Util.AddCBWithOffset(locations, s.metSWSH_30000, 30001, Legal.Met_SWSH_3);
|
||||
|
@ -150,6 +152,19 @@ namespace PKHeX.Core
|
|||
return locations;
|
||||
}
|
||||
|
||||
private static List<ComboItem> CreateGen8b(GameStrings s)
|
||||
{
|
||||
// Manually add invalid (-1) location from SWSH as ID 65535
|
||||
var locations = new List<ComboItem> { new(s.metSWSH_00000[0], 0xFFFF) };
|
||||
Util.AddCBWithOffset(locations, s.metBDSP_60000, 60000, Locations.Daycare5);
|
||||
Util.AddCBWithOffset(locations, s.metBDSP_30000, 30000, Locations.LinkTrade6);
|
||||
Util.AddCBWithOffset(locations, s.metBDSP_00000, 00000, Legal.Met_BS_0);
|
||||
Util.AddCBWithOffset(locations, s.metBDSP_30000, 30000, Legal.Met_BS_3);
|
||||
Util.AddCBWithOffset(locations, s.metBDSP_40000, 40000, Legal.Met_BS_4);
|
||||
Util.AddCBWithOffset(locations, s.metBDSP_60000, 60000, Legal.Met_BS_6);
|
||||
return locations;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches a Met Location list for a <see cref="version"/> that has been transferred away from and overwritten.
|
||||
/// </summary>
|
||||
|
@ -185,6 +200,7 @@ namespace PKHeX.Core
|
|||
or GD or SV or C => Partition2(MetGen7, z => z < 234), // Dividing Peak Tunnel
|
||||
GP or GE or GO => Partition2(MetGen7GG, z => z <= 54), // Pokémon League
|
||||
SW or SH => Partition2(MetGen8, z => z < 400),
|
||||
BD or SP => Partition2(MetGen8b, z => z < 628),
|
||||
_ => GetLocationListModified(version, currentGen),
|
||||
};
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ namespace PKHeX.Core
|
|||
|
||||
// Gen8
|
||||
SW or SH => SWSH,
|
||||
BD or SP => BDSP,
|
||||
_ => Invalid,
|
||||
};
|
||||
|
||||
|
@ -137,6 +138,7 @@ namespace PKHeX.Core
|
|||
return Legal.MaxSpeciesID_7_USUM;
|
||||
return Legal.MaxSpeciesID_7_USUM;
|
||||
}
|
||||
if (BDSP.Contains(game)) return Legal.MaxSpeciesID_8b;
|
||||
if (Gen8.Contains(game)) return Legal.MaxSpeciesID_8;
|
||||
return -1;
|
||||
}
|
||||
|
@ -197,7 +199,8 @@ namespace PKHeX.Core
|
|||
Gen7b => GG.Contains(g2) || GO == g2,
|
||||
|
||||
SWSH => g2 is SW or SH,
|
||||
Gen8 => SWSH.Contains(g2),
|
||||
BDSP => g2 is BD or SP,
|
||||
Gen8 => SWSH.Contains(g2) || BD.Contains(g2),
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
|
74
PKHeX.Core/Legality/Areas/EncounterArea8b.cs
Normal file
74
PKHeX.Core/Legality/Areas/EncounterArea8b.cs
Normal file
|
@ -0,0 +1,74 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <inheritdoc cref="EncounterArea" />
|
||||
/// <summary>
|
||||
/// <see cref="GameVersion.BDSP"/> encounter area
|
||||
/// </summary>
|
||||
public sealed record EncounterArea8b : EncounterArea
|
||||
{
|
||||
public readonly EncounterSlot8b[] Slots;
|
||||
|
||||
protected override IReadOnlyList<EncounterSlot> Raw => Slots;
|
||||
|
||||
public static EncounterArea8b[] GetAreas(byte[][] input, GameVersion game)
|
||||
{
|
||||
var result = new EncounterArea8b[input.Length];
|
||||
for (int i = 0; i < input.Length; i++)
|
||||
result[i] = new EncounterArea8b(input[i], game);
|
||||
return result;
|
||||
}
|
||||
|
||||
private EncounterArea8b(byte[] data, GameVersion game) : base(game)
|
||||
{
|
||||
Location = data[0] | (data[1] << 8);
|
||||
Type = (SlotType)data[2];
|
||||
|
||||
Slots = ReadSlots(data);
|
||||
}
|
||||
|
||||
private EncounterSlot8b[] ReadSlots(byte[] data)
|
||||
{
|
||||
const int size = 4;
|
||||
int count = (data.Length - 4) / size;
|
||||
var slots = new EncounterSlot8b[count];
|
||||
for (int i = 0; i < slots.Length; i++)
|
||||
{
|
||||
int offset = 4 + (size * i);
|
||||
ushort SpecForm = BitConverter.ToUInt16(data, offset);
|
||||
int species = SpecForm & 0x3FF;
|
||||
int form = SpecForm >> 11;
|
||||
int min = data[offset + 2];
|
||||
int max = data[offset + 3];
|
||||
slots[i] = new EncounterSlot8b(this, species, form, min, max);
|
||||
}
|
||||
return slots;
|
||||
}
|
||||
|
||||
public override IEnumerable<EncounterSlot> GetMatchingSlots(PKM pkm, IReadOnlyList<EvoCriteria> chain)
|
||||
{
|
||||
foreach (var slot in Slots)
|
||||
{
|
||||
foreach (var evo in chain)
|
||||
{
|
||||
if (slot.Species != evo.Species)
|
||||
continue;
|
||||
|
||||
if (!slot.IsLevelWithinRange(pkm.Met_Level))
|
||||
break;
|
||||
|
||||
if (slot.Form != evo.Form && slot.Species is not ((int)Species.Furfrou or (int)Species.Oricorio))
|
||||
{
|
||||
if (!slot.IsRandomUnspecificForm) // Minior, etc
|
||||
break;
|
||||
}
|
||||
|
||||
yield return slot;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@ namespace PKHeX.Core
|
|||
B, W, B2, W2,
|
||||
X, Y, OR, AS,
|
||||
SN, MN, US, UM,
|
||||
SW, SH,
|
||||
SW, SH, BD, SP,
|
||||
|
||||
GS,
|
||||
};
|
||||
|
|
|
@ -50,6 +50,8 @@ namespace PKHeX.Core
|
|||
// Gen 8
|
||||
internal static readonly EggMoves7[] EggMovesSWSH = EggMoves7.GetArray(BinLinker.Unpack(Util.GetBinaryResource("eggmove_swsh.pkl"), "ss"));
|
||||
internal static readonly Learnset[] LevelUpSWSH = LearnsetReader.GetArray(BinLinker.Unpack(Util.GetBinaryResource("lvlmove_swsh.pkl"), "ss"));
|
||||
internal static readonly EggMoves7[] EggMovesBDSP = EggMoves7.GetArray(BinLinker.Unpack(Util.GetBinaryResource("eggmove_bdsp.pkl"), "bs"));
|
||||
internal static readonly Learnset[] LevelUpBDSP = LearnsetReader.GetArray(BinLinker.Unpack(Util.GetBinaryResource("lvlmove_bdsp.pkl"), "bs"));
|
||||
|
||||
public static IReadOnlyList<byte> GetPPTable(PKM pkm, int format)
|
||||
{
|
||||
|
@ -72,6 +74,13 @@ namespace PKHeX.Core
|
|||
_ => Array.Empty<byte>(),
|
||||
};
|
||||
|
||||
public static ICollection<int> GetDummiedMovesHashSet(PKM pkm) => pkm switch
|
||||
{
|
||||
PK8 => DummiedMoves_SWSH,
|
||||
PB8 => DummiedMoves_BDSP,
|
||||
_ => Array.Empty<int>(),
|
||||
};
|
||||
|
||||
internal static int GetMaxSpeciesOrigin(PKM pkm)
|
||||
{
|
||||
if (pkm.Format == 1)
|
||||
|
|
|
@ -30,6 +30,9 @@ namespace PKHeX.Core
|
|||
/// <summary>Event Database for Generation 8</summary>
|
||||
public static IReadOnlyList<WC8> MGDB_G8 { get; private set; } = Array.Empty<WC8>();
|
||||
|
||||
/// <summary>Event Database for Generation 8 <see cref="GameVersion.BDSP"/></summary>
|
||||
public static IReadOnlyList<WB8> MGDB_G8B { get; private set; } = Array.Empty<WB8>();
|
||||
|
||||
/// <summary>Indicates if the databases are initialized.</summary>
|
||||
public static bool Initialized => MGDB_G3.Count != 0;
|
||||
|
||||
|
@ -41,6 +44,7 @@ namespace PKHeX.Core
|
|||
|
||||
private static WB7[] GetWB7DB(byte[] bin) => Get(bin, WB7.SizeFull, d => new WB7(d));
|
||||
private static WC8[] GetWC8DB(byte[] bin) => Get(bin, WC8.Size, d => new WC8(d));
|
||||
private static WB8[] GetWB8DB(byte[] bin) => Get(bin, WB8.Size, d => new WB8(d));
|
||||
|
||||
private static T[] Get<T>(byte[] bin, int size, Func<byte[], T> ctor)
|
||||
{
|
||||
|
@ -63,6 +67,7 @@ namespace PKHeX.Core
|
|||
ICollection<WC7> g7 = GetWC7DB(Util.GetBinaryResource("wc7.pkl"), Util.GetBinaryResource("wc7full.pkl"));
|
||||
ICollection<WB7> b7 = GetWB7DB(Util.GetBinaryResource("wb7full.pkl"));
|
||||
ICollection<WC8> g8 = GetWC8DB(Util.GetBinaryResource("wc8.pkl"));
|
||||
ICollection<WB8> b8 = GetWB8DB(Util.GetBinaryResource("wb8.pkl"));
|
||||
|
||||
foreach (var gift in paths.Where(Directory.Exists).SelectMany(MysteryUtil.GetGiftsFromFolder))
|
||||
{
|
||||
|
@ -81,6 +86,7 @@ namespace PKHeX.Core
|
|||
case WC7 wc7: AddOrExpand(ref g7, wc7); continue;
|
||||
case WB7 wb7: AddOrExpand(ref b7, wb7); continue;
|
||||
case WC8 wc8: AddOrExpand(ref g8, wc8); continue;
|
||||
case WB8 wb8: AddOrExpand(ref b8, wb8); continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,6 +108,7 @@ namespace PKHeX.Core
|
|||
MGDB_G7 = SetArray(g7);
|
||||
MGDB_G7GG = SetArray(b7);
|
||||
MGDB_G8 = SetArray(g8);
|
||||
MGDB_G8B = SetArray(b8);
|
||||
}
|
||||
|
||||
public static IEnumerable<MysteryGift> GetAllEvents(bool sorted = true)
|
||||
|
@ -114,6 +121,7 @@ namespace PKHeX.Core
|
|||
MGDB_G7,
|
||||
MGDB_G7GG,
|
||||
MGDB_G8,
|
||||
MGDB_G8B,
|
||||
}.SelectMany(z => z);
|
||||
regular = regular.Where(mg => !mg.IsItem && mg.IsPokémon && mg.Species > 0);
|
||||
var result = MGDB_G3.Concat(regular);
|
||||
|
|
103
PKHeX.Core/Legality/Encounters/Data/Encounters8b.cs
Normal file
103
PKHeX.Core/Legality/Encounters/Data/Encounters8b.cs
Normal file
|
@ -0,0 +1,103 @@
|
|||
using static PKHeX.Core.EncounterUtil;
|
||||
using static PKHeX.Core.Shiny;
|
||||
using static PKHeX.Core.GameVersion;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
internal static class Encounters8b
|
||||
{
|
||||
private static readonly EncounterArea8b[] SlotsBD_OW = EncounterArea8b.GetAreas(Get("encounter_bd", "bs"), BD);
|
||||
private static readonly EncounterArea8b[] SlotsSP_OW = EncounterArea8b.GetAreas(Get("encounter_sp", "bs"), SP);
|
||||
private static readonly EncounterArea8b[] SlotsBD_UG = EncounterArea8b.GetAreas(Get("underground_bd", "bs"), BD);
|
||||
private static readonly EncounterArea8b[] SlotsSP_UG = EncounterArea8b.GetAreas(Get("underground_sp", "bs"), SP);
|
||||
|
||||
internal static readonly EncounterArea8b[] SlotsBD = ArrayUtil.ConcatAll(SlotsBD_OW, SlotsBD_UG);
|
||||
internal static readonly EncounterArea8b[] SlotsSP = ArrayUtil.ConcatAll(SlotsSP_OW, SlotsSP_UG);
|
||||
|
||||
private static byte[][] Get(string resource, string ident) => BinLinker.Unpack(Util.GetBinaryResource($"{resource}.pkl"), ident);
|
||||
|
||||
static Encounters8b() => MarkEncounterTradeStrings(TradeGift_BDSP, TradeBDSP);
|
||||
|
||||
private static readonly EncounterStatic8b[] Encounter_BDSP =
|
||||
{
|
||||
// Gifts
|
||||
new (BDSP) { Gift = true, Species = 387, Level = 05, Location = 323 }, // Turtwig
|
||||
new (BDSP) { Gift = true, Species = 390, Level = 05, Location = 323 }, // Chimchar
|
||||
new (BDSP) { Gift = true, Species = 393, Level = 05, Location = 323 }, // Piplup
|
||||
new (BDSP) { Gift = true, Species = 133, Level = 05, Location = 104 }, // Eevee
|
||||
new (BDSP) { Gift = true, Species = 440, Level = 01, EggLocation = 60007, EggCycles = 40 }, // Happiny Egg from Traveling Man
|
||||
new (BDSP) { Gift = true, Species = 447, Level = 01, EggLocation = 60005, EggCycles = 25 }, // Riolu Egg from Riley
|
||||
|
||||
// Fossils
|
||||
new (BDSP) { Gift = true, Species = 138, Level = 01, Location = 049, FlawlessIVCount = 3 }, // Omanyte
|
||||
new (BDSP) { Gift = true, Species = 140, Level = 01, Location = 049, FlawlessIVCount = 3 }, // Kabuto
|
||||
new (BDSP) { Gift = true, Species = 142, Level = 01, Location = 049, FlawlessIVCount = 3 }, // Aerodactyl
|
||||
new (BDSP) { Gift = true, Species = 345, Level = 01, Location = 049, FlawlessIVCount = 3 }, // Lileep
|
||||
new (BDSP) { Gift = true, Species = 347, Level = 01, Location = 049, FlawlessIVCount = 3 }, // Anorith
|
||||
new (BDSP) { Gift = true, Species = 408, Level = 01, Location = 049, FlawlessIVCount = 3 }, // Cranidos
|
||||
new (BDSP) { Gift = true, Species = 410, Level = 01, Location = 049, FlawlessIVCount = 3 }, // Shieldon
|
||||
|
||||
// Game-specific gifts
|
||||
new (BDSP) { Gift = true, Species = 151, Level = 01, Ability = 2, Location = 438, Shiny = Never, FlawlessIVCount = 3, Fateful = true }, // Mew
|
||||
new (BDSP) { Gift = true, Species = 385, Level = 05, Ability = 2, Location = 438, Shiny = Never, FlawlessIVCount = 3, Fateful = true }, // Jirachi
|
||||
|
||||
// Stationary
|
||||
new (BDSP) { Species = 425, Level = 22, Location = 197 }, // Drifloon
|
||||
new (BDSP) { Species = 442, Level = 25, Location = 367 }, // Spiritomb
|
||||
new (BDSP) { Species = 479, Level = 15, Location = 311 }, // Rotom
|
||||
|
||||
// Roamers
|
||||
new (BDSP) { Species = 481, Level = 50, FlawlessIVCount = 3, Roaming = true }, // Mesprit
|
||||
new (BDSP) { Species = 488, Level = 50, FlawlessIVCount = 3, Roaming = true }, // Cresselia
|
||||
|
||||
// Legendary
|
||||
new (BDSP) { Species = 480, Level = 50, Location = 331, FlawlessIVCount = 3 }, // Uxie
|
||||
new (BDSP) { Species = 482, Level = 50, Location = 328, FlawlessIVCount = 3 }, // Azelf
|
||||
new (BD ) { Species = 483, Level = 47, Location = 216, FlawlessIVCount = 3 }, // Dialga
|
||||
new ( SP) { Species = 484, Level = 47, Location = 217, FlawlessIVCount = 3 }, // Palkia
|
||||
new (BDSP) { Species = 485, Level = 70, Location = 262, FlawlessIVCount = 3 }, // Heatran
|
||||
new (BDSP) { Species = 486, Level = 70, Location = 291, FlawlessIVCount = 3 }, // Regigigas
|
||||
new (BDSP) { Species = 487, Level = 70, Location = 266, FlawlessIVCount = 3 }, // Giratina
|
||||
|
||||
// Mythical
|
||||
//new (BDSP) { Species = 491, Level = 50, Location = 333, FlawlessIVCount = 3, Fateful = true }, // Darkrai
|
||||
//new (BDSP) { Species = 492, Level = 30, Location = 285, FlawlessIVCount = 3, Fateful = true }, // Shaymin
|
||||
//new (BDSP) { Species = 493, Level = 80, Location = 218, FlawlessIVCount = 3, Fateful = true }, // Arceus
|
||||
|
||||
// Ramanas Park (Pure Space)
|
||||
new ( SP) { Species = 144, Level = 70, Ability = 4, Location = 506, FlawlessIVCount = 3 }, // Articuno
|
||||
new ( SP) { Species = 145, Level = 70, Ability = 4, Location = 506, FlawlessIVCount = 3 }, // Zapdos
|
||||
new ( SP) { Species = 146, Level = 70, Ability = 4, Location = 506, FlawlessIVCount = 3 }, // Moltres
|
||||
new (BD ) { Species = 243, Level = 70, Ability = 4, Location = 506, FlawlessIVCount = 3 }, // Raikou
|
||||
new (BD ) { Species = 244, Level = 70, Ability = 4, Location = 506, FlawlessIVCount = 3 }, // Entei
|
||||
new (BD ) { Species = 245, Level = 70, Ability = 4, Location = 506, FlawlessIVCount = 3 }, // Suicune
|
||||
new (BDSP) { Species = 377, Level = 70, Ability = 4, Location = 506, FlawlessIVCount = 3 }, // Regirock
|
||||
new (BDSP) { Species = 378, Level = 70, Ability = 4, Location = 506, FlawlessIVCount = 3 }, // Regice
|
||||
new (BDSP) { Species = 379, Level = 70, Ability = 4, Location = 506, FlawlessIVCount = 3 }, // Registeel
|
||||
new (BDSP) { Species = 380, Level = 70, Location = 506, FlawlessIVCount = 3 }, // Latias
|
||||
new (BDSP) { Species = 381, Level = 70, Location = 506, FlawlessIVCount = 3 }, // Latios
|
||||
|
||||
// Ramanas Park (Deep Space)
|
||||
new (BDSP) { Species = 150, Level = 70, Ability = 4, Location = 507, FlawlessIVCount = 3 }, // Mewtwo
|
||||
new ( SP) { Species = 249, Level = 70, Ability = 4, Location = 507, FlawlessIVCount = 3 }, // Lugia
|
||||
new (BD ) { Species = 250, Level = 70, Ability = 4, Location = 507, FlawlessIVCount = 3 }, // Ho-Oh
|
||||
new (BDSP) { Species = 382, Level = 70, Location = 507, FlawlessIVCount = 3 }, // Kyogre
|
||||
new (BDSP) { Species = 383, Level = 70, Location = 507, FlawlessIVCount = 3 }, // Groudon
|
||||
new (BDSP) { Species = 384, Level = 70, Location = 507, FlawlessIVCount = 3 }, // Rayquaza
|
||||
};
|
||||
|
||||
internal static readonly EncounterStatic8b[] StaticBD = GetEncounters(Encounter_BDSP, BD);
|
||||
internal static readonly EncounterStatic8b[] StaticSP = GetEncounters(Encounter_BDSP, SP);
|
||||
|
||||
private const string tradeBDSP = "tradebdsp";
|
||||
private static readonly string[][] TradeBDSP = Util.GetLanguageStrings10(tradeBDSP, "zh2");
|
||||
|
||||
internal static readonly EncounterTrade8b[] TradeGift_BDSP =
|
||||
{
|
||||
new (BDSP) { Species = 063, Level = 09, Ability = 1, Gender = 0, OTGender = 0, TID = 25643, IVs = new[] {28,10,09,31,11,03}, Moves = new[] {100,000,000,000}, HeightScalar = 029, WeightScalar = 202, Nature = Nature.Quiet }, // Abra
|
||||
new (BDSP) { Species = 441, Level = 15, Ability = 2, Gender = 1, OTGender = 0, TID = 44142, IVs = new[] {17,08,29,25,17,23}, Moves = new[] {448,047,064,045}, HeightScalar = 088, WeightScalar = 091, Nature = Nature.Lonely }, // Chatot
|
||||
new (BDSP) { Species = 093, Level = 33, Ability = 1, Gender = 0, OTGender = 0, TID = 19248, IVs = new[] {18,24,28,02,22,30}, Moves = new[] {247,371,389,109}, HeightScalar = 096, WeightScalar = 208, Nature = Nature.Hasty }, // Haunter
|
||||
new (BDSP) { Species = 129, Level = 45, Ability = 1, Gender = 1, OTGender = 0, TID = 53277, IVs = new[] {03,03,31,02,11,03}, Moves = new[] {150,000,000,000}, HeightScalar = 169, WeightScalar = 068, Nature = Nature.Mild }, // Magikarp
|
||||
};
|
||||
}
|
||||
}
|
188
PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot8b.cs
Normal file
188
PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot8b.cs
Normal file
|
@ -0,0 +1,188 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Encounter Slot found in <see cref="GameVersion.BDSP"/>.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="EncounterSlot"/>
|
||||
public sealed record EncounterSlot8b : EncounterSlot
|
||||
{
|
||||
public override int Generation => 8;
|
||||
public bool IsUnderground => Area.Location is (>= 508 and <= 617);
|
||||
public bool IsMarsh => Area.Location is (>= 219 and <= 224);
|
||||
|
||||
public EncounterSlot8b(EncounterArea area, int species, int form, int min, int max) : base(area, species, form, min, max)
|
||||
{
|
||||
}
|
||||
protected override void SetFormatSpecificData(PKM pk)
|
||||
{
|
||||
if (IsUnderground)
|
||||
{
|
||||
if (GetBaseEggMove(out int move1))
|
||||
pk.RelearnMove1 = move1;
|
||||
}
|
||||
else if (IsMarsh)
|
||||
{
|
||||
pk.Ball = (int)Ball.Safari;
|
||||
}
|
||||
pk.SetRandomEC();
|
||||
}
|
||||
|
||||
public bool CanBeUndergroundMove(int move)
|
||||
{
|
||||
var et = EvolutionTree.Evolves8b;
|
||||
var sf = et.GetBaseSpeciesForm(Species, Form);
|
||||
var species = sf & 0x7FF;
|
||||
var form = sf >> 11;
|
||||
if (IgnoreEggMoves.TryGetValue(species, out var exclude) && Array.IndexOf(exclude, move) != -1)
|
||||
return false;
|
||||
|
||||
var baseEgg = MoveEgg.GetEggMoves(8, species, form, Version);
|
||||
return baseEgg.Length == 0 || Array.IndexOf(baseEgg, move) >= 0;
|
||||
}
|
||||
|
||||
public bool GetBaseEggMove(out int move)
|
||||
{
|
||||
var et = EvolutionTree.Evolves8b;
|
||||
var sf = et.GetBaseSpeciesForm(Species, Form);
|
||||
var species = sf & 0x7FF;
|
||||
var form = sf >> 11;
|
||||
|
||||
int[] Exclude = IgnoreEggMoves.TryGetValue(species, out var exclude) ? exclude : Array.Empty<int>();
|
||||
var baseEgg = MoveEgg.GetEggMoves(8, species, form, Version);
|
||||
if (baseEgg.Length == 0)
|
||||
{
|
||||
move = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
var rnd = Util.Rand;
|
||||
while (true)
|
||||
{
|
||||
var index = rnd.Next(baseEgg.Length);
|
||||
move = baseEgg[index];
|
||||
if (Array.IndexOf(Exclude, move) == -1)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly Dictionary<int, int[]> IgnoreEggMoves = new()
|
||||
{
|
||||
{004, new[] {394}}, // Charmander
|
||||
{016, new[] {403}}, // Pidgey
|
||||
{019, new[] {044}}, // Rattata
|
||||
{027, new[] {229}}, // Sandshrew
|
||||
{037, new[] {180,050,326}}, // Vulpix
|
||||
{050, new[] {310}}, // Diglett
|
||||
{056, new[] {370}}, // Mankey
|
||||
{058, new[] {242,336,394}}, // Growlithe
|
||||
{060, new[] {061,341}}, // Poliwag
|
||||
{066, new[] {282}}, // Machop
|
||||
{077, new[] {172}}, // Ponyta
|
||||
{079, new[] {428}}, // Slowpoke
|
||||
{083, new[] {348}}, // Farfetch’d
|
||||
{084, new[] {098,283}}, // Doduo
|
||||
{086, new[] {227}}, // Seel
|
||||
{098, new[] {175,021}}, // Krabby
|
||||
{102, new[] {235}}, // Exeggcute
|
||||
{108, new[] {187}}, // Lickitung
|
||||
{109, new[] {194}}, // Koffing
|
||||
{113, new[] {270}}, // Chansey
|
||||
{114, new[] {072}}, // Tangela
|
||||
{115, new[] {023,116}}, // Kangaskhan
|
||||
{116, new[] {225}}, // Horsea
|
||||
{122, new[] {102,298}}, // Mr. Mime
|
||||
{127, new[] {450,276}}, // Pinsir
|
||||
{133, new[] {204,343}}, // Eevee
|
||||
{140, new[] {341}}, // Kabuto
|
||||
{143, new[] {122,562}}, // Snorlax
|
||||
{147, new[] {349,407}}, // Dratini
|
||||
{152, new[] {267,312,034}}, // Chikorita
|
||||
{155, new[] {098,038}}, // Cyndaquil
|
||||
{158, new[] {242,037,056}}, // Totodile
|
||||
{161, new[] {179}}, // Sentret
|
||||
{170, new[] {175}}, // Chinchou
|
||||
{173, new[] {150}}, // Cleffa
|
||||
{179, new[] {036,268}}, // Mareep
|
||||
{183, new[] {276}}, // Marill
|
||||
{187, new[] {388}}, // Hoppip
|
||||
{190, new[] {103,097}}, // Aipom
|
||||
{191, new[] {073,275}}, // Sunkern
|
||||
{198, new[] {017,372}}, // Murkrow
|
||||
{200, new[] {180}}, // Misdreavus
|
||||
{204, new[] {038}}, // Pineco
|
||||
{206, new[] {246}}, // Dunsparce
|
||||
{209, new[] {242,423,424,422}}, // Snubbull
|
||||
{214, new[] {224}}, // Heracross
|
||||
{216, new[] {313}}, // Teddiursa
|
||||
{218, new[] {414}}, // Slugma
|
||||
{220, new[] {036}}, // Swinub
|
||||
{222, new[] {392}}, // Corsola
|
||||
{223, new[] {062}}, // Remoraid
|
||||
{226, new[] {056,469}}, // Mantine
|
||||
{227, new[] {065,413}}, // Skarmory
|
||||
{228, new[] {251,424}}, // Houndour
|
||||
{234, new[] {428}}, // Stantler
|
||||
{236, new[] {270}}, // Tyrogue
|
||||
{238, new[] {008}}, // Smoochum
|
||||
{252, new[] {283,437}}, // Treecko
|
||||
{255, new[] {179,297}}, // Torchic
|
||||
{261, new[] {281,389,583}}, // Poochyena
|
||||
{270, new[] {175,055}}, // Lotad
|
||||
{276, new[] {413}}, // Taillow
|
||||
{278, new[] {054,097}}, // Wingull
|
||||
{283, new[] {453}}, // Surskit
|
||||
{285, new[] {388,402}}, // Shroomish
|
||||
{296, new[] {197}}, // Makuhita
|
||||
{298, new[] {021}}, // Azurill
|
||||
{299, new[] {335}}, // Nosepass
|
||||
{300, new[] {252}}, // Skitty
|
||||
{302, new[] {212}}, // Sableye
|
||||
{303, new[] {389}}, // Mawile
|
||||
{304, new[] {442}}, // Aron
|
||||
{309, new[] {435,422}}, // Electrike
|
||||
{311, new[] {435,204}}, // Plusle
|
||||
{312, new[] {435,313}}, // Minun
|
||||
{313, new[] {227}}, // Volbeat
|
||||
{314, new[] {227}}, // Illumise
|
||||
{315, new[] {235}}, // Roselia
|
||||
{316, new[] {220,441}}, // Gulpin
|
||||
{320, new[] {034}}, // Wailmer
|
||||
{322, new[] {281}}, // Numel
|
||||
{324, new[] {284,499}}, // Torkoal
|
||||
{325, new[] {428}}, // Spoink
|
||||
{328, new[] {414}}, // Trapinch
|
||||
{336, new[] {400}}, // Seviper
|
||||
{339, new[] {330}}, // Barboach
|
||||
{341, new[] {283,282}}, // Corphish
|
||||
{345, new[] {072}}, // Lileep
|
||||
{352, new[] {050,492}}, // Kecleon
|
||||
{353, new[] {425,566}}, // Shuppet
|
||||
{357, new[] {437,235,349,692}}, // Tropius
|
||||
{359, new[] {389,195}}, // Absol
|
||||
{363, new[] {205}}, // Spheal
|
||||
{369, new[] {401}}, // Relicanth
|
||||
{370, new[] {392}}, // Luvdisc
|
||||
{387, new[] {074}}, // Turtwig
|
||||
{390, new[] {612}}, // Chimchar
|
||||
{393, new[] {056}}, // Piplup
|
||||
{399, new[] {111,205}}, // Bidoof
|
||||
{408, new[] {043}}, // Cranidos
|
||||
{417, new[] {608}}, // Pachirisu
|
||||
{418, new[] {401}}, // Buizel
|
||||
{422, new[] {262}}, // Shellos
|
||||
{425, new[] {194,366}}, // Drifloon
|
||||
{439, new[] {102,298}}, // Mime Jr.
|
||||
{442, new[] {425}}, // Spiritomb
|
||||
{443, new[] {225,328}}, // Gible
|
||||
{446, new[] {122}}, // Munchlax
|
||||
{449, new[] {303,328}}, // Hippopotas
|
||||
{451, new[] {400}}, // Skorupi
|
||||
{456, new[] {175}}, // Finneon
|
||||
{458, new[] {056,469}}, // Mantyke
|
||||
{459, new[] {054}}, // Snover
|
||||
};
|
||||
}
|
||||
}
|
|
@ -132,7 +132,7 @@ namespace PKHeX.Core
|
|||
if (Generation >= 4)
|
||||
{
|
||||
bool traded = (int)Version == tr.Game;
|
||||
pk.Egg_Location = EncounterSuggestion.GetSuggestedEncounterEggLocationEgg(Generation, traded);
|
||||
pk.Egg_Location = EncounterSuggestion.GetSuggestedEncounterEggLocationEgg(Generation, Version, traded);
|
||||
pk.EggMetDate = today;
|
||||
}
|
||||
pk.Egg_Location = EggLocation;
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static PKHeX.Core.StaticCorrelation8bRequirement;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Generation 7 Static Encounter
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="EncounterStatic"/>
|
||||
public sealed record EncounterStatic8b : EncounterStatic, IRelearn, IStaticCorrelation8b
|
||||
{
|
||||
public override int Generation => 8;
|
||||
public IReadOnlyList<int> Relearn { get; init; } = Array.Empty<int>();
|
||||
|
||||
public bool Roaming { get; init; } = false;
|
||||
|
||||
public EncounterStatic8b(GameVersion game) : base(game)
|
||||
{
|
||||
EggLocation = Locations.Default8bNone;
|
||||
}
|
||||
|
||||
protected override bool IsMatchLocation(PKM pkm)
|
||||
{
|
||||
if (!Roaming)
|
||||
return base.IsMatchLocation(pkm);
|
||||
return Roaming_MetLocation_BDSP.Contains(pkm.Met_Location);
|
||||
}
|
||||
|
||||
public StaticCorrelation8bRequirement GetRequirement(PKM pk) => Roaming
|
||||
? MustHave
|
||||
: MustNotHave;
|
||||
|
||||
public bool IsStaticCorrelationCorrect(PKM pk)
|
||||
{
|
||||
return Roaming8bRNG.ValidateRoamingEncounter(pk, Shiny == Shiny.Random ? Shiny.FixedValue : Shiny, FlawlessIVCount);
|
||||
}
|
||||
|
||||
protected override bool IsMatchEggLocation(PKM pkm)
|
||||
{
|
||||
var eggloc = (short)pkm.Egg_Location;
|
||||
if (!EggEncounter)
|
||||
return eggloc == (short)EggLocation;
|
||||
|
||||
if (!pkm.IsEgg) // hatched
|
||||
return eggloc == (short)EggLocation || eggloc == Locations.LinkTrade6NPC;
|
||||
|
||||
// Unhatched:
|
||||
if (eggloc != (short)EggLocation)
|
||||
return false;
|
||||
if ((short)pkm.Met_Location is not (Locations.Default8bNone or Locations.LinkTrade6NPC))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void ApplyDetails(ITrainerInfo sav, EncounterCriteria criteria, PKM pk)
|
||||
{
|
||||
pk.Met_Location = pk.Egg_Location = Locations.Default8bNone;
|
||||
base.ApplyDetails(sav, criteria, pk);
|
||||
var req = GetRequirement(pk);
|
||||
if (req != MustHave)
|
||||
{
|
||||
pk.SetRandomEC();
|
||||
return;
|
||||
}
|
||||
var shiny = Shiny == Shiny.Random ? Shiny.FixedValue : Shiny;
|
||||
Roaming8bRNG.ApplyDetails(pk, criteria, shiny, FlawlessIVCount);
|
||||
}
|
||||
|
||||
protected override void SetMetData(PKM pk, int level, DateTime today)
|
||||
{
|
||||
pk.Met_Level = level;
|
||||
pk.Met_Location = !Roaming ? Location : Roaming_MetLocation_BDSP[0];
|
||||
pk.MetDate = today;
|
||||
}
|
||||
|
||||
private static readonly int[] Roaming_MetLocation_BDSP =
|
||||
{
|
||||
197, 201, 354, 355, 356, 357, 358, 359, 361, 362, 364, 365, 367, 373, 375, 377,
|
||||
378, 379, 383, 385, 392, 394, 395, 397, 400, 403, 404, 407, 411, 412, 414, 416,
|
||||
420,
|
||||
};
|
||||
}
|
||||
|
||||
public interface IStaticCorrelation8b
|
||||
{
|
||||
StaticCorrelation8bRequirement GetRequirement(PKM pk);
|
||||
bool IsStaticCorrelationCorrect(PKM pk);
|
||||
}
|
||||
|
||||
public enum StaticCorrelation8bRequirement
|
||||
{
|
||||
CanBeEither,
|
||||
MustHave,
|
||||
MustNotHave,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Generation 7 Trade Encounter
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="EncounterTrade"/>
|
||||
public sealed record EncounterTrade8b : EncounterTrade, IContestStats, IScaledSize, IFixedOTFriendship
|
||||
{
|
||||
public override int Generation => 8;
|
||||
public override int Location => Locations.LinkTrade6NPC;
|
||||
|
||||
public EncounterTrade8b(GameVersion game) : base(game) => EggLocation = unchecked((ushort)Locations.Default8bNone);
|
||||
public byte CNT_Cool => BaseContest;
|
||||
public byte CNT_Beauty => BaseContest;
|
||||
public byte CNT_Cute => BaseContest;
|
||||
public byte CNT_Smart => BaseContest;
|
||||
public byte CNT_Tough => BaseContest;
|
||||
public byte CNT_Sheen => 0;
|
||||
public int OT_Friendship => Species == (int)Core.Species.Chatot ? 35 : 50;
|
||||
private byte BaseContest => Species == (int)Core.Species.Chatot ? (byte)20 : (byte)0;
|
||||
public int HeightScalar { get; set; }
|
||||
public int WeightScalar { get; set; }
|
||||
|
||||
public override bool IsMatchExact(PKM pkm, DexLevel evo)
|
||||
{
|
||||
if (pkm is IContestStats s && s.IsContestBelow(this))
|
||||
return false;
|
||||
if (pkm is IScaledSize h && h.HeightScalar != HeightScalar)
|
||||
return false;
|
||||
if (pkm is IScaledSize w && w.WeightScalar != WeightScalar)
|
||||
return false;
|
||||
return base.IsMatchExact(pkm, evo);
|
||||
}
|
||||
|
||||
protected override void ApplyDetails(ITrainerInfo sav, EncounterCriteria criteria, PKM pk)
|
||||
{
|
||||
base.ApplyDetails(sav, criteria, pk);
|
||||
var pb8 = (PB8)pk;
|
||||
|
||||
// Has German Language ID for all except German origin, which is English
|
||||
if (Species == (int)Core.Species.Magikarp)
|
||||
pb8.Language = (int)(pb8.Language == (int)LanguageID.German ? LanguageID.English : LanguageID.German);
|
||||
// All other trades received: English games have a Japanese language ID instead of English.
|
||||
else if (pb8.Language == (int)LanguageID.English)
|
||||
pb8.Language = (int)LanguageID.Japanese;
|
||||
|
||||
this.CopyContestStatsTo(pb8);
|
||||
pb8.HT_Language = sav.Language;
|
||||
pb8.HeightScalar = HeightScalar;
|
||||
pb8.WeightScalar = WeightScalar;
|
||||
pb8.SetRandomEC();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ namespace PKHeX.Core
|
|||
return pkm.Version switch
|
||||
{
|
||||
(int)GameVersion.GO => EncounterGenerator7.GetEncountersGO(pkm, chain),
|
||||
(int)GameVersion.BD or (int)GameVersion.SP => EncounterGenerator8b.GetEncounters(pkm, chain),
|
||||
_ => GetEncountersMainline(pkm, chain),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
using static PKHeX.Core.MysteryGiftGenerator;
|
||||
using static PKHeX.Core.EncounterTradeGenerator;
|
||||
using static PKHeX.Core.EncounterSlotGenerator;
|
||||
using static PKHeX.Core.EncounterStaticGenerator;
|
||||
using static PKHeX.Core.EncounterEggGenerator;
|
||||
using static PKHeX.Core.EncounterMatchRating;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
internal static class EncounterGenerator8b
|
||||
{
|
||||
public static IEnumerable<IEncounterable> GetEncounters(PKM pkm, IReadOnlyList<EvoCriteria> chain)
|
||||
{
|
||||
int ctr = 0;
|
||||
if (pkm.FatefulEncounter)
|
||||
{
|
||||
foreach (var z in GetValidGifts(pkm, chain))
|
||||
{ yield return z; ++ctr; }
|
||||
if (ctr != 0) yield break;
|
||||
}
|
||||
|
||||
if (Locations.IsEggLocationBred8b(pkm.Egg_Location))
|
||||
{
|
||||
foreach (var z in GenerateEggs(pkm, 8))
|
||||
{ yield return z; ++ctr; }
|
||||
if (ctr == 0) yield break;
|
||||
}
|
||||
|
||||
IEncounterable? cache = null;
|
||||
EncounterMatchRating rating = None;
|
||||
|
||||
// Trades
|
||||
if (pkm.Met_Location == Locations.LinkTrade6NPC)
|
||||
{
|
||||
foreach (var z in GetValidEncounterTrades(pkm, chain))
|
||||
{
|
||||
var match = z.GetMatchRating(pkm);
|
||||
if (match == Match)
|
||||
{
|
||||
yield return z;
|
||||
}
|
||||
else if (match < rating)
|
||||
{
|
||||
cache = z;
|
||||
rating = match;
|
||||
}
|
||||
}
|
||||
|
||||
if (cache != null)
|
||||
yield return cache;
|
||||
yield break;
|
||||
}
|
||||
|
||||
// Static Encounters can collide with wild encounters (close match); don't break if a Static Encounter is yielded.
|
||||
var encs = GetValidStaticEncounter(pkm, chain);
|
||||
foreach (var z in encs)
|
||||
{
|
||||
var match = z.GetMatchRating(pkm);
|
||||
if (match == Match)
|
||||
{
|
||||
yield return z;
|
||||
}
|
||||
else if (match < rating)
|
||||
{
|
||||
cache = z;
|
||||
rating = match;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var z in GetValidWildEncounters(pkm, chain))
|
||||
{
|
||||
var match = z.GetMatchRating(pkm);
|
||||
if (match == Match)
|
||||
{
|
||||
yield return z;
|
||||
}
|
||||
else if (match < rating)
|
||||
{
|
||||
cache = z;
|
||||
rating = match;
|
||||
}
|
||||
}
|
||||
|
||||
if (cache != null)
|
||||
yield return cache;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -145,7 +145,7 @@ namespace PKHeX.Core
|
|||
var format = pk.Format;
|
||||
if (format is 2 && version is GameVersion.RD or GameVersion.GN or GameVersion.BU or GameVersion.YW)
|
||||
format = 1; // try excluding baby pokemon from our evolution chain, for move learning purposes.
|
||||
var et = EvolutionTree.GetEvolutionTree(format);
|
||||
var et = EvolutionTree.GetEvolutionTree(pk, format);
|
||||
var chain = et.GetValidPreEvolutions(pk, maxLevel: 100, skipChecks: true);
|
||||
int[] needs = GetNeededMoves(pk, moves, chain);
|
||||
|
||||
|
@ -407,6 +407,8 @@ namespace PKHeX.Core
|
|||
yield return slot;
|
||||
else if (needs.Count == 1 && slot is EncounterSlot6AO {CanDexNav: true} dn && dn.CanBeDexNavMove(needs[0]))
|
||||
yield return slot;
|
||||
else if (needs.Count == 1 && slot is EncounterSlot8b {IsUnderground: true} ug && ug.CanBeUndergroundMove(needs[0]))
|
||||
yield return slot;
|
||||
else if (slot.Generation <= 2 && !needs.Except(MoveLevelUp.GetEncounterMoves(slot.Species, 0, slot.LevelMin, slot.Version)).Any())
|
||||
yield return slot;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ using static PKHeX.Core.Encounters6;
|
|||
using static PKHeX.Core.Encounters7;
|
||||
using static PKHeX.Core.Encounters7b;
|
||||
using static PKHeX.Core.Encounters8;
|
||||
using static PKHeX.Core.Encounters8b;
|
||||
using static PKHeX.Core.EncountersGO;
|
||||
|
||||
using static PKHeX.Core.GameVersion;
|
||||
|
@ -43,7 +44,7 @@ namespace PKHeX.Core
|
|||
|
||||
private static IEnumerable<EncounterSlot> GetRawEncounterSlots(PKM pkm, IReadOnlyList<EvoCriteria> chain, GameVersion gameSource)
|
||||
{
|
||||
if (pkm.Egg_Location != 0 || pkm.IsEgg)
|
||||
if (!Locations.IsNoneLocation(gameSource, pkm.Egg_Location) || pkm.IsEgg)
|
||||
yield break;
|
||||
|
||||
var possibleAreas = GetEncounterAreas(pkm, gameSource);
|
||||
|
@ -150,6 +151,8 @@ namespace PKHeX.Core
|
|||
GO => GetEncounterTableGO(pkm),
|
||||
SW => SlotsSW,
|
||||
SH => SlotsSH,
|
||||
BD => SlotsBD,
|
||||
SP => SlotsSP,
|
||||
_ => Array.Empty<EncounterArea>(),
|
||||
};
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ using static PKHeX.Core.Encounters6;
|
|||
using static PKHeX.Core.Encounters7;
|
||||
using static PKHeX.Core.Encounters7b;
|
||||
using static PKHeX.Core.Encounters8;
|
||||
using static PKHeX.Core.Encounters8b;
|
||||
|
||||
using static PKHeX.Core.GameVersion;
|
||||
|
||||
|
@ -172,6 +173,8 @@ namespace PKHeX.Core
|
|||
|
||||
SW => StaticSW,
|
||||
SH => StaticSH,
|
||||
BD => StaticBD,
|
||||
SP => StaticSP,
|
||||
_ => Array.Empty<EncounterStatic>(),
|
||||
};
|
||||
|
||||
|
|
|
@ -95,6 +95,7 @@ namespace PKHeX.Core
|
|||
US or UM => Encounters7.TradeGift_USUM,
|
||||
GP or GE => Encounters7b.TradeGift_GG,
|
||||
SW or SH => Encounters8.TradeGift_SWSH,
|
||||
BD or SP => Encounters8b.TradeGift_BDSP,
|
||||
_ => Array.Empty<EncounterTrade>(),
|
||||
};
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace PKHeX.Core
|
|||
5 => MGDB_G5,
|
||||
6 => MGDB_G6,
|
||||
7 => pkm.LGPE ? MGDB_G7GG : MGDB_G7,
|
||||
8 => MGDB_G8,
|
||||
8 => pkm.BDSP ? MGDB_G8B : MGDB_G8,
|
||||
_ => Array.Empty<MysteryGift>(),
|
||||
};
|
||||
|
||||
|
|
|
@ -50,14 +50,15 @@ namespace PKHeX.Core
|
|||
|
||||
public static int GetSuggestedEncounterEggLocationEgg(PKM pkm, bool traded = false)
|
||||
{
|
||||
return GetSuggestedEncounterEggLocationEgg(pkm.Generation, traded);
|
||||
return GetSuggestedEncounterEggLocationEgg(pkm.Generation, (GameVersion)pkm.Version, traded);
|
||||
}
|
||||
|
||||
public static int GetSuggestedEncounterEggLocationEgg(int generation, bool traded = false) => generation switch
|
||||
public static int GetSuggestedEncounterEggLocationEgg(int generation, GameVersion version, bool traded = false) => generation switch
|
||||
{
|
||||
1 or 2 or 3 => 0,
|
||||
4 => traded ? Locations.LinkTrade4 : Locations.Daycare4,
|
||||
5 => traded ? Locations.LinkTrade5 : Locations.Daycare5,
|
||||
8 when BDSP.Contains(version)=> traded ? Locations.LinkTrade6NPC : Locations.Daycare8b,
|
||||
_ => traded ? Locations.LinkTrade6 : Locations.Daycare5,
|
||||
};
|
||||
|
||||
|
@ -100,6 +101,7 @@ namespace PKHeX.Core
|
|||
GSC or RBY => pkm.Met_Level == 0 ? 0 : Locations.HatchLocationC,
|
||||
|
||||
SW or SH => Locations.HatchLocation8,
|
||||
BD or SP => Locations.HatchLocation8b,
|
||||
_ => -1,
|
||||
};
|
||||
|
||||
|
|
|
@ -81,6 +81,7 @@ namespace PKHeX.Core
|
|||
5 => pkm.IsEgg ? VerifyUnhatchedEgg(pkm, Locations.LinkTrade5) : VerifyEncounterEgg5(pkm),
|
||||
6 => pkm.IsEgg ? VerifyUnhatchedEgg(pkm, Locations.LinkTrade6) : VerifyEncounterEgg6(pkm),
|
||||
7 => pkm.IsEgg ? VerifyUnhatchedEgg(pkm, Locations.LinkTrade6) : VerifyEncounterEgg7(pkm),
|
||||
8 when GameVersion.BDSP.Contains((GameVersion)pkm.Version) => pkm.IsEgg ? VerifyUnhatchedEgg(pkm, Locations.LinkTrade6NPC, Locations.Default8bNone) : VerifyEncounterEgg8BDSP(pkm),
|
||||
8 => pkm.IsEgg ? VerifyUnhatchedEgg(pkm, Locations.LinkTrade6) : VerifyEncounterEgg8(pkm),
|
||||
_ => new CheckResult(Severity.Invalid, LEggLocationInvalid, CheckIdentifier.Encounter),
|
||||
};
|
||||
|
@ -199,6 +200,15 @@ namespace PKHeX.Core
|
|||
return new CheckResult(Severity.Invalid, LEggLocationInvalid, CheckIdentifier.Encounter);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterEgg8BDSP(PKM pkm)
|
||||
{
|
||||
if (pkm.BDSP)
|
||||
return VerifyEncounterEggLevelLoc(pkm, 1, Legal.ValidMet_BDSP);
|
||||
|
||||
// no other games
|
||||
return new CheckResult(Severity.Invalid, LEggLocationInvalid, CheckIdentifier.Encounter);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyEncounterEggLevelLoc(PKM pkm, int eggLevel, ICollection<int> MetLocations)
|
||||
{
|
||||
if (pkm.Met_Level != eggLevel)
|
||||
|
@ -208,7 +218,7 @@ namespace PKHeX.Core
|
|||
: new CheckResult(Severity.Invalid, LEggLocationInvalid, CheckIdentifier.Encounter);
|
||||
}
|
||||
|
||||
private static CheckResult VerifyUnhatchedEgg(PKM pkm, int tradeLoc)
|
||||
private static CheckResult VerifyUnhatchedEgg(PKM pkm, int tradeLoc, short noneLoc = 0)
|
||||
{
|
||||
var eggLevel = pkm.Format < 5 ? 0 : 1;
|
||||
if (pkm.Met_Level != eggLevel)
|
||||
|
@ -219,7 +229,7 @@ namespace PKHeX.Core
|
|||
var met = pkm.Met_Location;
|
||||
if (met == tradeLoc)
|
||||
return new CheckResult(Severity.Valid, LEggLocationTrade, CheckIdentifier.Encounter);
|
||||
return met == 0
|
||||
return (short)met == noneLoc
|
||||
? new CheckResult(Severity.Valid, LEggUnhatched, CheckIdentifier.Encounter)
|
||||
: new CheckResult(Severity.Invalid, LEggLocationNone, CheckIdentifier.Encounter);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using static PKHeX.Core.LegalityCheckStrings;
|
||||
using static PKHeX.Core.ParseSettings;
|
||||
|
||||
|
@ -22,7 +21,8 @@ namespace PKHeX.Core
|
|||
{
|
||||
IRelearn s when s.Relearn.Count != 0 => VerifyRelearnSpecifiedMoveset(pkm, s.Relearn, result),
|
||||
EncounterEgg e => VerifyEggMoveset(e, result, pkm.RelearnMoves),
|
||||
EncounterSlot6AO z when pkm.RelearnMove1 != 0 && z.CanDexNav => VerifyRelearnDexNav(pkm, result),
|
||||
EncounterSlot6AO z when pkm.RelearnMove1 != 0 && z.CanDexNav => VerifyRelearnDexNav(pkm, result, z),
|
||||
EncounterSlot8b {IsUnderground:true} u => VerifyRelearnUnderground(pkm, result, u),
|
||||
_ => VerifyRelearnNone(pkm, result),
|
||||
};
|
||||
}
|
||||
|
@ -45,13 +45,10 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
private static CheckResult[] VerifyRelearnDexNav(PKM pkm, CheckResult[] result)
|
||||
private static CheckResult[] VerifyRelearnDexNav(PKM pkm, CheckResult[] result, EncounterSlot6AO slot)
|
||||
{
|
||||
// DexNav Pokémon can have 1 random egg move as a relearn move.
|
||||
var baseSpec = EvoBase.GetBaseSpecies(pkm);
|
||||
var firstRelearn = pkm.RelearnMove1;
|
||||
var eggMoves = MoveEgg.GetEggMoves(6, baseSpec.Species, baseSpec.Form, GameVersion.OR);
|
||||
result[0] = Array.IndexOf(eggMoves, firstRelearn) == -1 // not found
|
||||
result[0] = !slot.CanBeDexNavMove(pkm.RelearnMove1) // not found
|
||||
? new CheckResult(Severity.Invalid, LMoveRelearnDexNav, CheckIdentifier.RelearnMove)
|
||||
: DummyValid;
|
||||
|
||||
|
@ -63,6 +60,21 @@ namespace PKHeX.Core
|
|||
return result;
|
||||
}
|
||||
|
||||
private static CheckResult[] VerifyRelearnUnderground(PKM pkm, CheckResult[] result, EncounterSlot8b slot)
|
||||
{
|
||||
// Underground Pokémon can have 1 random egg move as a relearn move.
|
||||
result[0] = !slot.CanBeUndergroundMove(pkm.RelearnMove1) // not found
|
||||
? new CheckResult(Severity.Invalid, LMoveRelearnUnderground, CheckIdentifier.RelearnMove)
|
||||
: DummyValid;
|
||||
|
||||
// All other relearn moves must be empty.
|
||||
result[3] = pkm.RelearnMove4 == 0 ? DummyValid : DummyNone;
|
||||
result[2] = pkm.RelearnMove3 == 0 ? DummyValid : DummyNone;
|
||||
result[1] = pkm.RelearnMove2 == 0 ? DummyValid : DummyNone;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static CheckResult[] VerifyRelearnNone(PKM pkm, CheckResult[] result)
|
||||
{
|
||||
// No relearn moves should be present.
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace PKHeX.Core
|
|||
private static readonly EvolutionTree Evolves7 = new(Unpack("uu"), Gen7, PersonalTable.USUM, MaxSpeciesID_7_USUM);
|
||||
private static readonly EvolutionTree Evolves7b = new(Unpack("gg"), Gen7, PersonalTable.GG, MaxSpeciesID_7b);
|
||||
private static readonly EvolutionTree Evolves8 = new(Unpack("ss"), Gen8, PersonalTable.SWSH, MaxSpeciesID_8);
|
||||
internal static readonly EvolutionTree Evolves8b = new(Unpack("bs"), Gen8, PersonalTable.BDSP, MaxSpeciesID_8b);
|
||||
|
||||
private static byte[] Get(string resource) => Util.GetBinaryResource($"evos_{resource}.pkl");
|
||||
private static byte[][] Unpack(string resource) => BinLinker.Unpack(Get(resource), resource);
|
||||
|
@ -32,6 +33,7 @@ namespace PKHeX.Core
|
|||
// Add in banned evolution data!
|
||||
Evolves7.FixEvoTreeSM();
|
||||
Evolves8.FixEvoTreeSS();
|
||||
Evolves8b.FixEvoTreeBS();
|
||||
}
|
||||
|
||||
public static EvolutionTree GetEvolutionTree(int generation) => generation switch
|
||||
|
@ -55,7 +57,7 @@ namespace PKHeX.Core
|
|||
5 => Evolves5,
|
||||
6 => Evolves6,
|
||||
7 => pkm.Version is (int)GO or (int)GP or (int)GE ? Evolves7b : Evolves7,
|
||||
_ => Evolves8,
|
||||
_ => pkm.Version is (int)BD or (int)SP ? Evolves8b : Evolves8,
|
||||
};
|
||||
|
||||
private readonly IReadOnlyList<EvolutionMethod[]> Entries;
|
||||
|
@ -172,6 +174,12 @@ namespace PKHeX.Core
|
|||
BanEvo(s, 0, pkm => pkm is IGigantamax {CanGigantamax: true});
|
||||
}
|
||||
|
||||
private void FixEvoTreeBS()
|
||||
{
|
||||
// Eevee is programmed to evolve into Glaceon via Ice Stone or level up at the Ice Rock, but Ice Stone is unreleased.
|
||||
BanEvo((int)Species.Glaceon, 0, pkm => pkm.CurrentLevel == pkm.Met_Level);
|
||||
}
|
||||
|
||||
private void BanEvo(int species, int form, Func<PKM, bool> func)
|
||||
{
|
||||
var key = GetLookupKey(species, form);
|
||||
|
|
|
@ -354,6 +354,7 @@ namespace PKHeX.Core
|
|||
public static string LMoveSourceSharedF { get; set; } = "Shared Non-Relearn Move in Generation {0}.";
|
||||
|
||||
public static string LMoveRelearnDexNav { get; set; } = "Not an expected DexNav move.";
|
||||
public static string LMoveRelearnUnderground { get; set; } = "Not an expected Underground egg move.";
|
||||
public static string LMoveRelearnEgg { get; set; } = "Base Egg move.";
|
||||
public static string LMoveRelearnEggMissing { get; set; } = "Base Egg move missing.";
|
||||
public static string LMoveRelearnFExpect_0 { get; set; } = "Expected the following Relearn Moves: {0} ({1}";
|
||||
|
|
|
@ -141,6 +141,14 @@ namespace PKHeX.Core
|
|||
return LevelUpSWSH[index].GetMoves(lvl);
|
||||
}
|
||||
break;
|
||||
|
||||
case BD or SP or BDSP:
|
||||
if (pkm.InhabitedGeneration(8))
|
||||
{
|
||||
int index = PersonalTable.SWSH.GetFormIndex(species, form);
|
||||
return LevelUpBDSP[index].GetMoves(lvl);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return Array.Empty<int>();
|
||||
}
|
||||
|
@ -165,11 +173,20 @@ namespace PKHeX.Core
|
|||
internal static IEnumerable<int> GetValidMoves(PKM pkm, IReadOnlyList<EvoCriteria> evoChain, int generation, MoveSourceType types = MoveSourceType.ExternalSources, bool RemoveTransferHM = true)
|
||||
{
|
||||
GameVersion version = (GameVersion)pkm.Version;
|
||||
if (!pkm.IsUntraded)
|
||||
if (!pkm.IsUntraded && !IsLandlockedFormat(pkm))
|
||||
version = Any;
|
||||
return GetValidMoves(pkm, version, evoChain, generation, types: types, RemoveTransferHM: RemoveTransferHM);
|
||||
}
|
||||
|
||||
private static bool IsLandlockedFormat(PKM pkm)
|
||||
{
|
||||
if (pkm.BDSP)
|
||||
return true;
|
||||
if (pkm.LGPE)
|
||||
return pkm.Format == 7;
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static IEnumerable<int> GetValidRelearn(PKM pkm, int species, int form, GameVersion version = Any)
|
||||
{
|
||||
return GetValidRelearn(pkm, species, form, Breeding.GetCanInheritMoves(species), version);
|
||||
|
|
|
@ -43,6 +43,7 @@ namespace PKHeX.Core
|
|||
GO or GP or GE or GG => Legal.LevelUpGG,
|
||||
|
||||
SW or SH or SWSH => Legal.LevelUpSWSH,
|
||||
BD or SP or BDSP => Legal.LevelUpBDSP,
|
||||
|
||||
Gen1 => Legal.LevelUpY,
|
||||
Gen2 => Legal.LevelUpC,
|
||||
|
@ -86,6 +87,7 @@ namespace PKHeX.Core
|
|||
GO or GP or GE or GG => PersonalTable.GG,
|
||||
|
||||
SW or SH or SWSH => PersonalTable.SWSH,
|
||||
BD or SP or BDSP => PersonalTable.BDSP,
|
||||
|
||||
Gen1 => PersonalTable.Y,
|
||||
Gen2 => PersonalTable.C,
|
||||
|
|
|
@ -34,7 +34,8 @@ namespace PKHeX.Core
|
|||
|
||||
7 when version is SN or MN => GetFormEggMoves(species, form, EggMovesSM),
|
||||
7 when version is US or UM => GetFormEggMoves(species, form, EggMovesUSUM),
|
||||
8 => GetFormEggMoves(species, form, EggMovesSWSH),
|
||||
8 when version is SW or SH => GetFormEggMoves(species, form, EggMovesSWSH),
|
||||
8 when version is BD or SP => GetFormEggMoves(species, form, EggMovesBDSP),
|
||||
_ => Array.Empty<int>(),
|
||||
};
|
||||
|
||||
|
@ -59,6 +60,7 @@ namespace PKHeX.Core
|
|||
SN or MN when species <= MaxSpeciesID_7 => getMoves(LevelUpSM, PersonalTable.SM),
|
||||
US or UM => getMoves(LevelUpUSUM, PersonalTable.USUM),
|
||||
SW or SH => getMoves(LevelUpSWSH, PersonalTable.SWSH),
|
||||
BD or SP => getMoves(LevelUpBDSP, PersonalTable.BDSP),
|
||||
_ => Array.Empty<int>(),
|
||||
};
|
||||
|
||||
|
@ -77,11 +79,22 @@ namespace PKHeX.Core
|
|||
{
|
||||
if (gen < 8 || pkm.IsEgg)
|
||||
return Array.Empty<int>();
|
||||
var table = PersonalTable.SWSH;
|
||||
var entry = (PersonalInfoSWSH)table.GetFormEntry(pkm.Species, pkm.Form);
|
||||
var baseSpecies = entry.HatchSpecies;
|
||||
var baseForm = entry.HatchFormIndexEverstone;
|
||||
return GetEggMoves(8, baseSpecies, baseForm, SW);
|
||||
if (pkm.BDSP)
|
||||
{
|
||||
var table = PersonalTable.BDSP;
|
||||
var entry = (PersonalInfoBDSP)table.GetFormEntry(pkm.Species, pkm.Form);
|
||||
var baseSpecies = entry.HatchSpecies;
|
||||
var baseForm = entry.HatchFormIndex;
|
||||
return GetEggMoves(8, baseSpecies, baseForm, BD);
|
||||
}
|
||||
else
|
||||
{
|
||||
var table = PersonalTable.SWSH;
|
||||
var entry = (PersonalInfoSWSH)table.GetFormEntry(pkm.Species, pkm.Form);
|
||||
var baseSpecies = entry.HatchSpecies;
|
||||
var baseForm = entry.HatchFormIndexEverstone;
|
||||
return GetEggMoves(8, baseSpecies, baseForm, SW);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace PKHeX.Core
|
|||
public static class MoveLevelUp
|
||||
{
|
||||
private static readonly LearnLookup
|
||||
LearnBDSP = new(PersonalTable.BDSP, LevelUpBDSP, BDSP),
|
||||
LearnSWSH = new(PersonalTable.SWSH, LevelUpSWSH, SWSH),
|
||||
LearnSM = new(PersonalTable.SM, LevelUpSM, SM),
|
||||
LearnUSUM = new(PersonalTable.USUM, LevelUpUSUM, USUM),
|
||||
|
@ -213,6 +214,11 @@ namespace PKHeX.Core
|
|||
if (species > MaxSpeciesID_8)
|
||||
return LearnNONE;
|
||||
return LearnSWSH.GetIsLevelUp(species, form, move, maxLevel);
|
||||
|
||||
case BD or SP or BDSP:
|
||||
if (species > MaxSpeciesID_8b)
|
||||
return LearnNONE;
|
||||
return LearnBDSP.GetIsLevelUp(species, form, move, maxLevel);
|
||||
}
|
||||
return LearnNONE;
|
||||
}
|
||||
|
@ -471,6 +477,11 @@ namespace PKHeX.Core
|
|||
if (species > MaxSpeciesID_8)
|
||||
return moves;
|
||||
return LearnSWSH.AddMoves(moves, species, form, maxLevel);
|
||||
|
||||
case BD or SP or BDSP:
|
||||
if (species > MaxSpeciesID_8b)
|
||||
return moves;
|
||||
return LearnBDSP.AddMoves(moves, species, form, maxLevel);
|
||||
}
|
||||
return moves;
|
||||
}
|
||||
|
|
|
@ -243,6 +243,18 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
if (GameVersion.BDSP.Contains(ver))
|
||||
{
|
||||
for (int i = 0; i < PersonalInfoSWSH.CountTM; i++)
|
||||
{
|
||||
if (Legal.TMHM_BDSP[i] != move)
|
||||
continue;
|
||||
if (PersonalTable.BDSP.GetFormEntry(species, form).TMHM[i])
|
||||
return GameVersion.BDSP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Legal.NONE;
|
||||
}
|
||||
|
||||
|
@ -260,7 +272,7 @@ namespace PKHeX.Core
|
|||
break;
|
||||
if (allowBit)
|
||||
return GameVersion.SWSH;
|
||||
if (((PK8)pkm).GetMoveRecordFlag(i))
|
||||
if (((G8PKM)pkm).GetMoveRecordFlag(i))
|
||||
return GameVersion.SWSH;
|
||||
if (i == 12 && species == (int)Species.Calyrex && form == 0) // TR12
|
||||
return GameVersion.SWSH; // Agility Calyrex without TR glitch.
|
||||
|
@ -409,6 +421,9 @@ namespace PKHeX.Core
|
|||
case GameVersion.Any:
|
||||
case GameVersion.SW or GameVersion.SH or GameVersion.SWSH:
|
||||
AddMachineSWSH(r, species, form);
|
||||
break;
|
||||
case GameVersion.BD or GameVersion.SP or GameVersion.BDSP:
|
||||
AddMachineBDSP(r, species, form);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -461,11 +476,20 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
private static void AddMachineBDSP(List<int> r, int species, int form)
|
||||
{
|
||||
if (species > Legal.MaxSpeciesID_8b)
|
||||
return;
|
||||
var pi = PersonalTable.BDSP.GetFormEntry(species, form);
|
||||
r.AddRange(Legal.TMHM_BDSP.Where((_, m) => pi.TMHM[m]));
|
||||
}
|
||||
|
||||
public static void AddRecordSWSH(List<int> r, int species, int form, PKM pkm)
|
||||
{
|
||||
if (pkm is not PK8 pk8)
|
||||
return;
|
||||
var pi = PersonalTable.SWSH.GetFormEntry(species, form);
|
||||
var tmhm = pi.TMHM;
|
||||
var pk8 = (PK8)pkm;
|
||||
for (int i = 0; i < PersonalInfoSWSH.CountTR; i++)
|
||||
{
|
||||
var index = i + PersonalInfoSWSH.CountTM;
|
||||
|
|
73
PKHeX.Core/Legality/RNG/Algorithms/Xoroshiro128Plus8b.cs
Normal file
73
PKHeX.Core/Legality/RNG/Algorithms/Xoroshiro128Plus8b.cs
Normal file
|
@ -0,0 +1,73 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Self-modifying RNG structure that implements xoroshiro128+ which split-mixes the initial seed to populate all 128-bits of the initial state, rather than using a fixed 64-bit half.
|
||||
/// </summary>
|
||||
/// <remarks>https://en.wikipedia.org/wiki/Xoroshiro128%2B</remarks>
|
||||
/// <seealso cref="Xoroshiro128Plus"/>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1815:Override equals and operator equals on value types", Justification = "Unused")]
|
||||
public ref struct Xoroshiro128Plus8b
|
||||
{
|
||||
private ulong s0, s1;
|
||||
|
||||
public Xoroshiro128Plus8b(ulong seed)
|
||||
{
|
||||
var _s0 = seed - 0x61C8864680B583EB;
|
||||
var _s1 = seed + 0x3C6EF372FE94F82A;
|
||||
|
||||
_s0 = 0xBF58476D1CE4E5B9 * (_s0 ^ (_s0 >> 30));
|
||||
_s1 = 0xBF58476D1CE4E5B9 * (_s1 ^ (_s1 >> 30));
|
||||
|
||||
_s0 = 0x94D049BB133111EB * (_s0 ^ (_s0 >> 27));
|
||||
_s1 = 0x94D049BB133111EB * (_s1 ^ (_s1 >> 27));
|
||||
|
||||
s0 = _s0 ^ (_s0 >> 31);
|
||||
s1 = _s1 ^ (_s1 >> 31);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ulong RotateLeft(ulong x, int k)
|
||||
{
|
||||
return (x << k) | (x >> (64 - k));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the next random <see cref="ulong"/>.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ulong Next()
|
||||
{
|
||||
var _s0 = s0;
|
||||
var _s1 = s1;
|
||||
ulong result = _s0 + _s1;
|
||||
|
||||
_s1 ^= _s0;
|
||||
// Final calculations and store back to fields
|
||||
s0 = RotateLeft(_s0, 24) ^ _s1 ^ (_s1 << 16);
|
||||
s1 = RotateLeft(_s1, 37);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool NextBool() => (Next() >> 63) != 0;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public byte NextByte() => (byte)(Next() >> 56);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ushort UShort() => (ushort)(Next() >> 48);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public uint NextUInt() => (uint)(Next() >> 32);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public uint NextUInt(uint max)
|
||||
{
|
||||
var rnd = NextUInt();
|
||||
return rnd - ((rnd / max) * max);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -183,6 +183,12 @@ namespace PKHeX.Core
|
|||
/// <remarks>Formulaic based on PID & EC values from a 32bit-seed.</remarks>
|
||||
Overworld8,
|
||||
|
||||
/// <summary>
|
||||
/// Generation 8b Roaming Pokemon PID
|
||||
/// </summary>
|
||||
/// <remarks>Formulaic based on EC value = 32bit-seed.</remarks>
|
||||
Roaming8b,
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
|
240
PKHeX.Core/Legality/RNG/Roaming8bRNG.cs
Normal file
240
PKHeX.Core/Legality/RNG/Roaming8bRNG.cs
Normal file
|
@ -0,0 +1,240 @@
|
|||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains logic for the Generation 8b (BD/SP) roaming spawns.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Roaming encounters use the pokemon's 32-bit <see cref="PKM.EncryptionConstant"/> as RNG seed.
|
||||
/// </remarks>
|
||||
public static class Roaming8bRNG
|
||||
{
|
||||
private const int NoMatchIVs = -1;
|
||||
private const int UNSET = -1;
|
||||
|
||||
public static void ApplyDetails(PKM pk, EncounterCriteria criteria, Shiny shiny = Shiny.FixedValue, int flawless = -1)
|
||||
{
|
||||
if (shiny == Shiny.FixedValue)
|
||||
shiny = criteria.Shiny is Shiny.Random or Shiny.Never ? Shiny.Never : Shiny.Always;
|
||||
if (flawless == -1)
|
||||
flawless = 0;
|
||||
|
||||
int ctr = 0;
|
||||
const int maxAttempts = 50_000;
|
||||
var rnd = Util.Rand;
|
||||
do
|
||||
{
|
||||
var seed = Util.Rand32(rnd);
|
||||
if (TryApplyFromSeed(pk, criteria, shiny, flawless, seed))
|
||||
return;
|
||||
} while (++ctr != maxAttempts);
|
||||
TryApplyFromSeed(pk, EncounterCriteria.Unrestricted, shiny, flawless, Util.Rand32(rnd));
|
||||
}
|
||||
|
||||
private static bool TryApplyFromSeed(PKM pk, EncounterCriteria criteria, Shiny shiny, int flawless, uint seed)
|
||||
{
|
||||
var xoro = new Xoroshiro128Plus8b(seed);
|
||||
|
||||
// Encryption Constant
|
||||
pk.EncryptionConstant = seed;
|
||||
var _ = xoro.NextUInt(); // fakeTID
|
||||
|
||||
// PID
|
||||
var pid = xoro.NextUInt();
|
||||
if (shiny == Shiny.Never)
|
||||
{
|
||||
if (GetIsShiny(pk.TID, pk.SID, pid))
|
||||
return false;
|
||||
}
|
||||
else if (shiny != Shiny.Random)
|
||||
{
|
||||
if (!GetIsShiny(pk.TID, pk.SID, pid))
|
||||
return false;
|
||||
|
||||
if (shiny == Shiny.AlwaysSquare && pk.ShinyXor != 0)
|
||||
return false;
|
||||
if (shiny == Shiny.AlwaysStar && pk.ShinyXor == 0)
|
||||
return false;
|
||||
}
|
||||
pk.PID = pid;
|
||||
|
||||
// Check IVs: Create flawless IVs at random indexes, then the random IVs for not flawless.
|
||||
int[] ivs = { UNSET, UNSET, UNSET, UNSET, UNSET, UNSET };
|
||||
const int MAX = 31;
|
||||
var determined = 0;
|
||||
while (determined < flawless)
|
||||
{
|
||||
var idx = xoro.NextUInt(6);
|
||||
if (ivs[idx] != UNSET)
|
||||
continue;
|
||||
ivs[idx] = 31;
|
||||
determined++;
|
||||
}
|
||||
|
||||
for (var i = 0; i < ivs.Length; i++)
|
||||
{
|
||||
if (ivs[i] == UNSET)
|
||||
ivs[i] = (int)xoro.NextUInt(MAX + 1);
|
||||
}
|
||||
|
||||
if (!criteria.IsIVsCompatible(ivs, 8))
|
||||
return false;
|
||||
|
||||
pk.IV_HP = ivs[0];
|
||||
pk.IV_ATK = ivs[1];
|
||||
pk.IV_DEF = ivs[2];
|
||||
pk.IV_SPA = ivs[3];
|
||||
pk.IV_SPD = ivs[4];
|
||||
pk.IV_SPE = ivs[5];
|
||||
|
||||
// Ability
|
||||
pk.SetAbilityIndex((int)xoro.NextUInt(2));
|
||||
|
||||
// Remainder
|
||||
var scale = (IScaledSize)pk;
|
||||
scale.HeightScalar = (int)xoro.NextUInt(0x81) + (int)xoro.NextUInt(0x80);
|
||||
scale.WeightScalar = (int)xoro.NextUInt(0x81) + (int)xoro.NextUInt(0x80);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool ValidateRoamingEncounter(PKM pk, Shiny shiny = Shiny.Random, int flawless = 0)
|
||||
{
|
||||
var seed = pk.EncryptionConstant;
|
||||
var xoro = new Xoroshiro128Plus8b(seed);
|
||||
|
||||
// Check PID
|
||||
var _ = xoro.NextUInt(); // fakeTID
|
||||
var pid = xoro.NextUInt();
|
||||
if (pk.PID != pid)
|
||||
return false;
|
||||
|
||||
// Check IVs: Create flawless IVs at random indexes, then the random IVs for not flawless.
|
||||
int[] ivs = { UNSET, UNSET, UNSET, UNSET, UNSET, UNSET };
|
||||
|
||||
var determined = 0;
|
||||
while (determined < flawless)
|
||||
{
|
||||
var idx = xoro.NextUInt(6);
|
||||
if (ivs[idx] != UNSET)
|
||||
continue;
|
||||
ivs[idx] = 31;
|
||||
determined++;
|
||||
}
|
||||
|
||||
for (var i = 0; i < ivs.Length; i++)
|
||||
{
|
||||
if (ivs[i] == UNSET)
|
||||
ivs[i] = (int)xoro.NextUInt(31 + 1);
|
||||
}
|
||||
|
||||
if (ivs[0] != pk.GetIV(0)) return false;
|
||||
if (ivs[1] != pk.GetIV(1)) return false;
|
||||
if (ivs[2] != pk.GetIV(2)) return false;
|
||||
if (ivs[3] != pk.GetIV(4)) return false;
|
||||
if (ivs[4] != pk.GetIV(5)) return false;
|
||||
if (ivs[5] != pk.GetIV(3)) return false;
|
||||
|
||||
// Don't check Hidden ability, as roaming encounters are 1/2 only.
|
||||
if (pk.AbilityNumber != (1 << (int)xoro.NextUInt(2)))
|
||||
return false;
|
||||
|
||||
return GetIsMatchEnd(pk, xoro) || GetIsMatchEndWithCuteCharm(pk, xoro) || GetIsMatchEndWithSynchronize(pk, xoro);
|
||||
}
|
||||
|
||||
private static bool GetIsMatchEnd(PKM pk, Xoroshiro128Plus8b xoro)
|
||||
{
|
||||
// Check that gender matches
|
||||
var genderRatio = PersonalTable.BDSP.GetFormEntry(pk.Species, pk.Form).Gender;
|
||||
if (genderRatio == PersonalInfo.RatioMagicGenderless)
|
||||
{
|
||||
if (pk.Gender != (int)Gender.Genderless)
|
||||
return false;
|
||||
}
|
||||
else if (genderRatio == PersonalInfo.RatioMagicMale)
|
||||
{
|
||||
if (pk.Gender != (int)Gender.Male)
|
||||
return false;
|
||||
}
|
||||
else if (genderRatio == PersonalInfo.RatioMagicFemale)
|
||||
{
|
||||
if (pk.Gender != (int)Gender.Female)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pk.Gender != (((int)xoro.NextUInt(253) + 1 < genderRatio) ? 1 : 0))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that the nature matches
|
||||
if (pk.Nature != (int)xoro.NextUInt(25))
|
||||
return false;
|
||||
|
||||
return GetIsHeightWeightMatch(pk, xoro);
|
||||
}
|
||||
|
||||
private static bool GetIsMatchEndWithCuteCharm(PKM pk, Xoroshiro128Plus8b xoro)
|
||||
{
|
||||
// Check that gender matches
|
||||
// Assume that the gender is a match due to cute charm.
|
||||
|
||||
// Check that the nature matches
|
||||
if (pk.Nature != (int)xoro.NextUInt(25))
|
||||
return false;
|
||||
|
||||
return GetIsHeightWeightMatch(pk, xoro);
|
||||
}
|
||||
|
||||
private static bool GetIsMatchEndWithSynchronize(PKM pk, Xoroshiro128Plus8b xoro)
|
||||
{
|
||||
// Check that gender matches
|
||||
var genderRatio = PersonalTable.BDSP.GetFormEntry(pk.Species, pk.Form).Gender;
|
||||
if (genderRatio == PersonalInfo.RatioMagicGenderless)
|
||||
{
|
||||
if (pk.Gender != (int)Gender.Genderless)
|
||||
return false;
|
||||
}
|
||||
else if (genderRatio == PersonalInfo.RatioMagicMale)
|
||||
{
|
||||
if (pk.Gender != (int)Gender.Male)
|
||||
return false;
|
||||
}
|
||||
else if (genderRatio == PersonalInfo.RatioMagicFemale)
|
||||
{
|
||||
if (pk.Gender != (int)Gender.Female)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pk.Gender != (((int)xoro.NextUInt(253) + 1 < genderRatio) ? 1 : 0))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Assume that the nature is a match due to synchronize.
|
||||
|
||||
return GetIsHeightWeightMatch(pk, xoro);
|
||||
}
|
||||
|
||||
private static bool GetIsHeightWeightMatch(PKM pk, Xoroshiro128Plus8b xoro)
|
||||
{
|
||||
// Check height/weight
|
||||
if (pk is not IScaledSize s)
|
||||
return false;
|
||||
|
||||
var height = xoro.NextUInt(0x81) + xoro.NextUInt(0x80);
|
||||
var weight = xoro.NextUInt(0x81) + xoro.NextUInt(0x80);
|
||||
return s.HeightScalar == height && s.WeightScalar == weight;
|
||||
}
|
||||
|
||||
private static bool GetIsShiny(int tid, int sid, uint pid)
|
||||
{
|
||||
return GetShinyXor(pid, (uint)((sid << 16) | tid)) < 16;
|
||||
}
|
||||
|
||||
private static uint GetShinyXor(uint pid, uint oid)
|
||||
{
|
||||
var xor = pid ^ oid;
|
||||
return (xor ^ (xor >> 16)) & 0xFFFF;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -86,10 +86,10 @@ namespace PKHeX.Core
|
|||
new byte[] { 00, 00, 00, 00, 00, 29, 09, 02, 02 }, // Sylveon (Eevee with Fairy Move)
|
||||
new byte[] { 00, 00, 00, 00, 18, 15, 15, 02, 32 }, // Mr. Mime (Mime Jr with Mimic)
|
||||
new byte[] { 00, 00, 00, 00, 17, 17, 15, 02, 16 }, // Sudowoodo (Bonsly with Mimic)
|
||||
new byte[] { 00, 00, 00, 00, 32, 32, 32, 02, 00 }, // Ambipom (Aipom with Double Hit)
|
||||
new byte[] { 00, 00, 00, 00, 32, 32, 32, 02, 32 }, // Ambipom (Aipom with Double Hit)
|
||||
new byte[] { 00, 00, 02, 00, 02, 33, 33, 02, 06 }, // Lickilicky (Lickitung with Rollout)
|
||||
new byte[] { 00, 00, 00, 00, 02, 36, 38, 02, 24 }, // Tangrowth (Tangela with Ancient Power)
|
||||
new byte[] { 00, 00, 00, 00, 02, 33, 33, 02, 00 }, // Yanmega (Yanma with Ancient Power)
|
||||
new byte[] { 00, 00, 00, 00, 02, 33, 33, 02, 33 }, // Yanmega (Yanma with Ancient Power)
|
||||
new byte[] { 00, 00, 00, 00, 02, 02, 02, 02, 02 }, // Mamoswine (Piloswine with Ancient Power)
|
||||
new byte[] { 00, 00, 00, 00, 00, 00, 00, 02, 28 }, // Tsareena (Steenee with Stomp)
|
||||
new byte[] { 00, 00, 00, 00, 00, 00, 00, 00, 35 }, // Grapploct (Clobbopus with Taunt)
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace PKHeX.Core
|
|||
{
|
||||
if (pk is PB7 pb7) // no held items in game
|
||||
return pb7.HeldItem == 0;
|
||||
return IsHeldItemAllowed(pk.HeldItem, pk.Format);
|
||||
return IsHeldItemAllowed(pk.HeldItem, pk.Format, pk);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -28,15 +28,15 @@ namespace PKHeX.Core
|
|||
/// <param name="item">Held Item ID</param>
|
||||
/// <param name="generation">Generation Number</param>
|
||||
/// <returns>True if able to be held, false if not</returns>
|
||||
public static bool IsHeldItemAllowed(int item, int generation)
|
||||
public static bool IsHeldItemAllowed(int item, int generation, PKM pk)
|
||||
{
|
||||
if (item == 0)
|
||||
return true;
|
||||
var items = GetReleasedHeldItems(generation);
|
||||
var items = GetReleasedHeldItems(generation, pk);
|
||||
return (uint)item < items.Count && items[item];
|
||||
}
|
||||
|
||||
private static IReadOnlyList<bool> GetReleasedHeldItems(int generation) => generation switch
|
||||
private static IReadOnlyList<bool> GetReleasedHeldItems(int generation, PKM pk) => generation switch
|
||||
{
|
||||
2 => ReleasedHeldItems_2,
|
||||
3 => ReleasedHeldItems_3,
|
||||
|
@ -44,6 +44,7 @@ namespace PKHeX.Core
|
|||
5 => ReleasedHeldItems_5,
|
||||
6 => ReleasedHeldItems_6,
|
||||
7 => ReleasedHeldItems_7,
|
||||
8 when pk is PB8 => ReleasedHeldItems_8b,
|
||||
8 => ReleasedHeldItems_8,
|
||||
_ => Array.Empty<bool>(),
|
||||
};
|
||||
|
|
|
@ -136,7 +136,7 @@ namespace PKHeX.Core
|
|||
return false;
|
||||
return gen switch
|
||||
{
|
||||
8 => move <= Legal.MaxMoveID_8_R2 && !Legal.DummiedMoves_SWSH.Contains(move),
|
||||
8 => move <= Legal.MaxMoveID_8_R2 && !Legal.GetDummiedMovesHashSet(pkm).Contains(move),
|
||||
_ => move <= Legal.MaxMoveID_6_AO,
|
||||
};
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ namespace PKHeX.Core
|
|||
private static bool IsSpecialEncounterMoveEggDeleted(PKM pkm, IEncounterable enc)
|
||||
{
|
||||
if (pkm is IBattleVersion { BattleVersion: not 0 }) // can hide Relearn moves (Gen6+ Eggs, or DexNav)
|
||||
return enc is EncounterEgg { Generation: >= 6 } or EncounterSlot6AO { CanDexNav: true };
|
||||
return enc is EncounterEgg { Generation: >= 6 } or EncounterSlot6AO { CanDexNav: true } or EncounterSlot8b { IsUnderground: true };
|
||||
return enc is EncounterEgg { Generation: < 6 }; // egg moves that are no longer in the movepool
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
public const int Daycare4 = 2000;
|
||||
public const int Daycare5 = 60002;
|
||||
public const int Daycare8b = 60010;
|
||||
|
||||
public const int LinkTrade2NPC = 126;
|
||||
public const int LinkTrade3NPC = 254;
|
||||
|
@ -55,6 +56,9 @@
|
|||
/// <summary> Route 5 in <see cref="GameVersion.SWSH"/> </summary>
|
||||
public const int HatchLocation8 = 40;
|
||||
|
||||
/// <summary> Solaceon Town in <see cref="GameVersion.BDSP"/> </summary>
|
||||
public const int HatchLocation8b = 446;
|
||||
|
||||
/// <summary> Generation 1 -> Generation 7 Transfer Location (Kanto) </summary>
|
||||
public const int Transfer1 = 30013;
|
||||
|
||||
|
@ -96,6 +100,11 @@
|
|||
|
||||
public const int BugCatchingContest4 = 207;
|
||||
|
||||
/// <summary>
|
||||
/// -1
|
||||
/// </summary>
|
||||
public const int Default8bNone = -1;
|
||||
|
||||
public static int TradedEggLocationNPC(int generation) => generation switch
|
||||
{
|
||||
1 => LinkTrade2NPC,
|
||||
|
@ -106,10 +115,11 @@
|
|||
_ => LinkTrade6NPC,
|
||||
};
|
||||
|
||||
public static int TradedEggLocation(int generation) => generation switch
|
||||
public static int TradedEggLocation(int generation, GameVersion ver) => generation switch
|
||||
{
|
||||
4 => LinkTrade4,
|
||||
5 => LinkTrade5,
|
||||
8 when GameVersion.BDSP.Contains(ver) => LinkTrade6NPC,
|
||||
_ => LinkTrade6,
|
||||
};
|
||||
|
||||
|
@ -134,5 +144,14 @@
|
|||
|
||||
public static bool IsEggLocationBred5(int loc) => loc is Daycare5 or LinkTrade5;
|
||||
public static bool IsEggLocationBred6(int loc) => loc is Daycare5 or LinkTrade6;
|
||||
public static bool IsEggLocationBred8b(int loc) => loc is Daycare8b or LinkTrade6NPC;
|
||||
|
||||
public static bool IsNoneLocation(GameVersion ver, int location) => GetNoneLocation(ver) == (short)location;
|
||||
|
||||
public static int GetNoneLocation(GameVersion ver) => ver switch
|
||||
{
|
||||
GameVersion.BD or GameVersion.SP => Default8bNone,
|
||||
_ => 0,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,6 +127,8 @@ namespace PKHeX.Core
|
|||
return false;
|
||||
if (generation is 6 && move is ((int)ThousandArrows or (int)ThousandWaves))
|
||||
return false;
|
||||
if (generation is 8 && DummiedMoves_BDSP.Contains(move)) // can't Sketch unusable moves in BDSP
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
350
PKHeX.Core/Legality/Tables/Tables8bs.cs
Normal file
350
PKHeX.Core/Legality/Tables/Tables8bs.cs
Normal file
|
@ -0,0 +1,350 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
public static partial class Legal
|
||||
{
|
||||
internal const int MaxSpeciesID_8b = MaxSpeciesID_4; // Arceus-493
|
||||
internal const int MaxMoveID_8b = MaxMoveID_8_R2;
|
||||
internal const int MaxItemID_8b = 1822; // DS Sounds
|
||||
internal const int MaxBallID_8b = (int)Ball.Beast;
|
||||
internal const int MaxGameID_8b = (int)GameVersion.SP;
|
||||
internal const int MaxAbilityID_8b = MaxAbilityID_8_R2;
|
||||
|
||||
#region Met Locations
|
||||
|
||||
// TODO
|
||||
internal static readonly int[] Met_BS_0 =
|
||||
{
|
||||
000, 001, 002, 003, 004, 005, 006, 007, 008, 009,
|
||||
010, 011, 012, 013, 014, 015, 016, 017, 018, 019,
|
||||
020, 021, 022, 023, 024, 025, 026, 027, 028, 029,
|
||||
030, 031, 032, 033, 034, 035, 036, 037, 038, 039,
|
||||
040, 041, 042, 043, 044, 045, 046, 047, 048, 049,
|
||||
050, 051, 052, 053, 054, 055, 056, 057, 058, 059,
|
||||
060, 061, 062, 063, 064, 065, 066, 067, 068, 069,
|
||||
070, 071, 072, 073, 074, 075, 076, 077, 078, 079,
|
||||
080, 081, 082, 083, 084, 085, 086, 087, 088, 089,
|
||||
090, 091, 092, 093, 094, 095, 096, 097, 098, 099,
|
||||
100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
|
||||
110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
|
||||
120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
|
||||
130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
|
||||
140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
|
||||
150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
|
||||
160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
|
||||
170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
|
||||
180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
|
||||
190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
|
||||
200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
|
||||
210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
|
||||
220, 221, 222, 223, 224, 225, 226, 227, 228, 229,
|
||||
230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
|
||||
240, 241, 242, 243, 244, 245, 246, 247, 248, 249,
|
||||
250, 251, 252, 253, 254, 255, 256, 257, 258, 259,
|
||||
260, 261, 262, 263, 264, 265, 266, 267, 268, 269,
|
||||
270, 271, 272, 273, 274, 275, 276, 277, 278, 279,
|
||||
280, 281, 282, 283, 284, 285, 286, 287, 288, 289,
|
||||
290, 291, 292, 293, 294, 295, 296, 297, 298, 299,
|
||||
300, 301, 302, 303, 304, 305, 306, 307, 308, 309,
|
||||
310, 311, 312, 313, 314, 315, 316, 317, 318, 319,
|
||||
320, 321, 322, 323, 324, 325, 326, 327, 328, 329,
|
||||
330, 331, 332, 333, 334, 335, 336, 337, 338, 339,
|
||||
340, 341, 342, 343, 344, 345, 346, 347, 348, 349,
|
||||
350, 351, 352, 353, 354, 355, 356, 357, 358, 359,
|
||||
360, 361, 362, 363, 364, 365, 366, 367, 368, 369,
|
||||
370, 371, 372, 373, 374, 375, 376, 377, 378, 379,
|
||||
380, 381, 382, 383, 384, 385, 386, 387, 388, 389,
|
||||
390, 391, 392, 393, 394, 395, 396, 397, 398, 399,
|
||||
400, 401, 402, 403, 404, 405, 406, 407, 408, 409,
|
||||
410, 411, 412, 413, 414, 415, 416, 417, 418, 419,
|
||||
420, 421, 422, 423, 424, 425, 426, 427, 428, 429,
|
||||
430, 431, 432, 433, 434, 435, 436, 437, 438, 439,
|
||||
440, 441, 442, 443, 444, 445, 446, 447, 448, 449,
|
||||
450, 451, 452, 453, 454, 455, 456, 457, 458, 459,
|
||||
460, 461, 462, 463, 464, 465, 466, 467, 468, 469,
|
||||
470, 471, 472, 473, 474, 475, 476, 477, 478, 479,
|
||||
480, 481, 482, 483, 484, 485, 486, 487, 488, 489,
|
||||
490, 491, 492, 493, 494, 495, 496, 497, 498, 499,
|
||||
500, 501, 502, 503, 504, 505, 506, 507, 508, 509,
|
||||
510, 511, 512, 513, 514, 515, 516, 517, 518, 519,
|
||||
520, 521, 522, 523, 524, 525, 526, 527, 528, 529,
|
||||
530, 531, 532, 533, 534, 535, 536, 537, 538, 539,
|
||||
540, 541, 542, 543, 544, 545, 546, 547, 548, 549,
|
||||
550, 551, 552, 553, 554, 555, 556, 557, 558, 559,
|
||||
560, 561, 562, 563, 564, 565, 566, 567, 568, 569,
|
||||
570, 571, 572, 573, 574, 575, 576, 577, 578, 579,
|
||||
580, 581, 582, 583, 584, 585, 586, 587, 588, 589,
|
||||
590, 591, 592, 593, 594, 595, 596, 597, 598, 599,
|
||||
600, 601, 602, 603, 604, 605, 606, 607, 608, 609,
|
||||
610, 611, 612, 613, 614, 615, 616, 617, 618, 619,
|
||||
620, 621, 622, 623, 624, 625, 626,
|
||||
|
||||
// Skip the secret base met location IDs because no Pokémon can be obtained in them.
|
||||
|
||||
// Ramanas Park rooms with lights out
|
||||
648, 649, 650, 651, 652, 653, 654, 655, 656, 657,
|
||||
};
|
||||
|
||||
internal static readonly int[] Met_BS_3 =
|
||||
{
|
||||
30001, 30003, 30004, 30005, 30006, 30007, 30009, 30010, 30011, 30012, 30013, 30014, 30015, 30016, 30017, 30018, 30019, 30020, 30021
|
||||
};
|
||||
|
||||
internal static readonly int[] Met_BS_4 =
|
||||
{
|
||||
40001, 40002, 40003, 40005, 40006, 40007, 40008, 40009,
|
||||
40010, 40011, 40012, 40013, 40014, 40016, 40017, 40018, 40019,
|
||||
40020, 40021, 40022, 40024, 40025, 40026, 40027, 40028, 40029,
|
||||
40030, 40032, 40033, 40034, 40035, 40036, 40037, 40038, 40039,
|
||||
40040, 40041, 40042, 40043, 40044, 40045, 40047, 40048, 40049,
|
||||
40050, 40051, 40052, 40053, 40055, 40056, 40057, 40058, 40059,
|
||||
40060, 40061, 40063, 40064, 40065, 40066, 40067, 40068, 40069,
|
||||
40070, 40071, 40072, 40074, 40075, 40076, 40077,
|
||||
};
|
||||
|
||||
internal static readonly int[] Met_BS_6 = {/* XY */ 60001, 60003, /* ORAS */ 60004, /* BDSP */ 60005, 60006, 60007, 60010 };
|
||||
|
||||
#endregion
|
||||
|
||||
internal static readonly ushort[] Pouch_Regular_BS =
|
||||
{
|
||||
045, 046, 047, 048, 049, 050, 051, 052, 053, 072, 073, 074, 075, 076, 077, 078,
|
||||
079, 080, 081, 082, 083, 084, 085, 093, 094, 107, 108, 109, 110, 111, 112, 135,
|
||||
136, 213, 214, 215, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228,
|
||||
229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244,
|
||||
245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260,
|
||||
261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276,
|
||||
277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292,
|
||||
293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308,
|
||||
309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324,
|
||||
325, 326, 327, 537, 565, 566, 567, 568, 569, 570, 644, 645, 849,
|
||||
|
||||
1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244,
|
||||
1245, 1246, 1247, 1248, 1249, 1250, 1251, 1606,
|
||||
};
|
||||
|
||||
internal static readonly ushort[] Pouch_Ball_BS =
|
||||
{
|
||||
001, 002, 003, 004, 005, 006, 007, 008, 009, 010, 011, 012, 013, 014, 015, 016,
|
||||
492, 493, 494, 495, 496, 497, 498, 499, 500,
|
||||
576,
|
||||
851,
|
||||
};
|
||||
|
||||
internal static readonly ushort[] Pouch_Battle_BS =
|
||||
{
|
||||
055, 056, 057, 058, 059, 060, 061, 062, 063,
|
||||
};
|
||||
|
||||
internal static readonly ushort[] Pouch_Items_BS = ArrayUtil.ConcatAll(Pouch_Regular_BS, Pouch_Ball_BS, Pouch_Battle_BS);
|
||||
|
||||
internal static readonly ushort[] Pouch_Key_BS =
|
||||
{
|
||||
428, 431, 432, 433, 438, 439, 440, 443, 445, 446, 447, 448, 449, 450, 451, 452,
|
||||
453, 454, 459, 460, 461, 462, 463, 464, 466, 467, 631, 632,
|
||||
|
||||
1267, 1278, 1822,
|
||||
|
||||
// 455 Azure Flute (nonfunctional as of 1.1.0)
|
||||
};
|
||||
|
||||
internal static readonly ushort[] Pouch_Medicine_BS =
|
||||
{
|
||||
017, 018, 019, 020, 021, 022, 023, 024, 025, 026, 027, 028, 029, 030, 031, 032, 033, 034, 035, 036, 037,
|
||||
038, 039, 040, 041, 042, 043, 044, 054,
|
||||
|
||||
// 134 Sweet Heart (future event item?)
|
||||
};
|
||||
|
||||
internal static readonly ushort[] Pouch_Berries_BS =
|
||||
{
|
||||
149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
|
||||
159, 160, 161, 162, 163, 169, 170, 171, 172, 173,
|
||||
174, 184, 185, 186, 187, 188, 189, 190, 191, 192,
|
||||
193, 194, 195, 196, 197, 198, 199, 200, 201, 202,
|
||||
203, 204, 205, 206, 207, 208, 209, 210, 211, 212,
|
||||
686,
|
||||
};
|
||||
|
||||
internal static readonly ushort[] Pouch_Treasure_BS =
|
||||
{
|
||||
086, 087, 088, 089, 090, 091, 092, 099, 100, 101, 102, 103, 104, 105, 106, 795, 796,
|
||||
|
||||
1808, 1809, 1810, 1811, 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1819, 1820, 1821,
|
||||
};
|
||||
|
||||
internal static readonly ushort[] Pouch_TMHM_BS = // TM01-TM100
|
||||
{
|
||||
328, 329, 330, 331, 332, 333, 334, 335, 336, 337,
|
||||
338, 339, 340, 341, 342, 343, 344, 345, 346, 347,
|
||||
348, 349, 350, 351, 352, 353, 354, 355, 356, 357,
|
||||
358, 359, 360, 361, 362, 363, 364, 365, 366, 367,
|
||||
368, 369, 370, 371, 372, 373, 374, 375, 376, 377,
|
||||
378, 379, 380, 381, 382, 383, 384, 385, 386, 387,
|
||||
388, 389, 390, 391, 392, 393, 394, 395, 396, 397,
|
||||
398, 399, 400, 401, 402, 403, 404, 405, 406, 407,
|
||||
408, 409, 410, 411, 412, 413, 414, 415, 416, 417,
|
||||
418, 419,
|
||||
420, 421, 422, 423, 424, 425, 426, 427, // Previously called HM0X, in BDSP they're now called TM93-TM100
|
||||
};
|
||||
|
||||
internal static readonly ushort[] HeldItems_BS = ArrayUtil.ConcatAll(Pouch_Items_BS, Pouch_Berries_BS, Pouch_TMHM_BS, Pouch_Medicine_BS, Pouch_Treasure_BS);
|
||||
|
||||
#region Moves
|
||||
|
||||
public static readonly int[] TMHM_BDSP =
|
||||
{
|
||||
264, 337, 352, 347, 046, 092, 258, 339, 331, 237,
|
||||
241, 269, 058, 059, 063, 113, 182, 240, 202, 219,
|
||||
218, 076, 231, 085, 087, 089, 216, 091, 094, 247,
|
||||
280, 104, 115, 351, 053, 188, 201, 126, 317, 332,
|
||||
259, 263, 290, 156, 213, 168, 211, 285, 289, 315,
|
||||
355, 411, 412, 206, 362, 374, 451, 203, 406, 409,
|
||||
261, 318, 373, 153, 421, 371, 278, 416, 397, 148,
|
||||
444, 419, 086, 360, 014, 446, 244, 445, 399, 157,
|
||||
404, 214, 363, 398, 138, 447, 207, 365, 369, 164,
|
||||
430, 433,
|
||||
015, 019, 057, 070, 432, 249, 127, 431,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Moves that are kill
|
||||
/// </summary>
|
||||
public static readonly HashSet<int> DummiedMoves_BDSP = new()
|
||||
{
|
||||
002, 003, 004, 013, 026, 027, 041, 049, 082, 096,
|
||||
099, 112, 117, 119, 121, 125, 128, 131, 132, 140,
|
||||
145, 146, 149, 158, 159, 169, 171, 185, 193, 216,
|
||||
218, 222, 228, 265, 274, 287, 289, 290, 293, 300,
|
||||
301, 302, 316, 318, 320, 324, 327, 346, 357, 358,
|
||||
363, 373, 376, 377, 378, 381, 382, 386, 426, 429,
|
||||
443, 445, 456, 466, 477, 481, 485, 498, 507, 508,
|
||||
516, 518, 519, 520, 527, 531, 532, 533, 535, 537,
|
||||
539, 541, 543, 544, 545, 546, 547, 548, 549, 550,
|
||||
551, 552, 553, 554, 557, 558, 559, 560, 561, 563,
|
||||
567, 569, 570, 571, 576, 578, 582, 587, 588, 591,
|
||||
592, 593, 594, 600, 601, 603, 606, 607, 610, 613,
|
||||
614, 615, 616, 617, 621, 622, 623, 624, 625, 626,
|
||||
627, 628, 629, 630, 631, 632, 633, 634, 635, 636,
|
||||
637, 638, 639, 640, 641, 642, 643, 644, 645, 646,
|
||||
647, 648, 649, 650, 651, 652, 653, 654, 655, 656,
|
||||
657, 658, 659, 660, 661, 662, 663, 664, 665, 666,
|
||||
669, 671, 674, 676, 677, 678, 680, 681, 683, 685,
|
||||
686, 687, 688, 689, 690, 691, 693, 695, 696, 697,
|
||||
698, 699, 700, 701, 702, 703, 704, 705, 706, 708,
|
||||
709, 711, 712, 713, 714, 716, 717, 718, 719, 720,
|
||||
721, 722, 723, 724, 725, 726, 727, 728, 729, 730,
|
||||
731, 732, 733, 734, 735, 736, 737, 738, 739, 740,
|
||||
741, 742, 743, 744, 745, 746, 747, 748, 749, 750,
|
||||
751, 752, 753, 754, 755, 756, 757, 758, 759, 760,
|
||||
761, 762, 763, 764, 765, 766, 767, 768, 769, 770,
|
||||
771, 772, 773, 774, 775, 777, 778, 779, 780, 781,
|
||||
782, 783, 784, 785, 786, 787, 788, 789, 790, 792,
|
||||
793, 794, 795, 796, 797, 798, 799, 800, 801, 802,
|
||||
803, 804, 805, 806, 807, 808, 809, 810, 811, 812,
|
||||
813, 814, 815, 816, 817, 818, 819, 820, 821, 822,
|
||||
823, 824, 825, 826,
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
#region Unreleased Items
|
||||
internal static readonly bool[] ReleasedHeldItems_8b = GetPermitList(MaxItemID_8b, HeldItems_BS, new ushort[]
|
||||
{
|
||||
849, // Ice Stone
|
||||
|
||||
005, // Safari Ball
|
||||
016, // Cherish Ball
|
||||
500, // Park Ball
|
||||
576, // Dream Ball
|
||||
851, // Beast Ball
|
||||
|
||||
1808, // Mysterious Shard S
|
||||
1809, // Mysterious Shard L
|
||||
1810, // Digger Drill
|
||||
1811, // Kanto Slate
|
||||
1812, // Johto Slate
|
||||
1813, // Soul Slate
|
||||
1814, // Rainbow Slate
|
||||
1815, // Squall Slate
|
||||
1816, // Oceanic Slate
|
||||
1817, // Tectonic Slate
|
||||
1818, // Stratospheric Slate
|
||||
1819, // Genome Slate
|
||||
1820, // Discovery Slate
|
||||
1821, // Distortion Slate
|
||||
});
|
||||
#endregion
|
||||
|
||||
internal static readonly HashSet<int> ValidMet_BDSP = new()
|
||||
{
|
||||
000, 001, 002, 003, 004, 005, 006, 007, 008, 009,
|
||||
010, 011, 012, 013, 014, 015, 016, 017, 018, 019,
|
||||
020, 021, 022, 023, 024, 025, 026, 027, 028, 029,
|
||||
030, 031, 032, 033, 034, 035, 036, 037, 038, 039,
|
||||
040, 041, 042, 043, 044, 045, 046, 047, 048, 049,
|
||||
050, 051, 052, 053, 054, 055, 056, 057, 058, 059,
|
||||
060, 061, 062, 063, 064, 065, 066, 067, 068, 069,
|
||||
070, 071, 072, 073, 074, 075, 076, 077, 078, 079,
|
||||
080, 081, 082, 083, 084, 085, 086, 087, 088, 089,
|
||||
090, 091, 092, 093, 094, 095, 096, 097, 098, 099,
|
||||
100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
|
||||
110, 111, 112, 113, 114, 115, 116, 117, 118, 119,
|
||||
120, 121, 122, 123, 124, 125, 126, 127, 128, 129,
|
||||
130, 131, 132, 133, 134, 135, 136, 137, 138, 139,
|
||||
140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
|
||||
150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
|
||||
160, 161, 162, 163, 164, 165, 166, 167, 168, 169,
|
||||
170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
|
||||
180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
|
||||
190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
|
||||
200, 201, 202, 203, 204, 205, 206, 207, 208, 209,
|
||||
210, 211, 212, 213, 214, 215, 216, 217, 218, 219,
|
||||
220, 221, 222, 223, 224, 225, 226, 227, 228, 229,
|
||||
230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
|
||||
240, 241, 242, 243, 244, 245, 246, 247, 248, 249,
|
||||
250, 251, 252, 253, 254, 255, 256, 257, 258, 259,
|
||||
260, 261, 262, 263, 264, 265, 266, 267, 268, 269,
|
||||
270, 271, 272, 273, 274, 275, 276, 277, 278, 279,
|
||||
280, 281, 282, 283, 284, 285, 286, 287, 288, 289,
|
||||
290, 291, 292, 293, 294, 295, 296, 297, 298, 299,
|
||||
300, 301, 302, 303, 304, 305, 306, 307, 308, 309,
|
||||
310, 311, 312, 313, 314, 315, 316, 317, 318, 319,
|
||||
320, 321, 322, 323, 324, 325, 326, 327, 328, 329,
|
||||
330, 331, 332, 333, 334, 335, 336, 337, 338, 339,
|
||||
340, 341, 342, 343, 344, 345, 346, 347, 348, 349,
|
||||
350, 351, 352, 353, 354, 355, 356, 357, 358, 359,
|
||||
360, 361, 362, 363, 364, 365, 366, 367, 368, 369,
|
||||
370, 371, 372, 373, 374, 375, 376, 377, 378, 379,
|
||||
380, 381, 382, 383, 384, 385, 386, 387, 388, 389,
|
||||
390, 391, 392, 393, 394, 395, 396, 397, 398, 399,
|
||||
400, 401, 402, 403, 404, 405, 406, 407, 408, 409,
|
||||
410, 411, 412, 413, 414, 415, 416, 417, 418, 419,
|
||||
420, 421, 422, 423, 424, 425, 426, 427, 428, 429,
|
||||
430, 431, 432, 433, 434, 435, 436, 437, 438, 439,
|
||||
440, 441, 442, 443, 444, 445, 446, 447, 448, 449,
|
||||
450, 451, 452, 453, 454, 455, 456, 457, 458, 459,
|
||||
460, 461, 462, 463, 464, 465, 466, 467, 468, 469,
|
||||
470, 471, 472, 473, 474, 475, 476, 477, 478, 479,
|
||||
480, 481, 482, 483, 484, 485, 486, 487, 488, 489,
|
||||
490, 491, 492, 493, 494, 495, 496, 497, 498, 499,
|
||||
500, 501, 502, 503, 504, 505, 506, 507, 508, 509,
|
||||
510, 511, 512, 513, 514, 515, 516, 517, 518, 519,
|
||||
520, 521, 522, 523, 524, 525, 526, 527, 528, 529,
|
||||
530, 531, 532, 533, 534, 535, 536, 537, 538, 539,
|
||||
540, 541, 542, 543, 544, 545, 546, 547, 548, 549,
|
||||
550, 551, 552, 553, 554, 555, 556, 557, 558, 559,
|
||||
560, 561, 562, 563, 564, 565, 566, 567, 568, 569,
|
||||
570, 571, 572, 573, 574, 575, 576, 577, 578, 579,
|
||||
580, 581, 582, 583, 584, 585, 586, 587, 588, 589,
|
||||
590, 591, 592, 593, 594, 595, 596, 597, 598, 599,
|
||||
600, 601, 602, 603, 604, 605, 606, 607, 608, 609,
|
||||
610, 611, 612, 613, 614, 615, 616, 617, 618, 619,
|
||||
620, 621, 622, 623, 624, 625, 626,
|
||||
|
||||
// Ramanas Park rooms with lights out
|
||||
648, 649, 650, 651, 652, 653, 654, 655, 656, 657,
|
||||
};
|
||||
}
|
||||
}
|
|
@ -983,5 +983,34 @@ namespace PKHeX.Core
|
|||
(int)Voltorb, // Voltorb
|
||||
(int)Flabébé + (3 << 11), // Flabébé-Blue
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// All egg species that can inherit a Safar Ball when bred in BD/SP.
|
||||
/// </summary>
|
||||
internal static readonly HashSet<int> InheritSafari_BDSP = new()
|
||||
{
|
||||
(int)Ekans,
|
||||
(int)Azurill,
|
||||
(int)Barboach,
|
||||
(int)Bidoof,
|
||||
(int)Budew,
|
||||
(int)Carnivine,
|
||||
(int)Carvanha,
|
||||
(int)Croagunk,
|
||||
(int)Exeggcute,
|
||||
(int)Gulpin,
|
||||
(int)Hoothoot,
|
||||
(int)Kangaskhan,
|
||||
(int)Magikarp,
|
||||
(int)Marill,
|
||||
(int)Paras,
|
||||
(int)Psyduck,
|
||||
(int)Roselia,
|
||||
(int)Shroomish,
|
||||
(int)Skorupi,
|
||||
(int)Starly,
|
||||
(int)Wooper,
|
||||
(int)Yanma,
|
||||
};
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ namespace PKHeX.Core
|
|||
5 => WildPokeBalls5,
|
||||
6 => WildPokeballs6,
|
||||
7 => GameVersion.Gen7b.Contains(game) ? WildPokeballs7b : WildPokeballs7,
|
||||
8 when GameVersion.BDSP.Contains(game) => WildPokeBalls4_HGSS,
|
||||
8 => GameVersion.GO == game ? WildPokeballs8g : WildPokeballs8,
|
||||
_ => Array.Empty<int>(),
|
||||
};
|
||||
|
|
|
@ -36,6 +36,8 @@ namespace PKHeX.Core
|
|||
return VerifyBallEquals(data, s.Ball);
|
||||
case EncounterSlot8GO: // Already a strict match
|
||||
return GetResult(true);
|
||||
case EncounterSlot8b {IsMarsh: true}:
|
||||
return VerifyBallEquals(data, (int)Safari);
|
||||
}
|
||||
|
||||
// Capture / Inherit cases -- can be one of many balls
|
||||
|
@ -104,7 +106,7 @@ namespace PKHeX.Core
|
|||
{
|
||||
6 => VerifyBallEggGen6(data), // Gen6 Inheritance Rules
|
||||
7 => VerifyBallEggGen7(data), // Gen7 Inheritance Rules
|
||||
8 => VerifyBallEggGen8(data),
|
||||
8 => data.pkm.BDSP ? VerifyBallEggGen8BDSP(data) : VerifyBallEggGen8(data),
|
||||
_ => NONE,
|
||||
};
|
||||
|
||||
|
@ -252,6 +254,23 @@ namespace PKHeX.Core
|
|||
return NONE;
|
||||
}
|
||||
|
||||
private CheckResult VerifyBallEggGen8BDSP(LegalityAnalysis data)
|
||||
{
|
||||
int species = data.EncounterMatch.Species;
|
||||
if (species is (int)Species.Phione)
|
||||
return VerifyBallEquals(data, (int)Poke);
|
||||
|
||||
if (data.pkm.Ball == (int)Safari)
|
||||
{
|
||||
if (BallBreedLegality.InheritSafari_BDSP.Contains(species))
|
||||
return GetValid(LBallSpeciesPass);
|
||||
return GetInvalid(LBallSpecies);
|
||||
}
|
||||
|
||||
var balls = BallUseLegality.GetWildBalls(8, GameVersion.BDSP);
|
||||
return VerifyBallEquals(data, balls);
|
||||
}
|
||||
|
||||
private CheckResult VerifyBallEggGen8(LegalityAnalysis data)
|
||||
{
|
||||
var pkm = data.pkm;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
4 => true,
|
||||
5 => s.CNT_Sheen == 0 && pkm.Format >= 6, // ORAS Contests
|
||||
6 => s.CNT_Sheen == 0 && (!pkm.IsUntraded || pkm.AO),
|
||||
8 => pkm.BDSP, // BDSP Contests
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ namespace PKHeX.Core
|
|||
// If none match, then it is not a valid OT friendship.
|
||||
var fs = pkm.OT_Friendship;
|
||||
var enc = data.Info.EncounterMatch;
|
||||
if (GetBaseFriendship(origin, enc.Species, enc.Form) != fs)
|
||||
if (GetBaseFriendship(enc, origin) != fs)
|
||||
data.AddLine(GetInvalid(LegalityCheckStrings.LMemoryStatFriendshipOTBaseEvent));
|
||||
}
|
||||
}
|
||||
|
@ -185,11 +185,19 @@ namespace PKHeX.Core
|
|||
WC6 wc6 when wc6.OT_Name.Length > 0 => false,
|
||||
WC7 wc7 when wc7.OT_Name.Length > 0 && wc7.TID != 18075 => false, // Ash Pikachu QR Gift doesn't set Current Handler
|
||||
WC8 wc8 when wc8.GetHasOT(pkm.Language) => false,
|
||||
WB8 wb8 when wb8.GetHasOT(pkm.Language) => false,
|
||||
WC8 {IsHOMEGift: true} => false,
|
||||
_ => true,
|
||||
};
|
||||
}
|
||||
|
||||
private static int GetBaseFriendship(IEncounterTemplate enc, int generation) => enc switch
|
||||
{
|
||||
IFixedOTFriendship f => f.OT_Friendship,
|
||||
{ Version: GameVersion.BD or GameVersion.SP } => PersonalTable.SWSH.GetFormEntry(enc.Species, enc.Form).BaseFriendship,
|
||||
_ => GetBaseFriendship(generation, enc.Species, enc.Form),
|
||||
};
|
||||
|
||||
private static int GetBaseFriendship(int generation, int species, int form) => generation switch
|
||||
{
|
||||
1 => PersonalTable.USUM[species].BaseFriendship,
|
||||
|
|
|
@ -186,7 +186,7 @@ namespace PKHeX.Core
|
|||
var clone = pk8.Clone();
|
||||
clone.Species = (int) Species.Nincada;
|
||||
((IRibbonIndex) clone).SetRibbon(affix);
|
||||
var parse = RibbonVerifier.GetRibbonResults(clone, enc);
|
||||
var parse = RibbonVerifier.GetRibbonResults(clone, data.Info.EvoChainsAllGens, enc);
|
||||
var expect = $"Ribbon{(RibbonIndex) affix}";
|
||||
var name = RibbonStrings.GetName(expect);
|
||||
bool invalid = parse.FirstOrDefault(z => z.Name == name)?.Invalid == true;
|
||||
|
|
|
@ -14,6 +14,12 @@ namespace PKHeX.Core
|
|||
|
||||
public override void Verify(LegalityAnalysis data)
|
||||
{
|
||||
if (data.pkm.BDSP)
|
||||
{
|
||||
VerifyOTMemoryIs(data, 0, 0, 0, 0);
|
||||
VerifyHTMemoryNone(data, (ITrainerMemories)data.pkm);
|
||||
return;
|
||||
}
|
||||
VerifyOTMemory(data);
|
||||
VerifyHTMemory(data);
|
||||
}
|
||||
|
@ -252,6 +258,7 @@ namespace PKHeX.Core
|
|||
case 7 when pkm.GG: // LGPE does not set memories.
|
||||
case 8 when pkm.GO_HOME: // HOME does not set memories.
|
||||
case 8 when pkm.Met_Location == Locations.HOME8: // HOME does not set memories.
|
||||
case 8 when pkm.BDSP: // BDSP does not set memories.
|
||||
return false;
|
||||
|
||||
// Eggs cannot have memories
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace PKHeX.Core
|
|||
|
||||
switch (pkm)
|
||||
{
|
||||
case PK7 {ResortEventStatus: >= 20}:
|
||||
case PK7 {ResortEventStatus: >= ResortEventState.MAX}:
|
||||
data.AddLine(GetInvalid(LTransferBad));
|
||||
break;
|
||||
case PB7 pb7:
|
||||
|
@ -58,6 +58,9 @@ namespace PKHeX.Core
|
|||
case PK8 pk8:
|
||||
VerifySWSHStats(data, pk8);
|
||||
break;
|
||||
case PB8 pb8:
|
||||
VerifyBDSPStats(data, pb8);
|
||||
break;
|
||||
}
|
||||
|
||||
if (pkm.Format >= 6)
|
||||
|
@ -90,6 +93,23 @@ namespace PKHeX.Core
|
|||
if (!valid)
|
||||
data.AddLine(GetInvalid(LPIDTypeMismatch));
|
||||
}
|
||||
else if (enc is IStaticCorrelation8b s8b)
|
||||
{
|
||||
var match = s8b.IsStaticCorrelationCorrect(pkm);
|
||||
var req = s8b.GetRequirement(pkm);
|
||||
if (match)
|
||||
data.Info.PIDIV = new PIDIV(PIDType.Roaming8b, pkm.EncryptionConstant);
|
||||
|
||||
bool valid = req switch
|
||||
{
|
||||
StaticCorrelation8bRequirement.MustHave => match,
|
||||
StaticCorrelation8bRequirement.MustNotHave => !match,
|
||||
_ => true,
|
||||
};
|
||||
|
||||
if (!valid)
|
||||
data.AddLine(GetInvalid(LPIDTypeMismatch));
|
||||
}
|
||||
|
||||
VerifyMiscFatefulEncounter(data);
|
||||
}
|
||||
|
@ -255,7 +275,7 @@ namespace PKHeX.Core
|
|||
data.AddLine(GetInvalid(msg, Egg));
|
||||
}
|
||||
|
||||
if (pkm is PK8 pk8)
|
||||
if (pkm is G8PKM pk8)
|
||||
{
|
||||
if (pk8.HasAnyMoveRecordFlag())
|
||||
data.AddLine(GetInvalid(LEggRelearnFlags, Egg));
|
||||
|
@ -309,7 +329,8 @@ namespace PKHeX.Core
|
|||
{
|
||||
case WC6 wc6 when !wc6.CanBeReceivedByVersion(pkm.Version) && !pkm.WasTradedEgg:
|
||||
case WC7 wc7 when !wc7.CanBeReceivedByVersion(pkm.Version) && !pkm.WasTradedEgg:
|
||||
case WC8 wc8 when !wc8.CanBeReceivedByVersion(pkm.Version) && !pkm.WasTradedEgg:
|
||||
case WC8 wc8 when !wc8.CanBeReceivedByVersion(pkm.Version):
|
||||
case WB8 wb8 when !wb8.CanBeReceivedByVersion(pkm.Version):
|
||||
data.AddLine(GetInvalid(LEncGiftVersionNotDistributed, GameOrigin));
|
||||
return;
|
||||
case WC6 wc6 when wc6.RestrictLanguage != 0 && pkm.Language != wc6.RestrictLanguage:
|
||||
|
@ -443,13 +464,7 @@ namespace PKHeX.Core
|
|||
data.AddLine(GetInvalid(string.Format(LMemorySocialTooHigh_0, byte.MaxValue), Encounter));
|
||||
}
|
||||
|
||||
var sn = pk8.StatNature;
|
||||
if (sn != pk8.Nature)
|
||||
{
|
||||
// Only allow Serious nature (12); disallow all other neutral natures.
|
||||
if (sn != 12 && (sn > 24 || sn % 6 == 0))
|
||||
data.AddLine(GetInvalid(LStatNatureInvalid));
|
||||
}
|
||||
VerifyStatNature(data, pk8);
|
||||
|
||||
var bv = pk8.BattleVersion;
|
||||
if (bv != 0)
|
||||
|
@ -495,7 +510,44 @@ namespace PKHeX.Core
|
|||
data.AddLine(GetInvalid(string.Format(LMoveSourceTR, ParseSettings.MoveStrings[Legal.TMHM_SWSH[i + PersonalInfoSWSH.CountTM]])));
|
||||
}
|
||||
|
||||
// weight/height scalars can be legally 0 (1:65536) so don't bother checking
|
||||
// weight/height scalars can be legally 0 so don't bother checking
|
||||
}
|
||||
|
||||
private void VerifyBDSPStats(LegalityAnalysis data, PB8 pb8)
|
||||
{
|
||||
if (pb8.Favorite)
|
||||
data.AddLine(GetInvalid(LFavoriteMarkingUnavailable, Encounter));
|
||||
|
||||
var social = pb8.Sociability;
|
||||
if (social != 0)
|
||||
data.AddLine(GetInvalid(LMemorySocialZero, Encounter));
|
||||
|
||||
VerifyStatNature(data, pb8);
|
||||
|
||||
var bv = pb8.BattleVersion;
|
||||
if (bv != 0)
|
||||
data.AddLine(GetInvalid(LStatBattleVersionInvalid));
|
||||
|
||||
if (pb8.CanGigantamax)
|
||||
GetInvalid(LStatGigantamaxInvalid);
|
||||
|
||||
if (pb8.DynamaxLevel != 0)
|
||||
data.AddLine(GetInvalid(LStatDynamaxInvalid));
|
||||
|
||||
if (pb8.HasAnyMoveRecordFlag() && !pb8.IsEgg) // already checked for eggs
|
||||
data.AddLine(GetInvalid(LEggRelearnFlags));
|
||||
|
||||
// weight/height scalars can be legally 0 so don't bother checking
|
||||
}
|
||||
|
||||
private void VerifyStatNature(LegalityAnalysis data, PKM pk)
|
||||
{
|
||||
var sn = pk.StatNature;
|
||||
if (sn == pk.Nature)
|
||||
return;
|
||||
// Only allow Serious nature (12); disallow all other neutral natures.
|
||||
if (sn != 12 && (sn > 24 || sn % 6 == 0))
|
||||
data.AddLine(GetInvalid(LStatNatureInvalid));
|
||||
}
|
||||
|
||||
private static bool CanLearnTR(int species, int form, int tr)
|
||||
|
|
|
@ -34,6 +34,8 @@ namespace PKHeX.Core
|
|||
if (enc is ILangNicknamedTemplate n)
|
||||
{
|
||||
VerifyFixedNicknameEncounter(data, n, enc, pkm, nickname);
|
||||
if (pkm.IsEgg)
|
||||
VerifyNicknameEgg(data);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -244,8 +246,8 @@ namespace PKHeX.Core
|
|||
data.AddLine(GetInvalid(pkm.IsNicknamed ? LNickFlagEggNo : LNickFlagEggYes, CheckIdentifier.Egg));
|
||||
break;
|
||||
default:
|
||||
if (!pkm.IsNicknamed)
|
||||
data.AddLine(GetInvalid(LNickFlagEggYes, CheckIdentifier.Egg));
|
||||
if (pkm.IsNicknamed == Info.EncounterMatch is (EncounterStatic8b or WB8)) // bdsp doesn't use for ingame gifts
|
||||
data.AddLine(GetInvalid(pkm.IsNicknamed ? LNickFlagEggNo : LNickFlagEggYes, CheckIdentifier.Egg));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -269,6 +271,7 @@ namespace PKHeX.Core
|
|||
case 5: VerifyTrade5(data, t); return;
|
||||
case 6:
|
||||
case 7:
|
||||
case 8 when t is EncounterTrade8b: VerifyTrade8b(data, t); return;
|
||||
case 8:
|
||||
VerifyTrade(data, t, data.pkm.Language); return;
|
||||
}
|
||||
|
@ -357,6 +360,15 @@ namespace PKHeX.Core
|
|||
VerifyTrade(data, t, lang);
|
||||
}
|
||||
|
||||
private static void VerifyTrade8b(LegalityAnalysis data, EncounterTrade t)
|
||||
{
|
||||
var pkm = data.pkm;
|
||||
int lang = pkm.Language;
|
||||
if (t.Species == (int)Species.Magikarp)
|
||||
lang = DetectTradeLanguageG4MeisterMagikarp(pkm, t, lang);
|
||||
VerifyTrade(data, t, lang);
|
||||
}
|
||||
|
||||
private static void FlagKoreanIncompatibleSameGenTrade(LegalityAnalysis data, PKM pkm, int lang)
|
||||
{
|
||||
if (pkm.Format != 4 || lang != (int)Korean)
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace PKHeX.Core
|
|||
return;
|
||||
}
|
||||
|
||||
var result = GetIncorrectRibbons(pkm, enc);
|
||||
var result = GetIncorrectRibbons(pkm, data.Info.EvoChainsAllGens, enc);
|
||||
if (result.Count != 0)
|
||||
{
|
||||
var msg = string.Join(Environment.NewLine, result);
|
||||
|
@ -38,11 +38,11 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
private static List<string> GetIncorrectRibbons(PKM pkm, IEncounterTemplate enc)
|
||||
private static List<string> GetIncorrectRibbons(PKM pkm, IReadOnlyList<EvoCriteria>[] evos, IEncounterTemplate enc)
|
||||
{
|
||||
List<string> missingRibbons = new();
|
||||
List<string> invalidRibbons = new();
|
||||
var ribs = GetRibbonResults(pkm, enc);
|
||||
var ribs = GetRibbonResults(pkm, evos, enc);
|
||||
foreach (var bad in ribs)
|
||||
(bad.Invalid ? invalidRibbons : missingRibbons).Add(bad.Name);
|
||||
|
||||
|
@ -75,14 +75,14 @@ namespace PKHeX.Core
|
|||
return false;
|
||||
}
|
||||
|
||||
internal static IEnumerable<RibbonResult> GetRibbonResults(PKM pkm, IEncounterTemplate enc)
|
||||
internal static IEnumerable<RibbonResult> GetRibbonResults(PKM pkm, IReadOnlyList<EvoCriteria>[] evos, IEncounterTemplate enc)
|
||||
{
|
||||
return GetInvalidRibbons(pkm, enc)
|
||||
return GetInvalidRibbons(pkm, evos, enc)
|
||||
.Concat(GetInvalidRibbonsEvent1(pkm, enc))
|
||||
.Concat(GetInvalidRibbonsEvent2(pkm, enc));
|
||||
}
|
||||
|
||||
private static IEnumerable<RibbonResult> GetInvalidRibbons(PKM pkm, IEncounterTemplate enc)
|
||||
private static IEnumerable<RibbonResult> GetInvalidRibbons(PKM pkm, IReadOnlyList<EvoCriteria>[] evos, IEncounterTemplate enc)
|
||||
{
|
||||
// is a part of Event4, but O3 doesn't have the others
|
||||
if (pkm is IRibbonSetOnly3 {RibbonWorld: true})
|
||||
|
@ -130,9 +130,14 @@ namespace PKHeX.Core
|
|||
if (pkm is IRibbonSetCommon4 s4)
|
||||
{
|
||||
bool inhabited4 = gen is 3 or 4;
|
||||
var iterate = GetInvalidRibbons4Any(pkm, s4, gen);
|
||||
var iterate = GetInvalidRibbons4Any(pkm, evos, s4, gen);
|
||||
if (!inhabited4)
|
||||
iterate = iterate.Concat(GetInvalidRibbonsNone(s4.RibbonBitsOnly(), s4.RibbonNamesOnly()));
|
||||
{
|
||||
if (pkm.BDSP) // Allow Sinnoh Champion. ILCA reused the Gen4 ribbon for the remake.
|
||||
iterate = iterate.Concat(GetInvalidRibbonsNoneSkipIndex(s4.RibbonBitsOnly(), s4.RibbonNamesOnly(), 1));
|
||||
else
|
||||
iterate = iterate.Concat(GetInvalidRibbonsNone(s4.RibbonBitsOnly(), s4.RibbonNamesOnly()));
|
||||
}
|
||||
foreach (var z in iterate)
|
||||
yield return z;
|
||||
}
|
||||
|
@ -200,11 +205,11 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<RibbonResult> GetInvalidRibbons4Any(PKM pkm, IRibbonSetCommon4 s4, int gen)
|
||||
private static IEnumerable<RibbonResult> GetInvalidRibbons4Any(PKM pkm, IReadOnlyList<EvoCriteria>[] evos, IRibbonSetCommon4 s4, int gen)
|
||||
{
|
||||
if (s4.RibbonRecord)
|
||||
yield return new RibbonResult(nameof(s4.RibbonRecord)); // Unobtainable
|
||||
if (s4.RibbonFootprint && !CanHaveFootprintRibbon(pkm, gen))
|
||||
if (s4.RibbonFootprint && !CanHaveFootprintRibbon(pkm, evos, gen))
|
||||
yield return new RibbonResult(nameof(s4.RibbonFootprint));
|
||||
|
||||
bool gen34 = gen is 3 or 4;
|
||||
|
@ -356,7 +361,7 @@ namespace PKHeX.Core
|
|||
|
||||
private static IEnumerable<RibbonResult> GetInvalidRibbons8Any(PKM pkm, IRibbonSetCommon8 s8, IEncounterTemplate enc)
|
||||
{
|
||||
if (!pkm.InhabitedGeneration(8) || !((PersonalInfoSWSH)PersonalTable.SWSH[pkm.Species]).IsPresentInGame)
|
||||
if (!pkm.InhabitedGeneration(8) || !((PersonalInfoSWSH)PersonalTable.SWSH[pkm.Species]).IsPresentInGame || pkm.BDSP)
|
||||
{
|
||||
if (s8.RibbonChampionGalar)
|
||||
yield return new RibbonResult(nameof(s8.RibbonChampionGalar));
|
||||
|
@ -397,6 +402,18 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// can be expanded upon if SWSH gets updated with the new ribbon when HOME has BDSP support
|
||||
if (!pkm.BDSP && s8.RibbonTwinklingStar)
|
||||
{
|
||||
yield return new RibbonResult(nameof(s8.RibbonTwinklingStar));
|
||||
}
|
||||
|
||||
// new ribbon likely from Legends: Arceus; inaccessible until then
|
||||
if (s8.RibbonPioneer)
|
||||
{
|
||||
yield return new RibbonResult(nameof(s8.RibbonPioneer));
|
||||
}
|
||||
}
|
||||
|
||||
private static bool CanParticipateInRankedSWSH(PKM pkm, IEncounterTemplate enc)
|
||||
|
@ -480,6 +497,15 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<RibbonResult> GetInvalidRibbonsNoneSkipIndex(IReadOnlyList<bool> bits, IReadOnlyList<string> names, int skipIndex)
|
||||
{
|
||||
for (int i = 0; i < bits.Count; i++)
|
||||
{
|
||||
if (bits[i] && i != skipIndex)
|
||||
yield return new RibbonResult(names[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsAllowedInContest4(int species) => species != 201 && species != 132; // Disallow Unown and Ditto
|
||||
|
||||
private static bool IsAllowedBattleFrontier(int species) => !Legal.BattleFrontierBanlist.Contains(species);
|
||||
|
@ -491,15 +517,27 @@ namespace PKHeX.Core
|
|||
return IsAllowedBattleFrontier(species);
|
||||
}
|
||||
|
||||
private static bool CanHaveFootprintRibbon(PKM pkm, int gen)
|
||||
private static bool CanHaveFootprintRibbon(PKM pkm, IReadOnlyList<EvoCriteria>[] evos, int gen)
|
||||
{
|
||||
if (gen <= 4) // Friendship Check unnecessary - can decrease after obtaining ribbon.
|
||||
return true;
|
||||
// Gen5: Can't obtain
|
||||
if (pkm.Format < 6)
|
||||
return false;
|
||||
|
||||
// Gen6/7: Increase level by 30 from original level
|
||||
if (pkm.Format >= 6 && (gen != 8 && !pkm.GG) && (pkm.CurrentLevel - pkm.Met_Level >= 30))
|
||||
if (gen != 8 && !pkm.GG && (pkm.CurrentLevel - pkm.Met_Level >= 30))
|
||||
return true;
|
||||
|
||||
// Gen8-BDSP: Variable by species Footprint
|
||||
if (pkm.BDSP)
|
||||
{
|
||||
if (evos[8].Any(z => z.Species <= Legal.MaxSpeciesID_4 && !HasFootprintBDSP[z.Species]))
|
||||
return true; // no footprint
|
||||
if (pkm.CurrentLevel - pkm.Met_Level >= 30)
|
||||
return true; // traveled well
|
||||
}
|
||||
|
||||
// Gen8: Can't obtain
|
||||
return false;
|
||||
}
|
||||
|
@ -525,5 +563,60 @@ namespace PKHeX.Core
|
|||
{
|
||||
return gen == 3 && IsAllowedBattleFrontier(pkm.Species);
|
||||
}
|
||||
|
||||
// Footprint type is not Type 5, requiring 30 levels.
|
||||
private static readonly bool[] HasFootprintBDSP =
|
||||
{
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, false, true, true, false, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, false, false, true, false,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, false, false, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
false, false, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, false, true, true,
|
||||
false, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, false, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, false, true, true, false, false, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, false, true, true, true, true, true, true,
|
||||
true, true, true, false, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, false, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, false, true, false, true,
|
||||
true, true, true, false, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
false, true, true, true, true, true, true, true, true, false,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, false, false, true,
|
||||
true, true, true, false, false, false, false, false, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, false, true, false, false, true, false, false, false,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, false, false, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, true, true, true, true, true, true, true, true,
|
||||
true, true, false, true, true, true, true, true, true, true,
|
||||
true, true, true, true, false, true, false, true, true, true,
|
||||
true, true, true, true, true, true, false, true, true, true,
|
||||
true, true, true, true,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,9 +125,16 @@ namespace PKHeX.Core
|
|||
public void VerifyTransferLegalityG8(LegalityAnalysis data)
|
||||
{
|
||||
var pkm = data.pkm;
|
||||
if (pkm is PB8 pb8)
|
||||
{
|
||||
VerifyTransferLegalityG8(data, pb8);
|
||||
return;
|
||||
}
|
||||
|
||||
// PK8
|
||||
int species = pkm.Species;
|
||||
var pi = (PersonalInfoSWSH)PersonalTable.SWSH.GetFormEntry(species, pkm.Form);
|
||||
if (!pi.IsPresentInGame) // Can't transfer
|
||||
if (!pi.IsPresentInGame || pkm.BDSP) // Can't transfer
|
||||
{
|
||||
data.AddLine(GetInvalid(LTransferBad));
|
||||
return;
|
||||
|
@ -153,6 +160,19 @@ namespace PKHeX.Core
|
|||
}
|
||||
}
|
||||
|
||||
// bdsp logic
|
||||
private void VerifyTransferLegalityG8(LegalityAnalysis data, PB8 pk)
|
||||
{
|
||||
// Tracker value is set via Transfer across HOME.
|
||||
// No HOME access yet.
|
||||
if (pk is IHomeTrack { Tracker: not 0 })
|
||||
data.AddLine(GetInvalid(LTransferTrackerShouldBeZero));
|
||||
|
||||
var pi = (PersonalInfoBDSP)PersonalTable.BDSP.GetFormEntry(pk.Species, pk.Form);
|
||||
if (!pi.IsPresentInGame || !pk.BDSP) // Can't transfer
|
||||
data.AddLine(GetInvalid(LTransferBad));
|
||||
}
|
||||
|
||||
private void VerifyHOMETransfer(LegalityAnalysis data, PKM pkm)
|
||||
{
|
||||
if (pkm is not IScaledSize s)
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace PKHeX.Core
|
|||
/// <returns>A boolean indicating whether or not the given length is valid for a mystery gift.</returns>
|
||||
public static bool IsMysteryGift(long len) => Sizes.Contains((int)len);
|
||||
|
||||
private static readonly HashSet<int> Sizes = new() { WC8.Size, WC6Full.Size, WC6.Size, PGF.Size, PGT.Size, PCD.Size };
|
||||
private static readonly HashSet<int> Sizes = new() { WB8.Size, WC8.Size, WC6Full.Size, WC6.Size, PGF.Size, PGT.Size, PCD.Size };
|
||||
|
||||
/// <summary>
|
||||
/// Converts the given data to a <see cref="MysteryGift"/>.
|
||||
|
@ -35,6 +35,7 @@ namespace PKHeX.Core
|
|||
WB7.Size when ext == ".wb7" => new WB7(data),
|
||||
WR7.Size when ext == ".wr7" => new WR7(data),
|
||||
WC8.Size when ext is ".wc8" or ".wc8full" => new WC8(data),
|
||||
WB8.Size when ext is ".wb8" => new WB8(data),
|
||||
|
||||
WB7.SizeFull when ext == ".wb7full" => new WB7(data),
|
||||
WC6Full.Size when ext == ".wc6full" => new WC6Full(data).Gift,
|
||||
|
@ -54,6 +55,7 @@ namespace PKHeX.Core
|
|||
PGF.Size => new PGF(data),
|
||||
WR7.Size => new WR7(data),
|
||||
WC8.Size => new WC8(data),
|
||||
WB8.Size => new WB8(data),
|
||||
|
||||
// WC6/WC7: Check year
|
||||
WC6.Size => BitConverter.ToUInt32(data, 0x4C) / 10000 < 2000 ? new WC7(data) : new WC6(data),
|
||||
|
|
750
PKHeX.Core/MysteryGifts/WB8.cs
Normal file
750
PKHeX.Core/MysteryGifts/WB8.cs
Normal file
|
@ -0,0 +1,750 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using static PKHeX.Core.RibbonIndex;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Generation 8b Mystery Gift Template File
|
||||
/// </summary>
|
||||
public sealed class WB8 : DataMysteryGift, ILangNick, INature, IRibbonIndex, IContestStats, ILangNicknamedTemplate,
|
||||
IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetMark8
|
||||
{
|
||||
public const int Size = 0x2DC;
|
||||
public const int CardStart = 0x0;
|
||||
|
||||
public override int Generation => 8;
|
||||
|
||||
public enum GiftType : byte
|
||||
{
|
||||
None = 0,
|
||||
Pokemon = 1,
|
||||
Item = 2,
|
||||
BP = 3,
|
||||
Clothing = 4,
|
||||
Money = 5,
|
||||
UnderGroundItem = 6,
|
||||
}
|
||||
|
||||
public WB8() : this(new byte[Size]) { }
|
||||
public WB8(byte[] data) : base(data) { }
|
||||
|
||||
// TODO: public byte RestrictVersion?
|
||||
|
||||
public bool CanBeReceivedByVersion(int v) => v is (int) GameVersion.BD or (int) GameVersion.SP;
|
||||
|
||||
// General Card Properties
|
||||
|
||||
// +0x0: Timestamp
|
||||
|
||||
public override int CardID
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, CardStart + 0x8);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x8);
|
||||
}
|
||||
|
||||
public byte CardFlags { get => Data[CardStart + 0x10]; set => Data[CardStart + 0x10] = value; }
|
||||
public GiftType CardType { get => (GiftType)Data[CardStart + 0x11]; set => Data[CardStart + 0x11] = (byte)value; }
|
||||
public bool GiftRepeatable { get => (CardFlags & 1) == 0; set => CardFlags = (byte)((CardFlags & ~1) | (value ? 0 : 1)); }
|
||||
public bool GiftOncePerDay { get => (CardFlags & 4) == 4; set => CardFlags = (byte)((CardFlags & ~4) | (value ? 4 : 0)); }
|
||||
public override bool GiftUsed { get => false; set { } }
|
||||
|
||||
public int CardTitleIndex
|
||||
{
|
||||
get => Data[CardStart + 0x12];
|
||||
set => Data[CardStart + 0x12] = (byte) value;
|
||||
}
|
||||
|
||||
public override string CardTitle
|
||||
{
|
||||
get => "Mystery Gift"; // TODO: Use text string from CardTitleIndex
|
||||
set => throw new Exception();
|
||||
}
|
||||
|
||||
// Item Properties
|
||||
public override bool IsItem { get => CardType == GiftType.Item; set { if (value) CardType = GiftType.Item; } }
|
||||
|
||||
public override int ItemID
|
||||
{
|
||||
get => GetItem(0);
|
||||
set => SetItem(0, (ushort)value);
|
||||
}
|
||||
|
||||
public override int Quantity
|
||||
{
|
||||
get => GetQuantity(0);
|
||||
set => SetQuantity(0, (ushort)value);
|
||||
}
|
||||
|
||||
public int GetItem(int index) => BitConverter.ToUInt16(Data, CardStart + 0x20 + (0x10 * index));
|
||||
public void SetItem(int index, ushort item) => BitConverter.GetBytes(item).CopyTo(Data, CardStart + 0x20 + (0x10 * index));
|
||||
public int GetQuantity(int index) => BitConverter.ToUInt16(Data, CardStart + 0x22 + (0x10 * index));
|
||||
public void SetQuantity(int index, ushort quantity) => BitConverter.GetBytes(quantity).CopyTo(Data, CardStart + 0x22 + (0x10 * index));
|
||||
|
||||
// Pokémon Properties
|
||||
public override bool IsPokémon { get => CardType == GiftType.Pokemon; set { if (value) CardType = GiftType.Pokemon; } }
|
||||
|
||||
public override bool IsShiny
|
||||
{
|
||||
get
|
||||
{
|
||||
var type = PIDType;
|
||||
if (type is Shiny.AlwaysStar or Shiny.AlwaysSquare)
|
||||
return true;
|
||||
if (type != Shiny.FixedValue)
|
||||
return false;
|
||||
|
||||
// Player owned anti-shiny fixed PID
|
||||
if (TID == 0 && SID == 0)
|
||||
return false;
|
||||
|
||||
var pid = PID;
|
||||
var psv = (int)((pid >> 16 ^ (pid & 0xFFFF)) >> 4);
|
||||
var tsv = (TID ^ SID) >> 4;
|
||||
return (psv ^ tsv) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
public override int TID
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, CardStart + 0x20);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x20);
|
||||
}
|
||||
|
||||
public override int SID {
|
||||
get => BitConverter.ToUInt16(Data, CardStart + 0x22);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x22);
|
||||
}
|
||||
|
||||
public int OriginGame
|
||||
{
|
||||
get => BitConverter.ToInt32(Data, CardStart + 0x24);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, CardStart + 0x24);
|
||||
}
|
||||
|
||||
public uint EncryptionConstant
|
||||
{
|
||||
get => BitConverter.ToUInt32(Data, CardStart + 0x28);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, CardStart + 0x28);
|
||||
}
|
||||
|
||||
public uint PID
|
||||
{
|
||||
get => BitConverter.ToUInt32(Data, CardStart + 0x2C);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, CardStart + 0x2C);
|
||||
}
|
||||
|
||||
// Nicknames, OT Names 0x30 - 0x270
|
||||
public override int EggLocation { get => BitConverter.ToUInt16(Data, CardStart + 0x270); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x270); }
|
||||
public int MetLocation { get => BitConverter.ToUInt16(Data, CardStart + 0x272); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x272); }
|
||||
|
||||
public override int Ball
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, CardStart + 0x274);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x274);
|
||||
}
|
||||
|
||||
public override int HeldItem
|
||||
{
|
||||
get => BitConverter.ToUInt16(Data, CardStart + 0x276);
|
||||
set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x276);
|
||||
}
|
||||
|
||||
public int Move1 { get => BitConverter.ToUInt16(Data, CardStart + 0x278); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x278); }
|
||||
public int Move2 { get => BitConverter.ToUInt16(Data, CardStart + 0x27A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x27A); }
|
||||
public int Move3 { get => BitConverter.ToUInt16(Data, CardStart + 0x27C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x27C); }
|
||||
public int Move4 { get => BitConverter.ToUInt16(Data, CardStart + 0x27E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x27E); }
|
||||
public int RelearnMove1 { get => BitConverter.ToUInt16(Data, CardStart + 0x280); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x280); }
|
||||
public int RelearnMove2 { get => BitConverter.ToUInt16(Data, CardStart + 0x282); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x282); }
|
||||
public int RelearnMove3 { get => BitConverter.ToUInt16(Data, CardStart + 0x284); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x284); }
|
||||
public int RelearnMove4 { get => BitConverter.ToUInt16(Data, CardStart + 0x286); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x286); }
|
||||
|
||||
public override int Species { get => BitConverter.ToUInt16(Data, CardStart + 0x288); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, CardStart + 0x288); }
|
||||
public override int Form { get => Data[CardStart + 0x28A]; set => Data[CardStart + 0x28A] = (byte)value; }
|
||||
public override int Gender { get => Data[CardStart + 0x28B]; set => Data[CardStart + 0x28B] = (byte)value; }
|
||||
public override int Level { get => Data[CardStart + 0x28C]; set => Data[CardStart + 0x28C] = (byte)value; }
|
||||
public override bool IsEgg { get => Data[CardStart + 0x28D] == 1; set => Data[CardStart + 0x28D] = value ? (byte)1 : (byte)0; }
|
||||
public int Nature { get => (sbyte)Data[CardStart + 0x28E]; set => Data[CardStart + 0x28E] = (byte)value; }
|
||||
public override int AbilityType { get => Data[CardStart + 0x28F]; set => Data[CardStart + 0x28F] = (byte)value; }
|
||||
|
||||
private byte PIDTypeValue => Data[CardStart + 0x290];
|
||||
|
||||
public Shiny PIDType => PIDTypeValue switch
|
||||
{
|
||||
0 => Shiny.Never,
|
||||
1 => Shiny.Random,
|
||||
2 => Shiny.AlwaysStar,
|
||||
3 => Shiny.AlwaysSquare,
|
||||
4 => Shiny.FixedValue,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(PIDType)),
|
||||
};
|
||||
|
||||
public int MetLevel { get => Data[CardStart + 0x291]; set => Data[CardStart + 0x291] = (byte)value; }
|
||||
|
||||
// Ribbons 0x24C-0x26C
|
||||
private const int RibbonBytesOffset = 0x292;
|
||||
private const int RibbonBytesCount = 0x20;
|
||||
private const int RibbonByteNone = 0xFF; // signed -1
|
||||
|
||||
public bool HasMark()
|
||||
{
|
||||
for (int i = 0; i < RibbonBytesCount; i++)
|
||||
{
|
||||
var val = Data[RibbonBytesOffset + i];
|
||||
if (val == RibbonByteNone)
|
||||
return false;
|
||||
if ((RibbonIndex)val is >= MarkLunchtime and <= MarkSlump)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public byte GetRibbonAtIndex(int byteIndex)
|
||||
{
|
||||
if ((uint)byteIndex >= RibbonBytesCount)
|
||||
throw new IndexOutOfRangeException();
|
||||
return Data[RibbonBytesOffset + byteIndex];
|
||||
}
|
||||
|
||||
public void SetRibbonAtIndex(int byteIndex, byte ribbonIndex)
|
||||
{
|
||||
if ((uint)byteIndex >= RibbonBytesCount)
|
||||
throw new IndexOutOfRangeException();
|
||||
Data[RibbonBytesOffset + byteIndex] = ribbonIndex;
|
||||
}
|
||||
|
||||
public int IV_HP { get => Data[CardStart + 0x2B2]; set => Data[CardStart + 0x2B2] = (byte)value; }
|
||||
public int IV_ATK { get => Data[CardStart + 0x2B3]; set => Data[CardStart + 0x2B3] = (byte)value; }
|
||||
public int IV_DEF { get => Data[CardStart + 0x2B4]; set => Data[CardStart + 0x2B4] = (byte)value; }
|
||||
public int IV_SPE { get => Data[CardStart + 0x2B5]; set => Data[CardStart + 0x2B5] = (byte)value; }
|
||||
public int IV_SPA { get => Data[CardStart + 0x2B6]; set => Data[CardStart + 0x2B6] = (byte)value; }
|
||||
public int IV_SPD { get => Data[CardStart + 0x2B7]; set => Data[CardStart + 0x2B7] = (byte)value; }
|
||||
|
||||
public int OTGender { get => Data[CardStart + 0x2B8]; set => Data[CardStart + 0x2B8] = (byte)value; }
|
||||
|
||||
public int EV_HP { get => Data[CardStart + 0x2B9]; set => Data[CardStart + 0x2B9] = (byte)value; }
|
||||
public int EV_ATK { get => Data[CardStart + 0x2BA]; set => Data[CardStart + 0x2BA] = (byte)value; }
|
||||
public int EV_DEF { get => Data[CardStart + 0x2BB]; set => Data[CardStart + 0x2BB] = (byte)value; }
|
||||
public int EV_SPE { get => Data[CardStart + 0x2BC]; set => Data[CardStart + 0x2BC] = (byte)value; }
|
||||
public int EV_SPA { get => Data[CardStart + 0x2BD]; set => Data[CardStart + 0x2BD] = (byte)value; }
|
||||
public int EV_SPD { get => Data[CardStart + 0x2BE]; set => Data[CardStart + 0x2BE] = (byte)value; }
|
||||
|
||||
public byte CNT_Cool { get => Data[0x2BF]; set => Data[0x2BF] = value; }
|
||||
public byte CNT_Beauty { get => Data[0x2C0]; set => Data[0x2C0] = value; }
|
||||
public byte CNT_Cute { get => Data[0x2C1]; set => Data[0x2C1] = value; }
|
||||
public byte CNT_Smart { get => Data[0x2C2]; set => Data[0x2C2] = value; }
|
||||
public byte CNT_Tough { get => Data[0x2C3]; set => Data[0x2C3] = value; }
|
||||
public byte CNT_Sheen { get => Data[0x2C4]; set => Data[0x2C4] = value; }
|
||||
|
||||
// Meta Accessible Properties
|
||||
public override int[] IVs
|
||||
{
|
||||
get => new[] { IV_HP, IV_ATK, IV_DEF, IV_SPE, IV_SPA, IV_SPD };
|
||||
set
|
||||
{
|
||||
if (value.Length != 6) return;
|
||||
IV_HP = value[0]; IV_ATK = value[1]; IV_DEF = value[2];
|
||||
IV_SPE = value[3]; IV_SPA = value[4]; IV_SPD = value[5];
|
||||
}
|
||||
}
|
||||
|
||||
public int[] EVs
|
||||
{
|
||||
get => new[] { EV_HP, EV_ATK, EV_DEF, EV_SPE, EV_SPA, EV_SPD };
|
||||
set
|
||||
{
|
||||
if (value.Length != 6) return;
|
||||
EV_HP = value[0]; EV_ATK = value[1]; EV_DEF = value[2];
|
||||
EV_SPE = value[3]; EV_SPA = value[4]; EV_SPD = value[5];
|
||||
}
|
||||
}
|
||||
|
||||
public bool GetIsNicknamed(int language) => BitConverter.ToUInt16(Data, GetNicknameOffset(language)) != 0;
|
||||
|
||||
public bool CanBeAnyLanguage()
|
||||
{
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
var ofs = GetLanguageOffset(i);
|
||||
var lang = BitConverter.ToInt16(Data, ofs);
|
||||
if (lang != 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool CanHaveLanguage(int language)
|
||||
{
|
||||
if (language is < (int)LanguageID.Japanese or > (int)LanguageID.ChineseT)
|
||||
return false;
|
||||
|
||||
if (CanBeAnyLanguage())
|
||||
return true;
|
||||
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
var ofs = GetLanguageOffset(i);
|
||||
var lang = BitConverter.ToInt16(Data, ofs);
|
||||
if (lang == language)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int GetLanguage(int redeemLanguage) => Data[GetLanguageOffset(GetLanguageIndex(redeemLanguage))];
|
||||
private static int GetLanguageOffset(int index) => 0x30 + (index * 0x20) + 0x1A;
|
||||
|
||||
public bool GetHasOT(int language) => BitConverter.ToUInt16(Data, GetOTOffset(language)) != 0;
|
||||
|
||||
private static int GetLanguageIndex(int language)
|
||||
{
|
||||
var lang = (LanguageID) language;
|
||||
if (lang is < LanguageID.Japanese or LanguageID.UNUSED_6 or > LanguageID.ChineseT)
|
||||
return (int) LanguageID.English; // fallback
|
||||
return lang < LanguageID.UNUSED_6 ? language - 1 : language - 2;
|
||||
}
|
||||
|
||||
public override int Location { get => MetLocation; set => MetLocation = (ushort)value; }
|
||||
|
||||
public override IReadOnlyList<int> Moves
|
||||
{
|
||||
get => new[] { Move1, Move2, Move3, Move4 };
|
||||
set
|
||||
{
|
||||
if (value.Count > 0) Move1 = value[0];
|
||||
if (value.Count > 1) Move2 = value[1];
|
||||
if (value.Count > 2) Move3 = value[2];
|
||||
if (value.Count > 3) Move4 = value[3];
|
||||
}
|
||||
}
|
||||
|
||||
public override IReadOnlyList<int> Relearn
|
||||
{
|
||||
get => new[] { RelearnMove1, RelearnMove2, RelearnMove3, RelearnMove4 };
|
||||
set
|
||||
{
|
||||
if (value.Count > 0) RelearnMove1 = value[0];
|
||||
if (value.Count > 1) RelearnMove2 = value[1];
|
||||
if (value.Count > 2) RelearnMove3 = value[2];
|
||||
if (value.Count > 3) RelearnMove4 = value[3];
|
||||
}
|
||||
}
|
||||
|
||||
public override string OT_Name { get; set; } = string.Empty;
|
||||
public string Nickname => string.Empty;
|
||||
public bool IsNicknamed => false;
|
||||
public int Language => 2;
|
||||
|
||||
public string GetNickname(int language) => StringConverter.GetString7b(Data, GetNicknameOffset(language), 0x1A);
|
||||
public void SetNickname(int language, string value) => StringConverter.SetString7b(value, 12, 13).CopyTo(Data, GetNicknameOffset(language));
|
||||
|
||||
public string GetOT(int language) => StringConverter.GetString7b(Data, GetOTOffset(language), 0x1A);
|
||||
public void SetOT(int language, string value) => StringConverter.SetString7b(value, 12, 13).CopyTo(Data, GetOTOffset(language));
|
||||
|
||||
private static int GetNicknameOffset(int language)
|
||||
{
|
||||
int index = GetLanguageIndex(language);
|
||||
return 0x30 + (index * 0x20);
|
||||
}
|
||||
|
||||
private static int GetOTOffset(int language)
|
||||
{
|
||||
int index = GetLanguageIndex(language);
|
||||
return 0x150 + (index * 0x20);
|
||||
}
|
||||
|
||||
public bool CanHandleOT(int language) => !GetHasOT(language);
|
||||
|
||||
public override GameVersion Version
|
||||
{
|
||||
get => OriginGame != 0 ? (GameVersion)OriginGame : GameVersion.BDSP;
|
||||
set { }
|
||||
}
|
||||
|
||||
public override PKM ConvertToPKM(ITrainerInfo sav, EncounterCriteria criteria)
|
||||
{
|
||||
if (!IsPokémon)
|
||||
throw new ArgumentException(nameof(IsPokémon));
|
||||
|
||||
int currentLevel = Level > 0 ? Level : (1 + Util.Rand.Next(100));
|
||||
int metLevel = MetLevel > 0 ? MetLevel : currentLevel;
|
||||
var pi = PersonalTable.BDSP.GetFormEntry(Species, Form);
|
||||
var language = sav.Language;
|
||||
var OT = GetOT(language);
|
||||
bool hasOT = GetHasOT(language);
|
||||
|
||||
var pk = new PB8
|
||||
{
|
||||
EncryptionConstant = EncryptionConstant != 0 ? EncryptionConstant : Util.Rand32(),
|
||||
TID = TID,
|
||||
SID = SID,
|
||||
Species = Species,
|
||||
Form = Form,
|
||||
CurrentLevel = currentLevel,
|
||||
Ball = Ball != 0 ? Ball : 4, // Default is Pokeball
|
||||
Met_Level = metLevel,
|
||||
HeldItem = HeldItem,
|
||||
|
||||
EXP = Experience.GetEXP(currentLevel, pi.EXPGrowth),
|
||||
|
||||
Move1 = Move1,
|
||||
Move2 = Move2,
|
||||
Move3 = Move3,
|
||||
Move4 = Move4,
|
||||
RelearnMove1 = RelearnMove1,
|
||||
RelearnMove2 = RelearnMove2,
|
||||
RelearnMove3 = RelearnMove3,
|
||||
RelearnMove4 = RelearnMove4,
|
||||
|
||||
Version = OriginGame != 0 ? OriginGame : sav.Game,
|
||||
|
||||
OT_Name = OT.Length > 0 ? OT : sav.OT,
|
||||
OT_Gender = OTGender < 2 ? OTGender : sav.Gender,
|
||||
HT_Name = hasOT ? sav.OT : string.Empty,
|
||||
HT_Gender = hasOT ? sav.Gender : 0,
|
||||
HT_Language = hasOT ? language : 0,
|
||||
CurrentHandler = hasOT ? 1 : 0,
|
||||
OT_Friendship = pi.BaseFriendship,
|
||||
|
||||
FatefulEncounter = true,
|
||||
|
||||
EVs = EVs,
|
||||
|
||||
CNT_Cool = CNT_Cool,
|
||||
CNT_Beauty = CNT_Beauty,
|
||||
CNT_Cute = CNT_Cute,
|
||||
CNT_Smart = CNT_Smart,
|
||||
CNT_Tough = CNT_Tough,
|
||||
CNT_Sheen = CNT_Sheen,
|
||||
|
||||
Met_Location = MetLocation,
|
||||
Egg_Location = EggLocation,
|
||||
};
|
||||
|
||||
if (Species == (int)Core.Species.Manaphy && IsEgg)
|
||||
{
|
||||
pk.Egg_Location = MetLocation;
|
||||
pk.Met_Location = Locations.Default8bNone;
|
||||
pk.IsNicknamed = false;
|
||||
}
|
||||
pk.SetMaximumPPCurrent();
|
||||
|
||||
if ((sav.Generation > Generation && OriginGame == 0) || !CanBeReceivedByVersion(pk.Version))
|
||||
{
|
||||
// give random valid game
|
||||
var rnd = Util.Rand;
|
||||
do { pk.Version = (int)GameVersion.SW + rnd.Next(2); }
|
||||
while (!CanBeReceivedByVersion(pk.Version));
|
||||
}
|
||||
|
||||
if (pk.TID == 0 && pk.SID == 0)
|
||||
{
|
||||
pk.TID = sav.TID;
|
||||
pk.SID = sav.SID;
|
||||
}
|
||||
|
||||
pk.MetDate = DateTime.Now;
|
||||
|
||||
var nickname_language = GetLanguage(language);
|
||||
pk.Language = nickname_language != 0 ? nickname_language : sav.Language;
|
||||
pk.IsNicknamed = !IsEgg && GetIsNicknamed(language);
|
||||
pk.Nickname = pk.IsNicknamed ? GetNickname(language) : SpeciesName.GetSpeciesNameGeneration(Species, pk.Language, Generation);
|
||||
|
||||
for (var i = 0; i < RibbonBytesCount; i++)
|
||||
{
|
||||
var ribbon = GetRibbonAtIndex(i);
|
||||
if (ribbon != RibbonByteNone)
|
||||
pk.SetRibbon(ribbon);
|
||||
}
|
||||
|
||||
SetPINGA(pk, criteria);
|
||||
|
||||
if (IsEgg)
|
||||
SetEggMetData(pk);
|
||||
pk.CurrentFriendship = pk.IsEgg ? pi.HatchCycles : pi.BaseFriendship;
|
||||
|
||||
pk.HeightScalar = PokeSizeUtil.GetRandomScalar();
|
||||
pk.WeightScalar = PokeSizeUtil.GetRandomScalar();
|
||||
|
||||
pk.ResetPartyStats();
|
||||
pk.RefreshChecksum();
|
||||
return pk;
|
||||
}
|
||||
|
||||
private void SetEggMetData(PKM pk)
|
||||
{
|
||||
pk.IsEgg = true;
|
||||
pk.EggMetDate = DateTime.Now;
|
||||
pk.Nickname = SpeciesName.GetSpeciesNameGeneration(0, pk.Language, Generation);
|
||||
pk.IsNicknamed = true;
|
||||
}
|
||||
|
||||
private void SetPINGA(PKM pk, EncounterCriteria criteria)
|
||||
{
|
||||
var pi = PersonalTable.BDSP.GetFormEntry(Species, Form);
|
||||
pk.Nature = (int)criteria.GetNature(Nature == -1 ? Core.Nature.Random : (Nature)Nature);
|
||||
pk.StatNature = pk.Nature;
|
||||
pk.Gender = criteria.GetGender(Gender, pi);
|
||||
var av = GetAbilityIndex(criteria);
|
||||
pk.RefreshAbility(av);
|
||||
SetPID(pk);
|
||||
SetIVs(pk);
|
||||
}
|
||||
|
||||
private int GetAbilityIndex(EncounterCriteria criteria) => AbilityType switch
|
||||
{
|
||||
00 or 01 or 02 => AbilityType, // Fixed 0/1/2
|
||||
03 or 04 => criteria.GetAbilityFromType(AbilityType), // 0/1 or 0/1/H
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(AbilityType)),
|
||||
};
|
||||
|
||||
private uint GetPID(ITrainerID tr, byte type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
0 => GetAntishiny(tr), // Random, Never Shiny
|
||||
1 => Util.Rand32(), // Random, Any
|
||||
2 => (uint) (((tr.TID ^ tr.SID ^ (PID & 0xFFFF) ^ 1) << 16) | (PID & 0xFFFF)), // Fixed, Force Star
|
||||
3 => (uint) (((tr.TID ^ tr.SID ^ (PID & 0xFFFF) ^ 0) << 16) | (PID & 0xFFFF)), // Fixed, Force Square
|
||||
4 => PID, // Fixed, Force Value
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(type)),
|
||||
};
|
||||
|
||||
static uint GetAntishiny(ITrainerID tr)
|
||||
{
|
||||
var pid = Util.Rand32();
|
||||
if (tr.IsShiny(pid, 8))
|
||||
return pid ^ 0x1000_0000;
|
||||
return pid;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetPID(PKM pk)
|
||||
{
|
||||
pk.PID = GetPID(pk, PIDTypeValue);
|
||||
}
|
||||
|
||||
private void SetIVs(PKM pk)
|
||||
{
|
||||
int[] finalIVs = new int[6];
|
||||
var ivflag = Array.Find(IVs, iv => (byte)(iv - 0xFC) < 3);
|
||||
var rng = Util.Rand;
|
||||
if (ivflag == 0) // Random IVs
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
finalIVs[i] = IVs[i] > 31 ? rng.Next(32) : IVs[i];
|
||||
}
|
||||
else // 1/2/3 perfect IVs
|
||||
{
|
||||
int IVCount = ivflag - 0xFB;
|
||||
do { finalIVs[rng.Next(6)] = 31; }
|
||||
while (finalIVs.Count(iv => iv == 31) < IVCount);
|
||||
for (int i = 0; i < 6; i++)
|
||||
finalIVs[i] = finalIVs[i] == 31 ? 31 : rng.Next(32);
|
||||
}
|
||||
pk.IVs = finalIVs;
|
||||
}
|
||||
|
||||
public override bool IsMatchExact(PKM pkm, DexLevel evo)
|
||||
{
|
||||
if ((short)pkm.Egg_Location == Locations.Default8bNone) // Not Egg
|
||||
{
|
||||
if (OTGender < 2)
|
||||
{
|
||||
if (SID != pkm.SID) return false;
|
||||
if (TID != pkm.TID) return false;
|
||||
if (OTGender != pkm.OT_Gender) return false;
|
||||
}
|
||||
|
||||
if (!CanBeAnyLanguage() && !CanHaveLanguage(pkm.Language))
|
||||
return false;
|
||||
|
||||
var OT = GetOT(pkm.Language); // May not be guaranteed to work.
|
||||
if (!string.IsNullOrEmpty(OT) && OT != pkm.OT_Name) return false;
|
||||
if (OriginGame != 0 && OriginGame != pkm.Version) return false;
|
||||
if (EncryptionConstant != 0)
|
||||
{
|
||||
if (EncryptionConstant != pkm.EncryptionConstant)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (Form != evo.Form && !FormInfo.IsFormChangeable(Species, Form, pkm.Form, pkm.Format))
|
||||
return false;
|
||||
|
||||
if (IsEgg)
|
||||
{
|
||||
var eggloc = Species == (int)Core.Species.Manaphy ? MetLocation : EggLocation;
|
||||
if (eggloc != pkm.Egg_Location) // traded
|
||||
{
|
||||
if (pkm.Egg_Location != Locations.LinkTrade6NPC)
|
||||
return false;
|
||||
if (PIDType == Shiny.Random && pkm.IsShiny && pkm.ShinyXor > 1)
|
||||
return false; // shiny traded egg will always have xor0/1.
|
||||
}
|
||||
if (!PIDType.IsValid(pkm))
|
||||
{
|
||||
return false; // can't be traded away for unshiny
|
||||
}
|
||||
|
||||
if (pkm.IsEgg && !pkm.IsNative)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!PIDType.IsValid(pkm)) return false;
|
||||
if (EggLocation != pkm.Egg_Location) return false;
|
||||
if (MetLocation != pkm.Met_Location) return false;
|
||||
}
|
||||
|
||||
if (MetLevel != 0 && MetLevel != pkm.Met_Level) return false;
|
||||
if ((Ball == 0 ? 4 : Ball) != pkm.Ball) return false;
|
||||
if (OTGender < 2 && OTGender != pkm.OT_Gender) return false;
|
||||
if (Nature != -1 && pkm.Nature != Nature) return false;
|
||||
if (Gender != 3 && Gender != pkm.Gender) return false;
|
||||
|
||||
// PID Types 0 and 1 do not use the fixed PID value.
|
||||
// Values 2,3 are specific shiny states, and 4 is fixed value.
|
||||
// 2,3,4 can change if it is a traded egg to ensure the same shiny state.
|
||||
var type = PIDTypeValue;
|
||||
if (type <= 1)
|
||||
return true;
|
||||
return pkm.PID == GetPID(pkm, type);
|
||||
}
|
||||
|
||||
protected override bool IsMatchDeferred(PKM pkm) => Species != pkm.Species;
|
||||
protected override bool IsMatchPartial(PKM pkm) => false; // no version compatibility checks yet.
|
||||
|
||||
#region Lazy Ribbon Implementation
|
||||
public bool RibbonEarth { get => this.GetRibbonIndex(Earth); set => this.SetRibbonIndex(Earth, value); }
|
||||
public bool RibbonNational { get => this.GetRibbonIndex(National); set => this.SetRibbonIndex(National, value); }
|
||||
public bool RibbonCountry { get => this.GetRibbonIndex(Country); set => this.SetRibbonIndex(Country, value); }
|
||||
public bool RibbonChampionBattle { get => this.GetRibbonIndex(ChampionBattle); set => this.SetRibbonIndex(ChampionBattle, value); }
|
||||
public bool RibbonChampionRegional { get => this.GetRibbonIndex(ChampionRegional); set => this.SetRibbonIndex(ChampionRegional, value); }
|
||||
public bool RibbonChampionNational { get => this.GetRibbonIndex(ChampionNational); set => this.SetRibbonIndex(ChampionNational, value); }
|
||||
public bool RibbonClassic { get => this.GetRibbonIndex(Classic); set => this.SetRibbonIndex(Classic, value); }
|
||||
public bool RibbonWishing { get => this.GetRibbonIndex(Wishing); set => this.SetRibbonIndex(Wishing, value); }
|
||||
public bool RibbonPremier { get => this.GetRibbonIndex(Premier); set => this.SetRibbonIndex(Premier, value); }
|
||||
public bool RibbonEvent { get => this.GetRibbonIndex(Event); set => this.SetRibbonIndex(Event, value); }
|
||||
public bool RibbonBirthday { get => this.GetRibbonIndex(Birthday); set => this.SetRibbonIndex(Birthday, value); }
|
||||
public bool RibbonSpecial { get => this.GetRibbonIndex(Special); set => this.SetRibbonIndex(Special, value); }
|
||||
public bool RibbonWorld { get => this.GetRibbonIndex(World); set => this.SetRibbonIndex(World, value); }
|
||||
public bool RibbonChampionWorld { get => this.GetRibbonIndex(ChampionWorld); set => this.SetRibbonIndex(ChampionWorld, value); }
|
||||
public bool RibbonSouvenir { get => this.GetRibbonIndex(Souvenir); set => this.SetRibbonIndex(Souvenir, value); }
|
||||
public bool RibbonChampionG3 { get => this.GetRibbonIndex(ChampionG3); set => this.SetRibbonIndex(ChampionG3, value); }
|
||||
public bool RibbonArtist { get => this.GetRibbonIndex(Artist); set => this.SetRibbonIndex(Artist, value); }
|
||||
public bool RibbonEffort { get => this.GetRibbonIndex(Effort); set => this.SetRibbonIndex(Effort, value); }
|
||||
public bool RibbonChampionSinnoh { get => this.GetRibbonIndex(ChampionSinnoh); set => this.SetRibbonIndex(ChampionSinnoh, value); }
|
||||
public bool RibbonAlert { get => this.GetRibbonIndex(Alert); set => this.SetRibbonIndex(Alert, value); }
|
||||
public bool RibbonShock { get => this.GetRibbonIndex(Shock); set => this.SetRibbonIndex(Shock, value); }
|
||||
public bool RibbonDowncast { get => this.GetRibbonIndex(Downcast); set => this.SetRibbonIndex(Downcast, value); }
|
||||
public bool RibbonCareless { get => this.GetRibbonIndex(Careless); set => this.SetRibbonIndex(Careless, value); }
|
||||
public bool RibbonRelax { get => this.GetRibbonIndex(Relax); set => this.SetRibbonIndex(Relax, value); }
|
||||
public bool RibbonSnooze { get => this.GetRibbonIndex(Snooze); set => this.SetRibbonIndex(Snooze, value); }
|
||||
public bool RibbonSmile { get => this.GetRibbonIndex(Smile); set => this.SetRibbonIndex(Smile, value); }
|
||||
public bool RibbonGorgeous { get => this.GetRibbonIndex(Gorgeous); set => this.SetRibbonIndex(Gorgeous, value); }
|
||||
public bool RibbonRoyal { get => this.GetRibbonIndex(Royal); set => this.SetRibbonIndex(Royal, value); }
|
||||
public bool RibbonGorgeousRoyal { get => this.GetRibbonIndex(GorgeousRoyal); set => this.SetRibbonIndex(GorgeousRoyal, value); }
|
||||
public bool RibbonFootprint { get => this.GetRibbonIndex(Footprint); set => this.SetRibbonIndex(Footprint, value); }
|
||||
public bool RibbonRecord { get => this.GetRibbonIndex(Record); set => this.SetRibbonIndex(Record, value); }
|
||||
public bool RibbonLegend { get => this.GetRibbonIndex(Legend); set => this.SetRibbonIndex(Legend, value); }
|
||||
public bool RibbonChampionKalos { get => this.GetRibbonIndex(ChampionKalos); set => this.SetRibbonIndex(ChampionKalos, value); }
|
||||
public bool RibbonChampionG6Hoenn { get => this.GetRibbonIndex(ChampionG6Hoenn); set => this.SetRibbonIndex(ChampionG6Hoenn, value); }
|
||||
public bool RibbonBestFriends { get => this.GetRibbonIndex(BestFriends); set => this.SetRibbonIndex(BestFriends, value); }
|
||||
public bool RibbonTraining { get => this.GetRibbonIndex(Training); set => this.SetRibbonIndex(Training, value); }
|
||||
public bool RibbonBattlerSkillful { get => this.GetRibbonIndex(BattlerSkillful); set => this.SetRibbonIndex(BattlerSkillful, value); }
|
||||
public bool RibbonBattlerExpert { get => this.GetRibbonIndex(BattlerExpert); set => this.SetRibbonIndex(BattlerExpert, value); }
|
||||
public bool RibbonContestStar { get => this.GetRibbonIndex(ContestStar); set => this.SetRibbonIndex(ContestStar, value); }
|
||||
public bool RibbonMasterCoolness { get => this.GetRibbonIndex(MasterCoolness); set => this.SetRibbonIndex(MasterCoolness, value); }
|
||||
public bool RibbonMasterBeauty { get => this.GetRibbonIndex(MasterBeauty); set => this.SetRibbonIndex(MasterBeauty, value); }
|
||||
public bool RibbonMasterCuteness { get => this.GetRibbonIndex(MasterCuteness); set => this.SetRibbonIndex(MasterCuteness, value); }
|
||||
public bool RibbonMasterCleverness { get => this.GetRibbonIndex(MasterCleverness); set => this.SetRibbonIndex(MasterCleverness, value); }
|
||||
public bool RibbonMasterToughness { get => this.GetRibbonIndex(MasterToughness); set => this.SetRibbonIndex(MasterToughness, value); }
|
||||
|
||||
public int RibbonCountMemoryContest { get => 0; set { } }
|
||||
public int RibbonCountMemoryBattle { get => 0; set { } }
|
||||
|
||||
public bool RibbonChampionAlola { get => this.GetRibbonIndex(ChampionAlola); set => this.SetRibbonIndex(ChampionAlola, value); }
|
||||
public bool RibbonBattleRoyale { get => this.GetRibbonIndex(BattleRoyale); set => this.SetRibbonIndex(BattleRoyale, value); }
|
||||
public bool RibbonBattleTreeGreat { get => this.GetRibbonIndex(BattleTreeGreat); set => this.SetRibbonIndex(BattleTreeGreat, value); }
|
||||
public bool RibbonBattleTreeMaster { get => this.GetRibbonIndex(BattleTreeMaster); set => this.SetRibbonIndex(BattleTreeMaster, value); }
|
||||
public bool RibbonChampionGalar { get => this.GetRibbonIndex(ChampionGalar); set => this.SetRibbonIndex(ChampionGalar, value); }
|
||||
public bool RibbonTowerMaster { get => this.GetRibbonIndex(TowerMaster); set => this.SetRibbonIndex(TowerMaster, value); }
|
||||
public bool RibbonMasterRank { get => this.GetRibbonIndex(MasterRank); set => this.SetRibbonIndex(MasterRank, value); }
|
||||
public bool RibbonMarkLunchtime { get => this.GetRibbonIndex(MarkLunchtime); set => this.SetRibbonIndex(MarkLunchtime, value); }
|
||||
public bool RibbonMarkSleepyTime { get => this.GetRibbonIndex(MarkSleepyTime); set => this.SetRibbonIndex(MarkSleepyTime, value); }
|
||||
public bool RibbonMarkDusk { get => this.GetRibbonIndex(MarkDusk); set => this.SetRibbonIndex(MarkDusk, value); }
|
||||
public bool RibbonMarkDawn { get => this.GetRibbonIndex(MarkDawn); set => this.SetRibbonIndex(MarkDawn, value); }
|
||||
public bool RibbonMarkCloudy { get => this.GetRibbonIndex(MarkCloudy); set => this.SetRibbonIndex(MarkCloudy, value); }
|
||||
public bool RibbonMarkRainy { get => this.GetRibbonIndex(MarkRainy); set => this.SetRibbonIndex(MarkRainy, value); }
|
||||
public bool RibbonMarkStormy { get => this.GetRibbonIndex(MarkStormy); set => this.SetRibbonIndex(MarkStormy, value); }
|
||||
public bool RibbonMarkSnowy { get => this.GetRibbonIndex(MarkSnowy); set => this.SetRibbonIndex(MarkSnowy, value); }
|
||||
public bool RibbonMarkBlizzard { get => this.GetRibbonIndex(MarkBlizzard); set => this.SetRibbonIndex(MarkBlizzard, value); }
|
||||
public bool RibbonMarkDry { get => this.GetRibbonIndex(MarkDry); set => this.SetRibbonIndex(MarkDry, value); }
|
||||
public bool RibbonMarkSandstorm { get => this.GetRibbonIndex(MarkSandstorm); set => this.SetRibbonIndex(MarkSandstorm, value); }
|
||||
public bool RibbonMarkMisty { get => this.GetRibbonIndex(MarkMisty); set => this.SetRibbonIndex(MarkMisty, value); }
|
||||
public bool RibbonMarkDestiny { get => this.GetRibbonIndex(MarkDestiny); set => this.SetRibbonIndex(MarkDestiny, value); }
|
||||
public bool RibbonMarkFishing { get => this.GetRibbonIndex(MarkFishing); set => this.SetRibbonIndex(MarkFishing, value); }
|
||||
public bool RibbonMarkCurry { get => this.GetRibbonIndex(MarkCurry); set => this.SetRibbonIndex(MarkCurry, value); }
|
||||
public bool RibbonMarkUncommon { get => this.GetRibbonIndex(MarkUncommon); set => this.SetRibbonIndex(MarkUncommon, value); }
|
||||
public bool RibbonMarkRare { get => this.GetRibbonIndex(MarkRare); set => this.SetRibbonIndex(MarkRare, value); }
|
||||
public bool RibbonMarkRowdy { get => this.GetRibbonIndex(MarkRowdy); set => this.SetRibbonIndex(MarkRowdy, value); }
|
||||
public bool RibbonMarkAbsentMinded { get => this.GetRibbonIndex(MarkAbsentMinded); set => this.SetRibbonIndex(MarkAbsentMinded, value); }
|
||||
public bool RibbonMarkJittery { get => this.GetRibbonIndex(MarkJittery); set => this.SetRibbonIndex(MarkJittery, value); }
|
||||
public bool RibbonMarkExcited { get => this.GetRibbonIndex(MarkExcited); set => this.SetRibbonIndex(MarkExcited, value); }
|
||||
public bool RibbonMarkCharismatic { get => this.GetRibbonIndex(MarkCharismatic); set => this.SetRibbonIndex(MarkCharismatic, value); }
|
||||
public bool RibbonMarkCalmness { get => this.GetRibbonIndex(MarkCalmness); set => this.SetRibbonIndex(MarkCalmness, value); }
|
||||
public bool RibbonMarkIntense { get => this.GetRibbonIndex(MarkIntense); set => this.SetRibbonIndex(MarkIntense, value); }
|
||||
public bool RibbonMarkZonedOut { get => this.GetRibbonIndex(MarkZonedOut); set => this.SetRibbonIndex(MarkZonedOut, value); }
|
||||
public bool RibbonMarkJoyful { get => this.GetRibbonIndex(MarkJoyful); set => this.SetRibbonIndex(MarkJoyful, value); }
|
||||
public bool RibbonMarkAngry { get => this.GetRibbonIndex(MarkAngry); set => this.SetRibbonIndex(MarkAngry, value); }
|
||||
public bool RibbonMarkSmiley { get => this.GetRibbonIndex(MarkSmiley); set => this.SetRibbonIndex(MarkSmiley, value); }
|
||||
public bool RibbonMarkTeary { get => this.GetRibbonIndex(MarkTeary); set => this.SetRibbonIndex(MarkTeary, value); }
|
||||
public bool RibbonMarkUpbeat { get => this.GetRibbonIndex(MarkUpbeat); set => this.SetRibbonIndex(MarkUpbeat, value); }
|
||||
public bool RibbonMarkPeeved { get => this.GetRibbonIndex(MarkPeeved); set => this.SetRibbonIndex(MarkPeeved, value); }
|
||||
public bool RibbonMarkIntellectual { get => this.GetRibbonIndex(MarkIntellectual); set => this.SetRibbonIndex(MarkIntellectual, value); }
|
||||
public bool RibbonMarkFerocious { get => this.GetRibbonIndex(MarkFerocious); set => this.SetRibbonIndex(MarkFerocious, value); }
|
||||
public bool RibbonMarkCrafty { get => this.GetRibbonIndex(MarkCrafty); set => this.SetRibbonIndex(MarkCrafty, value); }
|
||||
public bool RibbonMarkScowling { get => this.GetRibbonIndex(MarkScowling); set => this.SetRibbonIndex(MarkScowling, value); }
|
||||
public bool RibbonMarkKindly { get => this.GetRibbonIndex(MarkKindly); set => this.SetRibbonIndex(MarkKindly, value); }
|
||||
public bool RibbonMarkFlustered { get => this.GetRibbonIndex(MarkFlustered); set => this.SetRibbonIndex(MarkFlustered, value); }
|
||||
public bool RibbonMarkPumpedUp { get => this.GetRibbonIndex(MarkPumpedUp); set => this.SetRibbonIndex(MarkPumpedUp, value); }
|
||||
public bool RibbonMarkZeroEnergy { get => this.GetRibbonIndex(MarkZeroEnergy); set => this.SetRibbonIndex(MarkZeroEnergy, value); }
|
||||
public bool RibbonMarkPrideful { get => this.GetRibbonIndex(MarkPrideful); set => this.SetRibbonIndex(MarkPrideful, value); }
|
||||
public bool RibbonMarkUnsure { get => this.GetRibbonIndex(MarkUnsure); set => this.SetRibbonIndex(MarkUnsure, value); }
|
||||
public bool RibbonMarkHumble { get => this.GetRibbonIndex(MarkHumble); set => this.SetRibbonIndex(MarkHumble, value); }
|
||||
public bool RibbonMarkThorny { get => this.GetRibbonIndex(MarkThorny); set => this.SetRibbonIndex(MarkThorny, value); }
|
||||
public bool RibbonMarkVigor { get => this.GetRibbonIndex(MarkVigor); set => this.SetRibbonIndex(MarkVigor, value); }
|
||||
public bool RibbonMarkSlump { get => this.GetRibbonIndex(MarkSlump); set => this.SetRibbonIndex(MarkSlump, value); }
|
||||
public bool RibbonTwinklingStar { get => this.GetRibbonIndex(TwinklingStar); set => this.SetRibbonIndex(TwinklingStar, value); }
|
||||
public bool RibbonPioneer { get => this.GetRibbonIndex(Pioneer); set => this.SetRibbonIndex(Pioneer, value); }
|
||||
|
||||
public int GetRibbonByte(int index) => Array.FindIndex(Data, RibbonBytesOffset, RibbonBytesCount, z => z == index);
|
||||
public bool GetRibbon(int index) => GetRibbonByte(index) >= 0;
|
||||
|
||||
public void SetRibbon(int index, bool value = true)
|
||||
{
|
||||
if ((uint)index > (uint)MarkSlump)
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
|
||||
if (value)
|
||||
{
|
||||
if (GetRibbon(index))
|
||||
return;
|
||||
var openIndex = Array.FindIndex(Data, RibbonBytesOffset, RibbonBytesCount, z => z != RibbonByteNone);
|
||||
if (openIndex < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
SetRibbonAtIndex(openIndex, (byte)index);
|
||||
}
|
||||
else
|
||||
{
|
||||
var ofs = GetRibbonByte(index);
|
||||
if (ofs < 0)
|
||||
return;
|
||||
SetRibbonAtIndex(ofs, RibbonByteNone);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -759,6 +759,8 @@ namespace PKHeX.Core
|
|||
public bool RibbonMarkThorny { get => this.GetRibbonIndex(MarkThorny); set => this.SetRibbonIndex(MarkThorny, value); }
|
||||
public bool RibbonMarkVigor { get => this.GetRibbonIndex(MarkVigor); set => this.SetRibbonIndex(MarkVigor, value); }
|
||||
public bool RibbonMarkSlump { get => this.GetRibbonIndex(MarkSlump); set => this.SetRibbonIndex(MarkSlump, value); }
|
||||
public bool RibbonTwinklingStar { get => this.GetRibbonIndex(TwinklingStar); set => this.SetRibbonIndex(TwinklingStar, value); }
|
||||
public bool RibbonPioneer { get => this.GetRibbonIndex(Pioneer); set => this.SetRibbonIndex(Pioneer, value); }
|
||||
|
||||
public int GetRibbonByte(int index) => Array.FindIndex(Data, RibbonBytesOffset, RibbonBytesCount, z => z == index);
|
||||
public bool GetRibbon(int index) => GetRibbonByte(index) >= 0;
|
||||
|
|
504
PKHeX.Core/PKM/G8PKM.cs
Normal file
504
PKHeX.Core/PKM/G8PKM.cs
Normal file
|
@ -0,0 +1,504 @@
|
|||
using System;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary> Generation 8 <see cref="PKM"/> format. </summary>
|
||||
public abstract class G8PKM : PKM,
|
||||
IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetMark8, IRibbonSetAffixed,
|
||||
IContestStats, IContestStatsMutable, IHyperTrain, IScaledSize, IGigantamax, IFavorite, IDynamaxLevel, IRibbonIndex, IHandlerLanguage, IFormArgument, IHomeTrack, IBattleVersion, ITrainerMemories
|
||||
{
|
||||
public sealed override int Format => 8;
|
||||
protected G8PKM() : base(PokeCrypto.SIZE_8PARTY) { }
|
||||
protected G8PKM(byte[] data) : base(DecryptParty(data)) { }
|
||||
|
||||
private static byte[] DecryptParty(byte[] data)
|
||||
{
|
||||
PokeCrypto.DecryptIfEncrypted8(ref data);
|
||||
Array.Resize(ref data, PokeCrypto.SIZE_8PARTY);
|
||||
return data;
|
||||
}
|
||||
|
||||
protected override ushort CalculateChecksum()
|
||||
{
|
||||
ushort chk = 0;
|
||||
for (int i = 8; i < PokeCrypto.SIZE_8STORED; i += 2)
|
||||
chk += BitConverter.ToUInt16(Data, i);
|
||||
return chk;
|
||||
}
|
||||
|
||||
// Simple Generated Attributes
|
||||
public override int CurrentFriendship
|
||||
{
|
||||
get => CurrentHandler == 0 ? OT_Friendship : HT_Friendship;
|
||||
set { if (CurrentHandler == 0) OT_Friendship = value; else HT_Friendship = value; }
|
||||
}
|
||||
|
||||
private string GetString(int offset, int count) => StringConverter.GetString7b(Data, offset, count);
|
||||
private static byte[] SetString(string value, int maxLength) => StringConverter.SetString7b(value, maxLength);
|
||||
|
||||
public override int SIZE_PARTY => PokeCrypto.SIZE_8PARTY;
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_8STORED;
|
||||
|
||||
// Trash Bytes
|
||||
public override Span<byte> Nickname_Trash { get => Data.AsSpan(0x58, 24); set { if (value.Length == 24) value.CopyTo(Data.AsSpan(0x58)); } }
|
||||
public override Span<byte> HT_Trash { get => Data.AsSpan(0xA8, 24); set { if (value.Length == 24) value.CopyTo(Data.AsSpan(0xA8)); } }
|
||||
public override Span<byte> OT_Trash { get => Data.AsSpan(0xF8, 24); set { if (value.Length == 24) value.CopyTo(Data.AsSpan(0xF8)); } }
|
||||
|
||||
// Maximums
|
||||
public override int MaxIV => 31;
|
||||
public override int MaxEV => 252;
|
||||
public override int OTLength => 12;
|
||||
public override int NickLength => 12;
|
||||
|
||||
public override int PSV => (int)((PID >> 16 ^ (PID & 0xFFFF)) >> 4);
|
||||
public override int TSV => (TID ^ SID) >> 4;
|
||||
public override bool IsUntraded => Data[0xA8] == 0 && Data[0xA8 + 1] == 0 && Format == Generation; // immediately terminated HT_Name data (\0)
|
||||
|
||||
// Complex Generated Attributes
|
||||
public override int Characteristic
|
||||
{
|
||||
get
|
||||
{
|
||||
int pm6 = (int)(EncryptionConstant % 6);
|
||||
int maxIV = MaximumIV;
|
||||
int pm6stat = 0;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
pm6stat = (pm6 + i) % 6;
|
||||
if (GetIV(pm6stat) == maxIV)
|
||||
break;
|
||||
}
|
||||
return (pm6stat * 5) + (maxIV % 5);
|
||||
}
|
||||
}
|
||||
|
||||
// Methods
|
||||
protected override byte[] Encrypt()
|
||||
{
|
||||
RefreshChecksum();
|
||||
return PokeCrypto.EncryptArray8(Data);
|
||||
}
|
||||
|
||||
public void FixRelearn()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (RelearnMove4 != 0 && RelearnMove3 == 0)
|
||||
{
|
||||
RelearnMove3 = RelearnMove4;
|
||||
RelearnMove4 = 0;
|
||||
}
|
||||
if (RelearnMove3 != 0 && RelearnMove2 == 0)
|
||||
{
|
||||
RelearnMove2 = RelearnMove3;
|
||||
RelearnMove3 = 0;
|
||||
continue;
|
||||
}
|
||||
if (RelearnMove2 != 0 && RelearnMove1 == 0)
|
||||
{
|
||||
RelearnMove1 = RelearnMove2;
|
||||
RelearnMove2 = 0;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override uint EncryptionConstant { get => BitConverter.ToUInt32(Data, 0x00); set => BitConverter.GetBytes(value).CopyTo(Data, 0x00); }
|
||||
public override ushort Sanity { get => BitConverter.ToUInt16(Data, 0x04); set => BitConverter.GetBytes(value).CopyTo(Data, 0x04); }
|
||||
public override ushort Checksum { get => BitConverter.ToUInt16(Data, 0x06); set => BitConverter.GetBytes(value).CopyTo(Data, 0x06); }
|
||||
|
||||
// Structure
|
||||
#region Block A
|
||||
public override int Species { get => BitConverter.ToUInt16(Data, 0x08); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x08); }
|
||||
public override int HeldItem { get => BitConverter.ToUInt16(Data, 0x0A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0A); }
|
||||
public override int TID { get => BitConverter.ToUInt16(Data, 0x0C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0C); }
|
||||
public override int SID { get => BitConverter.ToUInt16(Data, 0x0E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0E); }
|
||||
public override uint EXP { get => BitConverter.ToUInt32(Data, 0x10); set => BitConverter.GetBytes(value).CopyTo(Data, 0x10); }
|
||||
public override int Ability { get => BitConverter.ToUInt16(Data, 0x14); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x14); }
|
||||
public override int AbilityNumber { get => Data[0x16] & 7; set => Data[0x16] = (byte)((Data[0x16] & ~7) | (value & 7)); }
|
||||
public bool Favorite { get => (Data[0x16] & 8) != 0; set => Data[0x16] = (byte)((Data[0x16] & ~8) | ((value ? 1 : 0) << 3)); } // unused, was in LGPE but not in SWSH
|
||||
public bool CanGigantamax { get => (Data[0x16] & 16) != 0; set => Data[0x16] = (byte)((Data[0x16] & ~16) | (value ? 16 : 0)); }
|
||||
// 0x17 alignment unused
|
||||
public override int MarkValue { get => BitConverter.ToUInt16(Data, 0x18); protected set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x18); }
|
||||
// 0x1A alignment unused
|
||||
// 0x1B alignment unused
|
||||
public override uint PID { get => BitConverter.ToUInt32(Data, 0x1C); set => BitConverter.GetBytes(value).CopyTo(Data, 0x1C); }
|
||||
public override int Nature { get => Data[0x20]; set => Data[0x20] = (byte)value; }
|
||||
public override int StatNature { get => Data[0x21]; set => Data[0x21] = (byte)value; }
|
||||
public override bool FatefulEncounter { get => (Data[0x22] & 1) == 1; set => Data[0x22] = (byte)((Data[0x22] & ~0x01) | (value ? 1 : 0)); }
|
||||
public bool Flag2 { get => (Data[0x22] & 2) == 2; set => Data[0x22] = (byte)((Data[0x22] & ~0x02) | (value ? 2 : 0)); }
|
||||
public override int Gender { get => (Data[0x22] >> 2) & 0x3; set => Data[0x22] = (byte)((Data[0x22] & 0xF3) | (value << 2)); }
|
||||
// 0x23 alignment unused
|
||||
|
||||
public override int Form { get => BitConverter.ToUInt16(Data, 0x24); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x24); }
|
||||
public override int EV_HP { get => Data[0x26]; set => Data[0x26] = (byte)value; }
|
||||
public override int EV_ATK { get => Data[0x27]; set => Data[0x27] = (byte)value; }
|
||||
public override int EV_DEF { get => Data[0x28]; set => Data[0x28] = (byte)value; }
|
||||
public override int EV_SPE { get => Data[0x29]; set => Data[0x29] = (byte)value; }
|
||||
public override int EV_SPA { get => Data[0x2A]; set => Data[0x2A] = (byte)value; }
|
||||
public override int EV_SPD { get => Data[0x2B]; set => Data[0x2B] = (byte)value; }
|
||||
public byte CNT_Cool { get => Data[0x2C]; set => Data[0x2C] = value; }
|
||||
public byte CNT_Beauty { get => Data[0x2D]; set => Data[0x2D] = value; }
|
||||
public byte CNT_Cute { get => Data[0x2E]; set => Data[0x2E] = value; }
|
||||
public byte CNT_Smart { get => Data[0x2F]; set => Data[0x2F] = value; }
|
||||
public byte CNT_Tough { get => Data[0x30]; set => Data[0x30] = value; }
|
||||
public byte CNT_Sheen { get => Data[0x31]; set => Data[0x31] = value; }
|
||||
private byte PKRS { get => Data[0x32]; set => Data[0x32] = value; }
|
||||
public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); }
|
||||
public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | value << 4); }
|
||||
// 0x33 unused padding
|
||||
|
||||
// ribbon u32
|
||||
public bool RibbonChampionKalos { get => FlagUtil.GetFlag(Data, 0x34, 0); set => FlagUtil.SetFlag(Data, 0x34, 0, value); }
|
||||
public bool RibbonChampionG3 { get => FlagUtil.GetFlag(Data, 0x34, 1); set => FlagUtil.SetFlag(Data, 0x34, 1, value); }
|
||||
public bool RibbonChampionSinnoh { get => FlagUtil.GetFlag(Data, 0x34, 2); set => FlagUtil.SetFlag(Data, 0x34, 2, value); }
|
||||
public bool RibbonBestFriends { get => FlagUtil.GetFlag(Data, 0x34, 3); set => FlagUtil.SetFlag(Data, 0x34, 3, value); }
|
||||
public bool RibbonTraining { get => FlagUtil.GetFlag(Data, 0x34, 4); set => FlagUtil.SetFlag(Data, 0x34, 4, value); }
|
||||
public bool RibbonBattlerSkillful { get => FlagUtil.GetFlag(Data, 0x34, 5); set => FlagUtil.SetFlag(Data, 0x34, 5, value); }
|
||||
public bool RibbonBattlerExpert { get => FlagUtil.GetFlag(Data, 0x34, 6); set => FlagUtil.SetFlag(Data, 0x34, 6, value); }
|
||||
public bool RibbonEffort { get => FlagUtil.GetFlag(Data, 0x34, 7); set => FlagUtil.SetFlag(Data, 0x34, 7, value); }
|
||||
|
||||
public bool RibbonAlert { get => FlagUtil.GetFlag(Data, 0x35, 0); set => FlagUtil.SetFlag(Data, 0x35, 0, value); }
|
||||
public bool RibbonShock { get => FlagUtil.GetFlag(Data, 0x35, 1); set => FlagUtil.SetFlag(Data, 0x35, 1, value); }
|
||||
public bool RibbonDowncast { get => FlagUtil.GetFlag(Data, 0x35, 2); set => FlagUtil.SetFlag(Data, 0x35, 2, value); }
|
||||
public bool RibbonCareless { get => FlagUtil.GetFlag(Data, 0x35, 3); set => FlagUtil.SetFlag(Data, 0x35, 3, value); }
|
||||
public bool RibbonRelax { get => FlagUtil.GetFlag(Data, 0x35, 4); set => FlagUtil.SetFlag(Data, 0x35, 4, value); }
|
||||
public bool RibbonSnooze { get => FlagUtil.GetFlag(Data, 0x35, 5); set => FlagUtil.SetFlag(Data, 0x35, 5, value); }
|
||||
public bool RibbonSmile { get => FlagUtil.GetFlag(Data, 0x35, 6); set => FlagUtil.SetFlag(Data, 0x35, 6, value); }
|
||||
public bool RibbonGorgeous { get => FlagUtil.GetFlag(Data, 0x35, 7); set => FlagUtil.SetFlag(Data, 0x35, 7, value); }
|
||||
|
||||
public bool RibbonRoyal { get => FlagUtil.GetFlag(Data, 0x36, 0); set => FlagUtil.SetFlag(Data, 0x36, 0, value); }
|
||||
public bool RibbonGorgeousRoyal { get => FlagUtil.GetFlag(Data, 0x36, 1); set => FlagUtil.SetFlag(Data, 0x36, 1, value); }
|
||||
public bool RibbonArtist { get => FlagUtil.GetFlag(Data, 0x36, 2); set => FlagUtil.SetFlag(Data, 0x36, 2, value); }
|
||||
public bool RibbonFootprint { get => FlagUtil.GetFlag(Data, 0x36, 3); set => FlagUtil.SetFlag(Data, 0x36, 3, value); }
|
||||
public bool RibbonRecord { get => FlagUtil.GetFlag(Data, 0x36, 4); set => FlagUtil.SetFlag(Data, 0x36, 4, value); }
|
||||
public bool RibbonLegend { get => FlagUtil.GetFlag(Data, 0x36, 5); set => FlagUtil.SetFlag(Data, 0x36, 5, value); }
|
||||
public bool RibbonCountry { get => FlagUtil.GetFlag(Data, 0x36, 6); set => FlagUtil.SetFlag(Data, 0x36, 6, value); }
|
||||
public bool RibbonNational { get => FlagUtil.GetFlag(Data, 0x36, 7); set => FlagUtil.SetFlag(Data, 0x36, 7, value); }
|
||||
|
||||
public bool RibbonEarth { get => FlagUtil.GetFlag(Data, 0x37, 0); set => FlagUtil.SetFlag(Data, 0x37, 0, value); }
|
||||
public bool RibbonWorld { get => FlagUtil.GetFlag(Data, 0x37, 1); set => FlagUtil.SetFlag(Data, 0x37, 1, value); }
|
||||
public bool RibbonClassic { get => FlagUtil.GetFlag(Data, 0x37, 2); set => FlagUtil.SetFlag(Data, 0x37, 2, value); }
|
||||
public bool RibbonPremier { get => FlagUtil.GetFlag(Data, 0x37, 3); set => FlagUtil.SetFlag(Data, 0x37, 3, value); }
|
||||
public bool RibbonEvent { get => FlagUtil.GetFlag(Data, 0x37, 4); set => FlagUtil.SetFlag(Data, 0x37, 4, value); }
|
||||
public bool RibbonBirthday { get => FlagUtil.GetFlag(Data, 0x37, 5); set => FlagUtil.SetFlag(Data, 0x37, 5, value); }
|
||||
public bool RibbonSpecial { get => FlagUtil.GetFlag(Data, 0x37, 6); set => FlagUtil.SetFlag(Data, 0x37, 6, value); }
|
||||
public bool RibbonSouvenir { get => FlagUtil.GetFlag(Data, 0x37, 7); set => FlagUtil.SetFlag(Data, 0x37, 7, value); }
|
||||
|
||||
// ribbon u32
|
||||
public bool RibbonWishing { get => FlagUtil.GetFlag(Data, 0x38, 0); set => FlagUtil.SetFlag(Data, 0x38, 0, value); }
|
||||
public bool RibbonChampionBattle { get => FlagUtil.GetFlag(Data, 0x38, 1); set => FlagUtil.SetFlag(Data, 0x38, 1, value); }
|
||||
public bool RibbonChampionRegional { get => FlagUtil.GetFlag(Data, 0x38, 2); set => FlagUtil.SetFlag(Data, 0x38, 2, value); }
|
||||
public bool RibbonChampionNational { get => FlagUtil.GetFlag(Data, 0x38, 3); set => FlagUtil.SetFlag(Data, 0x38, 3, value); }
|
||||
public bool RibbonChampionWorld { get => FlagUtil.GetFlag(Data, 0x38, 4); set => FlagUtil.SetFlag(Data, 0x38, 4, value); }
|
||||
public bool HasContestMemoryRibbon { get => FlagUtil.GetFlag(Data, 0x38, 5); set => FlagUtil.SetFlag(Data, 0x38, 5, value); }
|
||||
public bool HasBattleMemoryRibbon { get => FlagUtil.GetFlag(Data, 0x38, 6); set => FlagUtil.SetFlag(Data, 0x38, 6, value); }
|
||||
public bool RibbonChampionG6Hoenn { get => FlagUtil.GetFlag(Data, 0x38, 7); set => FlagUtil.SetFlag(Data, 0x38, 7, value); }
|
||||
|
||||
public bool RibbonContestStar { get => FlagUtil.GetFlag(Data, 0x39, 0); set => FlagUtil.SetFlag(Data, 0x39, 0, value); }
|
||||
public bool RibbonMasterCoolness { get => FlagUtil.GetFlag(Data, 0x39, 1); set => FlagUtil.SetFlag(Data, 0x39, 1, value); }
|
||||
public bool RibbonMasterBeauty { get => FlagUtil.GetFlag(Data, 0x39, 2); set => FlagUtil.SetFlag(Data, 0x39, 2, value); }
|
||||
public bool RibbonMasterCuteness { get => FlagUtil.GetFlag(Data, 0x39, 3); set => FlagUtil.SetFlag(Data, 0x39, 3, value); }
|
||||
public bool RibbonMasterCleverness { get => FlagUtil.GetFlag(Data, 0x39, 4); set => FlagUtil.SetFlag(Data, 0x39, 4, value); }
|
||||
public bool RibbonMasterToughness { get => FlagUtil.GetFlag(Data, 0x39, 5); set => FlagUtil.SetFlag(Data, 0x39, 5, value); }
|
||||
public bool RibbonChampionAlola { get => FlagUtil.GetFlag(Data, 0x39, 6); set => FlagUtil.SetFlag(Data, 0x39, 6, value); }
|
||||
public bool RibbonBattleRoyale { get => FlagUtil.GetFlag(Data, 0x39, 7); set => FlagUtil.SetFlag(Data, 0x39, 7, value); }
|
||||
|
||||
public bool RibbonBattleTreeGreat { get => FlagUtil.GetFlag(Data, 0x3A, 0); set => FlagUtil.SetFlag(Data, 0x3A, 0, value); }
|
||||
public bool RibbonBattleTreeMaster { get => FlagUtil.GetFlag(Data, 0x3A, 1); set => FlagUtil.SetFlag(Data, 0x3A, 1, value); }
|
||||
public bool RibbonChampionGalar { get => FlagUtil.GetFlag(Data, 0x3A, 2); set => FlagUtil.SetFlag(Data, 0x3A, 2, value); }
|
||||
public bool RibbonTowerMaster { get => FlagUtil.GetFlag(Data, 0x3A, 3); set => FlagUtil.SetFlag(Data, 0x3A, 3, value); }
|
||||
public bool RibbonMasterRank { get => FlagUtil.GetFlag(Data, 0x3A, 4); set => FlagUtil.SetFlag(Data, 0x3A, 4, value); }
|
||||
public bool RibbonMarkLunchtime { get => FlagUtil.GetFlag(Data, 0x3A, 5); set => FlagUtil.SetFlag(Data, 0x3A, 5, value); }
|
||||
public bool RibbonMarkSleepyTime { get => FlagUtil.GetFlag(Data, 0x3A, 6); set => FlagUtil.SetFlag(Data, 0x3A, 6, value); }
|
||||
public bool RibbonMarkDusk { get => FlagUtil.GetFlag(Data, 0x3A, 7); set => FlagUtil.SetFlag(Data, 0x3A, 7, value); }
|
||||
|
||||
public bool RibbonMarkDawn { get => FlagUtil.GetFlag(Data, 0x3B, 0); set => FlagUtil.SetFlag(Data, 0x3B, 0, value); }
|
||||
public bool RibbonMarkCloudy { get => FlagUtil.GetFlag(Data, 0x3B, 1); set => FlagUtil.SetFlag(Data, 0x3B, 1, value); }
|
||||
public bool RibbonMarkRainy { get => FlagUtil.GetFlag(Data, 0x3B, 2); set => FlagUtil.SetFlag(Data, 0x3B, 2, value); }
|
||||
public bool RibbonMarkStormy { get => FlagUtil.GetFlag(Data, 0x3B, 3); set => FlagUtil.SetFlag(Data, 0x3B, 3, value); }
|
||||
public bool RibbonMarkSnowy { get => FlagUtil.GetFlag(Data, 0x3B, 4); set => FlagUtil.SetFlag(Data, 0x3B, 4, value); }
|
||||
public bool RibbonMarkBlizzard { get => FlagUtil.GetFlag(Data, 0x3B, 5); set => FlagUtil.SetFlag(Data, 0x3B, 5, value); }
|
||||
public bool RibbonMarkDry { get => FlagUtil.GetFlag(Data, 0x3B, 6); set => FlagUtil.SetFlag(Data, 0x3B, 6, value); }
|
||||
public bool RibbonMarkSandstorm { get => FlagUtil.GetFlag(Data, 0x3B, 7); set => FlagUtil.SetFlag(Data, 0x3B, 7, value); }
|
||||
public int RibbonCountMemoryContest { get => Data[0x3C]; set => HasContestMemoryRibbon = (Data[0x3C] = (byte)value) != 0; }
|
||||
public int RibbonCountMemoryBattle { get => Data[0x3D]; set => HasBattleMemoryRibbon = (Data[0x3D] = (byte)value) != 0; }
|
||||
// 0x3E padding
|
||||
// 0x3F padding
|
||||
|
||||
// 0x40 Ribbon 1
|
||||
public bool RibbonMarkMisty { get => FlagUtil.GetFlag(Data, 0x40, 0); set => FlagUtil.SetFlag(Data, 0x40, 0, value); }
|
||||
public bool RibbonMarkDestiny { get => FlagUtil.GetFlag(Data, 0x40, 1); set => FlagUtil.SetFlag(Data, 0x40, 1, value); }
|
||||
public bool RibbonMarkFishing { get => FlagUtil.GetFlag(Data, 0x40, 2); set => FlagUtil.SetFlag(Data, 0x40, 2, value); }
|
||||
public bool RibbonMarkCurry { get => FlagUtil.GetFlag(Data, 0x40, 3); set => FlagUtil.SetFlag(Data, 0x40, 3, value); }
|
||||
public bool RibbonMarkUncommon { get => FlagUtil.GetFlag(Data, 0x40, 4); set => FlagUtil.SetFlag(Data, 0x40, 4, value); }
|
||||
public bool RibbonMarkRare { get => FlagUtil.GetFlag(Data, 0x40, 5); set => FlagUtil.SetFlag(Data, 0x40, 5, value); }
|
||||
public bool RibbonMarkRowdy { get => FlagUtil.GetFlag(Data, 0x40, 6); set => FlagUtil.SetFlag(Data, 0x40, 6, value); }
|
||||
public bool RibbonMarkAbsentMinded { get => FlagUtil.GetFlag(Data, 0x40, 7); set => FlagUtil.SetFlag(Data, 0x40, 7, value); }
|
||||
|
||||
public bool RibbonMarkJittery { get => FlagUtil.GetFlag(Data, 0x41, 0); set => FlagUtil.SetFlag(Data, 0x41, 0, value); }
|
||||
public bool RibbonMarkExcited { get => FlagUtil.GetFlag(Data, 0x41, 1); set => FlagUtil.SetFlag(Data, 0x41, 1, value); }
|
||||
public bool RibbonMarkCharismatic { get => FlagUtil.GetFlag(Data, 0x41, 2); set => FlagUtil.SetFlag(Data, 0x41, 2, value); }
|
||||
public bool RibbonMarkCalmness { get => FlagUtil.GetFlag(Data, 0x41, 3); set => FlagUtil.SetFlag(Data, 0x41, 3, value); }
|
||||
public bool RibbonMarkIntense { get => FlagUtil.GetFlag(Data, 0x41, 4); set => FlagUtil.SetFlag(Data, 0x41, 4, value); }
|
||||
public bool RibbonMarkZonedOut { get => FlagUtil.GetFlag(Data, 0x41, 5); set => FlagUtil.SetFlag(Data, 0x41, 5, value); }
|
||||
public bool RibbonMarkJoyful { get => FlagUtil.GetFlag(Data, 0x41, 6); set => FlagUtil.SetFlag(Data, 0x41, 6, value); }
|
||||
public bool RibbonMarkAngry { get => FlagUtil.GetFlag(Data, 0x41, 7); set => FlagUtil.SetFlag(Data, 0x41, 7, value); }
|
||||
|
||||
public bool RibbonMarkSmiley { get => FlagUtil.GetFlag(Data, 0x42, 0); set => FlagUtil.SetFlag(Data, 0x42, 0, value); }
|
||||
public bool RibbonMarkTeary { get => FlagUtil.GetFlag(Data, 0x42, 1); set => FlagUtil.SetFlag(Data, 0x42, 1, value); }
|
||||
public bool RibbonMarkUpbeat { get => FlagUtil.GetFlag(Data, 0x42, 2); set => FlagUtil.SetFlag(Data, 0x42, 2, value); }
|
||||
public bool RibbonMarkPeeved { get => FlagUtil.GetFlag(Data, 0x42, 3); set => FlagUtil.SetFlag(Data, 0x42, 3, value); }
|
||||
public bool RibbonMarkIntellectual { get => FlagUtil.GetFlag(Data, 0x42, 4); set => FlagUtil.SetFlag(Data, 0x42, 4, value); }
|
||||
public bool RibbonMarkFerocious { get => FlagUtil.GetFlag(Data, 0x42, 5); set => FlagUtil.SetFlag(Data, 0x42, 5, value); }
|
||||
public bool RibbonMarkCrafty { get => FlagUtil.GetFlag(Data, 0x42, 6); set => FlagUtil.SetFlag(Data, 0x42, 6, value); }
|
||||
public bool RibbonMarkScowling { get => FlagUtil.GetFlag(Data, 0x42, 7); set => FlagUtil.SetFlag(Data, 0x42, 7, value); }
|
||||
|
||||
public bool RibbonMarkKindly { get => FlagUtil.GetFlag(Data, 0x43, 0); set => FlagUtil.SetFlag(Data, 0x43, 0, value); }
|
||||
public bool RibbonMarkFlustered { get => FlagUtil.GetFlag(Data, 0x43, 1); set => FlagUtil.SetFlag(Data, 0x43, 1, value); }
|
||||
public bool RibbonMarkPumpedUp { get => FlagUtil.GetFlag(Data, 0x43, 2); set => FlagUtil.SetFlag(Data, 0x43, 2, value); }
|
||||
public bool RibbonMarkZeroEnergy { get => FlagUtil.GetFlag(Data, 0x43, 3); set => FlagUtil.SetFlag(Data, 0x43, 3, value); }
|
||||
public bool RibbonMarkPrideful { get => FlagUtil.GetFlag(Data, 0x43, 4); set => FlagUtil.SetFlag(Data, 0x43, 4, value); }
|
||||
public bool RibbonMarkUnsure { get => FlagUtil.GetFlag(Data, 0x43, 5); set => FlagUtil.SetFlag(Data, 0x43, 5, value); }
|
||||
public bool RibbonMarkHumble { get => FlagUtil.GetFlag(Data, 0x43, 6); set => FlagUtil.SetFlag(Data, 0x43, 6, value); }
|
||||
public bool RibbonMarkThorny { get => FlagUtil.GetFlag(Data, 0x43, 7); set => FlagUtil.SetFlag(Data, 0x43, 7, value); }
|
||||
// 0x44 Ribbon 2
|
||||
|
||||
public bool RibbonMarkVigor { get => FlagUtil.GetFlag(Data, 0x44, 0); set => FlagUtil.SetFlag(Data, 0x44, 0, value); }
|
||||
public bool RibbonMarkSlump { get => FlagUtil.GetFlag(Data, 0x44, 1); set => FlagUtil.SetFlag(Data, 0x44, 1, value); }
|
||||
public bool RibbonTwinklingStar { get => FlagUtil.GetFlag(Data, 0x44, 2); set => FlagUtil.SetFlag(Data, 0x44, 2, value); }
|
||||
public bool RibbonPioneer { get => FlagUtil.GetFlag(Data, 0x44, 3); set => FlagUtil.SetFlag(Data, 0x44, 3, value); }
|
||||
public bool RIB44_4 { get => FlagUtil.GetFlag(Data, 0x44, 4); set => FlagUtil.SetFlag(Data, 0x44, 4, value); }
|
||||
public bool RIB44_5 { get => FlagUtil.GetFlag(Data, 0x44, 5); set => FlagUtil.SetFlag(Data, 0x44, 5, value); }
|
||||
public bool RIB44_6 { get => FlagUtil.GetFlag(Data, 0x44, 6); set => FlagUtil.SetFlag(Data, 0x44, 6, value); }
|
||||
public bool RIB44_7 { get => FlagUtil.GetFlag(Data, 0x44, 7); set => FlagUtil.SetFlag(Data, 0x44, 7, value); }
|
||||
|
||||
public bool RIB45_0 { get => FlagUtil.GetFlag(Data, 0x45, 0); set => FlagUtil.SetFlag(Data, 0x45, 0, value); }
|
||||
public bool RIB45_1 { get => FlagUtil.GetFlag(Data, 0x45, 1); set => FlagUtil.SetFlag(Data, 0x45, 1, value); }
|
||||
public bool RIB45_2 { get => FlagUtil.GetFlag(Data, 0x45, 2); set => FlagUtil.SetFlag(Data, 0x45, 2, value); }
|
||||
public bool RIB45_3 { get => FlagUtil.GetFlag(Data, 0x45, 3); set => FlagUtil.SetFlag(Data, 0x45, 3, value); }
|
||||
public bool RIB45_4 { get => FlagUtil.GetFlag(Data, 0x45, 4); set => FlagUtil.SetFlag(Data, 0x45, 4, value); }
|
||||
public bool RIB45_5 { get => FlagUtil.GetFlag(Data, 0x45, 5); set => FlagUtil.SetFlag(Data, 0x45, 5, value); }
|
||||
public bool RIB45_6 { get => FlagUtil.GetFlag(Data, 0x45, 6); set => FlagUtil.SetFlag(Data, 0x45, 6, value); }
|
||||
public bool RIB45_7 { get => FlagUtil.GetFlag(Data, 0x45, 7); set => FlagUtil.SetFlag(Data, 0x45, 7, value); }
|
||||
|
||||
public bool RIB46_0 { get => FlagUtil.GetFlag(Data, 0x41, 0); set => FlagUtil.SetFlag(Data, 0x41, 0, value); }
|
||||
public bool RIB46_1 { get => FlagUtil.GetFlag(Data, 0x46, 1); set => FlagUtil.SetFlag(Data, 0x46, 1, value); }
|
||||
public bool RIB46_2 { get => FlagUtil.GetFlag(Data, 0x46, 2); set => FlagUtil.SetFlag(Data, 0x46, 2, value); }
|
||||
public bool RIB46_3 { get => FlagUtil.GetFlag(Data, 0x46, 3); set => FlagUtil.SetFlag(Data, 0x46, 3, value); }
|
||||
public bool RIB46_4 { get => FlagUtil.GetFlag(Data, 0x46, 4); set => FlagUtil.SetFlag(Data, 0x46, 4, value); }
|
||||
public bool RIB46_5 { get => FlagUtil.GetFlag(Data, 0x46, 5); set => FlagUtil.SetFlag(Data, 0x46, 5, value); }
|
||||
public bool RIB46_6 { get => FlagUtil.GetFlag(Data, 0x46, 6); set => FlagUtil.SetFlag(Data, 0x46, 6, value); }
|
||||
public bool RIB46_7 { get => FlagUtil.GetFlag(Data, 0x46, 7); set => FlagUtil.SetFlag(Data, 0x46, 7, value); }
|
||||
|
||||
public bool RIB47_0 { get => FlagUtil.GetFlag(Data, 0x47, 0); set => FlagUtil.SetFlag(Data, 0x47, 0, value); }
|
||||
public bool RIB47_1 { get => FlagUtil.GetFlag(Data, 0x47, 1); set => FlagUtil.SetFlag(Data, 0x47, 1, value); }
|
||||
public bool RIB47_2 { get => FlagUtil.GetFlag(Data, 0x47, 2); set => FlagUtil.SetFlag(Data, 0x47, 2, value); }
|
||||
public bool RIB47_3 { get => FlagUtil.GetFlag(Data, 0x47, 3); set => FlagUtil.SetFlag(Data, 0x47, 3, value); }
|
||||
public bool RIB47_4 { get => FlagUtil.GetFlag(Data, 0x47, 4); set => FlagUtil.SetFlag(Data, 0x47, 4, value); }
|
||||
public bool RIB47_5 { get => FlagUtil.GetFlag(Data, 0x47, 5); set => FlagUtil.SetFlag(Data, 0x47, 5, value); }
|
||||
public bool RIB47_6 { get => FlagUtil.GetFlag(Data, 0x47, 6); set => FlagUtil.SetFlag(Data, 0x47, 6, value); }
|
||||
public bool RIB47_7 { get => FlagUtil.GetFlag(Data, 0x47, 7); set => FlagUtil.SetFlag(Data, 0x47, 7, value); }
|
||||
|
||||
public bool HasMark()
|
||||
{
|
||||
var d = Data;
|
||||
if ((BitConverter.ToUInt16(d, 0x3A) & 0xFFE0) != 0)
|
||||
return true;
|
||||
if (BitConverter.ToUInt32(d, 0x40) != 0)
|
||||
return true;
|
||||
return (d[0x44] & 3) != 0;
|
||||
}
|
||||
|
||||
public uint Sociability { get => BitConverter.ToUInt32(Data, 0x48); set => BitConverter.GetBytes(value).CopyTo(Data, 0x48); }
|
||||
|
||||
// 0x4C-0x4F unused
|
||||
|
||||
public int HeightScalar { get => Data[0x50]; set => Data[0x50] = (byte)value; }
|
||||
public int WeightScalar { get => Data[0x51]; set => Data[0x51] = (byte)value; }
|
||||
|
||||
// 0x52-0x57 unused
|
||||
|
||||
#endregion
|
||||
#region Block B
|
||||
public override string Nickname
|
||||
{
|
||||
get => GetString(0x58, 24);
|
||||
set => SetString(value, 12).CopyTo(Data, 0x58);
|
||||
}
|
||||
|
||||
// 2 bytes for \0, automatically handled above
|
||||
|
||||
public override int Move1 { get => BitConverter.ToUInt16(Data, 0x72); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x72); }
|
||||
public override int Move2 { get => BitConverter.ToUInt16(Data, 0x74); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x74); }
|
||||
public override int Move3 { get => BitConverter.ToUInt16(Data, 0x76); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x76); }
|
||||
public override int Move4 { get => BitConverter.ToUInt16(Data, 0x78); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x78); }
|
||||
|
||||
public override int Move1_PP { get => Data[0x7A]; set => Data[0x7A] = (byte)value; }
|
||||
public override int Move2_PP { get => Data[0x7B]; set => Data[0x7B] = (byte)value; }
|
||||
public override int Move3_PP { get => Data[0x7C]; set => Data[0x7C] = (byte)value; }
|
||||
public override int Move4_PP { get => Data[0x7D]; set => Data[0x7D] = (byte)value; }
|
||||
public override int Move1_PPUps { get => Data[0x7E]; set => Data[0x7E] = (byte)value; }
|
||||
public override int Move2_PPUps { get => Data[0x7F]; set => Data[0x7F] = (byte)value; }
|
||||
public override int Move3_PPUps { get => Data[0x80]; set => Data[0x80] = (byte)value; }
|
||||
public override int Move4_PPUps { get => Data[0x81]; set => Data[0x81] = (byte)value; }
|
||||
|
||||
public override int RelearnMove1 { get => BitConverter.ToUInt16(Data, 0x82); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x82); }
|
||||
public override int RelearnMove2 { get => BitConverter.ToUInt16(Data, 0x84); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x84); }
|
||||
public override int RelearnMove3 { get => BitConverter.ToUInt16(Data, 0x86); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x86); }
|
||||
public override int RelearnMove4 { get => BitConverter.ToUInt16(Data, 0x88); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x88); }
|
||||
|
||||
public override int Stat_HPCurrent { get => BitConverter.ToUInt16(Data, 0x8A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x8A); }
|
||||
|
||||
private uint IV32 { get => BitConverter.ToUInt32(Data, 0x8C); set => BitConverter.GetBytes(value).CopyTo(Data, 0x8C); }
|
||||
public override int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | ((value > 31 ? 31u : (uint)value) << 00); }
|
||||
public override int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | ((value > 31 ? 31u : (uint)value) << 05); }
|
||||
public override int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | ((value > 31 ? 31u : (uint)value) << 10); }
|
||||
public override int IV_SPE { get => (int)(IV32 >> 15) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 15)) | ((value > 31 ? 31u : (uint)value) << 15); }
|
||||
public override int IV_SPA { get => (int)(IV32 >> 20) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 20)) | ((value > 31 ? 31u : (uint)value) << 20); }
|
||||
public override int IV_SPD { get => (int)(IV32 >> 25) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 25)) | ((value > 31 ? 31u : (uint)value) << 25); }
|
||||
public override bool IsEgg { get => ((IV32 >> 30) & 1) == 1; set => IV32 = (IV32 & ~0x40000000u) | (value ? 0x40000000u : 0u); }
|
||||
public override bool IsNicknamed { get => ((IV32 >> 31) & 1) == 1; set => IV32 = (IV32 & 0x7FFFFFFFu) | (value ? 0x80000000u : 0u); }
|
||||
|
||||
public byte DynamaxLevel { get => Data[0x90]; set => Data[0x90] = value; }
|
||||
|
||||
// 0x90-0x93 unused
|
||||
|
||||
public override int Status_Condition { get => BitConverter.ToInt32(Data, 0x94); set => BitConverter.GetBytes(value).CopyTo(Data, 0x94); }
|
||||
public int Unk98 { get => BitConverter.ToInt32(Data, 0x98); set => BitConverter.GetBytes(value).CopyTo(Data, 0x98); }
|
||||
|
||||
// 0x9C-0xA7 unused
|
||||
|
||||
#endregion
|
||||
#region Block C
|
||||
public override string HT_Name { get => GetString(0xA8, 24); set => SetString(value, 12).CopyTo(Data, 0xA8); }
|
||||
public override int HT_Gender { get => Data[0xC2]; set => Data[0xC2] = (byte)value; }
|
||||
public int HT_Language { get => Data[0xC3]; set => Data[0xC3] = (byte)value; }
|
||||
public override int CurrentHandler { get => Data[0xC4]; set => Data[0xC4] = (byte)value; }
|
||||
// 0xC5 unused (alignment)
|
||||
public int HT_TrainerID { get => BitConverter.ToUInt16(Data, 0xC6); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xC6); } // unused?
|
||||
public override int HT_Friendship { get => Data[0xC8]; set => Data[0xC8] = (byte)value; }
|
||||
public int HT_Intensity { get => Data[0xC9]; set => Data[0xC9] = (byte)value; }
|
||||
public int HT_Memory { get => Data[0xCA]; set => Data[0xCA] = (byte)value; }
|
||||
public int HT_Feeling { get => Data[0xCB]; set => Data[0xCB] = (byte)value; }
|
||||
public int HT_TextVar { get => BitConverter.ToUInt16(Data, 0xCC); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xCC); }
|
||||
|
||||
// 0xCE-0xDB unused
|
||||
|
||||
public override byte Fullness { get => Data[0xDC]; set => Data[0xDC] = value; }
|
||||
public override byte Enjoyment { get => Data[0xDD]; set => Data[0xDD] = value; }
|
||||
public override int Version { get => Data[0xDE]; set => Data[0xDE] = (byte)value; }
|
||||
public int BattleVersion { get => Data[0xDF]; set => Data[0xDF] = (byte)value; }
|
||||
// public override int Region { get => Data[0xE0]; set => Data[0xE0] = (byte)value; }
|
||||
// public override int ConsoleRegion { get => Data[0xE1]; set => Data[0xE1] = (byte)value; }
|
||||
public override int Language { get => Data[0xE2]; set => Data[0xE2] = (byte)value; }
|
||||
public int UnkE3 { get => Data[0xE3]; set => Data[0xE3] = (byte)value; }
|
||||
public uint FormArgument { get => BitConverter.ToUInt32(Data, 0xE4); set => BitConverter.GetBytes(value).CopyTo(Data, 0xE4); }
|
||||
public byte FormArgumentRemain { get => (byte)FormArgument; set => FormArgument = (FormArgument & ~0xFFu) | value; }
|
||||
public byte FormArgumentElapsed { get => (byte)(FormArgument >> 8); set => FormArgument = (FormArgument & ~0xFF00u) | (uint)(value << 8); }
|
||||
public byte FormArgumentMaximum { get => (byte)(FormArgument >> 16); set => FormArgument = (FormArgument & ~0xFF0000u) | (uint)(value << 16); }
|
||||
public sbyte AffixedRibbon { get => (sbyte)Data[0xE8]; set => Data[0xE8] = (byte)value; } // selected ribbon
|
||||
// remainder unused
|
||||
|
||||
#endregion
|
||||
#region Block D
|
||||
public override string OT_Name { get => GetString(0xF8, 24); set => SetString(value, 12).CopyTo(Data, 0xF8); }
|
||||
public override int OT_Friendship { get => Data[0x112]; set => Data[0x112] = (byte)value; }
|
||||
public int OT_Intensity { get => Data[0x113]; set => Data[0x113] = (byte)value; }
|
||||
public int OT_Memory { get => Data[0x114]; set => Data[0x114] = (byte)value; }
|
||||
// 0x115 unused align
|
||||
public int OT_TextVar { get => BitConverter.ToUInt16(Data, 0x116); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x116); }
|
||||
public int OT_Feeling { get => Data[0x118]; set => Data[0x118] = (byte)value; }
|
||||
public override int Egg_Year { get => Data[0x119]; set => Data[0x119] = (byte)value; }
|
||||
public override int Egg_Month { get => Data[0x11A]; set => Data[0x11A] = (byte)value; }
|
||||
public override int Egg_Day { get => Data[0x11B]; set => Data[0x11B] = (byte)value; }
|
||||
public override int Met_Year { get => Data[0x11C]; set => Data[0x11C] = (byte)value; }
|
||||
public override int Met_Month { get => Data[0x11D]; set => Data[0x11D] = (byte)value; }
|
||||
public override int Met_Day { get => Data[0x11E]; set => Data[0x11E] = (byte)value; }
|
||||
// 0x11F unused align
|
||||
public override int Egg_Location { get => BitConverter.ToUInt16(Data, 0x120); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x120); }
|
||||
public override int Met_Location { get => BitConverter.ToUInt16(Data, 0x122); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x122); }
|
||||
public override int Ball { get => Data[0x124]; set => Data[0x124] = (byte)value; }
|
||||
public override int Met_Level { get => Data[0x125] & ~0x80; set => Data[0x125] = (byte)((Data[0x125] & 0x80) | value); }
|
||||
public override int OT_Gender { get => Data[0x125] >> 7; set => Data[0x125] = (byte)((Data[0x125] & ~0x80) | (value << 7)); }
|
||||
public int HyperTrainFlags { get => Data[0x126]; set => Data[0x126] = (byte)value; }
|
||||
public bool HT_HP { get => ((HyperTrainFlags >> 0) & 1) == 1; set => HyperTrainFlags = (HyperTrainFlags & ~(1 << 0)) | ((value ? 1 : 0) << 0); }
|
||||
public bool HT_ATK { get => ((HyperTrainFlags >> 1) & 1) == 1; set => HyperTrainFlags = (HyperTrainFlags & ~(1 << 1)) | ((value ? 1 : 0) << 1); }
|
||||
public bool HT_DEF { get => ((HyperTrainFlags >> 2) & 1) == 1; set => HyperTrainFlags = (HyperTrainFlags & ~(1 << 2)) | ((value ? 1 : 0) << 2); }
|
||||
public bool HT_SPA { get => ((HyperTrainFlags >> 3) & 1) == 1; set => HyperTrainFlags = (HyperTrainFlags & ~(1 << 3)) | ((value ? 1 : 0) << 3); }
|
||||
public bool HT_SPD { get => ((HyperTrainFlags >> 4) & 1) == 1; set => HyperTrainFlags = (HyperTrainFlags & ~(1 << 4)) | ((value ? 1 : 0) << 4); }
|
||||
public bool HT_SPE { get => ((HyperTrainFlags >> 5) & 1) == 1; set => HyperTrainFlags = (HyperTrainFlags & ~(1 << 5)) | ((value ? 1 : 0) << 5); }
|
||||
|
||||
public bool GetMoveRecordFlag(int index)
|
||||
{
|
||||
if ((uint)index > 112) // 14 bytes, 8 bits
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
int ofs = index >> 3;
|
||||
return FlagUtil.GetFlag(Data, 0x127 + ofs, index & 7);
|
||||
}
|
||||
|
||||
public void SetMoveRecordFlag(int index, bool value)
|
||||
{
|
||||
if ((uint)index > 112) // 14 bytes, 8 bits
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
int ofs = index >> 3;
|
||||
FlagUtil.SetFlag(Data, 0x127 + ofs, index & 7, value);
|
||||
}
|
||||
|
||||
public bool HasAnyMoveRecordFlag() => Array.FindIndex(Data, 0x127, 14, z => z != 0) >= 0;
|
||||
|
||||
// Why did you mis-align this field, GameFreak?
|
||||
public ulong Tracker
|
||||
{
|
||||
get => BitConverter.ToUInt64(Data, 0x135);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x135);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region Battle Stats
|
||||
public override int Stat_Level { get => Data[0x148]; set => Data[0x148] = (byte)value; }
|
||||
// 0x149 unused alignment
|
||||
public override int Stat_HPMax { get => BitConverter.ToUInt16(Data, 0x14A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x14A); }
|
||||
public override int Stat_ATK { get => BitConverter.ToUInt16(Data, 0x14C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x14C); }
|
||||
public override int Stat_DEF { get => BitConverter.ToUInt16(Data, 0x14E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x14E); }
|
||||
public override int Stat_SPE { get => BitConverter.ToUInt16(Data, 0x150); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x150); }
|
||||
public override int Stat_SPA { get => BitConverter.ToUInt16(Data, 0x152); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x152); }
|
||||
public override int Stat_SPD { get => BitConverter.ToUInt16(Data, 0x154); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x154); }
|
||||
#endregion
|
||||
|
||||
public override int[] Markings
|
||||
{
|
||||
get
|
||||
{
|
||||
int[] marks = new int[8];
|
||||
int val = MarkValue;
|
||||
for (int i = 0; i < marks.Length; i++)
|
||||
marks[i] = ((val >> (i * 2)) & 3) % 3;
|
||||
return marks;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value.Length > 8)
|
||||
return;
|
||||
int v = 0;
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
v |= (value[i] % 3) << (i * 2);
|
||||
MarkValue = v;
|
||||
}
|
||||
}
|
||||
|
||||
public bool GetRibbon(int index) => FlagUtil.GetFlag(Data, GetRibbonByte(index), index & 7);
|
||||
public void SetRibbon(int index, bool value = true) => FlagUtil.SetFlag(Data, GetRibbonByte(index), index & 7, value);
|
||||
|
||||
public int GetRibbonByte(int index)
|
||||
{
|
||||
if ((uint)index >= 128)
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
if (index < 64)
|
||||
return 0x34 + (index >> 3);
|
||||
index -= 64;
|
||||
return 0x40 + (index >> 3);
|
||||
}
|
||||
}
|
||||
}
|
110
PKHeX.Core/PKM/PB8.cs
Normal file
110
PKHeX.Core/PKM/PB8.cs
Normal file
|
@ -0,0 +1,110 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary> Generation 8 <see cref="PKM"/> format. </summary>
|
||||
public sealed class PB8 : G8PKM
|
||||
{
|
||||
private static readonly ushort[] Unused =
|
||||
{
|
||||
// Alignment bytes
|
||||
0x17, 0x1A, 0x1B, 0x23, 0x33, 0x3E, 0x3F,
|
||||
0x4C, 0x4D, 0x4E, 0x4F,
|
||||
0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||||
|
||||
0x91, 0x92, 0x93,
|
||||
0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
|
||||
|
||||
0xC5,
|
||||
0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB,
|
||||
0xE0, 0xE1, // Old Console Region / Region
|
||||
0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
|
||||
0x115, 0x11F, // Alignment
|
||||
|
||||
0x13D, 0x13E, 0x13F,
|
||||
0x140, 0x141, 0x142, 0x143, 0x144, 0x145, 0x146, 0x147,
|
||||
};
|
||||
|
||||
public override IReadOnlyList<ushort> ExtraBytes => Unused;
|
||||
public override PersonalInfo PersonalInfo => PersonalTable.BDSP.GetFormEntry(Species, Form);
|
||||
|
||||
public PB8() => Egg_Location = Met_Location = Locations.Default8bNone;
|
||||
public PB8(byte[] data) : base(data) { }
|
||||
public override PKM Clone() => new PB8((byte[])Data.Clone());
|
||||
|
||||
public void Trade(ITrainerInfo tr, int Day = 1, int Month = 1, int Year = 2015)
|
||||
{
|
||||
if (IsEgg)
|
||||
{
|
||||
// Eggs do not have any modifications done if they are traded
|
||||
// Apply link trade data, only if it left the OT (ignore if dumped & imported, or cloned, etc)
|
||||
// if ((tr.OT != OT_Name) || (tr.TID != TID) || (tr.SID != SID) || (tr.Gender != OT_Gender))
|
||||
// SetLinkTradeEgg(Day, Month, Year, Locations.LinkTrade6NPC);
|
||||
// return;
|
||||
}
|
||||
|
||||
// Process to the HT if the OT of the Pokémon does not match the SAV's OT info.
|
||||
if (!TradeOT(tr))
|
||||
TradeHT(tr);
|
||||
}
|
||||
|
||||
public void FixMemories()
|
||||
{
|
||||
if (BDSP)
|
||||
{
|
||||
OT_TextVar = OT_Memory = OT_Intensity = OT_Feeling = 0;
|
||||
HT_TextVar = HT_Memory = HT_Intensity = HT_Feeling = 0; // future inter-format conversion?
|
||||
}
|
||||
|
||||
if (IsEgg) // No memories if is egg.
|
||||
{
|
||||
HT_Language = HT_Friendship = HT_TextVar = HT_Memory = HT_Intensity = HT_Feeling =
|
||||
/* OT_Friendship */ OT_TextVar = OT_Memory = OT_Intensity = OT_Feeling = 0;
|
||||
|
||||
// Clear Handler
|
||||
HT_Trash.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsUntraded)
|
||||
HT_Language = HT_Friendship = HT_TextVar = HT_Memory = HT_Intensity = HT_Feeling = 0;
|
||||
|
||||
int gen = Generation;
|
||||
if (gen < 6)
|
||||
OT_TextVar = OT_Memory = OT_Intensity = OT_Feeling = 0;
|
||||
// if (gen != 8) // must be transferred via HOME, and must have memories
|
||||
// this.SetTradeMemoryHT8(); // not faking HOME tracker.
|
||||
}
|
||||
|
||||
private bool TradeOT(ITrainerInfo tr)
|
||||
{
|
||||
// Check to see if the OT matches the SAV's OT info.
|
||||
if (!(tr.OT == OT_Name && tr.TID == TID && tr.SID == SID && tr.Gender == OT_Gender))
|
||||
return false;
|
||||
|
||||
CurrentHandler = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void TradeHT(ITrainerInfo tr)
|
||||
{
|
||||
if (HT_Name != tr.OT)
|
||||
{
|
||||
HT_Friendship = 50;
|
||||
HT_Name = tr.OT;
|
||||
}
|
||||
CurrentHandler = 1;
|
||||
HT_Gender = tr.Gender;
|
||||
HT_Language = tr.Language;
|
||||
//this.SetTradeMemoryHT8();
|
||||
}
|
||||
|
||||
// Maximums
|
||||
public override int MaxMoveID => Legal.MaxMoveID_8b;
|
||||
public override int MaxSpeciesID => Legal.MaxSpeciesID_8b;
|
||||
public override int MaxAbilityID => Legal.MaxAbilityID_8b;
|
||||
public override int MaxItemID => Legal.MaxItemID_8b;
|
||||
public override int MaxBallID => Legal.MaxBallID_8b;
|
||||
public override int MaxGameID => Legal.MaxGameID_8b;
|
||||
}
|
||||
}
|
|
@ -109,7 +109,7 @@ namespace PKHeX.Core
|
|||
public byte CNT_Smart { get => Data[0x27]; set => Data[0x27] = value; }
|
||||
public byte CNT_Tough { get => Data[0x28]; set => Data[0x28] = value; }
|
||||
public byte CNT_Sheen { get => Data[0x29]; set => Data[0x29] = value; }
|
||||
public byte ResortEventStatus { get => Data[0x2A]; set => Data[0x2A] = value; }
|
||||
public ResortEventState ResortEventStatus { get => (ResortEventState)Data[0x2A]; set => Data[0x2A] = (byte)value; }
|
||||
private byte PKRS { get => Data[0x2B]; set => Data[0x2B] = value; }
|
||||
public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); }
|
||||
public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | value << 4); }
|
||||
|
@ -656,4 +656,29 @@ namespace PKHeX.Core
|
|||
return pk8; // Done!
|
||||
}
|
||||
}
|
||||
|
||||
public enum ResortEventState : byte
|
||||
{
|
||||
NONE = 0,
|
||||
SEIKAKU = 1,
|
||||
CARE = 2,
|
||||
LIKE_RESORT = 3,
|
||||
LIKE_BATTLE = 4,
|
||||
LIKE_ADV = 5,
|
||||
GOOD_FRIEND = 6,
|
||||
GIM = 7,
|
||||
HOTSPA = 8,
|
||||
WILD = 9,
|
||||
WILD_LOVE = 10,
|
||||
WILD_LIVE = 11,
|
||||
POKEMAME_GET1 = 12,
|
||||
POKEMAME_GET2 = 13,
|
||||
POKEMAME_GET3 = 14,
|
||||
KINOMI_HELP = 15,
|
||||
PLAY_STATE = 16,
|
||||
HOTSPA_STATE = 17,
|
||||
HOTSPA_DIZZY = 18,
|
||||
HOTSPA_EGG_HATCHING = 19,
|
||||
MAX = 20,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,7 @@ using System.Collections.Generic;
|
|||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary> Generation 8 <see cref="PKM"/> format. </summary>
|
||||
public sealed class PK8 : PKM,
|
||||
IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetMark8,
|
||||
IContestStats, IContestStatsMutable, IHyperTrain, IScaledSize, IGigantamax, IFavorite, IDynamaxLevel, IRibbonIndex, IHandlerLanguage, IFormArgument, IHomeTrack, IBattleVersion, ITrainerMemories
|
||||
public sealed class PK8 : G8PKM
|
||||
{
|
||||
private static readonly ushort[] Unused =
|
||||
{
|
||||
|
@ -29,107 +27,12 @@ namespace PKHeX.Core
|
|||
};
|
||||
|
||||
public override IReadOnlyList<ushort> ExtraBytes => Unused;
|
||||
public override int Format => 8;
|
||||
public override PersonalInfo PersonalInfo => PersonalTable.SWSH.GetFormEntry(Species, Form);
|
||||
|
||||
public PK8() : base(PokeCrypto.SIZE_8PARTY) => AffixedRibbon = -1; // 00 would make it show Kalos Champion :)
|
||||
public PK8(byte[] data) : base(DecryptParty(data)) { }
|
||||
|
||||
private static byte[] DecryptParty(byte[] data)
|
||||
{
|
||||
PokeCrypto.DecryptIfEncrypted8(ref data);
|
||||
Array.Resize(ref data, PokeCrypto.SIZE_8PARTY);
|
||||
return data;
|
||||
}
|
||||
|
||||
protected override ushort CalculateChecksum()
|
||||
{
|
||||
ushort chk = 0;
|
||||
for (int i = 8; i < PokeCrypto.SIZE_8STORED; i += 2)
|
||||
chk += BitConverter.ToUInt16(Data, i);
|
||||
return chk;
|
||||
}
|
||||
|
||||
// Simple Generated Attributes
|
||||
public override int CurrentFriendship
|
||||
{
|
||||
get => CurrentHandler == 0 ? OT_Friendship : HT_Friendship;
|
||||
set { if (CurrentHandler == 0) OT_Friendship = value; else HT_Friendship = value; }
|
||||
}
|
||||
|
||||
public PK8() => AffixedRibbon = -1; // 00 would make it show Kalos Champion :)
|
||||
public PK8(byte[] data) : base(data) { }
|
||||
public override PKM Clone() => new PK8((byte[])Data.Clone());
|
||||
|
||||
private string GetString(int offset, int count) => StringConverter.GetString7b(Data, offset, count);
|
||||
private static byte[] SetString(string value, int maxLength) => StringConverter.SetString7b(value, maxLength);
|
||||
|
||||
public override int SIZE_PARTY => PokeCrypto.SIZE_8PARTY;
|
||||
public override int SIZE_STORED => PokeCrypto.SIZE_8STORED;
|
||||
|
||||
// Trash Bytes
|
||||
public override Span<byte> Nickname_Trash { get => Data.AsSpan(0x58, 24); set { if (value.Length == 24) value.CopyTo(Data.AsSpan(0x58)); } }
|
||||
public override Span<byte> HT_Trash { get => Data.AsSpan(0xA8, 24); set { if (value.Length == 24) value.CopyTo(Data.AsSpan(0xA8)); } }
|
||||
public override Span<byte> OT_Trash { get => Data.AsSpan(0xF8, 24); set { if (value.Length == 24) value.CopyTo(Data.AsSpan(0xF8)); } }
|
||||
|
||||
// Maximums
|
||||
public override int MaxIV => 31;
|
||||
public override int MaxEV => 252;
|
||||
public override int OTLength => 12;
|
||||
public override int NickLength => 12;
|
||||
|
||||
public override int PSV => (int)((PID >> 16 ^ (PID & 0xFFFF)) >> 4);
|
||||
public override int TSV => (TID ^ SID) >> 4;
|
||||
public override bool IsUntraded => Data[0xA8] == 0 && Data[0xA8 + 1] == 0 && Format == Generation; // immediately terminated HT_Name data (\0)
|
||||
|
||||
// Complex Generated Attributes
|
||||
public override int Characteristic
|
||||
{
|
||||
get
|
||||
{
|
||||
int pm6 = (int)(EncryptionConstant % 6);
|
||||
int maxIV = MaximumIV;
|
||||
int pm6stat = 0;
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
pm6stat = (pm6 + i) % 6;
|
||||
if (GetIV(pm6stat) == maxIV)
|
||||
break;
|
||||
}
|
||||
return (pm6stat * 5) + (maxIV % 5);
|
||||
}
|
||||
}
|
||||
|
||||
// Methods
|
||||
protected override byte[] Encrypt()
|
||||
{
|
||||
RefreshChecksum();
|
||||
return PokeCrypto.EncryptArray8(Data);
|
||||
}
|
||||
|
||||
public void FixRelearn()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (RelearnMove4 != 0 && RelearnMove3 == 0)
|
||||
{
|
||||
RelearnMove3 = RelearnMove4;
|
||||
RelearnMove4 = 0;
|
||||
}
|
||||
if (RelearnMove3 != 0 && RelearnMove2 == 0)
|
||||
{
|
||||
RelearnMove2 = RelearnMove3;
|
||||
RelearnMove3 = 0;
|
||||
continue;
|
||||
}
|
||||
if (RelearnMove2 != 0 && RelearnMove1 == 0)
|
||||
{
|
||||
RelearnMove1 = RelearnMove2;
|
||||
RelearnMove2 = 0;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void Trade(ITrainerInfo tr, int Day = 1, int Month = 1, int Year = 2015)
|
||||
{
|
||||
if (IsEgg)
|
||||
|
@ -145,391 +48,8 @@ namespace PKHeX.Core
|
|||
if (!TradeOT(tr))
|
||||
TradeHT(tr);
|
||||
}
|
||||
|
||||
public override uint EncryptionConstant { get => BitConverter.ToUInt32(Data, 0x00); set => BitConverter.GetBytes(value).CopyTo(Data, 0x00); }
|
||||
public override ushort Sanity { get => BitConverter.ToUInt16(Data, 0x04); set => BitConverter.GetBytes(value).CopyTo(Data, 0x04); }
|
||||
public override ushort Checksum { get => BitConverter.ToUInt16(Data, 0x06); set => BitConverter.GetBytes(value).CopyTo(Data, 0x06); }
|
||||
|
||||
// Structure
|
||||
#region Block A
|
||||
public override int Species { get => BitConverter.ToUInt16(Data, 0x08); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x08); }
|
||||
public override int HeldItem { get => BitConverter.ToUInt16(Data, 0x0A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0A); }
|
||||
public override int TID { get => BitConverter.ToUInt16(Data, 0x0C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0C); }
|
||||
public override int SID { get => BitConverter.ToUInt16(Data, 0x0E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0E); }
|
||||
public override uint EXP { get => BitConverter.ToUInt32(Data, 0x10); set => BitConverter.GetBytes(value).CopyTo(Data, 0x10); }
|
||||
public override int Ability { get => BitConverter.ToUInt16(Data, 0x14); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x14); }
|
||||
public override int AbilityNumber { get => Data[0x16] & 7; set => Data[0x16] = (byte)((Data[0x16] & ~7) | (value & 7)); }
|
||||
public bool Favorite { get => (Data[0x16] & 8) != 0; set => Data[0x16] = (byte)((Data[0x16] & ~8) | ((value ? 1 : 0) << 3)); } // unused, was in LGPE but not in SWSH
|
||||
public bool CanGigantamax { get => (Data[0x16] & 16) != 0; set => Data[0x16] = (byte)((Data[0x16] & ~16) | (value ? 16 : 0)); }
|
||||
// 0x17 alignment unused
|
||||
public override int MarkValue { get => BitConverter.ToUInt16(Data, 0x18); protected set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x18); }
|
||||
// 0x1A alignment unused
|
||||
// 0x1B alignment unused
|
||||
public override uint PID { get => BitConverter.ToUInt32(Data, 0x1C); set => BitConverter.GetBytes(value).CopyTo(Data, 0x1C); }
|
||||
public override int Nature { get => Data[0x20]; set => Data[0x20] = (byte)value; }
|
||||
public override int StatNature { get => Data[0x21]; set => Data[0x21] = (byte)value; }
|
||||
public override bool FatefulEncounter { get => (Data[0x22] & 1) == 1; set => Data[0x22] = (byte)((Data[0x22] & ~0x01) | (value ? 1 : 0)); }
|
||||
public bool Flag2 { get => (Data[0x22] & 2) == 2; set => Data[0x22] = (byte)((Data[0x22] & ~0x02) | (value ? 2 : 0)); }
|
||||
public override int Gender { get => (Data[0x22] >> 2) & 0x3; set => Data[0x22] = (byte)((Data[0x22] & 0xF3) | (value << 2)); }
|
||||
// 0x23 alignment unused
|
||||
|
||||
public override int Form { get => BitConverter.ToUInt16(Data, 0x24); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x24); }
|
||||
public override int EV_HP { get => Data[0x26]; set => Data[0x26] = (byte)value; }
|
||||
public override int EV_ATK { get => Data[0x27]; set => Data[0x27] = (byte)value; }
|
||||
public override int EV_DEF { get => Data[0x28]; set => Data[0x28] = (byte)value; }
|
||||
public override int EV_SPE { get => Data[0x29]; set => Data[0x29] = (byte)value; }
|
||||
public override int EV_SPA { get => Data[0x2A]; set => Data[0x2A] = (byte)value; }
|
||||
public override int EV_SPD { get => Data[0x2B]; set => Data[0x2B] = (byte)value; }
|
||||
public byte CNT_Cool { get => Data[0x2C]; set => Data[0x2C] = value; }
|
||||
public byte CNT_Beauty { get => Data[0x2D]; set => Data[0x2D] = value; }
|
||||
public byte CNT_Cute { get => Data[0x2E]; set => Data[0x2E] = value; }
|
||||
public byte CNT_Smart { get => Data[0x2F]; set => Data[0x2F] = value; }
|
||||
public byte CNT_Tough { get => Data[0x30]; set => Data[0x30] = value; }
|
||||
public byte CNT_Sheen { get => Data[0x31]; set => Data[0x31] = value; }
|
||||
private byte PKRS { get => Data[0x32]; set => Data[0x32] = value; }
|
||||
public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); }
|
||||
public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | value << 4); }
|
||||
// 0x33 unused padding
|
||||
|
||||
// ribbon u32
|
||||
public bool RibbonChampionKalos { get => FlagUtil.GetFlag(Data, 0x34, 0); set => FlagUtil.SetFlag(Data, 0x34, 0, value); }
|
||||
public bool RibbonChampionG3 { get => FlagUtil.GetFlag(Data, 0x34, 1); set => FlagUtil.SetFlag(Data, 0x34, 1, value); }
|
||||
public bool RibbonChampionSinnoh { get => FlagUtil.GetFlag(Data, 0x34, 2); set => FlagUtil.SetFlag(Data, 0x34, 2, value); }
|
||||
public bool RibbonBestFriends { get => FlagUtil.GetFlag(Data, 0x34, 3); set => FlagUtil.SetFlag(Data, 0x34, 3, value); }
|
||||
public bool RibbonTraining { get => FlagUtil.GetFlag(Data, 0x34, 4); set => FlagUtil.SetFlag(Data, 0x34, 4, value); }
|
||||
public bool RibbonBattlerSkillful { get => FlagUtil.GetFlag(Data, 0x34, 5); set => FlagUtil.SetFlag(Data, 0x34, 5, value); }
|
||||
public bool RibbonBattlerExpert { get => FlagUtil.GetFlag(Data, 0x34, 6); set => FlagUtil.SetFlag(Data, 0x34, 6, value); }
|
||||
public bool RibbonEffort { get => FlagUtil.GetFlag(Data, 0x34, 7); set => FlagUtil.SetFlag(Data, 0x34, 7, value); }
|
||||
|
||||
public bool RibbonAlert { get => FlagUtil.GetFlag(Data, 0x35, 0); set => FlagUtil.SetFlag(Data, 0x35, 0, value); }
|
||||
public bool RibbonShock { get => FlagUtil.GetFlag(Data, 0x35, 1); set => FlagUtil.SetFlag(Data, 0x35, 1, value); }
|
||||
public bool RibbonDowncast { get => FlagUtil.GetFlag(Data, 0x35, 2); set => FlagUtil.SetFlag(Data, 0x35, 2, value); }
|
||||
public bool RibbonCareless { get => FlagUtil.GetFlag(Data, 0x35, 3); set => FlagUtil.SetFlag(Data, 0x35, 3, value); }
|
||||
public bool RibbonRelax { get => FlagUtil.GetFlag(Data, 0x35, 4); set => FlagUtil.SetFlag(Data, 0x35, 4, value); }
|
||||
public bool RibbonSnooze { get => FlagUtil.GetFlag(Data, 0x35, 5); set => FlagUtil.SetFlag(Data, 0x35, 5, value); }
|
||||
public bool RibbonSmile { get => FlagUtil.GetFlag(Data, 0x35, 6); set => FlagUtil.SetFlag(Data, 0x35, 6, value); }
|
||||
public bool RibbonGorgeous { get => FlagUtil.GetFlag(Data, 0x35, 7); set => FlagUtil.SetFlag(Data, 0x35, 7, value); }
|
||||
|
||||
public bool RibbonRoyal { get => FlagUtil.GetFlag(Data, 0x36, 0); set => FlagUtil.SetFlag(Data, 0x36, 0, value); }
|
||||
public bool RibbonGorgeousRoyal { get => FlagUtil.GetFlag(Data, 0x36, 1); set => FlagUtil.SetFlag(Data, 0x36, 1, value); }
|
||||
public bool RibbonArtist { get => FlagUtil.GetFlag(Data, 0x36, 2); set => FlagUtil.SetFlag(Data, 0x36, 2, value); }
|
||||
public bool RibbonFootprint { get => FlagUtil.GetFlag(Data, 0x36, 3); set => FlagUtil.SetFlag(Data, 0x36, 3, value); }
|
||||
public bool RibbonRecord { get => FlagUtil.GetFlag(Data, 0x36, 4); set => FlagUtil.SetFlag(Data, 0x36, 4, value); }
|
||||
public bool RibbonLegend { get => FlagUtil.GetFlag(Data, 0x36, 5); set => FlagUtil.SetFlag(Data, 0x36, 5, value); }
|
||||
public bool RibbonCountry { get => FlagUtil.GetFlag(Data, 0x36, 6); set => FlagUtil.SetFlag(Data, 0x36, 6, value); }
|
||||
public bool RibbonNational { get => FlagUtil.GetFlag(Data, 0x36, 7); set => FlagUtil.SetFlag(Data, 0x36, 7, value); }
|
||||
|
||||
public bool RibbonEarth { get => FlagUtil.GetFlag(Data, 0x37, 0); set => FlagUtil.SetFlag(Data, 0x37, 0, value); }
|
||||
public bool RibbonWorld { get => FlagUtil.GetFlag(Data, 0x37, 1); set => FlagUtil.SetFlag(Data, 0x37, 1, value); }
|
||||
public bool RibbonClassic { get => FlagUtil.GetFlag(Data, 0x37, 2); set => FlagUtil.SetFlag(Data, 0x37, 2, value); }
|
||||
public bool RibbonPremier { get => FlagUtil.GetFlag(Data, 0x37, 3); set => FlagUtil.SetFlag(Data, 0x37, 3, value); }
|
||||
public bool RibbonEvent { get => FlagUtil.GetFlag(Data, 0x37, 4); set => FlagUtil.SetFlag(Data, 0x37, 4, value); }
|
||||
public bool RibbonBirthday { get => FlagUtil.GetFlag(Data, 0x37, 5); set => FlagUtil.SetFlag(Data, 0x37, 5, value); }
|
||||
public bool RibbonSpecial { get => FlagUtil.GetFlag(Data, 0x37, 6); set => FlagUtil.SetFlag(Data, 0x37, 6, value); }
|
||||
public bool RibbonSouvenir { get => FlagUtil.GetFlag(Data, 0x37, 7); set => FlagUtil.SetFlag(Data, 0x37, 7, value); }
|
||||
|
||||
// ribbon u32
|
||||
public bool RibbonWishing { get => FlagUtil.GetFlag(Data, 0x38, 0); set => FlagUtil.SetFlag(Data, 0x38, 0, value); }
|
||||
public bool RibbonChampionBattle { get => FlagUtil.GetFlag(Data, 0x38, 1); set => FlagUtil.SetFlag(Data, 0x38, 1, value); }
|
||||
public bool RibbonChampionRegional { get => FlagUtil.GetFlag(Data, 0x38, 2); set => FlagUtil.SetFlag(Data, 0x38, 2, value); }
|
||||
public bool RibbonChampionNational { get => FlagUtil.GetFlag(Data, 0x38, 3); set => FlagUtil.SetFlag(Data, 0x38, 3, value); }
|
||||
public bool RibbonChampionWorld { get => FlagUtil.GetFlag(Data, 0x38, 4); set => FlagUtil.SetFlag(Data, 0x38, 4, value); }
|
||||
public bool HasContestMemoryRibbon { get => FlagUtil.GetFlag(Data, 0x38, 5); set => FlagUtil.SetFlag(Data, 0x38, 5, value); }
|
||||
public bool HasBattleMemoryRibbon { get => FlagUtil.GetFlag(Data, 0x38, 6); set => FlagUtil.SetFlag(Data, 0x38, 6, value); }
|
||||
public bool RibbonChampionG6Hoenn { get => FlagUtil.GetFlag(Data, 0x38, 7); set => FlagUtil.SetFlag(Data, 0x38, 7, value); }
|
||||
|
||||
public bool RibbonContestStar { get => FlagUtil.GetFlag(Data, 0x39, 0); set => FlagUtil.SetFlag(Data, 0x39, 0, value); }
|
||||
public bool RibbonMasterCoolness { get => FlagUtil.GetFlag(Data, 0x39, 1); set => FlagUtil.SetFlag(Data, 0x39, 1, value); }
|
||||
public bool RibbonMasterBeauty { get => FlagUtil.GetFlag(Data, 0x39, 2); set => FlagUtil.SetFlag(Data, 0x39, 2, value); }
|
||||
public bool RibbonMasterCuteness { get => FlagUtil.GetFlag(Data, 0x39, 3); set => FlagUtil.SetFlag(Data, 0x39, 3, value); }
|
||||
public bool RibbonMasterCleverness { get => FlagUtil.GetFlag(Data, 0x39, 4); set => FlagUtil.SetFlag(Data, 0x39, 4, value); }
|
||||
public bool RibbonMasterToughness { get => FlagUtil.GetFlag(Data, 0x39, 5); set => FlagUtil.SetFlag(Data, 0x39, 5, value); }
|
||||
public bool RibbonChampionAlola { get => FlagUtil.GetFlag(Data, 0x39, 6); set => FlagUtil.SetFlag(Data, 0x39, 6, value); }
|
||||
public bool RibbonBattleRoyale { get => FlagUtil.GetFlag(Data, 0x39, 7); set => FlagUtil.SetFlag(Data, 0x39, 7, value); }
|
||||
|
||||
public bool RibbonBattleTreeGreat { get => FlagUtil.GetFlag(Data, 0x3A, 0); set => FlagUtil.SetFlag(Data, 0x3A, 0, value); }
|
||||
public bool RibbonBattleTreeMaster { get => FlagUtil.GetFlag(Data, 0x3A, 1); set => FlagUtil.SetFlag(Data, 0x3A, 1, value); }
|
||||
public bool RibbonChampionGalar { get => FlagUtil.GetFlag(Data, 0x3A, 2); set => FlagUtil.SetFlag(Data, 0x3A, 2, value); }
|
||||
public bool RibbonTowerMaster { get => FlagUtil.GetFlag(Data, 0x3A, 3); set => FlagUtil.SetFlag(Data, 0x3A, 3, value); }
|
||||
public bool RibbonMasterRank { get => FlagUtil.GetFlag(Data, 0x3A, 4); set => FlagUtil.SetFlag(Data, 0x3A, 4, value); }
|
||||
public bool RibbonMarkLunchtime { get => FlagUtil.GetFlag(Data, 0x3A, 5); set => FlagUtil.SetFlag(Data, 0x3A, 5, value); }
|
||||
public bool RibbonMarkSleepyTime { get => FlagUtil.GetFlag(Data, 0x3A, 6); set => FlagUtil.SetFlag(Data, 0x3A, 6, value); }
|
||||
public bool RibbonMarkDusk { get => FlagUtil.GetFlag(Data, 0x3A, 7); set => FlagUtil.SetFlag(Data, 0x3A, 7, value); }
|
||||
|
||||
public bool RibbonMarkDawn { get => FlagUtil.GetFlag(Data, 0x3B, 0); set => FlagUtil.SetFlag(Data, 0x3B, 0, value); }
|
||||
public bool RibbonMarkCloudy { get => FlagUtil.GetFlag(Data, 0x3B, 1); set => FlagUtil.SetFlag(Data, 0x3B, 1, value); }
|
||||
public bool RibbonMarkRainy { get => FlagUtil.GetFlag(Data, 0x3B, 2); set => FlagUtil.SetFlag(Data, 0x3B, 2, value); }
|
||||
public bool RibbonMarkStormy { get => FlagUtil.GetFlag(Data, 0x3B, 3); set => FlagUtil.SetFlag(Data, 0x3B, 3, value); }
|
||||
public bool RibbonMarkSnowy { get => FlagUtil.GetFlag(Data, 0x3B, 4); set => FlagUtil.SetFlag(Data, 0x3B, 4, value); }
|
||||
public bool RibbonMarkBlizzard { get => FlagUtil.GetFlag(Data, 0x3B, 5); set => FlagUtil.SetFlag(Data, 0x3B, 5, value); }
|
||||
public bool RibbonMarkDry { get => FlagUtil.GetFlag(Data, 0x3B, 6); set => FlagUtil.SetFlag(Data, 0x3B, 6, value); }
|
||||
public bool RibbonMarkSandstorm { get => FlagUtil.GetFlag(Data, 0x3B, 7); set => FlagUtil.SetFlag(Data, 0x3B, 7, value); }
|
||||
public int RibbonCountMemoryContest { get => Data[0x3C]; set => HasContestMemoryRibbon = (Data[0x3C] = (byte)value) != 0; }
|
||||
public int RibbonCountMemoryBattle { get => Data[0x3D]; set => HasBattleMemoryRibbon = (Data[0x3D] = (byte)value) != 0; }
|
||||
// 0x3E padding
|
||||
// 0x3F padding
|
||||
|
||||
// 0x40 Ribbon 1
|
||||
public bool RibbonMarkMisty { get => FlagUtil.GetFlag(Data, 0x40, 0); set => FlagUtil.SetFlag(Data, 0x40, 0, value); }
|
||||
public bool RibbonMarkDestiny { get => FlagUtil.GetFlag(Data, 0x40, 1); set => FlagUtil.SetFlag(Data, 0x40, 1, value); }
|
||||
public bool RibbonMarkFishing { get => FlagUtil.GetFlag(Data, 0x40, 2); set => FlagUtil.SetFlag(Data, 0x40, 2, value); }
|
||||
public bool RibbonMarkCurry { get => FlagUtil.GetFlag(Data, 0x40, 3); set => FlagUtil.SetFlag(Data, 0x40, 3, value); }
|
||||
public bool RibbonMarkUncommon { get => FlagUtil.GetFlag(Data, 0x40, 4); set => FlagUtil.SetFlag(Data, 0x40, 4, value); }
|
||||
public bool RibbonMarkRare { get => FlagUtil.GetFlag(Data, 0x40, 5); set => FlagUtil.SetFlag(Data, 0x40, 5, value); }
|
||||
public bool RibbonMarkRowdy { get => FlagUtil.GetFlag(Data, 0x40, 6); set => FlagUtil.SetFlag(Data, 0x40, 6, value); }
|
||||
public bool RibbonMarkAbsentMinded { get => FlagUtil.GetFlag(Data, 0x40, 7); set => FlagUtil.SetFlag(Data, 0x40, 7, value); }
|
||||
|
||||
public bool RibbonMarkJittery { get => FlagUtil.GetFlag(Data, 0x41, 0); set => FlagUtil.SetFlag(Data, 0x41, 0, value); }
|
||||
public bool RibbonMarkExcited { get => FlagUtil.GetFlag(Data, 0x41, 1); set => FlagUtil.SetFlag(Data, 0x41, 1, value); }
|
||||
public bool RibbonMarkCharismatic { get => FlagUtil.GetFlag(Data, 0x41, 2); set => FlagUtil.SetFlag(Data, 0x41, 2, value); }
|
||||
public bool RibbonMarkCalmness { get => FlagUtil.GetFlag(Data, 0x41, 3); set => FlagUtil.SetFlag(Data, 0x41, 3, value); }
|
||||
public bool RibbonMarkIntense { get => FlagUtil.GetFlag(Data, 0x41, 4); set => FlagUtil.SetFlag(Data, 0x41, 4, value); }
|
||||
public bool RibbonMarkZonedOut { get => FlagUtil.GetFlag(Data, 0x41, 5); set => FlagUtil.SetFlag(Data, 0x41, 5, value); }
|
||||
public bool RibbonMarkJoyful { get => FlagUtil.GetFlag(Data, 0x41, 6); set => FlagUtil.SetFlag(Data, 0x41, 6, value); }
|
||||
public bool RibbonMarkAngry { get => FlagUtil.GetFlag(Data, 0x41, 7); set => FlagUtil.SetFlag(Data, 0x41, 7, value); }
|
||||
|
||||
public bool RibbonMarkSmiley { get => FlagUtil.GetFlag(Data, 0x42, 0); set => FlagUtil.SetFlag(Data, 0x42, 0, value); }
|
||||
public bool RibbonMarkTeary { get => FlagUtil.GetFlag(Data, 0x42, 1); set => FlagUtil.SetFlag(Data, 0x42, 1, value); }
|
||||
public bool RibbonMarkUpbeat { get => FlagUtil.GetFlag(Data, 0x42, 2); set => FlagUtil.SetFlag(Data, 0x42, 2, value); }
|
||||
public bool RibbonMarkPeeved { get => FlagUtil.GetFlag(Data, 0x42, 3); set => FlagUtil.SetFlag(Data, 0x42, 3, value); }
|
||||
public bool RibbonMarkIntellectual { get => FlagUtil.GetFlag(Data, 0x42, 4); set => FlagUtil.SetFlag(Data, 0x42, 4, value); }
|
||||
public bool RibbonMarkFerocious { get => FlagUtil.GetFlag(Data, 0x42, 5); set => FlagUtil.SetFlag(Data, 0x42, 5, value); }
|
||||
public bool RibbonMarkCrafty { get => FlagUtil.GetFlag(Data, 0x42, 6); set => FlagUtil.SetFlag(Data, 0x42, 6, value); }
|
||||
public bool RibbonMarkScowling { get => FlagUtil.GetFlag(Data, 0x42, 7); set => FlagUtil.SetFlag(Data, 0x42, 7, value); }
|
||||
|
||||
public bool RibbonMarkKindly { get => FlagUtil.GetFlag(Data, 0x43, 0); set => FlagUtil.SetFlag(Data, 0x43, 0, value); }
|
||||
public bool RibbonMarkFlustered { get => FlagUtil.GetFlag(Data, 0x43, 1); set => FlagUtil.SetFlag(Data, 0x43, 1, value); }
|
||||
public bool RibbonMarkPumpedUp { get => FlagUtil.GetFlag(Data, 0x43, 2); set => FlagUtil.SetFlag(Data, 0x43, 2, value); }
|
||||
public bool RibbonMarkZeroEnergy { get => FlagUtil.GetFlag(Data, 0x43, 3); set => FlagUtil.SetFlag(Data, 0x43, 3, value); }
|
||||
public bool RibbonMarkPrideful { get => FlagUtil.GetFlag(Data, 0x43, 4); set => FlagUtil.SetFlag(Data, 0x43, 4, value); }
|
||||
public bool RibbonMarkUnsure { get => FlagUtil.GetFlag(Data, 0x43, 5); set => FlagUtil.SetFlag(Data, 0x43, 5, value); }
|
||||
public bool RibbonMarkHumble { get => FlagUtil.GetFlag(Data, 0x43, 6); set => FlagUtil.SetFlag(Data, 0x43, 6, value); }
|
||||
public bool RibbonMarkThorny { get => FlagUtil.GetFlag(Data, 0x43, 7); set => FlagUtil.SetFlag(Data, 0x43, 7, value); }
|
||||
// 0x44 Ribbon 2
|
||||
|
||||
public bool RibbonMarkVigor { get => FlagUtil.GetFlag(Data, 0x44, 0); set => FlagUtil.SetFlag(Data, 0x44, 0, value); }
|
||||
public bool RibbonMarkSlump { get => FlagUtil.GetFlag(Data, 0x44, 1); set => FlagUtil.SetFlag(Data, 0x44, 1, value); }
|
||||
public bool RIB44_2 { get => FlagUtil.GetFlag(Data, 0x44, 2); set => FlagUtil.SetFlag(Data, 0x44, 2, value); }
|
||||
public bool RIB44_3 { get => FlagUtil.GetFlag(Data, 0x44, 3); set => FlagUtil.SetFlag(Data, 0x44, 3, value); }
|
||||
public bool RIB44_4 { get => FlagUtil.GetFlag(Data, 0x44, 4); set => FlagUtil.SetFlag(Data, 0x44, 4, value); }
|
||||
public bool RIB44_5 { get => FlagUtil.GetFlag(Data, 0x44, 5); set => FlagUtil.SetFlag(Data, 0x44, 5, value); }
|
||||
public bool RIB44_6 { get => FlagUtil.GetFlag(Data, 0x44, 6); set => FlagUtil.SetFlag(Data, 0x44, 6, value); }
|
||||
public bool RIB44_7 { get => FlagUtil.GetFlag(Data, 0x44, 7); set => FlagUtil.SetFlag(Data, 0x44, 7, value); }
|
||||
|
||||
public bool RIB45_0 { get => FlagUtil.GetFlag(Data, 0x45, 0); set => FlagUtil.SetFlag(Data, 0x45, 0, value); }
|
||||
public bool RIB45_1 { get => FlagUtil.GetFlag(Data, 0x45, 1); set => FlagUtil.SetFlag(Data, 0x45, 1, value); }
|
||||
public bool RIB45_2 { get => FlagUtil.GetFlag(Data, 0x45, 2); set => FlagUtil.SetFlag(Data, 0x45, 2, value); }
|
||||
public bool RIB45_3 { get => FlagUtil.GetFlag(Data, 0x45, 3); set => FlagUtil.SetFlag(Data, 0x45, 3, value); }
|
||||
public bool RIB45_4 { get => FlagUtil.GetFlag(Data, 0x45, 4); set => FlagUtil.SetFlag(Data, 0x45, 4, value); }
|
||||
public bool RIB45_5 { get => FlagUtil.GetFlag(Data, 0x45, 5); set => FlagUtil.SetFlag(Data, 0x45, 5, value); }
|
||||
public bool RIB45_6 { get => FlagUtil.GetFlag(Data, 0x45, 6); set => FlagUtil.SetFlag(Data, 0x45, 6, value); }
|
||||
public bool RIB45_7 { get => FlagUtil.GetFlag(Data, 0x45, 7); set => FlagUtil.SetFlag(Data, 0x45, 7, value); }
|
||||
|
||||
public bool RIB46_0 { get => FlagUtil.GetFlag(Data, 0x41, 0); set => FlagUtil.SetFlag(Data, 0x41, 0, value); }
|
||||
public bool RIB46_1 { get => FlagUtil.GetFlag(Data, 0x46, 1); set => FlagUtil.SetFlag(Data, 0x46, 1, value); }
|
||||
public bool RIB46_2 { get => FlagUtil.GetFlag(Data, 0x46, 2); set => FlagUtil.SetFlag(Data, 0x46, 2, value); }
|
||||
public bool RIB46_3 { get => FlagUtil.GetFlag(Data, 0x46, 3); set => FlagUtil.SetFlag(Data, 0x46, 3, value); }
|
||||
public bool RIB46_4 { get => FlagUtil.GetFlag(Data, 0x46, 4); set => FlagUtil.SetFlag(Data, 0x46, 4, value); }
|
||||
public bool RIB46_5 { get => FlagUtil.GetFlag(Data, 0x46, 5); set => FlagUtil.SetFlag(Data, 0x46, 5, value); }
|
||||
public bool RIB46_6 { get => FlagUtil.GetFlag(Data, 0x46, 6); set => FlagUtil.SetFlag(Data, 0x46, 6, value); }
|
||||
public bool RIB46_7 { get => FlagUtil.GetFlag(Data, 0x46, 7); set => FlagUtil.SetFlag(Data, 0x46, 7, value); }
|
||||
|
||||
public bool RIB47_0 { get => FlagUtil.GetFlag(Data, 0x47, 0); set => FlagUtil.SetFlag(Data, 0x47, 0, value); }
|
||||
public bool RIB47_1 { get => FlagUtil.GetFlag(Data, 0x47, 1); set => FlagUtil.SetFlag(Data, 0x47, 1, value); }
|
||||
public bool RIB47_2 { get => FlagUtil.GetFlag(Data, 0x47, 2); set => FlagUtil.SetFlag(Data, 0x47, 2, value); }
|
||||
public bool RIB47_3 { get => FlagUtil.GetFlag(Data, 0x47, 3); set => FlagUtil.SetFlag(Data, 0x47, 3, value); }
|
||||
public bool RIB47_4 { get => FlagUtil.GetFlag(Data, 0x47, 4); set => FlagUtil.SetFlag(Data, 0x47, 4, value); }
|
||||
public bool RIB47_5 { get => FlagUtil.GetFlag(Data, 0x47, 5); set => FlagUtil.SetFlag(Data, 0x47, 5, value); }
|
||||
public bool RIB47_6 { get => FlagUtil.GetFlag(Data, 0x47, 6); set => FlagUtil.SetFlag(Data, 0x47, 6, value); }
|
||||
public bool RIB47_7 { get => FlagUtil.GetFlag(Data, 0x47, 7); set => FlagUtil.SetFlag(Data, 0x47, 7, value); }
|
||||
|
||||
public bool HasMark()
|
||||
{
|
||||
var d = Data;
|
||||
if ((BitConverter.ToUInt16(d, 0x3A) & 0xFFE0) != 0)
|
||||
return true;
|
||||
if (BitConverter.ToUInt32(d, 0x40) != 0)
|
||||
return true;
|
||||
return (d[0x44] & 3) != 0;
|
||||
}
|
||||
|
||||
public uint Sociability { get => BitConverter.ToUInt32(Data, 0x48); set => BitConverter.GetBytes(value).CopyTo(Data, 0x48); }
|
||||
|
||||
// 0x4C-0x4F unused
|
||||
|
||||
public int HeightScalar { get => Data[0x50]; set => Data[0x50] = (byte)value; }
|
||||
public int WeightScalar { get => Data[0x51]; set => Data[0x51] = (byte)value; }
|
||||
|
||||
// 0x52-0x57 unused
|
||||
|
||||
#endregion
|
||||
#region Block B
|
||||
public override string Nickname
|
||||
{
|
||||
get => GetString(0x58, 24);
|
||||
set => SetString(value, 12).CopyTo(Data, 0x58);
|
||||
}
|
||||
|
||||
// 2 bytes for \0, automatically handled above
|
||||
|
||||
public override int Move1 { get => BitConverter.ToUInt16(Data, 0x72); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x72); }
|
||||
public override int Move2 { get => BitConverter.ToUInt16(Data, 0x74); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x74); }
|
||||
public override int Move3 { get => BitConverter.ToUInt16(Data, 0x76); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x76); }
|
||||
public override int Move4 { get => BitConverter.ToUInt16(Data, 0x78); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x78); }
|
||||
|
||||
public override int Move1_PP { get => Data[0x7A]; set => Data[0x7A] = (byte)value; }
|
||||
public override int Move2_PP { get => Data[0x7B]; set => Data[0x7B] = (byte)value; }
|
||||
public override int Move3_PP { get => Data[0x7C]; set => Data[0x7C] = (byte)value; }
|
||||
public override int Move4_PP { get => Data[0x7D]; set => Data[0x7D] = (byte)value; }
|
||||
public override int Move1_PPUps { get => Data[0x7E]; set => Data[0x7E] = (byte)value; }
|
||||
public override int Move2_PPUps { get => Data[0x7F]; set => Data[0x7F] = (byte)value; }
|
||||
public override int Move3_PPUps { get => Data[0x80]; set => Data[0x80] = (byte)value; }
|
||||
public override int Move4_PPUps { get => Data[0x81]; set => Data[0x81] = (byte)value; }
|
||||
|
||||
public override int RelearnMove1 { get => BitConverter.ToUInt16(Data, 0x82); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x82); }
|
||||
public override int RelearnMove2 { get => BitConverter.ToUInt16(Data, 0x84); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x84); }
|
||||
public override int RelearnMove3 { get => BitConverter.ToUInt16(Data, 0x86); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x86); }
|
||||
public override int RelearnMove4 { get => BitConverter.ToUInt16(Data, 0x88); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x88); }
|
||||
|
||||
public override int Stat_HPCurrent { get => BitConverter.ToUInt16(Data, 0x8A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x8A); }
|
||||
|
||||
private uint IV32 { get => BitConverter.ToUInt32(Data, 0x8C); set => BitConverter.GetBytes(value).CopyTo(Data, 0x8C); }
|
||||
public override int IV_HP { get => (int)(IV32 >> 00) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 00)) | ((value > 31 ? 31u : (uint)value) << 00); }
|
||||
public override int IV_ATK { get => (int)(IV32 >> 05) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 05)) | ((value > 31 ? 31u : (uint)value) << 05); }
|
||||
public override int IV_DEF { get => (int)(IV32 >> 10) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 10)) | ((value > 31 ? 31u : (uint)value) << 10); }
|
||||
public override int IV_SPE { get => (int)(IV32 >> 15) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 15)) | ((value > 31 ? 31u : (uint)value) << 15); }
|
||||
public override int IV_SPA { get => (int)(IV32 >> 20) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 20)) | ((value > 31 ? 31u : (uint)value) << 20); }
|
||||
public override int IV_SPD { get => (int)(IV32 >> 25) & 0x1F; set => IV32 = (IV32 & ~(0x1Fu << 25)) | ((value > 31 ? 31u : (uint)value) << 25); }
|
||||
public override bool IsEgg { get => ((IV32 >> 30) & 1) == 1; set => IV32 = (IV32 & ~0x40000000u) | (value ? 0x40000000u : 0u); }
|
||||
public override bool IsNicknamed { get => ((IV32 >> 31) & 1) == 1; set => IV32 = (IV32 & 0x7FFFFFFFu) | (value ? 0x80000000u : 0u); }
|
||||
|
||||
public byte DynamaxLevel { get => Data[0x90]; set => Data[0x90] = value; }
|
||||
|
||||
// 0x90-0x93 unused
|
||||
|
||||
public override int Status_Condition { get => BitConverter.ToInt32(Data, 0x94); set => BitConverter.GetBytes(value).CopyTo(Data, 0x94); }
|
||||
public int Unk98 { get => BitConverter.ToInt32(Data, 0x98); set => BitConverter.GetBytes(value).CopyTo(Data, 0x98); }
|
||||
|
||||
// 0x9C-0xA7 unused
|
||||
|
||||
#endregion
|
||||
#region Block C
|
||||
public override string HT_Name { get => GetString(0xA8, 24); set => SetString(value, 12).CopyTo(Data, 0xA8); }
|
||||
public override int HT_Gender { get => Data[0xC2]; set => Data[0xC2] = (byte)value; }
|
||||
public int HT_Language { get => Data[0xC3]; set => Data[0xC3] = (byte)value; }
|
||||
public override int CurrentHandler { get => Data[0xC4]; set => Data[0xC4] = (byte)value; }
|
||||
// 0xC5 unused (alignment)
|
||||
public int HT_TrainerID { get => BitConverter.ToUInt16(Data, 0xC6); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xC6); } // unused?
|
||||
public override int HT_Friendship { get => Data[0xC8]; set => Data[0xC8] = (byte)value; }
|
||||
public int HT_Intensity { get => Data[0xC9]; set => Data[0xC9] = (byte)value; }
|
||||
public int HT_Memory { get => Data[0xCA]; set => Data[0xCA] = (byte)value; }
|
||||
public int HT_Feeling { get => Data[0xCB]; set => Data[0xCB] = (byte)value; }
|
||||
public int HT_TextVar { get => BitConverter.ToUInt16(Data, 0xCC); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0xCC); }
|
||||
|
||||
// 0xCE-0xDB unused
|
||||
|
||||
public override byte Fullness { get => Data[0xDC]; set => Data[0xDC] = value; }
|
||||
public override byte Enjoyment { get => Data[0xDD]; set => Data[0xDD] = value; }
|
||||
public override int Version { get => Data[0xDE]; set => Data[0xDE] = (byte)value; }
|
||||
public int BattleVersion { get => Data[0xDF]; set => Data[0xDF] = (byte)value; }
|
||||
// public override int Region { get => Data[0xE0]; set => Data[0xE0] = (byte)value; }
|
||||
// public override int ConsoleRegion { get => Data[0xE1]; set => Data[0xE1] = (byte)value; }
|
||||
public override int Language { get => Data[0xE2]; set => Data[0xE2] = (byte)value; }
|
||||
public int UnkE3 { get => Data[0xE3]; set => Data[0xE3] = (byte)value; }
|
||||
public uint FormArgument { get => BitConverter.ToUInt32(Data, 0xE4); set => BitConverter.GetBytes(value).CopyTo(Data, 0xE4); }
|
||||
public byte FormArgumentRemain { get => (byte)FormArgument; set => FormArgument = (FormArgument & ~0xFFu) | value; }
|
||||
public byte FormArgumentElapsed { get => (byte)(FormArgument >> 8); set => FormArgument = (FormArgument & ~0xFF00u) | (uint)(value << 8); }
|
||||
public byte FormArgumentMaximum { get => (byte)(FormArgument >> 16); set => FormArgument = (FormArgument & ~0xFF0000u) | (uint)(value << 16); }
|
||||
public sbyte AffixedRibbon { get => (sbyte)Data[0xE8]; set => Data[0xE8] = (byte)value; } // selected ribbon
|
||||
// remainder unused
|
||||
|
||||
#endregion
|
||||
#region Block D
|
||||
public override string OT_Name { get => GetString(0xF8, 24); set => SetString(value, 12).CopyTo(Data, 0xF8); }
|
||||
public override int OT_Friendship { get => Data[0x112]; set => Data[0x112] = (byte)value; }
|
||||
public int OT_Intensity { get => Data[0x113]; set => Data[0x113] = (byte)value; }
|
||||
public int OT_Memory { get => Data[0x114]; set => Data[0x114] = (byte)value; }
|
||||
// 0x115 unused align
|
||||
public int OT_TextVar { get => BitConverter.ToUInt16(Data, 0x116); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x116); }
|
||||
public int OT_Feeling { get => Data[0x118]; set => Data[0x118] = (byte)value; }
|
||||
public override int Egg_Year { get => Data[0x119]; set => Data[0x119] = (byte)value; }
|
||||
public override int Egg_Month { get => Data[0x11A]; set => Data[0x11A] = (byte)value; }
|
||||
public override int Egg_Day { get => Data[0x11B]; set => Data[0x11B] = (byte)value; }
|
||||
public override int Met_Year { get => Data[0x11C]; set => Data[0x11C] = (byte)value; }
|
||||
public override int Met_Month { get => Data[0x11D]; set => Data[0x11D] = (byte)value; }
|
||||
public override int Met_Day { get => Data[0x11E]; set => Data[0x11E] = (byte)value; }
|
||||
// 0x11F unused align
|
||||
public override int Egg_Location { get => BitConverter.ToUInt16(Data, 0x120); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x120); }
|
||||
public override int Met_Location { get => BitConverter.ToUInt16(Data, 0x122); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x122); }
|
||||
public override int Ball { get => Data[0x124]; set => Data[0x124] = (byte)value; }
|
||||
public override int Met_Level { get => Data[0x125] & ~0x80; set => Data[0x125] = (byte)((Data[0x125] & 0x80) | value); }
|
||||
public override int OT_Gender { get => Data[0x125] >> 7; set => Data[0x125] = (byte)((Data[0x125] & ~0x80) | (value << 7)); }
|
||||
public int HyperTrainFlags { get => Data[0x126]; set => Data[0x126] = (byte)value; }
|
||||
public bool HT_HP { get => ((HyperTrainFlags >> 0) & 1) == 1; set => HyperTrainFlags = (HyperTrainFlags & ~(1 << 0)) | ((value ? 1 : 0) << 0); }
|
||||
public bool HT_ATK { get => ((HyperTrainFlags >> 1) & 1) == 1; set => HyperTrainFlags = (HyperTrainFlags & ~(1 << 1)) | ((value ? 1 : 0) << 1); }
|
||||
public bool HT_DEF { get => ((HyperTrainFlags >> 2) & 1) == 1; set => HyperTrainFlags = (HyperTrainFlags & ~(1 << 2)) | ((value ? 1 : 0) << 2); }
|
||||
public bool HT_SPA { get => ((HyperTrainFlags >> 3) & 1) == 1; set => HyperTrainFlags = (HyperTrainFlags & ~(1 << 3)) | ((value ? 1 : 0) << 3); }
|
||||
public bool HT_SPD { get => ((HyperTrainFlags >> 4) & 1) == 1; set => HyperTrainFlags = (HyperTrainFlags & ~(1 << 4)) | ((value ? 1 : 0) << 4); }
|
||||
public bool HT_SPE { get => ((HyperTrainFlags >> 5) & 1) == 1; set => HyperTrainFlags = (HyperTrainFlags & ~(1 << 5)) | ((value ? 1 : 0) << 5); }
|
||||
|
||||
public bool GetMoveRecordFlag(int index)
|
||||
{
|
||||
if ((uint) index > 112) // 14 bytes, 8 bits
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
int ofs = index >> 3;
|
||||
return FlagUtil.GetFlag(Data, 0x127 + ofs, index & 7);
|
||||
}
|
||||
|
||||
public void SetMoveRecordFlag(int index, bool value)
|
||||
{
|
||||
if ((uint)index > 112) // 14 bytes, 8 bits
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
int ofs = index >> 3;
|
||||
FlagUtil.SetFlag(Data, 0x127 + ofs, index & 7, value);
|
||||
}
|
||||
|
||||
public bool HasAnyMoveRecordFlag() => Array.FindIndex(Data, 0x127, 14, z => z != 0) >= 0;
|
||||
|
||||
// Why did you mis-align this field, GameFreak?
|
||||
public ulong Tracker
|
||||
{
|
||||
get => BitConverter.ToUInt64(Data, 0x135);
|
||||
set => BitConverter.GetBytes(value).CopyTo(Data, 0x135);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#region Battle Stats
|
||||
public override int Stat_Level { get => Data[0x148]; set => Data[0x148] = (byte)value; }
|
||||
// 0x149 unused alignment
|
||||
public override int Stat_HPMax { get => BitConverter.ToUInt16(Data, 0x14A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x14A); }
|
||||
public override int Stat_ATK { get => BitConverter.ToUInt16(Data, 0x14C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x14C); }
|
||||
public override int Stat_DEF { get => BitConverter.ToUInt16(Data, 0x14E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x14E); }
|
||||
public override int Stat_SPE { get => BitConverter.ToUInt16(Data, 0x150); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x150); }
|
||||
public override int Stat_SPA { get => BitConverter.ToUInt16(Data, 0x152); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x152); }
|
||||
public override int Stat_SPD { get => BitConverter.ToUInt16(Data, 0x154); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x154); }
|
||||
|
||||
public int DynamaxType { get => BitConverter.ToUInt16(Data, 0x156); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x156); }
|
||||
#endregion
|
||||
|
||||
public override int[] Markings
|
||||
{
|
||||
get
|
||||
{
|
||||
int[] marks = new int[8];
|
||||
int val = MarkValue;
|
||||
for (int i = 0; i < marks.Length; i++)
|
||||
marks[i] = ((val >> (i * 2)) & 3) % 3;
|
||||
return marks;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value.Length > 8)
|
||||
return;
|
||||
int v = 0;
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
v |= (value[i] % 3) << (i * 2);
|
||||
MarkValue = v;
|
||||
}
|
||||
}
|
||||
|
||||
public void FixMemories()
|
||||
{
|
||||
|
@ -583,18 +103,5 @@ namespace PKHeX.Core
|
|||
public override int MaxItemID => Legal.MaxItemID_8;
|
||||
public override int MaxBallID => Legal.MaxBallID_8;
|
||||
public override int MaxGameID => Legal.MaxGameID_8;
|
||||
|
||||
public bool GetRibbon(int index) => FlagUtil.GetFlag(Data, GetRibbonByte(index), index & 7);
|
||||
public void SetRibbon(int index, bool value = true) => FlagUtil.SetFlag(Data, GetRibbonByte(index), index & 7, value);
|
||||
|
||||
public int GetRibbonByte(int index)
|
||||
{
|
||||
if ((uint)index >= 128)
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
if (index < 64)
|
||||
return 0x34 + (index >> 3);
|
||||
index -= 64;
|
||||
return 0x40 + (index >> 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -289,12 +289,13 @@ namespace PKHeX.Core
|
|||
public bool VC2 => Version is >= (int)GD and <= (int)C;
|
||||
public bool LGPE => Version is (int)GP or (int)GE;
|
||||
public bool SWSH => Version is (int)SW or (int)SH;
|
||||
public bool BDSP => Version is (int)BD or (int)SP;
|
||||
|
||||
public bool GO_LGPE => GO && Met_Location == Locations.GO7;
|
||||
public bool GO_HOME => GO && Met_Location == Locations.GO8;
|
||||
public bool VC => VC1 || VC2;
|
||||
public bool GG => LGPE || GO_LGPE;
|
||||
public bool Gen8 => Version is >= 44 and <= 45 || GO_HOME;
|
||||
public bool Gen8 => Version is >= 44 and <= 49 || GO_HOME;
|
||||
public bool Gen7 => Version is >= 30 and <= 33 || GG;
|
||||
public bool Gen6 => Version is >= 24 and <= 29;
|
||||
public bool Gen5 => Version is >= 20 and <= 23;
|
||||
|
@ -486,10 +487,10 @@ namespace PKHeX.Core
|
|||
}
|
||||
|
||||
// Misc Egg Facts
|
||||
public bool WasEgg => IsEgg || Egg_Location != 0;
|
||||
public bool WasEgg => IsEgg || !Locations.IsNoneLocation((GameVersion)Version, Egg_Location);
|
||||
public bool WasTradedEgg => Egg_Location == GetTradedEggLocation();
|
||||
public bool IsTradedEgg => Met_Location == GetTradedEggLocation();
|
||||
private int GetTradedEggLocation() => Locations.TradedEggLocation(Generation);
|
||||
private int GetTradedEggLocation() => Locations.TradedEggLocation(Generation, (GameVersion)Version);
|
||||
|
||||
public virtual bool IsUntraded => false;
|
||||
public bool IsNative => Generation == Format;
|
||||
|
|
|
@ -13,6 +13,8 @@ namespace PKHeX.Core
|
|||
{
|
||||
if (pkm.IsEgg)
|
||||
return false;
|
||||
if (pkm.BDSP)
|
||||
return false;
|
||||
return CanHaveDynamaxLevel(pkm.Species);
|
||||
}
|
||||
|
||||
|
|
10
PKHeX.Core/PKM/Shared/IFixedOTFriendship.cs
Normal file
10
PKHeX.Core/PKM/Shared/IFixedOTFriendship.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Exposes a friendship value with the original trainer.
|
||||
/// </summary>
|
||||
public interface IFixedOTFriendship
|
||||
{
|
||||
int OT_Friendship { get; }
|
||||
}
|
||||
}
|
|
@ -117,11 +117,19 @@ namespace PKHeX.Core
|
|||
4 => BitConverter.ToUInt16(data, 0x04) == 0 ? new PK4(data) : new BK4(data),
|
||||
5 => new PK5(data),
|
||||
6 => CheckPKMFormat7(new PK6(data), prefer),
|
||||
8 => new PK8(data),
|
||||
8 => CheckPKMFormat8(data),
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
private static PKM CheckPKMFormat8(byte[] data)
|
||||
{
|
||||
var ver = data[0xDE];
|
||||
if (GameVersion.BDSP.Contains(ver))
|
||||
return new PB8(data);
|
||||
return new PK8(data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the input PK6 file is really a PK7, if so, updates the object.
|
||||
/// </summary>
|
||||
|
@ -432,6 +440,7 @@ namespace PKHeX.Core
|
|||
{
|
||||
1 when ver == GameVersion.BU => new PK1(true),
|
||||
7 when GameVersion.Gen7b.Contains(ver) => new PB7(),
|
||||
8 when GameVersion.BDSP.Contains(ver) => new PB8(),
|
||||
_ => GetBlank(gen),
|
||||
};
|
||||
|
||||
|
|
|
@ -199,6 +199,7 @@ namespace PKHeX.Core
|
|||
};
|
||||
|
||||
internal const string ExtensionPB7 = "pb7";
|
||||
internal const string ExtensionPB8 = "pb8";
|
||||
|
||||
/// <summary>
|
||||
/// Gets an array of valid <see cref="PKM"/> file extensions.
|
||||
|
@ -221,6 +222,8 @@ namespace PKHeX.Core
|
|||
result.Add("bk4"); // battle revolution
|
||||
if (maxGeneration >= 7)
|
||||
result.Add(ExtensionPB7); // let's go
|
||||
if (maxGeneration >= 8)
|
||||
result.Add(ExtensionPB8); // Brilliant Diamond & Shining Pearl
|
||||
|
||||
return result.ToArray();
|
||||
}
|
||||
|
|
118
PKHeX.Core/PersonalInfo/PersonalInfoBDSP.cs
Normal file
118
PKHeX.Core/PersonalInfo/PersonalInfoBDSP.cs
Normal file
|
@ -0,0 +1,118 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PKHeX.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="PersonalInfo"/> class with values from the <see cref="GameVersion.BDSP"/> games.
|
||||
/// </summary>
|
||||
public sealed class PersonalInfoBDSP : PersonalInfo
|
||||
{
|
||||
public const int SIZE = 0x44;
|
||||
private const int CountTM = 100;
|
||||
|
||||
public override int HP { get => Data[0x00]; set => Data[0x00] = (byte)value; }
|
||||
public override int ATK { get => Data[0x01]; set => Data[0x01] = (byte)value; }
|
||||
public override int DEF { get => Data[0x02]; set => Data[0x02] = (byte)value; }
|
||||
public override int SPE { get => Data[0x03]; set => Data[0x03] = (byte)value; }
|
||||
public override int SPA { get => Data[0x04]; set => Data[0x04] = (byte)value; }
|
||||
public override int SPD { get => Data[0x05]; set => Data[0x05] = (byte)value; }
|
||||
public override int Type1 { get => Data[0x06]; set => Data[0x06] = (byte)value; }
|
||||
public override int Type2 { get => Data[0x07]; set => Data[0x07] = (byte)value; }
|
||||
public override int CatchRate { get => Data[0x08]; set => Data[0x08] = (byte)value; }
|
||||
public override int EvoStage { get => Data[0x09]; set => Data[0x09] = (byte)value; }
|
||||
private int EVYield { get => BitConverter.ToUInt16(Data, 0x0A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x0A); }
|
||||
public override int EV_HP { get => EVYield >> 0 & 0x3; set => EVYield = (EVYield & ~(0x3 << 0)) | (value & 0x3) << 0; }
|
||||
public override int EV_ATK { get => EVYield >> 2 & 0x3; set => EVYield = (EVYield & ~(0x3 << 2)) | (value & 0x3) << 2; }
|
||||
public override int EV_DEF { get => EVYield >> 4 & 0x3; set => EVYield = (EVYield & ~(0x3 << 4)) | (value & 0x3) << 4; }
|
||||
public override int EV_SPE { get => EVYield >> 6 & 0x3; set => EVYield = (EVYield & ~(0x3 << 6)) | (value & 0x3) << 6; }
|
||||
public override int EV_SPA { get => EVYield >> 8 & 0x3; set => EVYield = (EVYield & ~(0x3 << 8)) | (value & 0x3) << 8; }
|
||||
public override int EV_SPD { get => EVYield >> 10 & 0x3; set => EVYield = (EVYield & ~(0x3 << 10)) | (value & 0x3) << 10; }
|
||||
public int Item1 { get => BitConverter.ToInt16(Data, 0x0C); set => BitConverter.GetBytes((short)value).CopyTo(Data, 0x0C); }
|
||||
public int Item2 { get => BitConverter.ToInt16(Data, 0x0E); set => BitConverter.GetBytes((short)value).CopyTo(Data, 0x0E); }
|
||||
public int Item3 { get => BitConverter.ToInt16(Data, 0x10); set => BitConverter.GetBytes((short)value).CopyTo(Data, 0x10); }
|
||||
public override int Gender { get => Data[0x12]; set => Data[0x12] = (byte)value; }
|
||||
public override int HatchCycles { get => Data[0x13]; set => Data[0x13] = (byte)value; }
|
||||
public override int BaseFriendship { get => Data[0x14]; set => Data[0x14] = (byte)value; }
|
||||
public override int EXPGrowth { get => Data[0x15]; set => Data[0x15] = (byte)value; }
|
||||
public override int EggGroup1 { get => Data[0x16]; set => Data[0x16] = (byte)value; }
|
||||
public override int EggGroup2 { get => Data[0x17]; set => Data[0x17] = (byte)value; }
|
||||
public int Ability1 { get => BitConverter.ToUInt16(Data, 0x18); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x18); }
|
||||
public int Ability2 { get => BitConverter.ToUInt16(Data, 0x1A); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x1A); }
|
||||
public int AbilityH { get => BitConverter.ToUInt16(Data, 0x1C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x1C); }
|
||||
public override int EscapeRate { get => 0; set { } } // moved?
|
||||
protected internal override int FormStatsIndex { get => BitConverter.ToUInt16(Data, 0x1E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x1E); }
|
||||
public override int FormSprite { get => 0; set { } } // No longer defined in personal
|
||||
public override int FormCount { get => Data[0x20]; set => Data[0x20] = (byte)value; }
|
||||
public override int Color { get => Data[0x21] & 0x3F; set => Data[0x21] = (byte)((Data[0x21] & 0xC0) | (value & 0x3F)); }
|
||||
public bool IsPresentInGame { get => ((Data[0x21] >> 6) & 1) == 1; set => Data[0x21] = (byte)((Data[0x21] & ~0x40) | (value ? 0x40 : 0)); }
|
||||
public bool SpriteForm { get => false; set { } } // Unspecified in table
|
||||
public override int BaseEXP { get => BitConverter.ToUInt16(Data, 0x22); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x22); }
|
||||
public override int Height { get => BitConverter.ToUInt16(Data, 0x24); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x24); }
|
||||
public override int Weight { get => BitConverter.ToUInt16(Data, 0x26); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x26); }
|
||||
|
||||
//public uint TM1 { get => BitConverter.ToUInt32(Data, 0x28); set => BitConverter.GetBytes(value).CopyTo(Data, 0x28); }
|
||||
//public uint TM2 { get => BitConverter.ToUInt32(Data, 0x2C); set => BitConverter.GetBytes(value).CopyTo(Data, 0x2C); }
|
||||
//public uint TM3 { get => BitConverter.ToUInt32(Data, 0x30); set => BitConverter.GetBytes(value).CopyTo(Data, 0x30); }
|
||||
//public uint TM4 { get => BitConverter.ToUInt32(Data, 0x34); set => BitConverter.GetBytes(value).CopyTo(Data, 0x34); }
|
||||
//public uint Tutor { get => BitConverter.ToUInt32(Data, 0x38); set => BitConverter.GetBytes(value).CopyTo(Data, 0x38); }
|
||||
|
||||
public int Species { get => BitConverter.ToUInt16(Data, 0x3C); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x3C); }
|
||||
public int HatchSpecies { get => BitConverter.ToUInt16(Data, 0x3E); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x3E); }
|
||||
public int HatchFormIndex { get => BitConverter.ToUInt16(Data, 0x40); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x40); }
|
||||
public int PokeDexIndex { get => BitConverter.ToUInt16(Data, 0x42); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x42); }
|
||||
|
||||
public PersonalInfoBDSP(byte[] data) : base(data)
|
||||
{
|
||||
TMHM = new bool[CountTM];
|
||||
for (var i = 0; i < CountTM; i++)
|
||||
TMHM[i] = FlagUtil.GetFlag(Data, 0x28 + (i >> 3), i);
|
||||
|
||||
// 0x38-0x3B type tutors, but only 8 bits are valid flags.
|
||||
var typeTutors = new bool[8];
|
||||
for (int i = 0; i < typeTutors.Length; i++)
|
||||
typeTutors[i] = FlagUtil.GetFlag(Data, 0x38, i);
|
||||
TypeTutors = typeTutors;
|
||||
}
|
||||
|
||||
public override byte[] Write()
|
||||
{
|
||||
for (var i = 0; i < CountTM; i++)
|
||||
FlagUtil.SetFlag(Data, 0x28 + (i >> 3), i, TMHM[i]);
|
||||
for (int i = 0; i < TypeTutors.Length; i++)
|
||||
FlagUtil.SetFlag(Data, 0x38, i, TypeTutors[i]);
|
||||
return Data;
|
||||
}
|
||||
|
||||
public override IReadOnlyList<int> Items
|
||||
{
|
||||
get => new[] { Item1, Item2, Item3 };
|
||||
set
|
||||
{
|
||||
if (value.Count != 3) return;
|
||||
Item1 = value[0];
|
||||
Item2 = value[1];
|
||||
Item3 = value[2];
|
||||
}
|
||||
}
|
||||
|
||||
public override IReadOnlyList<int> Abilities
|
||||
{
|
||||
get => new[] { Ability1, Ability2, AbilityH };
|
||||
set
|
||||
{
|
||||
if (value.Count != 3) return;
|
||||
Ability1 = value[0];
|
||||
Ability2 = value[1];
|
||||
AbilityH = value[2];
|
||||
}
|
||||
}
|
||||
|
||||
public override int GetAbilityIndex(int abilityID) => abilityID == Ability1 ? 0 : abilityID == Ability2 ? 1 : abilityID == AbilityH ? 2 : -1;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the entry shows up in any of the built-in Pokédex.
|
||||
/// </summary>
|
||||
public bool IsInDex => PokeDexIndex != 0;
|
||||
}
|
||||
}
|
|
@ -12,6 +12,11 @@ namespace PKHeX.Core
|
|||
/// </remarks>
|
||||
public class PersonalTable
|
||||
{
|
||||
/// <summary>
|
||||
/// Personal Table used in <see cref="GameVersion.BDSP"/>.
|
||||
/// </summary>
|
||||
public static readonly PersonalTable BDSP = GetTable("bdsp", GameVersion.BDSP);
|
||||
|
||||
/// <summary>
|
||||
/// Personal Table used in <see cref="GameVersion.SWSH"/>.
|
||||
/// </summary>
|
||||
|
@ -124,7 +129,8 @@ namespace PKHeX.Core
|
|||
GameVersion.ORAS => z => new PersonalInfoORAS(z),
|
||||
GameVersion.SM or GameVersion.USUM => z => new PersonalInfoSM(z),
|
||||
GameVersion.GG => z => new PersonalInfoGG(z),
|
||||
_ => z => new PersonalInfoSWSH(z),
|
||||
GameVersion.SWSH => z => new PersonalInfoSWSH(z),
|
||||
_ => z => new PersonalInfoBDSP(z),
|
||||
};
|
||||
|
||||
private static int GetEntrySize(GameVersion format) => format switch
|
||||
|
@ -139,6 +145,7 @@ namespace PKHeX.Core
|
|||
GameVersion.ORAS => PersonalInfoORAS.SIZE,
|
||||
GameVersion.SM or GameVersion.USUM or GameVersion.GG => PersonalInfoSM.SIZE,
|
||||
GameVersion.SWSH => PersonalInfoSWSH.SIZE,
|
||||
GameVersion.BDSP => PersonalInfoBDSP.SIZE,
|
||||
_ => -1,
|
||||
};
|
||||
|
||||
|
|
BIN
PKHeX.Core/Resources/byte/eggmove/eggmove_bdsp.pkl
Normal file
BIN
PKHeX.Core/Resources/byte/eggmove/eggmove_bdsp.pkl
Normal file
Binary file not shown.
BIN
PKHeX.Core/Resources/byte/evolve/evos_bs.pkl
Normal file
BIN
PKHeX.Core/Resources/byte/evolve/evos_bs.pkl
Normal file
Binary file not shown.
BIN
PKHeX.Core/Resources/byte/levelup/lvlmove_bdsp.pkl
Normal file
BIN
PKHeX.Core/Resources/byte/levelup/lvlmove_bdsp.pkl
Normal file
Binary file not shown.
BIN
PKHeX.Core/Resources/byte/personal/personal_bdsp
Normal file
BIN
PKHeX.Core/Resources/byte/personal/personal_bdsp
Normal file
Binary file not shown.
8
PKHeX.Core/Resources/legality/gen8/text_tradebdsp_de.txt
Normal file
8
PKHeX.Core/Resources/legality/gen8/text_tradebdsp_de.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
Salla
|
||||
Plaupa
|
||||
Pollo
|
||||
Pador
|
||||
Hilary
|
||||
Norbert
|
||||
Mara
|
||||
The Master
|
8
PKHeX.Core/Resources/legality/gen8/text_tradebdsp_en.txt
Normal file
8
PKHeX.Core/Resources/legality/gen8/text_tradebdsp_en.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
Kazza
|
||||
Charap
|
||||
Gaspar
|
||||
Foppa
|
||||
Hilary
|
||||
Norton
|
||||
Mindy
|
||||
Meister
|
8
PKHeX.Core/Resources/legality/gen8/text_tradebdsp_es.txt
Normal file
8
PKHeX.Core/Resources/legality/gen8/text_tradebdsp_es.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
Kazza
|
||||
Charap
|
||||
Gaspar
|
||||
Foppa
|
||||
Amanda
|
||||
Alfio
|
||||
Regla
|
||||
Meister
|
8
PKHeX.Core/Resources/legality/gen8/text_tradebdsp_fr.txt
Normal file
8
PKHeX.Core/Resources/legality/gen8/text_tradebdsp_fr.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
Kazou
|
||||
Pijouk
|
||||
Trumi
|
||||
Bloupi
|
||||
Paula
|
||||
Pierre
|
||||
Marlène
|
||||
Meister
|
8
PKHeX.Core/Resources/legality/gen8/text_tradebdsp_it.txt
Normal file
8
PKHeX.Core/Resources/legality/gen8/text_tradebdsp_it.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
Keikei
|
||||
Charap
|
||||
Gaspar
|
||||
Mossy
|
||||
Hilary
|
||||
Norton
|
||||
Mindy
|
||||
The Master
|
8
PKHeX.Core/Resources/legality/gen8/text_tradebdsp_ja.txt
Normal file
8
PKHeX.Core/Resources/legality/gen8/text_tradebdsp_ja.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
ケーケー
|
||||
ペッチャラ
|
||||
ドロりん
|
||||
ポッちゃん
|
||||
ハッシー
|
||||
ノブリン
|
||||
ミナッチ
|
||||
マイスター
|
8
PKHeX.Core/Resources/legality/gen8/text_tradebdsp_ko.txt
Normal file
8
PKHeX.Core/Resources/legality/gen8/text_tradebdsp_ko.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
케이케이
|
||||
조자리
|
||||
고옹이
|
||||
Pador
|
||||
에이
|
||||
신달
|
||||
미나
|
||||
Master
|
8
PKHeX.Core/Resources/legality/gen8/text_tradebdsp_zh.txt
Normal file
8
PKHeX.Core/Resources/legality/gen8/text_tradebdsp_zh.txt
Normal file
|
@ -0,0 +1,8 @@
|
|||
凯凯
|
||||
聒查拉
|
||||
小无形
|
||||
Pador
|
||||
赫西
|
||||
诺布林
|
||||
米娜琦
|
||||
Master
|
|
@ -0,0 +1,8 @@
|
|||
凱凱
|
||||
小聒聒
|
||||
無形仔
|
||||
Pador
|
||||
荷希
|
||||
諾布林
|
||||
美琦
|
||||
Master
|
BIN
PKHeX.Core/Resources/legality/mgdb/wb8.pkl
Normal file
BIN
PKHeX.Core/Resources/legality/mgdb/wb8.pkl
Normal file
Binary file not shown.
Binary file not shown.
BIN
PKHeX.Core/Resources/legality/wild/Gen8/encounter_bd.pkl
Normal file
BIN
PKHeX.Core/Resources/legality/wild/Gen8/encounter_bd.pkl
Normal file
Binary file not shown.
BIN
PKHeX.Core/Resources/legality/wild/Gen8/encounter_sp.pkl
Normal file
BIN
PKHeX.Core/Resources/legality/wild/Gen8/encounter_sp.pkl
Normal file
Binary file not shown.
BIN
PKHeX.Core/Resources/legality/wild/Gen8/underground_bd.pkl
Normal file
BIN
PKHeX.Core/Resources/legality/wild/Gen8/underground_bd.pkl
Normal file
Binary file not shown.
BIN
PKHeX.Core/Resources/legality/wild/Gen8/underground_sp.pkl
Normal file
BIN
PKHeX.Core/Resources/legality/wild/Gen8/underground_sp.pkl
Normal file
Binary file not shown.
|
@ -1605,4 +1605,219 @@ Phantomkarotte
|
|||
Dyna-Erz
|
||||
Karottensamen
|
||||
Fähigk.-Pflaster
|
||||
Zügel des Bundes
|
||||
Zügel des Bundes
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Enigmafragment S
|
||||
Enigmafragment L
|
||||
Einwegbohrer
|
||||
Kanto-Platte
|
||||
Johto-Platte
|
||||
Gefühlsplatte
|
||||
Regenbogenplatte
|
||||
Sturmplatte
|
||||
Meeresplatte
|
||||
Kontinentplatte
|
||||
Himmelsplatte
|
||||
Genplatte
|
||||
Weisungsplatte
|
||||
Zerrplatte
|
||||
DS-Player
|
|
@ -1605,4 +1605,219 @@ Shaderoot Carrot
|
|||
Dynite Ore
|
||||
Carrot Seeds
|
||||
Ability Patch
|
||||
Reins of Unity
|
||||
Reins of Unity
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Mysterious Shard S
|
||||
Mysterious Shard L
|
||||
Digger Drill
|
||||
Kanto Slate
|
||||
Johto Slate
|
||||
Soul Slate
|
||||
Rainbow Slate
|
||||
Squall Slate
|
||||
Oceanic Slate
|
||||
Tectonic Slate
|
||||
Stratospheric Slate
|
||||
Genome Slate
|
||||
Discovery Slate
|
||||
Distortion Slate
|
||||
DS Sounds
|
|
@ -1605,4 +1605,219 @@ Zanahoria Oscura
|
|||
Maxinium
|
||||
Sem. Zanahoria
|
||||
Parche Habilidad
|
||||
Riendas Unión
|
||||
Riendas Unión
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Esquirla Extraña S
|
||||
Esquirla Extraña L
|
||||
Taladro
|
||||
Losa Kanto
|
||||
Losa Johto
|
||||
Losa Empatía
|
||||
Losa Arcoíris
|
||||
Losa Tormenta
|
||||
Losa Mar
|
||||
Losa Tierra
|
||||
Losa Cielo
|
||||
Losa Genética
|
||||
Losa Inicio
|
||||
Losa Distorsión
|
||||
Reproductor DS
|
|
@ -1605,4 +1605,219 @@ Carotte Sombre
|
|||
Dynamaxium
|
||||
Graines Carotte
|
||||
Patch Talent
|
||||
Rênes de l’Unité
|
||||
Rênes de l’Unité
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Éclat Étrange S
|
||||
Éclat Étrange L
|
||||
Foreuse
|
||||
Tablette Kanto
|
||||
Tablette Johto
|
||||
Tablette Cœur
|
||||
Tablette Arc-en-ciel
|
||||
Tablette Tempête
|
||||
Tablette Océans
|
||||
Tablette Continents
|
||||
Tablette Cieux
|
||||
Tablette Génétique
|
||||
Tablette Guides
|
||||
Tablette Distorsion
|
||||
Lecteur DS
|
|
@ -1605,4 +1605,219 @@ Carota oscura
|
|||
Rocciamax
|
||||
Semi di carota
|
||||
Cerotto abilità
|
||||
Briglie legame
|
||||
Briglie legame
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Frammento insolito S
|
||||
Frammento insolito L
|
||||
Trivella
|
||||
Piastra di Kanto
|
||||
Piastra di Johto
|
||||
Piastra del cuore
|
||||
Piastra arcobaleno
|
||||
Piastra dei venti
|
||||
Piastra dei mari
|
||||
Piastra delle terre
|
||||
Piastra dei cieli
|
||||
Piastra del gene
|
||||
Piastra degli esordi
|
||||
Piastra distorta
|
||||
Lettore DS
|
|
@ -1605,4 +1605,219 @@
|
|||
マックスこうせき
|
||||
にんじんのタネ
|
||||
とくせいパッチ
|
||||
キズナのタヅナ
|
||||
キズナのタヅナ
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
なぞのかけらS
|
||||
なぞのかけらL
|
||||
あなほりドリル
|
||||
カントーのせきばん
|
||||
ジョウトのせきばん
|
||||
こころのせきばん
|
||||
にじのせきばん
|
||||
あらしのせきばん
|
||||
たいかいのせきばん
|
||||
たいりくのせきばん
|
||||
てんくうのせきばん
|
||||
いでんしのせきばん
|
||||
みちびきのせきばん
|
||||
やぶれたせきばん
|
||||
DSプレイヤー
|
|
@ -1605,4 +1605,219 @@ PP회복캡슐토이
|
|||
맥스광석
|
||||
당근씨
|
||||
특성패치
|
||||
유대의고삐
|
||||
유대의고삐
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
수수께끼의조각S
|
||||
수수께끼의조각L
|
||||
구멍파기드릴
|
||||
관동의석판
|
||||
성도의석판
|
||||
마음의석판
|
||||
무지개의석판
|
||||
폭풍의석판
|
||||
대해의석판
|
||||
대륙의석판
|
||||
천공의석판
|
||||
유전자의석판
|
||||
인도의석판
|
||||
깨어진석판
|
||||
DS플레이어
|
|
@ -1605,4 +1605,219 @@
|
|||
极矿石
|
||||
萝卜种子
|
||||
特性膏药
|
||||
牵绊缰绳
|
||||
牵绊缰绳
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
谜之碎片S
|
||||
谜之碎片L
|
||||
挖洞钻
|
||||
关都石板
|
||||
城都石板
|
||||
心之石板
|
||||
彩虹石板
|
||||
暴风石板
|
||||
大海石板
|
||||
大陆石板
|
||||
天空石板
|
||||
基因石板
|
||||
引导石板
|
||||
毁坏石板
|
||||
DS播放器
|
658
PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_de.txt
Normal file
658
PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_de.txt
Normal file
|
@ -0,0 +1,658 @@
|
|||
Jubelstadt
|
||||
Jubelstadt
|
||||
Jubelstadt
|
||||
Jubelstadt
|
||||
Jubelstadt
|
||||
Jubelstadt
|
||||
Jubelstadt
|
||||
Jubelstadt
|
||||
Jubelstadt
|
||||
Jubelstadt
|
||||
Jubelstadt
|
||||
Jubelstadt
|
||||
Jubelstadt
|
||||
Jubelstadt
|
||||
Jubelstadt
|
||||
Jubelstadt
|
||||
Jubelstadt
|
||||
Jubelstadt
|
||||
Jubelstadt
|
||||
Jubelstadt
|
||||
Jubelstadt
|
||||
Jubelstadt
|
||||
Jubelstadt
|
||||
Jubelstadt
|
||||
Fleetburg
|
||||
Fleetburg
|
||||
Fleetburg-Arena
|
||||
Fleetburg
|
||||
Fleetburg
|
||||
Fleetburg
|
||||
Fleetburg
|
||||
Fleetburg
|
||||
Fleetburg
|
||||
Fleetburg
|
||||
Fleetburg
|
||||
Fleetburg
|
||||
Fleetburg
|
||||
Fleetburg
|
||||
Erzelingen
|
||||
Erzelingen
|
||||
Erzelingen-Arena
|
||||
Erzelingen
|
||||
Erzelingen
|
||||
Erzelingen
|
||||
Erzelingen
|
||||
Erzelingen
|
||||
Erzelingen
|
||||
Erzelingen
|
||||
Erzelingen
|
||||
Erzelingen
|
||||
Erzelingen
|
||||
Erzelingen
|
||||
Erzelingen
|
||||
Erzelingen
|
||||
Ewigenau
|
||||
Ewigenau
|
||||
Ewigenau-Arena
|
||||
Ewigenau-Arena
|
||||
Ewigenau
|
||||
Ewigenau
|
||||
Ewigenau
|
||||
Ewigenau
|
||||
Ewigenau
|
||||
Ewigenau
|
||||
Ewigenau
|
||||
Ewigenau
|
||||
Ewigenau
|
||||
Ewigenau
|
||||
Ewigenau
|
||||
Ewigenau
|
||||
Ewigenau
|
||||
Ewigenau
|
||||
Ewigenau
|
||||
Ewigenau
|
||||
Herzhofen
|
||||
Herzhofen
|
||||
Herzhofen-Arena
|
||||
Herzhofen-Arena
|
||||
Herzhofen-Arena
|
||||
Herzhofen-Arena
|
||||
Herzhofen-Arena
|
||||
Herzhofen-Arena
|
||||
Herzhofen-Arena
|
||||
Herzhofen-Arena
|
||||
Herzhofen-Arena
|
||||
Herzhofen-Arena
|
||||
Herzhofen-Arena
|
||||
Herzhofen-Arena
|
||||
Herzhofen-Arena
|
||||
Herzhofen
|
||||
Herzhofen
|
||||
Herzhofen
|
||||
Herzhofen
|
||||
Herzhofen
|
||||
Herzhofen
|
||||
Herzhofen
|
||||
Herzhofen
|
||||
Herzhofen
|
||||
Herzhofen
|
||||
Herzhofen
|
||||
Herzhofen
|
||||
Herzhofen
|
||||
Herzhofen
|
||||
Herzhofen
|
||||
Herzhofen
|
||||
Herzhofen
|
||||
Herzhofen
|
||||
Herzhofen
|
||||
Herzhofen
|
||||
Herzhofen
|
||||
Weideburg
|
||||
Weideburg
|
||||
Weideburg-Arena
|
||||
Weideburg
|
||||
Weideburg
|
||||
Weideburg
|
||||
Weideburg
|
||||
Weideburg
|
||||
Weideburg
|
||||
Weideburg
|
||||
Weideburg
|
||||
Weideburg
|
||||
Weideburg
|
||||
Schleiede
|
||||
Schleiede-Arena
|
||||
Schleiede
|
||||
Schleiede
|
||||
Schleiede
|
||||
Schleiede
|
||||
Schleiede
|
||||
Schleiede
|
||||
Schleiede
|
||||
Schleiede
|
||||
Schleiede
|
||||
Schleiede
|
||||
Schleiede
|
||||
Schleiede
|
||||
Schleiede
|
||||
Schleiede
|
||||
Schleiede
|
||||
Schleiede
|
||||
Schleiede
|
||||
Sonnewik
|
||||
Sonnewik
|
||||
Sonnewik-Arena
|
||||
Sonnewik-Arena
|
||||
Sonnewik-Arena
|
||||
Sonnewik
|
||||
Sonnewik
|
||||
Sonnewik
|
||||
Sonnewik
|
||||
Sonnewik
|
||||
Sonnewik
|
||||
Sonnewik
|
||||
Sonnewik
|
||||
Sonnewik
|
||||
Sonnewik
|
||||
Sonnewik
|
||||
Sonnewik
|
||||
Blizzach
|
||||
Blizzach
|
||||
Blizzach-Arena
|
||||
Blizzach
|
||||
Blizzach
|
||||
Blizzach
|
||||
Blizzach
|
||||
Blizzach
|
||||
Pokémon-Liga
|
||||
Pokémon-Liga
|
||||
Pokémon-Liga
|
||||
Pokémon-Liga
|
||||
Pokémon-Liga
|
||||
Pokémon-Liga
|
||||
Pokémon-Liga
|
||||
Pokémon-Liga
|
||||
Pokémon-Liga
|
||||
Pokémon-Liga
|
||||
Pokémon-Liga
|
||||
Pokémon-Liga
|
||||
Pokémon-Liga
|
||||
Pokémon-Liga
|
||||
Pokémon-Liga
|
||||
Pokémon-Liga
|
||||
Pokémon-Liga
|
||||
Pokémon-Liga
|
||||
Pokémon-Liga
|
||||
Kampfareal
|
||||
Kampfareal
|
||||
Kampfareal
|
||||
Kampfareal
|
||||
Kampfareal
|
||||
Kampfareal
|
||||
Kampfareal
|
||||
Kampfareal
|
||||
Kampfareal
|
||||
Erzelingen-Mine
|
||||
Erzelingen-Mine
|
||||
Windkraftwerk
|
||||
Windkraftwerk
|
||||
Ewigwald
|
||||
Ewigwald
|
||||
Feurio-Hütte
|
||||
Feurio-Hütte
|
||||
Kraterberg
|
||||
Kraterberg
|
||||
Kraterberg
|
||||
Kraterberg
|
||||
Kraterberg
|
||||
Kraterberg
|
||||
Kraterberg
|
||||
Kraterberg
|
||||
Kraterberg
|
||||
Kraterberg
|
||||
Kraterberg
|
||||
Kraterberg
|
||||
Kraterberg
|
||||
Speersäule
|
||||
Speersäule
|
||||
Halle des Beginns
|
||||
Großmoor
|
||||
Großmoor
|
||||
Großmoor
|
||||
Großmoor
|
||||
Großmoor
|
||||
Großmoor
|
||||
Trostu-Ruinen
|
||||
Trostu-Ruinen
|
||||
Trostu-Ruinen
|
||||
Trostu-Ruinen
|
||||
Trostu-Ruinen
|
||||
Trostu-Ruinen
|
||||
Trostu-Ruinen
|
||||
Trostu-Ruinen
|
||||
Trostu-Ruinen
|
||||
Trostu-Ruinen
|
||||
Trostu-Ruinen
|
||||
Trostu-Ruinen
|
||||
Trostu-Ruinen
|
||||
Trostu-Ruinen
|
||||
Trostu-Ruinen
|
||||
Trostu-Ruinen
|
||||
Trostu-Ruinen
|
||||
Trostu-Ruinen
|
||||
Trostu-Ruinen
|
||||
Siegesstraße
|
||||
Siegesstraße
|
||||
Siegesstraße
|
||||
Siegesstraße
|
||||
Siegesstraße
|
||||
Siegesstraße
|
||||
Hamanasu-Park
|
||||
Platz der Treue
|
||||
Verwüsteter Pfad
|
||||
Auen von Flori
|
||||
Auen von Flori
|
||||
Erzelingen-Tor
|
||||
Erzelingen-Tor
|
||||
Vollmondinsel
|
||||
Vollmondinsel
|
||||
Kahlberg
|
||||
Kahlberg
|
||||
Kahlberg
|
||||
Kahlberg
|
||||
Scheidequelle
|
||||
Höhle der Umkehr
|
||||
Höhle der Umkehr
|
||||
Höhle der Umkehr
|
||||
Höhle der Umkehr
|
||||
Höhle der Umkehr
|
||||
Höhle der Umkehr
|
||||
Höhle der Umkehr
|
||||
Höhle der Umkehr
|
||||
Höhle der Umkehr
|
||||
Höhle der Umkehr
|
||||
Höhle der Umkehr
|
||||
Höhle der Umkehr
|
||||
Höhle der Umkehr
|
||||
Höhle der Umkehr
|
||||
Höhle der Umkehr
|
||||
Höhle der Umkehr
|
||||
Höhle der Umkehr
|
||||
Höhle der Umkehr
|
||||
Höhle der Umkehr
|
||||
Höhle der Umkehr
|
||||
Höhle der Umkehr
|
||||
Blumenparadies
|
||||
Blizzach-Tempel
|
||||
Blizzach-Tempel
|
||||
Blizzach-Tempel
|
||||
Blizzach-Tempel
|
||||
Blizzach-Tempel
|
||||
Blizzach-Tempel
|
||||
Bizarre Höhle
|
||||
Bizarre Höhle
|
||||
Maniac-Höhle
|
||||
Maniac-Höhle
|
||||
Maniac-Tunnel
|
||||
Ziergarten
|
||||
Eiseninsel
|
||||
Eiseninsel
|
||||
Eiseninsel
|
||||
Eiseninsel
|
||||
Eiseninsel
|
||||
Eiseninsel
|
||||
Eiseninsel
|
||||
Eiseninsel
|
||||
Alte Villa
|
||||
Alte Villa
|
||||
Alte Villa
|
||||
Alte Villa
|
||||
Alte Villa
|
||||
Alte Villa
|
||||
Alte Villa
|
||||
Alte Villa
|
||||
Alte Villa
|
||||
Galaktik-Zentrale
|
||||
Galaktik-Zentrale
|
||||
Galaktik-Zentrale
|
||||
Galaktik-Zentrale
|
||||
Galaktik-Zentrale
|
||||
Galaktik-Zentrale
|
||||
Galaktik-Zentrale
|
||||
Galaktik-Zentrale
|
||||
See der Wahrheit
|
||||
See der Wahrheit
|
||||
See der Wahrheit
|
||||
See der Kühnheit
|
||||
See der Kühnheit
|
||||
See der Kühnheit
|
||||
See der Stärke
|
||||
See der Stärke
|
||||
See der Stärke
|
||||
Neumondinsel
|
||||
Neumondinsel
|
||||
Duellpark
|
||||
Duellpark
|
||||
Duellpark
|
||||
Duellpark
|
||||
Duellpark
|
||||
Duellturm
|
||||
Duellturm
|
||||
Duellturm
|
||||
Duellturm
|
||||
Duellturm
|
||||
Duellturm
|
||||
Mysteriöser Ort
|
||||
Wahrheitsufer
|
||||
Kühnheitsufer
|
||||
Kühnheitsufer
|
||||
Kühnheitsufer
|
||||
Kühnheitsufer
|
||||
Stärkeufer
|
||||
Quellenpfad
|
||||
Mysteriöser Ort
|
||||
Route 201
|
||||
Route 202
|
||||
Route 203
|
||||
Route 204
|
||||
Route 204
|
||||
Route 205
|
||||
Route 205
|
||||
Route 205
|
||||
Route 206
|
||||
Route 206
|
||||
Route 207
|
||||
Route 208
|
||||
Route 208
|
||||
Route 209
|
||||
Route 209
|
||||
Route 209
|
||||
Route 209
|
||||
Route 209
|
||||
Route 209
|
||||
Route 210
|
||||
Route 210
|
||||
Route 210
|
||||
Route 210
|
||||
Route 211
|
||||
Route 211
|
||||
Route 212
|
||||
Route 212
|
||||
Route 212
|
||||
Route 212
|
||||
Route 212
|
||||
Route 212
|
||||
Route 213
|
||||
Route 213
|
||||
Route 213
|
||||
Route 213
|
||||
Route 213
|
||||
Route 213
|
||||
Route 213
|
||||
Route 214
|
||||
Route 214
|
||||
Route 215
|
||||
Route 216
|
||||
Route 216
|
||||
Route 217
|
||||
Route 217
|
||||
Route 217
|
||||
Route 218
|
||||
Route 218
|
||||
Route 218
|
||||
Route 219
|
||||
Route 221
|
||||
Route 221
|
||||
Route 221
|
||||
Route 222
|
||||
Route 222
|
||||
Route 222
|
||||
Route 222
|
||||
Route 224
|
||||
Route 225
|
||||
Route 225
|
||||
Route 227
|
||||
Route 227
|
||||
Route 228
|
||||
Route 228
|
||||
Route 228
|
||||
Route 228
|
||||
Route 229
|
||||
Mysteriöser Ort
|
||||
Zweiblattdorf
|
||||
Zweiblattdorf
|
||||
Zweiblattdorf
|
||||
Zweiblattdorf
|
||||
Zweiblattdorf
|
||||
Zweiblattdorf
|
||||
Zweiblattdorf
|
||||
Sandgemme
|
||||
Sandgemme
|
||||
Sandgemme
|
||||
Sandgemme
|
||||
Sandgemme
|
||||
Sandgemme
|
||||
Sandgemme
|
||||
Sandgemme
|
||||
Sandgemme
|
||||
Flori
|
||||
Flori
|
||||
Flori
|
||||
Flori
|
||||
Flori
|
||||
Flori
|
||||
Flori
|
||||
Flori
|
||||
Trostu
|
||||
Trostu
|
||||
Trostu
|
||||
Trostu
|
||||
Trostu
|
||||
Trostu
|
||||
Trostu
|
||||
Trostu
|
||||
Trostu
|
||||
Trostu
|
||||
Elyses
|
||||
Elyses
|
||||
Elyses
|
||||
Elyses
|
||||
Elyses
|
||||
Elyses
|
||||
Elyses
|
||||
Elyses
|
||||
Elyses
|
||||
Überlebensareal
|
||||
Überlebensareal
|
||||
Überlebensareal
|
||||
Überlebensareal
|
||||
Überlebensareal
|
||||
Überlebensareal
|
||||
Überlebensareal
|
||||
Überlebensareal
|
||||
Erholungsareal
|
||||
Erholungsareal
|
||||
Erholungsareal
|
||||
Erholungsareal
|
||||
Erholungsareal
|
||||
Erholungsareal
|
||||
Erholungsareal
|
||||
Erholungsareal
|
||||
Erholungsareal
|
||||
Erholungsareal
|
||||
Mysteriöser Ort
|
||||
Mysteriöser Ort
|
||||
Route 220
|
||||
Route 223
|
||||
Route 226
|
||||
Route 226
|
||||
Route 230
|
||||
Buhnenpfad
|
||||
Mysteriöser Ort
|
||||
Mysteriöser Ort
|
||||
Mysteriöser Ort
|
||||
Ewigenau
|
||||
Hamanasu-Park
|
||||
Hamanasu-Park
|
||||
Hamanasu-Park
|
||||
Hamanasu-Park
|
||||
Hamanasu-Park
|
||||
Hamanasu-Park
|
||||
Hamanasu-Park
|
||||
Hamanasu-Park
|
||||
Hamanasu-Park
|
||||
Hamanasu-Park
|
||||
Hamanasu-Park
|
||||
Hamanasu-Park
|
||||
Hamanasu-Park
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Hamanasu-Park
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Untergrundhöhlen
|
||||
Hamanasu-Park
|
||||
Hamanasu-Park
|
||||
Jubelstadt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Hamanasu-Park
|
||||
Hamanasu-Park
|
||||
Hamanasu-Park
|
||||
Hamanasu-Park
|
||||
Hamanasu-Park
|
||||
Hamanasu-Park
|
||||
Hamanasu-Park
|
||||
Hamanasu-Park
|
||||
Hamanasu-Park
|
||||
Hamanasu-Park
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue