2017-05-23 04:55:05 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Media;
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
using PKHeX.Core;
|
2019-09-29 16:47:06 +00:00
|
|
|
|
using PKHeX.Drawing;
|
2018-04-06 04:25:18 +00:00
|
|
|
|
using static PKHeX.Core.MessageStrings;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
|
|
|
|
|
namespace PKHeX.WinForms.Controls
|
|
|
|
|
{
|
2018-05-13 19:49:26 +00:00
|
|
|
|
public partial class SAVEditor : UserControl, ISlotViewer<PictureBox>, ISaveFileProvider
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
2020-10-18 18:02:39 +00:00
|
|
|
|
public SaveDataEditor<PictureBox> EditEnv = null!;
|
2019-11-16 01:34:18 +00:00
|
|
|
|
|
|
|
|
|
public void SetEditEnvironment(SaveDataEditor<PictureBox> value)
|
2019-09-03 02:30:58 +00:00
|
|
|
|
{
|
2019-11-16 01:34:18 +00:00
|
|
|
|
EditEnv = value;
|
|
|
|
|
M.Env = value;
|
|
|
|
|
menu.Editor = value;
|
|
|
|
|
SAV = value.SAV;
|
|
|
|
|
value.Slots.Publisher.Subscribers.Add(this);
|
|
|
|
|
value.Slots.Publisher.Subscribers.Add(SL_Party);
|
|
|
|
|
value.Slots.Publisher.Subscribers.Add(Box);
|
|
|
|
|
value.Slots.Publisher.Subscribers.Add(SL_Extra);
|
2019-09-03 02:30:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-10-18 18:02:39 +00:00
|
|
|
|
public SaveFile SAV { get; private set; } = new FakeSaveFile();
|
2018-05-13 19:49:26 +00:00
|
|
|
|
public int CurrentBox => Box.CurrentBox;
|
2020-12-22 07:37:07 +00:00
|
|
|
|
public SlotChangeManager M { get; }
|
2019-09-03 02:30:58 +00:00
|
|
|
|
public readonly ContextMenuSAV menu;
|
2018-05-24 01:29:30 +00:00
|
|
|
|
public readonly BoxMenuStrip SortMenu;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
|
2019-02-02 07:08:03 +00:00
|
|
|
|
public bool HaX;
|
2018-08-20 01:22:07 +00:00
|
|
|
|
public bool ModifyPKM { private get; set; }
|
|
|
|
|
private bool _hideSecret;
|
2020-10-18 18:02:39 +00:00
|
|
|
|
public bool HideSecretDetails { private get => _hideSecret; set => ToggleSecrets(SAV, _hideSecret = value); }
|
|
|
|
|
public ToolStripMenuItem Menu_Redo { get; set; } = null!;
|
|
|
|
|
public ToolStripMenuItem Menu_Undo { get; set; } = null!;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
private bool FieldsLoaded;
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-05-05 15:07:22 +00:00
|
|
|
|
public IList<PictureBox> SlotPictureBoxes { get; }
|
2019-09-03 02:30:58 +00:00
|
|
|
|
|
2018-05-05 15:07:22 +00:00
|
|
|
|
public int ViewIndex { get; set; } = -1;
|
|
|
|
|
|
2017-05-23 04:55:05 +00:00
|
|
|
|
public bool FlagIllegal
|
|
|
|
|
{
|
|
|
|
|
get => Box.FlagIllegal;
|
|
|
|
|
set
|
|
|
|
|
{
|
2019-11-16 01:34:18 +00:00
|
|
|
|
SL_Extra.FlagIllegal = SL_Party.FlagIllegal = Box.FlagIllegal = value && !HaX;
|
2020-10-18 18:02:39 +00:00
|
|
|
|
if (SAV is FakeSaveFile)
|
|
|
|
|
return;
|
|
|
|
|
ReloadSlots();
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-01-03 01:08:14 +00:00
|
|
|
|
public void ReloadSlots()
|
|
|
|
|
{
|
|
|
|
|
UpdateBoxViewers(all: true);
|
|
|
|
|
ResetNonBoxSlots();
|
|
|
|
|
}
|
2017-05-23 04:55:05 +00:00
|
|
|
|
|
2018-01-03 07:00:52 +00:00
|
|
|
|
public SAVEditor()
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
|
|
|
|
InitializeComponent();
|
2018-07-07 18:20:05 +00:00
|
|
|
|
|
|
|
|
|
L_SlotOccupied = new[] { L_DC1, L_DC2 };
|
|
|
|
|
TB_SlotEXP = new[] { TB_Daycare1XP, TB_Daycare2XP };
|
|
|
|
|
L_SlotEXP = new[] { L_XP1, L_XP2 };
|
2019-11-16 22:45:21 +00:00
|
|
|
|
SlotPictureBoxes = new[] { dcpkx1, dcpkx2 };
|
|
|
|
|
|
2018-12-20 06:10:32 +00:00
|
|
|
|
Tab_Box.ContextMenuStrip = SortMenu = new BoxMenuStrip(this);
|
2019-09-03 02:30:58 +00:00
|
|
|
|
M = new SlotChangeManager(this) {Env = EditEnv};
|
|
|
|
|
Box.Setup(M);
|
2019-11-16 01:34:18 +00:00
|
|
|
|
SL_Party.Setup(M);
|
2017-05-23 04:55:05 +00:00
|
|
|
|
|
2018-09-03 01:02:25 +00:00
|
|
|
|
SL_Extra.ViewIndex = -2;
|
2019-09-03 02:30:58 +00:00
|
|
|
|
menu = new ContextMenuSAV { Manager = M };
|
2018-09-03 01:02:25 +00:00
|
|
|
|
InitializeEvents();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void InitializeEvents()
|
|
|
|
|
{
|
2017-05-23 04:55:05 +00:00
|
|
|
|
foreach (PictureBox pb in SlotPictureBoxes)
|
2018-05-05 15:07:22 +00:00
|
|
|
|
{
|
|
|
|
|
InitializeDragDrop(pb);
|
2017-05-23 04:55:05 +00:00
|
|
|
|
pb.ContextMenuStrip = menu.mnuVSD;
|
2018-05-05 15:07:22 +00:00
|
|
|
|
}
|
2017-05-23 04:55:05 +00:00
|
|
|
|
|
2018-09-03 01:02:25 +00:00
|
|
|
|
GiveFeedback += (sender, e) => e.UseDefaultCursors = false;
|
2018-07-26 02:29:41 +00:00
|
|
|
|
Tab_Box.MouseWheel += (s, e) =>
|
|
|
|
|
{
|
2018-08-15 02:39:14 +00:00
|
|
|
|
if (menu.mnuVSD.Visible)
|
2018-08-12 18:01:21 +00:00
|
|
|
|
return;
|
2019-08-21 02:50:28 +00:00
|
|
|
|
Box.CurrentBox = e.Delta > 1 ? Box.Editor.MoveLeft() : Box.Editor.MoveRight();
|
2018-07-26 02:29:41 +00:00
|
|
|
|
};
|
|
|
|
|
|
2020-10-18 18:02:39 +00:00
|
|
|
|
GB_Daycare.Click += (o, args) => SwitchDaycare(GB_Daycare, args);
|
2017-05-23 04:55:05 +00:00
|
|
|
|
FLP_SAVtools.Scroll += WinFormsUtil.PanelScroll;
|
2018-06-17 00:03:22 +00:00
|
|
|
|
SortMenu.Opening += (s, x) => x.Cancel = !tabBoxMulti.GetTabRect(tabBoxMulti.SelectedIndex).Contains(PointToClient(MousePosition));
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-01-31 02:52:55 +00:00
|
|
|
|
private void InitializeDragDrop(Control pb)
|
|
|
|
|
{
|
|
|
|
|
pb.MouseEnter += M.MouseEnter;
|
|
|
|
|
pb.MouseLeave += M.MouseLeave;
|
|
|
|
|
pb.MouseClick += M.MouseClick;
|
2018-05-11 23:38:09 +00:00
|
|
|
|
pb.MouseMove += M.MouseMove;
|
2018-01-31 02:52:55 +00:00
|
|
|
|
pb.MouseDown += M.MouseDown;
|
|
|
|
|
pb.MouseUp += M.MouseUp;
|
|
|
|
|
|
|
|
|
|
pb.DragEnter += M.DragEnter;
|
2018-05-11 23:38:09 +00:00
|
|
|
|
pb.DragDrop += M.DragDrop;
|
2018-01-31 02:52:55 +00:00
|
|
|
|
pb.QueryContinueDrag += M.QueryContinueDrag;
|
|
|
|
|
pb.GiveFeedback += (sender, e) => e.UseDefaultCursors = false;
|
|
|
|
|
pb.AllowDrop = true;
|
|
|
|
|
pb.ContextMenuStrip = menu.mnuVSD;
|
|
|
|
|
}
|
2017-05-23 04:55:05 +00:00
|
|
|
|
|
|
|
|
|
/// <summary>Occurs when the Control Collection requests a cloning operation to the current box.</summary>
|
2020-10-18 18:02:39 +00:00
|
|
|
|
public event EventHandler? RequestCloneData;
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-05-23 04:55:05 +00:00
|
|
|
|
/// <summary>Occurs when the Control Collection requests a save to be reloaded.</summary>
|
2020-10-18 18:02:39 +00:00
|
|
|
|
public event EventHandler? RequestReloadSave;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
|
|
|
|
|
public void EnableDragDrop(DragEventHandler enter, DragEventHandler drop)
|
|
|
|
|
{
|
|
|
|
|
AllowDrop = true;
|
|
|
|
|
DragDrop += drop;
|
2020-10-18 18:02:39 +00:00
|
|
|
|
foreach (var tab in tabBoxMulti.TabPages.OfType<TabPage>())
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
|
|
|
|
tab.AllowDrop = true;
|
|
|
|
|
tab.DragEnter += enter;
|
|
|
|
|
tab.DragDrop += drop;
|
|
|
|
|
}
|
2019-08-21 02:50:28 +00:00
|
|
|
|
M.Drag.RequestExternalDragDrop += drop;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
2018-05-12 15:13:39 +00:00
|
|
|
|
|
2017-05-23 04:55:05 +00:00
|
|
|
|
// Generic Subfunctions //
|
2018-05-05 15:07:22 +00:00
|
|
|
|
public int GetSlotOffset(int slot)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
2019-11-16 01:34:18 +00:00
|
|
|
|
return SAV.GetDaycareSlotOffset(SAV.DaycareIndex, slot);
|
2018-01-31 02:52:55 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
public int SwapBoxesViewer(int viewBox)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
|
|
|
|
int mainBox = Box.CurrentBox;
|
|
|
|
|
Box.CurrentBox = viewBox;
|
|
|
|
|
return mainBox;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
public void UpdateBoxViewers(bool all = false)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
|
|
|
|
foreach (var v in M.Boxes.Where(v => v.CurrentBox == Box.CurrentBox || all))
|
|
|
|
|
{
|
|
|
|
|
v.FlagIllegal = Box.FlagIllegal;
|
|
|
|
|
v.ResetSlots();
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2019-09-03 02:30:58 +00:00
|
|
|
|
public void NotifySlotOld(ISlotInfo previous)
|
|
|
|
|
{
|
|
|
|
|
var index = GetViewIndex(previous);
|
|
|
|
|
if (index < 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
var pb = SlotPictureBoxes[index];
|
|
|
|
|
pb.BackgroundImage = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int GetViewIndex(ISlotInfo slot)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < SlotPictureBoxes.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
var data = GetSlotData(i);
|
|
|
|
|
if (data.Equals(slot))
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void NotifySlotChanged(ISlotInfo slot, SlotTouchType type, PKM pkm)
|
|
|
|
|
{
|
|
|
|
|
var index = GetViewIndex(slot);
|
|
|
|
|
if (index < 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (type.IsContentChange() && slot is SlotInfoParty)
|
|
|
|
|
ResetParty(); // lots of slots change, just update
|
|
|
|
|
|
|
|
|
|
var pb = SlotPictureBoxes[index];
|
|
|
|
|
SlotUtil.UpdateSlot(pb, slot, pkm, SAV, Box.FlagIllegal, type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ISlotInfo GetSlotData(PictureBox view)
|
|
|
|
|
{
|
|
|
|
|
var index = SlotPictureBoxes.IndexOf(view);
|
|
|
|
|
return GetSlotData(index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ISlotInfo GetSlotData(int index)
|
|
|
|
|
{
|
|
|
|
|
var ofs = GetSlotOffset(index);
|
2019-11-16 01:34:18 +00:00
|
|
|
|
return new SlotInfoMisc(SAV, index, ofs);
|
2019-09-03 02:30:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
public void SetPKMBoxes()
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
|
|
|
|
if (SAV.HasBox)
|
|
|
|
|
Box.ResetSlots();
|
|
|
|
|
|
2017-09-07 05:11:08 +00:00
|
|
|
|
ResetNonBoxSlots();
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-09-07 05:11:08 +00:00
|
|
|
|
private void ResetNonBoxSlots()
|
|
|
|
|
{
|
|
|
|
|
ResetParty();
|
|
|
|
|
ResetDaycare();
|
|
|
|
|
ResetMiscSlots();
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-09-07 05:11:08 +00:00
|
|
|
|
private void ResetMiscSlots()
|
|
|
|
|
{
|
2018-01-31 02:52:55 +00:00
|
|
|
|
var slots = SL_Extra.SlotPictureBoxes;
|
|
|
|
|
for (int i = 0; i < SL_Extra.SlotCount; i++)
|
2019-09-03 02:30:58 +00:00
|
|
|
|
{
|
|
|
|
|
var info = SL_Extra.GetSlotData(i);
|
|
|
|
|
var pb = slots[i];
|
|
|
|
|
SlotUtil.UpdateSlot(pb, info, info.Read(SAV), SAV, Box.FlagIllegal);
|
|
|
|
|
}
|
2017-09-07 05:11:08 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-09-07 05:11:08 +00:00
|
|
|
|
private void ResetParty()
|
|
|
|
|
{
|
2019-11-16 01:34:18 +00:00
|
|
|
|
if (SAV.HasParty)
|
|
|
|
|
SL_Party.ResetSlots();
|
2017-09-07 05:11:08 +00:00
|
|
|
|
}
|
2018-07-07 18:20:05 +00:00
|
|
|
|
|
|
|
|
|
private readonly Label[] L_SlotOccupied;
|
|
|
|
|
private readonly TextBox[] TB_SlotEXP;
|
|
|
|
|
private readonly Label[] L_SlotEXP;
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-09-07 05:11:08 +00:00
|
|
|
|
private void ResetDaycare()
|
|
|
|
|
{
|
|
|
|
|
if (!SAV.HasDaycare)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 2; i++)
|
|
|
|
|
{
|
2019-11-16 01:34:18 +00:00
|
|
|
|
var relIndex = i;
|
2019-09-03 02:30:58 +00:00
|
|
|
|
var pb = UpdateSlot(relIndex);
|
|
|
|
|
|
2017-09-07 05:11:08 +00:00
|
|
|
|
uint? exp = SAV.GetDaycareEXP(SAV.DaycareIndex, i);
|
|
|
|
|
TB_SlotEXP[i].Visible = L_SlotEXP[i].Visible = exp != null;
|
|
|
|
|
TB_SlotEXP[i].Text = exp.ToString();
|
2019-09-03 02:30:58 +00:00
|
|
|
|
|
2017-09-07 05:11:08 +00:00
|
|
|
|
bool? occ = SAV.IsDaycareOccupied(SAV.DaycareIndex, i);
|
|
|
|
|
L_SlotOccupied[i].Visible = occ != null;
|
|
|
|
|
if (occ == true) // If Occupied
|
2018-08-03 03:11:42 +00:00
|
|
|
|
{
|
2017-09-07 05:11:08 +00:00
|
|
|
|
L_SlotOccupied[i].Text = $"{i + 1}: ✓";
|
2018-08-03 03:11:42 +00:00
|
|
|
|
}
|
2017-09-07 05:11:08 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
L_SlotOccupied[i].Text = $"{i + 1}: ✘";
|
2020-01-18 21:27:48 +00:00
|
|
|
|
var current = pb.Image;
|
|
|
|
|
if (current != null)
|
|
|
|
|
pb.Image = ImageUtil.ChangeOpacity(current, 0.6);
|
2017-09-07 05:11:08 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool? egg = SAV.IsDaycareHasEgg(SAV.DaycareIndex);
|
|
|
|
|
DayCare_HasEgg.Visible = egg != null;
|
|
|
|
|
DayCare_HasEgg.Checked = egg == true;
|
|
|
|
|
|
|
|
|
|
var seed = SAV.GetDaycareRNGSeed(SAV.DaycareIndex);
|
2020-01-18 21:27:48 +00:00
|
|
|
|
bool hasSeed = !string.IsNullOrEmpty(seed);
|
|
|
|
|
if (hasSeed)
|
2017-09-07 05:11:08 +00:00
|
|
|
|
{
|
|
|
|
|
TB_RNGSeed.MaxLength = SAV.DaycareSeedSize;
|
|
|
|
|
TB_RNGSeed.Text = seed;
|
|
|
|
|
}
|
2020-01-18 21:27:48 +00:00
|
|
|
|
L_DaycareSeed.Visible = TB_RNGSeed.Visible = hasSeed;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2019-09-03 02:30:58 +00:00
|
|
|
|
private PictureBox UpdateSlot(int relIndex)
|
|
|
|
|
{
|
|
|
|
|
var info = GetSlotData(relIndex);
|
|
|
|
|
var pb = SlotPictureBoxes[relIndex];
|
|
|
|
|
SlotUtil.UpdateSlot(pb, info, info.Read(SAV), SAV, Box.FlagIllegal);
|
|
|
|
|
return pb;
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-13 02:28:35 +00:00
|
|
|
|
public void SetParty() => ResetParty();
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
public void ClickUndo()
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
2019-09-03 02:30:58 +00:00
|
|
|
|
EditEnv.Slots.Undo();
|
|
|
|
|
UpdateUndoRedo();
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
public void ClickRedo()
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
2019-09-03 02:30:58 +00:00
|
|
|
|
EditEnv.Slots.Redo();
|
|
|
|
|
UpdateUndoRedo();
|
|
|
|
|
}
|
2017-05-23 04:55:05 +00:00
|
|
|
|
|
2019-09-03 02:30:58 +00:00
|
|
|
|
public void UpdateUndoRedo()
|
|
|
|
|
{
|
|
|
|
|
Menu_Undo.Enabled = EditEnv.Slots.Changelog.CanUndo;
|
|
|
|
|
Menu_Redo.Enabled = EditEnv.Slots.Changelog.CanRedo;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-05-23 04:55:05 +00:00
|
|
|
|
public void SetClonesToBox(PKM pk)
|
|
|
|
|
{
|
2018-07-07 18:20:05 +00:00
|
|
|
|
if (WinFormsUtil.Prompt(MessageBoxButtons.YesNo, string.Format(MsgSaveBoxCloneFromTabs, Box.CurrentBoxName)) != DialogResult.Yes)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2018-07-07 18:20:05 +00:00
|
|
|
|
int slotSkipped = SetClonesToCurrentBox(pk, Box.CurrentBox);
|
|
|
|
|
if (slotSkipped > 0)
|
|
|
|
|
WinFormsUtil.Alert(string.Format(MsgSaveBoxImportSkippedLocked, slotSkipped));
|
|
|
|
|
|
|
|
|
|
UpdateBoxViewers();
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-07-07 18:20:05 +00:00
|
|
|
|
private int SetClonesToCurrentBox(PKM pk, int box)
|
|
|
|
|
{
|
2019-09-03 02:30:58 +00:00
|
|
|
|
var arr = new PKM[SAV.BoxSlotCount];
|
2017-05-23 04:55:05 +00:00
|
|
|
|
for (int i = 0; i < SAV.BoxSlotCount; i++) // set to every slot in box
|
2019-09-03 02:30:58 +00:00
|
|
|
|
arr[i] = pk;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
|
2019-09-03 02:30:58 +00:00
|
|
|
|
int slotSkipped = SAV.SetBoxData(arr, box);
|
|
|
|
|
Box.ResetSlots();
|
2018-07-07 18:20:05 +00:00
|
|
|
|
return slotSkipped;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
public void ClickSlot(object sender, EventArgs e)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
|
|
|
|
switch (ModifierKeys)
|
|
|
|
|
{
|
2019-09-03 02:30:58 +00:00
|
|
|
|
case Keys.Control | Keys.Alt:
|
|
|
|
|
ClickClone(sender, e);
|
|
|
|
|
break;
|
2018-07-07 18:20:05 +00:00
|
|
|
|
default: // forward to contextmenu for default behavior
|
2017-05-23 04:55:05 +00:00
|
|
|
|
menu.OmniClick(sender, e, ModifierKeys);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-21 23:31:41 +00:00
|
|
|
|
private void ClickBoxSort(object sender, MouseEventArgs e)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
2018-04-24 01:55:58 +00:00
|
|
|
|
if (tabBoxMulti.SelectedTab != Tab_Box)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
return;
|
2018-04-21 23:31:41 +00:00
|
|
|
|
if (!tabBoxMulti.GetTabRect(tabBoxMulti.SelectedIndex).Contains(PointToClient(MousePosition)))
|
2017-05-23 04:55:05 +00:00
|
|
|
|
return;
|
2020-05-26 23:59:47 +00:00
|
|
|
|
if ((e.Button & MouseButtons.Right) == 0)
|
2018-04-24 01:55:58 +00:00
|
|
|
|
{
|
2020-05-26 23:59:47 +00:00
|
|
|
|
if ((ModifierKeys & Keys.Alt) != 0)
|
2018-09-02 18:31:34 +00:00
|
|
|
|
SortMenu.Clear();
|
2020-05-26 23:59:47 +00:00
|
|
|
|
else if ((ModifierKeys & Keys.Control) != 0)
|
2018-09-02 18:31:34 +00:00
|
|
|
|
SortMenu.Sort();
|
2018-04-24 01:55:58 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2018-04-21 23:31:41 +00:00
|
|
|
|
var pt = Tab_Box.PointToScreen(new Point(0, 0));
|
|
|
|
|
SortMenu.Show(pt);
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2019-02-21 01:59:54 +00:00
|
|
|
|
public void FinishBoxManipulation(string message, bool all, int count)
|
2018-04-21 23:31:41 +00:00
|
|
|
|
{
|
2017-06-18 01:37:19 +00:00
|
|
|
|
SetPKMBoxes();
|
|
|
|
|
UpdateBoxViewers(all);
|
2020-01-18 21:27:48 +00:00
|
|
|
|
if (!string.IsNullOrWhiteSpace(message))
|
2019-02-21 01:59:54 +00:00
|
|
|
|
WinFormsUtil.Alert(message + $" ({count})");
|
2018-09-02 18:31:34 +00:00
|
|
|
|
else
|
|
|
|
|
SystemSounds.Asterisk.Play();
|
2018-04-21 23:31:41 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
private void ClickBoxDouble(object sender, MouseEventArgs e)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
|
|
|
|
if (tabBoxMulti.SelectedTab == Tab_SAV)
|
|
|
|
|
{
|
|
|
|
|
RequestReloadSave?.Invoke(sender, e);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (tabBoxMulti.SelectedTab != Tab_Box)
|
|
|
|
|
return;
|
|
|
|
|
if (!SAV.HasBox)
|
|
|
|
|
return;
|
2018-01-23 05:38:42 +00:00
|
|
|
|
if (ModifierKeys == Keys.Shift)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
|
|
|
|
if (M.Boxes.Count > 1) // subview open
|
2018-01-23 05:38:42 +00:00
|
|
|
|
{
|
|
|
|
|
// close all subviews
|
|
|
|
|
for (int i = 1; i < M.Boxes.Count; i++)
|
2018-07-07 18:20:05 +00:00
|
|
|
|
M.Boxes[i].ParentForm?.Close();
|
2018-01-23 05:38:42 +00:00
|
|
|
|
}
|
|
|
|
|
new SAV_BoxList(this, M).Show();
|
|
|
|
|
return;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
2018-01-23 05:38:42 +00:00
|
|
|
|
if (M.Boxes.Count > 1) // subview open
|
2019-10-26 19:58:55 +00:00
|
|
|
|
{
|
|
|
|
|
var z = M.Boxes[1].ParentForm;
|
|
|
|
|
if (z == null)
|
|
|
|
|
return;
|
|
|
|
|
z.CenterToForm(ParentForm);
|
|
|
|
|
z.BringToFront();
|
|
|
|
|
return;
|
|
|
|
|
}
|
2017-05-23 04:55:05 +00:00
|
|
|
|
new SAV_BoxViewer(this, M).Show();
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
private void ClickClone(object sender, EventArgs e)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
2019-12-07 23:15:35 +00:00
|
|
|
|
var detail = Box.GetSlotData((PictureBox) sender);
|
2019-12-07 21:56:00 +00:00
|
|
|
|
if (detail is SlotInfoBox)
|
2019-09-03 02:30:58 +00:00
|
|
|
|
RequestCloneData?.Invoke(sender, e);
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
private void UpdateSaveSlot(object sender, EventArgs e)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
2020-12-23 05:24:41 +00:00
|
|
|
|
if (SAV is not SAV4BR br)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
return;
|
2019-09-03 02:30:58 +00:00
|
|
|
|
br.CurrentSlot = WinFormsUtil.GetIndex(CB_SaveSlot);
|
2018-05-23 02:02:56 +00:00
|
|
|
|
Box.ResetBoxNames(); // fix box names
|
2017-06-18 01:37:19 +00:00
|
|
|
|
SetPKMBoxes();
|
2018-05-19 23:39:01 +00:00
|
|
|
|
UpdateBoxViewers(true);
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
private void UpdateStringSeed(object sender, EventArgs e)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
|
|
|
|
if (!FieldsLoaded)
|
|
|
|
|
return;
|
|
|
|
|
|
2020-12-23 05:24:41 +00:00
|
|
|
|
if (sender is not TextBox tb)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2018-07-07 18:20:05 +00:00
|
|
|
|
if (string.IsNullOrWhiteSpace(tb.Text))
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
|
|
|
|
tb.Undo();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
string filterText = Util.GetOnlyHex(tb.Text);
|
2019-02-02 07:08:03 +00:00
|
|
|
|
if (string.IsNullOrWhiteSpace(filterText) || filterText.Length != tb.Text.Length)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
2018-04-06 04:25:18 +00:00
|
|
|
|
WinFormsUtil.Alert(MsgProgramErrorExpectedHex, tb.Text);
|
2017-05-23 04:55:05 +00:00
|
|
|
|
tb.Undo();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Write final value back to the save
|
|
|
|
|
if (tb == TB_RNGSeed)
|
|
|
|
|
{
|
|
|
|
|
var value = filterText.PadLeft(SAV.DaycareSeedSize, '0');
|
2017-06-18 01:37:19 +00:00
|
|
|
|
SAV.SetDaycareRNGSeed(SAV.DaycareIndex, value);
|
2020-12-05 13:36:23 +00:00
|
|
|
|
SAV.State.Edited = true;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
2020-10-31 18:43:57 +00:00
|
|
|
|
else if (tb == TB_GameSync && SAV is IGameSync sync)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
2020-10-31 18:43:57 +00:00
|
|
|
|
var value = filterText.PadLeft(sync.GameSyncIDSize, '0');
|
|
|
|
|
sync.GameSyncID = value;
|
2020-12-05 13:36:23 +00:00
|
|
|
|
SAV.State.Edited = true;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
2018-12-19 01:15:35 +00:00
|
|
|
|
else if (SAV is ISecureValueStorage s)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
|
|
|
|
var value = Convert.ToUInt64(filterText, 16);
|
|
|
|
|
if (tb == TB_Secure1)
|
2018-12-19 01:15:35 +00:00
|
|
|
|
s.TimeStampCurrent = value;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
else if (tb == TB_Secure2)
|
2018-12-19 01:15:35 +00:00
|
|
|
|
s.TimeStampPrevious = value;
|
2020-12-05 13:36:23 +00:00
|
|
|
|
SAV.State.Edited = true;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
private void SwitchDaycare(object sender, EventArgs e)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
2018-05-20 03:48:03 +00:00
|
|
|
|
if (!SAV.HasTwoDaycares)
|
|
|
|
|
return;
|
|
|
|
|
var current = string.Format(MsgSaveSwitchDaycareCurrent, SAV.DaycareIndex + 1);
|
|
|
|
|
if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MsgSaveSwitchDaycareView, current))
|
|
|
|
|
return;
|
|
|
|
|
SAV.DaycareIndex ^= 1;
|
|
|
|
|
ResetDaycare();
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-05-23 04:55:05 +00:00
|
|
|
|
private void B_SaveBoxBin_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (!SAV.HasBox)
|
2018-04-07 04:23:09 +00:00
|
|
|
|
{ WinFormsUtil.Alert(MsgSaveBoxFailNone); return; }
|
2017-05-23 04:55:05 +00:00
|
|
|
|
Box.SaveBoxBinary();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Subfunction Save Buttons //
|
2020-10-04 01:59:36 +00:00
|
|
|
|
private static void OpenDialog(Form f)
|
|
|
|
|
{
|
|
|
|
|
f.ShowDialog();
|
|
|
|
|
f.Dispose();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void B_OpenWondercards_Click(object sender, EventArgs e) => OpenDialog(new SAV_Wondercard(SAV, sender as DataMysteryGift));
|
|
|
|
|
private void B_OpenPokepuffs_Click(object sender, EventArgs e) => OpenDialog(new SAV_Pokepuff(SAV));
|
|
|
|
|
private void B_OpenPokeBeans_Click(object sender, EventArgs e) => OpenDialog(new SAV_Pokebean(SAV));
|
|
|
|
|
private void B_OpenItemPouch_Click(object sender, EventArgs e) => OpenDialog(new SAV_Inventory(SAV));
|
|
|
|
|
private void B_OpenBerryField_Click(object sender, EventArgs e) => OpenDialog(new SAV_BerryFieldXY((SAV6XY)SAV));
|
|
|
|
|
private void B_OpenPokeblocks_Click(object sender, EventArgs e) => OpenDialog(new SAV_PokeBlockORAS(SAV));
|
|
|
|
|
private void B_OpenSuperTraining_Click(object sender, EventArgs e) => OpenDialog(new SAV_SuperTrain(SAV));
|
|
|
|
|
private void B_OpenSecretBase_Click(object sender, EventArgs e) => OpenDialog(new SAV_SecretBase(SAV));
|
|
|
|
|
private void B_CellsStickers_Click(object sender, EventArgs e) => OpenDialog(new SAV_ZygardeCell(SAV));
|
|
|
|
|
private void B_LinkInfo_Click(object sender, EventArgs e) => OpenDialog(new SAV_Link6(SAV));
|
|
|
|
|
private void B_Roamer_Click(object sender, EventArgs e) => OpenDialog(new SAV_Roamer3(SAV));
|
|
|
|
|
private void B_OpenApricorn_Click(object sender, EventArgs e) => OpenDialog(new SAV_Apricorn((SAV4HGSS)SAV));
|
|
|
|
|
private void B_CGearSkin_Click(object sender, EventArgs e) => OpenDialog(new SAV_CGearSkin(SAV));
|
|
|
|
|
private void B_OpenTrainerInfo_Click(object sender, EventArgs e) => OpenDialog(GetTrainerEditor(SAV));
|
|
|
|
|
private void B_OpenOPowers_Click(object sender, EventArgs e) => OpenDialog(new SAV_OPower((ISaveBlock6Main)SAV));
|
|
|
|
|
private void B_OpenHoneyTreeEditor_Click(object sender, EventArgs e) => OpenDialog(new SAV_HoneyTree((SAV4Sinnoh)SAV));
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-09-26 06:06:16 +00:00
|
|
|
|
private void B_OpenEventFlags_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
2019-10-08 01:40:09 +00:00
|
|
|
|
using var form = SAV switch
|
2018-11-14 03:23:31 +00:00
|
|
|
|
{
|
2019-10-08 01:40:09 +00:00
|
|
|
|
SAV1 s => (Form) new SAV_EventReset1(s),
|
|
|
|
|
SAV7b s => new SAV_EventWork(s),
|
2021-11-20 02:23:49 +00:00
|
|
|
|
SAV8BS s => new SAV_FlagWork8b(s),
|
2022-04-10 01:12:57 +00:00
|
|
|
|
IEventFlag37 g37 => new SAV_EventFlags(g37),
|
|
|
|
|
SAV2 s => new SAV_EventFlags2(s),
|
|
|
|
|
_ => throw new Exception(),
|
2019-10-08 01:40:09 +00:00
|
|
|
|
};
|
2017-09-26 06:06:16 +00:00
|
|
|
|
form.ShowDialog();
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-05-23 04:55:05 +00:00
|
|
|
|
private void B_OpenBoxLayout_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
2020-10-04 01:59:36 +00:00
|
|
|
|
OpenDialog(new SAV_BoxLayout(SAV, Box.CurrentBox));
|
2017-05-23 04:55:05 +00:00
|
|
|
|
Box.ResetBoxNames(); // fix box names
|
|
|
|
|
Box.ResetSlots(); // refresh box background
|
2017-06-18 01:37:19 +00:00
|
|
|
|
UpdateBoxViewers(all: true); // update subviewers
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2021-01-02 01:08:49 +00:00
|
|
|
|
private static Form GetTrainerEditor(SaveFile sav) => sav switch
|
2019-09-23 23:56:47 +00:00
|
|
|
|
{
|
2021-01-02 01:08:49 +00:00
|
|
|
|
SAV6 s6 => new SAV_Trainer(s6),
|
|
|
|
|
SAV7 s7 => new SAV_Trainer7(s7),
|
|
|
|
|
SAV7b b7 => new SAV_Trainer7GG(b7),
|
|
|
|
|
SAV8SWSH swsh => new SAV_Trainer8(swsh),
|
2021-11-20 18:34:20 +00:00
|
|
|
|
SAV8BS bs => new SAV_Trainer8b(bs),
|
2022-02-05 01:36:51 +00:00
|
|
|
|
SAV8LA la => new SAV_Trainer8a(la),
|
2021-08-20 20:49:20 +00:00
|
|
|
|
_ => new SAV_SimpleTrainer(sav),
|
2021-01-02 01:08:49 +00:00
|
|
|
|
};
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2019-12-24 07:30:21 +00:00
|
|
|
|
private void B_OpenRaids_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
2020-12-23 05:24:41 +00:00
|
|
|
|
if (SAV is not SAV8SWSH swsh)
|
2019-12-24 07:30:21 +00:00
|
|
|
|
return;
|
2020-10-24 18:09:29 +00:00
|
|
|
|
if (sender == B_Raids)
|
|
|
|
|
OpenDialog(new SAV_Raid8(swsh, swsh.Raid));
|
|
|
|
|
else if (sender == B_RaidArmor)
|
|
|
|
|
OpenDialog(new SAV_Raid8(swsh, swsh.RaidArmor));
|
|
|
|
|
else
|
|
|
|
|
OpenDialog(new SAV_Raid8(swsh, swsh.RaidCrown));
|
2019-12-24 07:30:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-10-04 01:22:29 +00:00
|
|
|
|
private void B_OtherSlots_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
void TryOpen(SaveFile sav, IReadOnlyList<SlotGroup> g)
|
|
|
|
|
{
|
|
|
|
|
var form = WinFormsUtil.FirstFormOfType<SAV_GroupViewer>();
|
|
|
|
|
if (form != null)
|
|
|
|
|
form.CenterToForm(ParentForm);
|
|
|
|
|
else
|
|
|
|
|
form = new SAV_GroupViewer(sav, M.Env.PKMEditor, g);
|
|
|
|
|
form.BringToFront();
|
|
|
|
|
form.Show();
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-04 16:26:15 +00:00
|
|
|
|
if (SAV is SAV_STADIUM s0)
|
2020-10-04 01:22:29 +00:00
|
|
|
|
TryOpen(s0, s0.GetRegisteredTeams());
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-14 03:04:21 +00:00
|
|
|
|
private void B_Blocks_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
2020-04-26 23:23:06 +00:00
|
|
|
|
var form = GetAccessorForm(SAV);
|
2020-01-14 03:04:21 +00:00
|
|
|
|
form.ShowDialog();
|
2020-04-26 23:23:06 +00:00
|
|
|
|
form.Dispose();
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-02 01:08:49 +00:00
|
|
|
|
private static Form GetAccessorForm(SaveFile sav) => sav switch
|
2020-04-26 23:23:06 +00:00
|
|
|
|
{
|
2021-03-14 23:14:15 +00:00
|
|
|
|
SAV5BW s => new SAV_Accessor<SaveBlockAccessor5BW>(s, s.Blocks),
|
|
|
|
|
SAV5B2W2 s => new SAV_Accessor<SaveBlockAccessor5B2W2>(s, s.Blocks),
|
|
|
|
|
SAV6XY s => new SAV_Accessor<SaveBlockAccessor6XY>(s, s.Blocks),
|
|
|
|
|
SAV6AO s => new SAV_Accessor<SaveBlockAccessor6AO>(s, s.Blocks),
|
|
|
|
|
SAV6AODemo s => new SAV_Accessor<SaveBlockAccessor6AODemo>(s, s.Blocks),
|
|
|
|
|
SAV7SM s => new SAV_Accessor<SaveBlockAccessor7SM>(s, s.Blocks),
|
|
|
|
|
SAV7USUM s => new SAV_Accessor<SaveBlockAccessor7USUM>(s, s.Blocks),
|
2021-09-16 21:06:52 +00:00
|
|
|
|
SAV7b s => new SAV_Accessor<SaveBlockAccessor7b>(s, s.Blocks),
|
2022-02-05 01:36:51 +00:00
|
|
|
|
ISCBlockArray s => new SAV_BlockDump8(s),
|
2021-01-02 01:08:49 +00:00
|
|
|
|
_ => GetPropertyForm(sav),
|
|
|
|
|
};
|
2020-04-26 23:23:06 +00:00
|
|
|
|
|
2020-10-04 01:59:36 +00:00
|
|
|
|
private static Form GetPropertyForm(object sav)
|
2020-04-26 23:23:06 +00:00
|
|
|
|
{
|
|
|
|
|
var form = new Form
|
|
|
|
|
{
|
|
|
|
|
Text = "Simple Editor",
|
2021-01-10 07:27:22 +00:00
|
|
|
|
StartPosition = FormStartPosition.CenterParent,
|
2020-04-26 23:23:06 +00:00
|
|
|
|
MinimumSize = new Size(350, 380),
|
|
|
|
|
MinimizeBox = false,
|
2021-08-20 20:49:20 +00:00
|
|
|
|
MaximizeBox = false,
|
2021-11-28 16:19:33 +00:00
|
|
|
|
Icon = Properties.Resources.Icon,
|
2020-04-26 23:23:06 +00:00
|
|
|
|
};
|
|
|
|
|
var pg = new PropertyGrid {SelectedObject = sav, Dock = DockStyle.Fill};
|
|
|
|
|
form.Controls.Add(pg);
|
|
|
|
|
return form;
|
2020-01-14 03:04:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-05-23 04:55:05 +00:00
|
|
|
|
private void B_OpenFriendSafari_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
2020-12-23 05:24:41 +00:00
|
|
|
|
if (SAV is not SAV6XY xy)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2018-04-06 04:25:18 +00:00
|
|
|
|
var dr = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MsgSaveGen6FriendSafari, MsgSaveGen6FriendSafariCheatDesc);
|
2018-07-07 18:20:05 +00:00
|
|
|
|
if (dr == DialogResult.Yes)
|
2019-06-09 02:56:11 +00:00
|
|
|
|
xy.UnlockAllFriendSafariSlots();
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
2018-07-07 18:20:05 +00:00
|
|
|
|
|
|
|
|
|
private void B_OpenPokedex_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
2019-10-08 01:40:09 +00:00
|
|
|
|
using var form = SAV switch
|
|
|
|
|
{
|
|
|
|
|
SAV1 s1 => new SAV_SimplePokedex(s1),
|
|
|
|
|
SAV2 s2 => new SAV_SimplePokedex(s2),
|
|
|
|
|
SAV3 s3 => new SAV_SimplePokedex(s3),
|
|
|
|
|
SAV4 s4 => new SAV_Pokedex4(s4),
|
|
|
|
|
SAV5 s5 => new SAV_Pokedex5(s5),
|
|
|
|
|
SAV6XY xy => new SAV_PokedexXY(xy),
|
|
|
|
|
SAV6AO ao => new SAV_PokedexORAS(ao),
|
|
|
|
|
SAV7 s7 => new SAV_PokedexSM(s7),
|
|
|
|
|
SAV7b b7 => new SAV_PokedexGG(b7),
|
|
|
|
|
SAV8SWSH swsh => new SAV_PokedexSWSH(swsh),
|
2021-11-20 02:23:49 +00:00
|
|
|
|
SAV8BS bs => new SAV_PokedexBDSP(bs),
|
2022-02-05 01:36:51 +00:00
|
|
|
|
SAV8LA la => new SAV_PokedexLA(la),
|
2021-08-20 20:49:20 +00:00
|
|
|
|
_ => (Form?)null,
|
2019-10-08 01:40:09 +00:00
|
|
|
|
};
|
|
|
|
|
form?.ShowDialog();
|
2018-07-07 18:20:05 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-05-23 04:55:05 +00:00
|
|
|
|
private void B_OpenMiscEditor_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
2019-10-08 01:40:09 +00:00
|
|
|
|
using var form = SAV.Generation switch
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
2019-10-08 01:40:09 +00:00
|
|
|
|
3 => new SAV_Misc3(SAV),
|
|
|
|
|
4 => new SAV_Misc4((SAV4) SAV),
|
|
|
|
|
5 => new SAV_Misc5(SAV),
|
2021-11-26 06:48:09 +00:00
|
|
|
|
8 when SAV is SAV8BS bs => new SAV_Misc8b(bs),
|
2020-10-18 18:02:39 +00:00
|
|
|
|
_ => (Form?)null,
|
2019-10-08 01:40:09 +00:00
|
|
|
|
};
|
|
|
|
|
form?.ShowDialog();
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-05-23 04:55:05 +00:00
|
|
|
|
private void B_OpenRTCEditor_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
switch (SAV.Generation)
|
|
|
|
|
{
|
2017-09-24 05:13:48 +00:00
|
|
|
|
case 2:
|
2019-03-30 19:34:51 +00:00
|
|
|
|
var sav2 = ((SAV2) SAV);
|
2019-03-31 23:59:01 +00:00
|
|
|
|
var msg = MsgSaveGen2RTCResetBitflag;
|
|
|
|
|
if (!sav2.Japanese) // show Reset Key for non-Japanese saves
|
|
|
|
|
msg = string.Format(MsgSaveGen2RTCResetPassword, sav2.ResetKey) + Environment.NewLine + Environment.NewLine + msg;
|
|
|
|
|
var dr = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, msg);
|
2019-03-30 19:34:51 +00:00
|
|
|
|
if (dr == DialogResult.Yes)
|
|
|
|
|
sav2.ResetRTC();
|
|
|
|
|
break;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
case 3:
|
2020-10-04 01:59:36 +00:00
|
|
|
|
OpenDialog(new SAV_RTC3(SAV));
|
2019-10-08 01:40:09 +00:00
|
|
|
|
break;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-05-23 04:55:05 +00:00
|
|
|
|
private void B_OUTPasserby_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (SAV.Generation != 6)
|
|
|
|
|
return;
|
2018-04-06 04:25:18 +00:00
|
|
|
|
if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MsgSaveGen6Passerby))
|
2017-05-23 04:55:05 +00:00
|
|
|
|
return;
|
2018-07-07 18:20:05 +00:00
|
|
|
|
var result = PSS6.GetPSSParse((SAV6)SAV);
|
2019-11-23 05:23:00 +00:00
|
|
|
|
WinFormsUtil.SetClipboardText(string.Join(Environment.NewLine, result));
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-05-23 04:55:05 +00:00
|
|
|
|
private void B_OUTHallofFame_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
2019-10-08 01:40:09 +00:00
|
|
|
|
using var form = SAV switch
|
|
|
|
|
{
|
|
|
|
|
SAV6 s6 => new SAV_HallOfFame(s6),
|
|
|
|
|
SAV7 s7 => new SAV_HallOfFame7(s7),
|
2020-10-18 18:02:39 +00:00
|
|
|
|
_ => (Form?)null,
|
2019-10-08 01:40:09 +00:00
|
|
|
|
};
|
|
|
|
|
form?.ShowDialog();
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-05-23 04:55:05 +00:00
|
|
|
|
private void B_JPEG_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
2019-07-06 05:02:29 +00:00
|
|
|
|
var s6 = (SAV6)SAV;
|
2020-12-05 14:09:33 +00:00
|
|
|
|
byte[] jpeg = s6.GetJPEGData();
|
|
|
|
|
if (jpeg.Length == 0)
|
2019-02-02 07:26:43 +00:00
|
|
|
|
{
|
|
|
|
|
WinFormsUtil.Alert(MsgSaveJPEGExportFail);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-07-06 05:02:29 +00:00
|
|
|
|
string filename = $"{s6.JPEGTitle}'s picture";
|
2019-10-08 01:40:09 +00:00
|
|
|
|
using var sfd = new SaveFileDialog { FileName = filename, Filter = "JPEG|*.jpeg" };
|
2019-02-02 07:26:43 +00:00
|
|
|
|
if (sfd.ShowDialog() != DialogResult.OK)
|
|
|
|
|
return;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
File.WriteAllBytes(sfd.FileName, jpeg);
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
private void ClickVerifyCHK(object sender, EventArgs e)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
2020-12-05 13:36:23 +00:00
|
|
|
|
if (SAV.State.Edited)
|
2019-04-14 16:08:33 +00:00
|
|
|
|
{
|
|
|
|
|
WinFormsUtil.Alert(MsgSaveChecksumFailEdited);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (SAV.ChecksumsValid)
|
|
|
|
|
{
|
|
|
|
|
WinFormsUtil.Alert(MsgSaveChecksumValid);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2017-05-23 04:55:05 +00:00
|
|
|
|
|
2018-04-06 04:25:18 +00:00
|
|
|
|
if (DialogResult.Yes == WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MsgSaveChecksumFailExport))
|
2019-11-23 05:23:00 +00:00
|
|
|
|
WinFormsUtil.SetClipboardText(SAV.ChecksumInfo);
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
2018-02-02 01:29:07 +00:00
|
|
|
|
|
2022-02-22 01:46:32 +00:00
|
|
|
|
private void ClickVerifyStoredEntities(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
var bulk = new BulkAnalysis(SAV);
|
|
|
|
|
if (bulk.Parse.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
WinFormsUtil.Alert("Clean!");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MsgClipboardLegalityExport) != DialogResult.Yes)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
var lines = bulk.Parse.Select(z => $"{z.Judgement}: {z.Comment}");
|
|
|
|
|
var msg = string.Join(Environment.NewLine, lines);
|
|
|
|
|
WinFormsUtil.SetClipboardText(msg);
|
|
|
|
|
SystemSounds.Asterisk.Play();
|
|
|
|
|
}
|
|
|
|
|
|
2017-05-23 04:55:05 +00:00
|
|
|
|
// File I/O
|
2019-03-30 00:52:26 +00:00
|
|
|
|
public bool GetBulkImportSettings(out bool clearAll, out bool overwrite, out PKMImportSetting noSetb)
|
2018-02-02 01:29:07 +00:00
|
|
|
|
{
|
2019-03-30 00:52:26 +00:00
|
|
|
|
clearAll = false; noSetb = PKMImportSetting.UseDefault; overwrite = false;
|
2018-04-06 04:25:18 +00:00
|
|
|
|
var dr = WinFormsUtil.Prompt(MessageBoxButtons.YesNoCancel, MsgSaveBoxImportClear, MsgSaveBoxImportClearNo);
|
2018-02-02 01:29:07 +00:00
|
|
|
|
if (dr == DialogResult.Cancel)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
clearAll = dr == DialogResult.Yes;
|
2018-09-03 01:02:25 +00:00
|
|
|
|
noSetb = GetPKMSetOverride(ModifyPKM);
|
2018-02-02 01:29:07 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
private static bool IsFolderPath(out string path)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
2019-10-08 01:40:09 +00:00
|
|
|
|
using var fbd = new FolderBrowserDialog();
|
2017-05-23 04:55:05 +00:00
|
|
|
|
var result = fbd.ShowDialog() == DialogResult.OK;
|
|
|
|
|
path = fbd.SelectedPath;
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool ExportSaveFile()
|
|
|
|
|
{
|
|
|
|
|
ValidateChildren();
|
2018-11-15 06:20:59 +00:00
|
|
|
|
bool reload = SAV is SAV7b b && b.FixPreWrite();
|
|
|
|
|
if (reload)
|
|
|
|
|
ReloadSlots();
|
2019-07-14 22:06:45 +00:00
|
|
|
|
return WinFormsUtil.ExportSAVDialog(SAV, SAV.CurrentBox);
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-05-23 04:55:05 +00:00
|
|
|
|
public bool ExportBackup()
|
|
|
|
|
{
|
2022-02-10 00:48:55 +00:00
|
|
|
|
if (!SAV.State.Exportable || SAV.Metadata.FilePath is not { } file)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
return false;
|
2022-02-24 05:53:01 +00:00
|
|
|
|
|
|
|
|
|
if (!File.Exists(file))
|
|
|
|
|
{
|
|
|
|
|
WinFormsUtil.Error(MsgSaveBackupNotFound, file);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var suggestion = Util.CleanFileName(SAV.Metadata.BAKName);
|
|
|
|
|
using var sfd = new SaveFileDialog {FileName = suggestion};
|
2017-05-23 04:55:05 +00:00
|
|
|
|
if (sfd.ShowDialog() != DialogResult.OK)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
string path = sfd.FileName;
|
2022-02-24 05:53:01 +00:00
|
|
|
|
if (!File.Exists(file)) // did they move it again?
|
|
|
|
|
{
|
|
|
|
|
WinFormsUtil.Error(MsgSaveBackupNotFound, file);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2022-02-10 00:48:55 +00:00
|
|
|
|
File.Copy(file, path);
|
2018-04-06 04:25:18 +00:00
|
|
|
|
WinFormsUtil.Alert(MsgSaveBackup, path);
|
2017-05-23 04:55:05 +00:00
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-05-23 04:55:05 +00:00
|
|
|
|
public bool OpenPCBoxBin(byte[] input, out string c)
|
|
|
|
|
{
|
2019-10-04 00:45:19 +00:00
|
|
|
|
if (SAV.GetPCBinary().Length == input.Length)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
2017-06-18 01:37:19 +00:00
|
|
|
|
if (SAV.IsAnySlotLockedInBox(0, SAV.BoxCount - 1))
|
2018-04-06 04:25:18 +00:00
|
|
|
|
{ c = MsgSaveBoxImportPCFailBattle; return false; }
|
2017-06-18 01:37:19 +00:00
|
|
|
|
if (!SAV.SetPCBinary(input))
|
2018-04-06 04:25:18 +00:00
|
|
|
|
{ c = string.Format(MsgSaveCurrentGeneration, SAV.Generation); return false; }
|
2017-05-23 04:55:05 +00:00
|
|
|
|
|
2018-04-06 04:25:18 +00:00
|
|
|
|
c = MsgSaveBoxImportPCBinary;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
2017-06-18 01:37:19 +00:00
|
|
|
|
else if (SAV.GetBoxBinary(Box.CurrentBox).Length == input.Length)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
2017-06-18 01:37:19 +00:00
|
|
|
|
if (SAV.IsAnySlotLockedInBox(Box.CurrentBox, Box.CurrentBox))
|
2018-04-06 04:25:18 +00:00
|
|
|
|
{ c = MsgSaveBoxImportBoxFailBattle; return false; }
|
2017-06-18 01:37:19 +00:00
|
|
|
|
if (!SAV.SetBoxBinary(input, Box.CurrentBox))
|
2018-04-06 04:25:18 +00:00
|
|
|
|
{ c = string.Format(MsgSaveCurrentGeneration, SAV.Generation); return false; }
|
2017-05-23 04:55:05 +00:00
|
|
|
|
|
2018-04-06 04:25:18 +00:00
|
|
|
|
c = MsgSaveBoxImportBoxBinary;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-04-06 04:25:18 +00:00
|
|
|
|
c = string.Format(MsgSaveCurrentGeneration, SAV.Generation);
|
2017-05-23 04:55:05 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2017-06-18 01:37:19 +00:00
|
|
|
|
SetPKMBoxes();
|
|
|
|
|
UpdateBoxViewers();
|
2017-05-23 04:55:05 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2020-11-04 04:12:42 +00:00
|
|
|
|
public bool OpenGroup(IPokeGroup b, out string c)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
2020-11-04 04:12:42 +00:00
|
|
|
|
var msg = string.Format(MsgSaveBoxImportGroup, Box.CurrentBoxName);
|
|
|
|
|
var prompt = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, msg, MsgSaveBoxImportOverwrite);
|
2017-05-23 04:55:05 +00:00
|
|
|
|
if (prompt != DialogResult.Yes)
|
|
|
|
|
{
|
|
|
|
|
c = string.Empty;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-30 00:52:26 +00:00
|
|
|
|
var noSetb = GetPKMSetOverride(ModifyPKM);
|
2020-11-04 04:12:42 +00:00
|
|
|
|
var slotSkipped = ImportGroup(b.Contents, SAV, Box.CurrentBox, noSetb);
|
|
|
|
|
|
|
|
|
|
SetPKMBoxes();
|
|
|
|
|
UpdateBoxViewers();
|
|
|
|
|
|
|
|
|
|
c = slotSkipped > 0 ? string.Format(MsgSaveBoxImportSkippedLocked, slotSkipped) : MsgSaveBoxImportGroupSuccess;
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static int ImportGroup(IEnumerable<PKM> data, SaveFile sav, int box, PKMImportSetting noSetb)
|
|
|
|
|
{
|
|
|
|
|
var type = sav.PKMType;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
int slotSkipped = 0;
|
2020-11-04 04:12:42 +00:00
|
|
|
|
int index = 0;
|
|
|
|
|
foreach (var x in data)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
2020-11-04 04:12:42 +00:00
|
|
|
|
var i = index++;
|
|
|
|
|
if (sav.IsSlotOverwriteProtected(box, i))
|
2019-09-03 02:30:58 +00:00
|
|
|
|
{
|
|
|
|
|
slotSkipped++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2017-05-23 04:55:05 +00:00
|
|
|
|
|
2022-04-09 08:39:34 +00:00
|
|
|
|
var convert = EntityConverter.ConvertToType(x, type, out _);
|
2020-11-04 04:12:42 +00:00
|
|
|
|
if (convert?.GetType() != type)
|
|
|
|
|
{
|
|
|
|
|
slotSkipped++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
sav.SetBoxSlotAtIndex(x, box, i, noSetb);
|
|
|
|
|
}
|
2017-05-23 04:55:05 +00:00
|
|
|
|
|
2020-11-04 04:12:42 +00:00
|
|
|
|
return slotSkipped;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2020-10-18 18:02:39 +00:00
|
|
|
|
public bool DumpBoxes(out string result, string? path = null, bool separate = false)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
2017-06-18 01:37:19 +00:00
|
|
|
|
if (path == null && !IsFolderPath(out path))
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
|
|
|
|
result = path;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-03 06:13:40 +00:00
|
|
|
|
Directory.CreateDirectory(path);
|
2017-05-23 04:55:05 +00:00
|
|
|
|
|
2019-02-10 04:19:55 +00:00
|
|
|
|
var count = SAV.DumpBoxes(path, separate);
|
|
|
|
|
if (count < 0)
|
|
|
|
|
result = MsgSaveBoxExportInvalid;
|
|
|
|
|
else
|
|
|
|
|
result = string.Format(MsgSaveBoxExportPathCount, count) + Environment.NewLine + path;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2020-10-18 18:02:39 +00:00
|
|
|
|
public bool DumpBox(out string result, string? path = null)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
2017-06-18 01:37:19 +00:00
|
|
|
|
if (path == null && !IsFolderPath(out path))
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
|
|
|
|
result = path;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-03 06:13:40 +00:00
|
|
|
|
Directory.CreateDirectory(path);
|
2017-05-23 04:55:05 +00:00
|
|
|
|
|
2019-02-10 04:19:55 +00:00
|
|
|
|
var count = SAV.DumpBox(path, Box.CurrentBox);
|
|
|
|
|
if (count < 0)
|
|
|
|
|
result = MsgSaveBoxExportInvalid;
|
|
|
|
|
else
|
|
|
|
|
result = string.Format(MsgSaveBoxExportPathCount, count) + Environment.NewLine + path;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2020-10-18 18:02:39 +00:00
|
|
|
|
public bool LoadBoxes(out string result, string? path = null)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
|
|
|
|
result = string.Empty;
|
|
|
|
|
if (!SAV.HasBox)
|
|
|
|
|
return false;
|
|
|
|
|
|
2017-06-18 01:37:19 +00:00
|
|
|
|
if (path == null && !IsFolderPath(out path))
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
|
|
|
|
result = path;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!Directory.Exists(path))
|
|
|
|
|
return false;
|
|
|
|
|
|
2018-12-29 01:58:13 +00:00
|
|
|
|
if (!GetBulkImportSettings(out bool clearAll, out var overwrite, out var noSetb))
|
2017-05-23 04:55:05 +00:00
|
|
|
|
return false;
|
|
|
|
|
|
2018-12-29 01:58:13 +00:00
|
|
|
|
SAV.LoadBoxes(path, out result, Box.CurrentBox, clearAll, overwrite, noSetb);
|
2017-06-18 01:37:19 +00:00
|
|
|
|
SetPKMBoxes();
|
2017-08-27 01:37:44 +00:00
|
|
|
|
UpdateBoxViewers();
|
2017-05-23 04:55:05 +00:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool ToggleInterface()
|
|
|
|
|
{
|
|
|
|
|
FieldsLoaded = false;
|
|
|
|
|
|
2017-06-19 05:27:40 +00:00
|
|
|
|
ToggleViewReset();
|
|
|
|
|
ToggleViewSubEditors(SAV);
|
|
|
|
|
|
|
|
|
|
bool WindowTranslationRequired = false;
|
|
|
|
|
WindowTranslationRequired |= ToggleViewBox(SAV);
|
2017-12-30 00:50:55 +00:00
|
|
|
|
int BoxTab = tabBoxMulti.TabPages.IndexOf(Tab_Box);
|
2017-06-19 05:27:40 +00:00
|
|
|
|
WindowTranslationRequired |= ToggleViewParty(SAV, BoxTab);
|
2017-12-30 00:50:55 +00:00
|
|
|
|
int PartyTab = tabBoxMulti.TabPages.IndexOf(Tab_PartyBattle);
|
2017-06-19 05:27:40 +00:00
|
|
|
|
WindowTranslationRequired |= ToggleViewDaycare(SAV, BoxTab, PartyTab);
|
2017-09-22 04:42:27 +00:00
|
|
|
|
SetPKMBoxes(); // Reload all of the PKX Windows
|
2017-06-19 05:27:40 +00:00
|
|
|
|
|
|
|
|
|
ToggleViewMisc(SAV);
|
|
|
|
|
|
|
|
|
|
FieldsLoaded = true;
|
|
|
|
|
return WindowTranslationRequired;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-06-19 05:27:40 +00:00
|
|
|
|
private void ToggleViewReset()
|
|
|
|
|
{
|
2017-05-23 04:55:05 +00:00
|
|
|
|
// Close subforms that are save dependent
|
|
|
|
|
foreach (var z in M.Boxes.Skip(1).ToArray())
|
|
|
|
|
z.FindForm()?.Close();
|
|
|
|
|
|
|
|
|
|
Box.M = M;
|
2019-11-16 01:34:18 +00:00
|
|
|
|
SL_Party.M = M;
|
|
|
|
|
if (SAV.HasBox)
|
|
|
|
|
{
|
|
|
|
|
bool newSlots = Box.InitializeFromSAV(SAV);
|
|
|
|
|
if (newSlots)
|
|
|
|
|
{
|
|
|
|
|
Box.HorizontallyCenter(Tab_Box);
|
|
|
|
|
foreach (var pb in Box.SlotPictureBoxes)
|
|
|
|
|
pb.ContextMenuStrip = menu.mnuVSD;
|
2019-11-17 05:03:24 +00:00
|
|
|
|
|
|
|
|
|
var grid = Box.BoxPokeGrid;
|
|
|
|
|
var height = grid.Height + grid.Location.Y + Box.Location.Y; // needed height
|
|
|
|
|
var required = height + 16;
|
|
|
|
|
var allowed = Tab_Box.Height;
|
|
|
|
|
if (required > allowed)
|
2021-05-29 22:31:47 +00:00
|
|
|
|
{
|
|
|
|
|
var form = FindForm();
|
|
|
|
|
if (form != null)
|
|
|
|
|
form.Height += required - allowed;
|
|
|
|
|
}
|
2019-11-16 01:34:18 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (SAV.HasParty)
|
2019-10-03 03:04:12 +00:00
|
|
|
|
{
|
2019-11-16 01:34:18 +00:00
|
|
|
|
bool newSlots = SL_Party.InitializeFromSAV(SAV);
|
|
|
|
|
if (newSlots)
|
|
|
|
|
{
|
|
|
|
|
SL_Party.HorizontallyCenter(Tab_PartyBattle);
|
|
|
|
|
foreach (var pb in SL_Party.SlotPictureBoxes)
|
|
|
|
|
pb.ContextMenuStrip = menu.mnuVSD;
|
|
|
|
|
}
|
2019-10-03 03:04:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-05-24 01:29:30 +00:00
|
|
|
|
SortMenu.ToggleVisibility();
|
2017-06-19 05:27:40 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-06-19 05:27:40 +00:00
|
|
|
|
private bool ToggleViewBox(SaveFile sav)
|
|
|
|
|
{
|
|
|
|
|
if (!sav.HasBox)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
2017-06-19 05:27:40 +00:00
|
|
|
|
if (tabBoxMulti.TabPages.Contains(Tab_Box))
|
|
|
|
|
tabBoxMulti.TabPages.Remove(Tab_Box);
|
|
|
|
|
B_SaveBoxBin.Enabled = false;
|
|
|
|
|
return false;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
2017-06-19 05:27:40 +00:00
|
|
|
|
|
|
|
|
|
B_SaveBoxBin.Enabled = true;
|
2019-11-16 01:34:18 +00:00
|
|
|
|
tabBoxMulti.SelectedIndex = 0;
|
2019-11-17 05:21:02 +00:00
|
|
|
|
|
|
|
|
|
var box = sav.CurrentBox;
|
|
|
|
|
Box.CurrentBox = (uint)box >= sav.BoxCount ? 0 : box;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
|
2017-06-19 05:27:40 +00:00
|
|
|
|
if (tabBoxMulti.TabPages.Contains(Tab_Box))
|
|
|
|
|
return false;
|
|
|
|
|
tabBoxMulti.TabPages.Insert(0, Tab_Box);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-06-19 05:27:40 +00:00
|
|
|
|
private bool ToggleViewParty(SaveFile sav, int BoxTab)
|
|
|
|
|
{
|
2020-12-05 13:36:23 +00:00
|
|
|
|
if (!sav.HasParty || !sav.State.Exportable)
|
2017-06-19 05:27:40 +00:00
|
|
|
|
{
|
|
|
|
|
if (tabBoxMulti.TabPages.Contains(Tab_PartyBattle))
|
|
|
|
|
tabBoxMulti.TabPages.Remove(Tab_PartyBattle);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (tabBoxMulti.TabPages.Contains(Tab_PartyBattle))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
int index = BoxTab;
|
|
|
|
|
if (index < 0)
|
|
|
|
|
index = -1;
|
|
|
|
|
tabBoxMulti.TabPages.Insert(index + 1, Tab_PartyBattle);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-06-19 05:27:40 +00:00
|
|
|
|
private bool ToggleViewDaycare(SaveFile sav, int BoxTab, int PartyTab)
|
|
|
|
|
{
|
2020-12-05 13:36:23 +00:00
|
|
|
|
if ((!sav.HasDaycare && SL_Extra.SlotCount == 0) || !sav.State.Exportable)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
2017-06-19 05:27:40 +00:00
|
|
|
|
if (tabBoxMulti.TabPages.Contains(Tab_Other))
|
|
|
|
|
tabBoxMulti.TabPages.Remove(Tab_Other);
|
|
|
|
|
return false;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-11-16 01:34:18 +00:00
|
|
|
|
SlotPictureBoxes[1].Visible = sav.Generation >= 2; // Second daycare slot
|
2017-06-19 05:27:40 +00:00
|
|
|
|
if (tabBoxMulti.TabPages.Contains(Tab_Other))
|
|
|
|
|
return false;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
|
2017-06-19 05:27:40 +00:00
|
|
|
|
int index = PartyTab;
|
|
|
|
|
if (index < 0)
|
|
|
|
|
index = BoxTab;
|
|
|
|
|
if (index < 0)
|
|
|
|
|
index = -1;
|
|
|
|
|
tabBoxMulti.TabPages.Insert(index + 1, Tab_Other);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-06-19 05:27:40 +00:00
|
|
|
|
private void ToggleViewSubEditors(SaveFile sav)
|
|
|
|
|
{
|
2020-12-05 13:36:23 +00:00
|
|
|
|
if (!sav.State.Exportable || sav is BulkStorage)
|
2018-02-24 21:03:32 +00:00
|
|
|
|
{
|
|
|
|
|
GB_SAVtools.Visible = false;
|
|
|
|
|
B_JPEG.Visible = false;
|
|
|
|
|
SL_Extra.HideAllSlots();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-28 18:26:08 +00:00
|
|
|
|
GB_Daycare.Visible = sav.HasDaycare;
|
|
|
|
|
B_OpenPokeblocks.Visible = sav is SAV6AO;
|
|
|
|
|
B_OpenSecretBase.Visible = sav is SAV6AO;
|
|
|
|
|
B_OpenPokepuffs.Visible = sav is ISaveBlock6Main;
|
|
|
|
|
B_JPEG.Visible = B_OpenLinkInfo.Visible = B_OpenSuperTraining.Visible = B_OUTPasserby.Visible = sav is ISaveBlock6Main;
|
|
|
|
|
B_OpenBoxLayout.Visible = sav.HasNamableBoxes;
|
|
|
|
|
B_OpenWondercards.Visible = sav.HasWondercards;
|
|
|
|
|
B_OpenHallofFame.Visible = sav is ISaveBlock6Main or SAV7;
|
|
|
|
|
B_OpenOPowers.Visible = sav is ISaveBlock6Main;
|
|
|
|
|
B_OpenPokedex.Visible = sav.HasPokeDex;
|
|
|
|
|
B_OpenBerryField.Visible = sav is SAV6XY; // oras undocumented
|
|
|
|
|
B_OpenFriendSafari.Visible = sav is SAV6XY;
|
2022-04-10 01:12:57 +00:00
|
|
|
|
B_OpenEventFlags.Visible = sav is IEventFlag37 or (SAV1 or SAV2 or SAV8BS or SAV7b);
|
2020-12-28 18:26:08 +00:00
|
|
|
|
B_CGearSkin.Visible = sav.Generation == 5;
|
|
|
|
|
B_OpenPokeBeans.Visible = B_CellsStickers.Visible = B_FestivalPlaza.Visible = sav is SAV7;
|
|
|
|
|
|
|
|
|
|
B_OtherSlots.Visible = sav is SAV1StadiumJ or SAV1Stadium or SAV2Stadium;
|
|
|
|
|
B_OpenTrainerInfo.Visible = B_OpenItemPouch.Visible = (sav.HasParty && SAV is not SAV4BR) || SAV is SAV7b; // Box RS & Battle Revolution
|
2021-11-26 06:48:09 +00:00
|
|
|
|
B_OpenMiscEditor.Visible = sav is SAV3 or SAV4 or SAV5 or SAV8BS;
|
2020-12-28 18:26:08 +00:00
|
|
|
|
B_Roamer.Visible = sav is SAV3;
|
|
|
|
|
|
2021-11-21 19:33:04 +00:00
|
|
|
|
B_OpenHoneyTreeEditor.Visible = sav is SAV4Sinnoh;
|
|
|
|
|
B_OpenUGSEditor.Visible = sav is SAV4Sinnoh or SAV8BS;
|
2021-11-27 10:06:35 +00:00
|
|
|
|
B_OpenSealStickers.Visible = B_Poffins.Visible = sav is SAV8BS;
|
2020-12-28 18:26:08 +00:00
|
|
|
|
B_OpenApricorn.Visible = sav is SAV4HGSS;
|
2021-03-16 06:51:58 +00:00
|
|
|
|
B_OpenRTCEditor.Visible = sav.Generation == 2 || sav is IGen3Hoenn;
|
2020-12-28 18:26:08 +00:00
|
|
|
|
B_MailBox.Visible = sav is SAV2 or SAV3 or SAV4 or SAV5;
|
|
|
|
|
|
|
|
|
|
B_Raids.Visible = sav is SAV8SWSH;
|
|
|
|
|
B_RaidArmor.Visible = sav is SAV8SWSH {SaveRevision: >= 1};
|
|
|
|
|
B_RaidCrown.Visible = sav is SAV8SWSH {SaveRevision: >= 2};
|
|
|
|
|
GB_SAVtools.Visible = B_Blocks.Visible = true;
|
|
|
|
|
|
|
|
|
|
var list = FLP_SAVtools.Controls.OfType<Control>().OrderBy(z => z.Text).ToArray();
|
2020-01-28 01:14:18 +00:00
|
|
|
|
FLP_SAVtools.Controls.Clear();
|
|
|
|
|
FLP_SAVtools.Controls.AddRange(list);
|
2020-12-28 18:26:08 +00:00
|
|
|
|
|
|
|
|
|
SL_Extra.SAV = sav;
|
|
|
|
|
SL_Extra.Initialize(sav.GetExtraSlots(HaX), InitializeDragDrop);
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-06-19 05:27:40 +00:00
|
|
|
|
private void ToggleViewMisc(SaveFile sav)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
|
|
|
|
// Generational Interface
|
2018-08-20 01:22:07 +00:00
|
|
|
|
ToggleSecrets(sav, HideSecretDetails);
|
2022-02-10 00:48:55 +00:00
|
|
|
|
B_VerifyCHK.Visible = SAV.State.Exportable;
|
|
|
|
|
Menu_ExportBAK.Visible = SAV.State.Exportable && SAV.Metadata.FilePath is not null;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
|
2018-05-20 03:48:03 +00:00
|
|
|
|
if (sav is SAV4BR br)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
|
|
|
|
L_SaveSlot.Visible = CB_SaveSlot.Visible = true;
|
2021-01-21 04:29:26 +00:00
|
|
|
|
var current = br.CurrentSlot;
|
2019-06-02 02:12:41 +00:00
|
|
|
|
var list = br.SaveNames.Select((z, i) => new ComboItem(z, i)).ToList();
|
2018-07-14 23:00:28 +00:00
|
|
|
|
CB_SaveSlot.InitializeBinding();
|
2018-05-20 03:48:03 +00:00
|
|
|
|
CB_SaveSlot.DataSource = new BindingSource(list, null);
|
2021-01-21 04:29:26 +00:00
|
|
|
|
CB_SaveSlot.SelectedValue = current;
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
2018-08-04 17:06:06 +00:00
|
|
|
|
{
|
2017-05-23 04:55:05 +00:00
|
|
|
|
L_SaveSlot.Visible = CB_SaveSlot.Visible = false;
|
2018-08-04 17:06:06 +00:00
|
|
|
|
}
|
2017-05-23 04:55:05 +00:00
|
|
|
|
|
2018-12-19 01:15:35 +00:00
|
|
|
|
if (sav is ISecureValueStorage s)
|
|
|
|
|
{
|
|
|
|
|
TB_Secure1.Text = s.TimeStampCurrent.ToString("X16");
|
|
|
|
|
TB_Secure2.Text = s.TimeStampPrevious.ToString("X16");
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-31 18:43:57 +00:00
|
|
|
|
if (sav is IGameSync sync)
|
2017-05-23 04:55:05 +00:00
|
|
|
|
{
|
2020-10-31 18:43:57 +00:00
|
|
|
|
var gsid = sync.GameSyncID;
|
|
|
|
|
TB_GameSync.Enabled = !string.IsNullOrEmpty(gsid);
|
|
|
|
|
TB_GameSync.MaxLength = sync.GameSyncIDSize;
|
|
|
|
|
TB_GameSync.Text = (string.IsNullOrEmpty(gsid) ? 0.ToString() : gsid).PadLeft(sync.GameSyncIDSize, '0');
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-20 01:22:07 +00:00
|
|
|
|
private void ToggleSecrets(SaveFile sav, bool hide)
|
|
|
|
|
{
|
2020-12-05 13:36:23 +00:00
|
|
|
|
var shouldShow = sav.State.Exportable && !hide;
|
2020-10-31 18:43:57 +00:00
|
|
|
|
TB_Secure1.Visible = TB_Secure2.Visible = L_Secure1.Visible = L_Secure2.Visible = shouldShow && sav is ISecureValueStorage;
|
|
|
|
|
TB_GameSync.Visible = L_GameSync.Visible = shouldShow && sav is IGameSync;
|
2018-08-20 01:22:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-05-23 04:55:05 +00:00
|
|
|
|
// DragDrop
|
2017-09-15 16:13:08 +00:00
|
|
|
|
private void MultiDragOver(object sender, DragEventArgs e)
|
|
|
|
|
{
|
|
|
|
|
// iterate over all tabs to see if a tab switch should occur when drag/dropping
|
|
|
|
|
Point pt = tabBoxMulti.PointToClient(new Point(e.X, e.Y));
|
|
|
|
|
for (int i = 0; i < tabBoxMulti.TabCount; i++)
|
|
|
|
|
{
|
|
|
|
|
if (tabBoxMulti.SelectedIndex == i || !tabBoxMulti.GetTabRect(i).Contains(pt))
|
|
|
|
|
continue;
|
|
|
|
|
tabBoxMulti.SelectedIndex = i;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-05-19 03:02:49 +00:00
|
|
|
|
|
2018-09-03 01:02:25 +00:00
|
|
|
|
public void ClickShowdownExportParty(object sender, EventArgs e) => ExportShowdownText(SAV, MsgSimulatorExportParty, sav => sav.PartyData);
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2018-06-17 04:56:16 +00:00
|
|
|
|
public void ClickShowdownExportCurrentBox(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (!SAV.HasBox)
|
|
|
|
|
return;
|
2018-09-03 01:02:25 +00:00
|
|
|
|
ExportShowdownText(SAV, MsgSimulatorExportList,
|
|
|
|
|
sav => (ModifierKeys & Keys.Control) != 0 ? sav.BoxData : sav.GetBoxData(CurrentBox));
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-17 02:46:22 +00:00
|
|
|
|
private static void ExportShowdownText(SaveFile sav, string success, Func<SaveFile, IEnumerable<PKM>> fetch)
|
2018-09-03 01:02:25 +00:00
|
|
|
|
{
|
2020-06-17 02:46:22 +00:00
|
|
|
|
var list = fetch(sav);
|
2020-12-29 05:42:54 +00:00
|
|
|
|
var result = ShowdownParsing.GetShowdownSets(list, Environment.NewLine + Environment.NewLine);
|
2020-06-17 02:46:22 +00:00
|
|
|
|
if (string.IsNullOrWhiteSpace(result))
|
|
|
|
|
return;
|
|
|
|
|
if (WinFormsUtil.SetClipboardText(result))
|
2019-02-02 07:08:03 +00:00
|
|
|
|
WinFormsUtil.Alert(success);
|
2018-06-17 04:56:16 +00:00
|
|
|
|
}
|
2017-08-27 19:32:43 +00:00
|
|
|
|
|
|
|
|
|
private void B_OpenUGSEditor_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
2021-11-21 19:33:04 +00:00
|
|
|
|
Form form;
|
|
|
|
|
if (SAV is SAV4Sinnoh s)
|
|
|
|
|
form = new SAV_Underground(s);
|
|
|
|
|
else if (SAV is SAV8BS bs)
|
|
|
|
|
form = new SAV_Underground8b(bs);
|
|
|
|
|
else
|
2020-12-28 18:26:08 +00:00
|
|
|
|
return;
|
|
|
|
|
form.ShowDialog();
|
2021-11-21 19:33:04 +00:00
|
|
|
|
form.Dispose();
|
2017-08-27 19:32:43 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2021-11-25 01:51:12 +00:00
|
|
|
|
private void B_OpenSealStickers_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (SAV is not SAV8BS bs)
|
|
|
|
|
return;
|
|
|
|
|
using var form = new SAV_SealStickers8b(bs);
|
|
|
|
|
form.ShowDialog();
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-27 10:06:35 +00:00
|
|
|
|
private void B_Poffins_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if (SAV is not SAV8BS bs)
|
|
|
|
|
return;
|
|
|
|
|
using var form = new SAV_Poffin8b(bs);
|
|
|
|
|
form.ShowDialog();
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-19 21:50:30 +00:00
|
|
|
|
private void B_FestivalPlaza_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
2020-12-28 18:26:08 +00:00
|
|
|
|
if (SAV is not SAV7 s)
|
|
|
|
|
return;
|
|
|
|
|
using var form = new SAV_FestivalPlaza(s);
|
|
|
|
|
form.ShowDialog();
|
2017-11-19 21:50:30 +00:00
|
|
|
|
}
|
2018-08-03 03:11:42 +00:00
|
|
|
|
|
2017-12-02 22:20:56 +00:00
|
|
|
|
private void B_MailBox_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
2019-10-20 03:33:37 +00:00
|
|
|
|
using var form = new SAV_MailBox(SAV);
|
|
|
|
|
form.ShowDialog();
|
2017-12-02 22:20:56 +00:00
|
|
|
|
ResetParty();
|
|
|
|
|
}
|
2018-01-21 23:30:57 +00:00
|
|
|
|
|
2019-03-30 00:52:26 +00:00
|
|
|
|
private static PKMImportSetting GetPKMSetOverride(bool currentSetting)
|
2018-09-03 01:02:25 +00:00
|
|
|
|
{
|
|
|
|
|
var yn = currentSetting ? MsgYes : MsgNo;
|
2019-09-03 02:30:58 +00:00
|
|
|
|
var choice = WinFormsUtil.Prompt(MessageBoxButtons.YesNoCancel,
|
2018-09-03 01:02:25 +00:00
|
|
|
|
MsgSaveBoxImportModifyIntro,
|
|
|
|
|
MsgSaveBoxImportModifyYes + Environment.NewLine +
|
|
|
|
|
MsgSaveBoxImportModifyNo + Environment.NewLine +
|
|
|
|
|
string.Format(MsgSaveBoxImportModifyCurrent, yn));
|
2019-10-08 01:40:09 +00:00
|
|
|
|
return choice switch
|
2019-01-12 02:27:29 +00:00
|
|
|
|
{
|
2019-10-08 01:40:09 +00:00
|
|
|
|
DialogResult.Yes => PKMImportSetting.Update,
|
|
|
|
|
DialogResult.No => PKMImportSetting.Skip,
|
2021-08-20 20:49:20 +00:00
|
|
|
|
_ => PKMImportSetting.UseDefault,
|
2019-10-08 01:40:09 +00:00
|
|
|
|
};
|
2018-09-03 01:02:25 +00:00
|
|
|
|
}
|
2021-10-22 05:13:21 +00:00
|
|
|
|
|
|
|
|
|
private void Menu_ExportBAK_Click(object sender, EventArgs e) => ExportBackup();
|
2017-05-23 04:55:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|