diff --git a/PKHeX.Core/Editing/Saves/Slots/Extensions.cs b/PKHeX.Core/Editing/Saves/Slots/Extensions.cs index 4ced2cca6..187cb1a6c 100644 --- a/PKHeX.Core/Editing/Saves/Slots/Extensions.cs +++ b/PKHeX.Core/Editing/Saves/Slots/Extensions.cs @@ -92,7 +92,7 @@ private static List GetExtraSlots5(SAV5 sav) }; if (sav is SAV5B2W2 b2w2) - list.Insert(1, new(b2w2.Forest.Fused, 0) { Type = StorageSlotType.Fused }); + list.Insert(1, new(b2w2.Forest.Fused, 0) { Type = StorageSlotType.FusedKyurem }); return list; } @@ -102,7 +102,7 @@ private static List GetExtraSlots6XY(SAV6XY sav) return [ new(sav.GTS.Upload, 0) {Type = StorageSlotType.GTS}, - new(sav.Fused[0], 0) {Type = StorageSlotType.Fused}, + new(sav.Fused[0], 0) {Type = StorageSlotType.FusedKyurem}, new(sav.SUBE.GiveSlot, 0) {Type = StorageSlotType.Misc}, // Old Man new(sav.BattleBox[0], 0) {Type = StorageSlotType.BattleBox}, @@ -119,7 +119,7 @@ private static List GetExtraSlots6AO(SAV6AO sav) return [ new(sav.GTS.Upload, 0) { Type = StorageSlotType.GTS }, - new(sav.Fused[0], 0) { Type = StorageSlotType.Fused }, + new(sav.Fused[0], 0) { Type = StorageSlotType.FusedKyurem }, new(sav.SUBE.GiveSlot, 0) {Type = StorageSlotType.Misc}, new(sav.BattleBox[0], 0) {Type = StorageSlotType.BattleBox}, @@ -136,14 +136,14 @@ private static List GetExtraSlots7(SAV7 sav, bool all) var list = new List { new(sav.GTS.Upload, 0) {Type = StorageSlotType.GTS}, - new(sav.Fused[0], 0, PartyFormat: true) {Type = StorageSlotType.Fused}, + new(sav.Fused[0], 0, PartyFormat: true) {Type = StorageSlotType.FusedKyurem}, }; if (sav is SAV7USUM uu) { list.AddRange( [ - new SlotInfoMisc(uu.Fused[1], 1, PartyFormat: true) {Type = StorageSlotType.Fused}, - new SlotInfoMisc(uu.Fused[2], 2, PartyFormat: true) {Type = StorageSlotType.Fused}, + new SlotInfoMisc(uu.Fused[1], 1, PartyFormat: true) {Type = StorageSlotType.FusedNecrozmaS}, + new SlotInfoMisc(uu.Fused[2], 2, PartyFormat: true) {Type = StorageSlotType.FusedNecrozmaM}, ]); list.AddRange( [ @@ -175,9 +175,9 @@ private static List GetExtraSlots8(ISaveBlock8Main sav) var dc = sav.Daycare; var list = new List { - new(fused[0], 0, true) {Type = StorageSlotType.Fused}, - new(fused[1], 1, true) {Type = StorageSlotType.Fused}, - new(fused[2], 2, true) {Type = StorageSlotType.Fused}, + new(fused[0], 0, true) {Type = StorageSlotType.FusedKyurem}, + new(fused[1], 1, true) {Type = StorageSlotType.FusedNecrozmaS}, + new(fused[2], 2, true) {Type = StorageSlotType.FusedNecrozmaM}, new(dc[0], 0) {Type = StorageSlotType.Daycare}, new(dc[1], 1) {Type = StorageSlotType.Daycare}, @@ -188,7 +188,7 @@ private static List GetExtraSlots8(ISaveBlock8Main sav) if (sav is SAV8SWSH {SaveRevision: >= 2} s8) { var block = s8.Blocks.GetBlockSafe(SaveBlockAccessor8SWSH.KFusedCalyrex); - var c = new SlotInfoMisc(block.Data, 3, true) {Type = StorageSlotType.Fused}; + var c = new SlotInfoMisc(block.Data, 3, true) {Type = StorageSlotType.FusedCalyrex}; list.Insert(3, c); } @@ -222,18 +222,18 @@ private static List GetExtraSlots9(SAV9SV sav) var list = new List { // Ride Legend - new(sav.BoxInfo.Raw.Slice(afterBox, PokeCrypto.SIZE_9PARTY), 0, true, Mutable: true) { Type = StorageSlotType.Party }, + new(sav.BoxInfo.Raw.Slice(afterBox, PokeCrypto.SIZE_9PARTY), 0, true, Mutable: true) { Type = StorageSlotType.Ride }, }; var block = sav.Blocks.GetBlock(SaveBlockAccessor9SV.KFusedCalyrex); - list.Add(new(block.Data, 0, true) { Type = StorageSlotType.Fused }); + list.Add(new(block.Data, 0, true) { Type = StorageSlotType.FusedCalyrex }); if (sav.Blocks.TryGetBlock(SaveBlockAccessor9SV.KFusedKyurem, out var kyurem)) - list.Add(new(kyurem.Data, 1, true) { Type = StorageSlotType.Fused }); + list.Add(new(kyurem.Data, 1, true) { Type = StorageSlotType.FusedKyurem }); if (sav.Blocks.TryGetBlock(SaveBlockAccessor9SV.KFusedNecrozmaS, out var solgaleo)) - list.Add(new(solgaleo.Data, 2, true) { Type = StorageSlotType.Fused }); + list.Add(new(solgaleo.Data, 2, true) { Type = StorageSlotType.FusedNecrozmaS }); if (sav.Blocks.TryGetBlock(SaveBlockAccessor9SV.KFusedNecrozmaM, out var lunala)) - list.Add(new(lunala.Data, 3, true) { Type = StorageSlotType.Fused }); + list.Add(new(lunala.Data, 3, true) { Type = StorageSlotType.FusedNecrozmaM }); if (sav.Blocks.TryGetBlock(SaveBlockAccessor9SV.KSurpriseTrade, out var surprise)) { diff --git a/PKHeX.Core/Editing/Saves/Slots/Info/ISlotInfo.cs b/PKHeX.Core/Editing/Saves/Slots/Info/ISlotInfo.cs index 8b1e20661..470bb7b40 100644 --- a/PKHeX.Core/Editing/Saves/Slots/Info/ISlotInfo.cs +++ b/PKHeX.Core/Editing/Saves/Slots/Info/ISlotInfo.cs @@ -8,7 +8,7 @@ public interface ISlotInfo /// /// Indicates the type of format the slot originates. Useful for legality purposes. /// - SlotOrigin Origin { get; } + StorageSlotType Type { get; } /// /// Differentiating slot number from other infos of the same type. diff --git a/PKHeX.Core/Editing/Saves/Slots/Info/SlotInfoBox.cs b/PKHeX.Core/Editing/Saves/Slots/Info/SlotInfoBox.cs index e5983a19e..ec85d7fee 100644 --- a/PKHeX.Core/Editing/Saves/Slots/Info/SlotInfoBox.cs +++ b/PKHeX.Core/Editing/Saves/Slots/Info/SlotInfoBox.cs @@ -5,7 +5,7 @@ namespace PKHeX.Core; /// public sealed record SlotInfoBox(int Box, int Slot) : ISlotInfo { - public SlotOrigin Origin => SlotOrigin.Box; + public StorageSlotType Type => StorageSlotType.Box; public bool CanWriteTo(SaveFile sav) => sav.HasBox && !sav.IsSlotLocked(Box, Slot); public WriteBlockedMessage CanWriteTo(SaveFile sav, PKM pk) => WriteBlockedMessage.None; diff --git a/PKHeX.Core/Editing/Saves/Slots/Info/SlotInfoFile.cs b/PKHeX.Core/Editing/Saves/Slots/Info/SlotInfoFile.cs index 2f633e735..6d43c5e1a 100644 --- a/PKHeX.Core/Editing/Saves/Slots/Info/SlotInfoFile.cs +++ b/PKHeX.Core/Editing/Saves/Slots/Info/SlotInfoFile.cs @@ -3,10 +3,10 @@ namespace PKHeX.Core; /// /// Records data for that originates from an external file. /// -/// +/// Path the file was loaded from. public sealed record SlotInfoFile(string Path) : ISlotInfo { - public SlotOrigin Origin => SlotOrigin.Party; + public StorageSlotType Type => StorageSlotType.Party; public int Slot => 0; public bool CanWriteTo(SaveFile sav) => false; diff --git a/PKHeX.Core/Editing/Saves/Slots/Info/SlotInfoLoader.cs b/PKHeX.Core/Editing/Saves/Slots/Info/SlotInfoLoader.cs index dee212adf..b5550eead 100644 --- a/PKHeX.Core/Editing/Saves/Slots/Info/SlotInfoLoader.cs +++ b/PKHeX.Core/Editing/Saves/Slots/Info/SlotInfoLoader.cs @@ -30,8 +30,9 @@ public static void AddFromLocalFile(string file, ConcurrentBag db, IT return; var data = File.ReadAllBytes(file); - _ = FileUtil.TryGetPKM(data, out var pk, fi.Extension, dest); - if (pk?.Species is not > 0) + if (!FileUtil.TryGetPKM(data, out var pk, fi.Extension, dest)) + return; + if (pk.Species is 0) return; var info = new SlotInfoFile(file); diff --git a/PKHeX.Core/Editing/Saves/Slots/Info/SlotInfoMisc.cs b/PKHeX.Core/Editing/Saves/Slots/Info/SlotInfoMisc.cs index dd0fe0160..60abbe987 100644 --- a/PKHeX.Core/Editing/Saves/Slots/Info/SlotInfoMisc.cs +++ b/PKHeX.Core/Editing/Saves/Slots/Info/SlotInfoMisc.cs @@ -7,10 +7,9 @@ namespace PKHeX.Core; /// public sealed record SlotInfoMisc(Memory Data, int Slot, bool PartyFormat = false, bool Mutable = false) : ISlotInfo { - public SlotOrigin Origin => PartyFormat ? SlotOrigin.Party : SlotOrigin.Box; + public required StorageSlotType Type { get; init; } public bool CanWriteTo(SaveFile sav) => Mutable; public WriteBlockedMessage CanWriteTo(SaveFile sav, PKM pk) => Mutable ? WriteBlockedMessage.None : WriteBlockedMessage.InvalidDestination; - public StorageSlotType Type { get; init; } public bool WriteTo(SaveFile sav, PKM pk, PKMImportSetting setting = PKMImportSetting.UseDefault) { diff --git a/PKHeX.Core/Editing/Saves/Slots/Info/SlotInfoParty.cs b/PKHeX.Core/Editing/Saves/Slots/Info/SlotInfoParty.cs index 72992e06e..af9778c6d 100644 --- a/PKHeX.Core/Editing/Saves/Slots/Info/SlotInfoParty.cs +++ b/PKHeX.Core/Editing/Saves/Slots/Info/SlotInfoParty.cs @@ -8,7 +8,7 @@ namespace PKHeX.Core; public sealed record SlotInfoParty(int Slot) : ISlotInfo { public int Slot { get; private set; } = Slot; - public SlotOrigin Origin => SlotOrigin.Party; + public StorageSlotType Type => StorageSlotType.Party; public bool CanWriteTo(SaveFile sav) => sav.HasParty; public WriteBlockedMessage CanWriteTo(SaveFile sav, PKM pk) => pk.IsEgg && sav.IsPartyAllEggs(Slot) diff --git a/PKHeX.Core/Editing/Saves/Slots/Info/SlotOrigin.cs b/PKHeX.Core/Editing/Saves/Slots/Info/SlotOrigin.cs deleted file mode 100644 index 6e894c61b..000000000 --- a/PKHeX.Core/Editing/Saves/Slots/Info/SlotOrigin.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace PKHeX.Core; - -/// -/// Indicates where the slot data originated from. -/// -public enum SlotOrigin : byte -{ - /// - /// Slot data originated from the Party, or follows "party format" data rules. - /// - /// Some games do not permit forms to exist outside the party. - Party = 0, - - /// - /// Slot data originated from the Box, or follows "stored" data rules. - /// - Box = 1, -} diff --git a/PKHeX.Core/Editing/Saves/Slots/StorageSlotType.cs b/PKHeX.Core/Editing/Saves/Slots/StorageSlotType.cs index 36a0f5a22..e2ae7e904 100644 --- a/PKHeX.Core/Editing/Saves/Slots/StorageSlotType.cs +++ b/PKHeX.Core/Editing/Saves/Slots/StorageSlotType.cs @@ -3,8 +3,10 @@ namespace PKHeX.Core; /// /// Extra Slot enumeration to indicate a general type of slot source. /// -public enum StorageSlotType +public enum StorageSlotType : byte { + None = 0, + Box, Party, @@ -14,10 +16,17 @@ public enum StorageSlotType Daycare, /// Global Trade Station (GTS) GTS, + /// Fused Legendary Storage - Fused, + FusedKyurem, + FusedNecrozmaS, + FusedNecrozmaM, + FusedCalyrex, + /// Miscellaneous Misc, /// Poké Pelago (Gen7) Resort, + /// Ride Legendary Slot (S/V) + Ride, } diff --git a/PKHeX.Core/Legality/Bulk/BulkAnalysis.cs b/PKHeX.Core/Legality/Bulk/BulkAnalysis.cs index 4ebcd1952..ac4eb0565 100644 --- a/PKHeX.Core/Legality/Bulk/BulkAnalysis.cs +++ b/PKHeX.Core/Legality/Bulk/BulkAnalysis.cs @@ -103,5 +103,5 @@ private static LegalityAnalysis[] GetIndividualAnalysis(IReadOnlyList return results; } - private static LegalityAnalysis Get(SlotCache cache) => new(cache.Entity, cache.SAV.Personal, cache.Source.Origin); + private static LegalityAnalysis Get(SlotCache cache) => new(cache.Entity, cache.SAV.Personal, cache.Source.Type); } diff --git a/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs b/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs index 30c4f62c3..c7c2dc013 100644 --- a/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs +++ b/PKHeX.Core/Legality/Formatting/LegalityCheckStrings.cs @@ -463,6 +463,9 @@ public static class LegalityCheckStrings public static string LStatNobleInvalid { get; set; } = "Noble Flag mismatch."; public static string LStatAlphaInvalid { get; set; } = "Alpha Flag mismatch."; + public static string LStoredSourceEgg { get; set; } = "Egg must be in Box or Party."; + public static string LStoredSourceInvalid_0 { get; set; } = "Invalid Stored Source: {0}"; + public static string LSuperComplete { get; set; } = "Super Training complete flag mismatch."; public static string LSuperDistro { get; set; } = "Distribution Super Training missions are not released."; public static string LSuperEgg { get; set; } = "Can't Super Train an Egg."; diff --git a/PKHeX.Core/Legality/LegalityAnalysis.cs b/PKHeX.Core/Legality/LegalityAnalysis.cs index 07e4b7f96..20a0ef27b 100644 --- a/PKHeX.Core/Legality/LegalityAnalysis.cs +++ b/PKHeX.Core/Legality/LegalityAnalysis.cs @@ -43,7 +43,7 @@ public sealed class LegalityAnalysis /// /// Indicates where the originated. /// - public readonly SlotOrigin SlotOrigin; + public readonly StorageSlotType SlotOrigin; /// /// Indicates if all checks ran to completion. @@ -61,20 +61,24 @@ public sealed class LegalityAnalysis /// public readonly LegalInfo Info; + private const StorageSlotType Ignore = StorageSlotType.None; + + internal bool IsStoredSlot(StorageSlotType type) => SlotOrigin == type || SlotOrigin is Ignore; + /// /// Checks the input data for legality. This is the best method for checking with context, as some games do not have all Alternate Form data available. /// /// Input data to check /// specific personal data /// Details about where the originated from. - public LegalityAnalysis(PKM pk, IPersonalTable table, SlotOrigin source = SlotOrigin.Party) : this(pk, table.GetFormEntry(pk.Species, pk.Form), source) { } + public LegalityAnalysis(PKM pk, IPersonalTable table, StorageSlotType source = Ignore) : this(pk, table.GetFormEntry(pk.Species, pk.Form), source) { } /// /// Checks the input data for legality. /// /// Input data to check /// Details about where the originated from. - public LegalityAnalysis(PKM pk, SlotOrigin source = SlotOrigin.Party) : this(pk, pk.PersonalInfo, source) { } + public LegalityAnalysis(PKM pk, StorageSlotType source = Ignore) : this(pk, pk.PersonalInfo, source) { } /// /// Checks the input data for legality. @@ -82,7 +86,7 @@ public sealed class LegalityAnalysis /// Input data to check /// Personal info to parse with /// Details about where the originated from. - public LegalityAnalysis(PKM pk, IPersonalInfo pi, SlotOrigin source = SlotOrigin.Party) + public LegalityAnalysis(PKM pk, IPersonalInfo pi, StorageSlotType source = Ignore) { Entity = pk; PersonalInfo = pi; @@ -302,6 +306,7 @@ private void UpdateChecks() if (format is 4 or 5 or 6) // Gen 6->7 transfer removes this property. Gen4GroundTile.Verify(this); + SlotType.Verify(this); if (format < 6) return; diff --git a/PKHeX.Core/Legality/LegalityAnalyzers.cs b/PKHeX.Core/Legality/LegalityAnalyzers.cs index 9e3069d6a..8bbf7f27a 100644 --- a/PKHeX.Core/Legality/LegalityAnalyzers.cs +++ b/PKHeX.Core/Legality/LegalityAnalyzers.cs @@ -36,4 +36,5 @@ internal static class LegalityAnalyzers public static readonly LegendsArceusVerifier Arceus = new(); public static readonly AwakenedValueVerifier Awakening = new(); public static readonly TrashByteVerifier Trash = new(); + public static readonly SlotTypeVerifier SlotType = new(); } diff --git a/PKHeX.Core/Legality/Structures/CheckIdentifier.cs b/PKHeX.Core/Legality/Structures/CheckIdentifier.cs index bdca02bbe..b6d16db9b 100644 --- a/PKHeX.Core/Legality/Structures/CheckIdentifier.cs +++ b/PKHeX.Core/Legality/Structures/CheckIdentifier.cs @@ -163,4 +163,9 @@ public enum CheckIdentifier : byte /// The pertains to string . /// TrashBytes, + + /// + /// The pertains to the . + /// + SlotType, } diff --git a/PKHeX.Core/Legality/Verifiers/FormArgumentVerifier.cs b/PKHeX.Core/Legality/Verifiers/FormArgumentVerifier.cs index 4e29059d4..213a257d7 100644 --- a/PKHeX.Core/Legality/Verifiers/FormArgumentVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/FormArgumentVerifier.cs @@ -111,7 +111,7 @@ private CheckResult VerifyFormArgument(LegalityAnalysis data, IFormArgument f) EncounterStatic9 { StarterBoxLegend: true } => arg switch { < 1 => GetInvalid(LFormArgumentLow), - 1 => data.SlotOrigin != SlotOrigin.Party ? GetInvalid(LFormParty) : GetValid(LFormArgumentValid), + 1 => !data.IsStoredSlot(StorageSlotType.Ride) ? GetInvalid(LFormParty) : GetValid(LFormArgumentValid), > 1 => GetInvalid(LFormArgumentHigh), }, _ => arg switch diff --git a/PKHeX.Core/Legality/Verifiers/FormVerifier.cs b/PKHeX.Core/Legality/Verifiers/FormVerifier.cs index d78749fd7..0ea53ba3b 100644 --- a/PKHeX.Core/Legality/Verifiers/FormVerifier.cs +++ b/PKHeX.Core/Legality/Verifiers/FormVerifier.cs @@ -172,7 +172,7 @@ private CheckResult VerifyForm(LegalityAnalysis data) case Shaymin: case Furfrou: case Hoopa: - if (form != 0 && data.SlotOrigin is not SlotOrigin.Party && pk.Format <= 6) // has form but stored in box + if (form != 0 && !data.IsStoredSlot(StorageSlotType.Party) && pk.Format <= 6) // has form but stored in box return GetInvalid(LFormParty); break; } diff --git a/PKHeX.Core/Legality/Verifiers/SlotTypeVerifier.cs b/PKHeX.Core/Legality/Verifiers/SlotTypeVerifier.cs new file mode 100644 index 000000000..a3faba764 --- /dev/null +++ b/PKHeX.Core/Legality/Verifiers/SlotTypeVerifier.cs @@ -0,0 +1,47 @@ +using static PKHeX.Core.LegalityCheckStrings; + +namespace PKHeX.Core; + +public sealed class SlotTypeVerifier : Verifier +{ + protected override CheckIdentifier Identifier => CheckIdentifier.SlotType; + + public override void Verify(LegalityAnalysis data) + { + var source = data.SlotOrigin; + if (source == 0) + return; // not provided, ignore + + var pk = data.Entity; + if (pk.IsEgg) + { + if (!IsSourceValidEgg(pk, source)) + data.AddLine(GetInvalid(LStoredSourceEgg)); + } + else + { + if (!IsSourceValid(pk, source)) + data.AddLine(GetInvalid(string.Format(LStoredSourceInvalid_0, source))); + } + } + + public static bool IsSourceValid(PKM pk, StorageSlotType source) => source switch + { + StorageSlotType.FusedKyurem => pk.Species is (int)Species.Reshiram or (int)Species.Zekrom, + StorageSlotType.FusedNecrozmaS => pk.Species is (int)Species.Solgaleo, + StorageSlotType.FusedNecrozmaM => pk.Species is (int)Species.Lunala, + StorageSlotType.FusedCalyrex => pk.Species is (int)Species.Glastrier or (int)Species.Spectrier, + + StorageSlotType.Ride => pk.Species is (int)Species.Koraidon or (int)Species.Miraidon && pk is PK9 {FormArgument: 1}, + _ => true, + }; + + public static bool IsSourceValidEgg(PKM pk, StorageSlotType source) => source switch + { + // Eggs should normally only be in Box or Party. + StorageSlotType.Box or StorageSlotType.Party => true, + StorageSlotType.Resort => true, // Poké Pelago can incubate eggs + StorageSlotType.Daycare when pk.Format == 2 => true, // ignore the "current egg" slot + _ => false, + }; +} diff --git a/PKHeX.Drawing.PokeSprite/Util/SpriteUtil.cs b/PKHeX.Drawing.PokeSprite/Util/SpriteUtil.cs index 93a380168..98bf1b16c 100644 --- a/PKHeX.Drawing.PokeSprite/Util/SpriteUtil.cs +++ b/PKHeX.Drawing.PokeSprite/Util/SpriteUtil.cs @@ -94,7 +94,7 @@ private static Bitmap GetSprite(PKM pk) return img; } - private static Bitmap GetSprite(PKM pk, SaveFile sav, int box, int slot, bool flagIllegal = false) + private static Bitmap GetSprite(PKM pk, SaveFile sav, int box, int slot, bool flagIllegal = false, StorageSlotType storage = StorageSlotType.None) { bool inBox = (uint)slot < MaxSlotCount; bool empty = pk.Species == 0; @@ -110,7 +110,7 @@ private static Bitmap GetSprite(PKM pk, SaveFile sav, int box, int slot, bool fl } if (flagIllegal) { - var la = new LegalityAnalysis(pk, sav.Personal, box != -1 ? SlotOrigin.Box : SlotOrigin.Party); + var la = new LegalityAnalysis(pk, sav.Personal, storage); if (!la.Valid) sprite = ImageUtil.LayerImage(sprite, Resources.warn, 0, FlagIllegalShiftY); else if (pk.Format >= 8 && MoveInfo.IsDummiedMoveAny(pk)) @@ -286,8 +286,9 @@ public static Bitmap Sprite(this IEncounterTemplate enc) _ => 0, }; - public static Bitmap Sprite(this PKM pk, SaveFile sav, int box, int slot, bool flagIllegal = false) - => GetSprite(pk, sav, box, slot, flagIllegal); + public static Bitmap Sprite(this PKM pk, SaveFile sav, int box = -1, int slot = -1, + bool flagIllegal = false, StorageSlotType storage = StorageSlotType.None) + => GetSprite(pk, sav, box, slot, flagIllegal, storage); public static Bitmap GetMysteryGiftPreviewPoke(MysteryGift gift) { diff --git a/PKHeX.WinForms/Controls/SAV Editor/ContextMenuSAV.cs b/PKHeX.WinForms/Controls/SAV Editor/ContextMenuSAV.cs index 1914601ab..d71277f44 100644 --- a/PKHeX.WinForms/Controls/SAV Editor/ContextMenuSAV.cs +++ b/PKHeX.WinForms/Controls/SAV Editor/ContextMenuSAV.cs @@ -112,28 +112,25 @@ private void ClickShowLegality(object sender, EventArgs e) var info = GetSenderInfo(sender); var sav = info.View.SAV; var pk = info.Slot.Read(sav); - var type = info.Slot is SlotInfoBox ? SlotOrigin.Box : SlotOrigin.Party; + var type = info.Slot.Type; var la = new LegalityAnalysis(pk, sav.Personal, type); RequestEditorLegality?.Invoke(la); } private void MenuOpening(object sender, CancelEventArgs e) { - var items = ((ContextMenuStrip)sender).Items; + var info = GetSenderInfo(sender); + bool canView = !info.IsEmpty() || Main.HaX; + bool canSet = info.CanWriteTo(); + bool canDelete = canSet && canView; + bool canLegality = ModifierKeys == Keys.Control && canView && RequestEditorLegality != null; - object? ctrl = ((ContextMenuStrip)sender).SourceControl; - if (ctrl is null) - return; - var info = GetSenderInfo(ctrl); - bool SlotFull = !info.IsEmpty(); - bool Editable = info.CanWriteTo(); - bool legality = ModifierKeys == Keys.Control; - ToggleItem(items, mnuSet, Editable); - ToggleItem(items, mnuDelete, Editable && SlotFull); - ToggleItem(items, mnuLegality, legality && SlotFull && RequestEditorLegality != null); - ToggleItem(items, mnuView, SlotFull || !Editable, true); + ToggleItem(mnuView, canView); + ToggleItem(mnuSet, canSet); + ToggleItem(mnuDelete, canDelete); + ToggleItem(mnuLegality, canLegality); - if (items.Count == 0) + if (!canView && !canSet && !canDelete) e.Cancel = true; } @@ -147,18 +144,8 @@ private static SlotViewInfo GetSenderInfo(object sender) return new SlotViewInfo(loc, view); } - private static void ToggleItem(ToolStripItemCollection items, ToolStripItem item, bool visible, bool first = false) + private static void ToggleItem(ToolStripItem item, bool visible) { - if (visible) - { - if (first) - items.Insert(0, item); - else - items.Add(item); - } - else if (items.Contains(item)) - { - items.Remove(item); - } + item.Visible = visible; } } diff --git a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs index 2873b9f9a..f6160958a 100644 --- a/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs +++ b/PKHeX.WinForms/Controls/SAV Editor/SAVEditor.cs @@ -209,7 +209,7 @@ private SlotInfoMisc GetSlotData(int index) { if (GetCurrentDaycare() is not { } s) throw new Exception(); - return new SlotInfoMisc(s.GetDaycareSlot(index), index); + return new SlotInfoMisc(s.GetDaycareSlot(index), index) {Type = StorageSlotType.Daycare}; } public void SetPKMBoxes() diff --git a/PKHeX.WinForms/Controls/Slots/SlotList.cs b/PKHeX.WinForms/Controls/Slots/SlotList.cs index dc63762e3..d08c4305e 100644 --- a/PKHeX.WinForms/Controls/Slots/SlotList.cs +++ b/PKHeX.WinForms/Controls/Slots/SlotList.cs @@ -8,8 +8,20 @@ namespace PKHeX.WinForms.Controls; public partial class SlotList : UserControl, ISlotViewer { - private static readonly string[] names = Enum.GetNames(); - private readonly Label[] Labels = new Label[names.Length]; + private static readonly string[] names = GetEnumNames(); + + public static string[] GetEnumNames() + { + var list = Enum.GetNames(); + foreach (ref var item in list.AsSpan()) + { + if (item.StartsWith("Fused")) + item = "Fused"; + } + return list; + } + + public readonly Label[] Labels = new Label[names.Length]; private readonly List slots = []; private List SlotOffsets = []; public int SlotCount { get; private set; } @@ -99,16 +111,16 @@ private void LoadSlots(int count, Action enableDragDropContext) private void AddControls(int countTotal) { - var type = (StorageSlotType)(-1); + var type = string.Empty; int added = -1; for (int i = 0; i < countTotal; i++) { var info = SlotOffsets[i]; - if (type != info.Type) + var label = Labels[(int)info.Type]; + if (label.Text != type) { added++; - type = info.Type; - var label = Labels[(int)type]; + type = label.Text; FLP_Slots.Controls.Add(label, 0, added++); } diff --git a/PKHeX.WinForms/Controls/Slots/SlotUtil.cs b/PKHeX.WinForms/Controls/Slots/SlotUtil.cs index 81a33bdbd..efa507571 100644 --- a/PKHeX.WinForms/Controls/Slots/SlotUtil.cs +++ b/PKHeX.WinForms/Controls/Slots/SlotUtil.cs @@ -59,9 +59,9 @@ public static void UpdateSlot(PictureBox pb, ISlotInfo c, PKM p, SaveFile s, boo var img = c switch { - SlotInfoBox b => p.Sprite(s, b.Box, b.Slot, flagIllegal), - SlotInfoParty ps => p.Sprite(s, -1, ps.Slot, flagIllegal), - _ => p.Sprite(s, -1, -1, flagIllegal), + SlotInfoBox b => p.Sprite(s, b.Box, b.Slot, flagIllegal, b.Type), + SlotInfoParty ps => p.Sprite(s, -1, ps.Slot, flagIllegal, ps.Type), + _ => p.Sprite(s, -1, -1, flagIllegal, c.Type), }; pb.BackColor = Color.Transparent; diff --git a/PKHeX.WinForms/MainWindow/Main.cs b/PKHeX.WinForms/MainWindow/Main.cs index 317e07f6e..6bd88921e 100644 --- a/PKHeX.WinForms/MainWindow/Main.cs +++ b/PKHeX.WinForms/MainWindow/Main.cs @@ -1162,7 +1162,7 @@ private void GetPreview(PictureBox pb, PKM? pk = null) if (menu != null) menu.Enabled = pk.Species != 0 || HaX; // Species - pb.Image = pk.Sprite(C_SAV.SAV, -1, -1, flagIllegal: false); + pb.Image = pk.Sprite(C_SAV.SAV); if (pb.BackColor == SlotUtil.BadDataColor) pb.BackColor = SlotUtil.GoodDataColor; } diff --git a/PKHeX.WinForms/Subforms/SAV_Database.cs b/PKHeX.WinForms/Subforms/SAV_Database.cs index fba48cfe5..fa87a253d 100644 --- a/PKHeX.WinForms/Subforms/SAV_Database.cs +++ b/PKHeX.WinForms/Subforms/SAV_Database.cs @@ -652,7 +652,7 @@ private void FillPKXBoxes(int start) int begin = start * RES_MIN; int end = Math.Min(RES_MAX, Results.Count - begin); for (int i = 0; i < end; i++) - PKXBOXES[i].Image = Results[i + begin].Entity.Sprite(SAV, -1, -1, true); + PKXBOXES[i].Image = Results[i + begin].Entity.Sprite(SAV, flagIllegal: true, storage: Results[i + begin].Source.Type); for (int i = end; i < RES_MAX; i++) PKXBOXES[i].Image = null; diff --git a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_FestivalPlaza.cs b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_FestivalPlaza.cs index df9836c86..55be933f9 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_FestivalPlaza.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/Gen7/SAV_FestivalPlaza.cs @@ -319,7 +319,7 @@ private void LoadBattleAgency() private void LoadPictureBox() { for (int i = 0; i < 3; i++) - PBs[i].Image = p[i].Sprite(SAV, -1, -1, flagIllegal: true); + PBs[i].Image = p[i].Sprite(SAV, flagIllegal: true); } private readonly NumericUpDown[] NUD_Trainers = new NumericUpDown[3]; diff --git a/PKHeX.WinForms/Subforms/Save Editors/SAV_GroupViewer.cs b/PKHeX.WinForms/Subforms/Save Editors/SAV_GroupViewer.cs index 6e1140e8d..7460212bf 100644 --- a/PKHeX.WinForms/Subforms/Save Editors/SAV_GroupViewer.cs +++ b/PKHeX.WinForms/Subforms/Save Editors/SAV_GroupViewer.cs @@ -117,7 +117,7 @@ private void LoadGroup(int index) var sav = SAV; for (int i = 0; i < slots.Length; i++) - Box.Entries[i].Image = slots[i].Sprite(sav, -1, -1, true); + Box.Entries[i].Image = slots[i].Sprite(sav, flagIllegal: true); if (slotSelected != -1 && (uint)slotSelected < Box.Entries.Count) Box.Entries[slotSelected].BackgroundImage = groupSelected != index ? null : SpriteUtil.Spriter.View; diff --git a/PKHeX.WinForms/Util/DevUtil.cs b/PKHeX.WinForms/Util/DevUtil.cs index 008cd38eb..7e3e95cf9 100644 --- a/PKHeX.WinForms/Util/DevUtil.cs +++ b/PKHeX.WinForms/Util/DevUtil.cs @@ -101,8 +101,7 @@ private static void UpdateTranslations() private static IEnumerable GetExtraControls() { - var slotGroupLabels = Enum.GetNames(); - foreach (var name in slotGroupLabels) + foreach (var name in SlotList.GetEnumNames().Distinct()) yield return new Label { Name = $"{nameof(Main)}.L_{name}", Text = name }; }