mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-24 04:53:08 +00:00
428ce52c27
Default settings do not flag, as Database view does not track the savefile (LegalityAnalysis only indirectly references the latest loaded save file, not the true source). Bulk Analysis will flag them correctly if run. Can be turned off.
1266 lines
45 KiB
C#
1266 lines
45 KiB
C#
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;
|
|
using PKHeX.Drawing;
|
|
using static PKHeX.Core.MessageStrings;
|
|
|
|
namespace PKHeX.WinForms.Controls
|
|
{
|
|
public partial class SAVEditor : UserControl, ISlotViewer<PictureBox>, ISaveFileProvider
|
|
{
|
|
public SaveDataEditor<PictureBox> EditEnv = null!;
|
|
|
|
public void SetEditEnvironment(SaveDataEditor<PictureBox> value)
|
|
{
|
|
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);
|
|
}
|
|
|
|
public SaveFile SAV { get; private set; } = new FakeSaveFile();
|
|
public int CurrentBox => Box.CurrentBox;
|
|
public SlotChangeManager M { get; }
|
|
public readonly ContextMenuSAV menu;
|
|
public readonly BoxMenuStrip SortMenu;
|
|
|
|
public bool HaX;
|
|
public bool ModifyPKM { private get; set; }
|
|
private bool _hideSecret;
|
|
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!;
|
|
private bool FieldsLoaded;
|
|
|
|
public IList<PictureBox> SlotPictureBoxes { get; }
|
|
|
|
public int ViewIndex { get; set; } = -1;
|
|
|
|
public bool FlagIllegal
|
|
{
|
|
get => Box.FlagIllegal;
|
|
set
|
|
{
|
|
SL_Extra.FlagIllegal = SL_Party.FlagIllegal = Box.FlagIllegal = value && !HaX;
|
|
if (SAV is FakeSaveFile)
|
|
return;
|
|
ReloadSlots();
|
|
}
|
|
}
|
|
|
|
public void ReloadSlots()
|
|
{
|
|
UpdateBoxViewers(all: true);
|
|
ResetNonBoxSlots();
|
|
}
|
|
|
|
public SAVEditor()
|
|
{
|
|
InitializeComponent();
|
|
|
|
L_SlotOccupied = new[] { L_DC1, L_DC2 };
|
|
TB_SlotEXP = new[] { TB_Daycare1XP, TB_Daycare2XP };
|
|
L_SlotEXP = new[] { L_XP1, L_XP2 };
|
|
SlotPictureBoxes = new[] { dcpkx1, dcpkx2 };
|
|
|
|
Tab_Box.ContextMenuStrip = SortMenu = new BoxMenuStrip(this);
|
|
M = new SlotChangeManager(this) {Env = EditEnv};
|
|
Box.Setup(M);
|
|
SL_Party.Setup(M);
|
|
|
|
SL_Extra.ViewIndex = -2;
|
|
menu = new ContextMenuSAV { Manager = M };
|
|
InitializeEvents();
|
|
}
|
|
|
|
private void InitializeEvents()
|
|
{
|
|
foreach (PictureBox pb in SlotPictureBoxes)
|
|
{
|
|
InitializeDragDrop(pb);
|
|
pb.ContextMenuStrip = menu.mnuVSD;
|
|
}
|
|
|
|
GiveFeedback += (sender, e) => e.UseDefaultCursors = false;
|
|
Tab_Box.MouseWheel += (s, e) =>
|
|
{
|
|
if (menu.mnuVSD.Visible)
|
|
return;
|
|
Box.CurrentBox = e.Delta > 1 ? Box.Editor.MoveLeft() : Box.Editor.MoveRight();
|
|
};
|
|
|
|
GB_Daycare.Click += (o, args) => SwitchDaycare(GB_Daycare, args);
|
|
FLP_SAVtools.Scroll += WinFormsUtil.PanelScroll;
|
|
SortMenu.Opening += (s, x) => x.Cancel = !tabBoxMulti.GetTabRect(tabBoxMulti.SelectedIndex).Contains(PointToClient(MousePosition));
|
|
}
|
|
|
|
private void InitializeDragDrop(Control pb)
|
|
{
|
|
pb.MouseEnter += M.MouseEnter;
|
|
pb.MouseLeave += M.MouseLeave;
|
|
pb.MouseClick += M.MouseClick;
|
|
pb.MouseMove += M.MouseMove;
|
|
pb.MouseDown += M.MouseDown;
|
|
pb.MouseUp += M.MouseUp;
|
|
|
|
pb.DragEnter += M.DragEnter;
|
|
pb.DragDrop += M.DragDrop;
|
|
pb.QueryContinueDrag += M.QueryContinueDrag;
|
|
pb.GiveFeedback += (sender, e) => e.UseDefaultCursors = false;
|
|
pb.AllowDrop = true;
|
|
pb.ContextMenuStrip = menu.mnuVSD;
|
|
}
|
|
|
|
/// <summary>Occurs when the Control Collection requests a cloning operation to the current box.</summary>
|
|
public event EventHandler? RequestCloneData;
|
|
|
|
/// <summary>Occurs when the Control Collection requests a save to be reloaded.</summary>
|
|
public event EventHandler? RequestReloadSave;
|
|
|
|
public void EnableDragDrop(DragEventHandler enter, DragEventHandler drop)
|
|
{
|
|
AllowDrop = true;
|
|
DragDrop += drop;
|
|
foreach (var tab in tabBoxMulti.TabPages.OfType<TabPage>())
|
|
{
|
|
tab.AllowDrop = true;
|
|
tab.DragEnter += enter;
|
|
tab.DragDrop += drop;
|
|
}
|
|
M.Drag.RequestExternalDragDrop += drop;
|
|
}
|
|
|
|
// Generic Subfunctions //
|
|
public int GetSlotOffset(int slot)
|
|
{
|
|
return SAV.GetDaycareSlotOffset(SAV.DaycareIndex, slot);
|
|
}
|
|
|
|
public int SwapBoxesViewer(int viewBox)
|
|
{
|
|
int mainBox = Box.CurrentBox;
|
|
Box.CurrentBox = viewBox;
|
|
return mainBox;
|
|
}
|
|
|
|
public void UpdateBoxViewers(bool all = false)
|
|
{
|
|
foreach (var v in M.Boxes.Where(v => v.CurrentBox == Box.CurrentBox || all))
|
|
{
|
|
v.FlagIllegal = Box.FlagIllegal;
|
|
v.ResetSlots();
|
|
}
|
|
}
|
|
|
|
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);
|
|
return new SlotInfoMisc(SAV, index, ofs);
|
|
}
|
|
|
|
public void SetPKMBoxes()
|
|
{
|
|
if (SAV.HasBox)
|
|
Box.ResetSlots();
|
|
|
|
ResetNonBoxSlots();
|
|
}
|
|
|
|
private void ResetNonBoxSlots()
|
|
{
|
|
ResetParty();
|
|
ResetDaycare();
|
|
ResetMiscSlots();
|
|
}
|
|
|
|
private void ResetMiscSlots()
|
|
{
|
|
var slots = SL_Extra.SlotPictureBoxes;
|
|
for (int i = 0; i < SL_Extra.SlotCount; i++)
|
|
{
|
|
var info = SL_Extra.GetSlotData(i);
|
|
var pb = slots[i];
|
|
SlotUtil.UpdateSlot(pb, info, info.Read(SAV), SAV, Box.FlagIllegal);
|
|
}
|
|
}
|
|
|
|
private void ResetParty()
|
|
{
|
|
if (SAV.HasParty)
|
|
SL_Party.ResetSlots();
|
|
}
|
|
|
|
private readonly Label[] L_SlotOccupied;
|
|
private readonly TextBox[] TB_SlotEXP;
|
|
private readonly Label[] L_SlotEXP;
|
|
|
|
private void ResetDaycare()
|
|
{
|
|
if (!SAV.HasDaycare)
|
|
return;
|
|
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
var relIndex = i;
|
|
var pb = UpdateSlot(relIndex);
|
|
|
|
uint? exp = SAV.GetDaycareEXP(SAV.DaycareIndex, i);
|
|
TB_SlotEXP[i].Visible = L_SlotEXP[i].Visible = exp != null;
|
|
TB_SlotEXP[i].Text = exp.ToString();
|
|
|
|
bool? occ = SAV.IsDaycareOccupied(SAV.DaycareIndex, i);
|
|
L_SlotOccupied[i].Visible = occ != null;
|
|
if (occ == true) // If Occupied
|
|
{
|
|
L_SlotOccupied[i].Text = $"{i + 1}: ✓";
|
|
}
|
|
else
|
|
{
|
|
L_SlotOccupied[i].Text = $"{i + 1}: ✘";
|
|
var current = pb.Image;
|
|
if (current != null)
|
|
pb.Image = ImageUtil.ChangeOpacity(current, 0.6);
|
|
}
|
|
}
|
|
|
|
bool? egg = SAV.IsDaycareHasEgg(SAV.DaycareIndex);
|
|
DayCare_HasEgg.Visible = egg != null;
|
|
DayCare_HasEgg.Checked = egg == true;
|
|
|
|
var seed = SAV.GetDaycareRNGSeed(SAV.DaycareIndex);
|
|
bool hasSeed = !string.IsNullOrEmpty(seed);
|
|
if (hasSeed)
|
|
{
|
|
TB_RNGSeed.MaxLength = SAV.DaycareSeedSize;
|
|
TB_RNGSeed.Text = seed;
|
|
}
|
|
L_DaycareSeed.Visible = TB_RNGSeed.Visible = hasSeed;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
public void SetParty() => ResetParty();
|
|
|
|
public void ClickUndo()
|
|
{
|
|
EditEnv.Slots.Undo();
|
|
UpdateUndoRedo();
|
|
}
|
|
|
|
public void ClickRedo()
|
|
{
|
|
EditEnv.Slots.Redo();
|
|
UpdateUndoRedo();
|
|
}
|
|
|
|
public void UpdateUndoRedo()
|
|
{
|
|
Menu_Undo.Enabled = EditEnv.Slots.Changelog.CanUndo;
|
|
Menu_Redo.Enabled = EditEnv.Slots.Changelog.CanRedo;
|
|
}
|
|
|
|
public void SetClonesToBox(PKM pk)
|
|
{
|
|
if (WinFormsUtil.Prompt(MessageBoxButtons.YesNo, string.Format(MsgSaveBoxCloneFromTabs, Box.CurrentBoxName)) != DialogResult.Yes)
|
|
return;
|
|
|
|
int slotSkipped = SetClonesToCurrentBox(pk, Box.CurrentBox);
|
|
if (slotSkipped > 0)
|
|
WinFormsUtil.Alert(string.Format(MsgSaveBoxImportSkippedLocked, slotSkipped));
|
|
|
|
UpdateBoxViewers();
|
|
}
|
|
|
|
private int SetClonesToCurrentBox(PKM pk, int box)
|
|
{
|
|
var arr = new PKM[SAV.BoxSlotCount];
|
|
for (int i = 0; i < SAV.BoxSlotCount; i++) // set to every slot in box
|
|
arr[i] = pk;
|
|
|
|
int slotSkipped = SAV.SetBoxData(arr, box);
|
|
Box.ResetSlots();
|
|
return slotSkipped;
|
|
}
|
|
|
|
public void ClickSlot(object sender, EventArgs e)
|
|
{
|
|
switch (ModifierKeys)
|
|
{
|
|
case Keys.Control | Keys.Alt:
|
|
ClickClone(sender, e);
|
|
break;
|
|
default: // forward to contextmenu for default behavior
|
|
menu.OmniClick(sender, e, ModifierKeys);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void ClickBoxSort(object sender, MouseEventArgs e)
|
|
{
|
|
if (tabBoxMulti.SelectedTab != Tab_Box)
|
|
return;
|
|
if (!tabBoxMulti.GetTabRect(tabBoxMulti.SelectedIndex).Contains(PointToClient(MousePosition)))
|
|
return;
|
|
if ((e.Button & MouseButtons.Right) == 0)
|
|
{
|
|
if ((ModifierKeys & Keys.Alt) != 0)
|
|
SortMenu.Clear();
|
|
else if ((ModifierKeys & Keys.Control) != 0)
|
|
SortMenu.Sort();
|
|
return;
|
|
}
|
|
var pt = Tab_Box.PointToScreen(new Point(0, 0));
|
|
SortMenu.Show(pt);
|
|
}
|
|
|
|
public void FinishBoxManipulation(string message, bool all, int count)
|
|
{
|
|
SetPKMBoxes();
|
|
UpdateBoxViewers(all);
|
|
if (!string.IsNullOrWhiteSpace(message))
|
|
WinFormsUtil.Alert(message + $" ({count})");
|
|
else
|
|
SystemSounds.Asterisk.Play();
|
|
}
|
|
|
|
private void ClickBoxDouble(object sender, MouseEventArgs e)
|
|
{
|
|
if (tabBoxMulti.SelectedTab == Tab_SAV)
|
|
{
|
|
RequestReloadSave?.Invoke(sender, e);
|
|
return;
|
|
}
|
|
if (tabBoxMulti.SelectedTab != Tab_Box)
|
|
return;
|
|
if (!SAV.HasBox)
|
|
return;
|
|
if (ModifierKeys == Keys.Shift)
|
|
{
|
|
if (M.Boxes.Count > 1) // subview open
|
|
{
|
|
// close all subviews
|
|
for (int i = 1; i < M.Boxes.Count; i++)
|
|
M.Boxes[i].ParentForm?.Close();
|
|
}
|
|
new SAV_BoxList(this, M).Show();
|
|
return;
|
|
}
|
|
if (M.Boxes.Count > 1) // subview open
|
|
{
|
|
var z = M.Boxes[1].ParentForm;
|
|
if (z == null)
|
|
return;
|
|
z.CenterToForm(ParentForm);
|
|
z.BringToFront();
|
|
return;
|
|
}
|
|
new SAV_BoxViewer(this, M).Show();
|
|
}
|
|
|
|
private void ClickClone(object sender, EventArgs e)
|
|
{
|
|
var detail = Box.GetSlotData((PictureBox) sender);
|
|
if (detail is SlotInfoBox)
|
|
RequestCloneData?.Invoke(sender, e);
|
|
}
|
|
|
|
private void UpdateSaveSlot(object sender, EventArgs e)
|
|
{
|
|
if (SAV is not SAV4BR br)
|
|
return;
|
|
br.CurrentSlot = WinFormsUtil.GetIndex(CB_SaveSlot);
|
|
Box.ResetBoxNames(); // fix box names
|
|
SetPKMBoxes();
|
|
UpdateBoxViewers(true);
|
|
}
|
|
|
|
private void UpdateStringSeed(object sender, EventArgs e)
|
|
{
|
|
if (!FieldsLoaded)
|
|
return;
|
|
|
|
if (sender is not TextBox tb)
|
|
return;
|
|
|
|
if (string.IsNullOrWhiteSpace(tb.Text))
|
|
{
|
|
tb.Undo();
|
|
return;
|
|
}
|
|
|
|
string filterText = Util.GetOnlyHex(tb.Text);
|
|
if (string.IsNullOrWhiteSpace(filterText) || filterText.Length != tb.Text.Length)
|
|
{
|
|
WinFormsUtil.Alert(MsgProgramErrorExpectedHex, tb.Text);
|
|
tb.Undo();
|
|
return;
|
|
}
|
|
|
|
// Write final value back to the save
|
|
if (tb == TB_RNGSeed)
|
|
{
|
|
var value = filterText.PadLeft(SAV.DaycareSeedSize, '0');
|
|
SAV.SetDaycareRNGSeed(SAV.DaycareIndex, value);
|
|
SAV.State.Edited = true;
|
|
}
|
|
else if (tb == TB_GameSync && SAV is IGameSync sync)
|
|
{
|
|
var value = filterText.PadLeft(sync.GameSyncIDSize, '0');
|
|
sync.GameSyncID = value;
|
|
SAV.State.Edited = true;
|
|
}
|
|
else if (SAV is ISecureValueStorage s)
|
|
{
|
|
var value = Convert.ToUInt64(filterText, 16);
|
|
if (tb == TB_Secure1)
|
|
s.TimeStampCurrent = value;
|
|
else if (tb == TB_Secure2)
|
|
s.TimeStampPrevious = value;
|
|
SAV.State.Edited = true;
|
|
}
|
|
}
|
|
|
|
private void SwitchDaycare(object sender, EventArgs e)
|
|
{
|
|
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();
|
|
}
|
|
|
|
private void B_SaveBoxBin_Click(object sender, EventArgs e)
|
|
{
|
|
if (!SAV.HasBox)
|
|
{ WinFormsUtil.Alert(MsgSaveBoxFailNone); return; }
|
|
Box.SaveBoxBinary();
|
|
}
|
|
|
|
// Subfunction Save Buttons //
|
|
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));
|
|
|
|
private void B_OpenEventFlags_Click(object sender, EventArgs e)
|
|
{
|
|
using var form = SAV switch
|
|
{
|
|
SAV1 s => (Form) new SAV_EventReset1(s),
|
|
SAV7b s => new SAV_EventWork(s),
|
|
SAV8BS s => new SAV_FlagWork8b(s),
|
|
IEventFlag37 g37 => new SAV_EventFlags(g37),
|
|
SAV2 s => new SAV_EventFlags2(s),
|
|
_ => throw new Exception(),
|
|
};
|
|
form.ShowDialog();
|
|
}
|
|
|
|
private void B_OpenBoxLayout_Click(object sender, EventArgs e)
|
|
{
|
|
OpenDialog(new SAV_BoxLayout(SAV, Box.CurrentBox));
|
|
Box.ResetBoxNames(); // fix box names
|
|
Box.ResetSlots(); // refresh box background
|
|
UpdateBoxViewers(all: true); // update subviewers
|
|
}
|
|
|
|
private static Form GetTrainerEditor(SaveFile sav) => sav switch
|
|
{
|
|
SAV6 s6 => new SAV_Trainer(s6),
|
|
SAV7 s7 => new SAV_Trainer7(s7),
|
|
SAV7b b7 => new SAV_Trainer7GG(b7),
|
|
SAV8SWSH swsh => new SAV_Trainer8(swsh),
|
|
SAV8BS bs => new SAV_Trainer8b(bs),
|
|
SAV8LA la => new SAV_Trainer8a(la),
|
|
_ => new SAV_SimpleTrainer(sav),
|
|
};
|
|
|
|
private void B_OpenRaids_Click(object sender, EventArgs e)
|
|
{
|
|
if (SAV is not SAV8SWSH swsh)
|
|
return;
|
|
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));
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
if (SAV is SAV_STADIUM s0)
|
|
TryOpen(s0, s0.GetRegisteredTeams());
|
|
}
|
|
|
|
private void B_Blocks_Click(object sender, EventArgs e)
|
|
{
|
|
var form = GetAccessorForm(SAV);
|
|
form.ShowDialog();
|
|
form.Dispose();
|
|
}
|
|
|
|
private static Form GetAccessorForm(SaveFile sav) => sav switch
|
|
{
|
|
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),
|
|
SAV7b s => new SAV_Accessor<SaveBlockAccessor7b>(s, s.Blocks),
|
|
ISCBlockArray s => new SAV_BlockDump8(s),
|
|
_ => GetPropertyForm(sav),
|
|
};
|
|
|
|
private static Form GetPropertyForm(object sav)
|
|
{
|
|
var form = new Form
|
|
{
|
|
Text = "Simple Editor",
|
|
StartPosition = FormStartPosition.CenterParent,
|
|
MinimumSize = new Size(350, 380),
|
|
MinimizeBox = false,
|
|
MaximizeBox = false,
|
|
Icon = Properties.Resources.Icon,
|
|
};
|
|
var pg = new PropertyGrid {SelectedObject = sav, Dock = DockStyle.Fill};
|
|
form.Controls.Add(pg);
|
|
return form;
|
|
}
|
|
|
|
private void B_OpenFriendSafari_Click(object sender, EventArgs e)
|
|
{
|
|
if (SAV is not SAV6XY xy)
|
|
return;
|
|
|
|
var dr = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MsgSaveGen6FriendSafari, MsgSaveGen6FriendSafariCheatDesc);
|
|
if (dr == DialogResult.Yes)
|
|
xy.UnlockAllFriendSafariSlots();
|
|
}
|
|
|
|
private void B_OpenPokedex_Click(object sender, EventArgs e)
|
|
{
|
|
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),
|
|
SAV8BS bs => new SAV_PokedexBDSP(bs),
|
|
SAV8LA la => new SAV_PokedexLA(la),
|
|
_ => (Form?)null,
|
|
};
|
|
form?.ShowDialog();
|
|
}
|
|
|
|
private void B_OpenMiscEditor_Click(object sender, EventArgs e)
|
|
{
|
|
using var form = SAV.Generation switch
|
|
{
|
|
3 => new SAV_Misc3(SAV),
|
|
4 => new SAV_Misc4((SAV4) SAV),
|
|
5 => new SAV_Misc5(SAV),
|
|
8 when SAV is SAV8BS bs => new SAV_Misc8b(bs),
|
|
_ => (Form?)null,
|
|
};
|
|
form?.ShowDialog();
|
|
}
|
|
|
|
private void B_OpenRTCEditor_Click(object sender, EventArgs e)
|
|
{
|
|
switch (SAV.Generation)
|
|
{
|
|
case 2:
|
|
var sav2 = ((SAV2) SAV);
|
|
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);
|
|
if (dr == DialogResult.Yes)
|
|
sav2.ResetRTC();
|
|
break;
|
|
case 3:
|
|
OpenDialog(new SAV_RTC3(SAV));
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void B_OUTPasserby_Click(object sender, EventArgs e)
|
|
{
|
|
if (SAV.Generation != 6)
|
|
return;
|
|
if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MsgSaveGen6Passerby))
|
|
return;
|
|
var result = PSS6.GetPSSParse((SAV6)SAV);
|
|
WinFormsUtil.SetClipboardText(string.Join(Environment.NewLine, result));
|
|
}
|
|
|
|
private void B_OUTHallofFame_Click(object sender, EventArgs e)
|
|
{
|
|
using var form = SAV switch
|
|
{
|
|
SAV6 s6 => new SAV_HallOfFame(s6),
|
|
SAV7 s7 => new SAV_HallOfFame7(s7),
|
|
_ => (Form?)null,
|
|
};
|
|
form?.ShowDialog();
|
|
}
|
|
|
|
private void B_JPEG_Click(object sender, EventArgs e)
|
|
{
|
|
var s6 = (SAV6)SAV;
|
|
byte[] jpeg = s6.GetJPEGData();
|
|
if (jpeg.Length == 0)
|
|
{
|
|
WinFormsUtil.Alert(MsgSaveJPEGExportFail);
|
|
return;
|
|
}
|
|
string filename = $"{s6.JPEGTitle}'s picture";
|
|
using var sfd = new SaveFileDialog { FileName = filename, Filter = "JPEG|*.jpeg" };
|
|
if (sfd.ShowDialog() != DialogResult.OK)
|
|
return;
|
|
File.WriteAllBytes(sfd.FileName, jpeg);
|
|
}
|
|
|
|
private void ClickVerifyCHK(object sender, EventArgs e)
|
|
{
|
|
if (SAV.State.Edited)
|
|
{
|
|
WinFormsUtil.Alert(MsgSaveChecksumFailEdited);
|
|
return;
|
|
}
|
|
if (SAV.ChecksumsValid)
|
|
{
|
|
WinFormsUtil.Alert(MsgSaveChecksumValid);
|
|
return;
|
|
}
|
|
|
|
if (DialogResult.Yes == WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MsgSaveChecksumFailExport))
|
|
WinFormsUtil.SetClipboardText(SAV.ChecksumInfo);
|
|
}
|
|
|
|
private void ClickVerifyStoredEntities(object sender, EventArgs e)
|
|
{
|
|
var bulk = new BulkAnalysis(SAV, Main.Settings.Bulk);
|
|
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();
|
|
}
|
|
|
|
// File I/O
|
|
public bool GetBulkImportSettings(out bool clearAll, out bool overwrite, out PKMImportSetting noSetb)
|
|
{
|
|
clearAll = false; noSetb = PKMImportSetting.UseDefault; overwrite = false;
|
|
var dr = WinFormsUtil.Prompt(MessageBoxButtons.YesNoCancel, MsgSaveBoxImportClear, MsgSaveBoxImportClearNo);
|
|
if (dr == DialogResult.Cancel)
|
|
return false;
|
|
|
|
clearAll = dr == DialogResult.Yes;
|
|
noSetb = GetPKMSetOverride(ModifyPKM);
|
|
return true;
|
|
}
|
|
|
|
private static bool IsFolderPath(out string path)
|
|
{
|
|
using var fbd = new FolderBrowserDialog();
|
|
var result = fbd.ShowDialog() == DialogResult.OK;
|
|
path = fbd.SelectedPath;
|
|
return result;
|
|
}
|
|
|
|
public bool ExportSaveFile()
|
|
{
|
|
ValidateChildren();
|
|
bool reload = SAV is SAV7b b && b.FixPreWrite();
|
|
if (reload)
|
|
ReloadSlots();
|
|
return WinFormsUtil.ExportSAVDialog(SAV, SAV.CurrentBox);
|
|
}
|
|
|
|
public bool ExportBackup()
|
|
{
|
|
if (!SAV.State.Exportable || SAV.Metadata.FilePath is not { } file)
|
|
return false;
|
|
|
|
if (!File.Exists(file))
|
|
{
|
|
WinFormsUtil.Error(MsgSaveBackupNotFound, file);
|
|
return false;
|
|
}
|
|
|
|
var suggestion = Util.CleanFileName(SAV.Metadata.BAKName);
|
|
using var sfd = new SaveFileDialog {FileName = suggestion};
|
|
if (sfd.ShowDialog() != DialogResult.OK)
|
|
return false;
|
|
|
|
string path = sfd.FileName;
|
|
if (!File.Exists(file)) // did they move it again?
|
|
{
|
|
WinFormsUtil.Error(MsgSaveBackupNotFound, file);
|
|
return false;
|
|
}
|
|
File.Copy(file, path);
|
|
WinFormsUtil.Alert(MsgSaveBackup, path);
|
|
|
|
return true;
|
|
}
|
|
|
|
public bool OpenPCBoxBin(byte[] input, out string c)
|
|
{
|
|
if (SAV.GetPCBinary().Length == input.Length)
|
|
{
|
|
if (SAV.IsAnySlotLockedInBox(0, SAV.BoxCount - 1))
|
|
{ c = MsgSaveBoxImportPCFailBattle; return false; }
|
|
if (!SAV.SetPCBinary(input))
|
|
{ c = string.Format(MsgSaveCurrentGeneration, SAV.Generation); return false; }
|
|
|
|
c = MsgSaveBoxImportPCBinary;
|
|
}
|
|
else if (SAV.GetBoxBinary(Box.CurrentBox).Length == input.Length)
|
|
{
|
|
if (SAV.IsAnySlotLockedInBox(Box.CurrentBox, Box.CurrentBox))
|
|
{ c = MsgSaveBoxImportBoxFailBattle; return false; }
|
|
if (!SAV.SetBoxBinary(input, Box.CurrentBox))
|
|
{ c = string.Format(MsgSaveCurrentGeneration, SAV.Generation); return false; }
|
|
|
|
c = MsgSaveBoxImportBoxBinary;
|
|
}
|
|
else
|
|
{
|
|
c = string.Format(MsgSaveCurrentGeneration, SAV.Generation);
|
|
return false;
|
|
}
|
|
SetPKMBoxes();
|
|
UpdateBoxViewers();
|
|
return true;
|
|
}
|
|
|
|
public bool OpenGroup(IPokeGroup b, out string c)
|
|
{
|
|
var msg = string.Format(MsgSaveBoxImportGroup, Box.CurrentBoxName);
|
|
var prompt = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, msg, MsgSaveBoxImportOverwrite);
|
|
if (prompt != DialogResult.Yes)
|
|
{
|
|
c = string.Empty;
|
|
return false;
|
|
}
|
|
|
|
var noSetb = GetPKMSetOverride(ModifyPKM);
|
|
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;
|
|
int slotSkipped = 0;
|
|
int index = 0;
|
|
foreach (var x in data)
|
|
{
|
|
var i = index++;
|
|
if (sav.IsSlotOverwriteProtected(box, i))
|
|
{
|
|
slotSkipped++;
|
|
continue;
|
|
}
|
|
|
|
var convert = EntityConverter.ConvertToType(x, type, out _);
|
|
if (convert?.GetType() != type)
|
|
{
|
|
slotSkipped++;
|
|
continue;
|
|
}
|
|
sav.SetBoxSlotAtIndex(x, box, i, noSetb);
|
|
}
|
|
|
|
return slotSkipped;
|
|
}
|
|
|
|
public bool DumpBoxes(out string result, string? path = null, bool separate = false)
|
|
{
|
|
if (path == null && !IsFolderPath(out path))
|
|
{
|
|
result = path;
|
|
return false;
|
|
}
|
|
|
|
Directory.CreateDirectory(path);
|
|
|
|
var count = SAV.DumpBoxes(path, separate);
|
|
if (count < 0)
|
|
result = MsgSaveBoxExportInvalid;
|
|
else
|
|
result = string.Format(MsgSaveBoxExportPathCount, count) + Environment.NewLine + path;
|
|
return true;
|
|
}
|
|
|
|
public bool DumpBox(out string result, string? path = null)
|
|
{
|
|
if (path == null && !IsFolderPath(out path))
|
|
{
|
|
result = path;
|
|
return false;
|
|
}
|
|
|
|
Directory.CreateDirectory(path);
|
|
|
|
var count = SAV.DumpBox(path, Box.CurrentBox);
|
|
if (count < 0)
|
|
result = MsgSaveBoxExportInvalid;
|
|
else
|
|
result = string.Format(MsgSaveBoxExportPathCount, count) + Environment.NewLine + path;
|
|
return true;
|
|
}
|
|
|
|
public bool LoadBoxes(out string result, string? path = null)
|
|
{
|
|
result = string.Empty;
|
|
if (!SAV.HasBox)
|
|
return false;
|
|
|
|
if (path == null && !IsFolderPath(out path))
|
|
{
|
|
result = path;
|
|
return false;
|
|
}
|
|
|
|
if (!Directory.Exists(path))
|
|
return false;
|
|
|
|
if (!GetBulkImportSettings(out bool clearAll, out var overwrite, out var noSetb))
|
|
return false;
|
|
|
|
SAV.LoadBoxes(path, out result, Box.CurrentBox, clearAll, overwrite, noSetb);
|
|
SetPKMBoxes();
|
|
UpdateBoxViewers();
|
|
return true;
|
|
}
|
|
|
|
public bool ToggleInterface()
|
|
{
|
|
FieldsLoaded = false;
|
|
|
|
ToggleViewReset();
|
|
ToggleViewSubEditors(SAV);
|
|
|
|
bool WindowTranslationRequired = false;
|
|
WindowTranslationRequired |= ToggleViewBox(SAV);
|
|
int BoxTab = tabBoxMulti.TabPages.IndexOf(Tab_Box);
|
|
WindowTranslationRequired |= ToggleViewParty(SAV, BoxTab);
|
|
int PartyTab = tabBoxMulti.TabPages.IndexOf(Tab_PartyBattle);
|
|
WindowTranslationRequired |= ToggleViewDaycare(SAV, BoxTab, PartyTab);
|
|
SetPKMBoxes(); // Reload all of the PKX Windows
|
|
|
|
ToggleViewMisc(SAV);
|
|
|
|
FieldsLoaded = true;
|
|
return WindowTranslationRequired;
|
|
}
|
|
|
|
private void ToggleViewReset()
|
|
{
|
|
// Close subforms that are save dependent
|
|
foreach (var z in M.Boxes.Skip(1).ToArray())
|
|
z.FindForm()?.Close();
|
|
|
|
Box.M = M;
|
|
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;
|
|
|
|
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)
|
|
{
|
|
var form = FindForm();
|
|
if (form != null)
|
|
form.Height += required - allowed;
|
|
}
|
|
}
|
|
}
|
|
if (SAV.HasParty)
|
|
{
|
|
bool newSlots = SL_Party.InitializeFromSAV(SAV);
|
|
if (newSlots)
|
|
{
|
|
SL_Party.HorizontallyCenter(Tab_PartyBattle);
|
|
foreach (var pb in SL_Party.SlotPictureBoxes)
|
|
pb.ContextMenuStrip = menu.mnuVSD;
|
|
}
|
|
}
|
|
|
|
SortMenu.ToggleVisibility();
|
|
}
|
|
|
|
private bool ToggleViewBox(SaveFile sav)
|
|
{
|
|
if (!sav.HasBox)
|
|
{
|
|
if (tabBoxMulti.TabPages.Contains(Tab_Box))
|
|
tabBoxMulti.TabPages.Remove(Tab_Box);
|
|
B_SaveBoxBin.Enabled = false;
|
|
return false;
|
|
}
|
|
|
|
B_SaveBoxBin.Enabled = true;
|
|
tabBoxMulti.SelectedIndex = 0;
|
|
|
|
var box = sav.CurrentBox;
|
|
Box.CurrentBox = (uint)box >= sav.BoxCount ? 0 : box;
|
|
|
|
if (tabBoxMulti.TabPages.Contains(Tab_Box))
|
|
return false;
|
|
tabBoxMulti.TabPages.Insert(0, Tab_Box);
|
|
return true;
|
|
}
|
|
|
|
private bool ToggleViewParty(SaveFile sav, int BoxTab)
|
|
{
|
|
if (!sav.HasParty || !sav.State.Exportable)
|
|
{
|
|
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;
|
|
}
|
|
|
|
private bool ToggleViewDaycare(SaveFile sav, int BoxTab, int PartyTab)
|
|
{
|
|
if ((!sav.HasDaycare && SL_Extra.SlotCount == 0) || !sav.State.Exportable)
|
|
{
|
|
if (tabBoxMulti.TabPages.Contains(Tab_Other))
|
|
tabBoxMulti.TabPages.Remove(Tab_Other);
|
|
return false;
|
|
}
|
|
|
|
SlotPictureBoxes[1].Visible = sav.Generation >= 2; // Second daycare slot
|
|
if (tabBoxMulti.TabPages.Contains(Tab_Other))
|
|
return false;
|
|
|
|
int index = PartyTab;
|
|
if (index < 0)
|
|
index = BoxTab;
|
|
if (index < 0)
|
|
index = -1;
|
|
tabBoxMulti.TabPages.Insert(index + 1, Tab_Other);
|
|
return true;
|
|
}
|
|
|
|
private void ToggleViewSubEditors(SaveFile sav)
|
|
{
|
|
if (!sav.State.Exportable || sav is BulkStorage)
|
|
{
|
|
GB_SAVtools.Visible = false;
|
|
B_JPEG.Visible = false;
|
|
SL_Extra.HideAllSlots();
|
|
return;
|
|
}
|
|
|
|
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;
|
|
B_OpenEventFlags.Visible = sav is IEventFlag37 or (SAV1 or SAV2 or SAV8BS or SAV7b);
|
|
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
|
|
B_OpenMiscEditor.Visible = sav is SAV3 or SAV4 or SAV5 or SAV8BS;
|
|
B_Roamer.Visible = sav is SAV3;
|
|
|
|
B_OpenHoneyTreeEditor.Visible = sav is SAV4Sinnoh;
|
|
B_OpenUGSEditor.Visible = sav is SAV4Sinnoh or SAV8BS;
|
|
B_OpenSealStickers.Visible = B_Poffins.Visible = sav is SAV8BS;
|
|
B_OpenApricorn.Visible = sav is SAV4HGSS;
|
|
B_OpenRTCEditor.Visible = sav.Generation == 2 || sav is IGen3Hoenn;
|
|
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();
|
|
FLP_SAVtools.Controls.Clear();
|
|
FLP_SAVtools.Controls.AddRange(list);
|
|
|
|
SL_Extra.SAV = sav;
|
|
SL_Extra.Initialize(sav.GetExtraSlots(HaX), InitializeDragDrop);
|
|
}
|
|
|
|
private void ToggleViewMisc(SaveFile sav)
|
|
{
|
|
// Generational Interface
|
|
ToggleSecrets(sav, HideSecretDetails);
|
|
B_VerifyCHK.Visible = SAV.State.Exportable;
|
|
Menu_ExportBAK.Visible = SAV.State.Exportable && SAV.Metadata.FilePath is not null;
|
|
|
|
if (sav is SAV4BR br)
|
|
{
|
|
L_SaveSlot.Visible = CB_SaveSlot.Visible = true;
|
|
var current = br.CurrentSlot;
|
|
var list = br.SaveNames.Select((z, i) => new ComboItem(z, i)).ToList();
|
|
CB_SaveSlot.InitializeBinding();
|
|
CB_SaveSlot.DataSource = new BindingSource(list, null);
|
|
CB_SaveSlot.SelectedValue = current;
|
|
}
|
|
else
|
|
{
|
|
L_SaveSlot.Visible = CB_SaveSlot.Visible = false;
|
|
}
|
|
|
|
if (sav is ISecureValueStorage s)
|
|
{
|
|
TB_Secure1.Text = s.TimeStampCurrent.ToString("X16");
|
|
TB_Secure2.Text = s.TimeStampPrevious.ToString("X16");
|
|
}
|
|
|
|
if (sav is IGameSync sync)
|
|
{
|
|
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');
|
|
}
|
|
}
|
|
|
|
private void ToggleSecrets(SaveFile sav, bool hide)
|
|
{
|
|
var shouldShow = sav.State.Exportable && !hide;
|
|
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;
|
|
}
|
|
|
|
// DragDrop
|
|
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;
|
|
}
|
|
}
|
|
|
|
public void ClickShowdownExportParty(object sender, EventArgs e) => ExportShowdownText(SAV, MsgSimulatorExportParty, sav => sav.PartyData);
|
|
|
|
public void ClickShowdownExportCurrentBox(object sender, EventArgs e)
|
|
{
|
|
if (!SAV.HasBox)
|
|
return;
|
|
ExportShowdownText(SAV, MsgSimulatorExportList,
|
|
sav => (ModifierKeys & Keys.Control) != 0 ? sav.BoxData : sav.GetBoxData(CurrentBox));
|
|
}
|
|
|
|
private static void ExportShowdownText(SaveFile sav, string success, Func<SaveFile, IEnumerable<PKM>> fetch)
|
|
{
|
|
var list = fetch(sav);
|
|
var result = ShowdownParsing.GetShowdownSets(list, Environment.NewLine + Environment.NewLine);
|
|
if (string.IsNullOrWhiteSpace(result))
|
|
return;
|
|
if (WinFormsUtil.SetClipboardText(result))
|
|
WinFormsUtil.Alert(success);
|
|
}
|
|
|
|
private void B_OpenUGSEditor_Click(object sender, EventArgs e)
|
|
{
|
|
Form form;
|
|
if (SAV is SAV4Sinnoh s)
|
|
form = new SAV_Underground(s);
|
|
else if (SAV is SAV8BS bs)
|
|
form = new SAV_Underground8b(bs);
|
|
else
|
|
return;
|
|
form.ShowDialog();
|
|
form.Dispose();
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
private void B_FestivalPlaza_Click(object sender, EventArgs e)
|
|
{
|
|
if (SAV is not SAV7 s)
|
|
return;
|
|
using var form = new SAV_FestivalPlaza(s);
|
|
form.ShowDialog();
|
|
}
|
|
|
|
private void B_MailBox_Click(object sender, EventArgs e)
|
|
{
|
|
using var form = new SAV_MailBox(SAV);
|
|
form.ShowDialog();
|
|
ResetParty();
|
|
}
|
|
|
|
private static PKMImportSetting GetPKMSetOverride(bool currentSetting)
|
|
{
|
|
var yn = currentSetting ? MsgYes : MsgNo;
|
|
var choice = WinFormsUtil.Prompt(MessageBoxButtons.YesNoCancel,
|
|
MsgSaveBoxImportModifyIntro,
|
|
MsgSaveBoxImportModifyYes + Environment.NewLine +
|
|
MsgSaveBoxImportModifyNo + Environment.NewLine +
|
|
string.Format(MsgSaveBoxImportModifyCurrent, yn));
|
|
return choice switch
|
|
{
|
|
DialogResult.Yes => PKMImportSetting.Update,
|
|
DialogResult.No => PKMImportSetting.Skip,
|
|
_ => PKMImportSetting.UseDefault,
|
|
};
|
|
}
|
|
|
|
private void Menu_ExportBAK_Click(object sender, EventArgs e) => ExportBackup();
|
|
}
|
|
}
|