diff --git a/PKHeX.Core/Editing/Applicators/MoveSetApplicator.cs b/PKHeX.Core/Editing/Applicators/MoveSetApplicator.cs index 20edc102509..2efa62a45ca 100644 --- a/PKHeX.Core/Editing/Applicators/MoveSetApplicator.cs +++ b/PKHeX.Core/Editing/Applicators/MoveSetApplicator.cs @@ -94,6 +94,20 @@ public static IReadOnlyList GetSuggestedRelearnMoves(this LegalityAnalysis } } + 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; diff --git a/PKHeX.Core/Editing/CommonEdits.cs b/PKHeX.Core/Editing/CommonEdits.cs index 4db15ef238c..139e9695775 100644 --- a/PKHeX.Core/Editing/CommonEdits.cs +++ b/PKHeX.Core/Editing/CommonEdits.cs @@ -375,7 +375,7 @@ public static void SetEggMetData(this PKM pk, GameVersion origin, GameVersion de { 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; } diff --git a/PKHeX.Core/Editing/Saves/Editors/EventOld/EventLabelCollection.cs b/PKHeX.Core/Editing/Saves/Editors/EventOld/EventLabelCollection.cs index 91c594638ea..f4bb32bc247 100644 --- a/PKHeX.Core/Editing/Saves/Editors/EventOld/EventLabelCollection.cs +++ b/PKHeX.Core/Editing/Saves/Editors/EventOld/EventLabelCollection.cs @@ -125,6 +125,131 @@ private static int TryParseHexDecConst(string c) }; } + public sealed class EventLabelCollectionSystem + { + public readonly IReadOnlyList Work; + public readonly IReadOnlyList Flag; + public readonly IReadOnlyList 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 GetFlags(IReadOnlyCollection strings, int maxValue) + { + var result = new List(strings.Count); + var processed = new HashSet(); + 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 GetValues(IReadOnlyCollection strings, int maxValue) + { + var result = new List(strings.Count); + var processed = new HashSet(); + 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 GetPredefinedArray(string combined) + { + var result = new List { 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, diff --git a/PKHeX.Core/Editing/Saves/Editors/EventWork/EventWorkDiff.cs b/PKHeX.Core/Editing/Saves/Editors/EventWork/EventWorkDiff.cs index 6616734229b..d04a786c20f 100644 --- a/PKHeX.Core/Editing/Saves/Editors/EventWork/EventWorkDiff.cs +++ b/PKHeX.Core/Editing/Saves/Editors/EventWork/EventWorkDiff.cs @@ -183,4 +183,113 @@ public WorkSummary(int rawIndex, EventWork7b ew, string text) } } } + + public sealed class EventWorkDiff8b : EventBlockDiff + { + public readonly List WorkChanged = new(); + private SaveFile? S1; + public readonly List SetSystem = new(); + public readonly List 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 Summarize() + { + if (S1 == null) + return Array.Empty(); + + 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 { "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; + } + } + } } diff --git a/PKHeX.Core/Editing/Saves/Editors/EventWork/EventWorkUtil.cs b/PKHeX.Core/Editing/Saves/Editors/EventWork/EventWorkUtil.cs index 3ef062b1f43..feb34db5af4 100644 --- a/PKHeX.Core/Editing/Saves/Editors/EventWork/EventWorkUtil.cs +++ b/PKHeX.Core/Editing/Saves/Editors/EventWork/EventWorkUtil.cs @@ -70,14 +70,13 @@ public static List GetVars(IEnumerable lines, Func /// Compares a and object of the same type to find changes. /// - /// Type of value used by /// Data before the event was triggered /// Data after the event was triggered /// List of flags that were turned on /// List of flags that were turned off - public static void DiffSavesFlag(IEventWork before, IEventWork after, List on, List off) + public static void DiffSavesFlag(IEventFlag before, IEventFlag after, List on, List 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 @@ public static void DiffSavesFlag(IEventWork before, IEventWork after, L } } + /// + /// Compares a and object of the same type to find changes. + /// + /// Data before the event was triggered + /// Data after the event was triggered + /// List of flags that were turned on + /// List of flags that were turned off + public static void DiffSavesSystem(ISystemFlag before, ISystemFlag after, List on, List 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); + } + } + /// /// Compares a and object of the same type to find changes. /// @@ -100,7 +121,7 @@ public static void DiffSavesFlag(IEventWork before, IEventWork after, L /// Summary of the value change public static void DiffSavesWork(IEventWork before, IEventWork after, List changed, List 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 @@ public static void DiffSavesWork(IEventWork before, IEventWork after, L } } } -} \ No newline at end of file +} diff --git a/PKHeX.Core/Editing/Saves/Editors/EventWork/SplitEventEditor.cs b/PKHeX.Core/Editing/Saves/Editors/EventWork/SplitEventEditor.cs index 1bcbb7a3709..8a9c528f6be 100644 --- a/PKHeX.Core/Editing/Saves/Editors/EventWork/SplitEventEditor.cs +++ b/PKHeX.Core/Editing/Saves/Editors/EventWork/SplitEventEditor.cs @@ -11,9 +11,9 @@ public sealed class SplitEventEditor where T : struct { public readonly IList Work; public readonly IList Flag; - public readonly IEventWork Block; + public readonly IEventVar Block; - public SplitEventEditor(IEventWork block, IEnumerable work, IEnumerable flag) + public SplitEventEditor(IEventVar block, IEnumerable work, IEnumerable flag) { Block = block; // load lines diff --git a/PKHeX.Core/Editing/Saves/Slots/Extensions.cs b/PKHeX.Core/Editing/Saves/Slots/Extensions.cs index 3b0480d2148..5de8210d203 100644 --- a/PKHeX.Core/Editing/Saves/Slots/Extensions.cs +++ b/PKHeX.Core/Editing/Saves/Slots/Extensions.cs @@ -54,6 +54,7 @@ public static List GetExtraSlots(this SaveFile sav, bool all = fal SAV7 sav7 => GetExtraSlots7(sav7, all), SAV7b lgpe => GetExtraSlots7b(lgpe), SAV8SWSH ss => GetExtraSlots8(ss), + SAV8BS bs => GetExtraSlots8b(bs), _ => None, }; @@ -201,5 +202,20 @@ private static List GetExtraSlots8(ISaveBlock8Main sav) return list; } + + private static List 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 }, + }; + } } } diff --git a/PKHeX.Core/Game/Enums/GameVersion.cs b/PKHeX.Core/Game/Enums/GameVersion.cs index 667bc2712c8..1ca0ff8f50b 100644 --- a/PKHeX.Core/Game/Enums/GameVersion.cs +++ b/PKHeX.Core/Game/Enums/GameVersion.cs @@ -202,6 +202,19 @@ public enum GameVersion /// Pokémon Shield (NX) /// SH = 45, + + // HOME = 46, + // PLA = 47, + + /// + /// Pokémon Brilliant Diamond (NX) + /// + BD = 48, + + /// + /// Pokémon Shining Pearl (NX) + /// + SP = 49, #endregion // The following values are not actually stored values in pkm data, @@ -379,6 +392,14 @@ public enum GameVersion /// SWSH, + /// + /// Pokémon Brilliant Diamond & Shining Pearl + /// + /// Used to lump data from the associated games as data assets are shared. + /// + /// + BDSP, + /// /// Generation 1 Games /// @@ -437,6 +458,7 @@ public enum GameVersion /// Generation 8 Games /// /// + /// Gen8, /// diff --git a/PKHeX.Core/Game/GameStrings/GameDataSource.cs b/PKHeX.Core/Game/GameStrings/GameDataSource.cs index 07414540c14..1906bfe98af 100644 --- a/PKHeX.Core/Game/GameStrings/GameDataSource.cs +++ b/PKHeX.Core/Game/GameStrings/GameDataSource.cs @@ -80,6 +80,7 @@ private static IReadOnlyList GetVersionList(GameStrings s) var list = s.gamelist; var games = new byte[] { + 48, 49, // 8 bdsp 44, 45, // 8 swsh 42, 43, // 7 gg 30, 31, // 7 sm diff --git a/PKHeX.Core/Game/GameStrings/GameStrings.cs b/PKHeX.Core/Game/GameStrings/GameStrings.cs index 2d3610ffabf..4e3f21967e2 100644 --- a/PKHeX.Core/Game/GameStrings/GameStrings.cs +++ b/PKHeX.Core/Game/GameStrings/GameStrings.cs @@ -24,6 +24,7 @@ public sealed class GameStrings : IBasicStrings 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 @@ public GameStrings(string l) 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 @@ private void SanitizeMetLocations() SanitizeMetG6XY(); SanitizeMetG7SM(); SanitizeMetG8SWSH(); + SanitizeMetG8BDSP(); if (lang is "es" or "it") { @@ -386,6 +393,50 @@ private void SanitizeMetG8SWSH() // 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(); + + foreach (var s in arr) + { + counts.TryGetValue(s, out var value); + counts[s] = value + 1; + } + +#if !DEBUG + var maxCounts = new Dictionary(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(), @@ -393,9 +444,29 @@ private void SanitizeMetG8SWSH() 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 @@ public string GetLocationName(bool isEggLocation, int location, int format, int 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(), }; @@ -543,5 +614,14 @@ public string GetLocationName(bool isEggLocation, int location, int format, int 6 => metSWSH_60000, _ => Array.Empty(), }; + + public IReadOnlyList GetLocationNames8b(int bankID) => bankID switch + { + 0 => metBDSP_00000, + 3 => metBDSP_30000, + 4 => metBDSP_40000, + 6 => metBDSP_60000, + _ => Array.Empty(), + }; } } diff --git a/PKHeX.Core/Game/GameStrings/MetDataSource.cs b/PKHeX.Core/Game/GameStrings/MetDataSource.cs index c7d64d831b5..6115c634a39 100644 --- a/PKHeX.Core/Game/GameStrings/MetDataSource.cs +++ b/PKHeX.Core/Game/GameStrings/MetDataSource.cs @@ -18,6 +18,7 @@ public sealed class MetDataSource private readonly List MetGen7; private readonly List MetGen7GG; private readonly List MetGen8; + private readonly List MetGen8b; private IReadOnlyList? MetGen4Transfer; private IReadOnlyList? MetGen5Transfer; @@ -33,6 +34,7 @@ public MetDataSource(GameStrings s) MetGen7 = CreateGen7(s); MetGen7GG = CreateGen7GG(s); MetGen8 = CreateGen8(s); + MetGen8b = CreateGen8b(s); } private static List CreateGen2(GameStrings s) @@ -129,7 +131,7 @@ private static List CreateGen7(GameStrings s) private static List 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 @@ private static List CreateGen7GG(GameStrings s) private static List 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 @@ private static List CreateGen8(GameStrings s) return locations; } + private static List CreateGen8b(GameStrings s) + { + // Manually add invalid (-1) location from SWSH as ID 65535 + var locations = new List { 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; + } + /// /// Fetches a Met Location list for a that has been transferred away from and overwritten. /// @@ -185,6 +200,7 @@ or RD or BU or GN or YW 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), }; diff --git a/PKHeX.Core/Game/GameUtil.cs b/PKHeX.Core/Game/GameUtil.cs index 2d7b11abf5f..dab5584e289 100644 --- a/PKHeX.Core/Game/GameUtil.cs +++ b/PKHeX.Core/Game/GameUtil.cs @@ -75,6 +75,7 @@ private static GameVersion[] GetValidGameVersions() // Gen8 SW or SH => SWSH, + BD or SP => BDSP, _ => Invalid, }; @@ -137,6 +138,7 @@ public static int GetMaxSpeciesID(this GameVersion game) 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 @@ public static bool Contains(this GameVersion g1, GameVersion g2) 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, }; } diff --git a/PKHeX.Core/Legality/Areas/EncounterArea8b.cs b/PKHeX.Core/Legality/Areas/EncounterArea8b.cs new file mode 100644 index 00000000000..0005ed0a96f --- /dev/null +++ b/PKHeX.Core/Legality/Areas/EncounterArea8b.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; + +namespace PKHeX.Core +{ + /// + /// + /// encounter area + /// + public sealed record EncounterArea8b : EncounterArea + { + public readonly EncounterSlot8b[] Slots; + + protected override IReadOnlyList 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 GetMatchingSlots(PKM pkm, IReadOnlyList 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; + } + } + } + } +} diff --git a/PKHeX.Core/Legality/Breeding.cs b/PKHeX.Core/Legality/Breeding.cs index 60d8d7e2549..9501671479c 100644 --- a/PKHeX.Core/Legality/Breeding.cs +++ b/PKHeX.Core/Legality/Breeding.cs @@ -24,7 +24,7 @@ public static class Breeding B, W, B2, W2, X, Y, OR, AS, SN, MN, US, UM, - SW, SH, + SW, SH, BD, SP, GS, }; diff --git a/PKHeX.Core/Legality/Core.cs b/PKHeX.Core/Legality/Core.cs index 467c5c12ecf..7804d541797 100644 --- a/PKHeX.Core/Legality/Core.cs +++ b/PKHeX.Core/Legality/Core.cs @@ -50,6 +50,8 @@ public static partial class Legal // 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 GetPPTable(PKM pkm, int format) { @@ -72,6 +74,13 @@ public static IReadOnlyList GetPPTable(PKM pkm, int format) _ => Array.Empty(), }; + public static ICollection GetDummiedMovesHashSet(PKM pkm) => pkm switch + { + PK8 => DummiedMoves_SWSH, + PB8 => DummiedMoves_BDSP, + _ => Array.Empty(), + }; + internal static int GetMaxSpeciesOrigin(PKM pkm) { if (pkm.Format == 1) diff --git a/PKHeX.Core/Legality/Encounters/Data/EncounterEvent.cs b/PKHeX.Core/Legality/Encounters/Data/EncounterEvent.cs index b4b00c24385..f69d3c6b009 100644 --- a/PKHeX.Core/Legality/Encounters/Data/EncounterEvent.cs +++ b/PKHeX.Core/Legality/Encounters/Data/EncounterEvent.cs @@ -30,6 +30,9 @@ public static class EncounterEvent /// Event Database for Generation 8 public static IReadOnlyList MGDB_G8 { get; private set; } = Array.Empty(); + /// Event Database for Generation 8 + public static IReadOnlyList MGDB_G8B { get; private set; } = Array.Empty(); + /// Indicates if the databases are initialized. public static bool Initialized => MGDB_G3.Count != 0; @@ -41,6 +44,7 @@ public static class EncounterEvent 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(byte[] bin, int size, Func ctor) { @@ -63,6 +67,7 @@ public static void RefreshMGDB(params string[] paths) ICollection g7 = GetWC7DB(Util.GetBinaryResource("wc7.pkl"), Util.GetBinaryResource("wc7full.pkl")); ICollection b7 = GetWB7DB(Util.GetBinaryResource("wb7full.pkl")); ICollection g8 = GetWC8DB(Util.GetBinaryResource("wc8.pkl")); + ICollection b8 = GetWB8DB(Util.GetBinaryResource("wb8.pkl")); foreach (var gift in paths.Where(Directory.Exists).SelectMany(MysteryUtil.GetGiftsFromFolder)) { @@ -81,6 +86,7 @@ static void AddOrExpand(ref ICollection arr, T obj) 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 @@ static T[] SetArray(ICollection arr) MGDB_G7 = SetArray(g7); MGDB_G7GG = SetArray(b7); MGDB_G8 = SetArray(g8); + MGDB_G8B = SetArray(b8); } public static IEnumerable GetAllEvents(bool sorted = true) @@ -114,6 +121,7 @@ public static IEnumerable GetAllEvents(bool sorted = true) 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); diff --git a/PKHeX.Core/Legality/Encounters/Data/Encounters8b.cs b/PKHeX.Core/Legality/Encounters/Data/Encounters8b.cs new file mode 100644 index 00000000000..fd481995b74 --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/Data/Encounters8b.cs @@ -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 + }; + } +} diff --git a/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot8b.cs b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot8b.cs new file mode 100644 index 00000000000..a290ec3982a --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/EncounterSlot/EncounterSlot8b.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections.Generic; + +namespace PKHeX.Core +{ + /// + /// Encounter Slot found in . + /// + /// + 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(); + 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 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}}, // Farfetchd + {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 + }; + } +} diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic.cs index c76fc66fe51..d77b1014eb0 100644 --- a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic.cs +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic.cs @@ -132,7 +132,7 @@ private void SetEggMetData(PKM pk, ITrainerInfo tr, DateTime today) 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; diff --git a/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8b.cs b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8b.cs new file mode 100644 index 00000000000..e84f6ad6925 --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/EncounterStatic/EncounterStatic8b.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using static PKHeX.Core.StaticCorrelation8bRequirement; + +namespace PKHeX.Core +{ + /// + /// Generation 7 Static Encounter + /// + /// + public sealed record EncounterStatic8b : EncounterStatic, IRelearn, IStaticCorrelation8b + { + public override int Generation => 8; + public IReadOnlyList Relearn { get; init; } = Array.Empty(); + + 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, + } +} diff --git a/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade8b.cs b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade8b.cs new file mode 100644 index 00000000000..7add16914d7 --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/EncounterTrade/EncounterTrade8b.cs @@ -0,0 +1,54 @@ +namespace PKHeX.Core +{ + /// + /// Generation 7 Trade Encounter + /// + /// + 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(); + } + } +} diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8.cs index 956ed25b9ce..41728f8e826 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8.cs @@ -17,6 +17,7 @@ public static IEnumerable GetEncounters(PKM pkm) 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), }; } diff --git a/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8b.cs b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8b.cs new file mode 100644 index 00000000000..4036c8758c5 --- /dev/null +++ b/PKHeX.Core/Legality/Encounters/Generator/ByGeneration/EncounterGenerator8b.cs @@ -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 GetEncounters(PKM pkm, IReadOnlyList 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; + } + } +} diff --git a/PKHeX.Core/Legality/Encounters/Generator/Moveset/EncounterMovesetGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/Moveset/EncounterMovesetGenerator.cs index cddf0527a8b..fe322b6acdb 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Moveset/EncounterMovesetGenerator.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Moveset/EncounterMovesetGenerator.cs @@ -145,7 +145,7 @@ public static IEnumerable GenerateVersionEncounters(PKM pk, IEnu 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 @@ private static IEnumerable GetSlots(PKM pk, IReadOnlyList ne 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; } diff --git a/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterSlotGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterSlotGenerator.cs index 01d6fd18334..19b712ea94c 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterSlotGenerator.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterSlotGenerator.cs @@ -13,6 +13,7 @@ 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 @@ public static IEnumerable GetPossible(PKM pkm, IReadOnlyList GetRawEncounterSlots(PKM pkm, IReadOnlyList 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 @@ private static IEnumerable GetEncounterAreas(PKM pkm, GameVersion GO => GetEncounterTableGO(pkm), SW => SlotsSW, SH => SlotsSH, + BD => SlotsBD, + SP => SlotsSP, _ => Array.Empty(), }; diff --git a/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterStaticGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterStaticGenerator.cs index a2dd905a822..63c1f6d715a 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterStaticGenerator.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterStaticGenerator.cs @@ -13,6 +13,7 @@ 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 @@ internal static EncounterStatic7 GetVCStaticTransferEncounter(PKM pkm, IEncounte SW => StaticSW, SH => StaticSH, + BD => StaticBD, + SP => StaticSP, _ => Array.Empty(), }; diff --git a/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterTradeGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterTradeGenerator.cs index 6f1d36b391f..4344bafa97a 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterTradeGenerator.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Specific/EncounterTradeGenerator.cs @@ -95,6 +95,7 @@ private static IEnumerable GetTableVC(GameVersion game) 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(), }; } diff --git a/PKHeX.Core/Legality/Encounters/Generator/Specific/MysteryGiftGenerator.cs b/PKHeX.Core/Legality/Encounters/Generator/Specific/MysteryGiftGenerator.cs index 2baeb41b923..a69e5983f24 100644 --- a/PKHeX.Core/Legality/Encounters/Generator/Specific/MysteryGiftGenerator.cs +++ b/PKHeX.Core/Legality/Encounters/Generator/Specific/MysteryGiftGenerator.cs @@ -39,7 +39,7 @@ public static IEnumerable GetValidGifts(PKM pkm, IReadOnlyList MGDB_G5, 6 => MGDB_G6, 7 => pkm.LGPE ? MGDB_G7GG : MGDB_G7, - 8 => MGDB_G8, + 8 => pkm.BDSP ? MGDB_G8B : MGDB_G8, _ => Array.Empty(), }; diff --git a/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestion.cs b/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestion.cs index 52bfd8a07d4..13297de88c2 100644 --- a/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestion.cs +++ b/PKHeX.Core/Legality/Encounters/Information/EncounterSuggestion.cs @@ -50,14 +50,15 @@ public static int GetSuggestedEncounterEggMetLevel(PKM pkm) 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 @@ private static EncounterSuggestionData GetSuggestedEncounterStatic(PKM pkm, Enco GSC or RBY => pkm.Met_Level == 0 ? 0 : Locations.HatchLocationC, SW or SH => Locations.HatchLocation8, + BD or SP => Locations.HatchLocation8b, _ => -1, }; diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs b/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs index ecdf5ee8aa1..6eaf2acbb09 100644 --- a/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs +++ b/PKHeX.Core/Legality/Encounters/Verifiers/EncounterVerifier.cs @@ -81,6 +81,7 @@ private static CheckResult VerifyWildEncounterCrystalHeadbutt(ITrainerID tr, Enc 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 @@ private static CheckResult VerifyEncounterEgg8(PKM pkm) 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 MetLocations) { if (pkm.Met_Level != eggLevel) @@ -208,7 +218,7 @@ private static CheckResult VerifyEncounterEggLevelLoc(PKM pkm, int eggLevel, ICo : 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 @@ private static CheckResult VerifyUnhatchedEgg(PKM pkm, int tradeLoc) 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); } diff --git a/PKHeX.Core/Legality/Encounters/Verifiers/VerifyRelearnMoves.cs b/PKHeX.Core/Legality/Encounters/Verifiers/VerifyRelearnMoves.cs index 187c39e6aeb..d389f0894bd 100644 --- a/PKHeX.Core/Legality/Encounters/Verifiers/VerifyRelearnMoves.cs +++ b/PKHeX.Core/Legality/Encounters/Verifiers/VerifyRelearnMoves.cs @@ -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 @@ public static CheckResult[] VerifyRelearn(PKM pkm, IEncounterTemplate enc, Check { 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 @@ static CheckResult CheckResult(int move, int require) } } - 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 @@ private static CheckResult[] VerifyRelearnDexNav(PKM pkm, CheckResult[] result) 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. diff --git a/PKHeX.Core/Legality/Evolutions/EvolutionTree.cs b/PKHeX.Core/Legality/Evolutions/EvolutionTree.cs index 2d5c0a6a84e..387839add88 100644 --- a/PKHeX.Core/Legality/Evolutions/EvolutionTree.cs +++ b/PKHeX.Core/Legality/Evolutions/EvolutionTree.cs @@ -23,6 +23,7 @@ public sealed class EvolutionTree 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 @@ static EvolutionTree() // Add in banned evolution data! Evolves7.FixEvoTreeSM(); Evolves8.FixEvoTreeSS(); + Evolves8b.FixEvoTreeBS(); } public static EvolutionTree GetEvolutionTree(int generation) => generation switch @@ -55,7 +57,7 @@ static EvolutionTree() 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 Entries; @@ -172,6 +174,12 @@ private void FixEvoTreeSS() 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 func) { var key = GetLookupKey(species, form); diff --git a/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs b/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs index e4f9a5557d2..43713b647a3 100644 --- a/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs +++ b/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs @@ -354,6 +354,7 @@ public static class LegalityCheckStrings 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}"; diff --git a/PKHeX.Core/Legality/MoveList.cs b/PKHeX.Core/Legality/MoveList.cs index 493aa82e8d4..0f002042e1e 100644 --- a/PKHeX.Core/Legality/MoveList.cs +++ b/PKHeX.Core/Legality/MoveList.cs @@ -141,6 +141,14 @@ internal static int[] GetBaseEggMoves(PKM pkm, int species, int form, GameVersio 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(); } @@ -165,11 +173,20 @@ internal static IReadOnlyList[] GetValidMovesAllGens(PKM pkm, IReadOnlyList internal static IEnumerable GetValidMoves(PKM pkm, IReadOnlyList 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 GetValidRelearn(PKM pkm, int species, int form, GameVersion version = Any) { return GetValidRelearn(pkm, species, form, Breeding.GetCanInheritMoves(species), version); diff --git a/PKHeX.Core/Legality/Moves/GameData.cs b/PKHeX.Core/Legality/Moves/GameData.cs index d1f7087245a..731ad8e62bc 100644 --- a/PKHeX.Core/Legality/Moves/GameData.cs +++ b/PKHeX.Core/Legality/Moves/GameData.cs @@ -43,6 +43,7 @@ public static Learnset GetLearnset(GameVersion game, int species, int form) 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 @@ public static Learnset GetLearnset(GameVersion game, int species, int form) 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, diff --git a/PKHeX.Core/Legality/Moves/MoveEgg.cs b/PKHeX.Core/Legality/Moves/MoveEgg.cs index 334333c049d..e09031fe918 100644 --- a/PKHeX.Core/Legality/Moves/MoveEgg.cs +++ b/PKHeX.Core/Legality/Moves/MoveEgg.cs @@ -34,7 +34,8 @@ public static int[] GetEggMoves(PersonalInfo pi, int species, int form, GameVers 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(), }; @@ -59,6 +60,7 @@ internal static int[] GetRelearnLVLMoves(PKM pkm, int species, int form, int lvl 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(), }; @@ -77,11 +79,22 @@ public static int[] GetSharedEggMoves(PKM pkm, int gen) { if (gen < 8 || pkm.IsEgg) return Array.Empty(); - 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); + } } } } diff --git a/PKHeX.Core/Legality/Moves/MoveLevelUp.cs b/PKHeX.Core/Legality/Moves/MoveLevelUp.cs index 986d55ab12b..dda6625ab91 100644 --- a/PKHeX.Core/Legality/Moves/MoveLevelUp.cs +++ b/PKHeX.Core/Legality/Moves/MoveLevelUp.cs @@ -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 @@ private static LearnVersion GetIsLevelUp8(int species, int form, int move, int m 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 @@ private static List AddMovesLevelUp8(List moves, GameVersion ver, int 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; } diff --git a/PKHeX.Core/Legality/Moves/MoveTechnicalMachine.cs b/PKHeX.Core/Legality/Moves/MoveTechnicalMachine.cs index c5b3667d3f2..9f114177c1d 100644 --- a/PKHeX.Core/Legality/Moves/MoveTechnicalMachine.cs +++ b/PKHeX.Core/Legality/Moves/MoveTechnicalMachine.cs @@ -243,6 +243,18 @@ private static GameVersion GetIsMachine8(int species, int move, int form, GameVe } } + 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 @@ private static GameVersion GetIsRecord8(PKM pkm, int species, int move, int form 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 @@ private static void AddMachine8(List r, int species, int form, GameVersion 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 @@ private static void AddMachineSWSH(List r, int species, int form) } } + private static void AddMachineBDSP(List 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 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; diff --git a/PKHeX.Core/Legality/RNG/Algorithms/Xoroshiro128Plus8b.cs b/PKHeX.Core/Legality/RNG/Algorithms/Xoroshiro128Plus8b.cs new file mode 100644 index 00000000000..794e44510bc --- /dev/null +++ b/PKHeX.Core/Legality/RNG/Algorithms/Xoroshiro128Plus8b.cs @@ -0,0 +1,73 @@ +using System.Runtime.CompilerServices; + +namespace PKHeX.Core +{ + /// + /// 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. + /// + /// https://en.wikipedia.org/wiki/Xoroshiro128%2B + /// + [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)); + } + + /// + /// Gets the next random . + /// + [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); + } + } +} diff --git a/PKHeX.Core/Legality/RNG/PIDType.cs b/PKHeX.Core/Legality/RNG/PIDType.cs index 323b957d651..bac5992a0ad 100644 --- a/PKHeX.Core/Legality/RNG/PIDType.cs +++ b/PKHeX.Core/Legality/RNG/PIDType.cs @@ -183,6 +183,12 @@ public enum PIDType /// Formulaic based on PID & EC values from a 32bit-seed. Overworld8, + /// + /// Generation 8b Roaming Pokemon PID + /// + /// Formulaic based on EC value = 32bit-seed. + Roaming8b, + #endregion } diff --git a/PKHeX.Core/Legality/RNG/Roaming8bRNG.cs b/PKHeX.Core/Legality/RNG/Roaming8bRNG.cs new file mode 100644 index 00000000000..56ad4d2bdb8 --- /dev/null +++ b/PKHeX.Core/Legality/RNG/Roaming8bRNG.cs @@ -0,0 +1,240 @@ +namespace PKHeX.Core +{ + /// + /// Contains logic for the Generation 8b (BD/SP) roaming spawns. + /// + /// + /// Roaming encounters use the pokemon's 32-bit as RNG seed. + /// + 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; + } + } +} diff --git a/PKHeX.Core/Legality/Restrictions/EvolutionRestrictions.cs b/PKHeX.Core/Legality/Restrictions/EvolutionRestrictions.cs index c6816ee0a5d..3c2add3b250 100644 --- a/PKHeX.Core/Legality/Restrictions/EvolutionRestrictions.cs +++ b/PKHeX.Core/Legality/Restrictions/EvolutionRestrictions.cs @@ -86,10 +86,10 @@ public MoveEvolution(int referenceIndex, int move) 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) diff --git a/PKHeX.Core/Legality/Restrictions/ItemRestrictions.cs b/PKHeX.Core/Legality/Restrictions/ItemRestrictions.cs index fc68ef00f62..9b82fbfecbf 100644 --- a/PKHeX.Core/Legality/Restrictions/ItemRestrictions.cs +++ b/PKHeX.Core/Legality/Restrictions/ItemRestrictions.cs @@ -19,7 +19,7 @@ public static bool IsHeldItemAllowed(PKM pk) { 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); } /// @@ -28,15 +28,15 @@ public static bool IsHeldItemAllowed(PKM pk) /// Held Item ID /// Generation Number /// True if able to be held, false if not - 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 GetReleasedHeldItems(int generation) => generation switch + private static IReadOnlyList GetReleasedHeldItems(int generation, PKM pk) => generation switch { 2 => ReleasedHeldItems_2, 3 => ReleasedHeldItems_3, @@ -44,6 +44,7 @@ public static bool IsHeldItemAllowed(int item, int generation) 5 => ReleasedHeldItems_5, 6 => ReleasedHeldItems_6, 7 => ReleasedHeldItems_7, + 8 when pk is PB8 => ReleasedHeldItems_8b, 8 => ReleasedHeldItems_8, _ => Array.Empty(), }; diff --git a/PKHeX.Core/Legality/Restrictions/Memories/MemoryPermissions.cs b/PKHeX.Core/Legality/Restrictions/Memories/MemoryPermissions.cs index f1ae36360ea..cd36bb3d4c1 100644 --- a/PKHeX.Core/Legality/Restrictions/Memories/MemoryPermissions.cs +++ b/PKHeX.Core/Legality/Restrictions/Memories/MemoryPermissions.cs @@ -136,7 +136,7 @@ public static bool CanKnowMove(PKM pkm, MemoryVariableSet memory, int gen, Legal 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 @@ public static bool CanKnowMove(PKM pkm, MemoryVariableSet memory, int gen, Legal 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 } diff --git a/PKHeX.Core/Legality/Tables/Locations.cs b/PKHeX.Core/Legality/Tables/Locations.cs index 416cea39576..33c19cefcd4 100644 --- a/PKHeX.Core/Legality/Tables/Locations.cs +++ b/PKHeX.Core/Legality/Tables/Locations.cs @@ -11,6 +11,7 @@ public static class Locations 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 @@ public static class Locations /// Route 5 in public const int HatchLocation8 = 40; + /// Solaceon Town in + public const int HatchLocation8b = 446; + /// Generation 1 -> Generation 7 Transfer Location (Kanto) public const int Transfer1 = 30013; @@ -96,6 +100,11 @@ public static class Locations public const int BugCatchingContest4 = 207; + /// + /// -1 + /// + public const int Default8bNone = -1; + public static int TradedEggLocationNPC(int generation) => generation switch { 1 => LinkTrade2NPC, @@ -106,10 +115,11 @@ public static class Locations _ => 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 IsEggLocationBred4(int loc, GameVersion ver) 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, + }; } } diff --git a/PKHeX.Core/Legality/Tables/Tables.cs b/PKHeX.Core/Legality/Tables/Tables.cs index 0e53ed939dc..c5b07b7910f 100644 --- a/PKHeX.Core/Legality/Tables/Tables.cs +++ b/PKHeX.Core/Legality/Tables/Tables.cs @@ -127,6 +127,8 @@ public static bool IsValidSketch(int move, int generation) 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; } diff --git a/PKHeX.Core/Legality/Tables/Tables8bs.cs b/PKHeX.Core/Legality/Tables/Tables8bs.cs new file mode 100644 index 00000000000..a8b7274f72c --- /dev/null +++ b/PKHeX.Core/Legality/Tables/Tables8bs.cs @@ -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, + }; + + /// + /// Moves that are kill + /// + public static readonly HashSet 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 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, + }; + } +} diff --git a/PKHeX.Core/Legality/Verifiers/Ball/BallBreedLegality.cs b/PKHeX.Core/Legality/Verifiers/Ball/BallBreedLegality.cs index e537d2f6cc1..a8572e5cd64 100644 --- a/PKHeX.Core/Legality/Verifiers/Ball/BallBreedLegality.cs +++ b/PKHeX.Core/Legality/Verifiers/Ball/BallBreedLegality.cs @@ -983,5 +983,34 @@ internal static class BallBreedLegality (int)Voltorb, // Voltorb (int)Flabébé + (3 << 11), // Flabébé-Blue }; + + /// + /// All egg species that can inherit a Safar Ball when bred in BD/SP. + /// + internal static readonly HashSet 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, + }; } } \ No newline at end of file diff --git a/PKHeX.Core/Legality/Verifiers/Ball/BallUseLegality.cs b/PKHeX.Core/Legality/Verifiers/Ball/BallUseLegality.cs index 912c357dc92..a45f405a7f4 100644 --- a/PKHeX.Core/Legality/Verifiers/Ball/BallUseLegality.cs +++ b/PKHeX.Core/Legality/Verifiers/Ball/BallUseLegality.cs @@ -15,6 +15,7 @@ internal static class BallUseLegality 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(), }; diff --git a/PKHeX.Core/Legality/Verifiers/Ball/BallVerifier.cs b/PKHeX.Core/Legality/Verifiers/Ball/BallVerifier.cs index 12105d1457d..b17584732b7 100644 --- a/PKHeX.Core/Legality/Verifiers/Ball/BallVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/Ball/BallVerifier.cs @@ -36,6 +36,8 @@ private CheckResult VerifyBall(LegalityAnalysis data) 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 @@ private CheckResult VerifyBallEgg(LegalityAnalysis data) { 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 @@ private CheckResult VerifyBallEggGen7(LegalityAnalysis data) 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; diff --git a/PKHeX.Core/Legality/Verifiers/ContestStatVerifier.cs b/PKHeX.Core/Legality/Verifiers/ContestStatVerifier.cs index 0cf310147b3..e0efdb8885f 100644 --- a/PKHeX.Core/Legality/Verifiers/ContestStatVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/ContestStatVerifier.cs @@ -26,6 +26,7 @@ public override void Verify(LegalityAnalysis data) 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, }; } diff --git a/PKHeX.Core/Legality/Verifiers/HistoryVerifier.cs b/PKHeX.Core/Legality/Verifiers/HistoryVerifier.cs index ebd76189f87..807aa9de490 100644 --- a/PKHeX.Core/Legality/Verifiers/HistoryVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/HistoryVerifier.cs @@ -90,7 +90,7 @@ private void VerifyOTFriendship(LegalityAnalysis data, bool neverOT, int origin, // 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 @@ public static bool GetCanOTHandle(IEncounterTemplate enc, PKM pkm, int generatio 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, diff --git a/PKHeX.Core/Legality/Verifiers/MarkVerifier.cs b/PKHeX.Core/Legality/Verifiers/MarkVerifier.cs index 5ac43cf0d28..eece6a1257a 100644 --- a/PKHeX.Core/Legality/Verifiers/MarkVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/MarkVerifier.cs @@ -186,7 +186,7 @@ private void VerifyShedinjaAffixed(LegalityAnalysis data, sbyte affix, PK8 pk8) 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; diff --git a/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs b/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs index affe88e3de3..a2971c67041 100644 --- a/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/MemoryVerifier.cs @@ -14,6 +14,12 @@ public sealed class MemoryVerifier : Verifier 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 @@ private static bool CanHaveMemoryForOT(PKM pkm, int origin, int memory) 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 diff --git a/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs b/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs index 1678c221112..3d575b352be 100644 --- a/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/MiscVerifier.cs @@ -49,7 +49,7 @@ public override void Verify(LegalityAnalysis data) switch (pkm) { - case PK7 {ResortEventStatus: >= 20}: + case PK7 {ResortEventStatus: >= ResortEventState.MAX}: data.AddLine(GetInvalid(LTransferBad)); break; case PB7 pb7: @@ -58,6 +58,9 @@ public override void Verify(LegalityAnalysis data) case PK8 pk8: VerifySWSHStats(data, pk8); break; + case PB8 pb8: + VerifyBDSPStats(data, pb8); + break; } if (pkm.Format >= 6) @@ -90,6 +93,23 @@ public override void Verify(LegalityAnalysis data) 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 @@ private static void VerifyMiscEggCommon(LegalityAnalysis data) 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 @@ private static void VerifyReceivability(LegalityAnalysis data, MysteryGift g) { 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 @@ private void VerifySWSHStats(LegalityAnalysis data, PK8 pk8) 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 @@ private void VerifySWSHStats(LegalityAnalysis data, PK8 pk8) 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) diff --git a/PKHeX.Core/Legality/Verifiers/NicknameVerifier.cs b/PKHeX.Core/Legality/Verifiers/NicknameVerifier.cs index d115f8bfdd6..1f1dc338e97 100644 --- a/PKHeX.Core/Legality/Verifiers/NicknameVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/NicknameVerifier.cs @@ -34,6 +34,8 @@ public override void Verify(LegalityAnalysis data) if (enc is ILangNicknamedTemplate n) { VerifyFixedNicknameEncounter(data, n, enc, pkm, nickname); + if (pkm.IsEgg) + VerifyNicknameEgg(data); return; } @@ -244,8 +246,8 @@ private static void VerifyNicknameEgg(LegalityAnalysis data) 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 @@ private static void VerifyNicknameTrade(LegalityAnalysis data, EncounterTrade t) 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 @@ private static void VerifyTrade4(LegalityAnalysis data, EncounterTrade t) 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) diff --git a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifier.cs b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifier.cs index 579df5694b4..e3152097a68 100644 --- a/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/Ribbons/RibbonVerifier.cs @@ -26,7 +26,7 @@ public override void Verify(LegalityAnalysis data) 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 @@ public override void Verify(LegalityAnalysis data) } } - private static List GetIncorrectRibbons(PKM pkm, IEncounterTemplate enc) + private static List GetIncorrectRibbons(PKM pkm, IReadOnlyList[] evos, IEncounterTemplate enc) { List missingRibbons = new(); List 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 @@ private static bool GetIncorrectRibbonsEgg(PKM pkm, IEncounterTemplate enc) return false; } - internal static IEnumerable GetRibbonResults(PKM pkm, IEncounterTemplate enc) + internal static IEnumerable GetRibbonResults(PKM pkm, IReadOnlyList[] evos, IEncounterTemplate enc) { - return GetInvalidRibbons(pkm, enc) + return GetInvalidRibbons(pkm, evos, enc) .Concat(GetInvalidRibbonsEvent1(pkm, enc)) .Concat(GetInvalidRibbonsEvent2(pkm, enc)); } - private static IEnumerable GetInvalidRibbons(PKM pkm, IEncounterTemplate enc) + private static IEnumerable GetInvalidRibbons(PKM pkm, IReadOnlyList[] 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 @@ private static IEnumerable GetInvalidRibbons(PKM pkm, IEncounterTe 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 @@ private static IEnumerable GetMissingContestRibbons(IReadOnlyList< } } - private static IEnumerable GetInvalidRibbons4Any(PKM pkm, IRibbonSetCommon4 s4, int gen) + private static IEnumerable GetInvalidRibbons4Any(PKM pkm, IReadOnlyList[] 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 @@ private static IEnumerable GetInvalidRibbons7Any(PKM pkm, IRibbonS private static IEnumerable 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 @@ private static IEnumerable GetInvalidRibbons8Any(PKM pkm, IRibbonS } } } + + // 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 @@ private static IEnumerable GetInvalidRibbonsNone(IReadOnlyList GetInvalidRibbonsNoneSkipIndex(IReadOnlyList bits, IReadOnlyList 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 @@ private static bool IsAllowedBattleFrontier(int species, int form, int gen) return IsAllowedBattleFrontier(species); } - private static bool CanHaveFootprintRibbon(PKM pkm, int gen) + private static bool CanHaveFootprintRibbon(PKM pkm, IReadOnlyList[] 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 @@ private static bool CanHaveRibbonVictory(PKM pkm, int gen) { 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, + }; } } diff --git a/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs b/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs index ca4e2a5481d..3d94c8d680b 100644 --- a/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/TransferVerifier.cs @@ -125,9 +125,16 @@ public void VerifyTransferLegalityG4(LegalityAnalysis data) 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 @@ public void VerifyTransferLegalityG8(LegalityAnalysis data) } } + // 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) diff --git a/PKHeX.Core/MysteryGifts/MysteryGift.cs b/PKHeX.Core/MysteryGifts/MysteryGift.cs index 9dd00cf3ea8..0c83f55fa20 100644 --- a/PKHeX.Core/MysteryGifts/MysteryGift.cs +++ b/PKHeX.Core/MysteryGifts/MysteryGift.cs @@ -16,7 +16,7 @@ public abstract class MysteryGift : IEncounterable, IMoveset, IRelearn, ILocatio /// A boolean indicating whether or not the given length is valid for a mystery gift. public static bool IsMysteryGift(long len) => Sizes.Contains((int)len); - private static readonly HashSet Sizes = new() { WC8.Size, WC6Full.Size, WC6.Size, PGF.Size, PGT.Size, PCD.Size }; + private static readonly HashSet Sizes = new() { WB8.Size, WC8.Size, WC6Full.Size, WC6.Size, PGF.Size, PGT.Size, PCD.Size }; /// /// Converts the given data to a . @@ -35,6 +35,7 @@ public abstract class MysteryGift : IEncounterable, IMoveset, IRelearn, ILocatio 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 @@ public abstract class MysteryGift : IEncounterable, IMoveset, IRelearn, ILocatio 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), diff --git a/PKHeX.Core/MysteryGifts/WB8.cs b/PKHeX.Core/MysteryGifts/WB8.cs new file mode 100644 index 00000000000..da581769d4d --- /dev/null +++ b/PKHeX.Core/MysteryGifts/WB8.cs @@ -0,0 +1,750 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using static PKHeX.Core.RibbonIndex; + +namespace PKHeX.Core +{ + /// + /// Generation 8b Mystery Gift Template File + /// + 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 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 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 + } +} diff --git a/PKHeX.Core/MysteryGifts/WC8.cs b/PKHeX.Core/MysteryGifts/WC8.cs index eef88b03cf0..153ba1ec005 100644 --- a/PKHeX.Core/MysteryGifts/WC8.cs +++ b/PKHeX.Core/MysteryGifts/WC8.cs @@ -759,6 +759,8 @@ public override bool IsMatchExact(PKM pkm, DexLevel evo) 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; diff --git a/PKHeX.Core/PKM/G8PKM.cs b/PKHeX.Core/PKM/G8PKM.cs new file mode 100644 index 00000000000..d2d1f5ec3f5 --- /dev/null +++ b/PKHeX.Core/PKM/G8PKM.cs @@ -0,0 +1,504 @@ +using System; + +namespace PKHeX.Core +{ + /// Generation 8 format. + 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 Nickname_Trash { get => Data.AsSpan(0x58, 24); set { if (value.Length == 24) value.CopyTo(Data.AsSpan(0x58)); } } + public override Span HT_Trash { get => Data.AsSpan(0xA8, 24); set { if (value.Length == 24) value.CopyTo(Data.AsSpan(0xA8)); } } + public override Span 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); + } + } +} diff --git a/PKHeX.Core/PKM/PB8.cs b/PKHeX.Core/PKM/PB8.cs new file mode 100644 index 00000000000..d0581050556 --- /dev/null +++ b/PKHeX.Core/PKM/PB8.cs @@ -0,0 +1,110 @@ +using System.Collections.Generic; + +namespace PKHeX.Core +{ + /// Generation 8 format. + 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 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; + } +} diff --git a/PKHeX.Core/PKM/PK7.cs b/PKHeX.Core/PKM/PK7.cs index 9cdcf487f2c..baf57a6234e 100644 --- a/PKHeX.Core/PKM/PK7.cs +++ b/PKHeX.Core/PKM/PK7.cs @@ -109,7 +109,7 @@ public override uint PID 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 @@ public PK8 ConvertToPK8() 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, + } } diff --git a/PKHeX.Core/PKM/PK8.cs b/PKHeX.Core/PKM/PK8.cs index 6cb50db886f..6e6cff1ab96 100644 --- a/PKHeX.Core/PKM/PK8.cs +++ b/PKHeX.Core/PKM/PK8.cs @@ -4,9 +4,7 @@ namespace PKHeX.Core { /// Generation 8 format. - 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 @@ public sealed class PK8 : PKM, }; public override IReadOnlyList 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 Nickname_Trash { get => Data.AsSpan(0x58, 24); set { if (value.Length == 24) value.CopyTo(Data.AsSpan(0x58)); } } - public override Span HT_Trash { get => Data.AsSpan(0xA8, 24); set { if (value.Length == 24) value.CopyTo(Data.AsSpan(0xA8)); } } - public override Span 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 @@ public void Trade(ITrainerInfo tr, int Day = 1, int Month = 1, int Year = 2015) 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 @@ private void TradeHT(ITrainerInfo tr) 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); - } } -} \ No newline at end of file +} diff --git a/PKHeX.Core/PKM/PKM.cs b/PKHeX.Core/PKM/PKM.cs index 201b88eae47..a8b168ad770 100644 --- a/PKHeX.Core/PKM/PKM.cs +++ b/PKHeX.Core/PKM/PKM.cs @@ -289,12 +289,13 @@ private void SetID7(int sid7, int tid7) 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 @@ public virtual int HPType } // 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; diff --git a/PKHeX.Core/PKM/Shared/IDynamaxLevel.cs b/PKHeX.Core/PKM/Shared/IDynamaxLevel.cs index 3da777adffa..2307f125990 100644 --- a/PKHeX.Core/PKM/Shared/IDynamaxLevel.cs +++ b/PKHeX.Core/PKM/Shared/IDynamaxLevel.cs @@ -13,6 +13,8 @@ public static bool CanHaveDynamaxLevel(this IDynamaxLevel _, PKM pkm) { if (pkm.IsEgg) return false; + if (pkm.BDSP) + return false; return CanHaveDynamaxLevel(pkm.Species); } diff --git a/PKHeX.Core/PKM/Shared/IFixedOTFriendship.cs b/PKHeX.Core/PKM/Shared/IFixedOTFriendship.cs new file mode 100644 index 00000000000..4ab700efc8d --- /dev/null +++ b/PKHeX.Core/PKM/Shared/IFixedOTFriendship.cs @@ -0,0 +1,10 @@ +namespace PKHeX.Core +{ + /// + /// Exposes a friendship value with the original trainer. + /// + public interface IFixedOTFriendship + { + int OT_Friendship { get; } + } +} diff --git a/PKHeX.Core/PKM/Util/PKMConverter.cs b/PKHeX.Core/PKM/Util/PKMConverter.cs index 4f718de6f54..acaae03dab3 100644 --- a/PKHeX.Core/PKM/Util/PKMConverter.cs +++ b/PKHeX.Core/PKM/Util/PKMConverter.cs @@ -117,11 +117,19 @@ public static int GetPKMDataFormat(byte[] data) 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); + } + /// /// Checks if the input PK6 file is really a PK7, if so, updates the object. /// @@ -432,6 +440,7 @@ public static PKM GetBlank(Type type) { 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), }; diff --git a/PKHeX.Core/PKM/Util/PKX.cs b/PKHeX.Core/PKM/Util/PKX.cs index 3b0249ebbb8..7b2c6ccfe1f 100644 --- a/PKHeX.Core/PKM/Util/PKX.cs +++ b/PKHeX.Core/PKM/Util/PKX.cs @@ -199,6 +199,7 @@ public static int GetGenderFromPID(int species, uint pid) }; internal const string ExtensionPB7 = "pb7"; + internal const string ExtensionPB8 = "pb8"; /// /// Gets an array of valid file extensions. @@ -221,6 +222,8 @@ public static string[] GetPKMExtensions(int maxGeneration = Generation) 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(); } diff --git a/PKHeX.Core/PersonalInfo/PersonalInfoBDSP.cs b/PKHeX.Core/PersonalInfo/PersonalInfoBDSP.cs new file mode 100644 index 00000000000..0de1f5e38df --- /dev/null +++ b/PKHeX.Core/PersonalInfo/PersonalInfoBDSP.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.Generic; + +namespace PKHeX.Core +{ + /// + /// class with values from the games. + /// + 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 Items + { + get => new[] { Item1, Item2, Item3 }; + set + { + if (value.Count != 3) return; + Item1 = value[0]; + Item2 = value[1]; + Item3 = value[2]; + } + } + + public override IReadOnlyList 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; + + /// + /// Checks if the entry shows up in any of the built-in Pokédex. + /// + public bool IsInDex => PokeDexIndex != 0; + } +} diff --git a/PKHeX.Core/PersonalInfo/PersonalTable.cs b/PKHeX.Core/PersonalInfo/PersonalTable.cs index e85c8f11a97..83cbe9fc7fe 100644 --- a/PKHeX.Core/PersonalInfo/PersonalTable.cs +++ b/PKHeX.Core/PersonalInfo/PersonalTable.cs @@ -12,6 +12,11 @@ namespace PKHeX.Core /// public class PersonalTable { + /// + /// Personal Table used in . + /// + public static readonly PersonalTable BDSP = GetTable("bdsp", GameVersion.BDSP); + /// /// Personal Table used in . /// @@ -124,7 +129,8 @@ private static PersonalTable GetTable(string game, GameVersion format) 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 @@ private static PersonalTable GetTable(string game, GameVersion format) GameVersion.ORAS => PersonalInfoORAS.SIZE, GameVersion.SM or GameVersion.USUM or GameVersion.GG => PersonalInfoSM.SIZE, GameVersion.SWSH => PersonalInfoSWSH.SIZE, + GameVersion.BDSP => PersonalInfoBDSP.SIZE, _ => -1, }; diff --git a/PKHeX.Core/Resources/byte/eggmove/eggmove_bdsp.pkl b/PKHeX.Core/Resources/byte/eggmove/eggmove_bdsp.pkl new file mode 100644 index 00000000000..cc6ca7a9951 Binary files /dev/null and b/PKHeX.Core/Resources/byte/eggmove/eggmove_bdsp.pkl differ diff --git a/PKHeX.Core/Resources/byte/evolve/evos_bs.pkl b/PKHeX.Core/Resources/byte/evolve/evos_bs.pkl new file mode 100644 index 00000000000..1dde683e1e9 Binary files /dev/null and b/PKHeX.Core/Resources/byte/evolve/evos_bs.pkl differ diff --git a/PKHeX.Core/Resources/byte/levelup/lvlmove_bdsp.pkl b/PKHeX.Core/Resources/byte/levelup/lvlmove_bdsp.pkl new file mode 100644 index 00000000000..b6bee6ecbe6 Binary files /dev/null and b/PKHeX.Core/Resources/byte/levelup/lvlmove_bdsp.pkl differ diff --git a/PKHeX.Core/Resources/byte/personal/personal_bdsp b/PKHeX.Core/Resources/byte/personal/personal_bdsp new file mode 100644 index 00000000000..25e7ec95563 Binary files /dev/null and b/PKHeX.Core/Resources/byte/personal/personal_bdsp differ diff --git a/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_de.txt b/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_de.txt new file mode 100644 index 00000000000..14275038ec1 --- /dev/null +++ b/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_de.txt @@ -0,0 +1,8 @@ +Salla +Plaupa +Pollo +Pador +Hilary +Norbert +Mara +The Master \ No newline at end of file diff --git a/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_en.txt b/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_en.txt new file mode 100644 index 00000000000..e2c064624c5 --- /dev/null +++ b/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_en.txt @@ -0,0 +1,8 @@ +Kazza +Charap +Gaspar +Foppa +Hilary +Norton +Mindy +Meister \ No newline at end of file diff --git a/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_es.txt b/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_es.txt new file mode 100644 index 00000000000..4d916aa0079 --- /dev/null +++ b/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_es.txt @@ -0,0 +1,8 @@ +Kazza +Charap +Gaspar +Foppa +Amanda +Alfio +Regla +Meister \ No newline at end of file diff --git a/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_fr.txt b/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_fr.txt new file mode 100644 index 00000000000..de3eece932e --- /dev/null +++ b/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_fr.txt @@ -0,0 +1,8 @@ +Kazou +Pijouk +Trumi +Bloupi +Paula +Pierre +Marlène +Meister \ No newline at end of file diff --git a/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_it.txt b/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_it.txt new file mode 100644 index 00000000000..32ad3bda9e6 --- /dev/null +++ b/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_it.txt @@ -0,0 +1,8 @@ +Keikei +Charap +Gaspar +Mossy +Hilary +Norton +Mindy +The Master \ No newline at end of file diff --git a/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_ja.txt b/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_ja.txt new file mode 100644 index 00000000000..72892c2105a --- /dev/null +++ b/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_ja.txt @@ -0,0 +1,8 @@ +ケーケー +ペッチャラ +ドロりん +ポッちゃん +ハッシー +ノブリン +ミナッチ +マイスター \ No newline at end of file diff --git a/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_ko.txt b/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_ko.txt new file mode 100644 index 00000000000..9c492a12f23 --- /dev/null +++ b/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_ko.txt @@ -0,0 +1,8 @@ +케이케이 +조자리 +고옹이 +Pador +에이 +신달 +미나 +Master \ No newline at end of file diff --git a/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_zh.txt b/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_zh.txt new file mode 100644 index 00000000000..7e795c9ca36 --- /dev/null +++ b/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_zh.txt @@ -0,0 +1,8 @@ +凯凯 +聒查拉 +小无形 +Pador +赫西 +诺布林 +米娜琦 +Master \ No newline at end of file diff --git a/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_zh2.txt b/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_zh2.txt new file mode 100644 index 00000000000..899a4e488c1 --- /dev/null +++ b/PKHeX.Core/Resources/legality/gen8/text_tradebdsp_zh2.txt @@ -0,0 +1,8 @@ +凱凱 +小聒聒 +無形仔 +Pador +荷希 +諾布林 +美琦 +Master \ No newline at end of file diff --git a/PKHeX.Core/Resources/legality/mgdb/wb8.pkl b/PKHeX.Core/Resources/legality/mgdb/wb8.pkl new file mode 100644 index 00000000000..15855533a40 Binary files /dev/null and b/PKHeX.Core/Resources/legality/mgdb/wb8.pkl differ diff --git a/PKHeX.Core/Resources/legality/mgdb/wc8.pkl b/PKHeX.Core/Resources/legality/mgdb/wc8.pkl index 01d1486ac22..391baced86d 100644 Binary files a/PKHeX.Core/Resources/legality/mgdb/wc8.pkl and b/PKHeX.Core/Resources/legality/mgdb/wc8.pkl differ diff --git a/PKHeX.Core/Resources/legality/wild/Gen8/encounter_bd.pkl b/PKHeX.Core/Resources/legality/wild/Gen8/encounter_bd.pkl new file mode 100644 index 00000000000..5e7630373d9 Binary files /dev/null and b/PKHeX.Core/Resources/legality/wild/Gen8/encounter_bd.pkl differ diff --git a/PKHeX.Core/Resources/legality/wild/Gen8/encounter_sp.pkl b/PKHeX.Core/Resources/legality/wild/Gen8/encounter_sp.pkl new file mode 100644 index 00000000000..f904d6b2c43 Binary files /dev/null and b/PKHeX.Core/Resources/legality/wild/Gen8/encounter_sp.pkl differ diff --git a/PKHeX.Core/Resources/legality/wild/Gen8/underground_bd.pkl b/PKHeX.Core/Resources/legality/wild/Gen8/underground_bd.pkl new file mode 100644 index 00000000000..cbe2a8dfdba Binary files /dev/null and b/PKHeX.Core/Resources/legality/wild/Gen8/underground_bd.pkl differ diff --git a/PKHeX.Core/Resources/legality/wild/Gen8/underground_sp.pkl b/PKHeX.Core/Resources/legality/wild/Gen8/underground_sp.pkl new file mode 100644 index 00000000000..808360d43f6 Binary files /dev/null and b/PKHeX.Core/Resources/legality/wild/Gen8/underground_sp.pkl differ diff --git a/PKHeX.Core/Resources/text/items/text_Items_de.txt b/PKHeX.Core/Resources/text/items/text_Items_de.txt index cdaf774be28..95d64ffa62a 100644 --- a/PKHeX.Core/Resources/text/items/text_Items_de.txt +++ b/PKHeX.Core/Resources/text/items/text_Items_de.txt @@ -1605,4 +1605,219 @@ Phantomkarotte Dyna-Erz Karottensamen Fähigk.-Pflaster -Zügel des Bundes \ No newline at end of file +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 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/items/text_Items_en.txt b/PKHeX.Core/Resources/text/items/text_Items_en.txt index f3712cc7239..c14ba22a57c 100644 --- a/PKHeX.Core/Resources/text/items/text_Items_en.txt +++ b/PKHeX.Core/Resources/text/items/text_Items_en.txt @@ -1605,4 +1605,219 @@ Shaderoot Carrot Dynite Ore Carrot Seeds Ability Patch -Reins of Unity \ No newline at end of file +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 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/items/text_Items_es.txt b/PKHeX.Core/Resources/text/items/text_Items_es.txt index 78fa2399568..db21705c8df 100644 --- a/PKHeX.Core/Resources/text/items/text_Items_es.txt +++ b/PKHeX.Core/Resources/text/items/text_Items_es.txt @@ -1605,4 +1605,219 @@ Zanahoria Oscura Maxinium Sem. Zanahoria Parche Habilidad -Riendas Unión \ No newline at end of file +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 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/items/text_Items_fr.txt b/PKHeX.Core/Resources/text/items/text_Items_fr.txt index 79e9ce36b5d..42d287e556c 100644 --- a/PKHeX.Core/Resources/text/items/text_Items_fr.txt +++ b/PKHeX.Core/Resources/text/items/text_Items_fr.txt @@ -1605,4 +1605,219 @@ Carotte Sombre Dynamaxium Graines Carotte Patch Talent -Rênes de l’Unité \ No newline at end of file +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 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/items/text_Items_it.txt b/PKHeX.Core/Resources/text/items/text_Items_it.txt index bb21440ae62..224d6e95975 100644 --- a/PKHeX.Core/Resources/text/items/text_Items_it.txt +++ b/PKHeX.Core/Resources/text/items/text_Items_it.txt @@ -1605,4 +1605,219 @@ Carota oscura Rocciamax Semi di carota Cerotto abilità -Briglie legame \ No newline at end of file +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 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/items/text_Items_ja.txt b/PKHeX.Core/Resources/text/items/text_Items_ja.txt index fd8afcd6a5a..7a0cc3d9675 100644 --- a/PKHeX.Core/Resources/text/items/text_Items_ja.txt +++ b/PKHeX.Core/Resources/text/items/text_Items_ja.txt @@ -1605,4 +1605,219 @@ マックスこうせき にんじんのタネ とくせいパッチ -キズナのタヅナ \ No newline at end of file +キズナのタヅナ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +なぞのかけらS +なぞのかけらL +あなほりドリル +カントーのせきばん +ジョウトのせきばん +こころのせきばん +にじのせきばん +あらしのせきばん +たいかいのせきばん +たいりくのせきばん +てんくうのせきばん +いでんしのせきばん +みちびきのせきばん +やぶれたせきばん +DSプレイヤー \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/items/text_Items_ko.txt b/PKHeX.Core/Resources/text/items/text_Items_ko.txt index 9384a322859..890884a26b1 100644 --- a/PKHeX.Core/Resources/text/items/text_Items_ko.txt +++ b/PKHeX.Core/Resources/text/items/text_Items_ko.txt @@ -1605,4 +1605,219 @@ PP회복캡슐토이 맥스광석 당근씨 특성패치 -유대의고삐 \ No newline at end of file +유대의고삐 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +수수께끼의조각S +수수께끼의조각L +구멍파기드릴 +관동의석판 +성도의석판 +마음의석판 +무지개의석판 +폭풍의석판 +대해의석판 +대륙의석판 +천공의석판 +유전자의석판 +인도의석판 +깨어진석판 +DS플레이어 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/items/text_Items_zh.txt b/PKHeX.Core/Resources/text/items/text_Items_zh.txt index 46882061ec8..3291033d9b3 100644 --- a/PKHeX.Core/Resources/text/items/text_Items_zh.txt +++ b/PKHeX.Core/Resources/text/items/text_Items_zh.txt @@ -1605,4 +1605,219 @@ 极矿石 萝卜种子 特性膏药 -牵绊缰绳 \ No newline at end of file +牵绊缰绳 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +谜之碎片S +谜之碎片L +挖洞钻 +关都石板 +城都石板 +心之石板 +彩虹石板 +暴风石板 +大海石板 +大陆石板 +天空石板 +基因石板 +引导石板 +毁坏石板 +DS播放器 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_de.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_de.txt new file mode 100644 index 00000000000..8ebf919c673 --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_de.txt @@ -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 diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_en.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_en.txt new file mode 100644 index 00000000000..9023e47ad8b --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_en.txt @@ -0,0 +1,658 @@ +Jubilife City +Jubilife City +Jubilife City +Jubilife City +Jubilife City +Jubilife City +Jubilife City +Jubilife City +Jubilife City +Jubilife City +Jubilife City +Jubilife City +Jubilife City +Jubilife City +Jubilife City +Jubilife City +Jubilife City +Jubilife City +Jubilife City +Jubilife City +Jubilife City +Jubilife City +Jubilife City +Jubilife City +Canalave City +Canalave City +Canalave Gym +Canalave City +Canalave City +Canalave City +Canalave City +Canalave City +Canalave City +Canalave City +Canalave City +Canalave City +Canalave City +Canalave City +Oreburgh City +Oreburgh City +Oreburgh Gym +Oreburgh City +Oreburgh City +Oreburgh City +Oreburgh City +Oreburgh City +Oreburgh City +Oreburgh City +Oreburgh City +Oreburgh City +Oreburgh City +Oreburgh City +Oreburgh City +Oreburgh City +Eterna City +Eterna City +Eterna Gym +Eterna Gym +Eterna City +Eterna City +Eterna City +Eterna City +Eterna City +Eterna City +Eterna City +Eterna City +Eterna City +Eterna City +Eterna City +Eterna City +Eterna City +Eterna City +Eterna City +Eterna City +Hearthome City +Hearthome City +Hearthome Gym +Hearthome Gym +Hearthome Gym +Hearthome Gym +Hearthome Gym +Hearthome Gym +Hearthome Gym +Hearthome Gym +Hearthome Gym +Hearthome Gym +Hearthome Gym +Hearthome Gym +Hearthome Gym +Hearthome City +Hearthome City +Hearthome City +Hearthome City +Hearthome City +Hearthome City +Hearthome City +Hearthome City +Hearthome City +Hearthome City +Hearthome City +Hearthome City +Hearthome City +Hearthome City +Hearthome City +Hearthome City +Hearthome City +Hearthome City +Hearthome City +Hearthome City +Hearthome City +Pastoria City +Pastoria City +Pastoria Gym +Pastoria City +Pastoria City +Pastoria City +Pastoria City +Pastoria City +Pastoria City +Pastoria City +Pastoria City +Pastoria City +Pastoria City +Veilstone City +Veilstone Gym +Veilstone City +Veilstone City +Veilstone City +Veilstone City +Veilstone City +Veilstone City +Veilstone City +Veilstone City +Veilstone City +Veilstone City +Veilstone City +Veilstone City +Veilstone City +Veilstone City +Veilstone City +Veilstone City +Veilstone City +Sunyshore City +Sunyshore City +Sunyshore Gym +Sunyshore Gym +Sunyshore Gym +Sunyshore City +Sunyshore City +Sunyshore City +Sunyshore City +Sunyshore City +Sunyshore City +Sunyshore City +Sunyshore City +Sunyshore City +Sunyshore City +Sunyshore City +Sunyshore City +Snowpoint City +Snowpoint City +Snowpoint Gym +Snowpoint City +Snowpoint City +Snowpoint City +Snowpoint City +Snowpoint City +Pokémon League +Pokémon League +Pokémon League +Pokémon League +Pokémon League +Pokémon League +Pokémon League +Pokémon League +Pokémon League +Pokémon League +Pokémon League +Pokémon League +Pokémon League +Pokémon League +Pokémon League +Pokémon League +Pokémon League +Pokémon League +Pokémon League +Fight Area +Fight Area +Fight Area +Fight Area +Fight Area +Fight Area +Fight Area +Fight Area +Fight Area +Oreburgh Mine +Oreburgh Mine +Valley Windworks +Valley Windworks +Eterna Forest +Eterna Forest +Fuego Ironworks +Fuego Ironworks +Mount Coronet +Mount Coronet +Mount Coronet +Mount Coronet +Mount Coronet +Mount Coronet +Mount Coronet +Mount Coronet +Mount Coronet +Mount Coronet +Mount Coronet +Mount Coronet +Mount Coronet +Spear Pillar +Spear Pillar +Hall of Origin +Great Marsh +Great Marsh +Great Marsh +Great Marsh +Great Marsh +Great Marsh +Solaceon Ruins +Solaceon Ruins +Solaceon Ruins +Solaceon Ruins +Solaceon Ruins +Solaceon Ruins +Solaceon Ruins +Solaceon Ruins +Solaceon Ruins +Solaceon Ruins +Solaceon Ruins +Solaceon Ruins +Solaceon Ruins +Solaceon Ruins +Solaceon Ruins +Solaceon Ruins +Solaceon Ruins +Solaceon Ruins +Solaceon Ruins +Victory Road +Victory Road +Victory Road +Victory Road +Victory Road +Victory Road +Ramanas Park +Amity Square +Ravaged Path +Floaroma Meadow +Floaroma Meadow +Oreburgh Gate +Oreburgh Gate +Fullmoon Island +Fullmoon Island +Stark Mountain +Stark Mountain +Stark Mountain +Stark Mountain +Sendoff Spring +Turnback Cave +Turnback Cave +Turnback Cave +Turnback Cave +Turnback Cave +Turnback Cave +Turnback Cave +Turnback Cave +Turnback Cave +Turnback Cave +Turnback Cave +Turnback Cave +Turnback Cave +Turnback Cave +Turnback Cave +Turnback Cave +Turnback Cave +Turnback Cave +Turnback Cave +Turnback Cave +Turnback Cave +Flower Paradise +Snowpoint Temple +Snowpoint Temple +Snowpoint Temple +Snowpoint Temple +Snowpoint Temple +Snowpoint Temple +Wayward Cave +Wayward Cave +Ruin Maniac Cave +Ruin Maniac Cave +Maniac Tunnel +Trophy Garden +Iron Island +Iron Island +Iron Island +Iron Island +Iron Island +Iron Island +Iron Island +Iron Island +Old Chateau +Old Chateau +Old Chateau +Old Chateau +Old Chateau +Old Chateau +Old Chateau +Old Chateau +Old Chateau +Galactic HQ +Galactic HQ +Galactic HQ +Galactic HQ +Galactic HQ +Galactic HQ +Galactic HQ +Galactic HQ +Lake Verity +Lake Verity +Lake Verity +Lake Valor +Lake Valor +Lake Valor +Lake Acuity +Lake Acuity +Lake Acuity +Newmoon Island +Newmoon Island +Battle Park +Battle Park +Battle Park +Battle Park +Battle Park +Battle Tower +Battle Tower +Battle Tower +Battle Tower +Battle Tower +Battle Tower +Mystery Zone +Verity Lakefront +Valor Lakefront +Valor Lakefront +Valor Lakefront +Valor Lakefront +Acuity Lakefront +Spring Path +Mystery Zone +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 +Mystery Zone +Twinleaf Town +Twinleaf Town +Twinleaf Town +Twinleaf Town +Twinleaf Town +Twinleaf Town +Twinleaf Town +Sandgem Town +Sandgem Town +Sandgem Town +Sandgem Town +Sandgem Town +Sandgem Town +Sandgem Town +Sandgem Town +Sandgem Town +Floaroma Town +Floaroma Town +Floaroma Town +Floaroma Town +Floaroma Town +Floaroma Town +Floaroma Town +Floaroma Town +Solaceon Town +Solaceon Town +Solaceon Town +Solaceon Town +Solaceon Town +Solaceon Town +Solaceon Town +Solaceon Town +Solaceon Town +Solaceon Town +Celestic Town +Celestic Town +Celestic Town +Celestic Town +Celestic Town +Celestic Town +Celestic Town +Celestic Town +Celestic Town +Survival Area +Survival Area +Survival Area +Survival Area +Survival Area +Survival Area +Survival Area +Survival Area +Resort Area +Resort Area +Resort Area +Resort Area +Resort Area +Resort Area +Resort Area +Resort Area +Resort Area +Resort Area +Mystery Zone +Mystery Zone +Route 220 +Route 223 +Route 226 +Route 226 +Route 230 +Seabreak Path +Mystery Zone +Mystery Zone +Mystery Zone +Eterna City +Ramanas Park +Ramanas Park +Ramanas Park +Ramanas Park +Ramanas Park +Ramanas Park +Ramanas Park +Ramanas Park +Ramanas Park +Ramanas Park +Ramanas Park +Ramanas Park +Ramanas Park +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Ramanas Park +Grand Underground +Grand Underground +Grand Underground +Grand Underground +Ramanas Park +Ramanas Park +Jubilife City + + + + + + + + + + + + + + + + + + + + + +Ramanas Park +Ramanas Park +Ramanas Park +Ramanas Park +Ramanas Park +Ramanas Park +Ramanas Park +Ramanas Park +Ramanas Park +Ramanas Park diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_es.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_es.txt new file mode 100644 index 00000000000..53924632544 --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_es.txt @@ -0,0 +1,658 @@ +Ciudad Jubileo +Ciudad Jubileo +Ciudad Jubileo +Ciudad Jubileo +Ciudad Jubileo +Ciudad Jubileo +Ciudad Jubileo +Ciudad Jubileo +Ciudad Jubileo +Ciudad Jubileo +Ciudad Jubileo +Ciudad Jubileo +Ciudad Jubileo +Ciudad Jubileo +Ciudad Jubileo +Ciudad Jubileo +Ciudad Jubileo +Ciudad Jubileo +Ciudad Jubileo +Ciudad Jubileo +Ciudad Jubileo +Ciudad Jubileo +Ciudad Jubileo +Ciudad Jubileo +Ciudad Canal +Ciudad Canal +Gimnasio Canal +Ciudad Canal +Ciudad Canal +Ciudad Canal +Ciudad Canal +Ciudad Canal +Ciudad Canal +Ciudad Canal +Ciudad Canal +Ciudad Canal +Ciudad Canal +Ciudad Canal +Ciudad Pirita +Ciudad Pirita +Gimnasio Pirita +Ciudad Pirita +Ciudad Pirita +Ciudad Pirita +Ciudad Pirita +Ciudad Pirita +Ciudad Pirita +Ciudad Pirita +Ciudad Pirita +Ciudad Pirita +Ciudad Pirita +Ciudad Pirita +Ciudad Pirita +Ciudad Pirita +Ciudad Vetusta +Ciudad Vetusta +Gimnasio Vetusta +Gimnasio Vetusta +Ciudad Vetusta +Ciudad Vetusta +Ciudad Vetusta +Ciudad Vetusta +Ciudad Vetusta +Ciudad Vetusta +Ciudad Vetusta +Ciudad Vetusta +Ciudad Vetusta +Ciudad Vetusta +Ciudad Vetusta +Ciudad Vetusta +Ciudad Vetusta +Ciudad Vetusta +Ciudad Vetusta +Ciudad Vetusta +Ciudad Corazón +Ciudad Corazón +Gimnasio Corazón +Gimnasio Corazón +Gimnasio Corazón +Gimnasio Corazón +Gimnasio Corazón +Gimnasio Corazón +Gimnasio Corazón +Gimnasio Corazón +Gimnasio Corazón +Gimnasio Corazón +Gimnasio Corazón +Gimnasio Corazón +Gimnasio Corazón +Ciudad Corazón +Ciudad Corazón +Ciudad Corazón +Ciudad Corazón +Ciudad Corazón +Ciudad Corazón +Ciudad Corazón +Ciudad Corazón +Ciudad Corazón +Ciudad Corazón +Ciudad Corazón +Ciudad Corazón +Ciudad Corazón +Ciudad Corazón +Ciudad Corazón +Ciudad Corazón +Ciudad Corazón +Ciudad Corazón +Ciudad Corazón +Ciudad Corazón +Ciudad Corazón +Ciudad Pradera +Ciudad Pradera +Gimnasio Pradera +Ciudad Pradera +Ciudad Pradera +Ciudad Pradera +Ciudad Pradera +Ciudad Pradera +Ciudad Pradera +Ciudad Pradera +Ciudad Pradera +Ciudad Pradera +Ciudad Pradera +Ciudad Rocavelo +Gimnasio Rocavelo +Ciudad Rocavelo +Ciudad Rocavelo +Ciudad Rocavelo +Ciudad Rocavelo +Ciudad Rocavelo +Ciudad Rocavelo +Ciudad Rocavelo +Ciudad Rocavelo +Ciudad Rocavelo +Ciudad Rocavelo +Ciudad Rocavelo +Ciudad Rocavelo +Ciudad Rocavelo +Ciudad Rocavelo +Ciudad Rocavelo +Ciudad Rocavelo +Ciudad Rocavelo +Ciudad Marina +Ciudad Marina +Gimnasio Marina +Gimnasio Marina +Gimnasio Marina +Ciudad Marina +Ciudad Marina +Ciudad Marina +Ciudad Marina +Ciudad Marina +Ciudad Marina +Ciudad Marina +Ciudad Marina +Ciudad Marina +Ciudad Marina +Ciudad Marina +Ciudad Marina +Ciudad Puntaneva +Ciudad Puntaneva +Gimnasio Puntaneva +Ciudad Puntaneva +Ciudad Puntaneva +Ciudad Puntaneva +Ciudad Puntaneva +Ciudad Puntaneva +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 Pokémon +Zona Combate +Zona Combate +Zona Combate +Zona Combate +Zona Combate +Zona Combate +Zona Combate +Zona Combate +Zona Combate +Mina Pirita +Mina Pirita +Valle Eólico +Valle Eólico +Bosque Vetusto +Bosque Vetusto +Forja Fuego +Forja Fuego +Monte Corona +Monte Corona +Monte Corona +Monte Corona +Monte Corona +Monte Corona +Monte Corona +Monte Corona +Monte Corona +Monte Corona +Monte Corona +Monte Corona +Monte Corona +Columnas Lanza +Columnas Lanza +Sala del Origen +Gran Pantano +Gran Pantano +Gran Pantano +Gran Pantano +Gran Pantano +Gran Pantano +Ruinas Sosiego +Ruinas Sosiego +Ruinas Sosiego +Ruinas Sosiego +Ruinas Sosiego +Ruinas Sosiego +Ruinas Sosiego +Ruinas Sosiego +Ruinas Sosiego +Ruinas Sosiego +Ruinas Sosiego +Ruinas Sosiego +Ruinas Sosiego +Ruinas Sosiego +Ruinas Sosiego +Ruinas Sosiego +Ruinas Sosiego +Ruinas Sosiego +Ruinas Sosiego +Calle Victoria +Calle Victoria +Calle Victoria +Calle Victoria +Calle Victoria +Calle Victoria +Parque Hansa +Plaza Amistad +Senda Desolada +Prado Aromaflor +Prado Aromaflor +Puerta Pirita +Puerta Pirita +Isla Plenilunio +Isla Plenilunio +Montaña Dura +Montaña Dura +Montaña Dura +Montaña Dura +Fuente Despedida +Cueva Retorno +Cueva Retorno +Cueva Retorno +Cueva Retorno +Cueva Retorno +Cueva Retorno +Cueva Retorno +Cueva Retorno +Cueva Retorno +Cueva Retorno +Cueva Retorno +Cueva Retorno +Cueva Retorno +Cueva Retorno +Cueva Retorno +Cueva Retorno +Cueva Retorno +Cueva Retorno +Cueva Retorno +Cueva Retorno +Cueva Retorno +Paraíso Floral +Templo Puntaneva +Templo Puntaneva +Templo Puntaneva +Templo Puntaneva +Templo Puntaneva +Templo Puntaneva +Cueva Extravío +Cueva Extravío +Mina Ruinamaníaco +Mina Ruinamaníaco +Túnel Ruinamaníaco +Jardín Trofeo +Isla Hierro +Isla Hierro +Isla Hierro +Isla Hierro +Isla Hierro +Isla Hierro +Isla Hierro +Isla Hierro +Vieja Mansión +Vieja Mansión +Vieja Mansión +Vieja Mansión +Vieja Mansión +Vieja Mansión +Vieja Mansión +Vieja Mansión +Vieja Mansión +Base Galaxia +Base Galaxia +Base Galaxia +Base Galaxia +Base Galaxia +Base Galaxia +Base Galaxia +Base Galaxia +Lago Veraz +Lago Veraz +Lago Veraz +Lago Valor +Lago Valor +Lago Valor +Lago Agudeza +Lago Agudeza +Lago Agudeza +Isla Lunanueva +Isla Lunanueva +Parque Batalla +Parque Batalla +Parque Batalla +Parque Batalla +Parque Batalla +Torre Batalla +Torre Batalla +Torre Batalla +Torre Batalla +Torre Batalla +Torre Batalla +Lugar misterioso +Orilla Veraz +Orilla Valor +Orilla Valor +Orilla Valor +Orilla Valor +Orilla Agudeza +Vía Manantial +Lugar misterioso +Ruta 201 +Ruta 202 +Ruta 203 +Ruta 204 +Ruta 204 +Ruta 205 +Ruta 205 +Ruta 205 +Ruta 206 +Ruta 206 +Ruta 207 +Ruta 208 +Ruta 208 +Ruta 209 +Ruta 209 +Ruta 209 +Ruta 209 +Ruta 209 +Ruta 209 +Ruta 210 +Ruta 210 +Ruta 210 +Ruta 210 +Ruta 211 +Ruta 211 +Ruta 212 +Ruta 212 +Ruta 212 +Ruta 212 +Ruta 212 +Ruta 212 +Ruta 213 +Ruta 213 +Ruta 213 +Ruta 213 +Ruta 213 +Ruta 213 +Ruta 213 +Ruta 214 +Ruta 214 +Ruta 215 +Ruta 216 +Ruta 216 +Ruta 217 +Ruta 217 +Ruta 217 +Ruta 218 +Ruta 218 +Ruta 218 +Ruta 219 +Ruta 221 +Ruta 221 +Ruta 221 +Ruta 222 +Ruta 222 +Ruta 222 +Ruta 222 +Ruta 224 +Ruta 225 +Ruta 225 +Ruta 227 +Ruta 227 +Ruta 228 +Ruta 228 +Ruta 228 +Ruta 228 +Ruta 229 +Lugar misterioso +Pueblo Hojaverde +Pueblo Hojaverde +Pueblo Hojaverde +Pueblo Hojaverde +Pueblo Hojaverde +Pueblo Hojaverde +Pueblo Hojaverde +Pueblo Arena +Pueblo Arena +Pueblo Arena +Pueblo Arena +Pueblo Arena +Pueblo Arena +Pueblo Arena +Pueblo Arena +Pueblo Arena +Pueblo Aromaflor +Pueblo Aromaflor +Pueblo Aromaflor +Pueblo Aromaflor +Pueblo Aromaflor +Pueblo Aromaflor +Pueblo Aromaflor +Pueblo Aromaflor +Pueblo Sosiego +Pueblo Sosiego +Pueblo Sosiego +Pueblo Sosiego +Pueblo Sosiego +Pueblo Sosiego +Pueblo Sosiego +Pueblo Sosiego +Pueblo Sosiego +Pueblo Sosiego +Pueblo Caelestis +Pueblo Caelestis +Pueblo Caelestis +Pueblo Caelestis +Pueblo Caelestis +Pueblo Caelestis +Pueblo Caelestis +Pueblo Caelestis +Pueblo Caelestis +Zona Sobrevivir +Zona Sobrevivir +Zona Sobrevivir +Zona Sobrevivir +Zona Sobrevivir +Zona Sobrevivir +Zona Sobrevivir +Zona Sobrevivir +Zona Descanso +Zona Descanso +Zona Descanso +Zona Descanso +Zona Descanso +Zona Descanso +Zona Descanso +Zona Descanso +Zona Descanso +Zona Descanso +Lugar misterioso +Lugar misterioso +Ruta 220 +Ruta 223 +Ruta 226 +Ruta 226 +Ruta 230 +Vía Costera +Lugar misterioso +Lugar misterioso +Lugar misterioso +Ciudad Vetusta +Parque Hansa +Parque Hansa +Parque Hansa +Parque Hansa +Parque Hansa +Parque Hansa +Parque Hansa +Parque Hansa +Parque Hansa +Parque Hansa +Parque Hansa +Parque Hansa +Parque Hansa +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Parque Hansa +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Grutas del Subsuelo +Parque Hansa +Parque Hansa +Ciudad Jubileo + + + + + + + + + + + + + + + + + + + + + +Parque Hansa +Parque Hansa +Parque Hansa +Parque Hansa +Parque Hansa +Parque Hansa +Parque Hansa +Parque Hansa +Parque Hansa +Parque Hansa diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_fr.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_fr.txt new file mode 100644 index 00000000000..89b4dd722ab --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_fr.txt @@ -0,0 +1,658 @@ +Féli-Cité +Féli-Cité +Féli-Cité +Féli-Cité +Féli-Cité +Féli-Cité +Féli-Cité +Féli-Cité +Féli-Cité +Féli-Cité +Féli-Cité +Féli-Cité +Féli-Cité +Féli-Cité +Féli-Cité +Féli-Cité +Féli-Cité +Féli-Cité +Féli-Cité +Féli-Cité +Féli-Cité +Féli-Cité +Féli-Cité +Féli-Cité +Joliberges +Joliberges +Arène de Joliberges +Joliberges +Joliberges +Joliberges +Joliberges +Joliberges +Joliberges +Joliberges +Joliberges +Joliberges +Joliberges +Joliberges +Charbourg +Charbourg +Arène de Charbourg +Charbourg +Charbourg +Charbourg +Charbourg +Charbourg +Charbourg +Charbourg +Charbourg +Charbourg +Charbourg +Charbourg +Charbourg +Charbourg +Vestigion +Vestigion +Arène de Vestigion +Arène de Vestigion +Vestigion +Vestigion +Vestigion +Vestigion +Vestigion +Vestigion +Vestigion +Vestigion +Vestigion +Vestigion +Vestigion +Vestigion +Vestigion +Vestigion +Vestigion +Vestigion +Unionpolis +Unionpolis +Arène d’Unionpolis +Arène d’Unionpolis +Arène d’Unionpolis +Arène d’Unionpolis +Arène d’Unionpolis +Arène d’Unionpolis +Arène d’Unionpolis +Arène d’Unionpolis +Arène d’Unionpolis +Arène d’Unionpolis +Arène d’Unionpolis +Arène d’Unionpolis +Arène d’Unionpolis +Unionpolis +Unionpolis +Unionpolis +Unionpolis +Unionpolis +Unionpolis +Unionpolis +Unionpolis +Unionpolis +Unionpolis +Unionpolis +Unionpolis +Unionpolis +Unionpolis +Unionpolis +Unionpolis +Unionpolis +Unionpolis +Unionpolis +Unionpolis +Unionpolis +Verchamps +Verchamps +Arène de Verchamps +Verchamps +Verchamps +Verchamps +Verchamps +Verchamps +Verchamps +Verchamps +Verchamps +Verchamps +Verchamps +Voilaroc +Arène de Voilaroc +Voilaroc +Voilaroc +Voilaroc +Voilaroc +Voilaroc +Voilaroc +Voilaroc +Voilaroc +Voilaroc +Voilaroc +Voilaroc +Voilaroc +Voilaroc +Voilaroc +Voilaroc +Voilaroc +Voilaroc +Rivamar +Rivamar +Arène de Rivamar +Arène de Rivamar +Arène de Rivamar +Rivamar +Rivamar +Rivamar +Rivamar +Rivamar +Rivamar +Rivamar +Rivamar +Rivamar +Rivamar +Rivamar +Rivamar +Frimapic +Frimapic +Arène de Frimapic +Frimapic +Frimapic +Frimapic +Frimapic +Frimapic +Ligue Pokémon +Ligue Pokémon +Ligue Pokémon +Ligue Pokémon +Ligue Pokémon +Ligue Pokémon +Ligue Pokémon +Ligue Pokémon +Ligue Pokémon +Ligue Pokémon +Ligue Pokémon +Ligue Pokémon +Ligue Pokémon +Ligue Pokémon +Ligue Pokémon +Ligue Pokémon +Ligue Pokémon +Ligue Pokémon +Ligue Pokémon +Aire de Combat +Aire de Combat +Aire de Combat +Aire de Combat +Aire de Combat +Aire de Combat +Aire de Combat +Aire de Combat +Aire de Combat +Mine de Charbourg +Mine de Charbourg +Parc Éolien +Parc Éolien +Forêt de Vestigion +Forêt de Vestigion +Forge Fuego +Forge Fuego +Mont Couronné +Mont Couronné +Mont Couronné +Mont Couronné +Mont Couronné +Mont Couronné +Mont Couronné +Mont Couronné +Mont Couronné +Mont Couronné +Mont Couronné +Mont Couronné +Mont Couronné +Colonnes Lances +Colonnes Lances +Salle Originelle +Grand Marais +Grand Marais +Grand Marais +Grand Marais +Grand Marais +Grand Marais +Ruines de Bonville +Ruines de Bonville +Ruines de Bonville +Ruines de Bonville +Ruines de Bonville +Ruines de Bonville +Ruines de Bonville +Ruines de Bonville +Ruines de Bonville +Ruines de Bonville +Ruines de Bonville +Ruines de Bonville +Ruines de Bonville +Ruines de Bonville +Ruines de Bonville +Ruines de Bonville +Ruines de Bonville +Ruines de Bonville +Ruines de Bonville +Route Victoire +Route Victoire +Route Victoire +Route Victoire +Route Victoire +Route Victoire +Parc Rosa Rugosa +Square Paisible +Chemin Rocheux +Pré de Floraville +Pré de Floraville +Entrée de Charbourg +Entrée de Charbourg +Île Pleine Lune +Île Pleine Lune +Mont Abrupt +Mont Abrupt +Mont Abrupt +Mont Abrupt +Source des Adieux +Grotte du Retour +Grotte du Retour +Grotte du Retour +Grotte du Retour +Grotte du Retour +Grotte du Retour +Grotte du Retour +Grotte du Retour +Grotte du Retour +Grotte du Retour +Grotte du Retour +Grotte du Retour +Grotte du Retour +Grotte du Retour +Grotte du Retour +Grotte du Retour +Grotte du Retour +Grotte du Retour +Grotte du Retour +Grotte du Retour +Grotte du Retour +Paradis Fleuri +Temple de Frimapic +Temple de Frimapic +Temple de Frimapic +Temple de Frimapic +Temple de Frimapic +Temple de Frimapic +Grotte des Égarés +Grotte des Égarés +Grotte du Ruinophile +Grotte du Ruinophile +Tunnel du Ruinophile +Jardin Trophée +Île de Fer +Île de Fer +Île de Fer +Île de Fer +Île de Fer +Île de Fer +Île de Fer +Île de Fer +Vieux Château +Vieux Château +Vieux Château +Vieux Château +Vieux Château +Vieux Château +Vieux Château +Vieux Château +Vieux Château +QG Team Galaxie +QG Team Galaxie +QG Team Galaxie +QG Team Galaxie +QG Team Galaxie +QG Team Galaxie +QG Team Galaxie +QG Team Galaxie +Lac Vérité +Lac Vérité +Lac Vérité +Lac Courage +Lac Courage +Lac Courage +Lac Savoir +Lac Savoir +Lac Savoir +Île Nouvellune +Île Nouvellune +Parc des Combats +Parc des Combats +Parc des Combats +Parc des Combats +Parc des Combats +Tour de Combat +Tour de Combat +Tour de Combat +Tour de Combat +Tour de Combat +Tour de Combat +Endroit mystérieux +Rive du Lac Vérité +Rive du Lac Courage +Rive du Lac Courage +Rive du Lac Courage +Rive du Lac Courage +Rive du Lac Savoir +Chemin de la Source +Endroit mystérieux +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 +Endroit mystérieux +Bonaugure +Bonaugure +Bonaugure +Bonaugure +Bonaugure +Bonaugure +Bonaugure +Littorella +Littorella +Littorella +Littorella +Littorella +Littorella +Littorella +Littorella +Littorella +Floraville +Floraville +Floraville +Floraville +Floraville +Floraville +Floraville +Floraville +Bonville +Bonville +Bonville +Bonville +Bonville +Bonville +Bonville +Bonville +Bonville +Bonville +Célestia +Célestia +Célestia +Célestia +Célestia +Célestia +Célestia +Célestia +Célestia +Aire de Survie +Aire de Survie +Aire de Survie +Aire de Survie +Aire de Survie +Aire de Survie +Aire de Survie +Aire de Survie +Aire de Détente +Aire de Détente +Aire de Détente +Aire de Détente +Aire de Détente +Aire de Détente +Aire de Détente +Aire de Détente +Aire de Détente +Aire de Détente +Endroit mystérieux +Endroit mystérieux +Chenal 220 +Chenal 223 +Chenal 226 +Chenal 226 +Chenal 230 +Passage Marin +Endroit mystérieux +Endroit mystérieux +Endroit mystérieux +Vestigion +Parc Rosa Rugosa +Parc Rosa Rugosa +Parc Rosa Rugosa +Parc Rosa Rugosa +Parc Rosa Rugosa +Parc Rosa Rugosa +Parc Rosa Rugosa +Parc Rosa Rugosa +Parc Rosa Rugosa +Parc Rosa Rugosa +Parc Rosa Rugosa +Parc Rosa Rugosa +Parc Rosa Rugosa +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Parc Rosa Rugosa +Grands Souterrains +Grands Souterrains +Grands Souterrains +Grands Souterrains +Parc Rosa Rugosa +Parc Rosa Rugosa +Féli-Cité + + + + + + + + + + + + + + + + + + + + + +Parc Rosa Rugosa +Parc Rosa Rugosa +Parc Rosa Rugosa +Parc Rosa Rugosa +Parc Rosa Rugosa +Parc Rosa Rugosa +Parc Rosa Rugosa +Parc Rosa Rugosa +Parc Rosa Rugosa +Parc Rosa Rugosa diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_it.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_it.txt new file mode 100644 index 00000000000..ef39116d54a --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_it.txt @@ -0,0 +1,658 @@ +Giubilopoli +Giubilopoli +Giubilopoli +Giubilopoli +Giubilopoli +Giubilopoli +Giubilopoli +Giubilopoli +Giubilopoli +Giubilopoli +Giubilopoli +Giubilopoli +Giubilopoli +Giubilopoli +Giubilopoli +Giubilopoli +Giubilopoli +Giubilopoli +Giubilopoli +Giubilopoli +Giubilopoli +Giubilopoli +Giubilopoli +Giubilopoli +Canalipoli +Canalipoli +Palestra Canalipoli +Canalipoli +Canalipoli +Canalipoli +Canalipoli +Canalipoli +Canalipoli +Canalipoli +Canalipoli +Canalipoli +Canalipoli +Canalipoli +Mineropoli +Mineropoli +Palestra Mineropoli +Mineropoli +Mineropoli +Mineropoli +Mineropoli +Mineropoli +Mineropoli +Mineropoli +Mineropoli +Mineropoli +Mineropoli +Mineropoli +Mineropoli +Mineropoli +Evopoli +Evopoli +Palestra Evopoli +Palestra Evopoli +Evopoli +Evopoli +Evopoli +Evopoli +Evopoli +Evopoli +Evopoli +Evopoli +Evopoli +Evopoli +Evopoli +Evopoli +Evopoli +Evopoli +Evopoli +Evopoli +Cuoripoli +Cuoripoli +Palestra Cuoripoli +Palestra Cuoripoli +Palestra Cuoripoli +Palestra Cuoripoli +Palestra Cuoripoli +Palestra Cuoripoli +Palestra Cuoripoli +Palestra Cuoripoli +Palestra Cuoripoli +Palestra Cuoripoli +Palestra Cuoripoli +Palestra Cuoripoli +Palestra Cuoripoli +Cuoripoli +Cuoripoli +Cuoripoli +Cuoripoli +Cuoripoli +Cuoripoli +Cuoripoli +Cuoripoli +Cuoripoli +Cuoripoli +Cuoripoli +Cuoripoli +Cuoripoli +Cuoripoli +Cuoripoli +Cuoripoli +Cuoripoli +Cuoripoli +Cuoripoli +Cuoripoli +Cuoripoli +Pratopoli +Pratopoli +Palestra Pratopoli +Pratopoli +Pratopoli +Pratopoli +Pratopoli +Pratopoli +Pratopoli +Pratopoli +Pratopoli +Pratopoli +Pratopoli +Rupepoli +Palestra Rupepoli +Rupepoli +Rupepoli +Rupepoli +Rupepoli +Rupepoli +Rupepoli +Rupepoli +Rupepoli +Rupepoli +Rupepoli +Rupepoli +Rupepoli +Rupepoli +Rupepoli +Rupepoli +Rupepoli +Rupepoli +Arenipoli +Arenipoli +Palestra Arenipoli +Palestra Arenipoli +Palestra Arenipoli +Arenipoli +Arenipoli +Arenipoli +Arenipoli +Arenipoli +Arenipoli +Arenipoli +Arenipoli +Arenipoli +Arenipoli +Arenipoli +Arenipoli +Nevepoli +Nevepoli +Palestra Nevepoli +Nevepoli +Nevepoli +Nevepoli +Nevepoli +Nevepoli +Lega Pokémon +Lega Pokémon +Lega Pokémon +Lega Pokémon +Lega Pokémon +Lega Pokémon +Lega Pokémon +Lega Pokémon +Lega Pokémon +Lega Pokémon +Lega Pokémon +Lega Pokémon +Lega Pokémon +Lega Pokémon +Lega Pokémon +Lega Pokémon +Lega Pokémon +Lega Pokémon +Lega Pokémon +Area Sfida +Area Sfida +Area Sfida +Area Sfida +Area Sfida +Area Sfida +Area Sfida +Area Sfida +Area Sfida +Cava di Mineropoli +Cava di Mineropoli +Impianto Turbine +Impianto Turbine +Bosco di Evopoli +Bosco di Evopoli +Fonderie Fuego +Fonderie Fuego +Monte Corona +Monte Corona +Monte Corona +Monte Corona +Monte Corona +Monte Corona +Monte Corona +Monte Corona +Monte Corona +Monte Corona +Monte Corona +Monte Corona +Monte Corona +Vetta Lancia +Vetta Lancia +Spazio Origine +Gran Palude +Gran Palude +Gran Palude +Gran Palude +Gran Palude +Gran Palude +Rovine di Flemminia +Rovine di Flemminia +Rovine di Flemminia +Rovine di Flemminia +Rovine di Flemminia +Rovine di Flemminia +Rovine di Flemminia +Rovine di Flemminia +Rovine di Flemminia +Rovine di Flemminia +Rovine di Flemminia +Rovine di Flemminia +Rovine di Flemminia +Rovine di Flemminia +Rovine di Flemminia +Rovine di Flemminia +Rovine di Flemminia +Rovine di Flemminia +Rovine di Flemminia +Via Vittoria +Via Vittoria +Via Vittoria +Via Vittoria +Via Vittoria +Via Vittoria +Parco Rosa Rugosa +Parco Concordia +Cammino Roccioso +Prato Fiorito +Prato Fiorito +Varco di Mineropoli +Varco di Mineropoli +Isola Lunapiena +Isola Lunapiena +Monte Ostile +Monte Ostile +Monte Ostile +Monte Ostile +Fonte Saluto +Grotta Ritorno +Grotta Ritorno +Grotta Ritorno +Grotta Ritorno +Grotta Ritorno +Grotta Ritorno +Grotta Ritorno +Grotta Ritorno +Grotta Ritorno +Grotta Ritorno +Grotta Ritorno +Grotta Ritorno +Grotta Ritorno +Grotta Ritorno +Grotta Ritorno +Grotta Ritorno +Grotta Ritorno +Grotta Ritorno +Grotta Ritorno +Grotta Ritorno +Grotta Ritorno +Paradiso Fiore +Tempio di Nevepoli +Tempio di Nevepoli +Tempio di Nevepoli +Tempio di Nevepoli +Tempio di Nevepoli +Tempio di Nevepoli +Grotta Labirinto +Grotta Labirinto +Grotta Rovine +Grotta Rovine +Tunnel Rovine +Giardino Trofeo +Isola Ferrosa +Isola Ferrosa +Isola Ferrosa +Isola Ferrosa +Isola Ferrosa +Isola Ferrosa +Isola Ferrosa +Isola Ferrosa +Antico Château +Antico Château +Antico Château +Antico Château +Antico Château +Antico Château +Antico Château +Antico Château +Antico Château +Covo Team Galassia +Covo Team Galassia +Covo Team Galassia +Covo Team Galassia +Covo Team Galassia +Covo Team Galassia +Covo Team Galassia +Covo Team Galassia +Lago Verità +Lago Verità +Lago Verità +Lago Valore +Lago Valore +Lago Valore +Lago Arguzia +Lago Arguzia +Lago Arguzia +Isola Lunanuova +Isola Lunanuova +Giardino Lotta +Giardino Lotta +Giardino Lotta +Giardino Lotta +Giardino Lotta +Torre Lotta +Torre Lotta +Torre Lotta +Torre Lotta +Torre Lotta +Torre Lotta +Zona misteriosa +Riva Lago Verità +Riva Lago Valore +Riva Lago Valore +Riva Lago Valore +Riva Lago Valore +Riva Lago Arguzia +Sentiero Fonte +Zona misteriosa +Percorso 201 +Percorso 202 +Percorso 203 +Percorso 204 +Percorso 204 +Percorso 205 +Percorso 205 +Percorso 205 +Percorso 206 +Percorso 206 +Percorso 207 +Percorso 208 +Percorso 208 +Percorso 209 +Percorso 209 +Percorso 209 +Percorso 209 +Percorso 209 +Percorso 209 +Percorso 210 +Percorso 210 +Percorso 210 +Percorso 210 +Percorso 211 +Percorso 211 +Percorso 212 +Percorso 212 +Percorso 212 +Percorso 212 +Percorso 212 +Percorso 212 +Percorso 213 +Percorso 213 +Percorso 213 +Percorso 213 +Percorso 213 +Percorso 213 +Percorso 213 +Percorso 214 +Percorso 214 +Percorso 215 +Percorso 216 +Percorso 216 +Percorso 217 +Percorso 217 +Percorso 217 +Percorso 218 +Percorso 218 +Percorso 218 +Percorso 219 +Percorso 221 +Percorso 221 +Percorso 221 +Percorso 222 +Percorso 222 +Percorso 222 +Percorso 222 +Percorso 224 +Percorso 225 +Percorso 225 +Percorso 227 +Percorso 227 +Percorso 228 +Percorso 228 +Percorso 228 +Percorso 228 +Percorso 229 +Zona misteriosa +Duefoglie +Duefoglie +Duefoglie +Duefoglie +Duefoglie +Duefoglie +Duefoglie +Sabbiafine +Sabbiafine +Sabbiafine +Sabbiafine +Sabbiafine +Sabbiafine +Sabbiafine +Sabbiafine +Sabbiafine +Giardinfiorito +Giardinfiorito +Giardinfiorito +Giardinfiorito +Giardinfiorito +Giardinfiorito +Giardinfiorito +Giardinfiorito +Flemminia +Flemminia +Flemminia +Flemminia +Flemminia +Flemminia +Flemminia +Flemminia +Flemminia +Flemminia +Memoride +Memoride +Memoride +Memoride +Memoride +Memoride +Memoride +Memoride +Memoride +Area Provviste +Area Provviste +Area Provviste +Area Provviste +Area Provviste +Area Provviste +Area Provviste +Area Provviste +Area Svago +Area Svago +Area Svago +Area Svago +Area Svago +Area Svago +Area Svago +Area Svago +Area Svago +Area Svago +Zona misteriosa +Zona misteriosa +Percorso 220 +Percorso 223 +Percorso 226 +Percorso 226 +Percorso 230 +Via Frangimare +Zona misteriosa +Zona misteriosa +Zona misteriosa +Evopoli +Parco Rosa Rugosa +Parco Rosa Rugosa +Parco Rosa Rugosa +Parco Rosa Rugosa +Parco Rosa Rugosa +Parco Rosa Rugosa +Parco Rosa Rugosa +Parco Rosa Rugosa +Parco Rosa Rugosa +Parco Rosa Rugosa +Parco Rosa Rugosa +Parco Rosa Rugosa +Parco Rosa Rugosa +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Parco Rosa Rugosa +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Grandi Sotterranei +Parco Rosa Rugosa +Parco Rosa Rugosa +Giubilopoli + + + + + + + + + + + + + + + + + + + + + +Parco Rosa Rugosa +Parco Rosa Rugosa +Parco Rosa Rugosa +Parco Rosa Rugosa +Parco Rosa Rugosa +Parco Rosa Rugosa +Parco Rosa Rugosa +Parco Rosa Rugosa +Parco Rosa Rugosa +Parco Rosa Rugosa diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_ja.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_ja.txt new file mode 100644 index 00000000000..bf32ae96d2d --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_ja.txt @@ -0,0 +1,658 @@ +コトブキシティ +コトブキシティ +コトブキシティ +コトブキシティ +コトブキシティ +コトブキシティ +コトブキシティ +コトブキシティ +コトブキシティ +コトブキシティ +コトブキシティ +コトブキシティ +コトブキシティ +コトブキシティ +コトブキシティ +コトブキシティ +コトブキシティ +コトブキシティ +コトブキシティ +コトブキシティ +コトブキシティ +コトブキシティ +コトブキシティ +コトブキシティ +ミオシティ +ミオシティ +ミオジム +ミオシティ +ミオシティ +ミオシティ +ミオシティ +ミオシティ +ミオシティ +ミオシティ +ミオシティ +ミオシティ +ミオシティ +ミオシティ +クロガネシティ +クロガネシティ +クロガネジム +クロガネシティ +クロガネシティ +クロガネシティ +クロガネシティ +クロガネシティ +クロガネシティ +クロガネシティ +クロガネシティ +クロガネシティ +クロガネシティ +クロガネシティ +クロガネシティ +クロガネシティ +ハクタイシティ +ハクタイシティ +ハクタイジム +ハクタイジム +ハクタイシティ +ハクタイシティ +ハクタイシティ +ハクタイシティ +ハクタイシティ +ハクタイシティ +ハクタイシティ +ハクタイシティ +ハクタイシティ +ハクタイシティ +ハクタイシティ +ハクタイシティ +ハクタイシティ +ハクタイシティ +ハクタイシティ +ハクタイシティ +ヨスガシティ +ヨスガシティ +ヨスガジム +ヨスガジム +ヨスガジム +ヨスガジム +ヨスガジム +ヨスガジム +ヨスガジム +ヨスガジム +ヨスガジム +ヨスガジム +ヨスガジム +ヨスガジム +ヨスガジム +ヨスガシティ +ヨスガシティ +ヨスガシティ +ヨスガシティ +ヨスガシティ +ヨスガシティ +ヨスガシティ +ヨスガシティ +ヨスガシティ +ヨスガシティ +ヨスガシティ +ヨスガシティ +ヨスガシティ +ヨスガシティ +ヨスガシティ +ヨスガシティ +ヨスガシティ +ヨスガシティ +ヨスガシティ +ヨスガシティ +ヨスガシティ +ノモセシティ +ノモセシティ +ノモセジム +ノモセシティ +ノモセシティ +ノモセシティ +ノモセシティ +ノモセシティ +ノモセシティ +ノモセシティ +ノモセシティ +ノモセシティ +ノモセシティ +トバリシティ +トバリジム +トバリシティ +トバリシティ +トバリシティ +トバリシティ +トバリシティ +トバリシティ +トバリシティ +トバリシティ +トバリシティ +トバリシティ +トバリシティ +トバリシティ +トバリシティ +トバリシティ +トバリシティ +トバリシティ +トバリシティ +ナギサシティ +ナギサシティ +ナギサジム +ナギサジム +ナギサジム +ナギサシティ +ナギサシティ +ナギサシティ +ナギサシティ +ナギサシティ +ナギサシティ +ナギサシティ +ナギサシティ +ナギサシティ +ナギサシティ +ナギサシティ +ナギサシティ +キッサキシティ +キッサキシティ +キッサキジム +キッサキシティ +キッサキシティ +キッサキシティ +キッサキシティ +キッサキシティ +ポケモンリーグ +ポケモンリーグ +ポケモンリーグ +ポケモンリーグ +ポケモンリーグ +ポケモンリーグ +ポケモンリーグ +ポケモンリーグ +ポケモンリーグ +ポケモンリーグ +ポケモンリーグ +ポケモンリーグ +ポケモンリーグ +ポケモンリーグ +ポケモンリーグ +ポケモンリーグ +ポケモンリーグ +ポケモンリーグ +ポケモンリーグ +ファイトエリア +ファイトエリア +ファイトエリア +ファイトエリア +ファイトエリア +ファイトエリア +ファイトエリア +ファイトエリア +ファイトエリア +クロガネたんこう +クロガネたんこう +たにまのはつでんしょ +たにまのはつでんしょ +ハクタイのもり +ハクタイのもり +タタラせいてつじょ +タタラせいてつじょ +テンガンざん +テンガンざん +テンガンざん +テンガンざん +テンガンざん +テンガンざん +テンガンざん +テンガンざん +テンガンざん +テンガンざん +テンガンざん +テンガンざん +テンガンざん +やりのはしら +やりのはしら +はじまりのま +だいしつげん +だいしつげん +だいしつげん +だいしつげん +だいしつげん +だいしつげん +ズイのいせき +ズイのいせき +ズイのいせき +ズイのいせき +ズイのいせき +ズイのいせき +ズイのいせき +ズイのいせき +ズイのいせき +ズイのいせき +ズイのいせき +ズイのいせき +ズイのいせき +ズイのいせき +ズイのいせき +ズイのいせき +ズイのいせき +ズイのいせき +ズイのいせき +チャンピオンロード +チャンピオンロード +チャンピオンロード +チャンピオンロード +チャンピオンロード +チャンピオンロード +ハマナスパーク +ふれあいひろば +あれたぬけみち +ソノオのはなばたけ +ソノオのはなばたけ +クロガネゲート +クロガネゲート +まんげつじま +まんげつじま +ハードマウンテン +ハードマウンテン +ハードマウンテン +ハードマウンテン +おくりのいずみ +もどりのどうくつ +もどりのどうくつ +もどりのどうくつ +もどりのどうくつ +もどりのどうくつ +もどりのどうくつ +もどりのどうくつ +もどりのどうくつ +もどりのどうくつ +もどりのどうくつ +もどりのどうくつ +もどりのどうくつ +もどりのどうくつ +もどりのどうくつ +もどりのどうくつ +もどりのどうくつ +もどりのどうくつ +もどりのどうくつ +もどりのどうくつ +もどりのどうくつ +もどりのどうくつ +はなのらくえん +キッサキしんでん +キッサキしんでん +キッサキしんでん +キッサキしんでん +キッサキしんでん +キッサキしんでん +まよいのどうくつ +まよいのどうくつ +いせきマニアのあな +いせきマニアのあな +マニアトンネル +じまんのうらにわ +こうてつじま +こうてつじま +こうてつじま +こうてつじま +こうてつじま +こうてつじま +こうてつじま +こうてつじま +もりのようかん +もりのようかん +もりのようかん +もりのようかん +もりのようかん +もりのようかん +もりのようかん +もりのようかん +もりのようかん +ギンガだんアジト +ギンガだんアジト +ギンガだんアジト +ギンガだんアジト +ギンガだんアジト +ギンガだんアジト +ギンガだんアジト +ギンガだんアジト +シンジこ +シンジこ +シンジこ +リッシこ +リッシこ +リッシこ +エイチこ +エイチこ +エイチこ +しんげつじま +しんげつじま +バトルパーク +バトルパーク +バトルパーク +バトルパーク +バトルパーク +バトルタワー +バトルタワー +バトルタワー +バトルタワー +バトルタワー +バトルタワー +なぞのばしょ +シンジこのほとり +リッシこのほとり +リッシこのほとり +リッシこのほとり +リッシこのほとり +エイチこのほとり +かくれいずみへのみち +なぞのばしょ +201ばんどうろ +202ばんどうろ +203ばんどうろ +204ばんどうろ +204ばんどうろ +205ばんどうろ +205ばんどうろ +205ばんどうろ +206ばんどうろ +206ばんどうろ +207ばんどうろ +208ばんどうろ +208ばんどうろ +209ばんどうろ +209ばんどうろ +209ばんどうろ +209ばんどうろ +209ばんどうろ +209ばんどうろ +210ばんどうろ +210ばんどうろ +210ばんどうろ +210ばんどうろ +211ばんどうろ +211ばんどうろ +212ばんどうろ +212ばんどうろ +212ばんどうろ +212ばんどうろ +212ばんどうろ +212ばんどうろ +213ばんどうろ +213ばんどうろ +213ばんどうろ +213ばんどうろ +213ばんどうろ +213ばんどうろ +213ばんどうろ +214ばんどうろ +214ばんどうろ +215ばんどうろ +216ばんどうろ +216ばんどうろ +217ばんどうろ +217ばんどうろ +217ばんどうろ +218ばんどうろ +218ばんどうろ +218ばんどうろ +219ばんどうろ +221ばんどうろ +221ばんどうろ +221ばんどうろ +222ばんどうろ +222ばんどうろ +222ばんどうろ +222ばんどうろ +224ばんどうろ +225ばんどうろ +225ばんどうろ +227ばんどうろ +227ばんどうろ +228ばんどうろ +228ばんどうろ +228ばんどうろ +228ばんどうろ +229ばんどうろ +なぞのばしょ +フタバタウン +フタバタウン +フタバタウン +フタバタウン +フタバタウン +フタバタウン +フタバタウン +マサゴタウン +マサゴタウン +マサゴタウン +マサゴタウン +マサゴタウン +マサゴタウン +マサゴタウン +マサゴタウン +マサゴタウン +ソノオタウン +ソノオタウン +ソノオタウン +ソノオタウン +ソノオタウン +ソノオタウン +ソノオタウン +ソノオタウン +ズイタウン +ズイタウン +ズイタウン +ズイタウン +ズイタウン +ズイタウン +ズイタウン +ズイタウン +ズイタウン +ズイタウン +カンナギタウン +カンナギタウン +カンナギタウン +カンナギタウン +カンナギタウン +カンナギタウン +カンナギタウン +カンナギタウン +カンナギタウン +サバイバルエリア +サバイバルエリア +サバイバルエリア +サバイバルエリア +サバイバルエリア +サバイバルエリア +サバイバルエリア +サバイバルエリア +リゾートエリア +リゾートエリア +リゾートエリア +リゾートエリア +リゾートエリア +リゾートエリア +リゾートエリア +リゾートエリア +リゾートエリア +リゾートエリア +なぞのばしょ +なぞのばしょ +220ばんすいどう +223ばんすいどう +226ばんすいどう +226ばんすいどう +230ばんすいどう +うみわれのみち +なぞのばしょ +なぞのばしょ +なぞのばしょ +ハクタイシティ +ハマナスパーク +ハマナスパーク +ハマナスパーク +ハマナスパーク +ハマナスパーク +ハマナスパーク +ハマナスパーク +ハマナスパーク +ハマナスパーク +ハマナスパーク +ハマナスパーク +ハマナスパーク +ハマナスパーク +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ハマナスパーク +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ちかだいどうくつ +ハマナスパーク +ハマナスパーク +コトブキシティ + + + + + + + + + + + + + + + + + + + + + +ハマナスパーク +ハマナスパーク +ハマナスパーク +ハマナスパーク +ハマナスパーク +ハマナスパーク +ハマナスパーク +ハマナスパーク +ハマナスパーク +ハマナスパーク diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_ko.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_ko.txt new file mode 100644 index 00000000000..f7e6b0a2ef5 --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_ko.txt @@ -0,0 +1,658 @@ +축복시티 +축복시티 +축복시티 +축복시티 +축복시티 +축복시티 +축복시티 +축복시티 +축복시티 +축복시티 +축복시티 +축복시티 +축복시티 +축복시티 +축복시티 +축복시티 +축복시티 +축복시티 +축복시티 +축복시티 +축복시티 +축복시티 +축복시티 +축복시티 +운하시티 +운하시티 +운하체육관 +운하시티 +운하시티 +운하시티 +운하시티 +운하시티 +운하시티 +운하시티 +운하시티 +운하시티 +운하시티 +운하시티 +무쇠시티 +무쇠시티 +무쇠체육관 +무쇠시티 +무쇠시티 +무쇠시티 +무쇠시티 +무쇠시티 +무쇠시티 +무쇠시티 +무쇠시티 +무쇠시티 +무쇠시티 +무쇠시티 +무쇠시티 +무쇠시티 +영원시티 +영원시티 +영원체육관 +영원체육관 +영원시티 +영원시티 +영원시티 +영원시티 +영원시티 +영원시티 +영원시티 +영원시티 +영원시티 +영원시티 +영원시티 +영원시티 +영원시티 +영원시티 +영원시티 +영원시티 +연고시티 +연고시티 +연고체육관 +연고체육관 +연고체육관 +연고체육관 +연고체육관 +연고체육관 +연고체육관 +연고체육관 +연고체육관 +연고체육관 +연고체육관 +연고체육관 +연고체육관 +연고시티 +연고시티 +연고시티 +연고시티 +연고시티 +연고시티 +연고시티 +연고시티 +연고시티 +연고시티 +연고시티 +연고시티 +연고시티 +연고시티 +연고시티 +연고시티 +연고시티 +연고시티 +연고시티 +연고시티 +연고시티 +들판시티 +들판시티 +들판체육관 +들판시티 +들판시티 +들판시티 +들판시티 +들판시티 +들판시티 +들판시티 +들판시티 +들판시티 +들판시티 +장막시티 +장막체육관 +장막시티 +장막시티 +장막시티 +장막시티 +장막시티 +장막시티 +장막시티 +장막시티 +장막시티 +장막시티 +장막시티 +장막시티 +장막시티 +장막시티 +장막시티 +장막시티 +장막시티 +물가시티 +물가시티 +물가체육관 +물가체육관 +물가체육관 +물가시티 +물가시티 +물가시티 +물가시티 +물가시티 +물가시티 +물가시티 +물가시티 +물가시티 +물가시티 +물가시티 +물가시티 +선단시티 +선단시티 +선단체육관 +선단시티 +선단시티 +선단시티 +선단시티 +선단시티 +포켓몬리그 +포켓몬리그 +포켓몬리그 +포켓몬리그 +포켓몬리그 +포켓몬리그 +포켓몬리그 +포켓몬리그 +포켓몬리그 +포켓몬리그 +포켓몬리그 +포켓몬리그 +포켓몬리그 +포켓몬리그 +포켓몬리그 +포켓몬리그 +포켓몬리그 +포켓몬리그 +포켓몬리그 +파이트에리어 +파이트에리어 +파이트에리어 +파이트에리어 +파이트에리어 +파이트에리어 +파이트에리어 +파이트에리어 +파이트에리어 +무쇠탄갱 +무쇠탄갱 +골짜기발전소 +골짜기발전소 +영원의 숲 +영원의 숲 +골풀무제철소 +골풀무제철소 +천관산 +천관산 +천관산 +천관산 +천관산 +천관산 +천관산 +천관산 +천관산 +천관산 +천관산 +천관산 +천관산 +창기둥 +창기둥 +시작의 방 +대습초원 +대습초원 +대습초원 +대습초원 +대습초원 +대습초원 +신수유적 +신수유적 +신수유적 +신수유적 +신수유적 +신수유적 +신수유적 +신수유적 +신수유적 +신수유적 +신수유적 +신수유적 +신수유적 +신수유적 +신수유적 +신수유적 +신수유적 +신수유적 +신수유적 +챔피언로드 +챔피언로드 +챔피언로드 +챔피언로드 +챔피언로드 +챔피언로드 +해당화파크 +상호교류광장 +험한 샛길 +꽃향기의 꽃밭 +꽃향기의 꽃밭 +무쇠게이트 +무쇠게이트 +만월섬 +만월섬 +하드마운틴 +하드마운틴 +하드마운틴 +하드마운틴 +송별의 샘 +귀혼동굴 +귀혼동굴 +귀혼동굴 +귀혼동굴 +귀혼동굴 +귀혼동굴 +귀혼동굴 +귀혼동굴 +귀혼동굴 +귀혼동굴 +귀혼동굴 +귀혼동굴 +귀혼동굴 +귀혼동굴 +귀혼동굴 +귀혼동굴 +귀혼동굴 +귀혼동굴 +귀혼동굴 +귀혼동굴 +귀혼동굴 +꽃의 낙원 +선단신전 +선단신전 +선단신전 +선단신전 +선단신전 +선단신전 +미혹의 동굴 +미혹의 동굴 +유적마니아굴 +유적마니아굴 +마니아터널 +자랑의 뒷마당 +강철섬 +강철섬 +강철섬 +강철섬 +강철섬 +강철섬 +강철섬 +강철섬 +숲의 양옥집 +숲의 양옥집 +숲의 양옥집 +숲의 양옥집 +숲의 양옥집 +숲의 양옥집 +숲의 양옥집 +숲의 양옥집 +숲의 양옥집 +갤럭시단아지트 +갤럭시단아지트 +갤럭시단아지트 +갤럭시단아지트 +갤럭시단아지트 +갤럭시단아지트 +갤럭시단아지트 +갤럭시단아지트 +진실호수 +진실호수 +진실호수 +입지호수 +입지호수 +입지호수 +예지호수 +예지호수 +예지호수 +신월섬 +신월섬 +배틀파크 +배틀파크 +배틀파크 +배틀파크 +배틀파크 +배틀타워 +배틀타워 +배틀타워 +배틀타워 +배틀타워 +배틀타워 +수수께끼의 장소 +진실호수근처 +입지호수근처 +입지호수근처 +입지호수근처 +입지호수근처 +예지호수근처 +숨겨진 샘의 길 +수수께끼의 장소 +201번도로 +202번도로 +203번도로 +204번도로 +204번도로 +205번도로 +205번도로 +205번도로 +206번도로 +206번도로 +207번도로 +208번도로 +208번도로 +209번도로 +209번도로 +209번도로 +209번도로 +209번도로 +209번도로 +210번도로 +210번도로 +210번도로 +210번도로 +211번도로 +211번도로 +212번도로 +212번도로 +212번도로 +212번도로 +212번도로 +212번도로 +213번도로 +213번도로 +213번도로 +213번도로 +213번도로 +213번도로 +213번도로 +214번도로 +214번도로 +215번도로 +216번도로 +216번도로 +217번도로 +217번도로 +217번도로 +218번도로 +218번도로 +218번도로 +219번도로 +221번도로 +221번도로 +221번도로 +222번도로 +222번도로 +222번도로 +222번도로 +224번도로 +225번도로 +225번도로 +227번도로 +227번도로 +228번도로 +228번도로 +228번도로 +228번도로 +229번도로 +수수께끼의 장소 +떡잎마을 +떡잎마을 +떡잎마을 +떡잎마을 +떡잎마을 +떡잎마을 +떡잎마을 +잔모래마을 +잔모래마을 +잔모래마을 +잔모래마을 +잔모래마을 +잔모래마을 +잔모래마을 +잔모래마을 +잔모래마을 +꽃향기마을 +꽃향기마을 +꽃향기마을 +꽃향기마을 +꽃향기마을 +꽃향기마을 +꽃향기마을 +꽃향기마을 +신수마을 +신수마을 +신수마을 +신수마을 +신수마을 +신수마을 +신수마을 +신수마을 +신수마을 +신수마을 +봉신마을 +봉신마을 +봉신마을 +봉신마을 +봉신마을 +봉신마을 +봉신마을 +봉신마을 +봉신마을 +서바이벌에리어 +서바이벌에리어 +서바이벌에리어 +서바이벌에리어 +서바이벌에리어 +서바이벌에리어 +서바이벌에리어 +서바이벌에리어 +리조트에리어 +리조트에리어 +리조트에리어 +리조트에리어 +리조트에리어 +리조트에리어 +리조트에리어 +리조트에리어 +리조트에리어 +리조트에리어 +수수께끼의 장소 +수수께끼의 장소 +220번수로 +223번수로 +226번수로 +226번수로 +230번수로 +갈라진 바닷길 +수수께끼의 장소 +수수께끼의 장소 +수수께끼의 장소 +영원시티 +해당화파크 +해당화파크 +해당화파크 +해당화파크 +해당화파크 +해당화파크 +해당화파크 +해당화파크 +해당화파크 +해당화파크 +해당화파크 +해당화파크 +해당화파크 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +해당화파크 +지하대동굴 +지하대동굴 +지하대동굴 +지하대동굴 +해당화파크 +해당화파크 +축복시티 + + + + + + + + + + + + + + + + + + + + + +해당화파크 +해당화파크 +해당화파크 +해당화파크 +해당화파크 +해당화파크 +해당화파크 +해당화파크 +해당화파크 +해당화파크 diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_zh.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_zh.txt new file mode 100644 index 00000000000..35c50f59b32 --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_00000_zh.txt @@ -0,0 +1,658 @@ +祝庆市 +祝庆市 +祝庆市 +祝庆市 +祝庆市 +祝庆市 +祝庆市 +祝庆市 +祝庆市 +祝庆市 +祝庆市 +祝庆市 +祝庆市 +祝庆市 +祝庆市 +祝庆市 +祝庆市 +祝庆市 +祝庆市 +祝庆市 +祝庆市 +祝庆市 +祝庆市 +祝庆市 +水脉市 +水脉市 +水脉道馆 +水脉市 +水脉市 +水脉市 +水脉市 +水脉市 +水脉市 +水脉市 +水脉市 +水脉市 +水脉市 +水脉市 +黑金市 +黑金市 +黑金道馆 +黑金市 +黑金市 +黑金市 +黑金市 +黑金市 +黑金市 +黑金市 +黑金市 +黑金市 +黑金市 +黑金市 +黑金市 +黑金市 +百代市 +百代市 +百代道馆 +百代道馆 +百代市 +百代市 +百代市 +百代市 +百代市 +百代市 +百代市 +百代市 +百代市 +百代市 +百代市 +百代市 +百代市 +百代市 +百代市 +百代市 +家缘市 +家缘市 +家缘道馆 +家缘道馆 +家缘道馆 +家缘道馆 +家缘道馆 +家缘道馆 +家缘道馆 +家缘道馆 +家缘道馆 +家缘道馆 +家缘道馆 +家缘道馆 +家缘道馆 +家缘市 +家缘市 +家缘市 +家缘市 +家缘市 +家缘市 +家缘市 +家缘市 +家缘市 +家缘市 +家缘市 +家缘市 +家缘市 +家缘市 +家缘市 +家缘市 +家缘市 +家缘市 +家缘市 +家缘市 +家缘市 +野原市 +野原市 +野原道馆 +野原市 +野原市 +野原市 +野原市 +野原市 +野原市 +野原市 +野原市 +野原市 +野原市 +帷幕市 +帷幕道馆 +帷幕市 +帷幕市 +帷幕市 +帷幕市 +帷幕市 +帷幕市 +帷幕市 +帷幕市 +帷幕市 +帷幕市 +帷幕市 +帷幕市 +帷幕市 +帷幕市 +帷幕市 +帷幕市 +帷幕市 +滨海市 +滨海市 +滨海道馆 +滨海道馆 +滨海道馆 +滨海市 +滨海市 +滨海市 +滨海市 +滨海市 +滨海市 +滨海市 +滨海市 +滨海市 +滨海市 +滨海市 +滨海市 +雪峰市 +雪峰市 +雪峰道馆 +雪峰市 +雪峰市 +雪峰市 +雪峰市 +雪峰市 +宝可梦联盟 +宝可梦联盟 +宝可梦联盟 +宝可梦联盟 +宝可梦联盟 +宝可梦联盟 +宝可梦联盟 +宝可梦联盟 +宝可梦联盟 +宝可梦联盟 +宝可梦联盟 +宝可梦联盟 +宝可梦联盟 +宝可梦联盟 +宝可梦联盟 +宝可梦联盟 +宝可梦联盟 +宝可梦联盟 +宝可梦联盟 +战斗区 +战斗区 +战斗区 +战斗区 +战斗区 +战斗区 +战斗区 +战斗区 +战斗区 +黑金炭坑 +黑金炭坑 +山谷发电厂 +山谷发电厂 +百代森林 +百代森林 +多多罗钢铁厂 +多多罗钢铁厂 +天冠山 +天冠山 +天冠山 +天冠山 +天冠山 +天冠山 +天冠山 +天冠山 +天冠山 +天冠山 +天冠山 +天冠山 +天冠山 +枪之柱 +枪之柱 +起始之殿 +大湿地 +大湿地 +大湿地 +大湿地 +大湿地 +大湿地 +随意遗迹 +随意遗迹 +随意遗迹 +随意遗迹 +随意遗迹 +随意遗迹 +随意遗迹 +随意遗迹 +随意遗迹 +随意遗迹 +随意遗迹 +随意遗迹 +随意遗迹 +随意遗迹 +随意遗迹 +随意遗迹 +随意遗迹 +随意遗迹 +随意遗迹 +冠军之路 +冠军之路 +冠军之路 +冠军之路 +冠军之路 +冠军之路 +玫瑰公园 +互动广场 +荒芜小道 +花苑花田 +花苑花田 +黑金闸口 +黑金闸口 +满月岛 +满月岛 +严酷山 +严酷山 +严酷山 +严酷山 +送行之泉 +归途洞窟 +归途洞窟 +归途洞窟 +归途洞窟 +归途洞窟 +归途洞窟 +归途洞窟 +归途洞窟 +归途洞窟 +归途洞窟 +归途洞窟 +归途洞窟 +归途洞窟 +归途洞窟 +归途洞窟 +归途洞窟 +归途洞窟 +归途洞窟 +归途洞窟 +归途洞窟 +归途洞窟 +花之乐园 +雪峰神殿 +雪峰神殿 +雪峰神殿 +雪峰神殿 +雪峰神殿 +雪峰神殿 +迷幻洞窟 +迷幻洞窟 +遗迹迷洞穴 +遗迹迷洞穴 +遗迹迷隧道 +自豪的后院 +钢铁岛 +钢铁岛 +钢铁岛 +钢铁岛 +钢铁岛 +钢铁岛 +钢铁岛 +钢铁岛 +森之洋馆 +森之洋馆 +森之洋馆 +森之洋馆 +森之洋馆 +森之洋馆 +森之洋馆 +森之洋馆 +森之洋馆 +银河队基地 +银河队基地 +银河队基地 +银河队基地 +银河队基地 +银河队基地 +银河队基地 +银河队基地 +心齐湖 +心齐湖 +心齐湖 +立志湖 +立志湖 +立志湖 +睿智湖 +睿智湖 +睿智湖 +新月岛 +新月岛 +对战公园 +对战公园 +对战公园 +对战公园 +对战公园 +对战塔 +对战塔 +对战塔 +对战塔 +对战塔 +对战塔 +神秘的地方 +心齐湖畔 +立志湖畔 +立志湖畔 +立志湖畔 +立志湖畔 +睿智湖畔 +隐泉之路 +神秘的地方 +201号道路 +202号道路 +203号道路 +204号道路 +204号道路 +205号道路 +205号道路 +205号道路 +206号道路 +206号道路 +207号道路 +208号道路 +208号道路 +209号道路 +209号道路 +209号道路 +209号道路 +209号道路 +209号道路 +210号道路 +210号道路 +210号道路 +210号道路 +211号道路 +211号道路 +212号道路 +212号道路 +212号道路 +212号道路 +212号道路 +212号道路 +213号道路 +213号道路 +213号道路 +213号道路 +213号道路 +213号道路 +213号道路 +214号道路 +214号道路 +215号道路 +216号道路 +216号道路 +217号道路 +217号道路 +217号道路 +218号道路 +218号道路 +218号道路 +219号道路 +221号道路 +221号道路 +221号道路 +222号道路 +222号道路 +222号道路 +222号道路 +224号道路 +225号道路 +225号道路 +227号道路 +227号道路 +228号道路 +228号道路 +228号道路 +228号道路 +229号道路 +神秘的地方 +双叶镇 +双叶镇 +双叶镇 +双叶镇 +双叶镇 +双叶镇 +双叶镇 +真砂镇 +真砂镇 +真砂镇 +真砂镇 +真砂镇 +真砂镇 +真砂镇 +真砂镇 +真砂镇 +花苑镇 +花苑镇 +花苑镇 +花苑镇 +花苑镇 +花苑镇 +花苑镇 +花苑镇 +随意镇 +随意镇 +随意镇 +随意镇 +随意镇 +随意镇 +随意镇 +随意镇 +随意镇 +随意镇 +神和镇 +神和镇 +神和镇 +神和镇 +神和镇 +神和镇 +神和镇 +神和镇 +神和镇 +生存区 +生存区 +生存区 +生存区 +生存区 +生存区 +生存区 +生存区 +名胜区 +名胜区 +名胜区 +名胜区 +名胜区 +名胜区 +名胜区 +名胜区 +名胜区 +名胜区 +神秘的地方 +神秘的地方 +220号水路 +223号水路 +226号水路 +226号水路 +230号水路 +破海之路 +神秘的地方 +神秘的地方 +神秘的地方 +百代市 +玫瑰公园 +玫瑰公园 +玫瑰公园 +玫瑰公园 +玫瑰公园 +玫瑰公园 +玫瑰公园 +玫瑰公园 +玫瑰公园 +玫瑰公园 +玫瑰公园 +玫瑰公园 +玫瑰公园 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +玫瑰公园 +地下大洞窟 +地下大洞窟 +地下大洞窟 +地下大洞窟 +玫瑰公园 +玫瑰公园 +祝庆市 + + + + + + + + + + + + + + + + + + + + + +玫瑰公园 +玫瑰公园 +玫瑰公园 +玫瑰公园 +玫瑰公园 +玫瑰公园 +玫瑰公园 +玫瑰公园 +玫瑰公园 +玫瑰公园 diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_de.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_de.txt new file mode 100644 index 00000000000..0d252370a76 --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_de.txt @@ -0,0 +1,22 @@ + +Link-Tausch +Link-Tausch +Kanto-Region +Johto-Region +Hoenn-Region +Sinnoh-Region +Fernes Land +---------- +Einall-Region +Kalos-Region +Pokémon-Link +Pokémon GO +Kanto-Region +Hoenn-Region +Alola-Region +Pokémon-Resort +Johto-Region +Pokémon HOME +Kanto-Region +Galar-Region +Sinnoh-Region diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_en.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_en.txt new file mode 100644 index 00000000000..725c8ac901e --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_en.txt @@ -0,0 +1,22 @@ + +a Link Trade +a Link Trade +the Kanto region +the Johto region +the Hoenn region +the Sinnoh region +a distant land +—————— +the Unova region +the Kalos region +Pokémon Link +Pokémon GO +the Kanto region +the Hoenn region +the Alola region +Poké Pelago +the Johto region +Pokémon HOME +the Kanto region +the Galar region +the Sinnoh region diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_es.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_es.txt new file mode 100644 index 00000000000..7e0471e3530 --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_es.txt @@ -0,0 +1,22 @@ + +Intercambio en conexión +Intercambio en conexión +Kanto +Johto +Hoenn +Sinnoh +Tierra lejana +---------- +Teselia +Kalos +Nexo Pokémon +Pokémon GO +Kanto +Hoenn +Alola +Poké Resort +Johto +Pokémon HOME +Kanto +Galar +Sinnoh diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_fr.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_fr.txt new file mode 100644 index 00000000000..c52231bea68 --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_fr.txt @@ -0,0 +1,22 @@ + +Échange en réseau +Échange en réseau +Kanto +Johto +Hoenn +Sinnoh +Pays lointain +---------- +Unys +Kalos +Poké Lien +Pokémon GO +Kanto +Hoenn +Alola +Poké Loisir +Johto +Pokémon HOME +Kanto +Galar +Sinnoh diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_it.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_it.txt new file mode 100644 index 00000000000..b8937080468 --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_it.txt @@ -0,0 +1,22 @@ + +Scambio in link +Scambio in link +Kanto +Johto +Hoenn +Sinnoh +Terra lontana +---------- +Unima +Kalos +Pokémon Link +Pokémon GO +Kanto +Hoenn +Alola +Poké Resort +Johto +Pokémon HOME +Kanto +Galar +Sinnoh diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_ja.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_ja.txt new file mode 100644 index 00000000000..7550a3a5ded --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_ja.txt @@ -0,0 +1,22 @@ + +つうしんこうかん +つうしんこうかん +カントーちほう +ジョウトちほう +ホウエンちほう +シンオウちほう +とおくはなれたとち +---------- +イッシュちほう +カロスちほう +ポケモンリンク +Pokémon GO +カントーちほう +ホウエンちほう +アローラちほう +ポケリゾート +ジョウトちほう +Pokémon HOME +カントーちほう +ガラルちほう +シンオウちほう diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_ko.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_ko.txt new file mode 100644 index 00000000000..6bcb5b60d83 --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_ko.txt @@ -0,0 +1,22 @@ + +통신교환 +통신교환 +관동지방 +성도지방 +호연지방 +신오지방 +아주 먼 땅 +---------- +하나지방 +칼로스지방 +포켓몬링크 +Pokémon GO +관동지방 +호연지방 +알로라지방 +포켓리조트 +성도지방 +Pokémon HOME +관동지방 +가라르지방 +신오지방 diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_zh.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_zh.txt new file mode 100644 index 00000000000..7d0284d2470 --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_30000_zh.txt @@ -0,0 +1,22 @@ + +连接交换 +连接交换 +关都地区 +城都地区 +丰缘地区 +神奥地区 +遥远的土地 +---------- +合众地区 +卡洛斯地区 +宝可梦连接 +Pokémon GO +关都地区 +丰缘地区 +阿罗拉地区 +宝可度假地 +城都地区 +Pokémon HOME +关都地区 +伽勒尔地区 +神奥地区 diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_de.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_de.txt new file mode 100644 index 00000000000..005bf779bd7 --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_de.txt @@ -0,0 +1,87 @@ + +Netter Ort +Ferner Ort +Pokémon-Film + +Pokémon-Film 2019 +Pokémon-Film 2020 +Pokémon-Film 2021 +Pokémon-Film 2022 +Pokémon-Film 2023 +Pokémon-Film 2024 +Pokémon-Zeichentrickserie +Pokémon Center +Pokémon Center Tohoku +WCS + +WCS 2019 +WCS 2020 +WCS 2021 +WCS 2022 +WCS 2023 +WCS 2024 +Worlds + +Worlds 2019 +Worlds 2020 +Worlds 2021 +Worlds 2022 +Worlds 2023 +Worlds 2024 +VGE + +VGE 2019 +VGE 2020 +VGE 2021 +VGE 2022 +VGE 2023 +VGE 2024 +Pokémon-Veranstaltung +Kampfturnier +Videospiel-Veranstaltung +Pokémon Daisuki Club +Pokémon-TV-Programm +Konzert +Online-Geschenk +PGL + +Pokémon-Veranstaltung 2019 +Pokémon-Veranstaltung 2020 +Pokémon-Veranstaltung 2021 +Pokémon-Veranstaltung 2022 +Pokémon-Veranstaltung 2023 +Pokémon-Veranstaltung 2024 +Pokémon-Veranstaltung + +Pokémon-Veranstaltung 2019 +Pokémon-Veranstaltung 2020 +Pokémon-Veranstaltung 2021 +Pokémon-Veranstaltung 2022 +Pokémon-Veranstaltung 2023 +Pokémon-Veranstaltung 2024 +PokéPark + +PokéPark 2019 +PokéPark 2020 +PokéPark 2021 +PokéPark 2022 +PokéPark 2023 +PokéPark 2024 +Veranstaltung +GAME FREAK +Stadion +VGC + +VGC 2019 +VGC 2020 +VGC 2021 +VGC 2022 +VGC 2023 +VGC 2024 +Virtual Console +Pokémon GO +Pokémon Bank +Pokémon-Geschäft +Demoversion +Pokéball Plus +Pokémon HOME diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_en.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_en.txt new file mode 100644 index 00000000000..f924bce88ec --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_en.txt @@ -0,0 +1,87 @@ + +a lovely place +a faraway place +a Pokémon movie + +a 2019 Pokémon movie +a 2020 Pokémon movie +a 2021 Pokémon movie +a 2022 Pokémon movie +a 2023 Pokémon movie +a 2024 Pokémon movie +the Pokémon animated show +a Pokémon Center +Pokémon Center Tohoku +a WCS + +WCS 2019 +WCS 2020 +WCS 2021 +WCS 2022 +WCS 2023 +WCS 2024 +Worlds + +2019 Worlds +2020 Worlds +2021 Worlds +2022 Worlds +2023 Worlds +2024 Worlds +a VGE + +VGE 2019 +VGE 2020 +VGE 2021 +VGE 2022 +VGE 2023 +VGE 2024 +a Pokémon event +a Battle Competition +a game event +the Pokémon Daisuki Club +a Pokémon TV program +a concert +an online present +the PGL + +a 2019 Pokémon event +a 2020 Pokémon event +a 2021 Pokémon event +a 2022 Pokémon event +a 2023 Pokémon event +a 2024 Pokémon event +a Pokémon event + +a 2019 Pokémon event +a 2020 Pokémon event +a 2021 Pokémon event +a 2022 Pokémon event +a 2023 Pokémon event +a 2024 Pokémon event +PokéPark + +PokéPark 2019 +PokéPark 2020 +PokéPark 2021 +PokéPark 2022 +PokéPark 2023 +PokéPark 2024 +an event site +GAME FREAK +a stadium +a VGC event + +the VGC 2019 +the VGC 2020 +the VGC 2021 +the VGC 2022 +the VGC 2023 +the VGC 2024 +a Virtual Console game +Pokémon GO +Pokémon Bank +a Pokémon shop +a demo version +the Poké Ball Plus +Pokémon HOME diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_es.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_es.txt new file mode 100644 index 00000000000..76924a9fa14 --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_es.txt @@ -0,0 +1,87 @@ + +Lugar encantador +Lugar lejano +Película Pokémon + +Película Pokémon 2019 +Película Pokémon 2020 +Película Pokémon 2021 +Película Pokémon 2022 +Película Pokémon 2023 +Película Pokémon 2024 +Dibujos animados Pokémon +Pokémon Center +Pokémon Center Tohoku +WCS + +WCS 2019 +WCS 2020 +WCS 2021 +WCS 2022 +WCS 2023 +WCS 2024 +Worlds + +Worlds 2019 +Worlds 2020 +Worlds 2021 +Worlds 2022 +Worlds 2023 +Worlds 2024 +Evento de Videojuegos + +Evento Videojuegos 2019 +Evento Videojuegos 2020 +Evento Videojuegos 2021 +Evento Videojuegos 2022 +Evento Videojuegos 2023 +Evento Videojuegos 2024 +Evento Pokémon +Torneo +Evento de Videojuegos +Pokémon Daisuki Club +Programa sobre Pokémon +Concierto +Regalo en línea +Pokémon Global Link + +Evento Pokémon 2019 +Evento Pokémon 2020 +Evento Pokémon 2021 +Evento Pokémon 2022 +Evento Pokémon 2023 +Evento Pokémon 2024 +Evento Pokémon + +Evento Pokémon 2019 +Evento Pokémon 2020 +Evento Pokémon 2021 +Evento Pokémon 2022 +Evento Pokémon 2023 +Evento Pokémon 2024 +PokéPark + +PokéPark 2019 +PokéPark 2020 +PokéPark 2021 +PokéPark 2022 +PokéPark 2023 +PokéPark 2024 +Evento +GAME FREAK +Estadio +VGC + +VGC 2019 +VGC 2020 +VGC 2021 +VGC 2022 +VGC 2023 +VGC 2024 +Consola Virtual +Pokémon GO +Banco de Pokémon +Establecimiento Pokémon +Versión de prueba +Poké Ball Plus +Pokémon HOME diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_fr.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_fr.txt new file mode 100644 index 00000000000..d337a33cb4e --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_fr.txt @@ -0,0 +1,87 @@ + +Endroit superbe +Endroit lointain +Film Pokémon + +Film Pokémon 2019 +Film Pokémon 2020 +Film Pokémon 2021 +Film Pokémon 2022 +Film Pokémon 2023 +Film Pokémon 2024 +Dessin animé Pokémon +Pokémon Center +Pokémon Center Tohoku +WCS + +WCS 2019 +WCS 2020 +WCS 2021 +WCS 2022 +WCS 2023 +WCS 2024 +Worlds + +Worlds 2019 +Worlds 2020 +Worlds 2021 +Worlds 2022 +Worlds 2023 +Worlds 2024 +Évènement Jeu Vidéo + +Évènement Jeu Vidéo 2019 +Évènement Jeu Vidéo 2020 +Évènement Jeu Vidéo 2021 +Évènement Jeu Vidéo 2022 +Évènement Jeu Vidéo 2023 +Évènement Jeu Vidéo 2024 +Évènement Pokémon +Compétition +Évènement +Pokémon Daisuki Club +Émission Pokémon +Concert +Cadeau téléchargeable +Pokémon Global Link + +Évènement Pokémon 2019 +Évènement Pokémon 2020 +Évènement Pokémon 2021 +Évènement Pokémon 2022 +Évènement Pokémon 2023 +Évènement Pokémon 2024 +Évènement Pokémon + +Évènement Pokémon 2019 +Évènement Pokémon 2020 +Évènement Pokémon 2021 +Évènement Pokémon 2022 +Évènement Pokémon 2023 +Évènement Pokémon 2024 +PokéPark + +PokéPark 2019 +PokéPark 2020 +PokéPark 2021 +PokéPark 2022 +PokéPark 2023 +PokéPark 2024 +Lieu d’évènement +GAME FREAK +Stade +VGC + +VGC 2019 +VGC 2020 +VGC 2021 +VGC 2022 +VGC 2023 +VGC 2024 +Console virtuelle +Pokémon GO +Banque Pokémon +Magasin Pokémon +Démo +Poké Ball Plus +Pokémon HOME diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_it.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_it.txt new file mode 100644 index 00000000000..931b461ac14 --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_it.txt @@ -0,0 +1,87 @@ + +Luogo grazioso +Luogo remoto +Film Pokémon + +Film Pokémon 2019 +Film Pokémon 2020 +Film Pokémon 2021 +Film Pokémon 2022 +Film Pokémon 2023 +Film Pokémon 2024 +Cartone animato Pokémon +Pokémon Center +Pokémon Center Tohoku +WCS + +WCS 2019 +WCS 2020 +WCS 2021 +WCS 2022 +WCS 2023 +WCS 2024 +Worlds + +Worlds 2019 +Worlds 2020 +Worlds 2021 +Worlds 2022 +Worlds 2023 +Worlds 2024 +Evento di gioco + +Evento di gioco 2019 +Evento di gioco 2020 +Evento di gioco 2021 +Evento di gioco 2022 +Evento di gioco 2023 +Evento di gioco 2024 +Evento Pokémon +Gara +Evento di gioco +Pokémon Daisuki Club +Programma TV Pokémon +Concerto +Regalo online +PGL + +Evento Pokémon 2019 +Evento Pokémon 2020 +Evento Pokémon 2021 +Evento Pokémon 2022 +Evento Pokémon 2023 +Evento Pokémon 2024 +Evento Pokémon + +Evento Pokémon 2019 +Evento Pokémon 2020 +Evento Pokémon 2021 +Evento Pokémon 2022 +Evento Pokémon 2023 +Evento Pokémon 2024 +PokéPark + +PokéPark 2019 +PokéPark 2020 +PokéPark 2021 +PokéPark 2022 +PokéPark 2023 +PokéPark 2024 +Evento +GAME FREAK +Stadio +VGC + +VGC 2019 +VGC 2020 +VGC 2021 +VGC 2022 +VGC 2023 +VGC 2024 +Virtual Console +Pokémon GO +Banca Pokémon +Negozio Pokémon +Demo +Poké Ball Plus +Pokémon HOME diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_ja.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_ja.txt new file mode 100644 index 00000000000..e01db0443ec --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_ja.txt @@ -0,0 +1,87 @@ + +すてきなばしょ +とおいばしょ +ポケモンえいが + +ポケモンえいが19 +ポケモンえいが20 +ポケモンえいが21 +ポケモンえいが22 +ポケモンえいが23 +ポケモンえいが24 +ポケモンアニメ +ポケモンセンター +PCトウホク +WCS + +WCS2019 +WCS2020 +WCS2021 +WCS2022 +WCS2023 +WCS2024 +Worlds + +Worlds2019 +Worlds2020 +Worlds2021 +Worlds2022 +Worlds2023 +Worlds2024 +VGE + +VGE2019 +VGE2020 +VGE2021 +VGE2022 +VGE2023 +VGE2024 +ポケモンイベント +バトルたいかい +ゲームイベント +だいすきクラブ +ポケモンばんぐみ +コンサート +オンラインプレゼント +PGL + +ポケモンイベント19 +ポケモンイベント20 +ポケモンイベント21 +ポケモンイベント22 +ポケモンイベント23 +ポケモンイベント24 +ポケモンフェスタ + +ポケモンフェスタ19 +ポケモンフェスタ20 +ポケモンフェスタ21 +ポケモンフェスタ22 +ポケモンフェスタ23 +ポケモンフェスタ24 +ポケパーク + +ポケパーク2019 +ポケパーク2020 +ポケパーク2021 +ポケパーク2022 +ポケパーク2023 +ポケパーク2024 +イベントかいじょう +ゲームフリーク +スタジアム +VGC + +VGC2019 +VGC2020 +VGC2021 +VGC2022 +VGC2023 +VGC2024 +バーチャルコンソール +Pokémon GO +ポケモンバンク +ポケモンのショップ +たいけんばん +モンスターボール Plus +Pokémon HOME diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_ko.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_ko.txt new file mode 100644 index 00000000000..2439599b50d --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_ko.txt @@ -0,0 +1,87 @@ + +근사한 장소 +먼 곳 +포켓몬영화 + +포켓몬영화19 +포켓몬영화20 +포켓몬영화21 +포켓몬영화22 +포켓몬영화23 +포켓몬영화24 +포켓몬 애니메이션 +포켓몬센터 +PC도호쿠 +WCS + +WCS2019 +WCS2020 +WCS2021 +WCS2022 +WCS2023 +WCS2024 +Worlds + +Worlds2019 +Worlds2020 +Worlds2021 +Worlds2022 +Worlds2023 +Worlds2024 +VGE + +VGE2019 +VGE2020 +VGE2021 +VGE2022 +VGE2023 +VGE2024 +포켓몬이벤트 +배틀 대회 +게임 이벤트 +the Pokémon Daisuki Club +포켓몬 방송 +콘서트 +온라인 선물 +PGL + +포켓몬이벤트19 +포켓몬이벤트20 +포켓몬이벤트21 +포켓몬이벤트22 +포켓몬이벤트23 +포켓몬이벤트24 +포켓몬페스타 + +포켓몬페스타19 +포켓몬페스타20 +포켓몬페스타21 +포켓몬페스타22 +포켓몬페스타23 +포켓몬페스타24 +포켓파크 + +포켓파크2019 +포켓파크2020 +포켓파크2021 +포켓파크2022 +포켓파크2023 +포켓파크2024 +이벤트회장 +게임프리크 +스타디움 +VGC + +VGC2019 +VGC2020 +VGC2021 +VGC2022 +VGC2023 +VGC2024 +버추얼 콘솔 +Pokémon GO +포켓몬 뱅크 +a Pokémon shop +체험판 +몬스터볼 Plus +Pokémon HOME diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_zh.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_zh.txt new file mode 100644 index 00000000000..80a89feb984 --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_40000_zh.txt @@ -0,0 +1,87 @@ + +美丽的地方 +遥远的地方 +宝可梦电影 + +宝可梦电影19 +宝可梦电影20 +宝可梦电影21 +宝可梦电影22 +宝可梦电影23 +宝可梦电影24 +宝可梦动画片 +宝可梦中心 +东北PC +WCS + +WCS2019 +WCS2020 +WCS2021 +WCS2022 +WCS2023 +WCS2024 +Worlds + +Worlds2019 +Worlds2020 +Worlds2021 +Worlds2022 +Worlds2023 +Worlds2024 +VGE + +VGE2019 +VGE2020 +VGE2021 +VGE2022 +VGE2023 +VGE2024 +宝可梦活动 +对战大赛 +游戏活动 +发烧友俱乐部 +宝可梦节目 +音乐会 +在线礼物 +PGL + +宝可梦活动19 +宝可梦活动20 +宝可梦活动21 +宝可梦活动22 +宝可梦活动23 +宝可梦活动24 +宝可梦庆典 + +宝可梦庆典19 +宝可梦庆典20 +宝可梦庆典21 +宝可梦庆典22 +宝可梦庆典23 +宝可梦庆典24 +宝可公园 + +宝可公园2019 +宝可公园2020 +宝可公园2021 +宝可公园2022 +宝可公园2023 +宝可公园2024 +活动会场 +GAME FREAK +竞技场 +VGC + +VGC2019 +VGC2020 +VGC2021 +VGC2022 +VGC2023 +VGC2024 +Virtual Console +Pokémon GO +宝可梦虚拟银行 +宝可梦的店 +体验版 +精灵球 Plus +Pokémon HOME diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_de.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_de.txt new file mode 100644 index 00000000000..6f62cb6c8bf --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_de.txt @@ -0,0 +1,11 @@ + +Ferne Person +Hortleiterinnen +Schatzsucher +Dame der Heißen Quellen +Urs +Hort-Pärchen +Reisender + + +Hort-Pärchen diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_en.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_en.txt new file mode 100644 index 00000000000..5202de1e5ab --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_en.txt @@ -0,0 +1,11 @@ + +a stranger +a Nursery worker +a treasure hunter +an old hot-springs visitor +Riley +Nursery Couple +Traveling Man + + +Nursery Couple diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_es.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_es.txt new file mode 100644 index 00000000000..319e1110d71 --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_es.txt @@ -0,0 +1,11 @@ + +Persona lejana +Cuidados Pokémon +Buscatesoros +Anciana del Balneario +Quinoa +Cuidados Pokémon +Viajero + + +Cuidados Pokémon diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_fr.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_fr.txt new file mode 100644 index 00000000000..3f28b1a7eb9 --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_fr.txt @@ -0,0 +1,11 @@ + +Personne lointaine +Responsable de la Garderie +Chercheur de Trésors +Dame des Eaux Thermales +Armand +Garderie +Voyageur + + +Garderie diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_it.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_it.txt new file mode 100644 index 00000000000..214279867dc --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_it.txt @@ -0,0 +1,11 @@ + +Persona lontana +Staff dell’ostello +Cercatesori +Vecchina delle terme +Marisio +Coppia ostello +Viaggiatore + + +Coppia ostello diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_ja.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_ja.txt new file mode 100644 index 00000000000..75473d24a7c --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_ja.txt @@ -0,0 +1,11 @@ + +とおくにいるひと +あずかりやさん +トレジャーハンター +おんせんばあさん +ゲン +あずかりやふうふ +たびのおじさん + + +あずかりやふうふ diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_ko.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_ko.txt new file mode 100644 index 00000000000..d95b154bde0 --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_ko.txt @@ -0,0 +1,11 @@ + +멀리 있는 사람 +맡기미집 +트레져헌터 +온천할머니 +현이 +맡기미집부부 +나그네아저씨 + + +맡기미집부부 diff --git a/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_zh.txt b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_zh.txt new file mode 100644 index 00000000000..9afe1211608 --- /dev/null +++ b/PKHeX.Core/Resources/text/locations/gen8b/text_bdsp_60000_zh.txt @@ -0,0 +1,11 @@ + +远处的人 +寄放屋 +寻宝猎人 +温泉婆婆 +亚玄 +寄放屋夫妻 +旅行中的大叔 + + +寄放屋夫妻 diff --git a/PKHeX.Core/Resources/text/other/de/text_Games_de.txt b/PKHeX.Core/Resources/text/other/de/text_Games_de.txt index 807f9a8b8e3..8a586234162 100644 --- a/PKHeX.Core/Resources/text/other/de/text_Games_de.txt +++ b/PKHeX.Core/Resources/text/other/de/text_Games_de.txt @@ -43,4 +43,8 @@ Kristall Let's Go, Pikachu! Let's Go, Evoli! Schwert -Schild \ No newline at end of file +Schild + + +Strahlender Diamant +Leuchtende Perle \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/de/text_Ribbons_de.txt b/PKHeX.Core/Resources/text/other/de/text_Ribbons_de.txt index c3d6362dab1..c08c731d1ab 100644 --- a/PKHeX.Core/Resources/text/other/de/text_Ribbons_de.txt +++ b/PKHeX.Core/Resources/text/other/de/text_Ribbons_de.txt @@ -148,4 +148,6 @@ RibbonMarkUnsure Selbstzweifel-Zeichen RibbonMarkHumble Arglos-Zeichen RibbonMarkThorny Scheinheilig-Zeichen RibbonMarkVigor Elan-Zeichen -RibbonMarkSlump Formtief-Zeichen \ No newline at end of file +RibbonMarkSlump Formtief-Zeichen +RibbonTwinklingStar Glitzersternband +RibbonPioneer Pioneer \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/de/text_Wallpaper_de.txt b/PKHeX.Core/Resources/text/other/de/text_Wallpaper_de.txt index fe77c8b7caa..1d9c4f7bd94 100644 --- a/PKHeX.Core/Resources/text/other/de/text_Wallpaper_de.txt +++ b/PKHeX.Core/Resources/text/other/de/text_Wallpaper_de.txt @@ -21,4 +21,12 @@ Spezialmotiv 4 Spezialmotiv 5 Spezialmotiv 6 Spezialmotiv 7 -Spezialmotiv 8 \ No newline at end of file +Spezialmotiv 8 +Spezialmotiv 9 +Spezialmotiv 10 +Spezialmotiv 11 +Spezialmotiv 12 +Spezialmotiv 13 +Spezialmotiv 14 +Spezialmotiv 15 +Spezialmotiv 16 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/en/text_Games_en.txt b/PKHeX.Core/Resources/text/other/en/text_Games_en.txt index 1cd8f6b07d3..a5fc3a7eb4c 100644 --- a/PKHeX.Core/Resources/text/other/en/text_Games_en.txt +++ b/PKHeX.Core/Resources/text/other/en/text_Games_en.txt @@ -43,4 +43,8 @@ Crystal Let's Go, Pikachu! Let's Go, Eevee! Sword -Shield \ No newline at end of file +Shield + + +Brilliant Diamond +Shining Pearl \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/en/text_Ribbons_en.txt b/PKHeX.Core/Resources/text/other/en/text_Ribbons_en.txt index b7fbbea7cf4..d1ba67b6f66 100644 --- a/PKHeX.Core/Resources/text/other/en/text_Ribbons_en.txt +++ b/PKHeX.Core/Resources/text/other/en/text_Ribbons_en.txt @@ -148,4 +148,6 @@ RibbonMarkUnsure Unsure Mark RibbonMarkHumble Humble Mark RibbonMarkThorny Thorny Mark RibbonMarkVigor Vigor Mark -RibbonMarkSlump Slump Mark \ No newline at end of file +RibbonMarkSlump Slump Mark +RibbonTwinklingStar Twinkling Star +RibbonPioneer Pioneer \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/en/text_Wallpaper_en.txt b/PKHeX.Core/Resources/text/other/en/text_Wallpaper_en.txt index 08ab29b674d..69132267486 100644 --- a/PKHeX.Core/Resources/text/other/en/text_Wallpaper_en.txt +++ b/PKHeX.Core/Resources/text/other/en/text_Wallpaper_en.txt @@ -21,4 +21,12 @@ SPECIAL 4 SPECIAL 5 SPECIAL 6 SPECIAL 7 -SPECIAL 8 \ No newline at end of file +SPECIAL 8 +SPECIAL 9 +SPECIAL 10 +SPECIAL 11 +SPECIAL 12 +SPECIAL 13 +SPECIAL 14 +SPECIAL 15 +SPECIAL 16 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/es/text_Games_es.txt b/PKHeX.Core/Resources/text/other/es/text_Games_es.txt index c8478209eb5..d2c6263a40c 100644 --- a/PKHeX.Core/Resources/text/other/es/text_Games_es.txt +++ b/PKHeX.Core/Resources/text/other/es/text_Games_es.txt @@ -43,4 +43,8 @@ Cristal Let's Go, Pikachu! Let's Go, Eevee! Espada -Escudo \ No newline at end of file +Escudo + + +Diamante Brillante +Perla Reluciente \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/es/text_Ribbons_es.txt b/PKHeX.Core/Resources/text/other/es/text_Ribbons_es.txt index abcf870b6fe..a7fac530db5 100644 --- a/PKHeX.Core/Resources/text/other/es/text_Ribbons_es.txt +++ b/PKHeX.Core/Resources/text/other/es/text_Ribbons_es.txt @@ -148,4 +148,6 @@ RibbonMarkUnsure Emblema Inseguridad RibbonMarkHumble Emblema Sencillez RibbonMarkThorny Emblema Altanería RibbonMarkVigor Emblema Vigor -RibbonMarkSlump Emblema Extenuación \ No newline at end of file +RibbonMarkSlump Emblema Extenuación +RibbonTwinklingStar Cinta Estrella Rutilante +RibbonPioneer Pioneer \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/es/text_Wallpaper_es.txt b/PKHeX.Core/Resources/text/other/es/text_Wallpaper_es.txt index 1f573b099e8..a4a70686d83 100644 --- a/PKHeX.Core/Resources/text/other/es/text_Wallpaper_es.txt +++ b/PKHeX.Core/Resources/text/other/es/text_Wallpaper_es.txt @@ -21,4 +21,12 @@ Especial 4 Especial 5 Especial 6 Especial 7 -Especial 8 \ No newline at end of file +Especial 8 +Especial 9 +Especial 10 +Especial 11 +Especial 12 +Especial 13 +Especial 14 +Especial 15 +Especial 16 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/fr/text_Games_fr.txt b/PKHeX.Core/Resources/text/other/fr/text_Games_fr.txt index dca412a90e0..a019719ef61 100644 --- a/PKHeX.Core/Resources/text/other/fr/text_Games_fr.txt +++ b/PKHeX.Core/Resources/text/other/fr/text_Games_fr.txt @@ -43,4 +43,8 @@ Cristal Let's Go, Pikachu Let's Go, Évoli Épée -Bouclier \ No newline at end of file +Bouclier + + +Diamant Étincelant +Perle Scintillante \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/fr/text_Ribbons_fr.txt b/PKHeX.Core/Resources/text/other/fr/text_Ribbons_fr.txt index 3b49008deec..ef9b711ec30 100644 --- a/PKHeX.Core/Resources/text/other/fr/text_Ribbons_fr.txt +++ b/PKHeX.Core/Resources/text/other/fr/text_Ribbons_fr.txt @@ -149,3 +149,5 @@ RibbonMarkHumble Insigne Discrétion RibbonMarkThorny Insigne Frime RibbonMarkVigor Insigne Énergie RibbonMarkSlump Insigne Blessure +RibbonTwinklingStar Ruban Étoile Brillante +RibbonPioneer Pioneer \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/fr/text_Wallpaper_fr.txt b/PKHeX.Core/Resources/text/other/fr/text_Wallpaper_fr.txt index 0f51195596b..1f0fd968b67 100644 --- a/PKHeX.Core/Resources/text/other/fr/text_Wallpaper_fr.txt +++ b/PKHeX.Core/Resources/text/other/fr/text_Wallpaper_fr.txt @@ -21,4 +21,12 @@ Spécial 4 Spécial 5 Spécial 6 Spécial 7 -Spécial 8 \ No newline at end of file +Spécial 8 +Spécial 9 +Spécial 10 +Spécial 11 +Spécial 12 +Spécial 13 +Spécial 14 +Spécial 15 +Spécial 16 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/it/text_Games_it.txt b/PKHeX.Core/Resources/text/other/it/text_Games_it.txt index 8949fbb4ce9..38af96540d9 100644 --- a/PKHeX.Core/Resources/text/other/it/text_Games_it.txt +++ b/PKHeX.Core/Resources/text/other/it/text_Games_it.txt @@ -43,4 +43,8 @@ Cristallo Let's Go, Pikachu! Let's Go, Eevee! Spada -Scudo \ No newline at end of file +Scudo + + +Diamante Lucente +Perla Splendente \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/it/text_Ribbons_it.txt b/PKHeX.Core/Resources/text/other/it/text_Ribbons_it.txt index 162ec877bc2..cf939af30c2 100644 --- a/PKHeX.Core/Resources/text/other/it/text_Ribbons_it.txt +++ b/PKHeX.Core/Resources/text/other/it/text_Ribbons_it.txt @@ -148,4 +148,6 @@ RibbonMarkUnsure Emblema Insicurezza RibbonMarkHumble Emblema Ingenuità RibbonMarkThorny Emblema Artificio RibbonMarkVigor Emblema Vitalità -RibbonMarkSlump Emblema Sottotono \ No newline at end of file +RibbonMarkSlump Emblema Sottotono +RibbonTwinklingStar Fiocco Stella Brillante +RibbonPioneer Pioneer \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/it/text_Wallpaper_it.txt b/PKHeX.Core/Resources/text/other/it/text_Wallpaper_it.txt index 11f0d3b9574..6f21a660bce 100644 --- a/PKHeX.Core/Resources/text/other/it/text_Wallpaper_it.txt +++ b/PKHeX.Core/Resources/text/other/it/text_Wallpaper_it.txt @@ -21,4 +21,12 @@ Speciale 4 Speciale 5 Speciale 6 Speciale 7 -Speciale 8 \ No newline at end of file +Speciale 8 +Speciale 9 +Speciale 10 +Speciale 11 +Speciale 12 +Speciale 13 +Speciale 14 +Speciale 15 +Speciale 16 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/ja/text_Games_ja.txt b/PKHeX.Core/Resources/text/other/ja/text_Games_ja.txt index 24683459ca2..61b20dedd9a 100644 --- a/PKHeX.Core/Resources/text/other/ja/text_Games_ja.txt +++ b/PKHeX.Core/Resources/text/other/ja/text_Games_ja.txt @@ -43,4 +43,8 @@ GO Let's Go! ピカチュウ Let's Go! イーブイ ソード -シールド \ No newline at end of file +シールド + + +ブリリアントダイヤモンド +シャイニングパール \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/ja/text_Ribbons_ja.txt b/PKHeX.Core/Resources/text/other/ja/text_Ribbons_ja.txt index b65b722c92e..831fcb9c214 100644 --- a/PKHeX.Core/Resources/text/other/ja/text_Ribbons_ja.txt +++ b/PKHeX.Core/Resources/text/other/ja/text_Ribbons_ja.txt @@ -148,4 +148,6 @@ RibbonMarkUnsure ふしんのあかし RibbonMarkHumble ぼくとつのあかし RibbonMarkThorny ふじゅんのあかし RibbonMarkVigor げんきのあかし -RibbonMarkSlump ふちょうのあかし \ No newline at end of file +RibbonMarkSlump ふちょうのあかし +RibbonTwinklingStar トゥインクルスターリボン +RibbonPioneer Pioneer \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/ja/text_Wallpaper_ja.txt b/PKHeX.Core/Resources/text/other/ja/text_Wallpaper_ja.txt index 73e2c63fc34..93f117da616 100644 --- a/PKHeX.Core/Resources/text/other/ja/text_Wallpaper_ja.txt +++ b/PKHeX.Core/Resources/text/other/ja/text_Wallpaper_ja.txt @@ -21,4 +21,12 @@ スペシャル5 スペシャル6 スペシャル7 -スペシャル8 \ No newline at end of file +スペシャル8 +スペシャル9 +スペシャル10 +スペシャル11 +スペシャル12 +スペシャル13 +スペシャル14 +スペシャル15 +スペシャル16 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/ko/text_Games_ko.txt b/PKHeX.Core/Resources/text/other/ko/text_Games_ko.txt index 18a0439ccc3..5cb07cef7d3 100644 --- a/PKHeX.Core/Resources/text/other/ko/text_Games_ko.txt +++ b/PKHeX.Core/Resources/text/other/ko/text_Games_ko.txt @@ -43,4 +43,8 @@ Y 레츠고! 피카츄 레츠고! 이브이 소드 -실드 \ No newline at end of file +실드 + + +브릴리언트 다이아몬드 +샤이닝 펄 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/ko/text_Ribbons_ko.txt b/PKHeX.Core/Resources/text/other/ko/text_Ribbons_ko.txt index 5a547937b1c..c6f04a81824 100644 --- a/PKHeX.Core/Resources/text/other/ko/text_Ribbons_ko.txt +++ b/PKHeX.Core/Resources/text/other/ko/text_Ribbons_ko.txt @@ -148,4 +148,6 @@ RibbonMarkUnsure 불신의증표 RibbonMarkHumble 순박의증표 RibbonMarkThorny 불순의증표 RibbonMarkVigor 기력의증표 -RibbonMarkSlump 피곤의증표 \ No newline at end of file +RibbonMarkSlump 피곤의증표 +RibbonTwinklingStar 트윙클스타리본 +RibbonPioneer Pioneer \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/ko/text_Wallpaper_ko.txt b/PKHeX.Core/Resources/text/other/ko/text_Wallpaper_ko.txt index 8b53b02df6b..8a536da3bf5 100644 --- a/PKHeX.Core/Resources/text/other/ko/text_Wallpaper_ko.txt +++ b/PKHeX.Core/Resources/text/other/ko/text_Wallpaper_ko.txt @@ -21,4 +21,12 @@ 스페셜5 스페셜6 스페셜7 -스페셜8 \ No newline at end of file +스페셜8 +스페셜9 +스페셜10 +스페셜11 +스페셜12 +스페셜13 +스페셜14 +스페셜15 +스페셜16 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/zh/text_Games_zh.txt b/PKHeX.Core/Resources/text/other/zh/text_Games_zh.txt index ebf4abb9979..1f2aa2c13dd 100644 --- a/PKHeX.Core/Resources/text/other/zh/text_Games_zh.txt +++ b/PKHeX.Core/Resources/text/other/zh/text_Games_zh.txt @@ -44,3 +44,7 @@ Let's Go!皮卡丘 Let's Go!伊布 剑 盾 + + +晶燦鑽石 +明亮珍珠 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/zh/text_Ribbons_zh.txt b/PKHeX.Core/Resources/text/other/zh/text_Ribbons_zh.txt index 5ddc43d4b2b..fc3a817714a 100644 --- a/PKHeX.Core/Resources/text/other/zh/text_Ribbons_zh.txt +++ b/PKHeX.Core/Resources/text/other/zh/text_Ribbons_zh.txt @@ -148,4 +148,6 @@ RibbonMarkUnsure 自卑之证 RibbonMarkHumble 木讷之证 RibbonMarkThorny 不纯之证 RibbonMarkVigor 活力之证 -RibbonMarkSlump 不振之证 \ No newline at end of file +RibbonMarkSlump 不振之证 +RibbonTwinklingStar 闪亮之星奖章 +RibbonPioneer Pioneer \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/other/zh/text_Wallpaper_zh.txt b/PKHeX.Core/Resources/text/other/zh/text_Wallpaper_zh.txt index fed5c41bbf8..758539b694e 100644 --- a/PKHeX.Core/Resources/text/other/zh/text_Wallpaper_zh.txt +++ b/PKHeX.Core/Resources/text/other/zh/text_Wallpaper_zh.txt @@ -21,4 +21,12 @@ 特典5 特典6 特典7 -特典8 \ No newline at end of file +特典8 +特典9 +特典10 +特典11 +特典12 +特典13 +特典14 +特典15 +特典16 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/script/gen8/flag_bdsp_en.txt b/PKHeX.Core/Resources/text/script/gen8/flag_bdsp_en.txt new file mode 100644 index 00000000000..f775867c553 --- /dev/null +++ b/PKHeX.Core/Resources/text/script/gen8/flag_bdsp_en.txt @@ -0,0 +1,37 @@ +230 * FE_PC_SHINOU_ZUKAN_COMP + +1421 * FE_BTLTW_N_SINGLE_SUSPENSION +1422 * FE_BTLTW_N_DOUBLE_SUSPENSION +1423 * FE_BTLTW_M_SINGLE_SUSPENSION +1424 * FE_BTLTW_M_DOUBLE_SUSPENSION + +1426 * FE_TOWER_MASTER_WINED + +108 * FE_HIDEN_01_GET +109 * FE_HIDEN_02_GET +110 * FE_HIDEN_03_GET +111 * FE_HIDEN_04_GET +112 * FE_HIDEN_05_GET +113 * FE_HIDEN_06_GET +114 * FE_HIDEN_07_GET +115 * FE_HIDEN_08_GET + +1283 r FE_D10R0202POKE_01 +1284 r FE_D10R0202POKE_02 +1285 r FE_D10R0202POKE_03 +1286 r FE_D10R0301POKE_01 +1287 r FE_D10R0301POKE_02 +1288 r FE_D10R0301POKE_03 +1289 r FE_D10R0302POKE_01 +1290 r FE_D10R0302POKE_02 +1291 r FE_D10R0302POKE_03 +1292 r FE_D10R0303POKE_01 +1293 r FE_D10R0303POKE_02 +1294 r FE_D10R0303POKE_03 +1295 r FE_D10R0501POKE_01 +1296 r FE_D10R0502POKE_01 +1297 r FE_D10R0401POKE_01 +1298 r FE_D10R0402POKE_01 +1299 r FE_D10R0403POKE_01 +1300 r FE_D10R0601POKE_01 +1301 r FE_D10R0901POKE_01 \ No newline at end of file diff --git a/PKHeX.Core/Resources/text/script/gen8/system_bdsp_en.txt b/PKHeX.Core/Resources/text/script/gen8/system_bdsp_en.txt new file mode 100644 index 00000000000..6540593037d --- /dev/null +++ b/PKHeX.Core/Resources/text/script/gen8/system_bdsp_en.txt @@ -0,0 +1,37 @@ +124 * BADGE_ID_C03 +125 * BADGE_ID_C04 +126 * BADGE_ID_C07 +127 * BADGE_ID_C06 +128 * BADGE_ID_C05 +129 * BADGE_ID_C02 +130 * BADGE_ID_C09 +131 * BADGE_ID_C08 + +5 * SYS_FLAG_GAME_CLEAR +9 * SYS_FLAG_CON_STYLE_MASTER +10 * SYS_FLAG_CON_BEAUTIFUL_MASTER +11 * SYS_FLAG_CON_CUTE_MASTER +12 * SYS_FLAG_CON_CLEVER_MASTER +13 * SYS_FLAG_CON_STRONG_MASTER + +758 * SYS_FLAG_CON_STYLE_NORMAL +759 * SYS_FLAG_CON_STYLE_GREAT +760 * SYS_FLAG_CON_STYLE_ULTRA +761 * SYS_FLAG_CON_BEAUTIFUL_NORMAL +762 * SYS_FLAG_CON_BEAUTIFUL_GREAT +763 * SYS_FLAG_CON_BEAUTIFUL_ULTRA +764 * SYS_FLAG_CON_CUTE_NORMAL +765 * SYS_FLAG_CON_CUTE_GREAT +766 * SYS_FLAG_CON_CUTE_ULTRA +767 * SYS_FLAG_CON_CLEVER_NORMAL +768 * SYS_FLAG_CON_CLEVER_GREAT +769 * SYS_FLAG_CON_CLEVER_ULTRA +770 * SYS_FLAG_CON_STRONG_NORMAL +771 * SYS_FLAG_CON_STRONG_GREAT +772 * SYS_FLAG_CON_STRONG_ULTRA + +780 * SYS_NO_CAP_MODEL + +792 * SYS_FLAG_CON_FUR_NORMAL +793 * SYS_FLAG_CON_FUR_GREAT +794 * SYS_FLAG_CON_FUR_ULTRA diff --git a/PKHeX.Core/Resources/text/script/gen8/work_bdsp_en.txt b/PKHeX.Core/Resources/text/script/gen8/work_bdsp_en.txt new file mode 100644 index 00000000000..804301c473d --- /dev/null +++ b/PKHeX.Core/Resources/text/script/gen8/work_bdsp_en.txt @@ -0,0 +1,27 @@ +250 * SYS_WORK_FIRST_POKE_NO + +262 * SYS_WORK_UG_TALK_COUNT +273 * SYS_WORK_UG_TALK_COUNT2 + +267 * SYS_WORK_HAIHU_EVENT01 +268 * SYS_WORK_HAIHU_EVENT02 +269 * SYS_WORK_HAIHU_EVENT03 +275 * HAIHUEVENT_ID_D30 +276 * HAIHUEVENT_ID_D18 +277 * HAIHUEVENT_ID_D05 +330 * HAIHUEVENT_ID_C04 + +254 * SYS_WORK_HIDEMAP_01 +255 * SYS_WORK_HIDEMAP_02 +256 * SYS_WORK_HIDEMAP_03 +257 * SYS_WORK_HIDEMAP_04 + +278 * HIDEMAP_ID_D15 +279 * HIDEMAP_ID_D30 +280 * HIDEMAP_ID_L04 +281 * HIDEMAP_ID_D18 +291 * HIDEMAP_ID_C10 +292 * HIDEMAP_ID_D10R0101 + +331 * WK_PLAYER_BIRTH_MOUNTH +332 * WK_PLAYER_BIRTH_DAY diff --git a/PKHeX.Core/Ribbons/IRibbonSetAffixed.cs b/PKHeX.Core/Ribbons/IRibbonSetAffixed.cs new file mode 100644 index 00000000000..e39a8be757a --- /dev/null +++ b/PKHeX.Core/Ribbons/IRibbonSetAffixed.cs @@ -0,0 +1,7 @@ +namespace PKHeX.Core +{ + public interface IRibbonSetAffixed + { + sbyte AffixedRibbon { get; set; } + } +} diff --git a/PKHeX.Core/Ribbons/IRibbonSetCommon8.cs b/PKHeX.Core/Ribbons/IRibbonSetCommon8.cs index c65be82deff..0fd9726975d 100644 --- a/PKHeX.Core/Ribbons/IRibbonSetCommon8.cs +++ b/PKHeX.Core/Ribbons/IRibbonSetCommon8.cs @@ -6,6 +6,8 @@ public interface IRibbonSetCommon8 bool RibbonChampionGalar { get; set; } bool RibbonTowerMaster { get; set; } bool RibbonMasterRank { get; set; } + bool RibbonTwinklingStar { get; set; } + bool RibbonPioneer { get; set; } } internal static partial class RibbonExtensions @@ -14,6 +16,7 @@ internal static partial class RibbonExtensions { nameof(IRibbonSetCommon8.RibbonChampionGalar), nameof(IRibbonSetCommon8.RibbonTowerMaster), nameof(IRibbonSetCommon8.RibbonMasterRank), + nameof(IRibbonSetCommon8.RibbonTwinklingStar), nameof(IRibbonSetCommon8.RibbonPioneer), }; internal static bool[] RibbonBits(this IRibbonSetCommon8 set) @@ -23,6 +26,8 @@ internal static bool[] RibbonBits(this IRibbonSetCommon8 set) set.RibbonChampionGalar, set.RibbonTowerMaster, set.RibbonMasterRank, + set.RibbonTwinklingStar, + set.RibbonPioneer, }; } diff --git a/PKHeX.Core/Ribbons/RibbonIndex.cs b/PKHeX.Core/Ribbons/RibbonIndex.cs index 545b3aab2c4..3a5ac34eb48 100644 --- a/PKHeX.Core/Ribbons/RibbonIndex.cs +++ b/PKHeX.Core/Ribbons/RibbonIndex.cs @@ -104,6 +104,9 @@ public enum RibbonIndex MarkThorny, MarkVigor, MarkSlump, + + TwinklingStar, + Pioneer, } public static class RibbonIndexExtensions diff --git a/PKHeX.Core/Saves/Access/ISaveBlock8BS.cs b/PKHeX.Core/Saves/Access/ISaveBlock8BS.cs new file mode 100644 index 00000000000..e7d76c9c7e6 --- /dev/null +++ b/PKHeX.Core/Saves/Access/ISaveBlock8BS.cs @@ -0,0 +1,9 @@ +namespace PKHeX.Core +{ + /// + /// Interface for Accessing named blocks within a Generation 8 BD/SP save file. + /// + public interface ISaveBlock8BS + { + } +} diff --git a/PKHeX.Core/Saves/SAV8BS.cs b/PKHeX.Core/Saves/SAV8BS.cs new file mode 100644 index 00000000000..a636efe6226 --- /dev/null +++ b/PKHeX.Core/Saves/SAV8BS.cs @@ -0,0 +1,233 @@ +using System; +using System.Collections.Generic; +using System.Security.Cryptography; + +#nullable disable + +namespace PKHeX.Core +{ + public class SAV8BS : SaveFile, ISaveFileRevision + { + // Save Data Attributes + protected internal override string ShortSummary => $"{OT} ({Version})"; + public override string Extension => string.Empty; + + public override IReadOnlyList PKMExtensions => Array.FindAll(PKM.Extensions, f => + { + int gen = f[^1] - 0x30; + return gen <= 8; + }); + + public SAV8BS(byte[] data, bool exportable = true) : base(data, exportable) + { + Work = new FlagWork8b(this, 0x00004); + Items = new MyItem8b(this, 0x0563C); + PartyInfo = new Party8b(this, 0x14098); + BoxLayout = new BoxLayout8b(this, 0x148AA); + Config = new ConfigSave8b(this, 0x79B74); // size: 0x40 + MyStatus = new MyStatus8b(this, 0x79BB4); // size: 0x50 + Played = new PlayTime8b(this, 0x79C04); // size: 0x04 + Contest = new Contest8b(this, 0x79C08); // size: 0x720 + Zukan = new Zukan8b(this, 0x7A328); + + Initialize(); + } + + public SAV8BS() : this(new byte[SaveUtil.SIZE_G8BDSP_1], false) => SaveRevision = (int)Gem8Version.V1_1; + + private void Initialize() + { + Box = 0x14EF4; + Party = PartyInfo.Offset; + PokeDex = Zukan.PokeDex; + BoxLayout.LoadBattleTeams(); + } + + public override bool HasEvents => true; + + // Configuration + protected override int SIZE_STORED => PokeCrypto.SIZE_8STORED; + protected override int SIZE_PARTY => PokeCrypto.SIZE_8PARTY; + public override int SIZE_BOXSLOT => PokeCrypto.SIZE_8PARTY; + public override PKM BlankPKM => new PB8(); + public override Type PKMType => typeof(PB8); + + public override int BoxCount => BoxLayout8b.BoxCount; + public override int MaxEV => 252; + + public override int Generation => 8; + protected override int EventConstMax => 500; + public override PersonalTable Personal => PersonalTable.BDSP; + public override int OTLength => 12; + public override int NickLength => 12; + public override int MaxMoveID => Legal.MaxMoveID_8b; + public override int MaxSpeciesID => Legal.MaxSpeciesID_8b; + public override int MaxItemID => Legal.MaxItemID_8b; + public override int MaxBallID => Legal.MaxBallID_8b; + public override int MaxGameID => Legal.MaxGameID_8b; + public override int MaxAbilityID => Legal.MaxAbilityID_8b; + + public int SaveRevision + { + get => BitConverter.ToInt32(Data, 0); + init => BitConverter.GetBytes(value).CopyTo(Data, 0); + } + + public string SaveRevisionString => (Gem8Version)SaveRevision switch + { + Gem8Version.V1_0 => "-1.0.0", // Launch Revision + Gem8Version.V1_1 => "-1.1.0", // 1.1.0 + _ => throw new ArgumentOutOfRangeException(nameof(SaveRevision)), + }; + + public override IReadOnlyList HeldItems => Legal.HeldItems_BS; + protected override SaveFile CloneInternal() => new SAV8BS((byte[])(Data.Clone())); + + protected override byte[] GetFinalData() + { + BoxLayout.SaveBattleTeams(); + return base.GetFinalData(); + } + + protected void ReloadBattleTeams() + { + if (!State.Exportable) + BoxLayout.ClearBattleTeams(); + else // Valid slot locking info present + BoxLayout.LoadBattleTeams(); + } + + #region Checksums + + private const int HashOffset = SaveUtil.SIZE_G8BDSP - 0x10; + private Span CurrentHash => Data.AsSpan(SaveUtil.SIZE_G8BDSP - 0x10, 0x10); + + private byte[] ComputeHash() + { + CurrentHash.Fill(0); + using var md5 = new MD5CryptoServiceProvider(); + return md5.ComputeHash(Data); + } + + protected override void SetChecksums() => ComputeHash().CopyTo(Data, HashOffset); + public override string ChecksumInfo => !ChecksumsValid ? "MD5 Hash Invalid" : string.Empty; + + public override bool ChecksumsValid + { + get + { + // Cache hash and restore it after computation + var original = CurrentHash.ToArray(); + var newHash = ComputeHash(); + var result = newHash.AsSpan().SequenceEqual(original); + original.AsSpan().CopyTo(CurrentHash); + return result; + } + } + + #endregion + + protected override PKM GetPKM(byte[] data) => new PB8(data); + protected override byte[] DecryptPKM(byte[] data) => PokeCrypto.DecryptArray8(data); + + #region Blocks + // public Box8 BoxInfo { get; } + public FlagWork8b Work { get; } + public MyItem8b Items { get; } + public Party8b PartyInfo { get; } + // public MyItem Items { get; } + public BoxLayout8b BoxLayout { get; } + public ConfigSave8b Config { get; } + public MyStatus8b MyStatus { get; } + public PlayTime8b Played { get; } + public Contest8b Contest { get; } + // public Misc8 Misc { get; } + public Zukan8b Zukan { get; } + #endregion + + public override GameVersion Version => Game switch + { + (int)GameVersion.BD => GameVersion.BD, + (int)GameVersion.SP => GameVersion.SP, + _ => GameVersion.Invalid, + }; + + public override string GetString(byte[] data, int offset, int length) => StringConverter.GetString7b(data, offset, length); + + public override byte[] SetString(string value, int maxLength, int PadToSize = 0, ushort PadWith = 0) + { + if (PadToSize == 0) + PadToSize = maxLength + 1; + return StringConverter.SetString7b(value, maxLength, PadToSize, PadWith); + } + + public override bool GetEventFlag(int flagNumber) => Work.GetFlag(flagNumber); + public override void SetEventFlag(int flagNumber, bool value) => Work.SetFlag(flagNumber, value); + + // Player Information + public override int TID { get => MyStatus.TID; set => MyStatus.TID = value; } + public override int SID { get => MyStatus.SID; set => MyStatus.SID = value; } + public override int Game { get => MyStatus.Game; set => MyStatus.Game = value; } + public override int Gender { get => MyStatus.Male ? 0 : 1; set => MyStatus.Male = value == 0; } + public override int Language { get => Config.Language; set => Config.Language = value; } + public override string OT { get => MyStatus.OT; set => MyStatus.OT = value; } + public override uint Money { get => MyStatus.Money; set => MyStatus.Money = value; } + + public override int PlayedHours { get => Played.PlayedHours; set => Played.PlayedHours = (ushort)value; } + public override int PlayedMinutes { get => Played.PlayedMinutes; set => Played.PlayedMinutes = (byte)value; } + public override int PlayedSeconds { get => Played.PlayedSeconds; set => Played.PlayedSeconds = (byte)value; } + + // Inventory + public override IReadOnlyList Inventory { get => Items.Inventory; set => Items.Inventory = value; } + + // Storage + public override int GetPartyOffset(int slot) => Party + (SIZE_PARTY * slot); + public override int GetBoxOffset(int box) => Box + (SIZE_PARTY * box * 30); + protected override int GetBoxWallpaperOffset(int box) => BoxLayout.GetBoxWallpaperOffset(box); + public override int GetBoxWallpaper(int box) => BoxLayout.GetBoxWallpaper(box); + public override void SetBoxWallpaper(int box, int value) => BoxLayout.SetBoxWallpaper(box, value); + public override string GetBoxName(int box) => BoxLayout[box]; + public override void SetBoxName(int box, string value) => BoxLayout[box] = value; + public override byte[] GetDataForBox(PKM pkm) => pkm.EncryptedPartyData; + public override int CurrentBox { get => BoxLayout.CurrentBox; set => BoxLayout.CurrentBox = (byte)value; } + public override int BoxesUnlocked { get => BoxLayout.BoxesUnlocked; set => BoxLayout.BoxesUnlocked = (byte)value; } + + public string Rival + { + get => GetString(0x55F4, 0x1A); + set => SetString(value, OTLength).CopyTo(Data, 0x55F4); + } + + // zoneID + + public float TimeScale + { + get => BitConverter.ToSingle(Data, 0x5638); + set => BitConverter.GetBytes(value).CopyTo(Data, 0x5638); + } + + protected override void SetPKM(PKM pkm, bool isParty = false) + { + var pk = (PB8)pkm; + // Apply to this Save File + DateTime Date = DateTime.Now; + pk.Trade(this, Date.Day, Date.Month, Date.Year); + + pkm.RefreshChecksum(); + //AddCountAcquired(pkm); + } + + protected override void SetDex(PKM pkm) => Zukan.SetDex(pkm); + public override bool GetCaught(int species) => Zukan.GetCaught(species); + public override bool GetSeen(int species) => Zukan.GetSeen(species); + + public override int PartyCount + { + get => PartyInfo.PartyCount; + protected set => PartyInfo.PartyCount = value; + } + + public override PKM GetDecryptedPKM(byte[] data) => GetPKM(DecryptPKM(data)); + public override PKM GetBoxSlot(int offset) => GetDecryptedPKM(GetData(Data, offset, SIZE_PARTY)); // party format in boxes! + } +} diff --git a/PKHeX.Core/Saves/Substructures/Gen7/EventWork7b.cs b/PKHeX.Core/Saves/Substructures/Gen7/EventWork7b.cs index a98d4df5fa5..7e1c89dd849 100644 --- a/PKHeX.Core/Saves/Substructures/Gen7/EventWork7b.cs +++ b/PKHeX.Core/Saves/Substructures/Gen7/EventWork7b.cs @@ -2,7 +2,7 @@ namespace PKHeX.Core { - public sealed class EventWork7b : SaveBlock, IEventWork + public sealed class EventWork7b : SaveBlock, IEventVar { public EventWork7b(SAV7b sav, int offset) : base(sav) { @@ -51,8 +51,8 @@ public EventWork7b(SAV7b sav, int offset) : base(sav) private const int TitleFlagStart = 0x1298; // 0x1298 public const int MaxTitleFlag = 156; // Trainer, [1..153], Grand, Battle - public int MaxFlag => FlagCount; - public int MaxWork => WorkCount; + public int CountFlag => FlagCount; + public int CountWork => WorkCount; public int GetWork(int index) => BitConverter.ToInt32(Data, Offset + (index * WorkSize)); public void SetWork(int index, int value) => BitConverter.GetBytes(value).CopyTo(Data, Offset + (index * WorkSize)); diff --git a/PKHeX.Core/Saves/Substructures/Gen7/IEventWork.cs b/PKHeX.Core/Saves/Substructures/Gen7/IEventWork.cs index fbb4aae6f68..32949346e37 100644 --- a/PKHeX.Core/Saves/Substructures/Gen7/IEventWork.cs +++ b/PKHeX.Core/Saves/Substructures/Gen7/IEventWork.cs @@ -1,17 +1,10 @@ namespace PKHeX.Core { - public interface IEventWork + public interface IEventVar : IEventFlag, IEventWork { - int MaxFlag { get; } - int MaxWork { get; } - - T GetWork(int index); - void SetWork(int index, T value); T GetWork(EventVarType type, int index); void SetWork(EventVarType type, int index, T value); - bool GetFlag(int index); - void SetFlag(int index, bool value = true); bool GetFlag(EventVarType type, int index); void SetFlag(EventVarType type, int index, bool value = true); @@ -20,4 +13,25 @@ public interface IEventWork int GetFlagRawIndex(EventVarType type, int index); int GetWorkRawIndex(EventVarType type, int index); } -} \ No newline at end of file + + public interface IEventFlag + { + bool GetFlag(int index); + void SetFlag(int index, bool value = true); + int CountFlag { get; } + } + + public interface ISystemFlag + { + bool GetSystemFlag(int index); + void SetSystemFlag(int index, bool value = true); + int CountSystem { get; } + } + + public interface IEventWork + { + T GetWork(int index); + void SetWork(int index, T value); + int CountWork { get; } + } +} diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/BoxLayout8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/BoxLayout8b.cs new file mode 100644 index 00000000000..ec2e9bb11e5 --- /dev/null +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/BoxLayout8b.cs @@ -0,0 +1,151 @@ +using System; + +namespace PKHeX.Core +{ + public sealed class BoxLayout8b : SaveBlock, IBoxDetailName + { + public const int BoxCount = 40; + + private const int StringMaxLength = SAV6.LongStringLength / 2; + public readonly int[] TeamSlots = new int[TeamCount * TeamSlotCount]; + private const int TeamNameLength = 0x16; + + public BoxLayout8b(SAV8BS sav, int offset) : base(sav) => Offset = offset; + + private static int GetBoxNameOffset(int box) => SAV6.LongStringLength * box; + private static int GetTeamNameOffset(int box) => GetBoxNameOffset(BoxCount) + (TeamNameLength * box); + + public string GetBoxName(int box) + { + var boxName = SAV.GetString(Data, Offset + GetBoxNameOffset(box), SAV6.LongStringLength); + if (string.IsNullOrEmpty(boxName)) + boxName = $"Box {box + 1}"; + return boxName; + } + + public void SetBoxName(int box, string value) + { + var data = SAV.SetString(value, StringMaxLength, StringMaxLength, 0); + var offset = Offset + GetBoxNameOffset(box); + SAV.SetData(Data, data, offset); + } + + public string GetTeamName(int team) + { + var boxName = SAV.GetString(Data, Offset + GetTeamNameOffset(team), TeamNameLength); + if (string.IsNullOrEmpty(boxName)) + boxName = $"Team {team + 1}"; + return boxName; + } + + public void SetTeamName(int team, string value) + { + var data = SAV.SetString(value, StringMaxLength, TeamNameLength / 2, 0); + var offset = Offset + GetTeamNameOffset(team); + SAV.SetData(Data, data, offset); + } + + public string this[int i] + { + get => GetBoxName(i); + set => SetBoxName(i, value); + } + + public const int TeamPositionOffset = 0x5D4; + public const int TeamCount = 6; + public const int TeamSlotCount = 6; + private const short NONE_SELECTED = -1; + + public void LoadBattleTeams() + { + for (int i = 0; i < TeamCount * TeamSlotCount; i++) + { + short val = BitConverter.ToInt16(Data, Offset + TeamPositionOffset + (i * 2)); + if (val < 0) + { + TeamSlots[i] = NONE_SELECTED; + continue; + } + + int box = val >> 8; + int slot = val & 0xFF; + int index = (SAV.BoxSlotCount * box) + slot; + TeamSlots[i] = index & 0xFFFF; + } + } + + public void ClearBattleTeams() + { + for (int i = 0; i < TeamSlots.Length; i++) + TeamSlots[i] = NONE_SELECTED; + LockedTeam = 0; + } + + public void SaveBattleTeams() + { + for (int i = 0; i < TeamCount * 6; i++) + { + int index = TeamSlots[i]; + if (index < 0) + { + BitConverter.GetBytes((short)index).CopyTo(Data, Offset + TeamPositionOffset + (i * 2)); + continue; + } + + SAV.GetBoxSlotFromIndex(index, out var box, out var slot); + int val = (box << 8) | slot; + BitConverter.GetBytes((short)val).CopyTo(Data, Offset + TeamPositionOffset + (i * 2)); + } + } + + public byte LockedTeam + { + get => Data[Offset + 0x61C]; + set + { + if (value > BoxCount) + value = BoxCount; + Data[Offset + 0x61C] = value; + } + } + + public byte BoxesUnlocked + { + get => Data[Offset + 0x61D]; + set + { + if (value > BoxCount) + value = BoxCount; + Data[Offset + 0x61D] = value; + } + } + + public byte CurrentBox + { + get => Data[Offset + 0x61E]; + set => Data[Offset + 0x61E] = value; + } + + public int GetBoxWallpaperOffset(int box) => Offset + 0x620 + box; + + public int GetBoxWallpaper(int box) + { + if ((uint)box > BoxCount) + return 0; + return Data[GetBoxWallpaperOffset(box)]; + } + + public void SetBoxWallpaper(int box, int value) + { + if ((uint)box > BoxCount) + return; + Data[GetBoxWallpaperOffset(box)] = (byte)value; + } + + public ushort StatusPut + { + get => BitConverter.ToUInt16(Data, Offset + 0x648); + set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x648); + } + } +} diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/ConfigSave8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/ConfigSave8b.cs new file mode 100644 index 00000000000..bffb31b778e --- /dev/null +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/ConfigSave8b.cs @@ -0,0 +1,86 @@ +using System; +using System.ComponentModel; + +namespace PKHeX.Core +{ + /// + /// Configuration settings for player preference. + /// + /// size 0x40, struct_name CONFIG + [TypeConverter(typeof(ExpandableObjectConverter))] + public sealed class ConfigSave8b : SaveBlock + { + public ConfigSave8b(SAV8BS sav, int offset) : base(sav) => Offset = offset; + + public TextSpeedOption TextSpeed { get => (TextSpeedOption)BitConverter.ToInt32(Data, Offset + 0); set => BitConverter.GetBytes((int)value).CopyTo(Data, Offset + 0); } + public int Language { get => BitConverter.ToInt32(Data, Offset + 4); set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 4); } + public bool IsKanji { get => Data[Offset + 8] == 1; set => Data[Offset + 8] = (byte)(value ? 1 : 0); } + + public int WindowType + { + get => BitConverter.ToInt32(Data, Offset + 0x0C); + set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x0C); + } + + public BattleAnimationSetting MoveAnimations + { + get => (BattleAnimationSetting)BitConverter.ToInt32(Data, Offset + 0x10); + set => BitConverter.GetBytes((int)value).CopyTo(Data, Offset + 0x10); + } + + public BattleStyleSetting BattleStyle + { + get => (BattleStyleSetting)BitConverter.ToInt32(Data, Offset + 0x14); + set => BitConverter.GetBytes((int)value).CopyTo(Data, Offset + 0x14); + } + + public PartyBoxSetting PartyBox + { + get => (PartyBoxSetting)BitConverter.ToInt32(Data, Offset + 0x18); + set => BitConverter.GetBytes((int)value).CopyTo(Data, Offset + 0x18); + } + + // 4 byte bool, nice + public bool RegistNickname { get => Data[Offset + 0x1C] == 1; set => Data[Offset + 0x1C] = (byte)(value ? 1 : 0); } + public bool GyroSensor { get => Data[Offset + 0x20] == 1; set => Data[Offset + 0x20] = (byte)(value ? 1 : 0); } + public bool CameraShakeOfFossil { get => Data[Offset + 0x24] == 1; set => Data[Offset + 0x24] = (byte)(value ? 1 : 0); } + + public CameraInputMode CameraUpDown { get => (CameraInputMode)BitConverter.ToInt32(Data, Offset + 0x28); set => BitConverter.GetBytes((int)value).CopyTo(Data, Offset + 0x28); } + public CameraInputMode CamerLeftRight { get => (CameraInputMode)BitConverter.ToInt32(Data, Offset + 0x2C); set => BitConverter.GetBytes((int)value).CopyTo(Data, Offset + 0x2C); } + public bool AutoReport { get => Data[Offset + 0x30] == 1; set => Data[Offset + 0x30] = (byte)(value ? 1 : 0); } + public InputMode Input { get => (InputMode)BitConverter.ToInt32(Data, Offset + 0x34); set => BitConverter.GetBytes((int)value).CopyTo(Data, Offset + 0x34); } + public bool ShowNicknames { get => Data[Offset + 0x38] == 1; set => Data[Offset + 0x38] = (byte)(value ? 1 : 0); } + public byte VolumeBGM { get => Data[Offset + 0x3C]; set => Data[Offset + 0x3C] = value; } + public byte VolumeSoundEffects { get => Data[Offset + 0x3D]; set => Data[Offset + 0x3D] = value; } + public byte VolumeVoice { get => Data[Offset + 0x3E]; set => Data[Offset + 0x3E] = value; } + + public enum CameraInputMode + { + Normal, + Reverse, + } + public enum InputMode + { + Easy, + Normal, + } + + public enum BattleAnimationSetting + { + EffectsON, + EffectsOFF, + } + + public enum BattleStyleSetting + { + SWITCH, + SET, + } + + public enum PartyBoxSetting + { + Select, + SendBox, + } + } +} diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/Contest8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/Contest8b.cs new file mode 100644 index 00000000000..ea637bbb5cf --- /dev/null +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/Contest8b.cs @@ -0,0 +1,22 @@ +using System; +using System.ComponentModel; + +namespace PKHeX.Core +{ + /// + /// Contest photo and Rank Point storage. + /// + /// size 0x720, struct_name CONTEST_DATA + [TypeConverter(typeof(ExpandableObjectConverter))] + public sealed class Contest8b : SaveBlock + { + public const int SIZE_CONTEST_PHOTO = 0x16C; + public const int PHOTO_MAX = 5; + + public Contest8b(SAV8BS sav, int offset) : base(sav) => Offset = offset; + + private const int OFS_RANK = SIZE_CONTEST_PHOTO * PHOTO_MAX; // 0x71C; + + public uint ContestRankPoint { get => BitConverter.ToUInt32(Data, Offset + OFS_RANK); set => BitConverter.GetBytes(value).CopyTo(Data, Offset + OFS_RANK); } + } +} diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/FlagWork8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/FlagWork8b.cs new file mode 100644 index 00000000000..c9aae1edbd6 --- /dev/null +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/FlagWork8b.cs @@ -0,0 +1,98 @@ +using System; + +namespace PKHeX.Core +{ + /// + /// Structure that manages the 3 event variable storage arrays. + /// + /// Comprised of 3 fixed-sized arrays, we do our read/write in-place. Each element in an array is 4 bytes. Total size: 0x55F0 + public sealed class FlagWork8b : SaveBlock, IEventFlag, ISystemFlag, IEventWork + { + public const int COUNT_WORK = 500; + public const int COUNT_FLAG = 4000; + public const int COUNT_SYSTEM = 1000; + + public const int OFS_WORK = 0; + public const int OFS_FLAG = OFS_WORK + (COUNT_WORK * 4); + public const int OFS_SYSTEM = OFS_FLAG + (COUNT_FLAG * 4); + + public const int FH_START = 0; + public const int FH_END = 63; + public const int FE_FLAG_START = 63; + public const int FE_END = 314; + public const int FV_FLAG_START = 314; + public const int FV_END = 603; + public const int FT_START = 603; + public const int FT_END = 859; + public const int FV_FLD_START = 859; + public const int FV_FLD_END = 1115; + public const int TMFLG_START = 1115; + + private const int BASE_VANISH = FV_FLAG_START; + private const int END_VANISH = FV_END - 1; + private const int COUNT_VANISH = END_VANISH - BASE_VANISH; // 0x120 + + public FlagWork8b(SAV8BS sav, int offset) : base(sav) => Offset = offset; + public int CountFlag => COUNT_FLAG; + public int CountSystem => COUNT_SYSTEM; + public int CountWork => COUNT_WORK; + + private int GetOffsetFlag(int flagNo) + { + if ((uint)flagNo >= COUNT_FLAG) + throw new ArgumentOutOfRangeException(nameof(flagNo), $"Expected a number below {COUNT_FLAG}, not {flagNo}."); + return Offset + OFS_FLAG + (4 * flagNo); + } + private int GetOffsetSystem(int flagNo) + { + if ((uint)flagNo >= COUNT_SYSTEM) + throw new ArgumentOutOfRangeException(nameof(flagNo), $"Expected a number below {COUNT_SYSTEM}, not {flagNo}."); + return Offset + OFS_SYSTEM + (4 * flagNo); + } + + private int GetOffsetWork(int flagNo) + { + if ((uint)flagNo >= COUNT_WORK) + throw new ArgumentOutOfRangeException(nameof(flagNo), $"Expected a number below {COUNT_WORK}, not {flagNo}."); + return Offset + OFS_WORK + (4 * flagNo); + } + + public bool GetFlag (int flagNo) => BitConverter.ToInt32(Data, GetOffsetFlag(flagNo)) == 1; + public bool GetSystemFlag(int flagNo) => BitConverter.ToInt32(Data, GetOffsetSystem(flagNo)) == 1; + public int GetWork (int workNo) => BitConverter.ToInt32(Data, GetOffsetWork(workNo)); + public float GetFloatWork(int workNo) => BitConverter.ToSingle(Data, GetOffsetWork(workNo)); + + public void SetFlag (int flagNo, bool value) => BitConverter.GetBytes(value ? 1u : 0u).CopyTo(Data, GetOffsetFlag(flagNo)); + public void SetSystemFlag(int flagNo, bool value) => BitConverter.GetBytes(value ? 1u : 0u).CopyTo(Data, GetOffsetSystem(flagNo)); + public void SetWork (int workNo, int value) => BitConverter.GetBytes(value).CopyTo(Data, GetOffsetWork(workNo)); + public void SetFloatWork (int workNo, float value) => BitConverter.GetBytes(value).CopyTo(Data, GetOffsetWork(workNo)); + + public void ResetFlag (int flagNo) => SetFlag(flagNo, false); + public void ResetVanishFlag(int flagNo) => SetVanishFlag(flagNo, false); + public void ResetSystemFlag(int flagNo) => SetSystemFlag(flagNo, false); + public void ResetWork (int workNo) => SetWork(workNo, 0); + + public bool GetVanishFlag(int flagNo) + { + if ((uint)flagNo >= COUNT_VANISH) + throw new ArgumentOutOfRangeException(nameof(flagNo), $"Expected a number below {COUNT_VANISH}, not {flagNo}."); + return GetFlag(BASE_VANISH + flagNo); + } + + public void SetVanishFlag(int flagNo, bool value) + { + if ((uint)flagNo >= COUNT_VANISH) + throw new ArgumentOutOfRangeException(nameof(flagNo), $"Expected a number below {COUNT_VANISH}, not {flagNo}."); + SetFlag(BASE_VANISH + flagNo, value); + } + + public int BadgeCount() + { + // system flags 124-131 + int ctr = 0; + for (int i = 0; i < 8; i++) + ctr += GetSystemFlag(124 + i) ? 1 : 0; + return ctr; + } + } +} diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/Gem8Version.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/Gem8Version.cs new file mode 100644 index 00000000000..50937710877 --- /dev/null +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/Gem8Version.cs @@ -0,0 +1,17 @@ +namespace PKHeX.Core +{ + public enum Gem8Version + { + /// + /// Initial cartridge version shipped. + /// + /// + V1_0 = 0x25, + + /// + /// Pre-release patch. + /// + /// + V1_1 = 0x2C, + } +} diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/MyItem8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/MyItem8b.cs new file mode 100644 index 00000000000..f68d36e793d --- /dev/null +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/MyItem8b.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace PKHeX.Core +{ + /// + /// Player item pouches storage + /// + /// size=0xBB80 ( items) + public sealed class MyItem8b : MyItem + { + public const int ItemSaveSize = 3000; + + public MyItem8b(SAV8BS sav, int offset) : base(sav) => Offset = offset; + public override IReadOnlyList Inventory { get => ConvertToPouches(); set => LoadFromPouches(value); } + + private IReadOnlyList ConvertToPouches() + { + var pouches = new[] + { + MakePouch(InventoryType.Items), + MakePouch(InventoryType.KeyItems), + MakePouch(InventoryType.TMHMs), + MakePouch(InventoryType.Medicine), + MakePouch(InventoryType.Berries), + MakePouch(InventoryType.Balls), + MakePouch(InventoryType.BattleItems), + MakePouch(InventoryType.Treasure), + }; + return pouches.LoadAll(Data); + } + + private void LoadFromPouches(IReadOnlyList value) + { + value.SaveAll(Data); + CleanIllegalSlots(); + } + + private void CleanIllegalSlots() + { + var all = new[] + { + GetLegal(InventoryType.Items), + GetLegal(InventoryType.KeyItems), + GetLegal(InventoryType.TMHMs), + GetLegal(InventoryType.Medicine), + GetLegal(InventoryType.Berries), + GetLegal(InventoryType.Balls), + GetLegal(InventoryType.BattleItems), + GetLegal(InventoryType.Treasure), + }.SelectMany(z => z).Distinct(); + + var hashSet = new HashSet(all); + var empty = new InventoryItem(); + for (ushort i = 0; i < (ushort)SAV.MaxItemID; i++) // even though there are 3000, just overwrite the ones that people will mess up. + { + if (!hashSet.Contains(i)) + InventoryPouch8b.WriteItem(empty, Data, InventoryPouch8b.GetItemOffset(i, Offset)); + } + } + + private InventoryPouch8b MakePouch(InventoryType type) + { + ushort[] legal = GetLegal(type); + var max = GetMax(type); + return new InventoryPouch8b(type, legal, max, Offset); + } + + private static int GetMax(InventoryType type) => type switch + { + InventoryType.Items => 999, + InventoryType.KeyItems => 1, + InventoryType.TMHMs => 999, + InventoryType.Medicine => 999, + InventoryType.Berries => 999, + InventoryType.Balls => 999, + InventoryType.BattleItems => 999, + InventoryType.Treasure => 999, + _ => throw new ArgumentOutOfRangeException(nameof(type)) + }; + + private static ushort[] GetLegal(InventoryType type) => type switch + { + InventoryType.Items => Legal.Pouch_Regular_BS, + InventoryType.KeyItems => Legal.Pouch_Key_BS, + InventoryType.TMHMs => Legal.Pouch_TMHM_BS, + InventoryType.Medicine => Legal.Pouch_Medicine_BS, + InventoryType.Berries => Legal.Pouch_Berries_BS, + InventoryType.Balls => Legal.Pouch_Ball_BS, + InventoryType.BattleItems => Legal.Pouch_Battle_BS, + InventoryType.Treasure => Legal.Pouch_Treasure_BS, + _ => throw new ArgumentOutOfRangeException(nameof(type)) + }; + } +} diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/MyStatus8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/MyStatus8b.cs new file mode 100644 index 00000000000..e3c53dd24cc --- /dev/null +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/MyStatus8b.cs @@ -0,0 +1,119 @@ +using System; +using System.ComponentModel; + +namespace PKHeX.Core +{ + /// + /// Player status and info about the trainer + /// + [TypeConverter(typeof(ExpandableObjectConverter))] + public sealed class MyStatus8b : SaveBlock + { + public const int MAX_MONEY = 999_999; + public const byte MAX_BADGE = 8; + // public const byte MAX_RANK = 5; // unused? + + public MyStatus8b(SAV8BS sav, int offset) : base(sav) => Offset = offset; + + public string OT + { + get => SAV.GetString(Data, Offset + 0, 0x1A); + set => SAV.SetData(Data, SAV.SetString(value, SAV.OTLength), Offset + 0); + } + + public int TID + { + get => BitConverter.ToUInt16(Data, Offset + 0x1C); + set => BitConverter.GetBytes((ushort)value).CopyTo(Data, Offset + 0x1C); + } + + public int SID + { + get => BitConverter.ToUInt16(Data, Offset + 0x1E); + set => BitConverter.GetBytes((ushort)value).CopyTo(Data, Offset + 0x1E); + } + + public uint Money + { + get => BitConverter.ToUInt32(Data, Offset + 0x20); + set => BitConverter.GetBytes(Math.Min(MAX_MONEY, value)).CopyTo(Data, Offset + 0x20); + } + + public bool Male { get => Data[Offset + 0x24] == 1; set => Data[Offset + 0x24] = (byte)(value ? 1 : 0); } + // 3byte align + public byte RegionCode { get => Data[Offset + 0x28]; set => Data[Offset + 0x28] = value; } + public byte BadgeCount { get => Data[Offset + 0x29]; set => Data[Offset + 0x29] = Math.Min(MAX_BADGE, value); } + public byte TrainerView { get => Data[Offset + 0x2A]; set => Data[Offset + 0x2A] = value; } + public byte ROMCode { get => Data[Offset + 0x2B]; set => Data[Offset + 0x2B] = value; } + public bool GameClear { get => Data[Offset + 0x2C] == 1; set => Data[Offset + 0x2C] = (byte)(value ? 1 : 0); } + // 3byte align + public byte BodyType { get => Data[Offset + 0x30]; set => Data[Offset + 0x30] = value; } + public Fashion FashionID { get => (Fashion)Data[Offset + 0x31]; set => Data[Offset + 0x31] = (byte)value; } + // 2byte align + + public MoveType StarterType + { + get => (MoveType)BitConverter.ToInt32(Data, Offset + 0x34); + set => BitConverter.GetBytes((int)value).CopyTo(Data, Offset + 0x34); + } + + public bool DSPlayer { get => Data[Offset + 0x38] == 1; set => Data[Offset + 0x38] = (byte)(value ? 1 : 0); } + // 3byte align + + /// turewalkMemberIndex + public int FollowIndex { get => BitConverter.ToInt32(Data, Offset + 0x3C); set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x3C); } + public int X { get => BitConverter.ToInt32(Data, Offset + 0x40); set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x40); } + public int Y { get => BitConverter.ToInt32(Data, Offset + 0x44); set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x44); } + public float Height { get => BitConverter.ToSingle(Data, Offset + 0x48); set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x48); } + public float Rotation { get => BitConverter.ToSingle(Data, Offset + 0x4C); set => BitConverter.GetBytes(value).CopyTo(Data, Offset + 0x4C); } + + // end structure! + + public int Game + { + get => ROMCode switch + { + 0 => (int)GameVersion.BD, + 1 => (int)GameVersion.SP, + _ => throw new ArgumentOutOfRangeException(nameof(Game)), + }; + set => ROMCode = (GameVersion)value switch + { + GameVersion.BD => 0, + GameVersion.SP => 1, + _ => throw new ArgumentOutOfRangeException(nameof(Game)), + }; + } + + public enum Fashion : byte + { + Everyday_M = 0, + Contest_M = 1, + Pikachu_Hoodie_M = 2, + Platinum_M = 3, + Overalls_M = 4, + Eevee_Jacket_M = 5, + Gengar_Jacket_M = 6, + Cyber_M = 7, + Summer_M = 8, + Winter_M = 9, + Spring_M = 10, + Casual_M = 11, + Leather_Jacket_M = 12, + + Everyday_F = 100, + Contest_F = 101, + Pikachu_Hoodie_F = 102, + Platinum_F = 103, + Overalls_F = 104, + Eevee_Jacket_F = 105, + Gengar_Jacket_F = 106, + Cyber_F = 107, + Summer_F = 108, + Winter_F = 109, + Spring_F = 110, + Casual_F = 111, + Leather_Jacket_F = 112, + } + } +} diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/Party8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/Party8b.cs new file mode 100644 index 00000000000..23a238beb3d --- /dev/null +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/Party8b.cs @@ -0,0 +1,22 @@ +namespace PKHeX.Core +{ + /// + /// Party data storage and metadata + /// + public sealed class Party8b : SaveBlock + { + public Party8b(SAV8BS sav, int offset) : base(sav) => Offset = offset; + + public int PartyCount + { + get => Data[Offset + (6 * PokeCrypto.SIZE_8PARTY)]; + set => Data[Offset + (6 * PokeCrypto.SIZE_8PARTY)] = (byte)value; + } + + public int MarkingIndex + { + get => Data[Offset + (6 * PokeCrypto.SIZE_8PARTY) + 1]; + set => Data[Offset + (6 * PokeCrypto.SIZE_8PARTY) + 1] = (byte)value; + } + } +} diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/PlayTime8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/PlayTime8b.cs new file mode 100644 index 00000000000..845b48630e0 --- /dev/null +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/PlayTime8b.cs @@ -0,0 +1,23 @@ +using System; +using System.ComponentModel; + +namespace PKHeX.Core +{ + /// + /// Playtime storage + /// + [TypeConverter(typeof(ExpandableObjectConverter))] + public sealed class PlayTime8b : SaveBlock + { + public PlayTime8b(SAV8BS sav, int offset) : base(sav) => Offset = offset; + + public ushort PlayedHours + { + get => BitConverter.ToUInt16(Data, Offset); + set => BitConverter.GetBytes(value).CopyTo(Data, Offset); + } + + public byte PlayedMinutes { get => Data[Offset + 2]; set => Data[Offset + 2] = value; } + public byte PlayedSeconds { get => Data[Offset + 3]; set => Data[Offset + 3] = value; } + } +} diff --git a/PKHeX.Core/Saves/Substructures/Gen8/BS/Zukan8b.cs b/PKHeX.Core/Saves/Substructures/Gen8/BS/Zukan8b.cs new file mode 100644 index 00000000000..82cbcb43750 --- /dev/null +++ b/PKHeX.Core/Saves/Substructures/Gen8/BS/Zukan8b.cs @@ -0,0 +1,483 @@ +using System; + +namespace PKHeX.Core +{ + /// + /// Pokédex structure used for Brilliant Diamond & Shining Pearl. + /// + /// size 0x30B8, struct_name ZUKAN_WORK + public sealed class Zukan8b : ZukanBase + { + /* Structure Notes: + u32 [493] state: None/HeardOf/Seen/Captured + bool[493] maleShiny + bool[493] femaleShiny + bool[493] male + bool[493] female + bool[28] Unown Form + bool[28] Unown FormShiny + bool[4] Castform + bool[4] Castform + bool[4] Deoxys + bool[4] Deoxys + bool[3] Burmy + bool[3] Burmy + bool[3] Wormadam + bool[3] Wormadam + bool[3] Wormadam + bool[3] Wormadam + bool[3] Mothim + bool[3] Mothim + bool[2] Cherrim + bool[2] Cherrim + bool[2] Shellos + bool[2] Shellos + bool[2] Gastrodon + bool[2] Gastrodon + bool[6] Rotom + bool[6] Rotom + bool[2] Giratina + bool[2] Giratina + bool[2] Shaymin + bool[2] Shaymin + bool[18] Arceus + bool[18] Arceus + u32 [493] language flags + bool regional dex obtained + bool national dex obtained + */ + + private const int COUNT_SPECIES = 493; + private const int COUNT_UNOWN = 28; + private const int COUNT_CASTFORM = 4; + private const int COUNT_DEOXYS = 4; + private const int COUNT_BURMY = 3; + private const int COUNT_WORMADAM = 3; + private const int COUNT_MOTHIM = 3; + private const int COUNT_CHERRIM = 2; + private const int COUNT_SHELLOS = 2; + private const int COUNT_GASTRODON = 2; + private const int COUNT_ROTOM = 6; + private const int COUNT_GIRATINA = 2; + private const int COUNT_SHAYMIN = 2; + private const int COUNT_ARCEUS = 18; + + private const int SIZE_SPECIES = sizeof(ZukanState8b) * COUNT_SPECIES; + private const int ALIGN_BOOLARRAY = 4; + private const int SIZE_SPECIESBOOL = ALIGN_BOOLARRAY * COUNT_SPECIES; + private const int SIZE_UNOWN = ALIGN_BOOLARRAY * COUNT_UNOWN; + private const int SIZE_CASTFORM = ALIGN_BOOLARRAY * COUNT_CASTFORM; + private const int SIZE_DEOXYS = ALIGN_BOOLARRAY * COUNT_DEOXYS; + private const int SIZE_BURMY = ALIGN_BOOLARRAY * COUNT_BURMY; + private const int SIZE_WORMADAM = ALIGN_BOOLARRAY * COUNT_WORMADAM; + private const int SIZE_MOTHIM = ALIGN_BOOLARRAY * COUNT_MOTHIM; + private const int SIZE_CHERRIM = ALIGN_BOOLARRAY * COUNT_CHERRIM; + private const int SIZE_SHELLOS = ALIGN_BOOLARRAY * COUNT_SHELLOS; + private const int SIZE_GASTRODON = ALIGN_BOOLARRAY * COUNT_GASTRODON; + private const int SIZE_ROTOM = ALIGN_BOOLARRAY * COUNT_ROTOM; + private const int SIZE_GIRATINA = ALIGN_BOOLARRAY * COUNT_GIRATINA; + private const int SIZE_SHAYMIN = ALIGN_BOOLARRAY * COUNT_SHAYMIN; + private const int SIZE_ARCEUS = ALIGN_BOOLARRAY * COUNT_ARCEUS; + private const int SIZE_LANGUAGE = sizeof(int) * COUNT_SPECIES; + + private const int OFS_STATE = 0; + private const int OFS_MALESHINY = OFS_STATE + SIZE_SPECIES; + private const int OFS_FEMALESHINY = OFS_MALESHINY + SIZE_SPECIESBOOL; + private const int OFS_MALE = OFS_FEMALESHINY + SIZE_SPECIESBOOL; + private const int OFS_FEMALE = OFS_MALE + SIZE_SPECIESBOOL; + + private const int OFS_UNOWN = OFS_FEMALE + SIZE_SPECIESBOOL; + private const int OFS_SUNOWN = OFS_UNOWN + SIZE_UNOWN; + private const int OFS_CASTFORM = OFS_SUNOWN + SIZE_UNOWN; + private const int OFS_SCASTFORM = OFS_CASTFORM + SIZE_CASTFORM; + private const int OFS_DEOXYS = OFS_SCASTFORM + SIZE_CASTFORM; + private const int OFS_SDEOXYS = OFS_DEOXYS + SIZE_DEOXYS; + private const int OFS_BURMY = OFS_SDEOXYS + SIZE_DEOXYS; + private const int OFS_SBURMY = OFS_BURMY + SIZE_BURMY; + private const int OFS_WORMADAM = OFS_SBURMY + SIZE_BURMY; + private const int OFS_SWORMADAM = OFS_WORMADAM + SIZE_WORMADAM; + private const int OFS_MOTHIM = OFS_SWORMADAM + SIZE_WORMADAM; + private const int OFS_SMOTHIM = OFS_MOTHIM + SIZE_MOTHIM; + private const int OFS_CHERRIM = OFS_SMOTHIM + SIZE_MOTHIM; + private const int OFS_SCHERRIM = OFS_CHERRIM + SIZE_CHERRIM; + private const int OFS_SHELLOS = OFS_SCHERRIM + SIZE_CHERRIM; + private const int OFS_SSHELLOS = OFS_SHELLOS + SIZE_SHELLOS; + private const int OFS_GASTRODON = OFS_SSHELLOS + SIZE_SHELLOS; + private const int OFS_SGASTRODON = OFS_GASTRODON + SIZE_GASTRODON; + private const int OFS_ROTOM = OFS_SGASTRODON + SIZE_GASTRODON; + private const int OFS_SROTOM = OFS_ROTOM + SIZE_ROTOM; + private const int OFS_GIRATINA = OFS_SROTOM + SIZE_ROTOM; + private const int OFS_SGIRATINA = OFS_GIRATINA + SIZE_GIRATINA; + private const int OFS_SHAYMIN = OFS_SGIRATINA + SIZE_GIRATINA; + private const int OFS_SSHAYMIN = OFS_SHAYMIN + SIZE_SHAYMIN; + private const int OFS_ARCEUS = OFS_SSHAYMIN + SIZE_SHAYMIN; + private const int OFS_SARCEUS = OFS_ARCEUS + SIZE_ARCEUS; + + private const int OFS_LANGUAGE = OFS_SARCEUS + SIZE_ARCEUS; + private const int OFS_FLAG_REGIONAL = OFS_LANGUAGE + SIZE_LANGUAGE; // 0x30B0 + private const int OFS_FLAG_NATIONAL = OFS_FLAG_REGIONAL + 4; // 0x30B4 + // sizeof(this) = 0x30B8 + + private const int LANGUAGE_NONE = 0; + private const int LANGUAGE_ALL = // 0x1FF + 1 << (int)LanguageID.Japanese - 1 | + 1 << (int)LanguageID.English - 1 | + 1 << (int)LanguageID.French - 1 | + 1 << (int)LanguageID.Italian - 1 | + 1 << (int)LanguageID.German - 1 | + 1 << (int)LanguageID.Spanish - 2 | // Skip over Language 6 (unused) + 1 << (int)LanguageID.Korean - 2 | + 1 << (int)LanguageID.ChineseS - 2 | + 1 << (int)LanguageID.ChineseT - 2; + + private static PersonalTable Personal => PersonalTable.BDSP; + + public Zukan8b(SAV8BS sav, int dex) : base(sav, dex) { } + + public ZukanState8b GetState(int species) + { + if ((uint)species > Legal.MaxSpeciesID_4) + throw new ArgumentOutOfRangeException(nameof(species)); + + var index = species - 1; + var offset = OFS_STATE + (sizeof(int) * index); + return (ZukanState8b)BitConverter.ToInt32(SAV.Data, PokeDex + offset); + } + + public void SetState(int species, ZukanState8b state) + { + if ((uint)species > Legal.MaxSpeciesID_4) + throw new ArgumentOutOfRangeException(nameof(species)); + + var index = species - 1; + var offset = OFS_STATE + (sizeof(int) * index); + BitConverter.GetBytes((int)state).CopyTo(SAV.Data, PokeDex + offset); + } + + private bool GetBoolean(int index, int baseOffset, int max) + { + if ((uint)index > (uint)max) + throw new ArgumentOutOfRangeException(nameof(index)); + + var offset = baseOffset + (ALIGN_BOOLARRAY * index); + return BitConverter.ToUInt32(SAV.Data, PokeDex + offset) == 1; + } + + private void SetBoolean(int index, int baseOffset, int max, bool value) + { + if ((uint)index > (uint)max) + throw new ArgumentOutOfRangeException(nameof(index)); + + var offset = baseOffset + (ALIGN_BOOLARRAY * index); + BitConverter.GetBytes((uint)(value ? 1 : 0)).CopyTo(SAV.Data, PokeDex + offset); + } + + public void GetGenderFlags(int species, out bool m, out bool f, out bool ms, out bool fs) + { + m = GetBoolean(species - 1, OFS_MALE, COUNT_SPECIES - 1); + f = GetBoolean(species - 1, OFS_FEMALE, COUNT_SPECIES - 1); + ms = GetBoolean(species - 1, OFS_MALESHINY, COUNT_SPECIES - 1); + fs = GetBoolean(species - 1, OFS_FEMALESHINY, COUNT_SPECIES - 1); + } + + public void SetGenderFlags(int species, bool m, bool f, bool ms, bool fs) + { + SetBoolean(species - 1, OFS_MALE, COUNT_SPECIES - 1, m); + SetBoolean(species - 1, OFS_FEMALE, COUNT_SPECIES - 1, f); + SetBoolean(species - 1, OFS_MALESHINY, COUNT_SPECIES - 1, ms); + SetBoolean(species - 1, OFS_FEMALESHINY, COUNT_SPECIES - 1, fs); + } + + public bool GetLanguageFlag(int species, int language) + { + if ((uint)species > Legal.MaxSpeciesID_4) + throw new ArgumentOutOfRangeException(nameof(species)); + var languageBit = GetLanguageBit(language); + if (languageBit == -1) + return false; + + var index = species - 1; + var offset = OFS_LANGUAGE + (sizeof(int) * index); + var current = BitConverter.ToInt32(SAV.Data, PokeDex + offset); + return (current & (1 << languageBit)) != 0; + } + + public void SetLanguageFlag(int species, int language, bool value) + { + if ((uint)species > Legal.MaxSpeciesID_4) + throw new ArgumentOutOfRangeException(nameof(species)); + var languageBit = GetLanguageBit(language); + if (languageBit == -1) + return; + + var index = species - 1; + var offset = OFS_LANGUAGE + (sizeof(int) * index); + var current = BitConverter.ToInt32(SAV.Data, PokeDex + offset); + var mask = (1 << languageBit); + var update = value ? current | mask : current & ~(mask); + BitConverter.GetBytes(update).CopyTo(SAV.Data, PokeDex + offset); + } + + public void SetLanguageFlags(int species, int value) + { + if ((uint)species > Legal.MaxSpeciesID_4) + throw new ArgumentOutOfRangeException(nameof(species)); + + var index = species - 1; + var offset = OFS_LANGUAGE + (sizeof(int) * index); + BitConverter.GetBytes(value).CopyTo(SAV.Data, PokeDex + offset); + } + + private static int GetLanguageBit(int language) + { + if (language is 0 or (int)LanguageID.UNUSED_6 or > (int)LanguageID.ChineseT) + return -1; + if (language >= (int)LanguageID.Spanish) + return language - 2; + return language - 1; + } + + public bool HasRegionalDex + { + get => BitConverter.ToUInt32(SAV.Data, PokeDex + OFS_FLAG_REGIONAL) == 1; + set => BitConverter.GetBytes((uint)(value ? 1 : 0)).CopyTo(SAV.Data, PokeDex + OFS_FLAG_REGIONAL); + } + + public bool HasNationalDex + { + get => BitConverter.ToUInt32(SAV.Data, PokeDex + OFS_FLAG_NATIONAL) == 1; + set => BitConverter.GetBytes((uint)(value ? 1 : 0)).CopyTo(SAV.Data, PokeDex + OFS_FLAG_NATIONAL); + } + + public bool GetHasFormFlag(int species, int form, bool shiny) + { + var ct = GetFormCount(species); + if (ct == 0) + return false; + + var baseOffset = GetFormOffset(species); + var sizeShift = shiny ? GetFormSize(species) : 0; + var offset = baseOffset + sizeShift + (ALIGN_BOOLARRAY * form); + return BitConverter.ToUInt32(SAV.Data, PokeDex + offset) == 1; + } + + public void SetHasFormFlag(int species, int form, bool shiny, bool value) + { + var formCount = GetFormCount(species); + if (formCount is 0 || (uint)form >= formCount) + return; + + var baseOffset = GetFormOffset(species); + var sizeShift = shiny ? GetFormSize(species) : 0; + var offset = baseOffset + sizeShift + (ALIGN_BOOLARRAY * form); + BitConverter.GetBytes((uint)(value ? 1 : 0)).CopyTo(SAV.Data, PokeDex + offset); + } + + public static int GetFormCount(int species) => species switch + { + (int)Species.Unown => COUNT_UNOWN, + (int)Species.Castform => COUNT_CASTFORM, + (int)Species.Deoxys => COUNT_DEOXYS, + (int)Species.Burmy => COUNT_BURMY, + (int)Species.Wormadam => COUNT_WORMADAM, + (int)Species.Mothim => COUNT_MOTHIM, + (int)Species.Cherrim => COUNT_CHERRIM, + (int)Species.Shellos => COUNT_SHELLOS, + (int)Species.Gastrodon => COUNT_GASTRODON, + (int)Species.Rotom => COUNT_ROTOM, + (int)Species.Giratina => COUNT_GIRATINA, + (int)Species.Shaymin => COUNT_SHAYMIN, + (int)Species.Arceus => COUNT_ARCEUS, + _ => 0, + }; + + private static int GetFormSize(int species) => species switch + { + (int)Species.Unown => SIZE_UNOWN, + (int)Species.Castform => SIZE_CASTFORM, + (int)Species.Deoxys => SIZE_DEOXYS, + (int)Species.Burmy => SIZE_BURMY, + (int)Species.Wormadam => SIZE_WORMADAM, + (int)Species.Mothim => SIZE_MOTHIM, + (int)Species.Cherrim => SIZE_CHERRIM, + (int)Species.Shellos => SIZE_SHELLOS, + (int)Species.Gastrodon => SIZE_GASTRODON, + (int)Species.Rotom => SIZE_ROTOM, + (int)Species.Giratina => SIZE_GIRATINA, + (int)Species.Shaymin => SIZE_SHAYMIN, + (int)Species.Arceus => SIZE_ARCEUS, + _ => 0, + }; + + private static int GetFormOffset(int species) => species switch + { + (int)Species.Unown => OFS_UNOWN, + (int)Species.Castform => OFS_CASTFORM, + (int)Species.Deoxys => OFS_DEOXYS, + (int)Species.Burmy => OFS_BURMY, + (int)Species.Wormadam => OFS_WORMADAM, + (int)Species.Mothim => OFS_MOTHIM, + (int)Species.Cherrim => OFS_CHERRIM, + (int)Species.Shellos => OFS_SHELLOS, + (int)Species.Gastrodon => OFS_GASTRODON, + (int)Species.Rotom => OFS_ROTOM, + (int)Species.Giratina => OFS_GIRATINA, + (int)Species.Shaymin => OFS_SHAYMIN, + (int)Species.Arceus => OFS_ARCEUS, + _ => 0, + }; + + public bool GetHeard(int species) => GetState(species) >= ZukanState8b.HeardOf; + public override bool GetSeen(int species) => GetState(species) >= ZukanState8b.Seen; + public override bool GetCaught(int species) => GetState(species) >= ZukanState8b.Caught; + + public override void SetDex(PKM pkm) + { + int species = pkm.Species; + if (species is 0 or > Legal.MaxSpeciesID_4) + return; + if (pkm.IsEgg) // do not add + return; + + bool shiny = pkm.IsShiny; + SetState(species, ZukanState8b.Caught); + SetGenderFlag(species, pkm.Gender, shiny); + SetLanguageFlag(species, pkm.Language, true); + SetHasFormFlag(species, pkm.Form, shiny, true); + } + + private void SetGenderFlag(int species, int gender, bool shiny) + { + var ofs = (gender & 1) == 0 + ? shiny ? OFS_MALESHINY : OFS_MALE + : shiny ? OFS_FEMALESHINY : OFS_FEMALE; + SetBoolean(species - 1, ofs, COUNT_SPECIES - 1, true); + } + + public override void SeenNone() + { + for (int species = 1; species <= Legal.MaxSpeciesID_4; species++) + { + if (GetSeen(species)) + SetState(species, ZukanState8b.HeardOf); + SetGenderFlags(species, false, false, false, false); + SetLanguageFlags(species, 0); + } + } + + public override void CaughtNone() + { + for (int species = 1; species <= Legal.MaxSpeciesID_4; species++) + { + if (GetCaught(species)) + SetState(species, ZukanState8b.Seen); + SetLanguageFlags(species, 0); + } + } + + public override void SeenAll(bool shinyToo = false) + { + var pt = Personal; + for (int i = 1; i <= Legal.MaxSpeciesID_4; i++) + { + if (!GetSeen(i)) + SetState(i, ZukanState8b.Seen); + var pi = pt[i]; + var m = !pi.OnlyFemale; + var f = !pi.OnlyMale && !pi.Genderless; + SetGenderFlags(i, m, f, m && shinyToo, f && shinyToo); + } + } + + public override void CompleteDex(bool shinyToo = false) + { + for (int species = 1; species <= Legal.MaxSpeciesID_4; species++) + SetDexEntryAll(species, shinyToo); + } + + public override void CaughtAll(bool shinyToo = false) + { + var pt = Personal; + for (int species = 1; species <= Legal.MaxSpeciesID_4; species++) + { + SetState(species, ZukanState8b.Caught); + var pi = pt[species]; + var m = !pi.OnlyFemale; + var f = !pi.OnlyMale && !pi.Genderless; + SetGenderFlags(species, m, f, m && shinyToo, f && shinyToo); + SetLanguageFlag(species, SAV.Language, true); + } + } + + public override void SetAllSeen(bool value = true, bool shinyToo = false) + { + var pt = Personal; + for (int species = 1; species <= Legal.MaxSpeciesID_4; species++) + { + if (value) + { + if (!GetSeen(species)) + SetState(species, ZukanState8b.Seen); + var pi = pt[species]; + var m = !pi.OnlyFemale; + var f = !pi.OnlyMale && !pi.Genderless; + SetGenderFlags(species, m, f, m && shinyToo, f && shinyToo); + } + else + { + if (GetSeen(species)) + SetState(species, ZukanState8b.HeardOf); + SetGenderFlags(species, false, false, false, false); + } + } + } + + public override void SetDexEntryAll(int species, bool shinyToo = false) + { + SetState(species, ZukanState8b.Caught); + + var pt = Personal; + var pi = pt[species]; + var m = !pi.OnlyFemale; + var f = !pi.OnlyMale && !pi.Genderless; + SetGenderFlags(species, m, f, m && shinyToo, f && shinyToo); + + var formCount = GetFormCount(species); + if (formCount is not 0) + { + for (int form = 0; form < formCount; form++) + { + SetHasFormFlag(species, form, false, true); + if (shinyToo) + SetHasFormFlag(species, form, true, true); + } + } + SetLanguageFlags(species, LANGUAGE_ALL); + } + + public override void ClearDexEntryAll(int species) + { + SetState(species, ZukanState8b.None); + SetGenderFlags(species, false, false, false, false); + + var formCount = GetFormCount(species); + if (formCount is not 0) + { + for (int form = 0; form < formCount; form++) + { + SetHasFormFlag(species, form, false, false); + SetHasFormFlag(species, form, true, false); + } + } + SetLanguageFlags(species, LANGUAGE_NONE); + } + } + + public enum ZukanState8b + { + None, + HeardOf, + Seen, + Caught, + } +} diff --git a/PKHeX.Core/Saves/Substructures/Inventory/InventoryPouch.cs b/PKHeX.Core/Saves/Substructures/Inventory/InventoryPouch.cs index fce51c204ab..a203aecfe2d 100644 --- a/PKHeX.Core/Saves/Substructures/Inventory/InventoryPouch.cs +++ b/PKHeX.Core/Saves/Substructures/Inventory/InventoryPouch.cs @@ -252,7 +252,7 @@ private int GetSuggestedItemCount(ITrainerInfo sav, int item, int requestVal = 1 return InventoryPouch7b.GetSuggestedCount(Type, item, requestVal); if (sav is SAV8SWSH) return InventoryPouch8.GetSuggestedCount(Type, item, requestVal); - if (ItemConverter.IsItemHM((ushort)item, sav.Generation)) + if (sav is not SAV8BS && ItemConverter.IsItemHM((ushort)item, sav.Generation)) return 1; return Math.Min(MaxCount, requestVal); } diff --git a/PKHeX.Core/Saves/Substructures/Inventory/InventoryPouch8b.cs b/PKHeX.Core/Saves/Substructures/Inventory/InventoryPouch8b.cs new file mode 100644 index 00000000000..5215c46590d --- /dev/null +++ b/PKHeX.Core/Saves/Substructures/Inventory/InventoryPouch8b.cs @@ -0,0 +1,69 @@ +using System; +using System.Diagnostics; +using System.Linq; + +namespace PKHeX.Core +{ + public sealed class InventoryPouch8b : InventoryPouch + { + private const int SIZE_ITEM = 0x10; + + private InventoryItem[] OriginalItems = Array.Empty(); + public bool SetNew { get; set; } = false; + + public InventoryPouch8b(InventoryType type, ushort[] legal, int maxCount, int offset) : base(type, legal, maxCount, offset) { } + + public override void GetPouch(byte[] data) + { + Items = new InventoryItem[LegalItems.Length]; + int ctr = 0; + foreach (var index in LegalItems) + { + var ofs = GetItemOffset(index, Offset); + var count = BitConverter.ToInt32(data, ofs); + if (count == 0) + continue; + + bool isNew = BitConverter.ToInt32(data, ofs + 4) == 0; + bool isFavorite = BitConverter.ToInt32(data, ofs + 0x8) == 1; + // ushort sortOrder = BitConverter.ToUInt16(data, ofs + 0xE); + Items[ctr++] = new InventoryItem { Index = index, Count = count, New = isNew, FreeSpace = isFavorite }; + } + + while (ctr != LegalItems.Length) + Items[ctr++] = new InventoryItem(); + OriginalItems = Items.Select(i => i.Clone()).ToArray(); + } + + public override void SetPouch(byte[] data) + { + foreach (var item in Items) + { + var index = (ushort)item.Index; + var isInLegal = Array.IndexOf(LegalItems, index); + if (isInLegal == -1) + { + Debug.WriteLine($"Invalid Item ID returned within this pouch: {index}"); + continue; + } + + if (SetNew && item.Index != 0) + item.New |= OriginalItems.All(z => z.Index != item.Index); + + var ofs = GetItemOffset(index, Offset); + WriteItem(item, data, ofs); + } + } + + public static int GetItemOffset(ushort index, int baseOffset) => baseOffset + (SIZE_ITEM * index); + + public static void WriteItem(InventoryItem item, byte[] data, int ofs) + { + BitConverter.GetBytes((uint)item.Count).CopyTo(data, ofs); + BitConverter.GetBytes(item.New ? 0u : 1u).CopyTo(data, ofs + 4); + BitConverter.GetBytes(item.FreeSpace ? 1u : 0u).CopyTo(data, ofs + 8); + if (item.Count == 0) + BitConverter.GetBytes((ushort)0xFFFF).CopyTo(data, ofs + 0xE); + } + } +} diff --git a/PKHeX.Core/Saves/Util/SaveExtensions.cs b/PKHeX.Core/Saves/Util/SaveExtensions.cs index 3b8837ed25e..fecba93cca3 100644 --- a/PKHeX.Core/Saves/Util/SaveExtensions.cs +++ b/PKHeX.Core/Saves/Util/SaveExtensions.cs @@ -170,11 +170,16 @@ public static PKM GetCompatiblePKM(this SaveFile sav, PKM pk) } /// - /// Gets a blank file for the save file. If the template path exists, a template load will be attempted. + /// Gets a blank file for the save file. Adapts it to the save file. /// /// Save File to fetch a template for /// Template if it exists, or a blank from the - private static PKM LoadTemplateInternal(this SaveFile sav) => sav.BlankPKM; + private static PKM LoadTemplateInternal(this SaveFile sav) + { + var pk = sav.BlankPKM; + EntityTemplates.TemplateFields(pk, sav); + return pk; + } /// /// Gets a blank file for the save file. If the template path exists, a template load will be attempted. diff --git a/PKHeX.Core/Saves/Util/SaveUtil.cs b/PKHeX.Core/Saves/Util/SaveUtil.cs index de56bb5de02..6cf87b26424 100644 --- a/PKHeX.Core/Saves/Util/SaveUtil.cs +++ b/PKHeX.Core/Saves/Util/SaveUtil.cs @@ -14,6 +14,9 @@ public static class SaveUtil { public const int BEEF = 0x42454546; + public const int SIZE_G8BDSP = 0xE9828; + public const int SIZE_G8BDSP_1 = 0xEDC20; + public const int SIZE_G8SWSH = 0x1716B3; // 1.0 public const int SIZE_G8SWSH_1 = 0x17195E; // 1.0 -> 1.1 public const int SIZE_G8SWSH_2 = 0x180B19; // 1.0 -> 1.1 -> 1.2 @@ -93,6 +96,7 @@ public static class SaveUtil private static readonly HashSet Sizes = new(SizesGen2.Concat(SizesSWSH)) { + SIZE_G8BDSP, // SizesSWSH covers gen8 sizes since there's so many SIZE_G7SM, SIZE_G7USUM, SIZE_G7GG, SIZE_G6XY, SIZE_G6ORAS, SIZE_G6ORASDEMO, @@ -154,6 +158,8 @@ private static GameVersion GetSAVType(byte[] data) if ((ver = GetIsG8SAV(data)) != Invalid) return ver; + if ((ver = GetIsG8SAV_BDSP(data)) != Invalid) + return ver; return Invalid; } @@ -489,6 +495,14 @@ private static GameVersion GetIsG8SAV(byte[] data) return SwishCrypto.GetIsHashValid(data) ? SWSH : Invalid; } + private static GameVersion GetIsG8SAV_BDSP(byte[] data) + { + if (data.Length is not SIZE_G8BDSP && data.Length is not SIZE_G8BDSP_1) + return Invalid; + + return BDSP; + } + private static bool GetIsBank7(byte[] data) => data.Length == SIZE_G7BANK && data[0] != 0; private static bool GetIsBank4(byte[] data) => data.Length == SIZE_G4BANK && BitConverter.ToUInt32(data, 0x3FC00) != 0; // box name present private static bool GetIsBank3(byte[] data) => data.Length == SIZE_G4BANK && BitConverter.ToUInt32(data, 0x3FC00) == 0; // size collision with ^ @@ -586,6 +600,7 @@ private static GameVersion GetIsG8SAV(byte[] data) GG => new SAV7b(data), SWSH => new SAV8SWSH(data), + BDSP => new SAV8BS(data), // Side Games COLO => new SAV3Colosseum(data), @@ -730,6 +745,7 @@ public static SaveFile GetBlankSAV(GameVersion game, string trainerName, Languag GP or GE or GG or GO => new SAV7b(), SW or SH or SWSH => new SAV8SWSH(), + BD or SP or BDSP => new SAV8BS(), _ => throw new ArgumentOutOfRangeException(nameof(game)), }; diff --git a/PKHeX.Drawing/Names/BoxWallpaper.cs b/PKHeX.Drawing/Names/BoxWallpaper.cs index 25fde13403b..a0ba024e8b7 100644 --- a/PKHeX.Drawing/Names/BoxWallpaper.cs +++ b/PKHeX.Drawing/Names/BoxWallpaper.cs @@ -29,6 +29,7 @@ 4 when HGSS.Contains(version) => "hgss", 5 => B2W2.Contains(version) && index > 16 ? "b2w2" : "bw", 6 => ORAS.Contains(version) && index > 16 ? "ao" : "xy", 7 when !GG.Contains(version) => "xy", + 8 when BDSP.Contains(version) => "bdsp", 8 => "swsh", _ => string.Empty, }; @@ -75,6 +76,16 @@ public static bool IsWallpaperRed(GameVersion version, int wallpaperID) 20 => true, // Special5 Flare/Magma _ => false, }; + case 8 when BDSP.Contains(version): + return wallpaperID switch + { + 6 => true, // Volcano + 15 => true, // Checks + 21 => true, // Trio + 29 => true, // Nostalgic (Platinum) + 30 => true, // Legend (Platinum) + _ => false, + }; case 8: return wallpaperID switch { diff --git a/PKHeX.Drawing/Properties/Resources.Designer.cs b/PKHeX.Drawing/Properties/Resources.Designer.cs index bf0ae70cf33..02cfd5107f2 100644 --- a/PKHeX.Drawing/Properties/Resources.Designer.cs +++ b/PKHeX.Drawing/Properties/Resources.Designer.cs @@ -32390,6 +32390,16 @@ public static System.Drawing.Bitmap bitem_unk { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp01bdsp { + get { + object obj = ResourceManager.GetObject("box_wp01bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -32450,6 +32460,16 @@ public static System.Drawing.Bitmap box_wp01xy { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp02bdsp { + get { + object obj = ResourceManager.GetObject("box_wp02bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -32510,6 +32530,16 @@ public static System.Drawing.Bitmap box_wp02xy { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp03bdsp { + get { + object obj = ResourceManager.GetObject("box_wp03bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -32570,6 +32600,16 @@ public static System.Drawing.Bitmap box_wp03xy { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp04bdsp { + get { + object obj = ResourceManager.GetObject("box_wp04bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -32630,6 +32670,16 @@ public static System.Drawing.Bitmap box_wp04xy { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp05bdsp { + get { + object obj = ResourceManager.GetObject("box_wp05bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -32690,6 +32740,16 @@ public static System.Drawing.Bitmap box_wp05xy { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp06bdsp { + get { + object obj = ResourceManager.GetObject("box_wp06bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -32750,6 +32810,16 @@ public static System.Drawing.Bitmap box_wp06xy { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp07bdsp { + get { + object obj = ResourceManager.GetObject("box_wp07bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -32810,6 +32880,16 @@ public static System.Drawing.Bitmap box_wp07xy { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp08bdsp { + get { + object obj = ResourceManager.GetObject("box_wp08bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -32870,6 +32950,16 @@ public static System.Drawing.Bitmap box_wp08xy { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp09bdsp { + get { + object obj = ResourceManager.GetObject("box_wp09bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -32930,6 +33020,16 @@ public static System.Drawing.Bitmap box_wp09xy { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp10bdsp { + get { + object obj = ResourceManager.GetObject("box_wp10bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -32990,6 +33090,16 @@ public static System.Drawing.Bitmap box_wp10xy { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp11bdsp { + get { + object obj = ResourceManager.GetObject("box_wp11bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -33050,6 +33160,16 @@ public static System.Drawing.Bitmap box_wp11xy { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp12bdsp { + get { + object obj = ResourceManager.GetObject("box_wp12bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -33110,6 +33230,16 @@ public static System.Drawing.Bitmap box_wp12xy { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp13bdsp { + get { + object obj = ResourceManager.GetObject("box_wp13bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -33180,6 +33310,16 @@ public static System.Drawing.Bitmap box_wp13xy { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp14bdsp { + get { + object obj = ResourceManager.GetObject("box_wp14bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -33250,6 +33390,16 @@ public static System.Drawing.Bitmap box_wp14xy { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp15bdsp { + get { + object obj = ResourceManager.GetObject("box_wp15bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -33320,6 +33470,16 @@ public static System.Drawing.Bitmap box_wp15xy { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp16bdsp { + get { + object obj = ResourceManager.GetObject("box_wp16bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -33410,6 +33570,16 @@ public static System.Drawing.Bitmap box_wp17b2w2 { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp17bdsp { + get { + object obj = ResourceManager.GetObject("box_wp17bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -33490,6 +33660,16 @@ public static System.Drawing.Bitmap box_wp18b2w2 { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp18bdsp { + get { + object obj = ResourceManager.GetObject("box_wp18bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -33570,6 +33750,16 @@ public static System.Drawing.Bitmap box_wp19b2w2 { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp19bdsp { + get { + object obj = ResourceManager.GetObject("box_wp19bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -33650,6 +33840,16 @@ public static System.Drawing.Bitmap box_wp20b2w2 { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp20bdsp { + get { + object obj = ResourceManager.GetObject("box_wp20bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -33720,6 +33920,16 @@ public static System.Drawing.Bitmap box_wp21b2w2 { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp21bdsp { + get { + object obj = ResourceManager.GetObject("box_wp21bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -33790,6 +34000,16 @@ public static System.Drawing.Bitmap box_wp22b2w2 { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp22bdsp { + get { + object obj = ResourceManager.GetObject("box_wp22bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -33860,6 +34080,16 @@ public static System.Drawing.Bitmap box_wp23b2w2 { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp23bdsp { + get { + object obj = ResourceManager.GetObject("box_wp23bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -33930,6 +34160,16 @@ public static System.Drawing.Bitmap box_wp24b2w2 { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp24bdsp { + get { + object obj = ResourceManager.GetObject("box_wp24bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -33980,6 +34220,86 @@ public static System.Drawing.Bitmap box_wp24xy { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp25bdsp { + get { + object obj = ResourceManager.GetObject("box_wp25bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp26bdsp { + get { + object obj = ResourceManager.GetObject("box_wp26bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp27bdsp { + get { + object obj = ResourceManager.GetObject("box_wp27bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp28bdsp { + get { + object obj = ResourceManager.GetObject("box_wp28bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp29bdsp { + get { + object obj = ResourceManager.GetObject("box_wp29bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp30bdsp { + get { + object obj = ResourceManager.GetObject("box_wp30bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp31bdsp { + get { + object obj = ResourceManager.GetObject("box_wp31bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap box_wp32bdsp { + get { + object obj = ResourceManager.GetObject("box_wp32bdsp", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -35550,6 +35870,16 @@ public static System.Drawing.Bitmap ribbontraining { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap ribbontwinklingstar { + get { + object obj = ResourceManager.GetObject("ribbontwinklingstar", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/PKHeX.Drawing/Properties/Resources.resx b/PKHeX.Drawing/Properties/Resources.resx index 0d66624f137..7685646750d 100644 --- a/PKHeX.Drawing/Properties/Resources.resx +++ b/PKHeX.Drawing/Properties/Resources.resx @@ -11107,4 +11107,103 @@ ..\Resources\img\Big Pokemon Sprites\b_0.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\img\box\bdsp\box_wp01bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp02bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp03bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp04bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp05bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp06bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp07bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp08bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp09bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp10bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp11bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp12bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp13bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp14bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp15bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp16bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp17bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp18bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp19bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp20bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp21bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp22bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp23bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp24bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp25bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp26bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp27bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp28bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp29bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp30bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp31bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\box\bdsp\box_wp32bdsp.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\img\ribbons\ribbontwinklingstar.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp01bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp01bdsp.png new file mode 100644 index 00000000000..a35850034a6 Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp01bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp02bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp02bdsp.png new file mode 100644 index 00000000000..62b3c028dbf Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp02bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp03bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp03bdsp.png new file mode 100644 index 00000000000..d5cf6849cfd Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp03bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp04bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp04bdsp.png new file mode 100644 index 00000000000..77c41ba2ab4 Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp04bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp05bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp05bdsp.png new file mode 100644 index 00000000000..ea0c8115ed0 Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp05bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp06bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp06bdsp.png new file mode 100644 index 00000000000..afc79d990a6 Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp06bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp07bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp07bdsp.png new file mode 100644 index 00000000000..7f92594fa83 Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp07bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp08bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp08bdsp.png new file mode 100644 index 00000000000..b35fa7c61b2 Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp08bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp09bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp09bdsp.png new file mode 100644 index 00000000000..2c1b7b8f2e2 Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp09bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp10bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp10bdsp.png new file mode 100644 index 00000000000..eedfb78602b Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp10bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp11bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp11bdsp.png new file mode 100644 index 00000000000..3eb8125cb85 Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp11bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp12bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp12bdsp.png new file mode 100644 index 00000000000..00846726a26 Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp12bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp13bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp13bdsp.png new file mode 100644 index 00000000000..a33b8d284c8 Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp13bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp14bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp14bdsp.png new file mode 100644 index 00000000000..9599e9bf346 Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp14bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp15bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp15bdsp.png new file mode 100644 index 00000000000..875832dd13e Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp15bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp16bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp16bdsp.png new file mode 100644 index 00000000000..d1e888a8395 Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp16bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp17bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp17bdsp.png new file mode 100644 index 00000000000..7fd7e8c11ba Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp17bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp18bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp18bdsp.png new file mode 100644 index 00000000000..499704a1919 Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp18bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp19bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp19bdsp.png new file mode 100644 index 00000000000..5741468ad52 Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp19bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp20bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp20bdsp.png new file mode 100644 index 00000000000..088f2a99bc8 Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp20bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp21bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp21bdsp.png new file mode 100644 index 00000000000..7f6c4e0c54d Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp21bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp22bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp22bdsp.png new file mode 100644 index 00000000000..91aed8b7bd7 Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp22bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp23bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp23bdsp.png new file mode 100644 index 00000000000..197de8316bb Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp23bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp24bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp24bdsp.png new file mode 100644 index 00000000000..ac3e9c45096 Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp24bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp25bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp25bdsp.png new file mode 100644 index 00000000000..68160fbac2b Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp25bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp26bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp26bdsp.png new file mode 100644 index 00000000000..8ced48b6813 Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp26bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp27bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp27bdsp.png new file mode 100644 index 00000000000..2bca918a04d Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp27bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp28bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp28bdsp.png new file mode 100644 index 00000000000..7118e8ad63e Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp28bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp29bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp29bdsp.png new file mode 100644 index 00000000000..8d26c3d94e7 Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp29bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp30bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp30bdsp.png new file mode 100644 index 00000000000..7dca84f93bd Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp30bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp31bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp31bdsp.png new file mode 100644 index 00000000000..ed1ca98ac24 Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp31bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/box/bdsp/box_wp32bdsp.png b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp32bdsp.png new file mode 100644 index 00000000000..28e7bfd3fb3 Binary files /dev/null and b/PKHeX.Drawing/Resources/img/box/bdsp/box_wp32bdsp.png differ diff --git a/PKHeX.Drawing/Resources/img/ribbons/ribbontwinklingstar.png b/PKHeX.Drawing/Resources/img/ribbons/ribbontwinklingstar.png new file mode 100644 index 00000000000..5c4ef0203a3 Binary files /dev/null and b/PKHeX.Drawing/Resources/img/ribbons/ribbontwinklingstar.png differ diff --git a/PKHeX.Drawing/Sprites/SpriteBuilder.cs b/PKHeX.Drawing/Sprites/SpriteBuilder.cs index 54755da02a3..cc2359e162c 100644 --- a/PKHeX.Drawing/Sprites/SpriteBuilder.cs +++ b/PKHeX.Drawing/Sprites/SpriteBuilder.cs @@ -150,6 +150,7 @@ private Image LayerOverImageItem(Image baseImage, int item, int generation) Image itemimg = generation switch { <= 4 when item is >= 328 and <= 419 => ItemTM, // gen2/3/4 TM + 8 when item is >= 328 and <= 427 => ItemTM, // BDSP TMs >= 8 when item is >= 1130 and <= 1229 => ItemTR, // Gen8 TR _ => (Image?)Resources.ResourceManager.GetObject(GetItemResourceName(item)) ?? UnknownItem, }; diff --git a/PKHeX.Drawing/Sprites/SpriteUtil.cs b/PKHeX.Drawing/Sprites/SpriteUtil.cs index 1e89c02c192..0861fb5573f 100644 --- a/PKHeX.Drawing/Sprites/SpriteUtil.cs +++ b/PKHeX.Drawing/Sprites/SpriteUtil.cs @@ -157,7 +157,7 @@ private static Image GetSprite(PKM pk, SaveFile sav, int box, int slot, bool fla var la = new LegalityAnalysis(pk, sav.Personal, box != -1 ? SlotOrigin.Box : SlotOrigin.Party); if (!la.Valid) sprite = ImageUtil.LayerImage(sprite, Resources.warn, 0, FlagIllegalShiftY); - else if (pk.Format >= 8 && pk.Moves.Any(Legal.DummiedMoves_SWSH.Contains)) + else if (pk.Format >= 8 && pk.Moves.Any(Legal.GetDummiedMovesHashSet(pk).Contains)) sprite = ImageUtil.LayerImage(sprite, Resources.hint, 0, FlagIllegalShiftY); if (SpriteBuilder.ShowEncounterColorPKM != SpriteBackgroundType.None) sprite = ApplyEncounterColor(la.EncounterOriginal, sprite, SpriteBuilder.ShowEncounterColorPKM); diff --git a/PKHeX.WinForms/Controls/PKM Editor/EditPK8.cs b/PKHeX.WinForms/Controls/PKM Editor/EditPK8.cs index ce04ffef132..0e3dac9c6c8 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/EditPK8.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/EditPK8.cs @@ -44,5 +44,45 @@ private PK8 PreparePK8() pk8.RefreshChecksum(); return pk8; } + + private PB8 PreparePB8() + { + if (Entity is not PB8 pk8) + throw new FormatException(nameof(Entity)); + + SaveMisc1(pk8); + SaveMisc2(pk8); + SaveMisc3(pk8); + SaveMisc4(pk8); + SaveMisc6(pk8); + SaveMisc8(pk8); + + // Toss in Party Stats + SavePartyStats(pk8); + + pk8.FixMoves(); + pk8.FixRelearn(); + if (ModifyPKM) + pk8.FixMemories(); + pk8.RefreshChecksum(); + return pk8; + } + + private void PopulateFieldsPB8() + { + if (Entity is not PB8 pk8) + throw new FormatException(nameof(Entity)); + + LoadMisc1(pk8); + LoadMisc2(pk8); + LoadMisc3(pk8); + LoadMisc4(pk8); + LoadMisc6(pk8); + SizeCP.LoadPKM(pk8); + LoadMisc8(pk8); + + LoadPartyStats(pk8); + UpdateStats(); + } } } diff --git a/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs b/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs index 7752720f348..25298a690b8 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/LoadSave.cs @@ -238,21 +238,18 @@ private void SaveMisc3(PKM pk) private void LoadMisc4(PKM pk) { CAL_MetDate.Value = pk.MetDate ?? new DateTime(2000, 1, 1); - if (pk.Egg_Location == 0) + if (Locations.IsNoneLocation((GameVersion)pk.Version, pk.Egg_Location)) { CHK_AsEgg.Checked = GB_EggConditions.Enabled = false; - - CB_EggLocation.SelectedValue = 0; CAL_EggDate.Value = new DateTime(2000, 01, 01); } else { // Was obtained initially as an egg. CHK_AsEgg.Checked = GB_EggConditions.Enabled = true; - - CB_EggLocation.SelectedValue = pk.Egg_Location; CAL_EggDate.Value = pk.EggMetDate ?? new DateTime(2000, 1, 1); } + CB_EggLocation.SelectedValue = pk.Egg_Location; } private void SaveMisc4(PKM pk) @@ -261,7 +258,7 @@ private void SaveMisc4(PKM pk) // Default Dates DateTime? egg_date = null; - int egg_location = 0; + int egg_location = Locations.GetNoneLocation((GameVersion)pk.Version); if (CHK_AsEgg.Checked) // If encountered as an egg, load the Egg Met data from fields. { egg_date = CAL_EggDate.Value; @@ -270,7 +267,7 @@ private void SaveMisc4(PKM pk) // Egg Met Data pk.EggMetDate = egg_date; pk.Egg_Location = egg_location; - if (pk.IsEgg && pk.Met_Location == 0) // If still an egg, it has no hatch location/date. Zero it! + if (pk.IsEgg && Locations.IsNoneLocation((GameVersion)pk.Version, pk.Met_Location)) // If still an egg, it has no hatch location/date. Zero it! pk.MetDate = null; pk.Ability = WinFormsUtil.GetIndex(HaX ? DEV_Ability : CB_Ability); @@ -400,5 +397,24 @@ private void SaveMisc8(PK8 pk8) pk8.HT_Language = WinFormsUtil.GetIndex(CB_HTLanguage); pk8.BattleVersion = WinFormsUtil.GetIndex(CB_BattleVersion); } + + private void LoadMisc8(PB8 pk8) + { + CB_StatNature.SelectedValue = pk8.StatNature; + Stats.CB_DynamaxLevel.SelectedIndex = pk8.DynamaxLevel; + Stats.CHK_Gigantamax.Checked = pk8.CanGigantamax; + CB_HTLanguage.SelectedValue = pk8.HT_Language; + TB_HomeTracker.Text = pk8.Tracker.ToString("X16"); + CB_BattleVersion.SelectedValue = pk8.BattleVersion; + } + + private void SaveMisc8(PB8 pk8) + { + pk8.StatNature = WinFormsUtil.GetIndex(CB_StatNature); + pk8.DynamaxLevel = (byte)Math.Max(0, Stats.CB_DynamaxLevel.SelectedIndex); + pk8.CanGigantamax = Stats.CHK_Gigantamax.Checked; + pk8.HT_Language = WinFormsUtil.GetIndex(CB_HTLanguage); + pk8.BattleVersion = WinFormsUtil.GetIndex(CB_BattleVersion); + } } } diff --git a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs index 2a40e07aa8b..8585bb3d565 100644 --- a/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs +++ b/PKHeX.WinForms/Controls/PKM Editor/PKMEditor.cs @@ -14,7 +14,7 @@ namespace PKHeX.WinForms.Controls { public sealed partial class PKMEditor : UserControl, IMainEditor { - public bool IsInitialized { get; set; } + public bool IsInitialized { get; private set; } public PKMEditor() { @@ -49,7 +49,7 @@ public PKMEditor() new(new[] {CB_HeldItem}, pk => pk.Format >= 2, Criteria), new(new[] {CB_Ability, CB_Nature, CB_MetLocation, CB_Ball}, pk => pk.Format >= 3, Criteria), new(new[] {CB_EggLocation}, pk => pk.Format >= 4, Criteria), - new(new [] {CB_Country, CB_SubRegion}, pk => pk is PK6 or PK7, Criteria), + new(new[] {CB_Country, CB_SubRegion}, pk => pk is PK6 or PK7, Criteria), new(Relearn, pk => pk.Format >= 6, Criteria), new(new[] {CB_StatNature}, pk => pk.Format >= 8, Criteria), }; @@ -97,6 +97,8 @@ public void InitializeBinding() }; foreach (var cb in cbs.Concat(Moves.Concat(Relearn))) cb.InitializeBinding(); + + IsInitialized = true; } private void UpdateStats() @@ -234,58 +236,28 @@ public bool EditsComplete } } - public void SetPKMFormatMode(int Format, PKM pk) + public void SetPKMFormatMode(PKM pk) { // Load Extra Byte List SetPKMFormatExtraBytes(pk); - - switch (Format) - { - case 1: - GetFieldsfromPKM = PopulateFieldsPK1; - GetPKMfromFields = PreparePK1; - break; - case 2: - GetFieldsfromPKM = PopulateFieldsPK2; - GetPKMfromFields = PreparePK2; - break; - case 3: - GetFieldsfromPKM = PopulateFieldsPK3; - GetPKMfromFields = PreparePK3; - break; - case 4: - GetFieldsfromPKM = PopulateFieldsPK4; - GetPKMfromFields = PreparePK4; - break; - case 5: - GetFieldsfromPKM = PopulateFieldsPK5; - GetPKMfromFields = PreparePK5; - break; - case 6: - GetFieldsfromPKM = PopulateFieldsPK6; - GetPKMfromFields = PreparePK6; - break; - case 7: - switch (pk) - { - case PK7: - GetFieldsfromPKM = PopulateFieldsPK7; - GetPKMfromFields = PreparePK7; - break; - - case PB7: - GetFieldsfromPKM = PopulateFieldsPB7; - GetPKMfromFields = PreparePB7; - break; - } - break; - case 8: - GetFieldsfromPKM = PopulateFieldsPK8; - GetPKMfromFields = PreparePK8; - break; - } + (GetFieldsfromPKM, GetPKMfromFields) = GetLoadSet(pk); } + private (Action, Func) GetLoadSet(PKM pk) => pk.Format switch + { + 1 => (PopulateFieldsPK1, PreparePK1), + 2 => (PopulateFieldsPK2, PreparePK2), + 3 => (PopulateFieldsPK3, PreparePK3), + 4 => (PopulateFieldsPK4, PreparePK4), + 5 => (PopulateFieldsPK5, PreparePK5), + 6 => (PopulateFieldsPK6, PreparePK6), + 7 when pk is PK7 => (PopulateFieldsPK7, PreparePK7), + 7 when pk is PB7 => (PopulateFieldsPB7, PreparePB7), + 8 when pk is PK8 => (PopulateFieldsPK8, PreparePK8), + 8 when pk is PB8 => (PopulateFieldsPB8, PreparePB8), + _ => throw new FormatException($"Unrecognized Type: {pk.GetType()}"), + }; + private void SetPKMFormatExtraBytes(PKM pk) { var extraBytes = pk.ExtraBytes; @@ -361,7 +333,7 @@ public void UpdateLegality(LegalityAnalysis? la = null, bool skipMoveRepop = fal Bitmap? img; if (invalid) img = Resources.warn; - else if (Entity.Format >= 8 && Legal.DummiedMoves_SWSH.Contains(moves[i])) + else if (Entity.Format >= 8 && Legal.GetDummiedMovesHashSet(Entity).Contains(moves[i])) img = Resources.hint; else img = null; @@ -578,8 +550,10 @@ private void SetMarkings() return Properties.Resources.gen_6; if (pkm.Gen7) return Properties.Resources.gen_7; - if (pkm.Gen8) + if (pkm.SWSH) return Properties.Resources.gen_8; + if (pkm.BDSP) + return Properties.Resources.gen_bs; return null; } @@ -1445,7 +1419,7 @@ private void UpdateIsEgg(object sender, EventArgs e) { var sav = SaveFileRequested.Invoke(this, e); bool isTraded = sav.OT != TB_OT.Text || sav.TID != Entity.TID || sav.SID != Entity.SID; - var loc = isTraded ? Locations.TradedEggLocation(sav.Generation) : 0; + var loc = isTraded ? Locations.TradedEggLocation(sav.Generation, (GameVersion)sav.Version) : 0; CB_MetLocation.SelectedValue = loc; } else if (Entity.Format == 3) @@ -1995,7 +1969,6 @@ public void ChangeLanguage(ITrainerInfo sav, PKM pk) InitializeLanguage(sav); CenterSubEditors(); - PopulateFields(pk); // put data back in form } public void FlickerInterface() diff --git a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs index 14561a499f5..e458238b021 100644 --- a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs +++ b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs @@ -523,6 +523,7 @@ private void B_OpenEventFlags_Click(object sender, EventArgs e) { SAV1 s => (Form) new SAV_EventReset1(s), SAV7b s => new SAV_EventWork(s), + SAV8BS s => new SAV_FlagWork8b(s), _ => new SAV_EventFlags(SAV), }; form.ShowDialog(); @@ -634,6 +635,7 @@ private void B_OpenPokedex_Click(object sender, EventArgs e) SAV7 s7 => new SAV_PokedexSM(s7), SAV7b b7 => new SAV_PokedexGG(b7), SAV8SWSH swsh => new SAV_PokedexSWSH(swsh), + SAV8BS bs => new SAV_PokedexBDSP(bs), _ => (Form?)null, }; form?.ShowDialog(); diff --git a/PKHeX.WinForms/MainWindow/Main.Designer.cs b/PKHeX.WinForms/MainWindow/Main.Designer.cs index 64752a1e16a..22762122c15 100644 --- a/PKHeX.WinForms/MainWindow/Main.Designer.cs +++ b/PKHeX.WinForms/MainWindow/Main.Designer.cs @@ -411,7 +411,6 @@ public void InitializeComponent() this.PKME_Tabs.Data = null; this.PKME_Tabs.Dock = System.Windows.Forms.DockStyle.Fill; this.PKME_Tabs.HaX = false; - this.PKME_Tabs.IsInitialized = false; this.PKME_Tabs.Location = new System.Drawing.Point(0, 0); this.PKME_Tabs.Margin = new System.Windows.Forms.Padding(5); this.PKME_Tabs.Name = "PKME_Tabs"; diff --git a/PKHeX.WinForms/MainWindow/Main.cs b/PKHeX.WinForms/MainWindow/Main.cs index 38b071475d9..0677ae1a654 100644 --- a/PKHeX.WinForms/MainWindow/Main.cs +++ b/PKHeX.WinForms/MainWindow/Main.cs @@ -740,23 +740,20 @@ private void ResetSAVPKMEditors(SaveFile sav) C_SAV.SetEditEnvironment(new SaveDataEditor(sav, PKME_Tabs)); var pk = sav.LoadTemplate(TemplatePath); - var isBlank = pk.Data.SequenceEqual(sav.BlankPKM.Data); - if (isBlank) - EntityTemplates.TemplateFields(pk, sav); - bool init = PKME_Tabs.IsInitialized; PKME_Tabs.CurrentPKM = pk; + + bool init = PKME_Tabs.IsInitialized; if (!init) { PKME_Tabs.InitializeBinding(); - PKME_Tabs.IsInitialized = true; - PKME_Tabs.SetPKMFormatMode(sav.Generation, pk); - PKME_Tabs.ChangeLanguage(sav, pk); // populates fields + PKME_Tabs.SetPKMFormatMode(pk); + PKME_Tabs.ChangeLanguage(sav, pk); } else { - PKME_Tabs.SetPKMFormatMode(sav.Generation, pk); - PKME_Tabs.PopulateFields(pk); + PKME_Tabs.SetPKMFormatMode(pk); } + PKME_Tabs.PopulateFields(pk); // Initialize Overall Info Menu_LoadBoxes.Enabled = Menu_DumpBoxes.Enabled = Menu_DumpBox.Enabled = Menu_Report.Enabled = C_SAV.SAV.HasBox; @@ -900,6 +897,7 @@ private void ChangeMainLanguage(object sender, EventArgs e) var pk = PKME_Tabs.CurrentPKM.Clone(); PKME_Tabs.ChangeLanguage(sav, pk); + PKME_Tabs.PopulateFields(pk); // put data back in form Text = GetProgramTitle(sav); } } diff --git a/PKHeX.WinForms/PKHeX.WinForms.csproj b/PKHeX.WinForms/PKHeX.WinForms.csproj index 5934e42582c..d47e0732210 100644 --- a/PKHeX.WinForms/PKHeX.WinForms.csproj +++ b/PKHeX.WinForms/PKHeX.WinForms.csproj @@ -2,7 +2,7 @@ WinExe - net46;net5.0-windows + net46;net6.0-windows true PKHeX Project Pokémon @@ -12,7 +12,7 @@ Resources\Icon.ico PKHeX.WinForms.Program PKHeX - 21.10.01 + 21.11.19 9 enable diff --git a/PKHeX.WinForms/Properties/PKHeXSettings.cs b/PKHeX.WinForms/Properties/PKHeXSettings.cs index b8ebb8c0079..604c8aefe25 100644 --- a/PKHeX.WinForms/Properties/PKHeXSettings.cs +++ b/PKHeX.WinForms/Properties/PKHeXSettings.cs @@ -135,7 +135,7 @@ public sealed class StartupSettings : IStartupSettings public List RecentlyLoaded { get; set; } = new(MaxRecentCount); // Don't let invalid values slip into the startup version. - private GameVersion _defaultSaveVersion = GameVersion.SW; + private GameVersion _defaultSaveVersion = GameVersion.BD; private string _language = GameLanguage.DefaultLanguage; [Browsable(false)] diff --git a/PKHeX.WinForms/Properties/Resources.Designer.cs b/PKHeX.WinForms/Properties/Resources.Designer.cs index 916d396f3fa..75be5c9cdd7 100644 --- a/PKHeX.WinForms/Properties/Resources.Designer.cs +++ b/PKHeX.WinForms/Properties/Resources.Designer.cs @@ -8,7 +8,6 @@ // //------------------------------------------------------------------------------ -[assembly: System.Resources.NeutralResourcesLanguage("en")] namespace PKHeX.WinForms.Properties { using System; @@ -215,15 +214,13 @@ public static System.Drawing.Bitmap box_wp_default { /// Looks up a localized string similar to PKHeX - By Kaphotics ///http://projectpokemon.org/pkhex/ /// - ///20/04/14 - New Update: + ///21/10/01 - New Update: /// - Legality: - /// - - Added: Latest raid news data. - /// - - Fixed: HOME gifts now recognized. - /// - - Fixed: Antishiny Colosseum/XD spreads are recognized better for various gifts. - /// - - Fixed: Some unavailable evolution cases are now recognized correctly. - /// - - Fixed: Silvally Pixie Plate is now recognized correctly. - /// - - Fixed: Gen8 Raid downleveling thresholds are now recognized correctly. - /// - - Fixed: Gen8 Link trade eggs are no [rest of string was truncated]";. + /// - - Added: Gen8 memory checks for unobtainable values. Thanks @Lusamine, @skadiv! + /// - - Changed: Ball legality rules updated for Gen7 starters to account for the new Gen8 raids. + /// - - Changed: Gen1 Tradeback handling reworked for less overhead. + /// - - Fixed more met locations for XD shadow encounters. Thanks @LegoFigure11! + /// - - Fixed: Gen4 Cute Charm PIDs correctly emit RNG frames for encounter matching purposes [rest of string was truncated]";. /// public static string changelog { get { @@ -421,6 +418,16 @@ public static System.Drawing.Bitmap gen_8 { } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + public static System.Drawing.Bitmap gen_bs { + get { + object obj = ResourceManager.GetObject("gen_bs", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// @@ -522,26 +529,25 @@ public static System.Drawing.Bitmap import { } /// - /// Looks up a localized string similar to About=About + /// Looks up a localized string similar to About=Über ///BatchEditor=Batch Editor - ///ErrorWindow=Error - ///KChart=KChart + ///ErrorWindow=Fehler + ///KChart=KTabelle ///Main=PKHeX - ///MemoryAmie=Memory / Amie Editor - ///RibbonEditor=Ribbon Editor - ///SAV_Apricorn=Apricorn Editor - ///SAV_BerryField=Berry Field Viewer - ///SAV_BlockDump8=Savedata Block Dump + ///MemoryAmie=Erinnerung / Ami Editor + ///RibbonEditor=Band Editor + ///SAV_Apricorn=Aprikoko Editor + ///SAV_BerryField=Beerenfeld Ansicht + ///SAV_BlockDump8=Spielstand Block Dump ///SAV_BoxLayout=Box Layout Editor - ///SAV_BoxList=Storage Viewer + ///SAV_BoxList=PC Ansicht + ///SAV_Capture7GG=Fang Statistik Editor ///SAV_CGearSkin=C-Gear Skin - ///SAV_Database=Database - ///SAV_Encounters=Database + ///SAV_Database=Datenbank + ///SAV_Encounters=Datenbank ///SAV_EventFlags=Event Flag Editor ///SAV_EventReset1=Event Resetter - ///SAV_EventWork=Event Flag Editor - ///SAV_FolderList=Folder List - ///SA [rest of string was truncated]";. + ///SAV_EventWork=Event Fl [rest of string was truncated]";. /// public static string lang_de { get { @@ -562,14 +568,13 @@ public static string lang_de { ///SAV_BlockDump8=Savedata Block Dump ///SAV_BoxLayout=Box Layout Editor ///SAV_BoxList=Storage Viewer + ///SAV_Capture7GG=Capture Record Editor ///SAV_CGearSkin=C-Gear Skin ///SAV_Database=Database ///SAV_Encounters=Database ///SAV_EventFlags=Event Flag Editor ///SAV_EventReset1=Event Resetter - ///SAV_EventWork=Event Flag Editor - ///SAV_FolderList=Folder List - ///SA [rest of string was truncated]";. + ///SAV_EventWork=Event Flag [rest of string was truncated]";. /// public static string lang_en { get { @@ -590,11 +595,11 @@ public static string lang_en { ///SAV_BlockDump8=Respaldo de bloques ///SAV_BoxLayout=Editor de fondos de Cajas ///SAV_BoxList=Visor de Almacenamiento + ///SAV_Capture7GG=Capture Record Editor ///SAV_CGearSkin=Editor de la apariencia C-Gear ///SAV_Database=Base de Datos ///SAV_Encounters=Base de Datos - ///SAV_EventFlags=Editor de marca de eventos - ///SAV_Event [rest of string was truncated]";. + ///SAV_EventFlags [rest of string was truncated]";. /// public static string lang_es { get { @@ -604,7 +609,7 @@ public static string lang_es { /// /// Looks up a localized string similar to About=À propos - ///BatchEditor=Batch Editor + ///BatchEditor=Éditeur Batch ///ErrorWindow=Erreur ///KChart=KChart ///Main=PKHeX @@ -612,16 +617,15 @@ public static string lang_es { ///RibbonEditor=Rubans ///SAV_Apricorn=Noigrumes ///SAV_BerryField=Champs de Baies - ///SAV_BlockDump8=Savedata Block Dump + ///SAV_BlockDump8=Sauvegarde des blocs de données ///SAV_BoxLayout=Fonds de Boîtes - ///SAV_BoxList=Storage Viewer + ///SAV_BoxList=Visualiseur de stockage + ///SAV_Capture7GG=Capture Éditeur d'enregistrement ///SAV_CGearSkin=Fonds C-Gear ///SAV_Database=Base de Données - ///SAV_Encounters=Database + ///SAV_Encounters=Base de données ///SAV_EventFlags=Événements dans le Jeu - ///SAV_EventReset1=Réinitialisateur d'événements - ///SAV_EventWork=Event Flag Editor - ///SAV_FolderList=L [rest of string was truncated]";. + ///SAV_EventReset1=Ré [rest of string was truncated]";. /// public static string lang_fr { get { @@ -642,14 +646,13 @@ public static string lang_fr { ///SAV_BlockDump8=Savedata Block Dump ///SAV_BoxLayout=Box Layout Editor ///SAV_BoxList=Storage Viewer + ///SAV_Capture7GG=Capture Record Editor ///SAV_CGearSkin=C-Gear Skin ///SAV_Database=Database ///SAV_Encounters=Database ///SAV_EventFlags=Event Flag Editor ///SAV_EventReset1=Event Resetter - ///SAV_EventWork=Event Flag Editor - ///SAV_FolderList=Folder List - ///SA [rest of string was truncated]";. + ///SAV_EventWork=Event Flag [rest of string was truncated]";. /// public static string lang_it { get { @@ -670,6 +673,7 @@ public static string lang_it { ///SAV_BlockDump8=Savedata Block Dump ///SAV_BoxLayout=ボックスレイアウト ///SAV_BoxList=ボックスリスト + ///SAV_Capture7GG=Capture Record Editor ///SAV_CGearSkin=Cギア スキン ///SAV_Database=データベース ///SAV_Encounters=Database @@ -679,8 +683,7 @@ public static string lang_it { ///SAV_FolderList=フォルダリスト ///SAV_GameSelect=ゲームバーション ///SAV_HallOfFame=殿堂入りデータ - ///SAV_HallOfFame7=殿堂入りデータ参照 - ///SAV_HoneyTree=あまいかおりのする [rest of string was truncated]";. + ///SAV_HallOfFa [rest of string was truncated]";. /// public static string lang_ja { get { @@ -701,6 +704,7 @@ public static string lang_ja { ///SAV_BlockDump8=세이브 데이터 블록 덤프 ///SAV_BoxLayout=박스 레이아웃 편집 도구 ///SAV_BoxList=소지 공간 뷰어 + ///SAV_Capture7GG=Capture Record Editor ///SAV_CGearSkin=C기어 스킨 ///SAV_Database=데이터베이스 ///SAV_Encounters=데이터베이스 @@ -709,9 +713,7 @@ public static string lang_ja { ///SAV_EventWork=이벤트 플래그 편집 도구 ///SAV_FolderList=폴더 목록 ///SAV_GameSelect=게임 선택 - ///SAV_HallOfFame=전당등록 편집 도구 - ///SAV_HallOfFame7=전당등록 편집 도구 - ///SAV_ [rest of string was truncated]";. + ///SAV_HallOfFame=전당등록 편 [rest of string was truncated]";. /// public static string lang_ko { get { @@ -732,6 +734,7 @@ public static string lang_ko { ///SAV_BlockDump8=存档转储 ///SAV_BoxLayout=盒子外观 ///SAV_BoxList=寄放系统 + ///SAV_Capture7GG=捕获记录编辑 ///SAV_CGearSkin=C装置皮肤 ///SAV_Database=数据库 ///SAV_Encounters=数据库 @@ -745,8 +748,7 @@ public static string lang_ko { ///SAV_HoneyTree=甜甜蜜树编辑 ///SAV_Inventory=物品栏 ///SAV_Link6=宝可梦连接工具 - ///SAV_MailBox=邮箱编辑 - ///SAV_Misc3=训练家数据编辑 [rest of string was truncated]";. + ///SAV_MailBox= [rest of string was truncated]";. /// public static string lang_zh { get { diff --git a/PKHeX.WinForms/Properties/Resources.resx b/PKHeX.WinForms/Properties/Resources.resx index a245c497e19..f697f6759a3 100644 --- a/PKHeX.WinForms/Properties/Resources.resx +++ b/PKHeX.WinForms/Properties/Resources.resx @@ -370,4 +370,7 @@ ..\Resources\img\Markings\icon_btlrom.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\img\Markings\gen_bs.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/PKHeX.WinForms/Resources/img/Markings/gen_bs.png b/PKHeX.WinForms/Resources/img/Markings/gen_bs.png new file mode 100644 index 00000000000..8e8ea9f8eff Binary files /dev/null and b/PKHeX.WinForms/Resources/img/Markings/gen_bs.png differ diff --git a/PKHeX.WinForms/Resources/text/changelog.txt b/PKHeX.WinForms/Resources/text/changelog.txt index fa1ab3e25f6..f744c231fbe 100644 --- a/PKHeX.WinForms/Resources/text/changelog.txt +++ b/PKHeX.WinForms/Resources/text/changelog.txt @@ -1,7 +1,27 @@ PKHeX - By Kaphotics http://projectpokemon.org/pkhex/ -21/10/01 - New Update: +21/11/19 - New Update + - Introducing Brilliant Diamond & Shining Pearl Support! Thanks @SciresM, @sora10pls, @Lusamine, @architdate, @ReignOfComputer for troubleshooting! + - - Initial Legality Checking is provided. Please refer to the forums when reporting legality issues for BDSP parsing. + - - Bag editing, Pokédex, and Event Flags, Trainer Info editing is provided. More editable values can be found in the Block Data editor. + - - Things to note: no transferring SWSH/HOME<->BDSP, roamer PIDIV correlation, no memories. Future commits may tighten legality checks. + - Legality: + - - Gen1: Lessened severity of missing moveslots to Fishy, if the Pokémon has been sufficiently leveled up (can skip by leveling up multiple times). + - - Gen2: Crystal eggs hatched inside the 2nd floor of the Pokécenter are now correctly recognized. Thanks Freezing Dart! + - - Gen4: Cute Charm frame proc yielding now emits the correct seed, and identifies the correct encounter slot value. Thanks @valthisse ! + - Added: More event flag data labels. Thanks @FeralFalcon! Event data can now be filtered via settings if you only want to see rebattle, etc. + - Added: Rival name changing for all games that didn't yet have it. Thanks @FeralFalcon! + - Changed: .NET 6 support added for WinForms builds. .NET Framework 4.6 build is still the main build option. + - Changed: Starting up the program with command line arguments (or opening via an associated file) will more intelligently source a parter sav/pkm. + - Changed: Exporting a backup save file has been moved to the SAV tab, and the Export main has been merged in with the parent Export SAV item. + - Changed: Gen1/2 mainline save files now indicate if they are VC era or GB era in the program title. + - Changed: Gen2 modifying Hidden Power type now maximizes IVs for that type. + - Changed: Gen3 egg flag being set from the GUI now adapts the language as well to match the Gen3 quirk. + - Fixed: Box Report exporting to CSV no longer causes errors if a large amount of data is being written. Thanks GLBBx303! + - Fixed: Gen6 Secret Base giving all decorations now correctly gives all. Was overwriting Pokepuffs :( + +21/10/01 - New Update: (129061) [4098815] - Legality: - - Added: Gen8 memory checks for unobtainable values. Thanks @Lusamine, @skadiv! - - Changed: Ball legality rules updated for Gen7 starters to account for the new Gen8 raids. diff --git a/PKHeX.WinForms/Subforms/PKM Editors/MemoryAmie.cs b/PKHeX.WinForms/Subforms/PKM Editors/MemoryAmie.cs index 2fa58e52a49..e4a78ccbe72 100644 --- a/PKHeX.WinForms/Subforms/PKM Editors/MemoryAmie.cs +++ b/PKHeX.WinForms/Subforms/PKM Editors/MemoryAmie.cs @@ -70,7 +70,7 @@ private void LoadFields() M_CT_Affection.Text = a.HT_Affection.ToString(); } - if (pkm is PK8 pk8) + if (pkm is G8PKM pk8) MT_Sociability.Text = Math.Min(byte.MaxValue, pk8.Sociability).ToString(); if (pkm is ITrainerMemories m) @@ -195,7 +195,7 @@ private void SaveFields() m.HT_Feeling = CB_CTFeel.Enabled ? CB_CTFeel.SelectedIndex : 0; } - if (pkm is PK8 pk8) + if (pkm is G8PKM pk8) pk8.Sociability = (byte)Util.ToInt32(MT_Sociability.Text); } diff --git a/PKHeX.WinForms/Subforms/PKM Editors/TechRecordEditor.cs b/PKHeX.WinForms/Subforms/PKM Editors/TechRecordEditor.cs index 1450882be56..1f546f7c719 100644 --- a/PKHeX.WinForms/Subforms/PKM Editors/TechRecordEditor.cs +++ b/PKHeX.WinForms/Subforms/PKM Editors/TechRecordEditor.cs @@ -7,11 +7,11 @@ namespace PKHeX.WinForms { public partial class TechRecordEditor : Form { - private readonly PK8 pkm; + private readonly G8PKM pkm; public TechRecordEditor(PKM pk) { - pkm = (PK8)pk; + pkm = (G8PKM)pk; InitializeComponent(); WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage); diff --git a/PKHeX.WinForms/Subforms/SAV_Database.cs b/PKHeX.WinForms/Subforms/SAV_Database.cs index ebfdfb16028..28f29c72104 100644 --- a/PKHeX.WinForms/Subforms/SAV_Database.cs +++ b/PKHeX.WinForms/Subforms/SAV_Database.cs @@ -365,8 +365,12 @@ private static List LoadPKMSaves(string pkmdb, SaveFile SAV, IEnumera if (Main.Settings.EntityDb.FilterUnavailableSpecies) { + static bool IsPresentInGameSWSH(ISpeciesForm pk) => pk is PK8 || ((PersonalInfoSWSH)PersonalTable.SWSH.GetFormEntry(pk.Species, pk.Form)).IsPresentInGame; + static bool IsPresentInGameBDSP(ISpeciesForm pk) => pk is PB8;//|| ((PersonalInfoBDSP)PersonalTable.BDSP.GetFormEntry(pk.Species, pk.Form)).IsPresentInGame; if (SAV is SAV8SWSH) - result.RemoveAll(z => !(z.Entity is PK8 || ((PersonalInfoSWSH) PersonalTable.SWSH.GetFormEntry(z.Entity.Species, z.Entity.Form)).IsPresentInGame)); + result.RemoveAll(z => !IsPresentInGameSWSH(z.Entity)); + else if (SAV is SAV8BS) + result.RemoveAll(z => !IsPresentInGameBDSP(z.Entity)); } var sort = Main.Settings.EntityDb.InitialSortMode; diff --git a/PKHeX.WinForms/Subforms/SAV_Encounters.cs b/PKHeX.WinForms/Subforms/SAV_Encounters.cs index cba636e0cec..c24b4c2e2ad 100644 --- a/PKHeX.WinForms/Subforms/SAV_Encounters.cs +++ b/PKHeX.WinForms/Subforms/SAV_Encounters.cs @@ -231,9 +231,14 @@ private IEnumerable SearchDatabase() if (Main.Settings.EncounterDb.FilterUnavailableSpecies) { - results = SAV is SAV8SWSH - ? results.Where(z => ((PersonalInfoSWSH)PersonalTable.SWSH.GetFormEntry(z.Species, z.Form)).IsPresentInGame) - : results.Where(z => z.Generation <= 7); + static bool IsPresentInGameSWSH(ISpeciesForm pk) => pk is PK8 || ((PersonalInfoSWSH)PersonalTable.SWSH.GetFormEntry(pk.Species, pk.Form)).IsPresentInGame; + static bool IsPresentInGameBDSP(ISpeciesForm pk) => pk is PB8 || ((PersonalInfoBDSP)PersonalTable.BDSP.GetFormEntry(pk.Species, pk.Form)).IsPresentInGame; + results = SAV switch + { + SAV8SWSH => results.Where(IsPresentInGameSWSH), + SAV8BS => results.Where(IsPresentInGameBDSP), + _ => results.Where(z => z.Generation <= 7), + }; } if (RTB_Instructions.Lines.Any(line => line.Length > 0)) diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_FlagWork8b.Designer.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_FlagWork8b.Designer.cs new file mode 100644 index 00000000000..0c75f87e3a1 --- /dev/null +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_FlagWork8b.Designer.cs @@ -0,0 +1,475 @@ +namespace PKHeX.WinForms +{ + sealed partial class SAV_FlagWork8b + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.B_Cancel = new System.Windows.Forms.Button(); + this.GB_FlagStatus = new System.Windows.Forms.GroupBox(); + this.CHK_CustomFlag = new System.Windows.Forms.CheckBox(); + this.button1 = new System.Windows.Forms.Button(); + this.NUD_System = new System.Windows.Forms.NumericUpDown(); + this.CHK_CustomSystem = new System.Windows.Forms.CheckBox(); + this.B_ApplyFlag = new System.Windows.Forms.Button(); + this.B_ApplyWork = new System.Windows.Forms.Button(); + this.NUD_Work = new System.Windows.Forms.NumericUpDown(); + this.NUD_Flag = new System.Windows.Forms.NumericUpDown(); + this.CB_CustomWork = new System.Windows.Forms.ComboBox(); + this.L_CustomWork = new System.Windows.Forms.Label(); + this.B_Save = new System.Windows.Forms.Button(); + this.GB_Researcher = new System.Windows.Forms.GroupBox(); + this.RTB_Diff = new System.Windows.Forms.RichTextBox(); + this.TB_NewSAV = new System.Windows.Forms.TextBox(); + this.TB_OldSAV = new System.Windows.Forms.TextBox(); + this.B_LoadNew = new System.Windows.Forms.Button(); + this.B_LoadOld = new System.Windows.Forms.Button(); + this.L_EventFlagWarn = new System.Windows.Forms.Label(); + this.TC_Features = new System.Windows.Forms.TabControl(); + this.GB_Flags = new System.Windows.Forms.TabPage(); + this.TLP_Flags = new System.Windows.Forms.TableLayoutPanel(); + this.GB_System = new System.Windows.Forms.TabPage(); + this.TLP_System = new System.Windows.Forms.TableLayoutPanel(); + this.GB_Work = new System.Windows.Forms.TabPage(); + this.GB_Research = new System.Windows.Forms.TabPage(); + this.TLP_Work = new System.Windows.Forms.TableLayoutPanel(); + this.GB_FlagStatus.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.NUD_System)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.NUD_Work)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.NUD_Flag)).BeginInit(); + this.GB_Researcher.SuspendLayout(); + this.TC_Features.SuspendLayout(); + this.GB_Flags.SuspendLayout(); + this.GB_System.SuspendLayout(); + this.GB_Work.SuspendLayout(); + this.GB_Research.SuspendLayout(); + this.SuspendLayout(); + // + // B_Cancel + // + this.B_Cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.B_Cancel.Location = new System.Drawing.Point(289, 330); + this.B_Cancel.Name = "B_Cancel"; + this.B_Cancel.Size = new System.Drawing.Size(75, 23); + this.B_Cancel.TabIndex = 2; + this.B_Cancel.Text = "Cancel"; + this.B_Cancel.UseVisualStyleBackColor = true; + this.B_Cancel.Click += new System.EventHandler(this.B_Cancel_Click); + // + // GB_FlagStatus + // + this.GB_FlagStatus.Controls.Add(this.CHK_CustomFlag); + this.GB_FlagStatus.Controls.Add(this.button1); + this.GB_FlagStatus.Controls.Add(this.NUD_System); + this.GB_FlagStatus.Controls.Add(this.CHK_CustomSystem); + this.GB_FlagStatus.Controls.Add(this.B_ApplyFlag); + this.GB_FlagStatus.Controls.Add(this.B_ApplyWork); + this.GB_FlagStatus.Controls.Add(this.NUD_Work); + this.GB_FlagStatus.Controls.Add(this.NUD_Flag); + this.GB_FlagStatus.Controls.Add(this.CB_CustomWork); + this.GB_FlagStatus.Controls.Add(this.L_CustomWork); + this.GB_FlagStatus.Location = new System.Drawing.Point(3, 3); + this.GB_FlagStatus.Name = "GB_FlagStatus"; + this.GB_FlagStatus.Size = new System.Drawing.Size(325, 103); + this.GB_FlagStatus.TabIndex = 3; + this.GB_FlagStatus.TabStop = false; + this.GB_FlagStatus.Text = "Check Status"; + // + // CHK_CustomFlag + // + this.CHK_CustomFlag.CheckAlign = System.Drawing.ContentAlignment.MiddleRight; + this.CHK_CustomFlag.Location = new System.Drawing.Point(12, 16); + this.CHK_CustomFlag.Name = "CHK_CustomFlag"; + this.CHK_CustomFlag.Size = new System.Drawing.Size(141, 23); + this.CHK_CustomFlag.TabIndex = 45; + this.CHK_CustomFlag.Text = "Event Flag:"; + this.CHK_CustomFlag.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + this.CHK_CustomFlag.UseVisualStyleBackColor = true; + // + // button1 + // + this.button1.Location = new System.Drawing.Point(249, 38); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(68, 23); + this.button1.TabIndex = 44; + this.button1.Text = "Apply"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.B_ApplySystemFlag_Click); + // + // NUD_System + // + this.NUD_System.Location = new System.Drawing.Point(159, 40); + this.NUD_System.Maximum = new decimal(new int[] { + 999, + 0, + 0, + 0}); + this.NUD_System.Name = "NUD_System"; + this.NUD_System.Size = new System.Drawing.Size(45, 20); + this.NUD_System.TabIndex = 43; + this.NUD_System.ValueChanged += new System.EventHandler(this.ChangeCustomSystem); + // + // CHK_CustomSystem + // + this.CHK_CustomSystem.CheckAlign = System.Drawing.ContentAlignment.MiddleRight; + this.CHK_CustomSystem.Location = new System.Drawing.Point(12, 39); + this.CHK_CustomSystem.Name = "CHK_CustomSystem"; + this.CHK_CustomSystem.Size = new System.Drawing.Size(141, 23); + this.CHK_CustomSystem.TabIndex = 41; + this.CHK_CustomSystem.Text = "System Flag:"; + this.CHK_CustomSystem.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + this.CHK_CustomSystem.UseVisualStyleBackColor = true; + // + // B_ApplyFlag + // + this.B_ApplyFlag.Location = new System.Drawing.Point(249, 15); + this.B_ApplyFlag.Name = "B_ApplyFlag"; + this.B_ApplyFlag.Size = new System.Drawing.Size(68, 23); + this.B_ApplyFlag.TabIndex = 40; + this.B_ApplyFlag.Text = "Apply"; + this.B_ApplyFlag.UseVisualStyleBackColor = true; + this.B_ApplyFlag.Click += new System.EventHandler(this.B_ApplyFlag_Click); + // + // B_ApplyWork + // + this.B_ApplyWork.Location = new System.Drawing.Point(249, 70); + this.B_ApplyWork.Name = "B_ApplyWork"; + this.B_ApplyWork.Size = new System.Drawing.Size(68, 23); + this.B_ApplyWork.TabIndex = 39; + this.B_ApplyWork.Text = "Apply"; + this.B_ApplyWork.UseVisualStyleBackColor = true; + this.B_ApplyWork.Click += new System.EventHandler(this.B_ApplyWork_Click); + // + // NUD_Work + // + this.NUD_Work.Location = new System.Drawing.Point(159, 70); + this.NUD_Work.Maximum = new decimal(new int[] { + 499, + 0, + 0, + 0}); + this.NUD_Work.Name = "NUD_Work"; + this.NUD_Work.Size = new System.Drawing.Size(84, 20); + this.NUD_Work.TabIndex = 38; + // + // NUD_Flag + // + this.NUD_Flag.Location = new System.Drawing.Point(159, 17); + this.NUD_Flag.Maximum = new decimal(new int[] { + 3999, + 0, + 0, + 0}); + this.NUD_Flag.Name = "NUD_Flag"; + this.NUD_Flag.Size = new System.Drawing.Size(45, 20); + this.NUD_Flag.TabIndex = 9; + this.NUD_Flag.ValueChanged += new System.EventHandler(this.ChangeCustomFlag); + // + // CB_CustomWork + // + this.CB_CustomWork.DropDownHeight = 156; + this.CB_CustomWork.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.CB_CustomWork.DropDownWidth = 180; + this.CB_CustomWork.FormattingEnabled = true; + this.CB_CustomWork.IntegralHeight = false; + this.CB_CustomWork.Location = new System.Drawing.Point(87, 69); + this.CB_CustomWork.Name = "CB_CustomWork"; + this.CB_CustomWork.Size = new System.Drawing.Size(66, 21); + this.CB_CustomWork.TabIndex = 36; + this.CB_CustomWork.SelectedIndexChanged += new System.EventHandler(this.ChangeConstantIndex); + // + // L_CustomWork + // + this.L_CustomWork.Location = new System.Drawing.Point(9, 70); + this.L_CustomWork.Name = "L_CustomWork"; + this.L_CustomWork.Size = new System.Drawing.Size(72, 20); + this.L_CustomWork.TabIndex = 37; + this.L_CustomWork.Text = "Constant:"; + this.L_CustomWork.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // B_Save + // + this.B_Save.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.B_Save.Location = new System.Drawing.Point(372, 330); + this.B_Save.Name = "B_Save"; + this.B_Save.Size = new System.Drawing.Size(75, 23); + this.B_Save.TabIndex = 9; + this.B_Save.Text = "Save"; + this.B_Save.UseVisualStyleBackColor = true; + this.B_Save.Click += new System.EventHandler(this.B_Save_Click); + // + // GB_Researcher + // + this.GB_Researcher.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.GB_Researcher.Controls.Add(this.RTB_Diff); + this.GB_Researcher.Controls.Add(this.TB_NewSAV); + this.GB_Researcher.Controls.Add(this.TB_OldSAV); + this.GB_Researcher.Controls.Add(this.B_LoadNew); + this.GB_Researcher.Controls.Add(this.B_LoadOld); + this.GB_Researcher.Location = new System.Drawing.Point(3, 110); + this.GB_Researcher.Name = "GB_Researcher"; + this.GB_Researcher.Size = new System.Drawing.Size(416, 170); + this.GB_Researcher.TabIndex = 13; + this.GB_Researcher.TabStop = false; + this.GB_Researcher.Text = "FlagDiff Researcher"; + // + // RTB_Diff + // + this.RTB_Diff.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.RTB_Diff.Location = new System.Drawing.Point(3, 73); + this.RTB_Diff.Name = "RTB_Diff"; + this.RTB_Diff.ReadOnly = true; + this.RTB_Diff.Size = new System.Drawing.Size(413, 97); + this.RTB_Diff.TabIndex = 6; + this.RTB_Diff.Text = ""; + // + // TB_NewSAV + // + this.TB_NewSAV.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TB_NewSAV.Location = new System.Drawing.Point(93, 47); + this.TB_NewSAV.Name = "TB_NewSAV"; + this.TB_NewSAV.ReadOnly = true; + this.TB_NewSAV.Size = new System.Drawing.Size(317, 20); + this.TB_NewSAV.TabIndex = 5; + // + // TB_OldSAV + // + this.TB_OldSAV.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TB_OldSAV.Location = new System.Drawing.Point(93, 21); + this.TB_OldSAV.Name = "TB_OldSAV"; + this.TB_OldSAV.ReadOnly = true; + this.TB_OldSAV.Size = new System.Drawing.Size(317, 20); + this.TB_OldSAV.TabIndex = 4; + // + // B_LoadNew + // + this.B_LoadNew.Location = new System.Drawing.Point(12, 45); + this.B_LoadNew.Name = "B_LoadNew"; + this.B_LoadNew.Size = new System.Drawing.Size(75, 23); + this.B_LoadNew.TabIndex = 1; + this.B_LoadNew.Text = "Load New"; + this.B_LoadNew.UseVisualStyleBackColor = true; + this.B_LoadNew.Click += new System.EventHandler(this.OpenSAV); + // + // B_LoadOld + // + this.B_LoadOld.Location = new System.Drawing.Point(12, 19); + this.B_LoadOld.Name = "B_LoadOld"; + this.B_LoadOld.Size = new System.Drawing.Size(75, 23); + this.B_LoadOld.TabIndex = 0; + this.B_LoadOld.Text = "Load Old"; + this.B_LoadOld.UseVisualStyleBackColor = true; + this.B_LoadOld.Click += new System.EventHandler(this.OpenSAV); + // + // L_EventFlagWarn + // + this.L_EventFlagWarn.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.L_EventFlagWarn.ForeColor = System.Drawing.Color.Red; + this.L_EventFlagWarn.Location = new System.Drawing.Point(9, 324); + this.L_EventFlagWarn.Name = "L_EventFlagWarn"; + this.L_EventFlagWarn.Size = new System.Drawing.Size(262, 31); + this.L_EventFlagWarn.TabIndex = 41; + this.L_EventFlagWarn.Text = "Altering Event Flags may impact other story events. Save file backups are recomme" + + "nded."; + this.L_EventFlagWarn.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // TC_Features + // + this.TC_Features.AllowDrop = true; + this.TC_Features.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.TC_Features.Controls.Add(this.GB_Flags); + this.TC_Features.Controls.Add(this.GB_System); + this.TC_Features.Controls.Add(this.GB_Work); + this.TC_Features.Controls.Add(this.GB_Research); + this.TC_Features.Location = new System.Drawing.Point(12, 12); + this.TC_Features.Name = "TC_Features"; + this.TC_Features.SelectedIndex = 0; + this.TC_Features.Size = new System.Drawing.Size(430, 309); + this.TC_Features.TabIndex = 42; + // + // GB_Flags + // + this.GB_Flags.Controls.Add(this.TLP_Flags); + this.GB_Flags.Location = new System.Drawing.Point(4, 22); + this.GB_Flags.Name = "GB_Flags"; + this.GB_Flags.Padding = new System.Windows.Forms.Padding(3); + this.GB_Flags.Size = new System.Drawing.Size(422, 283); + this.GB_Flags.TabIndex = 0; + this.GB_Flags.Text = "Event Flags"; + this.GB_Flags.UseVisualStyleBackColor = true; + // + // TLP_Flags + // + this.TLP_Flags.AutoScroll = true; + this.TLP_Flags.ColumnCount = 2; + this.TLP_Flags.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.TLP_Flags.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.TLP_Flags.Dock = System.Windows.Forms.DockStyle.Fill; + this.TLP_Flags.Location = new System.Drawing.Point(3, 3); + this.TLP_Flags.Name = "TLP_Flags"; + this.TLP_Flags.RowCount = 2; + this.TLP_Flags.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.TLP_Flags.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.TLP_Flags.Size = new System.Drawing.Size(416, 277); + this.TLP_Flags.TabIndex = 1; + // + // GB_System + // + this.GB_System.Controls.Add(this.TLP_System); + this.GB_System.Location = new System.Drawing.Point(4, 22); + this.GB_System.Name = "GB_System"; + this.GB_System.Padding = new System.Windows.Forms.Padding(3); + this.GB_System.Size = new System.Drawing.Size(422, 283); + this.GB_System.TabIndex = 3; + this.GB_System.Text = "System Flags"; + this.GB_System.UseVisualStyleBackColor = true; + // + // TLP_System + // + this.TLP_System.AutoScroll = true; + this.TLP_System.ColumnCount = 2; + this.TLP_System.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.TLP_System.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.TLP_System.Dock = System.Windows.Forms.DockStyle.Fill; + this.TLP_System.Location = new System.Drawing.Point(3, 3); + this.TLP_System.Name = "TLP_System"; + this.TLP_System.RowCount = 2; + this.TLP_System.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.TLP_System.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.TLP_System.Size = new System.Drawing.Size(416, 277); + this.TLP_System.TabIndex = 1; + // + // GB_Work + // + this.GB_Work.Controls.Add(this.TLP_Work); + this.GB_Work.Location = new System.Drawing.Point(4, 22); + this.GB_Work.Name = "GB_Work"; + this.GB_Work.Padding = new System.Windows.Forms.Padding(3); + this.GB_Work.Size = new System.Drawing.Size(422, 283); + this.GB_Work.TabIndex = 1; + this.GB_Work.Text = "Work Values"; + this.GB_Work.UseVisualStyleBackColor = true; + // + // GB_Research + // + this.GB_Research.Controls.Add(this.GB_FlagStatus); + this.GB_Research.Controls.Add(this.GB_Researcher); + this.GB_Research.Location = new System.Drawing.Point(4, 22); + this.GB_Research.Name = "GB_Research"; + this.GB_Research.Padding = new System.Windows.Forms.Padding(3); + this.GB_Research.Size = new System.Drawing.Size(422, 283); + this.GB_Research.TabIndex = 2; + this.GB_Research.Text = "Research"; + this.GB_Research.UseVisualStyleBackColor = true; + // + // TLP_Work + // + this.TLP_Work.AutoScroll = true; + this.TLP_Work.ColumnCount = 3; + this.TLP_Work.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.TLP_Work.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); + this.TLP_Work.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 416F)); + this.TLP_Work.Dock = System.Windows.Forms.DockStyle.Fill; + this.TLP_Work.Location = new System.Drawing.Point(3, 3); + this.TLP_Work.Name = "TLP_Work"; + this.TLP_Work.RowCount = 1; + this.TLP_Work.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.TLP_Work.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.TLP_Work.Size = new System.Drawing.Size(416, 277); + this.TLP_Work.TabIndex = 2; + // + // SAV_FlagWork8b + // + this.AllowDrop = true; + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(454, 361); + this.Controls.Add(this.TC_Features); + this.Controls.Add(this.L_EventFlagWarn); + this.Controls.Add(this.B_Save); + this.Controls.Add(this.B_Cancel); + this.Icon = global::PKHeX.WinForms.Properties.Resources.Icon; + this.MaximizeBox = false; + this.MaximumSize = new System.Drawing.Size(670, 800); + this.MinimizeBox = false; + this.MinimumSize = new System.Drawing.Size(470, 400); + this.Name = "SAV_FlagWork8b"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Event Flag Editor"; + this.GB_FlagStatus.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.NUD_System)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.NUD_Work)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.NUD_Flag)).EndInit(); + this.GB_Researcher.ResumeLayout(false); + this.GB_Researcher.PerformLayout(); + this.TC_Features.ResumeLayout(false); + this.GB_Flags.ResumeLayout(false); + this.GB_System.ResumeLayout(false); + this.GB_Work.ResumeLayout(false); + this.GB_Research.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.Button B_Cancel; + private System.Windows.Forms.GroupBox GB_FlagStatus; + private System.Windows.Forms.NumericUpDown NUD_Flag; + private System.Windows.Forms.Button B_Save; + private System.Windows.Forms.GroupBox GB_Researcher; + private System.Windows.Forms.TextBox TB_NewSAV; + private System.Windows.Forms.TextBox TB_OldSAV; + private System.Windows.Forms.Button B_LoadNew; + private System.Windows.Forms.Button B_LoadOld; + private System.Windows.Forms.Label L_CustomWork; + private System.Windows.Forms.ComboBox CB_CustomWork; + private System.Windows.Forms.Label L_EventFlagWarn; + private System.Windows.Forms.TabControl TC_Features; + private System.Windows.Forms.TabPage GB_Flags; + private System.Windows.Forms.TabPage GB_Work; + private System.Windows.Forms.TabPage GB_Research; + private System.Windows.Forms.NumericUpDown NUD_Work; + private System.Windows.Forms.Button B_ApplyFlag; + private System.Windows.Forms.Button B_ApplyWork; + private System.Windows.Forms.RichTextBox RTB_Diff; + private System.Windows.Forms.TabPage GB_System; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.NumericUpDown NUD_System; + private System.Windows.Forms.CheckBox CHK_CustomSystem; + private System.Windows.Forms.CheckBox CHK_CustomFlag; + private System.Windows.Forms.TableLayoutPanel TLP_Flags; + private System.Windows.Forms.TableLayoutPanel TLP_System; + private System.Windows.Forms.TableLayoutPanel TLP_Work; + } +} \ No newline at end of file diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_FlagWork8b.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_FlagWork8b.cs new file mode 100644 index 00000000000..bc401ad0bad --- /dev/null +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_FlagWork8b.cs @@ -0,0 +1,326 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Windows.Forms; +using PKHeX.Core; +using static PKHeX.Core.GameVersion; + +namespace PKHeX.WinForms +{ + public sealed partial class SAV_FlagWork8b : Form + { + private readonly SAV8BS Origin; + private readonly SAV8BS SAV; + + private bool editing; + private readonly Dictionary WorkDict = new(); + private readonly Dictionary FlagDict = new(); + private readonly Dictionary SystemDict = new(); + + public SAV_FlagWork8b(SAV8BS sav) + { + InitializeComponent(); + + WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage); + + SAV = (SAV8BS)sav.Clone(); + Origin = sav; + + DragEnter += Main_DragEnter; + DragDrop += Main_DragDrop; + + CB_CustomWork.Items.Clear(); + for (int i = 0; i < SAV.Work.CountWork; i++) + CB_CustomWork.Items.Add(i.ToString()); + + SuspendLayout(); + editing = true; + var obj = SAV.Work; + var game = GetGameFilePrefix(SAV.Version); + var editor = new EventLabelCollectionSystem(game, obj.CountFlag - 1, obj.CountSystem - 1, obj.CountWork - 1); + LoadFlags(editor); + LoadSystem(editor); + LoadWork(editor); + editing = false; + ResumeLayout(); + + if (CB_CustomWork.Items.Count > 0) + { + CB_CustomWork.SelectedIndex = 0; + } + else + { + L_CustomWork.Visible = CB_CustomWork.Visible = NUD_Work.Visible = false; + TC_Features.TabPages.Remove(GB_Work); + } + + NUD_Flag.Maximum = obj.CountFlag - 1; + NUD_Flag.Text = "0"; + CHK_CustomFlag.Checked = obj.GetFlag(0); + NUD_System.Maximum = obj.CountSystem - 1; + NUD_System.Text = "0"; + CHK_CustomSystem.Checked = obj.GetSystemFlag(0); + + Text = $"{Text} ({sav.Version})"; + } + + private void LoadFlags(EventLabelCollectionSystem editor) + { + TLP_Flags.SuspendLayout(); + TLP_Flags.Scroll += WinFormsUtil.PanelScroll; + TLP_Flags.Controls.Clear(); + var labels = editor.Flag; + + var hide = Main.Settings.Advanced.HideEventTypeBelow; + labels = labels.OrderByDescending(z => z.Type).ToList(); + for (int i = 0; i < labels.Count; i++) + { + var (name, index, type) = labels[i]; + if (type < hide) + break; + + var lbl = new Label { Text = name, Margin = Padding.Empty, AutoSize = true }; + var chk = new CheckBox + { + CheckAlign = ContentAlignment.MiddleLeft, + Margin = Padding.Empty, + Checked = SAV.Work.GetFlag(index), + AutoSize = true, + }; + lbl.Click += (_, __) => chk.Checked ^= true; + chk.CheckedChanged += (_, __) => + { + SAV.Work.SetFlag(index, chk.Checked); + if (NUD_Flag.Value == index) + CHK_CustomFlag.Checked = chk.Checked; + }; + TLP_Flags.Controls.Add(chk, 0, i); + TLP_Flags.Controls.Add(lbl, 1, i); + + FlagDict.Add(index, chk); + } + + TLP_Flags.ResumeLayout(); + } + + private void LoadSystem(EventLabelCollectionSystem editor) + { + TLP_System.SuspendLayout(); + TLP_System.Scroll += WinFormsUtil.PanelScroll; + TLP_System.Controls.Clear(); + var labels = editor.System; + + var hide = Main.Settings.Advanced.HideEventTypeBelow; + labels = labels.OrderByDescending(z => z.Type).ToList(); + for (int i = 0; i < labels.Count; i++) + { + var (name, index, type) = labels[i]; + if (type < hide) + break; + + var lbl = new Label { Text = name, Margin = Padding.Empty, AutoSize = true }; + var chk = new CheckBox + { + CheckAlign = ContentAlignment.MiddleLeft, + Margin = Padding.Empty, + Checked = SAV.Work.GetSystemFlag(index), + AutoSize = true, + }; + lbl.Click += (_, __) => chk.Checked ^= true; + chk.CheckedChanged += (_, __) => + { + SAV.Work.SetSystemFlag(index, chk.Checked); + if (NUD_System.Value == index) + CHK_CustomSystem.Checked = chk.Checked; + }; + TLP_System.Controls.Add(chk, 0, i); + TLP_System.Controls.Add(lbl, 1, i); + + SystemDict.Add(index, chk); + } + + TLP_System.ResumeLayout(); + } + + private void LoadWork(EventLabelCollectionSystem editor) + { + TLP_Work.SuspendLayout(); + TLP_Work.Scroll += WinFormsUtil.PanelScroll; + TLP_Work.Controls.Clear(); + var labels = editor.Work; + var hide = Main.Settings.Advanced.HideEventTypeBelow; + labels = labels.OrderByDescending(z => z.Type).ToList(); + for (var i = 0; i < labels.Count; i++) + { + var entry = labels[i]; + if (entry.Type < hide) + break; + var lbl = new Label { Text = entry.Name, Margin = Padding.Empty, AutoSize = true }; + var mtb = new NumericUpDown + { + Maximum = ushort.MaxValue, + Minimum = ushort.MinValue, + Margin = Padding.Empty, + Width = 50, + }; + + var map = entry.PredefinedValues.Select(z => new ComboItem(z.Name, z.Value)).ToList(); + var cb = new ComboBox + { + Margin = Padding.Empty, + Width = 150, + DropDownStyle = ComboBoxStyle.DropDownList, + BindingContext = BindingContext, + DropDownWidth = Width + 100, + }; + cb.InitializeBinding(); + cb.DataSource = map; + + lbl.Click += (_, __) => mtb.Value = 0; + bool updating = false; + mtb.ValueChanged += ChangeConstValue; + void ChangeConstValue(object? sender, EventArgs e) + { + if (updating) + return; + + updating = true; + var value = (ushort)mtb.Value; + var (_, valueID) = map.Find(z => z.Value == value) ?? map[0]; + if (WinFormsUtil.GetIndex(cb) != valueID) + cb.SelectedValue = valueID; + + SAV.Work.SetWork(entry.Index, value); + if (CB_CustomWork.SelectedIndex == entry.Index) + mtb.Text = ((int)mtb.Value).ToString(); + updating = false; + } + cb.SelectedValueChanged += (o, args) => + { + if (editing || updating) + return; + var value = WinFormsUtil.GetIndex(cb); + mtb.Value = value == NamedEventConst.CustomMagicValue ? 0 : value; + }; + + mtb.Value = SAV.Work.GetWork(entry.Index); + if (mtb.Value == 0) + ChangeConstValue(this, EventArgs.Empty); + + TLP_Work.Controls.Add(lbl, 0, i); + TLP_Work.Controls.Add(cb, 1, i); + TLP_Work.Controls.Add(mtb, 2, i); + + WorkDict.Add(entry.Index, mtb); + } + + TLP_Work.ResumeLayout(); + } + + private void B_Cancel_Click(object sender, EventArgs e) + { + Close(); + } + + private void B_Save_Click(object sender, EventArgs e) + { + Origin.CopyChangesFrom(SAV); + Close(); + } + + private void ChangeCustomFlag(object sender, EventArgs e) => CHK_CustomFlag.Checked = SAV.Work.GetFlag((int)NUD_Flag.Value); + private void ChangeCustomSystem(object sender, EventArgs e) => CHK_CustomSystem.Checked = SAV.Work.GetSystemFlag((int)NUD_System.Value); + private void ChangeConstantIndex(object sender, EventArgs e) => NUD_Work.Value = SAV.Work.GetWork(CB_CustomWork.SelectedIndex); + + private void ChangeSAV() + { + if (TB_NewSAV.Text.Length > 0 && TB_OldSAV.Text.Length > 0) + DiffSaves(); + } + + private void OpenSAV(object sender, EventArgs e) + { + using var ofd = new OpenFileDialog(); + if (ofd.ShowDialog() == DialogResult.OK) + LoadSAV(sender, ofd.FileName); + } + + private void LoadSAV(object sender, string path) + { + if (sender == B_LoadOld) + TB_OldSAV.Text = path; + else + TB_NewSAV.Text = path; + ChangeSAV(); + } + + private static string GetGameFilePrefix(GameVersion game) => game switch + { + BD or SP or BDSP => "bdsp", + _ => throw new IndexOutOfRangeException(nameof(game)), + }; + + private void DiffSaves() + { + var diff = new EventWorkDiff8b(TB_OldSAV.Text, TB_NewSAV.Text); + if (diff.Message.Length != 0) + { + WinFormsUtil.Alert(diff.Message); + return; + } + + RTB_Diff.Lines = diff.Summarize().ToArray(); + } + + private static void Main_DragEnter(object sender, DragEventArgs e) + { + if (e.Data.GetDataPresent(DataFormats.FileDrop)) + e.Effect = DragDropEffects.Copy; + } + + private void Main_DragDrop(object sender, DragEventArgs e) + { + string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); + var dr = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, Name, "Yes: Old Save" + Environment.NewLine + "No: New Save"); + var button = dr == DialogResult.Yes ? B_LoadOld : B_LoadNew; + LoadSAV(button, files[0]); + } + + private void B_ApplyFlag_Click(object sender, EventArgs e) + { + var index = (int)NUD_Flag.Value; + SAV.Work.SetFlag(index, CHK_CustomFlag.Checked); + Origin.State.Edited = true; + + editing = true; + if (FlagDict.TryGetValue(index, out var chk)) + chk.Checked = CHK_CustomFlag.Checked; + editing = false; + } + + private void B_ApplySystemFlag_Click(object sender, EventArgs e) + { + var index = (int)NUD_System.Value; + SAV.Work.SetSystemFlag(index, CHK_CustomFlag.Checked); + Origin.State.Edited = true; + + editing = true; + if (SystemDict.TryGetValue(index, out var chk)) + chk.Checked = CHK_CustomSystem.Checked; + editing = false; + } + + private void B_ApplyWork_Click(object sender, EventArgs e) + { + var index = CB_CustomWork.SelectedIndex; + SAV.Work.SetWork(index, (int)NUD_Work.Value); + Origin.State.Edited = true; + + editing = true; + if (WorkDict.TryGetValue(index, out var nud)) + nud.Value = NUD_Work.Value; + editing = false; + } + } +} diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_PokedexBDSP.Designer.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_PokedexBDSP.Designer.cs new file mode 100644 index 00000000000..5f3016912d4 --- /dev/null +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_PokedexBDSP.Designer.cs @@ -0,0 +1,547 @@ +namespace PKHeX.WinForms +{ + partial class SAV_PokedexBDSP + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.B_Cancel = new System.Windows.Forms.Button(); + this.LB_Species = new System.Windows.Forms.ListBox(); + this.CHK_LangKOR = new System.Windows.Forms.CheckBox(); + this.CHK_LangSPA = new System.Windows.Forms.CheckBox(); + this.CHK_LangGER = new System.Windows.Forms.CheckBox(); + this.CHK_LangITA = new System.Windows.Forms.CheckBox(); + this.CHK_LangFRE = new System.Windows.Forms.CheckBox(); + this.CHK_LangENG = new System.Windows.Forms.CheckBox(); + this.CHK_LangJPN = new System.Windows.Forms.CheckBox(); + this.L_goto = new System.Windows.Forms.Label(); + this.CB_Species = new System.Windows.Forms.ComboBox(); + this.B_GiveAll = new System.Windows.Forms.Button(); + this.B_Save = new System.Windows.Forms.Button(); + this.B_Modify = new System.Windows.Forms.Button(); + this.GB_Language = new System.Windows.Forms.GroupBox(); + this.CHK_LangCHT = new System.Windows.Forms.CheckBox(); + this.CHK_LangCHS = new System.Windows.Forms.CheckBox(); + this.GB_Encountered = new System.Windows.Forms.GroupBox(); + this.CHK_FS = new System.Windows.Forms.CheckBox(); + this.CHK_MS = new System.Windows.Forms.CheckBox(); + this.CHK_F = new System.Windows.Forms.CheckBox(); + this.CHK_M = new System.Windows.Forms.CheckBox(); + this.modifyMenu = new System.Windows.Forms.ContextMenuStrip(this.components); + this.mnuSeenNone = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuSeenAll = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuCaughtNone = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuCaughtAll = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuComplete = new System.Windows.Forms.ToolStripMenuItem(); + this.CLB_FormRegular = new System.Windows.Forms.CheckedListBox(); + this.L_FormsSeen = new System.Windows.Forms.Label(); + this.CLB_FormShiny = new System.Windows.Forms.CheckedListBox(); + this.L_FormDisplayed = new System.Windows.Forms.Label(); + this.modifyMenuForms = new System.Windows.Forms.ContextMenuStrip(this.components); + this.mnuFormNone = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuFormAllRegular = new System.Windows.Forms.ToolStripMenuItem(); + this.mnuFormAllShinies = new System.Windows.Forms.ToolStripMenuItem(); + this.CB_State = new System.Windows.Forms.ComboBox(); + this.B_ModifyForms = new System.Windows.Forms.Button(); + this.CHK_National = new System.Windows.Forms.CheckBox(); + this.GB_Language.SuspendLayout(); + this.GB_Encountered.SuspendLayout(); + this.modifyMenu.SuspendLayout(); + this.modifyMenuForms.SuspendLayout(); + this.SuspendLayout(); + // + // B_Cancel + // + this.B_Cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.B_Cancel.Location = new System.Drawing.Point(351, 297); + this.B_Cancel.Name = "B_Cancel"; + this.B_Cancel.Size = new System.Drawing.Size(80, 23); + this.B_Cancel.TabIndex = 0; + this.B_Cancel.Text = "Cancel"; + this.B_Cancel.UseVisualStyleBackColor = true; + this.B_Cancel.Click += new System.EventHandler(this.B_Cancel_Click); + // + // LB_Species + // + this.LB_Species.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.LB_Species.FormattingEnabled = true; + this.LB_Species.Location = new System.Drawing.Point(12, 40); + this.LB_Species.Name = "LB_Species"; + this.LB_Species.Size = new System.Drawing.Size(130, 277); + this.LB_Species.TabIndex = 2; + this.LB_Species.SelectedIndexChanged += new System.EventHandler(this.ChangeLBSpecies); + // + // CHK_LangKOR + // + this.CHK_LangKOR.AutoSize = true; + this.CHK_LangKOR.Location = new System.Drawing.Point(6, 98); + this.CHK_LangKOR.Name = "CHK_LangKOR"; + this.CHK_LangKOR.Size = new System.Drawing.Size(60, 17); + this.CHK_LangKOR.TabIndex = 19; + this.CHK_LangKOR.Text = "Korean"; + this.CHK_LangKOR.UseVisualStyleBackColor = true; + // + // CHK_LangSPA + // + this.CHK_LangSPA.AutoSize = true; + this.CHK_LangSPA.Location = new System.Drawing.Point(6, 84); + this.CHK_LangSPA.Name = "CHK_LangSPA"; + this.CHK_LangSPA.Size = new System.Drawing.Size(64, 17); + this.CHK_LangSPA.TabIndex = 18; + this.CHK_LangSPA.Text = "Spanish"; + this.CHK_LangSPA.UseVisualStyleBackColor = true; + // + // CHK_LangGER + // + this.CHK_LangGER.AutoSize = true; + this.CHK_LangGER.Location = new System.Drawing.Point(6, 70); + this.CHK_LangGER.Name = "CHK_LangGER"; + this.CHK_LangGER.Size = new System.Drawing.Size(63, 17); + this.CHK_LangGER.TabIndex = 17; + this.CHK_LangGER.Text = "German"; + this.CHK_LangGER.UseVisualStyleBackColor = true; + // + // CHK_LangITA + // + this.CHK_LangITA.AutoSize = true; + this.CHK_LangITA.Location = new System.Drawing.Point(6, 56); + this.CHK_LangITA.Name = "CHK_LangITA"; + this.CHK_LangITA.Size = new System.Drawing.Size(54, 17); + this.CHK_LangITA.TabIndex = 16; + this.CHK_LangITA.Text = "Italian"; + this.CHK_LangITA.UseVisualStyleBackColor = true; + // + // CHK_LangFRE + // + this.CHK_LangFRE.AutoSize = true; + this.CHK_LangFRE.Location = new System.Drawing.Point(6, 42); + this.CHK_LangFRE.Name = "CHK_LangFRE"; + this.CHK_LangFRE.Size = new System.Drawing.Size(59, 17); + this.CHK_LangFRE.TabIndex = 15; + this.CHK_LangFRE.Text = "French"; + this.CHK_LangFRE.UseVisualStyleBackColor = true; + // + // CHK_LangENG + // + this.CHK_LangENG.AutoSize = true; + this.CHK_LangENG.Location = new System.Drawing.Point(6, 28); + this.CHK_LangENG.Name = "CHK_LangENG"; + this.CHK_LangENG.Size = new System.Drawing.Size(60, 17); + this.CHK_LangENG.TabIndex = 14; + this.CHK_LangENG.Text = "English"; + this.CHK_LangENG.UseVisualStyleBackColor = true; + // + // CHK_LangJPN + // + this.CHK_LangJPN.AutoSize = true; + this.CHK_LangJPN.Location = new System.Drawing.Point(6, 14); + this.CHK_LangJPN.Name = "CHK_LangJPN"; + this.CHK_LangJPN.Size = new System.Drawing.Size(72, 17); + this.CHK_LangJPN.TabIndex = 13; + this.CHK_LangJPN.Text = "Japanese"; + this.CHK_LangJPN.UseVisualStyleBackColor = true; + // + // L_goto + // + this.L_goto.AutoSize = true; + this.L_goto.Location = new System.Drawing.Point(12, 16); + this.L_goto.Name = "L_goto"; + this.L_goto.Size = new System.Drawing.Size(31, 13); + this.L_goto.TabIndex = 20; + this.L_goto.Text = "goto:"; + // + // CB_Species + // + this.CB_Species.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Suggest; + this.CB_Species.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; + this.CB_Species.DropDownWidth = 95; + this.CB_Species.FormattingEnabled = true; + this.CB_Species.Items.AddRange(new object[] { + "0"}); + this.CB_Species.Location = new System.Drawing.Point(50, 13); + this.CB_Species.Name = "CB_Species"; + this.CB_Species.Size = new System.Drawing.Size(92, 21); + this.CB_Species.TabIndex = 21; + this.CB_Species.SelectedIndexChanged += new System.EventHandler(this.ChangeCBSpecies); + this.CB_Species.SelectedValueChanged += new System.EventHandler(this.ChangeCBSpecies); + // + // B_GiveAll + // + this.B_GiveAll.Location = new System.Drawing.Point(149, 11); + this.B_GiveAll.Name = "B_GiveAll"; + this.B_GiveAll.Size = new System.Drawing.Size(60, 23); + this.B_GiveAll.TabIndex = 23; + this.B_GiveAll.Text = "Check All"; + this.B_GiveAll.UseVisualStyleBackColor = true; + this.B_GiveAll.Click += new System.EventHandler(this.B_GiveAll_Click); + // + // B_Save + // + this.B_Save.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.B_Save.Location = new System.Drawing.Point(437, 297); + this.B_Save.Name = "B_Save"; + this.B_Save.Size = new System.Drawing.Size(80, 23); + this.B_Save.TabIndex = 24; + this.B_Save.Text = "Save"; + this.B_Save.UseVisualStyleBackColor = true; + this.B_Save.Click += new System.EventHandler(this.B_Save_Click); + // + // B_Modify + // + this.B_Modify.Location = new System.Drawing.Point(233, 11); + this.B_Modify.Name = "B_Modify"; + this.B_Modify.Size = new System.Drawing.Size(60, 23); + this.B_Modify.TabIndex = 25; + this.B_Modify.Text = "Modify..."; + this.B_Modify.UseVisualStyleBackColor = true; + this.B_Modify.Click += new System.EventHandler(this.B_Modify_Click); + // + // GB_Language + // + this.GB_Language.Controls.Add(this.CHK_LangCHT); + this.GB_Language.Controls.Add(this.CHK_LangCHS); + this.GB_Language.Controls.Add(this.CHK_LangKOR); + this.GB_Language.Controls.Add(this.CHK_LangSPA); + this.GB_Language.Controls.Add(this.CHK_LangGER); + this.GB_Language.Controls.Add(this.CHK_LangITA); + this.GB_Language.Controls.Add(this.CHK_LangFRE); + this.GB_Language.Controls.Add(this.CHK_LangENG); + this.GB_Language.Controls.Add(this.CHK_LangJPN); + this.GB_Language.Location = new System.Drawing.Point(149, 146); + this.GB_Language.Name = "GB_Language"; + this.GB_Language.Size = new System.Drawing.Size(115, 145); + this.GB_Language.TabIndex = 26; + this.GB_Language.TabStop = false; + this.GB_Language.Text = "Languages"; + // + // CHK_LangCHT + // + this.CHK_LangCHT.AutoSize = true; + this.CHK_LangCHT.Location = new System.Drawing.Point(6, 126); + this.CHK_LangCHT.Name = "CHK_LangCHT"; + this.CHK_LangCHT.Size = new System.Drawing.Size(71, 17); + this.CHK_LangCHT.TabIndex = 21; + this.CHK_LangCHT.Text = "ChineseT"; + this.CHK_LangCHT.UseVisualStyleBackColor = true; + // + // CHK_LangCHS + // + this.CHK_LangCHS.AutoSize = true; + this.CHK_LangCHS.Location = new System.Drawing.Point(6, 112); + this.CHK_LangCHS.Name = "CHK_LangCHS"; + this.CHK_LangCHS.Size = new System.Drawing.Size(71, 17); + this.CHK_LangCHS.TabIndex = 20; + this.CHK_LangCHS.Text = "ChineseS"; + this.CHK_LangCHS.UseVisualStyleBackColor = true; + // + // GB_Encountered + // + this.GB_Encountered.Controls.Add(this.CHK_FS); + this.GB_Encountered.Controls.Add(this.CHK_MS); + this.GB_Encountered.Controls.Add(this.CHK_F); + this.GB_Encountered.Controls.Add(this.CHK_M); + this.GB_Encountered.Location = new System.Drawing.Point(149, 69); + this.GB_Encountered.Name = "GB_Encountered"; + this.GB_Encountered.Size = new System.Drawing.Size(115, 72); + this.GB_Encountered.TabIndex = 31; + this.GB_Encountered.TabStop = false; + this.GB_Encountered.Text = "Seen"; + // + // CHK_FS + // + this.CHK_FS.AutoSize = true; + this.CHK_FS.Location = new System.Drawing.Point(6, 55); + this.CHK_FS.Name = "CHK_FS"; + this.CHK_FS.Size = new System.Drawing.Size(89, 17); + this.CHK_FS.TabIndex = 7; + this.CHK_FS.Text = "Shiny Female"; + this.CHK_FS.UseVisualStyleBackColor = true; + // + // CHK_MS + // + this.CHK_MS.AutoSize = true; + this.CHK_MS.Location = new System.Drawing.Point(6, 41); + this.CHK_MS.Name = "CHK_MS"; + this.CHK_MS.Size = new System.Drawing.Size(78, 17); + this.CHK_MS.TabIndex = 6; + this.CHK_MS.Text = "Shiny Male"; + this.CHK_MS.UseVisualStyleBackColor = true; + // + // CHK_F + // + this.CHK_F.AutoSize = true; + this.CHK_F.Location = new System.Drawing.Point(6, 27); + this.CHK_F.Name = "CHK_F"; + this.CHK_F.Size = new System.Drawing.Size(60, 17); + this.CHK_F.TabIndex = 5; + this.CHK_F.Text = "Female"; + this.CHK_F.UseVisualStyleBackColor = true; + // + // CHK_M + // + this.CHK_M.AutoSize = true; + this.CHK_M.Location = new System.Drawing.Point(6, 13); + this.CHK_M.Name = "CHK_M"; + this.CHK_M.Size = new System.Drawing.Size(49, 17); + this.CHK_M.TabIndex = 4; + this.CHK_M.Text = "Male"; + this.CHK_M.UseVisualStyleBackColor = true; + // + // modifyMenu + // + this.modifyMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.mnuSeenNone, + this.mnuSeenAll, + this.mnuCaughtNone, + this.mnuCaughtAll, + this.mnuComplete}); + this.modifyMenu.Name = "modifyMenu"; + this.modifyMenu.Size = new System.Drawing.Size(150, 114); + // + // mnuSeenNone + // + this.mnuSeenNone.Name = "mnuSeenNone"; + this.mnuSeenNone.Size = new System.Drawing.Size(149, 22); + this.mnuSeenNone.Text = "Seen none"; + this.mnuSeenNone.Click += new System.EventHandler(this.ModifyAll); + // + // mnuSeenAll + // + this.mnuSeenAll.Name = "mnuSeenAll"; + this.mnuSeenAll.Size = new System.Drawing.Size(149, 22); + this.mnuSeenAll.Text = "Seen all"; + this.mnuSeenAll.Click += new System.EventHandler(this.ModifyAll); + // + // mnuCaughtNone + // + this.mnuCaughtNone.Name = "mnuCaughtNone"; + this.mnuCaughtNone.Size = new System.Drawing.Size(149, 22); + this.mnuCaughtNone.Text = "Caught none"; + this.mnuCaughtNone.Click += new System.EventHandler(this.ModifyAll); + // + // mnuCaughtAll + // + this.mnuCaughtAll.Name = "mnuCaughtAll"; + this.mnuCaughtAll.Size = new System.Drawing.Size(149, 22); + this.mnuCaughtAll.Text = "Caught all"; + this.mnuCaughtAll.Click += new System.EventHandler(this.ModifyAll); + // + // mnuComplete + // + this.mnuComplete.Name = "mnuComplete"; + this.mnuComplete.Size = new System.Drawing.Size(149, 22); + this.mnuComplete.Text = "Complete Dex"; + this.mnuComplete.Click += new System.EventHandler(this.ModifyAll); + // + // CLB_FormRegular + // + this.CLB_FormRegular.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.CLB_FormRegular.FormattingEnabled = true; + this.CLB_FormRegular.Location = new System.Drawing.Point(270, 64); + this.CLB_FormRegular.Name = "CLB_FormRegular"; + this.CLB_FormRegular.Size = new System.Drawing.Size(119, 229); + this.CLB_FormRegular.TabIndex = 34; + // + // L_FormsSeen + // + this.L_FormsSeen.Location = new System.Drawing.Point(267, 43); + this.L_FormsSeen.Name = "L_FormsSeen"; + this.L_FormsSeen.Size = new System.Drawing.Size(104, 20); + this.L_FormsSeen.TabIndex = 35; + this.L_FormsSeen.Text = "Forms:"; + this.L_FormsSeen.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // CLB_FormShiny + // + this.CLB_FormShiny.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.CLB_FormShiny.FormattingEnabled = true; + this.CLB_FormShiny.Location = new System.Drawing.Point(395, 64); + this.CLB_FormShiny.Name = "CLB_FormShiny"; + this.CLB_FormShiny.Size = new System.Drawing.Size(119, 229); + this.CLB_FormShiny.TabIndex = 36; + // + // L_FormDisplayed + // + this.L_FormDisplayed.Location = new System.Drawing.Point(392, 43); + this.L_FormDisplayed.Name = "L_FormDisplayed"; + this.L_FormDisplayed.Size = new System.Drawing.Size(104, 20); + this.L_FormDisplayed.TabIndex = 37; + this.L_FormDisplayed.Text = "Shiny Forms:"; + this.L_FormDisplayed.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; + // + // modifyMenuForms + // + this.modifyMenuForms.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.mnuFormNone, + this.mnuFormAllRegular, + this.mnuFormAllShinies}); + this.modifyMenuForms.Name = "modifyMenu"; + this.modifyMenuForms.Size = new System.Drawing.Size(154, 70); + // + // mnuFormNone + // + this.mnuFormNone.Name = "mnuFormNone"; + this.mnuFormNone.Size = new System.Drawing.Size(153, 22); + this.mnuFormNone.Text = "Seen none"; + this.mnuFormNone.Click += new System.EventHandler(this.ModifyAllForms); + // + // mnuFormAllRegular + // + this.mnuFormAllRegular.Name = "mnuFormAllRegular"; + this.mnuFormAllRegular.Size = new System.Drawing.Size(153, 22); + this.mnuFormAllRegular.Text = "Seen all"; + this.mnuFormAllRegular.Click += new System.EventHandler(this.ModifyAllForms); + // + // mnuFormAllShinies + // + this.mnuFormAllShinies.Name = "mnuFormAllShinies"; + this.mnuFormAllShinies.Size = new System.Drawing.Size(153, 22); + this.mnuFormAllShinies.Text = "Seen all shinies"; + this.mnuFormAllShinies.Click += new System.EventHandler(this.ModifyAllForms); + // + // CB_State + // + this.CB_State.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Suggest; + this.CB_State.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; + this.CB_State.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.CB_State.DropDownWidth = 95; + this.CB_State.FormattingEnabled = true; + this.CB_State.Items.AddRange(new object[] { + "None", + "Heard Of", + "Seen", + "Captured"}); + this.CB_State.Location = new System.Drawing.Point(148, 46); + this.CB_State.Name = "CB_State"; + this.CB_State.Size = new System.Drawing.Size(116, 21); + this.CB_State.TabIndex = 39; + // + // B_ModifyForms + // + this.B_ModifyForms.Location = new System.Drawing.Point(454, 11); + this.B_ModifyForms.Name = "B_ModifyForms"; + this.B_ModifyForms.Size = new System.Drawing.Size(60, 23); + this.B_ModifyForms.TabIndex = 40; + this.B_ModifyForms.Text = "Modify..."; + this.B_ModifyForms.UseVisualStyleBackColor = true; + this.B_ModifyForms.Click += new System.EventHandler(this.B_ModifyForms_Click); + // + // CHK_National + // + this.CHK_National.AutoSize = true; + this.CHK_National.Location = new System.Drawing.Point(155, 303); + this.CHK_National.Name = "CHK_National"; + this.CHK_National.Size = new System.Drawing.Size(112, 17); + this.CHK_National.TabIndex = 42; + this.CHK_National.Text = "National PokéDex"; + this.CHK_National.UseVisualStyleBackColor = true; + // + // SAV_PokedexBDSP + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(524, 327); + this.Controls.Add(this.CHK_National); + this.Controls.Add(this.B_ModifyForms); + this.Controls.Add(this.CB_State); + this.Controls.Add(this.L_FormDisplayed); + this.Controls.Add(this.CLB_FormShiny); + this.Controls.Add(this.L_FormsSeen); + this.Controls.Add(this.CLB_FormRegular); + this.Controls.Add(this.GB_Encountered); + this.Controls.Add(this.GB_Language); + this.Controls.Add(this.B_Modify); + this.Controls.Add(this.B_Save); + this.Controls.Add(this.B_GiveAll); + this.Controls.Add(this.CB_Species); + this.Controls.Add(this.L_goto); + this.Controls.Add(this.LB_Species); + this.Controls.Add(this.B_Cancel); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Icon = global::PKHeX.WinForms.Properties.Resources.Icon; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "SAV_PokedexBDSP"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "Pokédex Editor"; + this.GB_Language.ResumeLayout(false); + this.GB_Language.PerformLayout(); + this.GB_Encountered.ResumeLayout(false); + this.GB_Encountered.PerformLayout(); + this.modifyMenu.ResumeLayout(false); + this.modifyMenuForms.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button B_Cancel; + private System.Windows.Forms.ListBox LB_Species; + private System.Windows.Forms.CheckBox CHK_LangKOR; + private System.Windows.Forms.CheckBox CHK_LangSPA; + private System.Windows.Forms.CheckBox CHK_LangGER; + private System.Windows.Forms.CheckBox CHK_LangITA; + private System.Windows.Forms.CheckBox CHK_LangFRE; + private System.Windows.Forms.CheckBox CHK_LangENG; + private System.Windows.Forms.CheckBox CHK_LangJPN; + private System.Windows.Forms.Label L_goto; + private System.Windows.Forms.ComboBox CB_Species; + private System.Windows.Forms.Button B_GiveAll; + private System.Windows.Forms.Button B_Save; + private System.Windows.Forms.Button B_Modify; + private System.Windows.Forms.GroupBox GB_Language; + private System.Windows.Forms.GroupBox GB_Encountered; + private System.Windows.Forms.CheckBox CHK_FS; + private System.Windows.Forms.CheckBox CHK_MS; + private System.Windows.Forms.CheckBox CHK_F; + private System.Windows.Forms.CheckBox CHK_M; + private System.Windows.Forms.ContextMenuStrip modifyMenu; + private System.Windows.Forms.ToolStripMenuItem mnuSeenNone; + private System.Windows.Forms.ToolStripMenuItem mnuSeenAll; + private System.Windows.Forms.ToolStripMenuItem mnuCaughtNone; + private System.Windows.Forms.ToolStripMenuItem mnuCaughtAll; + private System.Windows.Forms.ToolStripMenuItem mnuComplete; + private System.Windows.Forms.Label L_FormsSeen; + private System.Windows.Forms.CheckedListBox CLB_FormRegular; + private System.Windows.Forms.CheckedListBox CLB_FormShiny; + private System.Windows.Forms.Label L_FormDisplayed; + private System.Windows.Forms.ContextMenuStrip modifyMenuForms; + private System.Windows.Forms.ToolStripMenuItem mnuFormNone; + private System.Windows.Forms.ToolStripMenuItem mnuFormAllShinies; + private System.Windows.Forms.ToolStripMenuItem mnuFormAllRegular; + private System.Windows.Forms.CheckBox CHK_LangCHT; + private System.Windows.Forms.CheckBox CHK_LangCHS; + private System.Windows.Forms.ComboBox CB_State; + private System.Windows.Forms.Button B_ModifyForms; + private System.Windows.Forms.CheckBox CHK_National; + } +} diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_PokedexBDSP.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_PokedexBDSP.cs new file mode 100644 index 00000000000..0bc08f57084 --- /dev/null +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen8/SAV_PokedexBDSP.cs @@ -0,0 +1,214 @@ +using System; +using System.Drawing; +using System.Linq; +using System.Windows.Forms; +using PKHeX.Core; + +namespace PKHeX.WinForms +{ + public partial class SAV_PokedexBDSP : Form + { + private readonly SaveFile Origin; + private readonly SAV8BS SAV; + private readonly Zukan8b Zukan; + + public SAV_PokedexBDSP(SaveFile sav) + { + InitializeComponent(); + WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage); + SAV = (SAV8BS)(Origin = sav).Clone(); + Zukan = SAV.Zukan; + + editing = true; + // Clear Listbox and ComboBox + LB_Species.Items.Clear(); + CB_Species.Items.Clear(); + + // Fill List + CB_Species.InitializeBinding(); + CB_Species.DataSource = new BindingSource(GameInfo.FilteredSources.Species.Skip(1).ToList(), null); + + for (int i = 1; i < SAV.MaxSpeciesID + 1; i++) + LB_Species.Items.Add($"{i:000} - {GameInfo.Strings.specieslist[i]}"); + + editing = false; + LB_Species.SelectedIndex = 0; + CB_Species.KeyDown += WinFormsUtil.RemoveDropCB; + CHK_National.Checked = Zukan.HasNationalDex; + } + + private bool editing; + private int species = -1; + + private void ChangeCBSpecies(object sender, EventArgs e) + { + if (editing) return; + SetEntry(); + + editing = true; + species = (int)CB_Species.SelectedValue; + LB_Species.SelectedIndex = species - 1; // Since we don't allow index0 in combobox, everything is shifted by 1 + LB_Species.TopIndex = LB_Species.SelectedIndex; + GetEntry(); + editing = false; + } + + private void ChangeLBSpecies(object sender, EventArgs e) + { + if (editing) return; + SetEntry(); + + editing = true; + species = LB_Species.SelectedIndex + 1; + CB_Species.SelectedValue = species; + GetEntry(); + editing = false; + } + + private void GetEntry() + { + // Load Bools for the data + CB_State.SelectedIndex = (int)Zukan.GetState(species); + Zukan.GetGenderFlags(species, out var m, out var f, out var ms, out var fs); + CHK_M.Checked = m; + CHK_F.Checked = f; + CHK_MS.Checked = ms; + CHK_FS.Checked = fs; + + CHK_LangJPN.Checked = Zukan.GetLanguageFlag(species, (int)LanguageID.Japanese); + CHK_LangENG.Checked = Zukan.GetLanguageFlag(species, (int)LanguageID.English ); + CHK_LangFRE.Checked = Zukan.GetLanguageFlag(species, (int)LanguageID.French ); + CHK_LangITA.Checked = Zukan.GetLanguageFlag(species, (int)LanguageID.Italian ); + CHK_LangGER.Checked = Zukan.GetLanguageFlag(species, (int)LanguageID.German ); + CHK_LangSPA.Checked = Zukan.GetLanguageFlag(species, (int)LanguageID.Spanish ); + CHK_LangKOR.Checked = Zukan.GetLanguageFlag(species, (int)LanguageID.Korean ); + CHK_LangCHS.Checked = Zukan.GetLanguageFlag(species, (int)LanguageID.ChineseS); + CHK_LangCHT.Checked = Zukan.GetLanguageFlag(species, (int)LanguageID.ChineseT); + + var f1 = CLB_FormRegular; + var f2 = CLB_FormShiny; + f1.Items.Clear(); + f2.Items.Clear(); + var fc = Zukan8b.GetFormCount(species); + if (fc <= 0) + return; + + var forms = FormConverter.GetFormList(species, GameInfo.Strings.types, GameInfo.Strings.forms, Main.GenderSymbols, SAV.Generation).Take(fc).ToArray(); + f1.Items.AddRange(forms); + f2.Items.AddRange(forms); + for (int i = 0; i < f1.Items.Count; i++) + { + f1.SetItemChecked(i, Zukan.GetHasFormFlag(species, i, false)); + f2.SetItemChecked(i, Zukan.GetHasFormFlag(species, i, true)); + } + } + + private void SetEntry() + { + if (species < 0) + return; + + Zukan.SetState(species, (ZukanState8b)CB_State.SelectedIndex); + Zukan.SetGenderFlags(species, CHK_M.Checked, CHK_F.Checked, CHK_MS.Checked, CHK_FS.Checked); + + Zukan.SetLanguageFlag(species, (int)LanguageID.Japanese, CHK_LangJPN.Checked); + Zukan.SetLanguageFlag(species, (int)LanguageID.English, CHK_LangENG.Checked); + Zukan.SetLanguageFlag(species, (int)LanguageID.French, CHK_LangFRE.Checked); + Zukan.SetLanguageFlag(species, (int)LanguageID.Italian, CHK_LangITA.Checked); + Zukan.SetLanguageFlag(species, (int)LanguageID.German, CHK_LangGER.Checked); + Zukan.SetLanguageFlag(species, (int)LanguageID.Spanish, CHK_LangSPA.Checked); + Zukan.SetLanguageFlag(species, (int)LanguageID.Korean, CHK_LangKOR.Checked); + Zukan.SetLanguageFlag(species, (int)LanguageID.ChineseS, CHK_LangCHS.Checked); + Zukan.SetLanguageFlag(species, (int)LanguageID.ChineseT, CHK_LangCHT.Checked); + + var f1 = CLB_FormRegular; + var f2 = CLB_FormShiny; + for (int i = 0; i < f1.Items.Count; i++) + { + Zukan.SetHasFormFlag(species, i, false, f1.GetItemChecked(i)); + Zukan.SetHasFormFlag(species, i, true , f2.GetItemChecked(i)); + } + } + + private void B_Cancel_Click(object sender, EventArgs e) + { + Close(); + } + + private void B_Save_Click(object sender, EventArgs e) + { + SetEntry(); + Zukan.HasNationalDex = CHK_National.Checked; + Origin.CopyChangesFrom(SAV); + Close(); + } + + private void B_GiveAll_Click(object sender, EventArgs e) + { + bool all = ModifierKeys != Keys.Control; + CB_State.SelectedIndex = all ? (int)ZukanState8b.Caught : 0; + CHK_M.Checked = CHK_F.Checked = CHK_MS.Checked = CHK_FS.Checked = all; + CHK_LangJPN.Checked = CHK_LangENG.Checked = CHK_LangFRE.Checked = CHK_LangGER.Checked = CHK_LangITA.Checked = all; + CHK_LangSPA.Checked = CHK_LangKOR.Checked = CHK_LangCHS.Checked = CHK_LangCHT.Checked = all; + } + + private void B_Modify_Click(object sender, EventArgs e) + { + Button btn = (Button)sender; + modifyMenu.Show(btn.PointToScreen(new Point(0, btn.Height))); + } + + private void B_ModifyForms_Click(object sender, EventArgs e) + { + Button btn = (Button)sender; + modifyMenuForms.Show(btn.PointToScreen(new Point(0, btn.Height))); + } + + private void ModifyAll(object sender, EventArgs e) + { + SetEntry(); + + if (sender == mnuSeenNone) + Zukan.SetAllSeen(false); + if (sender == mnuSeenAll) + Zukan.SetAllSeen(shinyToo: ModifierKeys == Keys.Control); + else if (sender == mnuCaughtAll) + Zukan.CaughtAll(); + else if (sender == mnuCaughtNone) + Zukan.CaughtNone(); + else if (sender == mnuComplete) + Zukan.CompleteDex(ModifierKeys == Keys.Control); + + GetEntry(); + } + + private void ModifyAllForms(object sender, EventArgs e) + { + var f1 = CLB_FormRegular; + var f2 = CLB_FormShiny; + if (sender == mnuFormAllRegular) + { + for (int i = 0; i < f1.Items.Count; i++) + { + f1.SetItemChecked(i, true); + f2.SetItemChecked(i, sender == mnuFormAllShinies); + } + } + else if (sender == mnuFormAllShinies) + { + for (int i = 0; i < f1.Items.Count; i++) + { + f2.SetItemChecked(i, true); + } + } + else // None + { + for (int i = 0; i < f1.Items.Count; i++) + { + f1.SetItemChecked(i, false); + f2.SetItemChecked(i, false); + } + } + } + } +} diff --git a/PKHeX.WinForms/Subforms/Save Editors/SAV_EventWork.cs b/PKHeX.WinForms/Subforms/Save Editors/SAV_EventWork.cs index 91b0aee565d..ada9329dbc7 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/SAV_EventWork.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/SAV_EventWork.cs @@ -11,7 +11,7 @@ namespace PKHeX.WinForms public sealed partial class SAV_EventWork : Form { private readonly SAV7b Origin; - private readonly IEventWork SAV; + private readonly IEventVar SAV; private readonly SplitEventEditor Editor; public SAV_EventWork(SAV7b sav) @@ -27,7 +27,7 @@ public SAV_EventWork(SAV7b sav) DragDrop += Main_DragDrop; CB_Stats.Items.Clear(); - for (int i = 0; i < SAV.MaxWork; i++) + for (int i = 0; i < SAV.CountWork; i++) CB_Stats.Items.Add(i.ToString()); var work = GetStringList(sav.Version, "const"); @@ -50,7 +50,7 @@ public SAV_EventWork(SAV7b sav) L_Stats.Visible = CB_Stats.Visible = NUD_Stat.Visible = false; TC_Features.TabPages.Remove(GB_Constants); } - NUD_Flag.Maximum = SAV.MaxFlag - 1; + NUD_Flag.Maximum = SAV.CountFlag - 1; NUD_Flag.Text = "0"; c_CustomFlag.Checked = SAV.GetFlag(0); @@ -248,6 +248,7 @@ private static string[] GetStringList(GameVersion game, string type) private static string GetGameFilePrefix(GameVersion game) => game switch { + BD or SP or BDSP => "bdsp", SW or SH or SWSH => "swsh", GP or GE or GG => "gg", X or Y => "xy", @@ -306,4 +307,4 @@ private void B_ApplyWork_Click(object sender, EventArgs e) Origin.State.Edited = true; } } -} \ No newline at end of file +} diff --git a/PKHeX.WinForms/Util/WinFormsUtil.cs b/PKHeX.WinForms/Util/WinFormsUtil.cs index 3c31ae849e6..f267d490018 100644 --- a/PKHeX.WinForms/Util/WinFormsUtil.cs +++ b/PKHeX.WinForms/Util/WinFormsUtil.cs @@ -444,7 +444,9 @@ public static bool ExportMGDialog(DataMysteryGift gift, GameVersion origin) 7 => GameVersion.GG.Contains(origin) ? "Beluga Gift Record|*.wr7" + all : "Gen7 Mystery Gift|*.wc7;*.wc7full" + all, - 8 => "Gen8 Mystery Gift|*.wc8" + all, + 8 => GameVersion.BDSP.Contains(origin) + ? "BD/SP Gift|*.wb8" + all + : "Gen8 Mystery Gift|*.wc8" + all, _ => string.Empty, }; diff --git a/README.md b/README.md index 82420570e2c..452b083d8ae 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ PKHeX expects save files that are not encrypted with console-specific keys. Use ## Screenshots -![Main Window](https://i.imgur.com/sM7kt4u.png) +![Main Window](https://i.imgur.com/tYYR3HT.png) ## Building diff --git a/Tests/PKHeX.Core.Tests/General/GeneralTests.cs b/Tests/PKHeX.Core.Tests/General/GeneralTests.cs index 569eddbd2eb..75d6db7eded 100644 --- a/Tests/PKHeX.Core.Tests/General/GeneralTests.cs +++ b/Tests/PKHeX.Core.Tests/General/GeneralTests.cs @@ -13,6 +13,13 @@ public void SWSH_Hypothesis() GameVersion.SH.Should().BeEquivalentTo(45); } + [Fact] + public void BDSP_Hypothesis() + { + GameVersion.BD.Should().BeEquivalentTo(48); + GameVersion.SP.Should().BeEquivalentTo(49); + } + [Fact] public void StringsLoad() => GameInfo.GetStrings(GameLanguage.DefaultLanguage); diff --git a/Tests/PKHeX.Core.Tests/Legality/LearnabilityTests.cs b/Tests/PKHeX.Core.Tests/Legality/LearnabilityTests.cs index aae267572d1..db265ddf2b9 100644 --- a/Tests/PKHeX.Core.Tests/Legality/LearnabilityTests.cs +++ b/Tests/PKHeX.Core.Tests/Legality/LearnabilityTests.cs @@ -11,7 +11,7 @@ public static class LearnabilityTests [InlineData(nameof(Species.Bulbasaur), "Razor Leaf", "Vine Whip")] [InlineData(nameof(Species.Charizard), "Fly")] [InlineData(nameof(Species.Mew), "Pound")] - [InlineData(nameof(Species.Smeargle), "Hyperspace Fury")] + [InlineData(nameof(Species.Smeargle), "Frenzy Plant")] public static void VerifyCanLearn(string species, params string[] moves) { var encs = EncounterLearn.GetLearn(species, moves);