From 251dc9c46a68aa9251ab00d0d5db60c68dfef02e Mon Sep 17 00:00:00 2001 From: Kurt Date: Thu, 15 Dec 2016 23:17:17 -0800 Subject: [PATCH] Add locked slot indication and write protection Reinterpreted #637, now utilizing the lock symbol (cropped to 30px vertical height) to indicate strongly that the slot is locked (which can only be viewed). --- PKHeX/MainWindow/Main.cs | 94 ++++++++++++++++--- PKHeX/PKM/PKM.cs | 1 + PKHeX/Resources/img/misc/locked.png | Bin 1401 -> 1304 bytes PKHeX/Saves/SAV7.cs | 21 ++++- PKHeX/Saves/SaveFile.cs | 13 ++- PKHeX/Subforms/Save Editors/SAV_BoxViewer.cs | 35 +++++-- PKHeX/Util/ImageUtil.cs | 2 + 7 files changed, 144 insertions(+), 22 deletions(-) diff --git a/PKHeX/MainWindow/Main.cs b/PKHeX/MainWindow/Main.cs index 2412d2086..07cfad104 100644 --- a/PKHeX/MainWindow/Main.cs +++ b/PKHeX/MainWindow/Main.cs @@ -711,10 +711,30 @@ private void openFile(byte[] input, string path, string ext) #region PC/Box Data else if (BitConverter.ToUInt16(input, 4) == 0 && BitConverter.ToUInt32(input, 8) > 0 && PKX.getIsPKM(input.Length / SAV.BoxSlotCount / SAV.BoxCount) || PKX.getIsPKM(input.Length / SAV.BoxSlotCount)) { - if (SAV.setPCBin(input)) - Util.Alert("PC Binary loaded."); - else if (SAV.setBoxBin(input, CB_BoxSelect.SelectedIndex)) - Util.Alert("Box Binary loaded."); + if (SAV.getPCBin().Length == input.Length) + { + if (SAV.getBoxHasLockedSlot(0, SAV.BoxCount - 1)) + Util.Alert("Battle Box slots prevent loading of PC data."); + else if (SAV.setPCBin(input)) + Util.Alert("PC Binary loaded."); + else + { + Util.Alert("Binary is not compatible with save file.", "Current SAV Generation: " + SAV.Generation); + return; + } + } + else if (SAV.getBoxBin(CB_BoxSelect.SelectedIndex).Length == input.Length) + { + if (SAV.getBoxHasLockedSlot(CB_BoxSelect.SelectedIndex, CB_BoxSelect.SelectedIndex)) + Util.Alert("Battle Box slots in box prevent loading of box data."); + else if (SAV.setBoxBin(input, CB_BoxSelect.SelectedIndex)) + Util.Alert("Box Binary loaded."); + else + { + Util.Alert("Binary is not compatible with save file.", "Current SAV Generation: " + SAV.Generation); + return; + } + } else { Util.Alert("Binary is not compatible with save file.", "Current SAV Generation: " + SAV.Generation); @@ -737,8 +757,16 @@ private void openFile(byte[] input, string path, string ext) bool? noSetb = getPKMSetOverride(); PKM[] data = b.BattlePKMs; int offset = SAV.getBoxOffset(CB_BoxSelect.SelectedIndex); + int slotSkipped = 0; for (int i = 0; i < 24; i++) + { + if (SAV.getIsSlotLocked(CB_BoxSelect.SelectedIndex, i)) + { slotSkipped++; continue; } SAV.setStoredSlot(data[i], offset + i*SAV.SIZE_STORED, noSetb); + } + + if (slotSkipped > 0) + Util.Alert($"Skipped {slotSkipped} locked slot{(slotSkipped > 1 ? "s" : "")}."); setPKXBoxes(); updateBoxViewers(); @@ -3124,23 +3152,31 @@ private void clickBoxSort(object sender, EventArgs e) bool all = false; if (ModifierKeys == (Keys.Alt | Keys.Shift) && DialogResult.Yes == Util.Prompt(MessageBoxButtons.YesNo, "Clear ALL Boxes?!")) { + if (SAV.getBoxHasLockedSlot(0, SAV.BoxCount - 1)) + { Util.Alert("Battle Box slots prevent the clearing of all boxes."); return; } SAV.resetBoxes(); modified = "Boxes cleared!"; all = true; } else if (ModifierKeys == Keys.Alt && DialogResult.Yes == Util.Prompt(MessageBoxButtons.YesNo, "Clear Current Box?")) { + if (SAV.getBoxHasLockedSlot(CB_BoxSelect.SelectedIndex, CB_BoxSelect.SelectedIndex)) + { Util.Alert("Battle Box slots prevent the clearing of box."); return; } SAV.resetBoxes(CB_BoxSelect.SelectedIndex, CB_BoxSelect.SelectedIndex + 1); modified = "Current Box cleared!"; } else if (ModifierKeys == (Keys.Control | Keys.Shift) && DialogResult.Yes == Util.Prompt(MessageBoxButtons.YesNo, "Sort ALL Boxes?!")) { + if (SAV.getBoxHasLockedSlot(0, SAV.BoxCount - 1)) + { Util.Alert("Battle Box slots prevent the sorting of all boxes."); return; } SAV.sortBoxes(); modified = "Boxes sorted!"; all = true; } else if (ModifierKeys == Keys.Control && DialogResult.Yes == Util.Prompt(MessageBoxButtons.YesNo, "Sort Current Box?")) { + if (SAV.getBoxHasLockedSlot(CB_BoxSelect.SelectedIndex, CB_BoxSelect.SelectedIndex)) + { Util.Alert("Battle Box slots prevent the sorting of box."); return; } SAV.sortBoxes(CB_BoxSelect.SelectedIndex, CB_BoxSelect.SelectedIndex + 1); modified = "Current Box sorted!"; } @@ -3231,6 +3267,8 @@ private void clickSet(object sender, EventArgs e) int slot = getSlot(sender); if (slot == 30 && (CB_Species.SelectedIndex == 0 || CHK_IsEgg.Checked)) { Util.Alert("Can't have empty/egg first slot."); return; } + if (SAV.getIsSlotLocked(CB_BoxSelect.SelectedIndex, slot)) + { Util.Alert("Can't set to locked slot."); return; } int offset = getPKXOffset(slot); if (offset < 0) @@ -3279,7 +3317,10 @@ private void clickSet(object sender, EventArgs e) private void clickDelete(object sender, EventArgs e) { int slot = getSlot(sender); - if (slot == 30 && SAV.PartyCount == 1 && !HaX) { Util.Alert("Can't delete first slot."); return; } + if (slot == 30 && SAV.PartyCount == 1 && !HaX) + { Util.Alert("Can't delete first slot."); return; } + if (SAV.getIsSlotLocked(CB_BoxSelect.SelectedIndex, slot)) + { Util.Alert("Can't delete locked slot."); return; } int offset = getPKXOffset(slot); if (offset < 0) @@ -3382,11 +3423,18 @@ private void clickClone(object sender, EventArgs e) PKM pk = preparePKM(); + int slotSkipped = 0; for (int i = 0; i < 30; i++) // set to every slot in box { + if (SAV.getIsSlotLocked(CB_BoxSelect.SelectedIndex, i)) + { slotSkipped++; continue; } SAV.setStoredSlot(pk, getPKXOffset(i)); getQuickFiller(SlotPictureBoxes[i], pk); } + + if (slotSkipped > 0) + Util.Alert($"Skipped {slotSkipped} locked slot{(slotSkipped > 1 ? "s" : "")}."); + updateBoxViewers(); } private void clickLegality(object sender, EventArgs e) @@ -3709,7 +3757,13 @@ private void getQuickFiller(PictureBox pb, PKM pk = null) pk = pk ?? preparePKM(false); // don't perform control loss click if (pb == dragout) mnuLQR.Enabled = pk.Species != 0; // Species - pb.Image = pk.Species != 0 ? pk.Sprite : null; + + var sprite = pk.Species != 0 ? pk.Sprite : null; + int slot = getSlot(pb); + bool locked = slot < 30 && SAV.getIsSlotLocked(CB_BoxSelect.SelectedIndex, slot); + if (locked) + sprite = Util.LayerImage(sprite, Properties.Resources.locked, 5, 0, 1); + pb.Image = sprite; if (pb.BackColor == Color.Red) pb.BackColor = Color.Transparent; } @@ -3733,7 +3787,13 @@ private void getSlotFiller(int offset, PictureBox pb) return; } // Something stored in slot. Only display if species is valid. - pb.Image = p.Species == 0 ? null : p.Sprite; + + var sprite = p.Species != 0 ? p.Sprite : null; + int slot = getSlot(pb); + bool locked = slot < 30 && SAV.getIsSlotLocked(CB_BoxSelect.SelectedIndex, slot); + if (locked) + sprite = Util.LayerImage(sprite, Properties.Resources.locked, 5, 0, 1); + pb.Image = sprite; pb.BackColor = Color.Transparent; pb.Visible = true; } @@ -4089,17 +4149,21 @@ private void pbBoxSlot_MouseMove(object sender, MouseEventArgs e) if (pb.Image == null) return; + int slot = getSlot(pb); + int box = slot >= 30 ? -1 : CB_BoxSelect.SelectedIndex; + if (SAV.getIsSlotLocked(box, slot)) + return; + // Set flag to prevent re-entering. DragInfo.slotDragDropInProgress = true; DragInfo.slotSource = this; - DragInfo.slotSourceSlotNumber = getSlot(pb); - int offset = getPKXOffset(DragInfo.slotSourceSlotNumber); + DragInfo.slotSourceSlotNumber = slot; + DragInfo.slotSourceBoxNumber = box; + DragInfo.slotSourceOffset = getPKXOffset(DragInfo.slotSourceSlotNumber); // Prepare Data - DragInfo.slotPkmSource = SAV.getData(offset, SAV.SIZE_STORED); - DragInfo.slotSourceOffset = offset; - DragInfo.slotSourceBoxNumber = DragInfo.slotSourceSlotNumber >= 30 ? -1 : CB_BoxSelect.SelectedIndex; + DragInfo.slotPkmSource = SAV.getData(DragInfo.slotSourceOffset, SAV.SIZE_STORED); // Make a new file name based off the PID bool encrypt = ModifierKeys == Keys.Control; @@ -4161,6 +4225,12 @@ private void pbBoxSlot_DragDrop(object sender, DragEventArgs e) // Check for In-Dropped files (PKX,SAV,ETC) string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); if (Directory.Exists(files[0])) { loadBoxesFromDB(files[0]); return; } + if (SAV.getIsSlotLocked(DragInfo.slotDestinationBoxNumber, DragInfo.slotDestinationSlotNumber)) + { + DragInfo.slotDestinationSlotNumber = -1; // Invalidate + Util.Alert("Unable to set to locked slot."); + return; + } if (DragInfo.slotSourceOffset < 0) // file { if (files.Length <= 0) diff --git a/PKHeX/PKM/PKM.cs b/PKHeX/PKM/PKM.cs index 541052444..b21da987c 100644 --- a/PKHeX/PKM/PKM.cs +++ b/PKHeX/PKM/PKM.cs @@ -258,6 +258,7 @@ public byte[] Write() // Derived public virtual int SpriteItem => HeldItem; public virtual bool IsShiny => TSV == PSV; + public virtual bool Locked { get { return false; } set { } } public int TrainerID7 => (int)((uint)(TID | (SID << 16)) % 1000000); public bool Gen7 => Version >= 30 && Version <= 31; public bool Gen6 => Version >= 24 && Version <= 29; diff --git a/PKHeX/Resources/img/misc/locked.png b/PKHeX/Resources/img/misc/locked.png index eca24819749657c6cbaf80e072a439b3f4915e6f..763a05a29bf03941ae41ec25231f9c032de4e225 100644 GIT binary patch delta 1295 zcmV+q1@QX$3YZEZiBL{Q4GJ0x0000DNk~Le0000U0000U2nGNE06Q?QqLD5ef5HF& z4#EKyC`y0;000HYa0UJ}RMaclJ3UW4EF`}uxe zzxzJVAfo?;@h_7+_ojwuK_%z`PH+X#82tVTr~&bS9-+?$O%T0Xyn8OI`i>PYO0*={(z;aAr3STf5QJ0q>NWF z0=U~mmv%p^rr(c9^v9Fuako8C-fe9br zOWX>malMwV^+-Z|_AMnfYz`*t12S131gj#ccB@(ZVisRNuA+lanOwg*C1en3)L??# zm-rh_FxsLN;@(=dyDL4hf4?SHh%dHTs5Cc1lx5G8vye&!{1c-xjT>%T5=vLv6?C;* zqBRzsNVdQzcg9Am%b2)m^|q{eS_hZkmljHw4y);>xAW=cjdMk8zFB8OIvr2|x7?f9 z$_-yx8z#hG?^B9Ii|^KrqIxMP1bN^dkg+gPca-ao*)>AkyDMG9e=kbX^`br!XnyV_FQjLa4#oc>zHTtg*Wra*<_)<7gK4=vM3?XGs#;Z zc8{|saXkliRL`Z$Z3g=FwMfy`QxS7l|NPE!y4qhvA2gVSe;AXDcQT&cVoiGzH*ny= z8t>wfLlV8eTS1?{H^-~^aATqn7bNLAAk+h~rUMdx(Wanvxk@(!ZHs-1^AmNQ5Jm$n zKvxAI-nV_cxNcL7Pcg>02g2DP6et1`_q{Y;{6Dr=Mpzt!~L3E*x&mgGy&c|0~22cj}^MQd4oks zmxeb_kGOx&_%VKWZ|3xfo%V-IQmZlcM z1mJl&@q?>r2M13^`Te-$-E`TrmfS_fS>YaI8EhV(A#Fa01D-dKu}6Vhg%OLs++vas zV4ppW)8)LUr2hto!9}zg%`|8S%`qCsZF*%T@+|{t;7;Iq%N%?7=n4khEqr^J4;BJW zuwqt}Wy%J2#oVf@2G21XRnR8Xtp#hqYOoS42L*tov4F>y^J0uVi-Uj?@I8s;{H5{0 z3{n6m$^_XU2P_!-%kNyC4mghEd4G-pEaiNh7sn#a_#27XVv$xc4haAN002ovPDHLk FV1jRiUbz4O delta 1393 zcmV-%1&;cd3i%2yiBL{Q4GJ0x0000DNk~Le0000W0000W2nGNE0CReJ^Z)<=0drDE zLIAGL9O;oE8-K$901m?e$8V@)000FJNkl8R8YmoGWfQn*@BjtoLd3Nc2v(dH~7T0#mXlp%}Kp=?bZE~?E6W^=7M zXD@%WshQR3d!GCI(WSUA?lNQh?zi9XInOztd!FYx&ws&>i2VLf{U^Aei@$qQ0}W6m z)B_De*C3L`@1H=mP%Px73gfq0bxIh`WaN1oNu@5fa1$EPa#^OTDI zI{gm-U4N=1`mvShf|Z6_^;Dd3hX7fc9Jn43s>wjS1!!eQjq43`qemqG&cCIhhRp$F zdq5)FgV3rl+P&2xGQa>gPipDVQwai~FePvh!F7{Ccnk0iI~r@z2!P(*I(KVN2Wq1Q zz~we8mF9#B+XeHaEC6W#odu5on4HEAwk-{!YkwVTx_(4OYph1$bfH=5ijL5gv0@^0 z+p^{v+WGr^X+d=5sE&SmJC9!8I9J%_S&UT(ZiLj%5Z(aT*ug7ng9X6X`!&MhlDmy# za8w8tK)KL8P{yJ}<8dB8Vb=?Q-d*X!esPkq7vo`&{#F5+*+J)4lK>dl<4C{NBAtkz zrGKx;h%@X(dh4>|rJD3u!^8M)=kfMu3#x*^mK_d&^DT>&lkhzP&w+w@8N333QNQBwSVahZ)vTrZbq0F8NTTv$iJmTz z$i6**UVQ@EIfJUO-nP|dDq9gw6{{pV(|?#wU)uA>H!QMn2EjvlGkOGoK@kUkq#%^K zpPWe}b)oc2yL$W>da46_3NF2wOT$f8>U%Mjwk!)5Ah`+B7UzB7atUBuFV?M7ZC+p`^M}I{MH9i_c z59OEyKw^}BHvr;29zz)Tp{4FruH(s`<@ci*b!tj&C3jJAR*1`f5k=@TxXpuNJQgAb z;8KY$$DCu9%B=~~LDccHXss@~gHpzD>0HK~vCKHbpe0h@KHa3Lgui7_8g!?}QY-`T zl^GzXi@TZm&?4E?0vj`N zAY_83LDQib&@9<8-*AeeWLR!O`RZl+5QuL;_QU?%HzYEE^59JH1Ul~Nc{2Z(!|gTS z>HKTB!(li@{LbHboCC5w&*S+bFpK*_r|T@oDtZ00000NkvXXu0mjfwc?Hk diff --git a/PKHeX/Saves/SAV7.cs b/PKHeX/Saves/SAV7.cs index 354817b7a..be650750e 100644 --- a/PKHeX/Saves/SAV7.cs +++ b/PKHeX/Saves/SAV7.cs @@ -25,11 +25,19 @@ public SAV7(byte[] data = null) if (!Exportable) resetBoxes(); - var demo = new byte[0x4C4].SequenceEqual(Data.Skip(PCLayout).Take(0x4C4)); + var demo = new byte[0x4C4].SequenceEqual(Data.Skip(PCLayout).Take(0x4C4)); // up to Battle Box values if (demo) { PokeDex = -1; // Disabled } + int lockedCount = 0; + for (int i = 0; i < LockedSlots.Length; i++) + { + short val = BitConverter.ToInt16(Data, BattleBoxFlags + i * 2); + if (val >= 0) + LockedSlots[lockedCount++] = (val & 0xFF + BoxSlotCount*(val >> 8)) & 0xFFFF; + } + Array.Resize(ref LockedSlots, lockedCount); } // Configuration @@ -219,11 +227,13 @@ private void getSAVOffsets() PokeDexLanguageFlags = PokeDex + 0x550; WondercardData = WondercardFlags + 0x100; + BattleBoxFlags = PCLayout + 0x4C4; PCBackgrounds = PCLayout + 0x5C0; LastViewedBox = PCLayout + 0x5E3; PCFlags = PCLayout + 0x5E0; FashionLength = 0x1A08; + LockedSlots = new int[36]; } else // Empty input { @@ -245,6 +255,7 @@ private void getSAVOffsets() private int JoinFestaData { get; set; } = int.MinValue; private int PokeFinderSave { get; set; } = int.MinValue; private int BattleTree { get; set; } = int.MinValue; + private int BattleBoxFlags { get; set; } = int.MinValue; // Accessible as SAV7 public int TrainerCard { get; private set; } = 0x14000; @@ -863,6 +874,14 @@ public override int PartyCount protected set { Data[Party + 6 * SIZE_PARTY] = (byte)value; } } public override int BoxesUnlocked { get { return Data[PCFlags + 1]; } set { Data[PCFlags + 1] = (byte)value; } } + public override bool getIsSlotLocked(int box, int slot) + { + if (slot >= 30 || box > BoxCount) + return true; + + int slotIndex = slot + BoxSlotCount*box; + return LockedSlots.Any(s => s == slotIndex); + } public override int DaycareSeedSize => 32; // 128 bits public override int getDaycareSlotOffset(int loc, int slot) diff --git a/PKHeX/Saves/SaveFile.cs b/PKHeX/Saves/SaveFile.cs index 4291c7aca..c1c6a25a6 100644 --- a/PKHeX/Saves/SaveFile.cs +++ b/PKHeX/Saves/SaveFile.cs @@ -206,6 +206,7 @@ public PKM[] BattleBoxData for (int i = 0; i < data.Length; i++) { data[i] = getStoredSlot(BattleBox + SIZE_STORED * i); + data[i].Locked = BattleBoxLocked; if (data[i].Species == 0) return data.Take(i).ToArray(); } @@ -352,6 +353,7 @@ public virtual MysteryGiftAlbum GiftAlbum public virtual int BoxesUnlocked { get { return -1; } set { } } public virtual byte[] BoxFlags { get { return null; } set { } } public virtual int CurrentBox { get { return 0; } set { } } + protected int[] LockedSlots = new int[0]; protected virtual int getBoxWallpaperOffset(int box) { return -1; } public int getBoxWallpaper(int box) @@ -451,6 +453,11 @@ public void deletePartySlot(int slot) setStoredSlot(BlankPKM, getPartyOffset(5), false, false); PartyCount -= 1; } + public virtual bool getIsSlotLocked(int box, int slot) { return false; } + public bool getBoxHasLockedSlot(int BoxStart, int BoxEnd) + { + return LockedSlots.Any(slot => BoxStart*BoxSlotCount <= slot && slot < (BoxEnd + 1)*BoxSlotCount); + } public void sortBoxes(int BoxStart = 0, int BoxEnd = -1) { @@ -485,6 +492,8 @@ public void resetBoxes(int BoxStart = 0, int BoxEnd = -1) public byte[] getBoxBin(int box) { return BoxData.Skip(box*BoxSlotCount).Take(BoxSlotCount).SelectMany(pk => pk.EncryptedBoxData).ToArray(); } public bool setPCBin(byte[] data) { + if (LockedSlots.Any()) + return false; if (data.Length != getPCBin().Length) return false; @@ -506,6 +515,8 @@ public bool setPCBin(byte[] data) } public bool setBoxBin(byte[] data, int box) { + if (LockedSlots.Any(slot => box * BoxSlotCount <= slot && slot < (box + 1) * BoxSlotCount)) + return false; if (data.Length != getBoxBin(box).Length) return false; @@ -553,6 +564,6 @@ public void setData(byte[] input, int Offset) Edited = true; } - public virtual bool RequiresMemeCrypto { get { return false; } } + public virtual bool RequiresMemeCrypto => false; } } diff --git a/PKHeX/Subforms/Save Editors/SAV_BoxViewer.cs b/PKHeX/Subforms/Save Editors/SAV_BoxViewer.cs index 1ba0180d8..12ec9bf6c 100644 --- a/PKHeX/Subforms/Save Editors/SAV_BoxViewer.cs +++ b/PKHeX/Subforms/Save Editors/SAV_BoxViewer.cs @@ -112,12 +112,22 @@ private void getSlotFiller(int offset, PictureBox pb) return; } // Something stored in slot. Only display if species is valid. - pb.Image = p.Species == 0 ? null : p.Sprite; + var sprite = p.Species != 0 ? p.Sprite : null; + int slot = getSlot(pb); + bool locked = slot < 30 && SAV.getIsSlotLocked(CB_BoxSelect.SelectedIndex, slot); + if (locked) + sprite = Util.LayerImage(sprite, Properties.Resources.locked, 5, 0, 1); + pb.Image = sprite; pb.BackColor = Color.Transparent; } private void getQuickFiller(PictureBox pb, PKM pk) { - pb.Image = pk.Species == 0 ? null : pk.Sprite; + var sprite = pk.Species != 0 ? pk.Sprite : null; + int slot = getSlot(pb); + bool locked = slot < 30 && SAV.getIsSlotLocked(CB_BoxSelect.SelectedIndex, slot); + if (locked) + sprite = Util.LayerImage(sprite, Properties.Resources.locked, 5, 0, 1); + pb.Image = sprite; if (pb.BackColor == Color.Red) pb.BackColor = Color.Transparent; } @@ -157,18 +167,21 @@ private void pbBoxSlot_MouseMove(object sender, MouseEventArgs e) if (pb.Image == null) return; + int slot = getSlot(pb); + int box = slot >= 30 ? -1 : CB_BoxSelect.SelectedIndex; + if (SAV.getIsSlotLocked(box, slot)) + return; + // Set flag to prevent re-entering. DragInfo.slotDragDropInProgress = true; DragInfo.slotSource = this; - DragInfo.slotSourceSlotNumber = getSlot(pb); - int offset = getPKXOffset(DragInfo.slotSourceSlotNumber); + DragInfo.slotSourceSlotNumber = slot; + DragInfo.slotSourceBoxNumber = box; + DragInfo.slotSourceOffset = getPKXOffset(DragInfo.slotSourceSlotNumber); // Prepare Data - DragInfo.slotPkmSource = SAV.getData(offset, SAV.SIZE_STORED); - DragInfo.slotSourceOffset = offset; - DragInfo.slotSourceBoxNumber = CB_BoxSelect.SelectedIndex; - DragInfo.slotSource = this; + DragInfo.slotPkmSource = SAV.getData(DragInfo.slotSourceOffset, SAV.SIZE_STORED); // Make a new file name based off the PID byte[] dragdata = SAV.decryptPKM(DragInfo.slotPkmSource); @@ -225,6 +238,12 @@ private void pbBoxSlot_DragDrop(object sender, DragEventArgs e) // Check for In-Dropped files (PKX,SAV,ETC) string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); if (Directory.Exists(files[0])) { return; } + if (SAV.getIsSlotLocked(DragInfo.slotDestinationBoxNumber, DragInfo.slotDestinationSlotNumber)) + { + DragInfo.slotDestinationSlotNumber = -1; // Invalidate + Util.Alert("Unable to set to locked slot."); + return; + } if (DragInfo.slotSourceOffset < 0) // file { if (files.Length <= 0) diff --git a/PKHeX/Util/ImageUtil.cs b/PKHeX/Util/ImageUtil.cs index 745c701c2..6bb9167ee 100644 --- a/PKHeX/Util/ImageUtil.cs +++ b/PKHeX/Util/ImageUtil.cs @@ -10,6 +10,8 @@ public static partial class Util // Image Layering/Blending Utility internal static Bitmap LayerImage(Image baseLayer, Image overLayer, int x, int y, double trans) { + if (baseLayer == null) + return overLayer as Bitmap; Bitmap img = new Bitmap(baseLayer.Width, baseLayer.Height); using (Graphics gr = Graphics.FromImage(img)) {